diff --git a/win32/include/boost/accumulators/accumulators.hpp b/win32/include/boost/accumulators/accumulators.hpp new file mode 100755 index 000000000..dca65d382 --- /dev/null +++ b/win32/include/boost/accumulators/accumulators.hpp @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file accumulators.hpp +/// Includes all of the Accumulators Framework +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_ACCUMULATORS_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_ACCUMULATORS_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/accumulators/accumulators_fwd.hpp b/win32/include/boost/accumulators/accumulators_fwd.hpp new file mode 100755 index 000000000..8fdf22223 --- /dev/null +++ b/win32/include/boost/accumulators/accumulators_fwd.hpp @@ -0,0 +1,211 @@ +/////////////////////////////////////////////////////////////////////////////// +// accumulators_fwd.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_ACCUMULATORS_FWD_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_ACCUMULATORS_FWD_HPP_EAN_28_10_2005 + +#include +#include // for mpl::na +#include +#include +#include +#include +#include +#include +#include + +#ifndef BOOST_ACCUMULATORS_MAX_FEATURES + /// The maximum number of accumulators that may be put in an accumulator_set. + /// Defaults to BOOST_MPL_LIMIT_VECTOR_SIZE (which defaults to 20). +# define BOOST_ACCUMULATORS_MAX_FEATURES BOOST_MPL_LIMIT_VECTOR_SIZE +#endif + +#if BOOST_ACCUMULATORS_MAX_FEATURES > BOOST_MPL_LIMIT_VECTOR_SIZE +# error BOOST_ACCUMULATORS_MAX_FEATURES cannot be larger than BOOST_MPL_LIMIT_VECTOR_SIZE +#endif + +#ifndef BOOST_ACCUMULATORS_MAX_ARGS + /// The maximum number of arguments that may be specified to an accumulator_set's + /// accumulation function. Defaults to 15. +# define BOOST_ACCUMULATORS_MAX_ARGS 15 +#endif + +#if BOOST_WORKAROUND(__GNUC__, == 3) \ + || BOOST_WORKAROUND(__EDG_VERSION__, BOOST_TESTED_AT(306)) +# define BOOST_ACCUMULATORS_BROKEN_CONST_OVERLOADS +#endif + +#ifdef BOOST_ACCUMULATORS_BROKEN_CONST_OVERLOADS +# include +# include +# define BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(T)\ + , typename boost::disable_if >::type * = 0 +#else +# define BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(T) +#endif + +namespace boost { namespace accumulators +{ + +/////////////////////////////////////////////////////////////////////////////// +// Named parameters tags +// +namespace tag +{ + struct sample; + struct weight; + struct accumulator; + struct weights; +} + +/////////////////////////////////////////////////////////////////////////////// +// User-level features +// +namespace tag +{ + template + struct value; + + template + struct value_tag; + + template + struct reference; + + template + struct reference_tag; + + template + struct external; + + template + struct droppable; +} + +template +struct droppable_accumulator_base; + +template +struct droppable_accumulator; + +template +struct with_cached_result; + +template +struct accumulator_set; + +template +struct extractor; + +template +struct feature_of; + +template +struct as_feature; + +template +struct as_weighted_feature; + +template +struct depends_on; + +template +struct features; + +template +typename mpl::apply::type const & +find_accumulator(AccumulatorSet const &acc); + +template +typename mpl::apply::type::result_type +extract_result(AccumulatorSet const &acc); + +template +typename mpl::apply::type::result_type +extract_result(AccumulatorSet const &acc, A1 const &a1); + +// ... other overloads generated by Boost.Preprocessor: + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_EXTRACT_RESULT_FWD(z, n, _) \ + template< \ + typename Feature \ + , typename AccumulatorSet \ + BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ + > \ + typename mpl::apply::type::result_type \ + extract_result( \ + AccumulatorSet const &acc \ + BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \ + ); + +/// INTERNAL ONLY +/// +BOOST_PP_REPEAT_FROM_TO( + 2 + , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) + , BOOST_ACCUMULATORS_EXTRACT_RESULT_FWD + , _ +) + +#ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED +template +typename mpl::apply::type::result_type +extract_result(AccumulatorSet const &acc, A1 const &a1, A2 const &a2 ...); +#endif + +namespace impl +{ + using namespace numeric::operators; + + template + struct external_impl; +} + +namespace detail +{ + template + struct feature_tag; + + template + struct to_accumulator; + + struct accumulator_set_base; + + template + struct is_accumulator_set; +} + +}} // namespace boost::accumulators + +// For defining boost::parameter keywords that can be inherited from to +// get a nested, class-scoped keyword with the requested alias +#define BOOST_PARAMETER_NESTED_KEYWORD(tag_namespace, name, alias) \ + namespace tag_namespace \ + { \ + template \ + struct name ## _ \ + { \ + static char const* keyword_name() \ + { \ + return #name; \ + } \ + static ::boost::parameter::keyword > &alias; \ + }; \ + template \ + ::boost::parameter::keyword > &name ## _::alias = \ + ::boost::parameter::keyword >::get(); \ + typedef name ## _ <> name; \ + } \ + namespace \ + { \ + ::boost::parameter::keyword &name = \ + ::boost::parameter::keyword::get(); \ + } + +#endif diff --git a/win32/include/boost/accumulators/framework/accumulator_base.hpp b/win32/include/boost/accumulators/framework/accumulator_base.hpp new file mode 100755 index 000000000..c3600e363 --- /dev/null +++ b/win32/include/boost/accumulators/framework/accumulator_base.hpp @@ -0,0 +1,65 @@ +/////////////////////////////////////////////////////////////////////////////// +// accumulator_base.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_BASE_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_BASE_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace detail +{ + typedef void void_; +} + +/////////////////////////////////////////////////////////////////////////////// +// dont_care +// +struct dont_care +{ + template + dont_care(Args const &) + { + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// accumulator_base +// +struct accumulator_base +{ + // hidden if defined in derived classes + detail::void_ operator ()(dont_care) + { + } + + typedef mpl::false_ is_droppable; + + detail::void_ add_ref(dont_care) + { + } + + detail::void_ drop(dont_care) + { + } + + detail::void_ on_drop(dont_care) + { + } +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/framework/accumulator_concept.hpp b/win32/include/boost/accumulators/framework/accumulator_concept.hpp new file mode 100755 index 000000000..1c3b12612 --- /dev/null +++ b/win32/include/boost/accumulators/framework/accumulator_concept.hpp @@ -0,0 +1,29 @@ +/////////////////////////////////////////////////////////////////////////////// +// accumulator_concept.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_CONCEPT_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_CONCEPT_HPP_EAN_28_10_2005 + +#include + +namespace boost { namespace accumulators +{ + +template +struct accumulator_concept +{ + void constraints() + { + // TODO: define the stat concept + } + + Stat stat; +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/framework/accumulator_set.hpp b/win32/include/boost/accumulators/framework/accumulator_set.hpp new file mode 100755 index 000000000..5d40847f6 --- /dev/null +++ b/win32/include/boost/accumulators/framework/accumulator_set.hpp @@ -0,0 +1,401 @@ +/////////////////////////////////////////////////////////////////////////////// +// accumulator_set.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace detail +{ + /////////////////////////////////////////////////////////////////////////////// + // accumulator_visitor + // wrap a boost::parameter argument pack in a Fusion extractor object + template + struct accumulator_visitor + { + explicit accumulator_visitor(Args const &args) + : args(args) + { + } + + template + void operator ()(Accumulator &accumulator) const + { + accumulator(this->args); + } + + private: + accumulator_visitor &operator =(accumulator_visitor const &); + Args const &args; + }; + + template + inline accumulator_visitor const make_accumulator_visitor(Args const &args) + { + return accumulator_visitor(args); + } + + typedef + parameter::parameters< + parameter::required + , parameter::optional + // ... and others which are not specified here... + > + accumulator_params; + + /////////////////////////////////////////////////////////////////////////////// + // accumulator_set_base + struct accumulator_set_base + { + }; + + /////////////////////////////////////////////////////////////////////////////// + // is_accumulator_set + template + struct is_accumulator_set + : is_base_and_derived + { + }; + +} // namespace detail + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4355) // warning C4355: 'this' : used in base member initializer list +#endif + +/////////////////////////////////////////////////////////////////////////////// +/// \brief A set of accumulators. +/// +/// accumulator_set resolves the dependencies between features and ensures that +/// the accumulators in the set are updated in the proper order. +/// +/// acccumulator_set provides a general mechanism to visit the accumulators +/// in the set in order, with or without a filter. You can also fetch a reference +/// to an accumulator that corresponds to a feature. +/// +template +struct accumulator_set + : detail::accumulator_set_base +{ + typedef Sample sample_type; ///< The type of the samples that will be accumulated + typedef Features features_type; ///< An MPL sequence of the features that should be accumulated. + typedef Weight weight_type; ///< The type of the weight parameter. Must be a scalar. Defaults to void. + + /// INTERNAL ONLY + /// + typedef + typename detail::make_accumulator_tuple< + Features + , Sample + , Weight + >::type + accumulators_mpl_vector; + + // generate a fusion::list of accumulators + /// INTERNAL ONLY + /// + typedef + typename detail::meta::make_acc_list< + accumulators_mpl_vector + >::type + accumulators_type; + + /// INTERNAL ONLY + /// + //BOOST_MPL_ASSERT((mpl::is_sequence)); + + /////////////////////////////////////////////////////////////////////////////// + /// default-construct all contained accumulators + accumulator_set() + : accumulators( + detail::make_acc_list( + accumulators_mpl_vector() + , detail::accumulator_params()(*this) + ) + ) + { + // Add-ref the Features that the user has specified + this->template visit_if >( + detail::make_add_ref_visitor(detail::accumulator_params()(*this)) + ); + } + + /// \overload + /// + /// \param a1 Optional named parameter to be passed to all the accumulators + template + explicit accumulator_set(A1 const &a1) + : accumulators( + detail::make_acc_list( + accumulators_mpl_vector() + , detail::accumulator_params()(*this, a1) + ) + ) + { + // Add-ref the Features that the user has specified + this->template visit_if >( + detail::make_add_ref_visitor(detail::accumulator_params()(*this)) + ); + } + + // ... other overloads generated by Boost.Preprocessor: + + /// INTERNAL ONLY + /// +#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR(z, n, _) \ + template \ + accumulator_set(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)) \ + : accumulators( \ + detail::make_acc_list( \ + accumulators_mpl_vector() \ + , detail::accumulator_params()( \ + *this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \ + ) \ + ) \ + ) \ + { \ + /* Add-ref the Features that the user has specified */ \ + this->template visit_if >( \ + detail::make_add_ref_visitor(detail::accumulator_params()(*this)) \ + ); \ + } + + /// INTERNAL ONLY + /// + BOOST_PP_REPEAT_FROM_TO( + 2 + , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) + , BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR + , _ + ) + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// \overload + /// + template + accumulator_set(A1 const &a1, A2 const &a2, ...); + #endif + + // ... other overloads generated by Boost.Preprocessor below ... + + /////////////////////////////////////////////////////////////////////////////// + /// Visitation + /// \param func UnaryFunction which is invoked with each accumulator in turn. + template + void visit(UnaryFunction const &func) + { + fusion::for_each(this->accumulators, func); + } + + /////////////////////////////////////////////////////////////////////////////// + /// Conditional visitation + /// \param func UnaryFunction which is invoked with each accumulator in turn, + /// provided the accumulator satisfies the MPL predicate FilterPred. + template + void visit_if(UnaryFunction const &func) + { + fusion::filter_view filtered_accs(this->accumulators); + fusion::for_each(filtered_accs, func); + } + + /////////////////////////////////////////////////////////////////////////////// + /// The return type of the operator() overloads is void. + typedef void result_type; + + /////////////////////////////////////////////////////////////////////////////// + /// Accumulation + /// \param a1 Optional named parameter to be passed to all the accumulators + void operator ()() + { + this->visit( + detail::make_accumulator_visitor( + detail::accumulator_params()(*this) + ) + ); + } + + template + void operator ()(A1 const &a1) + { + this->visit( + detail::make_accumulator_visitor( + detail::accumulator_params()(*this, a1) + ) + ); + } + + // ... other overloads generated by Boost.Preprocessor: + + /// INTERNAL ONLY + /// +#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP(z, n, _) \ + template \ + void operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)) \ + { \ + this->visit( \ + detail::make_accumulator_visitor( \ + detail::accumulator_params()( \ + *this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \ + ) \ + ) \ + ); \ + } + + /// INTERNAL ONLY + /// + BOOST_PP_REPEAT_FROM_TO( + 2 + , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) + , BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP + , _ + ) + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// \overload + /// + template + void operator ()(A1 const &a1, A2 const &a2, ...); + #endif + + /////////////////////////////////////////////////////////////////////////////// + /// Extraction + template + struct apply + : fusion::result_of::value_of< + typename fusion::result_of::find_if< + accumulators_type + , detail::matches_feature + >::type + > + { + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Extraction + template + typename apply::type &extract() + { + return *fusion::find_if >(this->accumulators); + } + + /// \overload + template + typename apply::type const &extract() const + { + return *fusion::find_if >(this->accumulators); + } + + /////////////////////////////////////////////////////////////////////////////// + /// Drop + template + void drop() + { + // You can only drop the features that you have specified explicitly + typedef typename apply::type the_accumulator; + BOOST_MPL_ASSERT((detail::contains_feature_of)); + + typedef + typename feature_of::type>::type + the_feature; + + (*fusion::find_if >(this->accumulators)) + .drop(detail::accumulator_params()(*this)); + + // Also drop accumulators that this feature depends on + typedef typename the_feature::dependencies dependencies; + this->template visit_if >( + detail::make_drop_visitor(detail::accumulator_params()(*this)) + ); + } + +private: + + accumulators_type accumulators; +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// find_accumulator +// find an accumulator in an accumulator_set corresponding to a feature +template +typename mpl::apply::type & +find_accumulator(AccumulatorSet &acc BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(AccumulatorSet)) +{ + return acc.template extract(); +} + +/// \overload +template +typename mpl::apply::type const & +find_accumulator(AccumulatorSet const &acc) +{ + return acc.template extract(); +} + +/////////////////////////////////////////////////////////////////////////////// +// extract_result +// extract a result from an accumulator set +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN(z, n, _) \ + template< \ + typename Feature \ + , typename AccumulatorSet \ + BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ + > \ + typename mpl::apply::type::result_type \ + extract_result( \ + AccumulatorSet const &acc \ + BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \ + ) \ + { \ + return find_accumulator(acc).result( \ + detail::accumulator_params()( \ + acc \ + BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \ + ) \ + ); \ + } + +BOOST_PP_REPEAT( + BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) + , BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN + , _ +) + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/framework/accumulators/droppable_accumulator.hpp b/win32/include/boost/accumulators/framework/accumulators/droppable_accumulator.hpp new file mode 100755 index 000000000..ccc531531 --- /dev/null +++ b/win32/include/boost/accumulators/framework/accumulators/droppable_accumulator.hpp @@ -0,0 +1,317 @@ +/////////////////////////////////////////////////////////////////////////////// +// droppable_accumulator.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_DROPPABLE_ACCUMULATOR_HPP_EAN_13_12_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_DROPPABLE_ACCUMULATOR_HPP_EAN_13_12_2005 + +#include +#include +#include +#include +#include // for feature_of +#include // for accumulator + +namespace boost { namespace accumulators +{ + + template + struct droppable_accumulator; + + namespace detail + { + /////////////////////////////////////////////////////////////////////////////// + // add_ref_visitor + // a fusion function object for add_ref'ing accumulators + template + struct add_ref_visitor + { + explicit add_ref_visitor(Args const &args) + : args_(args) + { + } + + template + void operator ()(Accumulator &acc) const + { + typedef typename Accumulator::feature_tag::dependencies dependencies; + + acc.add_ref(this->args_); + + // Also add_ref accumulators that this feature depends on + this->args_[accumulator].template + visit_if >( + *this + ); + } + + private: + add_ref_visitor &operator =(add_ref_visitor const &); + Args const &args_; + }; + + template + add_ref_visitor make_add_ref_visitor(Args const &args) + { + return add_ref_visitor(args); + } + + /////////////////////////////////////////////////////////////////////////////// + // drop_visitor + // a fusion function object for dropping accumulators + template + struct drop_visitor + { + explicit drop_visitor(Args const &args) + : args_(args) + { + } + + template + void operator ()(Accumulator &acc) const + { + if(typename Accumulator::is_droppable()) + { + typedef typename Accumulator::feature_tag::dependencies dependencies; + + acc.drop(this->args_); + // Also drop accumulators that this feature depends on + this->args_[accumulator].template + visit_if >( + *this + ); + } + } + + private: + drop_visitor &operator =(drop_visitor const &); + Args const &args_; + }; + + template + drop_visitor make_drop_visitor(Args const &args) + { + return drop_visitor(args); + } + } + + ////////////////////////////////////////////////////////////////////////// + // droppable_accumulator_base + template + struct droppable_accumulator_base + : Accumulator + { + typedef droppable_accumulator_base base; + typedef mpl::true_ is_droppable; + typedef typename Accumulator::result_type result_type; + + template + droppable_accumulator_base(Args const &args) + : Accumulator(args) + , ref_count_(0) + { + } + + template + void operator ()(Args const &args) + { + if(!this->is_dropped()) + { + this->Accumulator::operator ()(args); + } + } + + template + void add_ref(Args const &) + { + ++this->ref_count_; + } + + template + void drop(Args const &args) + { + BOOST_ASSERT(0 < this->ref_count_); + if(1 == this->ref_count_) + { + static_cast *>(this)->on_drop(args); + } + --this->ref_count_; + } + + bool is_dropped() const + { + return 0 == this->ref_count_; + } + + private: + int ref_count_; + }; + + ////////////////////////////////////////////////////////////////////////// + // droppable_accumulator + // this can be specialized for any type that needs special handling + template + struct droppable_accumulator + : droppable_accumulator_base + { + template + droppable_accumulator(Args const &args) + : droppable_accumulator::base(args) + { + } + }; + + ////////////////////////////////////////////////////////////////////////// + // with_cached_result + template + struct with_cached_result + : Accumulator + { + typedef typename Accumulator::result_type result_type; + + template + with_cached_result(Args const &args) + : Accumulator(args) + , cache() + { + } + + with_cached_result(with_cached_result const &that) + : Accumulator(*static_cast(&that)) + , cache() + { + if(that.has_result()) + { + this->set(that.get()); + } + } + + ~with_cached_result() + { + // Since this is a base class of droppable_accumulator_base, + // this destructor is called before any of droppable_accumulator_base's + // members get cleaned up, including is_dropped, so the following + // call to has_result() is valid. + if(this->has_result()) + { + this->get().~result_type(); + } + } + + template + void on_drop(Args const &args) + { + // cache the result at the point this calcuation was dropped + BOOST_ASSERT(!this->has_result()); + this->set(this->Accumulator::result(args)); + } + + template + result_type result(Args const &args) const + { + return this->has_result() ? this->get() : this->Accumulator::result(args); + } + + private: + with_cached_result &operator =(with_cached_result const &); + + void set(result_type const &result) + { + ::new(this->cache.address()) result_type(result); + } + + result_type const &get() const + { + return *static_cast(this->cache.address()); + } + + bool has_result() const + { + typedef with_cached_result this_type; + typedef droppable_accumulator_base derived_type; + return static_cast(this)->is_dropped(); + } + + aligned_storage cache; + }; + + namespace tag + { + template + struct as_droppable + { + typedef droppable type; + }; + + template + struct as_droppable > + { + typedef droppable type; + }; + + ////////////////////////////////////////////////////////////////////////// + // droppable + template + struct droppable + : as_feature::type + { + typedef typename as_feature::type feature_type; + typedef typename feature_type::dependencies tmp_dependencies_; + + typedef + typename mpl::transform< + typename feature_type::dependencies + , as_droppable + >::type + dependencies; + + struct impl + { + template + struct apply + { + typedef + droppable_accumulator< + typename mpl::apply2::type + > + type; + }; + }; + }; + } + + // make droppable work + template + struct as_feature > + { + typedef tag::droppable::type> type; + }; + + // make droppable work with non-void weights (should become + // droppable + template + struct as_weighted_feature > + { + typedef tag::droppable::type> type; + }; + + // for the purposes of feature-based dependency resolution, + // droppable provides the same feature as Foo + template + struct feature_of > + : feature_of + { + }; + + // Note: Usually, the extractor is pulled into the accumulators namespace with + // a using directive, not the tag. But the droppable<> feature doesn't have an + // extractor, so we can put the droppable tag in the accumulators namespace + // without fear of a name conflict. + using tag::droppable; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/framework/accumulators/external_accumulator.hpp b/win32/include/boost/accumulators/framework/accumulators/external_accumulator.hpp new file mode 100755 index 000000000..c3ecaacde --- /dev/null +++ b/win32/include/boost/accumulators/framework/accumulators/external_accumulator.hpp @@ -0,0 +1,108 @@ +/////////////////////////////////////////////////////////////////////////////// +// external_accumulator.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_EXTERNAL_ACCUMULATOR_HPP_EAN_01_12_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_EXTERNAL_ACCUMULATOR_HPP_EAN_01_12_2005 + +#include +#include +#include +#include // for feature_tag +#include +#include + +namespace boost { namespace accumulators { namespace impl +{ + + ////////////////////////////////////////////////////////////////////////// + // external_impl + /// INTERNAL ONLY + /// + template + struct external_impl + : accumulator_base + { + typedef typename Accumulator::result_type result_type; + typedef typename detail::feature_tag::type feature_tag; + + external_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + return this->extract_(args, args[parameter::keyword::get() | 0]); + } + + private: + + template + static result_type extract_(Args const &args, int) + { + // No named parameter passed to the extractor. Maybe the external + // feature is held by reference<>. + extractor extract; + return extract(reference_tag(args)); + } + + template + static result_type extract_(Args const &, AccumulatorSet const &acc) + { + // OK, a named parameter for this external feature was passed to the + // extractor, so use that. + extractor extract; + return extract(acc); + } + }; + +} // namespace impl + +namespace tag +{ + ////////////////////////////////////////////////////////////////////////// + // external + template + struct external + : depends_on > + { + typedef + accumulators::impl::external_impl< + detail::to_accumulator + , Tag + > + impl; + }; + + template + struct external + : depends_on<> + { + typedef + accumulators::impl::external_impl< + detail::to_accumulator + , Tag + > + impl; + }; +} + +// for the purposes of feature-based dependency resolution, +// external_accumulator provides the same feature as Feature +template +struct feature_of > + : feature_of +{ +}; + +// Note: Usually, the extractor is pulled into the accumulators namespace with +// a using directive, not the tag. But the external<> feature doesn't have an +// extractor, so we can put the external tag in the accumulators namespace +// without fear of a name conflict. +using tag::external; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/framework/accumulators/reference_accumulator.hpp b/win32/include/boost/accumulators/framework/accumulators/reference_accumulator.hpp new file mode 100755 index 000000000..f14f1efa6 --- /dev/null +++ b/win32/include/boost/accumulators/framework/accumulators/reference_accumulator.hpp @@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////////////// +// reference_accumulator.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_REFERENCE_ACCUMULATOR_HPP_EAN_03_23_2006 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_REFERENCE_ACCUMULATOR_HPP_EAN_03_23_2006 + +#include +#include +#include +#include // for feature_tag +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + ////////////////////////////////////////////////////////////////////////// + // reference_accumulator_impl + // + template + struct reference_accumulator_impl + : accumulator_base + { + typedef Referent &result_type; + + template + reference_accumulator_impl(Args const &args) + : ref(args[parameter::keyword::get()]) + { + } + + result_type result(dont_care) const + { + return this->ref; + } + + private: + reference_wrapper ref; + }; +} // namespace impl + +namespace tag +{ + ////////////////////////////////////////////////////////////////////////// + // reference_tag + template + struct reference_tag + { + }; + + ////////////////////////////////////////////////////////////////////////// + // reference + template + struct reference + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef mpl::always > impl; + }; +} + +namespace extract +{ + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, reference, (typename)(typename)) + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, reference_tag, (typename)) +} + +using extract::reference; +using extract::reference_tag; + +// Map all reference features to reference_tag so +// that references can be extracted using reference_tag +// without specifying the referent type. +template +struct feature_of > + : feature_of > +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/framework/accumulators/value_accumulator.hpp b/win32/include/boost/accumulators/framework/accumulators/value_accumulator.hpp new file mode 100755 index 000000000..65ca7f587 --- /dev/null +++ b/win32/include/boost/accumulators/framework/accumulators/value_accumulator.hpp @@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////////////// +// value_accumulator.hpp +// +// Copyright 2005 Eric Niebler, Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_VALUE_ACCUMULATOR_HPP_EAN_03_23_2006 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_VALUE_ACCUMULATOR_HPP_EAN_03_23_2006 + +#include +#include +#include // for feature_tag +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + + ////////////////////////////////////////////////////////////////////////// + // value_accumulator_impl + template + struct value_accumulator_impl + : accumulator_base + { + typedef ValueType result_type; + + template + value_accumulator_impl(Args const &args) + : val(args[parameter::keyword::get()]) + { + } + + result_type result(dont_care) const + { + return this->val; + } + + private: + ValueType val; + }; + +} // namespace impl + +namespace tag +{ + ////////////////////////////////////////////////////////////////////////// + // value_tag + template + struct value_tag + { + }; + + ////////////////////////////////////////////////////////////////////////// + // value + template + struct value + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef mpl::always > impl; + }; +} + +namespace extract +{ + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, value, (typename)(typename)) + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, value_tag, (typename)) +} + +using extract::value; +using extract::value_tag; + +// Map all value features to value_tag so +// that values can be extracted using value_tag +// without specifying the value type. +template +struct feature_of > + : feature_of > +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/framework/depends_on.hpp b/win32/include/boost/accumulators/framework/depends_on.hpp new file mode 100755 index 000000000..20270a6d1 --- /dev/null +++ b/win32/include/boost/accumulators/framework/depends_on.hpp @@ -0,0 +1,411 @@ +/////////////////////////////////////////////////////////////////////////////// +// depends_on.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_DEPENDS_ON_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_DEPENDS_ON_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + /////////////////////////////////////////////////////////////////////////// + // as_feature + template + struct as_feature + { + typedef Feature type; + }; + + /////////////////////////////////////////////////////////////////////////// + // weighted_feature + template + struct as_weighted_feature + { + typedef Feature type; + }; + + /////////////////////////////////////////////////////////////////////////// + // feature_of + template + struct feature_of + { + typedef Feature type; + }; + + namespace detail + { + /////////////////////////////////////////////////////////////////////////// + // feature_tag + template + struct feature_tag + { + typedef typename Accumulator::feature_tag type; + }; + + template + struct undroppable + { + typedef Feature type; + }; + + template + struct undroppable > + { + typedef Feature type; + }; + + // For the purpose of determining whether one feature depends on another, + // disregard whether the feature is droppable or not. + template + struct is_dependent_on + : is_base_and_derived< + typename undroppable::type + , typename undroppable::type + > + {}; + + template + struct depends_on_base + : mpl::inherit_linearly< + typename mpl::sort >::type + // Don't inherit multiply from a feature + , mpl::if_< + is_dependent_on + , mpl::_1 + , mpl::inherit + > + >::type + { + }; + } + + /////////////////////////////////////////////////////////////////////////// + /// depends_on + template + struct depends_on + : detail::depends_on_base< + typename mpl::transform< + mpl::vector + , as_feature + >::type + > + { + typedef mpl::false_ is_weight_accumulator; + typedef + typename mpl::transform< + mpl::vector + , as_feature + >::type + dependencies; + }; + + namespace detail + { + template + struct matches_feature + { + template + struct apply + : is_same< + typename feature_of::type>::type + , typename feature_of::type>::type>::type + > + {}; + }; + + template + struct contains_feature_of + { + typedef + mpl::transform_view > > + features_list; + + typedef + typename feature_of::type>::type + the_feature; + + typedef + typename mpl::contains::type + type; + }; + + // This is to work around a bug in early versions of Fusion which caused + // a compile error if contains_feature_of is used as a + // predicate to fusion::find_if + template + struct contains_feature_of_ + { + template + struct apply + : contains_feature_of + {}; + }; + + template< + typename First + , typename Last + , bool is_empty = fusion::result_of::equal_to::value + > + struct build_acc_list; + + template + struct build_acc_list + { + typedef fusion::nil type; + + template + static fusion::nil + call(Args const &, First const&, Last const&) + { + return fusion::nil(); + } + }; + + template + struct build_acc_list + { + typedef + build_acc_list::type, Last> + next_build_acc_list; + + typedef fusion::cons< + typename fusion::result_of::value_of::type + , typename next_build_acc_list::type> + type; + + template + static type + call(Args const &args, First const& f, Last const& l) + { + return type(args, next_build_acc_list::call(args, fusion::next(f), l)); + } + }; + + namespace meta + { + template + struct make_acc_list + : build_acc_list< + typename fusion::result_of::begin::type + , typename fusion::result_of::end::type + > + {}; + } + + template + typename meta::make_acc_list::type + make_acc_list(Sequence const &seq, Args const &args) + { + return meta::make_acc_list::call(args, fusion::begin(seq), fusion::end(seq)); + } + + /////////////////////////////////////////////////////////////////////////// + // checked_as_weighted_feature + template + struct checked_as_weighted_feature + { + typedef typename as_feature::type feature_type; + typedef typename as_weighted_feature::type type; + // weighted and non-weighted flavors should provide the same feature. + BOOST_MPL_ASSERT(( + is_same< + typename feature_of::type + , typename feature_of::type + > + )); + }; + + /////////////////////////////////////////////////////////////////////////// + // as_feature_list + template + struct as_feature_list + : mpl::transform_view > + { + }; + + template + struct as_feature_list + : mpl::transform_view > + { + }; + + /////////////////////////////////////////////////////////////////////////// + // accumulator_wrapper + template + struct accumulator_wrapper + : Accumulator + { + typedef Feature feature_tag; + + accumulator_wrapper(accumulator_wrapper const &that) + : Accumulator(*static_cast(&that)) + { + } + + template + accumulator_wrapper(Args const &args) + : Accumulator(args) + { + } + }; + + /////////////////////////////////////////////////////////////////////////// + // to_accumulator + template + struct to_accumulator + { + typedef + accumulator_wrapper< + typename mpl::apply2::type + , Feature + > + type; + }; + + template + struct to_accumulator > + { + BOOST_MPL_ASSERT((is_same)); + BOOST_MPL_ASSERT((is_same)); + + typedef + accumulator_wrapper< + typename mpl::apply2::type + , Feature + > + accumulator_type; + + typedef + typename mpl::if_< + typename Feature::is_weight_accumulator + , accumulator_wrapper, Feature> + , accumulator_type + >::type + type; + }; + + // BUGBUG work around a MPL bug wrt map insertion + template + struct insert_feature + : mpl::eval_if< + mpl::has_key::type> + , mpl::identity + , mpl::insert::type, Feature> > + > + { + }; + + template + struct insert_dependencies + : mpl::fold< + as_feature_list + , FeatureMap + , insert_dependencies< + insert_feature + , mpl::_2 + , Weight + > + > + { + }; + + template + struct insert_sequence + : mpl::fold< // BUGBUG should use insert_range, but doesn't seem to work for maps + as_feature_list + , FeatureMap + , insert_feature + > + { + }; + + template + struct make_accumulator_tuple + { + typedef + typename mpl::fold< + as_feature_list + , mpl::map0<> + , mpl::if_< + mpl::is_sequence + , insert_sequence + , insert_feature + > + >::type + feature_map; + + // for each element in the map, add its dependencies also + typedef + typename mpl::fold< + feature_map + , feature_map + , insert_dependencies, Weight> + >::type + feature_map_with_dependencies; + + // turn the map into a vector so we can sort it + typedef + typename mpl::insert_range< + mpl::vector<> + , mpl::end >::type + , mpl::transform_view > + >::type + feature_vector_with_dependencies; + + // sort the features according to which is derived from which + typedef + typename mpl::sort< + feature_vector_with_dependencies + , is_dependent_on + >::type + sorted_feature_vector; + + // From the vector of features, construct a vector of accumulators + typedef + typename mpl::transform< + sorted_feature_vector + , to_accumulator + >::type + type; + }; + + } // namespace detail + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/framework/external.hpp b/win32/include/boost/accumulators/framework/external.hpp new file mode 100755 index 000000000..5a224dd5f --- /dev/null +++ b/win32/include/boost/accumulators/framework/external.hpp @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +// external.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_EXTERNAL_HPP_EAN_01_12_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_EXTERNAL_HPP_EAN_01_12_2005 + +#include +#include + +//namespace boost { namespace accumulators +//{ +// +///////////////////////////////////////////////////////////////////////////////// +//// external +//// +//template +//struct external +//{ +//}; +// +//}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/framework/extractor.hpp b/win32/include/boost/accumulators/framework/extractor.hpp new file mode 100755 index 000000000..773d4c655 --- /dev/null +++ b/win32/include/boost/accumulators/framework/extractor.hpp @@ -0,0 +1,229 @@ +/////////////////////////////////////////////////////////////////////////////// +// extractor.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace detail +{ + template + struct accumulator_set_result + { + typedef typename as_feature::type feature_type; + typedef typename mpl::apply::type::result_type type; + }; + + template + struct argument_pack_result + : accumulator_set_result< + typename remove_reference< + typename parameter::binding::type + >::type + , Feature + > + { + }; + + template + struct extractor_result + : mpl::eval_if< + detail::is_accumulator_set + , accumulator_set_result + , argument_pack_result + > + { + }; + + template + typename extractor_result::type + do_extract(AccumulatorSet const &acc, mpl::true_) + { + typedef typename as_feature::type feature_type; + return extract_result(acc); + } + + template + typename extractor_result::type + do_extract(Args const &args, mpl::false_) + { + typedef typename as_feature::type feature_type; + return find_accumulator(args[accumulator]).result(args); + } + +} // namespace detail + + +/////////////////////////////////////////////////////////////////////////////// +/// Extracts the result associated with Feature from the specified accumulator_set. +template +struct extractor +{ + typedef extractor this_type; + + /// The result meta-function for determining the return type of the extractor + template + struct result; + + template + struct result + : detail::extractor_result + { + }; + + /// Extract the result associated with Feature from the accumulator set + /// \param acc The accumulator set object from which to extract the result + template + typename detail::extractor_result::type + operator ()(Arg1 const &arg1) const + { + // Arg1 could be an accumulator_set or an argument pack containing + // an accumulator_set. Dispatch accordingly. + return detail::do_extract(arg1, detail::is_accumulator_set()); + } + + /// \overload + /// + /// \param a1 Optional named parameter to be passed to the accumulator's result() function. + template + typename detail::extractor_result::type + operator ()(AccumulatorSet const &acc, A1 const &a1) const + { + BOOST_MPL_ASSERT((detail::is_accumulator_set)); + typedef typename as_feature::type feature_type; + return extract_result(acc, a1); + } + + // ... other overloads generated by Boost.Preprocessor: + + /// INTERNAL ONLY + /// +#define BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP(z, n, _) \ + template \ + struct result \ + : detail::extractor_result \ + {}; \ + template< \ + typename AccumulatorSet \ + BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ + > \ + typename detail::extractor_result::type \ + operator ()( \ + AccumulatorSet const &acc \ + BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \ + ) const \ + { \ + BOOST_MPL_ASSERT((detail::is_accumulator_set)); \ + typedef typename as_feature::type feature_type; \ + return extract_result(acc BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a));\ + } + + BOOST_PP_REPEAT_FROM_TO( + 2 + , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) + , BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP + , _ + ) + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// \overload + /// + template + typename detail::extractor_result::type + operator ()(AccumulatorSet const &acc, A1 const &a1, A2 const &a2, ...); + #endif +}; + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_ARRAY_REM(Array) \ + BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_ARRAY_SIZE(Array), BOOST_PP_ARRAY_DATA(Array)) + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_SEQ_REM(Seq) \ + BOOST_ACCUMULATORS_ARRAY_REM(BOOST_PP_SEQ_TO_ARRAY(Seq)) + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_ARGS_OP(s, data, elem) \ + T ## s + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_PARAMS_OP(s, data, elem) \ + elem T ## s + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) \ + Tag::Feature< \ + BOOST_ACCUMULATORS_SEQ_REM( \ + BOOST_PP_SEQ_TRANSFORM(BOOST_ACCUMULATORS_ARGS_OP, ~, ParamsSeq) \ + ) \ + > + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN_IMPL(z, n, Tag, Feature, ParamsSeq) \ + template< \ + BOOST_ACCUMULATORS_SEQ_REM( \ + BOOST_PP_SEQ_TRANSFORM(BOOST_ACCUMULATORS_PARAMS_OP, ~, ParamsSeq) \ + ) \ + , typename Arg1 \ + BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ + > \ + typename boost::accumulators::detail::extractor_result< \ + Arg1 \ + , BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) \ + >::type \ + Feature(Arg1 const &arg1 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) ) \ + { \ + typedef BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) feature_type; \ + return boost::accumulators::extractor()( \ + arg1 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)); \ + } + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN(z, n, _) \ + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN_IMPL( \ + z \ + , n \ + , BOOST_PP_ARRAY_ELEM(0, _) \ + , BOOST_PP_ARRAY_ELEM(1, _) \ + , BOOST_PP_ARRAY_ELEM(2, _) \ + ) + +#define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(Tag, Feature, ParamSeq) \ + BOOST_PP_REPEAT( \ + BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) \ + , BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN \ + , (3, (Tag, Feature, ParamSeq)) \ + ) + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/framework/features.hpp b/win32/include/boost/accumulators/framework/features.hpp new file mode 100755 index 000000000..2d17f8c9b --- /dev/null +++ b/win32/include/boost/accumulators/framework/features.hpp @@ -0,0 +1,29 @@ +/////////////////////////////////////////////////////////////////////////////// +// features.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_STATS_HPP_EAN_08_12_2005 +#define BOOST_ACCUMULATORS_STATISTICS_STATS_HPP_EAN_08_12_2005 + +#include +#include +#include + +namespace boost { namespace accumulators +{ + +/////////////////////////////////////////////////////////////////////////////// +// features +// +template +struct features + : mpl::vector +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/framework/parameters/accumulator.hpp b/win32/include/boost/accumulators/framework/parameters/accumulator.hpp new file mode 100755 index 000000000..0648cebfc --- /dev/null +++ b/win32/include/boost/accumulators/framework/parameters/accumulator.hpp @@ -0,0 +1,20 @@ +/////////////////////////////////////////////////////////////////////////////// +// accumulator.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_ACCUMULATOR_HPP_EAN_31_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_ACCUMULATOR_HPP_EAN_31_10_2005 + +#include + +namespace boost { namespace accumulators +{ + +BOOST_PARAMETER_KEYWORD(tag, accumulator) + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/framework/parameters/sample.hpp b/win32/include/boost/accumulators/framework/parameters/sample.hpp new file mode 100755 index 000000000..4ab695b7e --- /dev/null +++ b/win32/include/boost/accumulators/framework/parameters/sample.hpp @@ -0,0 +1,20 @@ +/////////////////////////////////////////////////////////////////////////////// +// sample.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_SAMPLE_HPP_EAN_31_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_SAMPLE_HPP_EAN_31_10_2005 + +#include + +namespace boost { namespace accumulators +{ + +BOOST_PARAMETER_KEYWORD(tag, sample) + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/framework/parameters/weight.hpp b/win32/include/boost/accumulators/framework/parameters/weight.hpp new file mode 100755 index 000000000..2c58da1ec --- /dev/null +++ b/win32/include/boost/accumulators/framework/parameters/weight.hpp @@ -0,0 +1,21 @@ +/////////////////////////////////////////////////////////////////////////////// +// weight.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHT_HPP_EAN_31_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHT_HPP_EAN_31_10_2005 + +#include + +namespace boost { namespace accumulators +{ + +// The weight of a single sample +BOOST_PARAMETER_KEYWORD(tag, weight) + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/framework/parameters/weights.hpp b/win32/include/boost/accumulators/framework/parameters/weights.hpp new file mode 100755 index 000000000..ca052fa5c --- /dev/null +++ b/win32/include/boost/accumulators/framework/parameters/weights.hpp @@ -0,0 +1,21 @@ +/////////////////////////////////////////////////////////////////////////////// +// weights.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHTS_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHTS_HPP_EAN_28_10_2005 + +#include + +namespace boost { namespace accumulators +{ + +// The weight accumulator +BOOST_PARAMETER_KEYWORD(tag, weights) + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/numeric/detail/function1.hpp b/win32/include/boost/accumulators/numeric/detail/function1.hpp new file mode 100755 index 000000000..09b79701d --- /dev/null +++ b/win32/include/boost/accumulators/numeric/detail/function1.hpp @@ -0,0 +1,75 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_DETAIL_FUNCTION1_DWA200655_HPP +# define BOOST_DETAIL_FUNCTION1_DWA200655_HPP + +# include +# include +# include +# include + +namespace boost { namespace detail { + +// A utility for creating unary function objects that play nicely with +// boost::result_of and that handle the forwarding problem. +// +// mpl::apply::type is expected to be a stateless function +// object that accepts an argument of type A0&. It is also expected +// to have a nested ::result_type identical to its return type. +template +struct function1 +{ + template + struct result + {}; + + template + struct result + { + // How adding const to arguments handles rvalues. + // + // if A0 is arg0 is represents actual argument + // -------- ------- -------------------------- + // T const & T const const T lvalue + // T & T non-const T lvalue + // T const T const const T rvalue + // T T const non-const T rvalue + typedef typename remove_reference< + typename add_const< A0 >::type + >::type arg0; + + typedef typename mpl::apply1::type impl; + typedef typename impl::result_type type; + }; + + // Handles mutable lvalues + template + typename result::type + operator ()(A0 &a0) const + { + typedef typename result::impl impl; + typedef typename result::type type; + typedef A0 &arg0; + BOOST_CONCEPT_ASSERT((UnaryFunction)); + //boost::function_requires >(); + return impl()(a0); + } + + // Handles const lvalues and all rvalues + template + typename result::type + operator ()(A0 const &a0) const + { + typedef typename result::impl impl; + typedef typename result::type type; + typedef A0 const &arg0; + BOOST_CONCEPT_ASSERT((UnaryFunction)); + //boost::function_requires >(); + return impl()(a0); + } +}; + +}} // namespace boost::detail + +#endif // BOOST_DETAIL_FUNCTION1_DWA200655_HPP diff --git a/win32/include/boost/accumulators/numeric/detail/function2.hpp b/win32/include/boost/accumulators/numeric/detail/function2.hpp new file mode 100755 index 000000000..0c5a5177e --- /dev/null +++ b/win32/include/boost/accumulators/numeric/detail/function2.hpp @@ -0,0 +1,10 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_DETAIL_FUNCTION2_DWA200655_HPP +# define BOOST_DETAIL_FUNCTION2_DWA200655_HPP + +# define args (2) +# include + +#endif // BOOST_DETAIL_FUNCTION2_DWA200655_HPP diff --git a/win32/include/boost/accumulators/numeric/detail/function3.hpp b/win32/include/boost/accumulators/numeric/detail/function3.hpp new file mode 100755 index 000000000..9058486ca --- /dev/null +++ b/win32/include/boost/accumulators/numeric/detail/function3.hpp @@ -0,0 +1,10 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_DETAIL_FUNCTION3_DWA2006514_HPP +# define BOOST_DETAIL_FUNCTION3_DWA2006514_HPP + +# define args (3) +# include + +#endif // BOOST_DETAIL_FUNCTION3_DWA2006514_HPP diff --git a/win32/include/boost/accumulators/numeric/detail/function4.hpp b/win32/include/boost/accumulators/numeric/detail/function4.hpp new file mode 100755 index 000000000..c219615ca --- /dev/null +++ b/win32/include/boost/accumulators/numeric/detail/function4.hpp @@ -0,0 +1,10 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_DETAIL_FUNCTION4_DWA2006514_HPP +# define BOOST_DETAIL_FUNCTION4_DWA2006514_HPP + +# define args (4) +# include + +#endif // BOOST_DETAIL_FUNCTION4_DWA2006514_HPP diff --git a/win32/include/boost/accumulators/numeric/detail/function_n.hpp b/win32/include/boost/accumulators/numeric/detail/function_n.hpp new file mode 100755 index 000000000..a485cafc9 --- /dev/null +++ b/win32/include/boost/accumulators/numeric/detail/function_n.hpp @@ -0,0 +1,148 @@ +// Copyright David Abrahams 2006. 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) +// +// #include guards intentionally disabled. +// #ifndef BOOST_DETAIL_FUNCTION_N_DWA2006514_HPP +// # define BOOST_DETAIL_FUNCTION_N_DWA2006514_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace detail { + +# define BOOST_DETAIL_default_arg(z, n, _) \ + typedef mpl::void_ BOOST_PP_CAT(arg, n); + +# define BOOST_DETAIL_function_arg(z, n, _) \ + typedef typename remove_reference< \ + typename add_const< BOOST_PP_CAT(A, n) >::type \ + >::type BOOST_PP_CAT(arg, n); + +#define BOOST_DETAIL_cat_arg_counts(s, state, n) \ + BOOST_PP_IF( \ + n \ + , BOOST_PP_CAT(state, BOOST_PP_CAT(_, n)) \ + , state \ + ) \ + /**/ + +#define function_name \ + BOOST_PP_SEQ_FOLD_LEFT( \ + BOOST_DETAIL_cat_arg_counts \ + , BOOST_PP_CAT(function, BOOST_PP_SEQ_HEAD(args)) \ + , BOOST_PP_SEQ_TAIL(args)(0) \ + ) \ + /**/ + +template +struct function_name +{ + BOOST_PP_REPEAT( + BOOST_MPL_LIMIT_METAFUNCTION_ARITY + , BOOST_DETAIL_default_arg + , ~ + ) + + template + struct result {}; + +#define BOOST_DETAIL_function_result(r, _, n) \ + template \ + struct result \ + { \ + BOOST_PP_REPEAT(n, BOOST_DETAIL_function_arg, ~) \ + typedef \ + typename BOOST_PP_CAT(mpl::apply, BOOST_MPL_LIMIT_METAFUNCTION_ARITY)<\ + F \ + BOOST_PP_ENUM_TRAILING_PARAMS( \ + BOOST_MPL_LIMIT_METAFUNCTION_ARITY \ + , arg \ + ) \ + >::type \ + impl; \ + typedef typename impl::result_type type; \ + }; \ + /**/ + + BOOST_PP_SEQ_FOR_EACH(BOOST_DETAIL_function_result, _, args) + +# define arg_type(r, _, i, is_const) \ + BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(A, i) BOOST_PP_CAT(const_if, is_const) & + +# define result_(r, n, constness) \ + typename result< \ + function_name( \ + BOOST_PP_SEQ_FOR_EACH_I_R(r, arg_type, ~, constness) \ + ) \ + > \ + /**/ + +# define param(r, _, i, is_const) BOOST_PP_COMMA_IF(i) \ + BOOST_PP_CAT(A, i) BOOST_PP_CAT(const_if, is_const) & BOOST_PP_CAT(x, i) + +# define param_list(r, n, constness) \ + BOOST_PP_SEQ_FOR_EACH_I_R(r, param, ~, constness) + +# define call_operator(r, constness) \ + template \ + result_(r, BOOST_PP_SEQ_SIZE(constness), constness)::type \ + operator ()( param_list(r, BOOST_PP_SEQ_SIZE(constness), constness) ) const \ + { \ + typedef result_(r, BOOST_PP_SEQ_SIZE(constness), constness)::impl impl; \ + return impl()(BOOST_PP_ENUM_PARAMS(BOOST_PP_SEQ_SIZE(constness), x)); \ + } \ + /**/ + +# define const_if0 +# define const_if1 const + +# define bits(z, n, _) ((0)(1)) + +# define gen_operator(r, _, n) \ + BOOST_PP_SEQ_FOR_EACH_PRODUCT_R( \ + r \ + , call_operator \ + , BOOST_PP_REPEAT(n, bits, ~) \ + ) \ + /**/ + + BOOST_PP_SEQ_FOR_EACH( + gen_operator + , ~ + , args + ) + +# undef bits +# undef const_if1 +# undef const_if0 +# undef call_operator +# undef param_list +# undef param +# undef result_ +# undef default_ +# undef arg_type +# undef gen_operator +# undef function_name + +# undef args +}; + +}} // namespace boost::detail + +//#endif // BOOST_DETAIL_FUNCTION_N_DWA2006514_HPP diff --git a/win32/include/boost/accumulators/numeric/detail/pod_singleton.hpp b/win32/include/boost/accumulators/numeric/detail/pod_singleton.hpp new file mode 100755 index 000000000..3794d3280 --- /dev/null +++ b/win32/include/boost/accumulators/numeric/detail/pod_singleton.hpp @@ -0,0 +1,20 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_DETAIL_POD_SINGLETON_DWA200655_HPP +# define BOOST_DETAIL_POD_SINGLETON_DWA200655_HPP + +namespace boost { namespace detail { + +template +struct pod_singleton +{ + static T instance; +}; + +template +T pod_singleton::instance; + +}} // namespace boost::detail + +#endif // BOOST_DETAIL_POD_SINGLETON_DWA200655_HPP diff --git a/win32/include/boost/accumulators/numeric/functional.hpp b/win32/include/boost/accumulators/numeric/functional.hpp new file mode 100755 index 000000000..6d615ca1b --- /dev/null +++ b/win32/include/boost/accumulators/numeric/functional.hpp @@ -0,0 +1,490 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file functional.hpp +/// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_NUMERIC_FUNCTIONAL_HPP_EAN_08_12_2005 +#define BOOST_NUMERIC_FUNCTIONAL_HPP_EAN_08_12_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_NUMERIC_FUNCTIONAL_STD_VECTOR_SUPPORT +# include +#endif + +#ifdef BOOST_NUMERIC_FUNCTIONAL_STD_VALARRAY_SUPPORT +# include +#endif + +#ifdef BOOST_NUMERIC_FUNCTIONAL_STD_COMPLEX_SUPPORT +# include +#endif + +/// INTERNAL ONLY +/// +#define BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED + +#ifdef BOOST_NUMERIC_FUNCTIONAL_DOXYGEN_INVOKED +// Hack to make Doxygen show the inheritance relationships +/// INTERNAL ONLY +/// +namespace std +{ + /// INTERNAL ONLY + /// + template struct unary_function {}; + /// INTERNAL ONLY + /// + template struct binary_function {}; +} +#endif + +namespace boost { namespace numeric +{ + namespace functional + { + /// INTERNAL ONLY + /// + template + struct are_integral + : mpl::and_, is_integral > + {}; + + template + struct left_ref + { + typedef Left &type; + }; + + namespace detail + { + template + T &lvalue_of(); + } + } + + // TODO: handle complex weight, valarray, MTL vectors + + /// INTERNAL ONLY + /// +#define BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(Name, Op) \ + namespace functional \ + { \ + template \ + struct result_of_ ## Name \ + { \ + BOOST_TYPEOF_NESTED_TYPEDEF_TPL( \ + nested \ + , Op boost::numeric::functional::detail::lvalue_of() \ + ) \ + typedef typename nested::type type; \ + }; \ + template \ + struct Name ## _base \ + : std::unary_function< \ + typename remove_const::type \ + , typename result_of_ ## Name::type \ + > \ + { \ + typename result_of_ ## Name::type operator ()(Arg &arg) const \ + { \ + return Op arg; \ + } \ + }; \ + template \ + struct Name \ + : Name ## _base \ + {}; \ + } \ + namespace op \ + { \ + struct Name \ + : boost::detail::function1 > > \ + {}; \ + } \ + namespace \ + { \ + op::Name const &Name = boost::detail::pod_singleton::instance; \ + } \ + /**/ + + /// INTERNAL ONLY + /// +#define BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(Name, Op, RetType) \ + namespace functional \ + { \ + template \ + struct result_of_ ## Name \ + { \ + RetType(Left, Op, Right) \ + }; \ + template \ + struct Name ## _base \ + : std::binary_function< \ + typename remove_const::type \ + , typename remove_const::type \ + , typename result_of_ ## Name::type \ + > \ + { \ + typename result_of_ ## Name::type \ + operator ()(Left &left, Right &right) const \ + { \ + return left Op right; \ + } \ + }; \ + template \ + struct Name \ + : Name ## _base \ + {}; \ + } \ + namespace op \ + { \ + struct Name \ + : boost::detail::function2< \ + functional::Name<_1, _2, functional::tag<_1>, functional::tag<_2> > \ + > \ + {}; \ + } \ + namespace \ + { \ + op::Name const &Name = boost::detail::pod_singleton::instance; \ + } \ + /**/ + + /// INTERNAL ONLY + /// +#define BOOST_NUMERIC_FUNCTIONAL_DEDUCED(Left, Op, Right) \ + BOOST_TYPEOF_NESTED_TYPEDEF_TPL( \ + nested \ + , boost::numeric::functional::detail::lvalue_of() Op \ + boost::numeric::functional::detail::lvalue_of() \ + ) \ + typedef typename nested::type type; \ + /**/ + + /// INTERNAL ONLY + /// +#define BOOST_NUMERIC_FUNCTIONAL_LEFT(Left, Op, Right) \ + typedef Left &type; \ + /**/ + + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(plus, +, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(minus, -, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(multiplies, *, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(divides, /, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(modulus, %, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(greater, >, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(greater_equal, >=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(less, <, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(less_equal, <=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(equal_to, ==, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(not_equal_to, !=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(assign, =, BOOST_NUMERIC_FUNCTIONAL_LEFT) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(plus_assign, +=, BOOST_NUMERIC_FUNCTIONAL_LEFT) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(minus_assign, -=, BOOST_NUMERIC_FUNCTIONAL_LEFT) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(multiplies_assign, *=, BOOST_NUMERIC_FUNCTIONAL_LEFT) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(divides_assign, /=, BOOST_NUMERIC_FUNCTIONAL_LEFT) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(modulus_assign, %=, BOOST_NUMERIC_FUNCTIONAL_LEFT) + + BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(unary_plus, +) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(unary_minus, -) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(complement, ~) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(logical_not, !) + +#undef BOOST_NUMERIC_FUNCTIONAL_LEFT +#undef BOOST_NUMERIC_FUNCTIONAL_DEDUCED +#undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP +#undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP + + namespace functional + { + template + struct min_assign_base + : std::binary_function + { + void operator ()(Left &left, Right &right) const + { + if(numeric::less(right, left)) + { + left = right; + } + } + }; + + template + struct max_assign_base + : std::binary_function + { + void operator ()(Left &left, Right &right) const + { + if(numeric::greater(right, left)) + { + left = right; + } + } + }; + + template + struct average_base + : functional::divides + {}; + + // partial specialization that promotes the arguments to double for + // integral division. + template + struct average_base >::type> + : functional::divides + {}; + + template + struct promote_base + : std::unary_function + { + To operator ()(From &from) const + { + return from; + } + }; + + template + struct promote_base + : std::unary_function + { + ToFrom &operator ()(ToFrom &tofrom) + { + return tofrom; + } + }; + + template + struct as_min_base + : std::unary_function::type> + { + typename remove_const::type operator ()(Arg &) const + { + return (std::numeric_limits::type>::min)(); + } + }; + + template + struct as_min_base >::type> + : std::unary_function::type> + { + typename remove_const::type operator ()(Arg &) const + { + return -(std::numeric_limits::type>::max)(); + } + }; + + template + struct as_max_base + : std::unary_function::type> + { + typename remove_const::type operator ()(Arg &) const + { + return (std::numeric_limits::type>::max)(); + } + }; + + template + struct as_zero_base + : std::unary_function::type> + { + typename remove_const::type operator ()(Arg &) const + { + return numeric::zero::type>::value; + } + }; + + template + struct as_one_base + : std::unary_function::type> + { + typename remove_const::type operator ()(Arg &) const + { + return numeric::one::type>::value; + } + }; + + template + struct promote + : promote_base + {}; + + template + struct min_assign + : min_assign_base + {}; + + template + struct max_assign + : max_assign_base + {}; + + template + struct average + : average_base + {}; + + template + struct as_min + : as_min_base + {}; + + template + struct as_max + : as_max_base + {}; + + template + struct as_zero + : as_zero_base + {}; + + template + struct as_one + : as_one_base + {}; + } + + namespace op + { + template + struct promote + : boost::detail::function1::type, functional::tag<_> > > + {}; + + struct min_assign + : boost::detail::function2, functional::tag<_2> > > + {}; + + struct max_assign + : boost::detail::function2, functional::tag<_2> > > + {}; + + struct average + : boost::detail::function2, functional::tag<_2> > > + {}; + + struct as_min + : boost::detail::function1 > > + {}; + + struct as_max + : boost::detail::function1 > > + {}; + + struct as_zero + : boost::detail::function1 > > + {}; + + struct as_one + : boost::detail::function1 > > + {}; + } + + namespace + { + op::min_assign const &min_assign = boost::detail::pod_singleton::instance; + op::max_assign const &max_assign = boost::detail::pod_singleton::instance; + op::average const &average = boost::detail::pod_singleton::instance; + op::as_min const &as_min = boost::detail::pod_singleton::instance; + op::as_max const &as_max = boost::detail::pod_singleton::instance; + op::as_zero const &as_zero = boost::detail::pod_singleton::instance; + op::as_one const &as_one = boost::detail::pod_singleton::instance; + } + + /////////////////////////////////////////////////////////////////////////////// + // promote + template + typename lazy_disable_if, mpl::if_, To &, To> >::type + promote(From &from) + { + return functional::promote()(from); + } + + template + typename mpl::if_, To const &, To const>::type + promote(From const &from) + { + return functional::promote()(from); + } + + template + struct default_ + { + typedef default_ type; + typedef T value_type; + static T const value; + + operator T const & () const + { + return default_::value; + } + }; + + template + T const default_::value = T(); + + template + struct one + { + typedef one type; + typedef T value_type; + static T const value; + + operator T const & () const + { + return one::value; + } + }; + + template + T const one::value = T(1); + + template + struct zero + { + typedef zero type; + typedef T value_type; + static T const value; + + operator T const & () const + { + return zero::value; + } + }; + + template + T const zero::value = T(); + + template + struct one_or_default + : mpl::if_, default_, one >::type + {}; + + template + struct zero_or_default + : mpl::if_, default_, zero >::type + {}; + +}} // namespace boost::numeric + +#endif diff --git a/win32/include/boost/accumulators/numeric/functional/complex.hpp b/win32/include/boost/accumulators/numeric/functional/complex.hpp new file mode 100755 index 000000000..8897f8819 --- /dev/null +++ b/win32/include/boost/accumulators/numeric/functional/complex.hpp @@ -0,0 +1,82 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file complex.hpp +/// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_NUMERIC_FUNCTIONAL_COMPLEX_HPP_EAN_01_17_2006 +#define BOOST_NUMERIC_FUNCTIONAL_COMPLEX_HPP_EAN_01_17_2006 + +#ifdef BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED +# error Include this file before boost/accumulators/numeric/functional.hpp +#endif + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace numeric { namespace operators +{ + // So that the stats compile when Sample type is std::complex + template + typename + disable_if< + mpl::or_, is_same, U> > + , std::complex + >::type + operator *(std::complex ri, U const &u) + { + // BUGBUG promote result to typeof(T()*u) ? + return ri *= static_cast(u); + } + + template + typename + disable_if< + mpl::or_, is_same, U> > + , std::complex + >::type + operator /(std::complex ri, U const &u) + { + // BUGBUG promote result to typeof(T()*u) ? + return ri /= static_cast(u); + } + +}}} // namespace boost::numeric::operators + +namespace boost { namespace numeric +{ + namespace detail + { + template + struct one_complex + { + static std::complex const value; + }; + + template + std::complex const one_complex::value + = std::complex(numeric::one::value, numeric::one::value); + } + + /// INTERNAL ONLY + /// + template + struct one > + : detail::one_complex + { + typedef one type; + typedef std::complex value_type; + operator value_type const & () const + { + return detail::one_complex::value; + } + }; + +}} // namespace boost::numeric + +#endif diff --git a/win32/include/boost/accumulators/numeric/functional/valarray.hpp b/win32/include/boost/accumulators/numeric/functional/valarray.hpp new file mode 100755 index 000000000..ea226da4c --- /dev/null +++ b/win32/include/boost/accumulators/numeric/functional/valarray.hpp @@ -0,0 +1,351 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file valarray.hpp +/// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_NUMERIC_FUNCTIONAL_VALARRAY_HPP_EAN_12_12_2005 +#define BOOST_NUMERIC_FUNCTIONAL_VALARRAY_HPP_EAN_12_12_2005 + +#ifdef BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED +# error Include this file before boost/accumulators/numeric/functional.hpp +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace numeric +{ + namespace operators + { + /////////////////////////////////////////////////////////////////////////////// + // Handle valarray / Right where Right is a scalar and Right != Left. + template + typename enable_if< + mpl::and_, mpl::not_ > > + , std::valarray::result_type> + >::type + operator /(std::valarray const &left, Right const &right) + { + typedef typename functional::divides::result_type value_type; + std::valarray result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::divides(left[i], right); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle valarray * Right where Right is a scalar and Right != Left. + template + typename enable_if< + mpl::and_, mpl::not_ > > + , std::valarray::result_type> + >::type + operator *(std::valarray const &left, Right const &right) + { + typedef typename functional::multiplies::result_type value_type; + std::valarray result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::multiplies(left[i], right); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle valarray + valarray where Right != Left. + template + typename disable_if< + is_same + , std::valarray::result_type> + >::type + operator +(std::valarray const &left, std::valarray const &right) + { + typedef typename functional::plus::result_type value_type; + std::valarray result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::plus(left[i], right[i]); + } + return result; + } + } + + namespace functional + { + struct std_valarray_tag; + + template + struct tag > + { + typedef std_valarray_tag type; + }; + + #ifdef __GLIBCXX__ + template + struct tag > + { + typedef std_valarray_tag type; + }; + #endif + + /// INTERNAL ONLY + /// + // This is necessary because the GCC stdlib uses expression templates, and + // typeof(som-valarray-expression) is not an instance of std::valarray + #define BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(Name, Op) \ + template \ + struct Name \ + : std::binary_function< \ + Left \ + , Right \ + , std::valarray< \ + typename Name< \ + typename Left::value_type \ + , typename Right::value_type \ + >::result_type \ + > \ + > \ + { \ + typedef typename Left::value_type left_value_type; \ + typedef typename Right::value_type right_value_type; \ + typedef \ + std::valarray< \ + typename Name::result_type \ + > \ + result_type; \ + result_type \ + operator ()(Left &left, Right &right) const \ + { \ + return numeric::promote >(left) \ + Op numeric::promote >(right); \ + } \ + }; \ + template \ + struct Name \ + : std::binary_function< \ + Left \ + , Right \ + , std::valarray< \ + typename Name::result_type \ + > \ + > \ + { \ + typedef typename Left::value_type left_value_type; \ + typedef \ + std::valarray< \ + typename Name::result_type \ + > \ + result_type; \ + result_type \ + operator ()(Left &left, Right &right) const \ + { \ + return numeric::promote >(left) Op right;\ + } \ + }; \ + template \ + struct Name \ + : std::binary_function< \ + Left \ + , Right \ + , std::valarray< \ + typename Name::result_type \ + > \ + > \ + { \ + typedef typename Right::value_type right_value_type; \ + typedef \ + std::valarray< \ + typename Name::result_type \ + > \ + result_type; \ + result_type \ + operator ()(Left &left, Right &right) const \ + { \ + return left Op numeric::promote >(right);\ + } \ + }; + + BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(plus, +) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(minus, -) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(multiplies, *) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(divides, /) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(modulus, %) + + #undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP + + /////////////////////////////////////////////////////////////////////////////// + // element-wise min of std::valarray + template + struct min_assign + : std::binary_function + { + void operator ()(Left &left, Right &right) const + { + BOOST_ASSERT(left.size() == right.size()); + for(std::size_t i = 0, size = left.size(); i != size; ++i) + { + if(numeric::less(right[i], left[i])) + { + left[i] = right[i]; + } + } + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // element-wise max of std::valarray + template + struct max_assign + : std::binary_function + { + void operator ()(Left &left, Right &right) const + { + BOOST_ASSERT(left.size() == right.size()); + for(std::size_t i = 0, size = left.size(); i != size; ++i) + { + if(numeric::greater(right[i], left[i])) + { + left[i] = right[i]; + } + } + } + }; + + // partial specialization of numeric::average<> for std::valarray. + template + struct average + : mpl::if_< + are_integral + , divides + , divides + >::type + {}; + + // promote + template + struct promote + : std::unary_function + { + To operator ()(From &arr) const + { + typename remove_const::type res(arr.size()); + for(std::size_t i = 0, size = arr.size(); i != size; ++i) + { + res[i] = numeric::promote(arr[i]); + } + return res; + } + }; + + template + struct promote + : std::unary_function + { + ToFrom &operator ()(ToFrom &tofrom) const + { + return tofrom; + } + }; + + // for "promoting" a std::valarray to a bool, useful for + // comparing 2 valarrays for equality: + // if(numeric::promote(a == b)) + template + struct promote + : std::unary_function + { + bool operator ()(From &arr) const + { + BOOST_MPL_ASSERT((is_same)); + for(std::size_t i = 0, size = arr.size(); i != size; ++i) + { + if(!arr[i]) + { + return false; + } + } + return true; + } + }; + + template + struct promote + : promote + {}; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_min + template + struct as_min + : std::unary_function::type> + { + typename remove_const::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(numeric::as_min(arr[0]), arr.size()); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_max + template + struct as_max + : std::unary_function::type> + { + typename remove_const::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(numeric::as_max(arr[0]), arr.size()); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_zero + template + struct as_zero + : std::unary_function::type> + { + typename remove_const::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(numeric::as_zero(arr[0]), arr.size()); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_one + template + struct as_one + : std::unary_function::type> + { + typename remove_const::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(numeric::as_one(arr[0]), arr.size()); + } + }; + + } // namespace functional + +}} // namespace boost::numeric + +#endif + diff --git a/win32/include/boost/accumulators/numeric/functional/vector.hpp b/win32/include/boost/accumulators/numeric/functional/vector.hpp new file mode 100755 index 000000000..964c04889 --- /dev/null +++ b/win32/include/boost/accumulators/numeric/functional/vector.hpp @@ -0,0 +1,320 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file vector.hpp +/// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_NUMERIC_FUNCTIONAL_VECTOR_HPP_EAN_12_12_2005 +#define BOOST_NUMERIC_FUNCTIONAL_VECTOR_HPP_EAN_12_12_2005 + +#ifdef BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED +# error Include this file before boost/accumulators/numeric/functional.hpp +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace numeric +{ + namespace operators + { + /////////////////////////////////////////////////////////////////////////////// + // Handle vector / Right where Right is a scalar. + template + typename enable_if< + is_scalar + , std::vector::result_type> + >::type + operator /(std::vector const &left, Right const &right) + { + typedef typename functional::divides::result_type value_type; + std::vector result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::divides(left[i], right); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle vector / vector. + template + std::vector::result_type> + operator /(std::vector const &left, std::vector const &right) + { + typedef typename functional::divides::result_type value_type; + std::vector result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::divides(left[i], right[i]); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle vector * Right where Right is a scalar. + template + typename enable_if< + is_scalar + , std::vector::result_type> + >::type + operator *(std::vector const &left, Right const &right) + { + typedef typename functional::multiplies::result_type value_type; + std::vector result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::multiplies(left[i], right); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle Left * vector where Left is a scalar. + template + typename enable_if< + is_scalar + , std::vector::result_type> + >::type + operator *(Left const &left, std::vector const &right) + { + typedef typename functional::multiplies::result_type value_type; + std::vector result(right.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::multiplies(left, right[i]); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle vector * vector + template + std::vector::result_type> + operator *(std::vector const &left, std::vector const &right) + { + typedef typename functional::multiplies::result_type value_type; + std::vector result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::multiplies(left[i], right[i]); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle vector + vector + template + std::vector::result_type> + operator +(std::vector const &left, std::vector const &right) + { + typedef typename functional::plus::result_type value_type; + std::vector result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::plus(left[i], right[i]); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle vector - vector + template + std::vector::result_type> + operator -(std::vector const &left, std::vector const &right) + { + typedef typename functional::minus::result_type value_type; + std::vector result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::minus(left[i], right[i]); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle vector += vector + template + std::vector & + operator +=(std::vector &left, std::vector const &right) + { + BOOST_ASSERT(left.size() == right.size()); + for(std::size_t i = 0, size = left.size(); i != size; ++i) + { + numeric::plus_assign(left[i], right[i]); + } + return left; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle -vector + template + std::vector::result_type> + operator -(std::vector const &arg) + { + typedef typename functional::unary_minus::result_type value_type; + std::vector result(arg.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::unary_minus(arg[i]); + } + return result; + } + } + + namespace functional + { + struct std_vector_tag; + + template + struct tag > + { + typedef std_vector_tag type; + }; + + /////////////////////////////////////////////////////////////////////////////// + // element-wise min of std::vector + template + struct min_assign + : std::binary_function + { + void operator ()(Left &left, Right &right) const + { + BOOST_ASSERT(left.size() == right.size()); + for(std::size_t i = 0, size = left.size(); i != size; ++i) + { + if(numeric::less(right[i], left[i])) + { + left[i] = right[i]; + } + } + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // element-wise max of std::vector + template + struct max_assign + : std::binary_function + { + void operator ()(Left &left, Right &right) const + { + BOOST_ASSERT(left.size() == right.size()); + for(std::size_t i = 0, size = left.size(); i != size; ++i) + { + if(numeric::greater(right[i], left[i])) + { + left[i] = right[i]; + } + } + } + }; + + // partial specialization for std::vector. + template + struct average + : mpl::if_< + are_integral + , divides + , divides + >::type + {}; + + // promote + template + struct promote + : std::unary_function + { + To operator ()(From &arr) const + { + typename remove_const::type res(arr.size()); + for(std::size_t i = 0, size = arr.size(); i != size; ++i) + { + res[i] = numeric::promote(arr[i]); + } + return res; + } + }; + + template + struct promote + : std::unary_function + { + ToFrom &operator ()(ToFrom &tofrom) const + { + return tofrom; + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_min + template + struct as_min + : std::unary_function::type> + { + typename remove_const::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(arr.size(), numeric::as_min(arr[0])); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_max + template + struct as_max + : std::unary_function::type> + { + typename remove_const::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(arr.size(), numeric::as_max(arr[0])); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_zero + template + struct as_zero + : std::unary_function::type> + { + typename remove_const::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(arr.size(), numeric::as_zero(arr[0])); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_one + template + struct as_one + : std::unary_function::type> + { + typename remove_const::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(arr.size(), numeric::as_one(arr[0])); + } + }; + + } // namespace functional + +}} // namespace boost::numeric + +#endif + diff --git a/win32/include/boost/accumulators/numeric/functional_fwd.hpp b/win32/include/boost/accumulators/numeric/functional_fwd.hpp new file mode 100755 index 000000000..b3de2ba56 --- /dev/null +++ b/win32/include/boost/accumulators/numeric/functional_fwd.hpp @@ -0,0 +1,221 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file functional_fwd.hpp +/// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_NUMERIC_FUNCTIONAL_FWD_HPP_EAN_08_12_2005 +#define BOOST_NUMERIC_FUNCTIONAL_FWD_HPP_EAN_08_12_2005 + +#include +#include +#include +#include +#include + +namespace boost { namespace numeric +{ + // For using directives -- this namespace may be re-opened elsewhere + namespace operators + {} + + namespace op + { + using mpl::_; + using mpl::_1; + using mpl::_2; + } + + namespace functional + { + using namespace operators; + + template + struct tag + { + typedef void type; + }; + + template + struct tag + : tag + {}; + + template + struct tag + : tag + {}; + + template + struct tag + : tag + {}; + + template + struct static_; + + template + struct are_integral; + } + + /// INTERNAL ONLY + /// +#define BOOST_NUMERIC_FUNCTIONAL_DECLARE_UNARY_OP(Name, Op) \ + namespace functional \ + { \ + template \ + struct Name ## _base; \ + template::type> \ + struct Name; \ + } \ + namespace op \ + { \ + struct Name; \ + } \ + namespace \ + { \ + extern op::Name const &Name; \ + } + + /// INTERNAL ONLY + /// +#define BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(Name) \ + namespace functional \ + { \ + template \ + struct result_of_ ## Name; \ + template \ + struct Name ## _base; \ + template< \ + typename Left \ + , typename Right \ + , typename LeftTag = typename tag::type \ + , typename RightTag = typename tag::type \ + > \ + struct Name; \ + } \ + namespace op \ + { \ + struct Name; \ + } \ + namespace \ + { \ + extern op::Name const &Name; \ + } + + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(plus) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(minus) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(multiplies) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(divides) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(modulus) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(greater) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(greater_equal) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(less) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(less_equal) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(equal_to) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(not_equal_to) + + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(assign) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(plus_assign) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(minus_assign) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(multiplies_assign) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(divides_assign) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(modulus_assign) + + BOOST_NUMERIC_FUNCTIONAL_DECLARE_UNARY_OP(unary_plus, +) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_UNARY_OP(unary_minus, -) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_UNARY_OP(complement, ~) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_UNARY_OP(logical_not, !) + +#undef BOOST_NUMERIC_FUNCTIONAL_DECLARE_UNARY_OP +#undef BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP + + + namespace functional + { + template + struct promote_base; + template + struct min_assign_base; + template + struct max_assign_base; + template + struct average_base; + template + struct as_min_base; + template + struct as_max_base; + template + struct as_zero_base; + template + struct as_one_base; + + template::type, typename FromTag = typename tag::type> + struct promote; + template::type, typename RightTag = typename tag::type> + struct min_assign; + template::type, typename RightTag = typename tag::type> + struct max_assign; + template::type, typename RightTag = typename tag::type> + struct average; + template::type> + struct as_min; + template::type> + struct as_max; + template::type> + struct as_zero; + template::type> + struct as_one; + } + + namespace op + { + template + struct promote; + struct min_assign; + struct max_assign; + struct average; + struct as_min; + struct as_max; + struct as_zero; + struct as_one; + } + + namespace + { + extern op::min_assign const &min_assign; + extern op::max_assign const &max_assign; + extern op::average const &average; + extern op::as_min const &as_min; + extern op::as_max const &as_max; + extern op::as_zero const &as_zero; + extern op::as_one const &as_one; + } + + template + typename lazy_disable_if, mpl::if_, To &, To> >::type + promote(From &from); + + template + typename mpl::if_, To const &, To const>::type + promote(From const &from); + + template + struct default_; + + template + struct one; + + template + struct zero; + + template + struct one_or_default; + + template + struct zero_or_default; + +}} // namespace boost::numeric + +#endif diff --git a/win32/include/boost/accumulators/statistics.hpp b/win32/include/boost/accumulators/statistics.hpp new file mode 100755 index 000000000..81bbe6076 --- /dev/null +++ b/win32/include/boost/accumulators/statistics.hpp @@ -0,0 +1,59 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file statistics.hpp +/// Includes all of the Statistical Accumulators Library +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_HPP_EAN_01_17_2006 +#define BOOST_ACCUMULATORS_STATISTICS_HPP_EAN_01_17_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/accumulators/statistics/count.hpp b/win32/include/boost/accumulators/statistics/count.hpp new file mode 100755 index 000000000..40fa7bde2 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/count.hpp @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////////// +// count.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_COUNT_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_COUNT_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + + /////////////////////////////////////////////////////////////////////////////// + // count_impl + struct count_impl + : accumulator_base + { + // for boost::result_of + typedef std::size_t result_type; + + count_impl(dont_care) + : cnt(0) + { + } + + void operator ()(dont_care) + { + ++this->cnt; + } + + result_type result(dont_care) const + { + return this->cnt; + } + + private: + std::size_t cnt; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::count +// +namespace tag +{ + struct count + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef mpl::always impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::count +// +namespace extract +{ + extractor const count = {}; +} + +using extract::count; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/covariance.hpp b/win32/include/boost/accumulators/statistics/covariance.hpp new file mode 100755 index 000000000..f0f66a5ab --- /dev/null +++ b/win32/include/boost/accumulators/statistics/covariance.hpp @@ -0,0 +1,218 @@ +/////////////////////////////////////////////////////////////////////////////// +// covariance.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_COVARIANCE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_COVARIANCE_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace numeric +{ + namespace functional + { + struct std_vector_tag; + + /////////////////////////////////////////////////////////////////////////////// + // functional::outer_product + template + struct outer_product_base + : functional::multiplies + {}; + + template::type, typename RightTag = typename tag::type> + struct outer_product + : outer_product_base + {}; + + template + struct outer_product + : std::binary_function< + Left + , Right + , ublas::matrix< + typename functional::multiplies< + typename Left::value_type + , typename Right::value_type + >::result_type + > + > + { + typedef + ublas::matrix< + typename functional::multiplies< + typename Left::value_type + , typename Right::value_type + >::result_type + > + result_type; + + result_type + operator ()(Left & left, Right & right) const + { + std::size_t left_size = left.size(); + std::size_t right_size = right.size(); + result_type result(left_size, right_size); + for (std::size_t i = 0; i < left_size; ++i) + for (std::size_t j = 0; j < right_size; ++j) + result(i,j) = numeric::multiplies(left[i], right[j]); + return result; + } + }; + } + + namespace op + { + struct outer_product + : boost::detail::function2, functional::tag<_2> > > + {}; + } + + namespace + { + op::outer_product const &outer_product = boost::detail::pod_singleton::instance; + } + +}} + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // covariance_impl + // + /** + @brief Covariance Estimator + + An iterative Monte Carlo estimator for the covariance \f$\mathrm{Cov}(X,X')\f$, where \f$X\f$ is a sample + and \f$X'\f$ is a variate, is given by: + + \f[ + \hat{c}_n = \frac{n-1}{n} \hat{c}_{n-1} + \frac{1}{n-1}(X_n - \hat{\mu}_n)(X_n' - \hat{\mu}_n'),\quad n\ge2,\quad\hat{c}_1 = 0, + \f] + + \f$\hat{\mu}_n\f$ and \f$\hat{\mu}_n'\f$ being the means of the samples and variates. + */ + template + struct covariance_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type sample_type; + typedef typename numeric::functional::average::result_type variate_type; + // for boost::result_of + typedef typename numeric::functional::outer_product::result_type result_type; + + template + covariance_impl(Args const &args) + : cov_( + numeric::outer_product( + numeric::average(args[sample | Sample()], (std::size_t)1) + , numeric::average(args[parameter::keyword::get() | VariateType()], (std::size_t)1) + ) + ) + { + } + + template + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + + if (cnt > 1) + { + extractor > const some_mean_of_variates = {}; + + this->cov_ = this->cov_*(cnt-1.)/cnt + + numeric::outer_product( + some_mean_of_variates(args) - args[parameter::keyword::get()] + , mean(args) - args[sample] + ) / (cnt-1.); + } + } + + result_type result(dont_care) const + { + return this->cov_; + } + + private: + result_type cov_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::covariance +// +namespace tag +{ + template + struct covariance + : depends_on > + { + typedef accumulators::impl::covariance_impl impl; + }; + + struct abstract_covariance + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::covariance +// +namespace extract +{ + extractor const covariance = {}; +} + +using extract::covariance; + +template +struct feature_of > + : feature_of +{ +}; + +// So that covariance can be automatically substituted with +// weighted_covariance when the weight parameter is non-void. +template +struct as_weighted_feature > +{ + typedef tag::weighted_covariance type; +}; + +template +struct feature_of > + : feature_of > +{}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/density.hpp b/win32/include/boost/accumulators/statistics/density.hpp new file mode 100755 index 000000000..ec94372a6 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/density.hpp @@ -0,0 +1,241 @@ + +/////////////////////////////////////////////////////////////////////////////// +// density.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_DENSITY_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_DENSITY_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +/////////////////////////////////////////////////////////////////////////////// +// cache_size and num_bins named parameters +// +BOOST_PARAMETER_NESTED_KEYWORD(tag, density_cache_size, cache_size) +BOOST_PARAMETER_NESTED_KEYWORD(tag, density_num_bins, num_bins) + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // density_impl + // density histogram + /** + @brief Histogram density estimator + + The histogram density estimator returns a histogram of the sample distribution. The positions and sizes of the bins + are determined using a specifiable number of cached samples (cache_size). The range between the minimum and the + maximum of the cached samples is subdivided into a specifiable number of bins (num_bins) of same size. Additionally, + an under- and an overflow bin is added to capture future under- and overflow samples. Once the bins are determined, + the cached samples and all subsequent samples are added to the correct bins. At the end, a range of std::pair is + return, where each pair contains the position of the bin (lower bound) and the samples count (normalized with the + total number of samples). + + @param density_cache_size Number of first samples used to determine min and max. + @param density_num_bins Number of bins (two additional bins collect under- and overflow samples). + */ + template + struct density_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + typedef std::vector > histogram_type; + typedef std::vector array_type; + // for boost::result_of + typedef iterator_range result_type; + + template + density_impl(Args const &args) + : cache_size(args[density_cache_size]) + , cache(cache_size) + , num_bins(args[density_num_bins]) + , samples_in_bin(num_bins + 2, 0.) + , bin_positions(num_bins + 2) + , histogram( + num_bins + 2 + , std::make_pair( + numeric::average(args[sample | Sample()],(std::size_t)1) + , numeric::average(args[sample | Sample()],(std::size_t)1) + ) + ) + , is_dirty(true) + { + } + + template + void operator ()(Args const &args) + { + this->is_dirty = true; + + std::size_t cnt = count(args); + + // Fill up cache with cache_size first samples + if (cnt <= this->cache_size) + { + this->cache[cnt - 1] = args[sample]; + } + + // Once cache_size samples have been accumulated, create num_bins bins of same size between + // the minimum and maximum of the cached samples as well as an under- and and an overflow bin. + // Store their lower bounds (bin_positions) and fill the bins with the cached samples (samples_in_bin). + if (cnt == this->cache_size) + { + float_type minimum = numeric::average((min)(args), (std::size_t)1); + float_type maximum = numeric::average((max)(args), (std::size_t)1); + float_type bin_size = numeric::average(maximum - minimum, this->num_bins ); + + // determine bin positions (their lower bounds) + for (std::size_t i = 0; i < this->num_bins + 2; ++i) + { + this->bin_positions[i] = minimum + (i - 1.) * bin_size; + } + + for (typename array_type::const_iterator iter = this->cache.begin(); iter != this->cache.end(); ++iter) + { + if (*iter < this->bin_positions[1]) + { + ++(this->samples_in_bin[0]); + } + else if (*iter >= this->bin_positions[this->num_bins + 1]) + { + ++(this->samples_in_bin[this->num_bins + 1]); + } + else + { + typename array_type::iterator it = std::upper_bound( + this->bin_positions.begin() + , this->bin_positions.end() + , *iter + ); + + std::size_t d = std::distance(this->bin_positions.begin(), it); + ++(this->samples_in_bin[d - 1]); + } + } + } + // Add each subsequent sample to the correct bin + else if (cnt > this->cache_size) + { + if (args[sample] < this->bin_positions[1]) + { + ++(this->samples_in_bin[0]); + } + else if (args[sample] >= this->bin_positions[this->num_bins + 1]) + { + ++(this->samples_in_bin[this->num_bins + 1]); + } + else + { + typename array_type::iterator it = std::upper_bound( + this->bin_positions.begin() + , this->bin_positions.end() + , args[sample] + ); + + std::size_t d = std::distance(this->bin_positions.begin(), it); + ++(this->samples_in_bin[d - 1]); + } + } + } + + template + result_type result(Args const &args) const + { + if (this->is_dirty) + { + this->is_dirty = false; + + // creates a vector of std::pair where each pair i holds + // the values bin_positions[i] (x-axis of histogram) and + // samples_in_bin[i] / cnt (y-axis of histogram). + + for (std::size_t i = 0; i < this->num_bins + 2; ++i) + { + this->histogram[i] = std::make_pair(this->bin_positions[i], numeric::average(this->samples_in_bin[i], count(args))); + } + } + // returns a range of pairs + return make_iterator_range(this->histogram); + } + + private: + std::size_t cache_size; // number of cached samples + array_type cache; // cache to store the first cache_size samples + std::size_t num_bins; // number of bins + array_type samples_in_bin; // number of samples in each bin + array_type bin_positions; // lower bounds of bins + mutable histogram_type histogram; // histogram + mutable bool is_dirty; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::density +// +namespace tag +{ + struct density + : depends_on + , density_cache_size + , density_num_bins + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::density_impl impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::density::cache_size named parameter + /// tag::density::num_bins named parameter + static boost::parameter::keyword const cache_size; + static boost::parameter::keyword const num_bins; + #endif + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::density +// +namespace extract +{ + extractor const density = {}; +} + +using extract::density; + +// So that density can be automatically substituted +// with weighted_density when the weight parameter is non-void. +template<> +struct as_weighted_feature +{ + typedef tag::weighted_density type; +}; + +template<> +struct feature_of + : feature_of +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/error_of.hpp b/win32/include/boost/accumulators/statistics/error_of.hpp new file mode 100755 index 000000000..05e732d96 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/error_of.hpp @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////// +// error_of.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_ERROR_OF_HPP_EAN_29_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_ERROR_OF_HPP_EAN_29_11_2005 + +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /// INTERNAL ONLY + /// + template + struct this_feature_has_no_error_calculation + : mpl::false_ + { + }; + + /////////////////////////////////////////////////////////////////////////////// + // error_of_impl + /// INTERNAL ONLY + /// + template + struct error_of_impl + : accumulator_base + { + // TODO: specialize this on the specific features that have errors we're + // interested in. + BOOST_MPL_ASSERT((this_feature_has_no_error_calculation)); + + // for boost::result_of + typedef int result_type; + + error_of_impl(dont_care) + { + } + + result_type result(dont_care) const + { + return 0; + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::error_of +// +namespace tag +{ + template + struct error_of + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::error_of_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::error_of +// +namespace extract +{ + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, error_of, (typename)) +} + +using extract::error_of; + +// make tag::error_of work +template +struct as_feature > +{ + typedef tag::error_of::type> type; +}; + +// make error_of work with non-void weights (should become +// error_of +template +struct as_weighted_feature > +{ + typedef tag::error_of::type> type; +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/error_of_mean.hpp b/win32/include/boost/accumulators/statistics/error_of_mean.hpp new file mode 100755 index 000000000..23298d336 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/error_of_mean.hpp @@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////////////////////// +// error_of.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_ERROR_OF_MEAN_HPP_EAN_27_03_2006 +#define BOOST_ACCUMULATORS_STATISTICS_ERROR_OF_MEAN_HPP_EAN_27_03_2006 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // error_of_mean_impl + template + struct error_of_mean_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + error_of_mean_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + using namespace std; + extractor const variance = {}; + return sqrt(numeric::average(variance(args), count(args) - 1)); + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::error_of +// +namespace tag +{ + template<> + struct error_of + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::error_of_mean_impl impl; + }; + + template<> + struct error_of + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::error_of_mean_impl impl; + }; +} + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/extended_p_square.hpp b/win32/include/boost/accumulators/statistics/extended_p_square.hpp new file mode 100755 index 000000000..821d72bca --- /dev/null +++ b/win32/include/boost/accumulators/statistics/extended_p_square.hpp @@ -0,0 +1,291 @@ +/////////////////////////////////////////////////////////////////////////////// +// extended_p_square.hpp +// +// Copyright 2005 Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_EXTENDED_SINGLE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_EXTENDED_SINGLE_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ +/////////////////////////////////////////////////////////////////////////////// +// probabilities named parameter +// +BOOST_PARAMETER_NESTED_KEYWORD(tag, extended_p_square_probabilities, probabilities) + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // extended_p_square_impl + // multiple quantile estimation + /** + @brief Multiple quantile estimation with the extended \f$P^2\f$ algorithm + + Extended \f$P^2\f$ algorithm for estimation of several quantiles without storing samples. + Assume that \f$m\f$ quantiles \f$\xi_{p_1}, \ldots, \xi_{p_m}\f$ are to be estimated. + Instead of storing the whole sample cumulative distribution, the algorithm maintains only + \f$m+2\f$ principal markers and \f$m+1\f$ middle markers, whose positions are updated + with each sample and whose heights are adjusted (if necessary) using a piecewise-parablic + formula. The heights of these central markers are the current estimates of the quantiles + and returned as an iterator range. + + For further details, see + + K. E. E. Raatikainen, Simultaneous estimation of several quantiles, Simulation, Volume 49, + Number 4 (October), 1986, p. 159-164. + + The extended \f$ P^2 \f$ algorithm generalizess the \f$ P^2 \f$ algorithm of + + R. Jain and I. Chlamtac, The P^2 algorithmus for dynamic calculation of quantiles and + histograms without storing observations, Communications of the ACM, + Volume 28 (October), Number 10, 1985, p. 1076-1085. + + @param extended_p_square_probabilities A vector of quantile probabilities. + */ + template + struct extended_p_square_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + typedef std::vector array_type; + // for boost::result_of + typedef iterator_range< + detail::lvalue_index_iterator< + permutation_iterator< + typename array_type::const_iterator + , detail::times2_iterator + > + > + > result_type; + + template + extended_p_square_impl(Args const &args) + : probabilities( + boost::begin(args[extended_p_square_probabilities]) + , boost::end(args[extended_p_square_probabilities]) + ) + , heights(2 * probabilities.size() + 3) + , actual_positions(heights.size()) + , desired_positions(heights.size()) + , positions_increments(heights.size()) + { + std::size_t num_quantiles = this->probabilities.size(); + std::size_t num_markers = this->heights.size(); + + for(std::size_t i = 0; i < num_markers; ++i) + { + this->actual_positions[i] = i + 1; + } + + this->positions_increments[0] = 0.; + this->positions_increments[num_markers - 1] = 1.; + + for(std::size_t i = 0; i < num_quantiles; ++i) + { + this->positions_increments[2 * i + 2] = probabilities[i]; + } + + for(std::size_t i = 0; i <= num_quantiles; ++i) + { + this->positions_increments[2 * i + 1] = + 0.5 * (this->positions_increments[2 * i] + this->positions_increments[2 * i + 2]); + } + + for(std::size_t i = 0; i < num_markers; ++i) + { + this->desired_positions[i] = 1. + 2. * (num_quantiles + 1.) * this->positions_increments[i]; + } + } + + template + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + + // m+2 principal markers and m+1 middle markers + std::size_t num_markers = 2 * this->probabilities.size() + 3; + + // first accumulate num_markers samples + if(cnt <= num_markers) + { + this->heights[cnt - 1] = args[sample]; + + // complete the initialization of heights by sorting + if(cnt == num_markers) + { + std::sort(this->heights.begin(), this->heights.end()); + } + } + else + { + std::size_t sample_cell = 1; + + // find cell k = sample_cell such that heights[k-1] <= sample < heights[k] + if(args[sample] < this->heights[0]) + { + this->heights[0] = args[sample]; + sample_cell = 1; + } + else if(args[sample] >= this->heights[num_markers - 1]) + { + this->heights[num_markers - 1] = args[sample]; + sample_cell = num_markers - 1; + } + else + { + typedef typename array_type::iterator iterator; + iterator it = std::upper_bound( + this->heights.begin() + , this->heights.end() + , args[sample] + ); + + sample_cell = std::distance(this->heights.begin(), it); + } + + // update actual positions of all markers above sample_cell index + for(std::size_t i = sample_cell; i < num_markers; ++i) + { + ++this->actual_positions[i]; + } + + // update desired positions of all markers + for(std::size_t i = 0; i < num_markers; ++i) + { + this->desired_positions[i] += this->positions_increments[i]; + } + + // adjust heights and actual positions of markers 1 to num_markers-2 if necessary + for(std::size_t i = 1; i <= num_markers - 2; ++i) + { + // offset to desired position + float_type d = this->desired_positions[i] - this->actual_positions[i]; + + // offset to next position + float_type dp = this->actual_positions[i+1] - this->actual_positions[i]; + + // offset to previous position + float_type dm = this->actual_positions[i-1] - this->actual_positions[i]; + + // height ds + float_type hp = (this->heights[i+1] - this->heights[i]) / dp; + float_type hm = (this->heights[i-1] - this->heights[i]) / dm; + + if((d >= 1 && dp > 1) || (d <= -1 && dm < -1)) + { + short sign_d = static_cast(d / std::abs(d)); + + float_type h = this->heights[i] + sign_d / (dp - dm) * ((sign_d - dm)*hp + + (dp - sign_d) * hm); + + // try adjusting heights[i] using p-squared formula + if(this->heights[i - 1] < h && h < this->heights[i + 1]) + { + this->heights[i] = h; + } + else + { + // use linear formula + if(d > 0) + { + this->heights[i] += hp; + } + if(d < 0) + { + this->heights[i] -= hm; + } + } + this->actual_positions[i] += sign_d; + } + } + } + } + + result_type result(dont_care) const + { + // for i in [1,probabilities.size()], return heights[i * 2] + detail::times2_iterator idx_begin = detail::make_times2_iterator(1); + detail::times2_iterator idx_end = detail::make_times2_iterator(this->probabilities.size() + 1); + + return result_type( + make_permutation_iterator(this->heights.begin(), idx_begin) + , make_permutation_iterator(this->heights.begin(), idx_end) + ); + } + + private: + array_type probabilities; // the quantile probabilities + array_type heights; // q_i + array_type actual_positions; // n_i + array_type desired_positions; // d_i + array_type positions_increments; // f_i + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::extended_p_square +// +namespace tag +{ + struct extended_p_square + : depends_on + , extended_p_square_probabilities + { + typedef accumulators::impl::extended_p_square_impl impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::extended_p_square::probabilities named paramter + static boost::parameter::keyword const probabilities; + #endif + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::extended_p_square +// +namespace extract +{ + extractor const extended_p_square = {}; +} + +using extract::extended_p_square; + +// So that extended_p_square can be automatically substituted with +// weighted_extended_p_square when the weight parameter is non-void +template<> +struct as_weighted_feature +{ + typedef tag::weighted_extended_p_square type; +}; + +template<> +struct feature_of + : feature_of +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/extended_p_square_quantile.hpp b/win32/include/boost/accumulators/statistics/extended_p_square_quantile.hpp new file mode 100755 index 000000000..72053a344 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/extended_p_square_quantile.hpp @@ -0,0 +1,314 @@ +/////////////////////////////////////////////////////////////////////////////// +// extended_p_square_quantile.hpp +// +// Copyright 2005 Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_EXTENDED_SINGLE_QUANTILE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_EXTENDED_SINGLE_QUANTILE_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // extended_p_square_quantile_impl + // single quantile estimation + /** + @brief Quantile estimation using the extended \f$P^2\f$ algorithm for weighted and unweighted samples + + Uses the quantile estimates calculated by the extended \f$P^2\f$ algorithm to compute + intermediate quantile estimates by means of quadratic interpolation. + + @param quantile_probability The probability of the quantile to be estimated. + */ + template // Impl1: weighted/unweighted // Impl2: linear/quadratic + struct extended_p_square_quantile_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + typedef std::vector array_type; + typedef iterator_range< + detail::lvalue_index_iterator< + permutation_iterator< + typename array_type::const_iterator + , detail::times2_iterator + > + > + > range_type; + // for boost::result_of + typedef float_type result_type; + + template + extended_p_square_quantile_impl(Args const &args) + : probabilities( + boost::begin(args[extended_p_square_probabilities]) + , boost::end(args[extended_p_square_probabilities]) + ) + { + } + + template + result_type result(Args const &args) const + { + typedef + typename mpl::if_< + is_same + , tag::weighted_extended_p_square + , tag::extended_p_square + >::type + extended_p_square_tag; + + extractor const some_extended_p_square = {}; + + array_type heights(some_extended_p_square(args).size()); + std::copy(some_extended_p_square(args).begin(), some_extended_p_square(args).end(), heights.begin()); + + this->probability = args[quantile_probability]; + + typename array_type::const_iterator iter_probs = std::lower_bound(this->probabilities.begin(), this->probabilities.end(), this->probability); + std::size_t dist = std::distance(this->probabilities.begin(), iter_probs); + typename array_type::const_iterator iter_heights = heights.begin() + dist; + + // If this->probability is not in a valid range return NaN or throw exception + if (this->probability < *this->probabilities.begin() || this->probability > *(this->probabilities.end() - 1)) + { + if (std::numeric_limits::has_quiet_NaN) + { + return std::numeric_limits::quiet_NaN(); + } + else + { + std::ostringstream msg; + msg << "probability = " << this->probability << " is not in valid range ("; + msg << *this->probabilities.begin() << ", " << *(this->probabilities.end() - 1) << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + return Sample(0); + } + + } + + if (*iter_probs == this->probability) + { + return heights[dist]; + } + else + { + result_type result; + + if (is_same::value) + { + ///////////////////////////////////////////////////////////////////////////////// + // LINEAR INTERPOLATION + // + float_type p1 = *iter_probs; + float_type p0 = *(iter_probs - 1); + float_type h1 = *iter_heights; + float_type h0 = *(iter_heights - 1); + + float_type a = numeric::average(h1 - h0, p1 - p0); + float_type b = h1 - p1 * a; + + result = a * this->probability + b; + } + else + { + ///////////////////////////////////////////////////////////////////////////////// + // QUADRATIC INTERPOLATION + // + float_type p0, p1, p2; + float_type h0, h1, h2; + + if ( (dist == 1 || *iter_probs - this->probability <= this->probability - *(iter_probs - 1) ) && dist != this->probabilities.size() - 1 ) + { + p0 = *(iter_probs - 1); + p1 = *iter_probs; + p2 = *(iter_probs + 1); + h0 = *(iter_heights - 1); + h1 = *iter_heights; + h2 = *(iter_heights + 1); + } + else + { + p0 = *(iter_probs - 2); + p1 = *(iter_probs - 1); + p2 = *iter_probs; + h0 = *(iter_heights - 2); + h1 = *(iter_heights - 1); + h2 = *iter_heights; + } + + float_type hp21 = numeric::average(h2 - h1, p2 - p1); + float_type hp10 = numeric::average(h1 - h0, p1 - p0); + float_type p21 = numeric::average(p2 * p2 - p1 * p1, p2 - p1); + float_type p10 = numeric::average(p1 * p1 - p0 * p0, p1 - p0); + + float_type a = numeric::average(hp21 - hp10, p21 - p10); + float_type b = hp21 - a * p21; + float_type c = h2 - a * p2 * p2 - b * p2; + + result = a * this->probability * this-> probability + b * this->probability + c; + } + + return result; + } + + } + private: + + array_type probabilities; + mutable float_type probability; + + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::extended_p_square_quantile +// +namespace tag +{ + struct extended_p_square_quantile + : depends_on + { + typedef accumulators::impl::extended_p_square_quantile_impl impl; + }; + struct extended_p_square_quantile_quadratic + : depends_on + { + typedef accumulators::impl::extended_p_square_quantile_impl impl; + }; + struct weighted_extended_p_square_quantile + : depends_on + { + typedef accumulators::impl::extended_p_square_quantile_impl impl; + }; + struct weighted_extended_p_square_quantile_quadratic + : depends_on + { + typedef accumulators::impl::extended_p_square_quantile_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::extended_p_square_quantile +// extract::weighted_extended_p_square_quantile +// +namespace extract +{ + extractor const extended_p_square_quantile = {}; + extractor const extended_p_square_quantile_quadratic = {}; + extractor const weighted_extended_p_square_quantile = {}; + extractor const weighted_extended_p_square_quantile_quadratic = {}; +} + +using extract::extended_p_square_quantile; +using extract::extended_p_square_quantile_quadratic; +using extract::weighted_extended_p_square_quantile; +using extract::weighted_extended_p_square_quantile_quadratic; + +// extended_p_square_quantile(linear) -> extended_p_square_quantile +template<> +struct as_feature +{ + typedef tag::extended_p_square_quantile type; +}; + +// extended_p_square_quantile(quadratic) -> extended_p_square_quantile_quadratic +template<> +struct as_feature +{ + typedef tag::extended_p_square_quantile_quadratic type; +}; + +// weighted_extended_p_square_quantile(linear) -> weighted_extended_p_square_quantile +template<> +struct as_feature +{ + typedef tag::weighted_extended_p_square_quantile type; +}; + +// weighted_extended_p_square_quantile(quadratic) -> weighted_extended_p_square_quantile_quadratic +template<> +struct as_feature +{ + typedef tag::weighted_extended_p_square_quantile_quadratic type; +}; + +// for the purposes of feature-based dependency resolution, +// extended_p_square_quantile and weighted_extended_p_square_quantile +// provide the same feature as quantile +template<> +struct feature_of + : feature_of +{ +}; +template<> +struct feature_of + : feature_of +{ +}; +// So that extended_p_square_quantile can be automatically substituted with +// weighted_extended_p_square_quantile when the weight parameter is non-void +template<> +struct as_weighted_feature +{ + typedef tag::weighted_extended_p_square_quantile type; +}; + +template<> +struct feature_of + : feature_of +{ +}; + +// So that extended_p_square_quantile_quadratic can be automatically substituted with +// weighted_extended_p_square_quantile_quadratic when the weight parameter is non-void +template<> +struct as_weighted_feature +{ + typedef tag::weighted_extended_p_square_quantile_quadratic type; +}; +template<> +struct feature_of + : feature_of +{ +}; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif diff --git a/win32/include/boost/accumulators/statistics/kurtosis.hpp b/win32/include/boost/accumulators/statistics/kurtosis.hpp new file mode 100755 index 000000000..21fdc456b --- /dev/null +++ b/win32/include/boost/accumulators/statistics/kurtosis.hpp @@ -0,0 +1,110 @@ +/////////////////////////////////////////////////////////////////////////////// +// kurtosis.hpp +// +// Copyright 2006 Olivier Gygi, Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_KURTOSIS_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_KURTOSIS_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // kurtosis_impl + /** + @brief Kurtosis estimation + + The kurtosis of a sample distribution is defined as the ratio of the 4th central moment and the square of the 2nd central + moment (the variance) of the samples, minus 3. The term \f$ -3 \f$ is added in order to ensure that the normal distribution + has zero kurtosis. The kurtosis can also be expressed by the simple moments: + + \f[ + \hat{g}_2 = + \frac + {\widehat{m}_n^{(4)}-4\widehat{m}_n^{(3)}\hat{\mu}_n+6\widehat{m}_n^{(2)}\hat{\mu}_n^2-3\hat{\mu}_n^4} + {\left(\widehat{m}_n^{(2)} - \hat{\mu}_n^{2}\right)^2} - 3, + \f] + + where \f$ \widehat{m}_n^{(i)} \f$ are the \f$ i \f$-th moment and \f$ \hat{\mu}_n \f$ the mean (first moment) of the + \f$ n \f$ samples. + */ + template + struct kurtosis_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + kurtosis_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + return numeric::average( + moment<4>(args) + - 4. * moment<3>(args) * mean(args) + + 6. * moment<2>(args) * mean(args) * mean(args) + - 3. * mean(args) * mean(args) * mean(args) * mean(args) + , ( moment<2>(args) - mean(args) * mean(args) ) + * ( moment<2>(args) - mean(args) * mean(args) ) + ) - 3.; + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::kurtosis +// +namespace tag +{ + struct kurtosis + : depends_on, moment<3>, moment<4> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::kurtosis_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::kurtosis +// +namespace extract +{ + extractor const kurtosis = {}; +} + +using extract::kurtosis; + +// So that kurtosis can be automatically substituted with +// weighted_kurtosis when the weight parameter is non-void +template<> +struct as_weighted_feature +{ + typedef tag::weighted_kurtosis type; +}; + +template<> +struct feature_of + : feature_of +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/max.hpp b/win32/include/boost/accumulators/statistics/max.hpp new file mode 100755 index 000000000..5763405f7 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/max.hpp @@ -0,0 +1,83 @@ +/////////////////////////////////////////////////////////////////////////////// +// max.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_MAX_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_MAX_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // max_impl + template + struct max_impl + : accumulator_base + { + // for boost::result_of + typedef Sample result_type; + + template + max_impl(Args const &args) + : max_(numeric::as_min(args[sample | Sample()])) + { + } + + template + void operator ()(Args const &args) + { + numeric::max_assign(this->max_, args[sample]); + } + + result_type result(dont_care) const + { + return this->max_; + } + + private: + Sample max_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::max +// +namespace tag +{ + struct max + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::max_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::max +// +namespace extract +{ + extractor const max = {}; +} + +using extract::max; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/mean.hpp b/win32/include/boost/accumulators/statistics/mean.hpp new file mode 100755 index 000000000..997b61edf --- /dev/null +++ b/win32/include/boost/accumulators/statistics/mean.hpp @@ -0,0 +1,295 @@ +/////////////////////////////////////////////////////////////////////////////// +// mean.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_MEAN_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_MEAN_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // mean_impl + // lazy, by default + template + struct mean_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + mean_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + extractor sum; + return numeric::average(sum(args), count(args)); + } + }; + + template + struct immediate_mean_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + template + immediate_mean_impl(Args const &args) + : mean(numeric::average(args[sample | Sample()], numeric::one::value)) + { + } + + template + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + this->mean = numeric::average( + (this->mean * (cnt - 1)) + args[parameter::keyword::get()] + , cnt + ); + } + + result_type result(dont_care) const + { + return this->mean; + } + + private: + result_type mean; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::mean +// tag::immediate_mean +// tag::mean_of_weights +// tag::immediate_mean_of_weights +// tag::mean_of_variates +// tag::immediate_mean_of_variates +// +namespace tag +{ + struct mean + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::mean_impl impl; + }; + struct immediate_mean + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::immediate_mean_impl impl; + }; + struct mean_of_weights + : depends_on + { + typedef mpl::true_ is_weight_accumulator; + /// INTERNAL ONLY + /// + typedef accumulators::impl::mean_impl impl; + }; + struct immediate_mean_of_weights + : depends_on + { + typedef mpl::true_ is_weight_accumulator; + /// INTERNAL ONLY + /// + typedef accumulators::impl::immediate_mean_impl impl; + }; + template + struct mean_of_variates + : depends_on > + { + /// INTERNAL ONLY + /// + typedef mpl::always > > impl; + }; + template + struct immediate_mean_of_variates + : depends_on + { + /// INTERNAL ONLY + /// + typedef mpl::always > impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::mean +// extract::mean_of_weights +// extract::mean_of_variates +// +namespace extract +{ + extractor const mean = {}; + extractor const mean_of_weights = {}; + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, mean_of_variates, (typename)(typename)) +} + +using extract::mean; +using extract::mean_of_weights; +using extract::mean_of_variates; + +// mean(lazy) -> mean +template<> +struct as_feature +{ + typedef tag::mean type; +}; + +// mean(immediate) -> immediate_mean +template<> +struct as_feature +{ + typedef tag::immediate_mean type; +}; + +// mean_of_weights(lazy) -> mean_of_weights +template<> +struct as_feature +{ + typedef tag::mean_of_weights type; +}; + +// mean_of_weights(immediate) -> immediate_mean_of_weights +template<> +struct as_feature +{ + typedef tag::immediate_mean_of_weights type; +}; + +// mean_of_variates(lazy) -> mean_of_variates +template +struct as_feature(lazy)> +{ + typedef tag::mean_of_variates type; +}; + +// mean_of_variates(immediate) -> immediate_mean_of_variates +template +struct as_feature(immediate)> +{ + typedef tag::immediate_mean_of_variates type; +}; + +// for the purposes of feature-based dependency resolution, +// immediate_mean provides the same feature as mean +template<> +struct feature_of + : feature_of +{ +}; + +// for the purposes of feature-based dependency resolution, +// immediate_mean provides the same feature as mean +template<> +struct feature_of + : feature_of +{ +}; + +// for the purposes of feature-based dependency resolution, +// immediate_mean provides the same feature as mean +template +struct feature_of > + : feature_of > +{ +}; + +// So that mean can be automatically substituted with +// weighted_mean when the weight parameter is non-void. +template<> +struct as_weighted_feature +{ + typedef tag::weighted_mean type; +}; + +template<> +struct feature_of + : feature_of +{}; + +// So that immediate_mean can be automatically substituted with +// immediate_weighted_mean when the weight parameter is non-void. +template<> +struct as_weighted_feature +{ + typedef tag::immediate_weighted_mean type; +}; + +template<> +struct feature_of + : feature_of +{}; + +// So that mean_of_weights<> can be automatically substituted with +// weighted_mean_of_variates<> when the weight parameter is non-void. +template +struct as_weighted_feature > +{ + typedef tag::weighted_mean_of_variates type; +}; + +template +struct feature_of > + : feature_of > +{ +}; + +// So that immediate_mean_of_weights<> can be automatically substituted with +// immediate_weighted_mean_of_variates<> when the weight parameter is non-void. +template +struct as_weighted_feature > +{ + typedef tag::immediate_weighted_mean_of_variates type; +}; + +template +struct feature_of > + : feature_of > +{ +}; + +//////////////////////////////////////////////////////////////////////////// +//// droppable_accumulator +//// need to specialize droppable lazy mean to cache the result at the +//// point the accumulator is dropped. +///// INTERNAL ONLY +///// +//template +//struct droppable_accumulator > +// : droppable_accumulator_base< +// with_cached_result > +// > +//{ +// template +// droppable_accumulator(Args const &args) +// : droppable_accumulator::base(args) +// { +// } +//}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/median.hpp b/win32/include/boost/accumulators/statistics/median.hpp new file mode 100755 index 000000000..dd52b687d --- /dev/null +++ b/win32/include/boost/accumulators/statistics/median.hpp @@ -0,0 +1,297 @@ +/////////////////////////////////////////////////////////////////////////////// +// median.hpp +// +// Copyright 2006 Eric Niebler, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_MEDIAN_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_MEDIAN_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // median_impl + // + /** + @brief Median estimation based on the \f$P^2\f$ quantile estimator + + The \f$P^2\f$ algorithm is invoked with a quantile probability of 0.5. + */ + template + struct median_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + median_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + return p_square_quantile_for_median(args); + } + }; + /////////////////////////////////////////////////////////////////////////////// + // with_density_median_impl + // + /** + @brief Median estimation based on the density estimator + + The algorithm determines the bin in which the \f$0.5*cnt\f$-th sample lies, \f$cnt\f$ being + the total number of samples. It returns the approximate horizontal position of this sample, + based on a linear interpolation inside the bin. + */ + template + struct with_density_median_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + typedef std::vector > histogram_type; + typedef iterator_range range_type; + // for boost::result_of + typedef float_type result_type; + + template + with_density_median_impl(Args const &args) + : sum(numeric::average(args[sample | Sample()], (std::size_t)1)) + , is_dirty(true) + { + } + + void operator ()(dont_care) + { + this->is_dirty = true; + } + + + template + result_type result(Args const &args) const + { + if (this->is_dirty) + { + this->is_dirty = false; + + std::size_t cnt = count(args); + range_type histogram = density(args); + typename range_type::iterator it = histogram.begin(); + while (this->sum < 0.5 * cnt) + { + this->sum += it->second * cnt; + ++it; + } + --it; + float_type over = numeric::average(this->sum - 0.5 * cnt, it->second * cnt); + this->median = it->first * over + (it + 1)->first * (1. - over); + } + + return this->median; + } + + private: + mutable float_type sum; + mutable bool is_dirty; + mutable float_type median; + }; + + /////////////////////////////////////////////////////////////////////////////// + // with_p_square_cumulative_distribution_median_impl + // + /** + @brief Median estimation based on the \f$P^2\f$ cumulative distribution estimator + + The algorithm determines the first (leftmost) bin with a height exceeding 0.5. It + returns the approximate horizontal position of where the cumulative distribution + equals 0.5, based on a linear interpolation inside the bin. + */ + template + struct with_p_square_cumulative_distribution_median_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + typedef std::vector > histogram_type; + typedef iterator_range range_type; + // for boost::result_of + typedef float_type result_type; + + with_p_square_cumulative_distribution_median_impl(dont_care) + : is_dirty(true) + { + } + + void operator ()(dont_care) + { + this->is_dirty = true; + } + + template + result_type result(Args const &args) const + { + if (this->is_dirty) + { + this->is_dirty = false; + + range_type histogram = p_square_cumulative_distribution(args); + typename range_type::iterator it = histogram.begin(); + while (it->second < 0.5) + { + ++it; + } + float_type over = numeric::average(it->second - 0.5, it->second - (it - 1)->second); + this->median = it->first * over + (it + 1)->first * ( 1. - over ); + } + + return this->median; + } + private: + + mutable bool is_dirty; + mutable float_type median; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::median +// tag::with_densisty_median +// tag::with_p_square_cumulative_distribution_median +// +namespace tag +{ + struct median + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::median_impl impl; + }; + struct with_density_median + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::with_density_median_impl impl; + }; + struct with_p_square_cumulative_distribution_median + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::with_p_square_cumulative_distribution_median_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::median +// extract::with_density_median +// extract::with_p_square_cumulative_distribution_median +// +namespace extract +{ + extractor const median = {}; + extractor const with_density_median = {}; + extractor const with_p_square_cumulative_distribution_median = {}; +} + +using extract::median; +using extract::with_density_median; +using extract::with_p_square_cumulative_distribution_median; + +// median(with_p_square_quantile) -> median +template<> +struct as_feature +{ + typedef tag::median type; +}; + +// median(with_density) -> with_density_median +template<> +struct as_feature +{ + typedef tag::with_density_median type; +}; + +// median(with_p_square_cumulative_distribution) -> with_p_square_cumulative_distribution_median +template<> +struct as_feature +{ + typedef tag::with_p_square_cumulative_distribution_median type; +}; + +// for the purposes of feature-based dependency resolution, +// with_density_median and with_p_square_cumulative_distribution_median +// provide the same feature as median +template<> +struct feature_of + : feature_of +{ +}; + +template<> +struct feature_of + : feature_of +{ +}; + +// So that median can be automatically substituted with +// weighted_median when the weight parameter is non-void. +template<> +struct as_weighted_feature +{ + typedef tag::weighted_median type; +}; + +template<> +struct feature_of + : feature_of +{ +}; + +// So that with_density_median can be automatically substituted with +// with_density_weighted_median when the weight parameter is non-void. +template<> +struct as_weighted_feature +{ + typedef tag::with_density_weighted_median type; +}; + +template<> +struct feature_of + : feature_of +{ +}; + +// So that with_p_square_cumulative_distribution_median can be automatically substituted with +// with_p_square_cumulative_distribution_weighted_median when the weight parameter is non-void. +template<> +struct as_weighted_feature +{ + typedef tag::with_p_square_cumulative_distribution_weighted_median type; +}; + +template<> +struct feature_of + : feature_of +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/min.hpp b/win32/include/boost/accumulators/statistics/min.hpp new file mode 100755 index 000000000..800c36403 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/min.hpp @@ -0,0 +1,83 @@ +/////////////////////////////////////////////////////////////////////////////// +// min.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_MIN_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_MIN_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // min_impl + template + struct min_impl + : accumulator_base + { + // for boost::result_of + typedef Sample result_type; + + template + min_impl(Args const &args) + : min_(numeric::as_max(args[sample | Sample()])) + { + } + + template + void operator ()(Args const &args) + { + numeric::min_assign(this->min_, args[sample]); + } + + result_type result(dont_care) const + { + return this->min_; + } + + private: + Sample min_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::min +// +namespace tag +{ + struct min + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::min_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::min +// +namespace extract +{ + extractor const min = {}; +} + +using extract::min; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/moment.hpp b/win32/include/boost/accumulators/statistics/moment.hpp new file mode 100755 index 000000000..6c1a83035 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/moment.hpp @@ -0,0 +1,125 @@ +/////////////////////////////////////////////////////////////////////////////// +// moment.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_MOMENT_HPP_EAN_15_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_MOMENT_HPP_EAN_15_11_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace numeric +{ + /// INTERNAL ONLY + /// + template + T const &pow(T const &x, mpl::int_<1>) + { + return x; + } + + /// INTERNAL ONLY + /// + template + T pow(T const &x, mpl::int_) + { + using namespace operators; + T y = numeric::pow(x, mpl::int_()); + T z = y * y; + return (N % 2) ? (z * x) : z; + } +}} + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // moment_impl + template + struct moment_impl + : accumulator_base // TODO: also depends_on sum of powers + { + BOOST_MPL_ASSERT_RELATION(N::value, >, 0); + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + template + moment_impl(Args const &args) + : sum(args[sample | Sample()]) + { + } + + template + void operator ()(Args const &args) + { + this->sum += numeric::pow(args[sample], N()); + } + + template + result_type result(Args const &args) const + { + return numeric::average(this->sum, count(args)); + } + + private: + Sample sum; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::moment +// +namespace tag +{ + template + struct moment + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::moment_impl, mpl::_1> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::moment +// +namespace extract +{ + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, moment, (int)) +} + +using extract::moment; + +// So that moment can be automatically substituted with +// weighted_moment when the weight parameter is non-void +template +struct as_weighted_feature > +{ + typedef tag::weighted_moment type; +}; + +template +struct feature_of > + : feature_of > +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/p_square_cumulative_distribution.hpp b/win32/include/boost/accumulators/statistics/p_square_cumulative_distribution.hpp new file mode 100755 index 000000000..20b7aa488 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/p_square_cumulative_distribution.hpp @@ -0,0 +1,258 @@ +/////////////////////////////////////////////////////////////////////////////// +// p_square_cumulative_distribution.hpp +// +// Copyright 2005 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ +/////////////////////////////////////////////////////////////////////////////// +// num_cells named parameter +// +BOOST_PARAMETER_NESTED_KEYWORD(tag, p_square_cumulative_distribution_num_cells, num_cells) + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // p_square_cumulative_distribution_impl + // cumulative_distribution calculation (as histogram) + /** + @brief Histogram calculation of the cumulative distribution with the \f$P^2\f$ algorithm + + A histogram of the sample cumulative distribution is computed dynamically without storing samples + based on the \f$ P^2 \f$ algorithm. The returned histogram has a specifiable amount (num_cells) + equiprobable (and not equal-sized) cells. + + For further details, see + + R. Jain and I. Chlamtac, The P^2 algorithmus for dynamic calculation of quantiles and + histograms without storing observations, Communications of the ACM, + Volume 28 (October), Number 10, 1985, p. 1076-1085. + + @param p_square_cumulative_distribution_num_cells. + */ + template + struct p_square_cumulative_distribution_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + typedef std::vector array_type; + typedef std::vector > histogram_type; + // for boost::result_of + typedef iterator_range result_type; + + template + p_square_cumulative_distribution_impl(Args const &args) + : num_cells(args[p_square_cumulative_distribution_num_cells]) + , heights(num_cells + 1) + , actual_positions(num_cells + 1) + , desired_positions(num_cells + 1) + , positions_increments(num_cells + 1) + , histogram(num_cells + 1) + , is_dirty(true) + { + std::size_t b = this->num_cells; + + for (std::size_t i = 0; i < b + 1; ++i) + { + this->actual_positions[i] = i + 1.; + this->desired_positions[i] = i + 1.; + this->positions_increments[i] = numeric::average(i, b); + } + } + + template + void operator ()(Args const &args) + { + this->is_dirty = true; + + std::size_t cnt = count(args); + std::size_t sample_cell = 1; // k + std::size_t b = this->num_cells; + + // accumulate num_cells + 1 first samples + if (cnt <= b + 1) + { + this->heights[cnt - 1] = args[sample]; + + // complete the initialization of heights by sorting + if (cnt == b + 1) + { + std::sort(this->heights.begin(), this->heights.end()); + } + } + else + { + // find cell k such that heights[k-1] <= args[sample] < heights[k] and adjust extreme values + if (args[sample] < this->heights[0]) + { + this->heights[0] = args[sample]; + sample_cell = 1; + } + else if (this->heights[b] <= args[sample]) + { + this->heights[b] = args[sample]; + sample_cell = b; + } + else + { + typename array_type::iterator it; + it = std::upper_bound( + this->heights.begin() + , this->heights.end() + , args[sample] + ); + + sample_cell = std::distance(this->heights.begin(), it); + } + + // increment positions of markers above sample_cell + for (std::size_t i = sample_cell; i < b + 1; ++i) + { + ++this->actual_positions[i]; + } + + // update desired position of markers 2 to num_cells + 1 + // (desired position of first marker is always 1) + for (std::size_t i = 1; i < b + 1; ++i) + { + this->desired_positions[i] += this->positions_increments[i]; + } + + // adjust heights of markers 2 to num_cells if necessary + for (std::size_t i = 1; i < b; ++i) + { + // offset to desire position + float_type d = this->desired_positions[i] - this->actual_positions[i]; + + // offset to next position + float_type dp = this->actual_positions[i + 1] - this->actual_positions[i]; + + // offset to previous position + float_type dm = this->actual_positions[i - 1] - this->actual_positions[i]; + + // height ds + float_type hp = (this->heights[i + 1] - this->heights[i]) / dp; + float_type hm = (this->heights[i - 1] - this->heights[i]) / dm; + + if ( ( d >= 1. && dp > 1. ) || ( d <= -1. && dm < -1. ) ) + { + short sign_d = static_cast(d / std::abs(d)); + + // try adjusting heights[i] using p-squared formula + float_type h = this->heights[i] + sign_d / (dp - dm) * ( (sign_d - dm) * hp + (dp - sign_d) * hm ); + + if ( this->heights[i - 1] < h && h < this->heights[i + 1] ) + { + this->heights[i] = h; + } + else + { + // use linear formula + if (d>0) + { + this->heights[i] += hp; + } + if (d<0) + { + this->heights[i] -= hm; + } + } + this->actual_positions[i] += sign_d; + } + } + } + } + + template + result_type result(Args const &args) const + { + if (this->is_dirty) + { + this->is_dirty = false; + + // creates a vector of std::pair where each pair i holds + // the values heights[i] (x-axis of histogram) and + // actual_positions[i] / cnt (y-axis of histogram) + + std::size_t cnt = count(args); + + for (std::size_t i = 0; i < this->histogram.size(); ++i) + { + this->histogram[i] = std::make_pair(this->heights[i], numeric::average(this->actual_positions[i], cnt)); + } + } + //return histogram; + return make_iterator_range(this->histogram); + } + + private: + std::size_t num_cells; // number of cells b + array_type heights; // q_i + array_type actual_positions; // n_i + array_type desired_positions; // n'_i + array_type positions_increments; // dn'_i + mutable histogram_type histogram; // histogram + mutable bool is_dirty; + }; + +} // namespace detail + +/////////////////////////////////////////////////////////////////////////////// +// tag::p_square_cumulative_distribution +// +namespace tag +{ + struct p_square_cumulative_distribution + : depends_on + , p_square_cumulative_distribution_num_cells + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::p_square_cumulative_distribution_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::p_square_cumulative_distribution +// +namespace extract +{ + extractor const p_square_cumulative_distribution = {}; +} + +using extract::p_square_cumulative_distribution; + +// So that p_square_cumulative_distribution can be automatically substituted with +// weighted_p_square_cumulative_distribution when the weight parameter is non-void +template<> +struct as_weighted_feature +{ + typedef tag::weighted_p_square_cumulative_distribution type; +}; + +template<> +struct feature_of + : feature_of +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/p_square_quantile.hpp b/win32/include/boost/accumulators/statistics/p_square_quantile.hpp new file mode 100755 index 000000000..1f24f3633 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/p_square_quantile.hpp @@ -0,0 +1,253 @@ +/////////////////////////////////////////////////////////////////////////////// +// p_square_quantile.hpp +// +// Copyright 2005 Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_QUANTILE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_QUANTILE_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // p_square_quantile_impl + // single quantile estimation + /** + @brief Single quantile estimation with the \f$P^2\f$ algorithm + + The \f$P^2\f$ algorithm estimates a quantile dynamically without storing samples. Instead of + storing the whole sample cumulative distribution, only five points (markers) are stored. The heights + of these markers are the minimum and the maximum of the samples and the current estimates of the + \f$(p/2)\f$-, \f$p\f$- and \f$(1+p)/2\f$-quantiles. Their positions are equal to the number + of samples that are smaller or equal to the markers. Each time a new samples is recorded, the + positions of the markers are updated and if necessary their heights are adjusted using a piecewise- + parabolic formula. + + For further details, see + + R. Jain and I. Chlamtac, The P^2 algorithmus fordynamic calculation of quantiles and + histograms without storing observations, Communications of the ACM, + Volume 28 (October), Number 10, 1985, p. 1076-1085. + + @param quantile_probability + */ + template + struct p_square_quantile_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + typedef array array_type; + // for boost::result_of + typedef float_type result_type; + + template + p_square_quantile_impl(Args const &args) + : p(is_same::value ? 0.5 : args[quantile_probability | 0.5]) + , heights() + , actual_positions() + , desired_positions() + , positions_increments() + { + for(std::size_t i = 0; i < 5; ++i) + { + this->actual_positions[i] = i + 1; + } + + this->desired_positions[0] = 1.; + this->desired_positions[1] = 1. + 2. * this->p; + this->desired_positions[2] = 1. + 4. * this->p; + this->desired_positions[3] = 3. + 2. * this->p; + this->desired_positions[4] = 5.; + + this->positions_increments[0] = 0.; + this->positions_increments[1] = this->p / 2.; + this->positions_increments[2] = this->p; + this->positions_increments[3] = (1. + this->p) / 2.; + this->positions_increments[4] = 1.; + } + + template + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + + // accumulate 5 first samples + if(cnt <= 5) + { + this->heights[cnt - 1] = args[sample]; + + // complete the initialization of heights by sorting + if(cnt == 5) + { + std::sort(this->heights.begin(), this->heights.end()); + } + } + else + { + std::size_t sample_cell = 1; // k + + // find cell k such that heights[k-1] <= args[sample] < heights[k] and ajust extreme values + if (args[sample] < this->heights[0]) + { + this->heights[0] = args[sample]; + sample_cell = 1; + } + else if (this->heights[4] <= args[sample]) + { + this->heights[4] = args[sample]; + sample_cell = 4; + } + else + { + typedef typename array_type::iterator iterator; + iterator it = std::upper_bound( + this->heights.begin() + , this->heights.end() + , args[sample] + ); + + sample_cell = std::distance(this->heights.begin(), it); + } + + // update positions of markers above sample_cell + for(std::size_t i = sample_cell; i < 5; ++i) + { + ++this->actual_positions[i]; + } + + // update desired positions of all markers + for(std::size_t i = 0; i < 5; ++i) + { + this->desired_positions[i] += this->positions_increments[i]; + } + + // adjust heights and actual positions of markers 1 to 3 if necessary + for(std::size_t i = 1; i <= 3; ++i) + { + // offset to desired positions + float_type d = this->desired_positions[i] - this->actual_positions[i]; + + // offset to next position + float_type dp = this->actual_positions[i + 1] - this->actual_positions[i]; + + // offset to previous position + float_type dm = this->actual_positions[i - 1] - this->actual_positions[i]; + + // height ds + float_type hp = (this->heights[i + 1] - this->heights[i]) / dp; + float_type hm = (this->heights[i - 1] - this->heights[i]) / dm; + + if((d >= 1. && dp > 1.) || (d <= -1. && dm < -1.)) + { + short sign_d = static_cast(d / std::abs(d)); + + // try adjusting heights[i] using p-squared formula + float_type h = this->heights[i] + sign_d / (dp - dm) * ((sign_d - dm) * hp + + (dp - sign_d) * hm); + + if(this->heights[i - 1] < h && h < this->heights[i + 1]) + { + this->heights[i] = h; + } + else + { + // use linear formula + if(d > 0) + { + this->heights[i] += hp; + } + if(d < 0) + { + this->heights[i] -= hm; + } + } + this->actual_positions[i] += sign_d; + } + } + } + } + + result_type result(dont_care) const + { + return this->heights[2]; + } + + private: + float_type p; // the quantile probability p + array_type heights; // q_i + array_type actual_positions; // n_i + array_type desired_positions; // n'_i + array_type positions_increments; // dn'_i + }; + +} // namespace detail + +/////////////////////////////////////////////////////////////////////////////// +// tag::p_square_quantile +// +namespace tag +{ + struct p_square_quantile + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::p_square_quantile_impl impl; + }; + struct p_square_quantile_for_median + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::p_square_quantile_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::p_square_quantile +// extract::p_square_quantile_for_median +// +namespace extract +{ + extractor const p_square_quantile = {}; + extractor const p_square_quantile_for_median = {}; +} + +using extract::p_square_quantile; +using extract::p_square_quantile_for_median; + +// So that p_square_quantile can be automatically substituted with +// weighted_p_square_quantile when the weight parameter is non-void +template<> +struct as_weighted_feature +{ + typedef tag::weighted_p_square_quantile type; +}; + +template<> +struct feature_of + : feature_of +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/parameters/quantile_probability.hpp b/win32/include/boost/accumulators/statistics/parameters/quantile_probability.hpp new file mode 100755 index 000000000..a7e89b906 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/parameters/quantile_probability.hpp @@ -0,0 +1,20 @@ +/////////////////////////////////////////////////////////////////////////////// +// quantile_probability.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_PARAMETERS_QUANTILE_PROBABILITY_HPP_EAN_03_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_PARAMETERS_QUANTILE_PROBABILITY_HPP_EAN_03_11_2005 + +#include + +namespace boost { namespace accumulators +{ + +BOOST_PARAMETER_KEYWORD(tag, quantile_probability) + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/peaks_over_threshold.hpp b/win32/include/boost/accumulators/statistics/peaks_over_threshold.hpp new file mode 100755 index 000000000..69af87515 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/peaks_over_threshold.hpp @@ -0,0 +1,399 @@ +/////////////////////////////////////////////////////////////////////////////// +// peaks_over_threshold.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_PEAKS_OVER_THRESHOLD_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_PEAKS_OVER_THRESHOLD_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include // pow +#include // stringstream +#include // runtime_error +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +/////////////////////////////////////////////////////////////////////////////// +// threshold_probability and threshold named parameters +// +BOOST_PARAMETER_NESTED_KEYWORD(tag, pot_threshold_value, threshold_value) +BOOST_PARAMETER_NESTED_KEYWORD(tag, pot_threshold_probability, threshold_probability) + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // peaks_over_threshold_impl + // works with an explicit threshold value and does not depend on order statistics + /** + @brief Peaks over Threshold Method for Quantile and Tail Mean Estimation + + According to the theorem of Pickands-Balkema-de Haan, the distribution function \f$F_u(x)\f$ of + the excesses \f$x\f$ over some sufficiently high threshold \f$u\f$ of a distribution function \f$F(x)\f$ + may be approximated by a generalized Pareto distribution + \f[ + G_{\xi,\beta}(x) = + \left\{ + \begin{array}{ll} + \beta^{-1}\left(1+\frac{\xi x}{\beta}\right)^{-1/\xi-1} & \textrm{if }\xi\neq0\\ + \beta^{-1}\exp\left(-\frac{x}{\beta}\right) & \textrm{if }\xi=0, + \end{array} + \right. + \f] + with suitable parameters \f$\xi\f$ and \f$\beta\f$ that can be estimated, e.g., with the method of moments, cf. + Hosking and Wallis (1987), + \f[ + \begin{array}{lll} + \hat{\xi} & = & \frac{1}{2}\left[1-\frac{(\hat{\mu}-u)^2}{\hat{\sigma}^2}\right]\\ + \hat{\beta} & = & \frac{\hat{\mu}-u}{2}\left[\frac{(\hat{\mu}-u)^2}{\hat{\sigma}^2}+1\right], + \end{array} + \f] + \f$\hat{\mu}\f$ and \f$\hat{\sigma}^2\f$ being the empirical mean and variance of the samples over + the threshold \f$u\f$. Equivalently, the distribution function + \f$F_u(x-u)\f$ of the exceedances \f$x-u\f$ can be approximated by + \f$G_{\xi,\beta}(x-u)=G_{\xi,\beta,u}(x)\f$. Since for \f$x\geq u\f$ the distribution function \f$F(x)\f$ + can be written as + \f[ + F(x) = [1 - \P(X \leq u)]F_u(x - u) + \P(X \leq u) + \f] + and the probability \f$\P(X \leq u)\f$ can be approximated by the empirical distribution function + \f$F_n(u)\f$ evaluated at \f$u\f$, an estimator of \f$F(x)\f$ is given by + \f[ + \widehat{F}(x) = [1 - F_n(u)]G_{\xi,\beta,u}(x) + F_n(u). + \f] + It can be shown that \f$\widehat{F}(x)\f$ is a generalized + Pareto distribution \f$G_{\xi,\bar{\beta},\bar{u}}(x)\f$ with \f$\bar{\beta}=\beta[1-F_n(u)]^{\xi}\f$ + and \f$\bar{u}=u-\bar{\beta}\left\{[1-F_n(u)]^{-\xi}-1\right\}/\xi\f$. By inverting \f$\widehat{F}(x)\f$, + one obtains an estimator for the \f$\alpha\f$-quantile, + \f[ + \hat{q}_{\alpha} = \bar{u} + \frac{\bar{\beta}}{\xi}\left[(1-\alpha)^{-\xi}-1\right], + \f] + and similarly an estimator for the (coherent) tail mean, + \f[ + \widehat{CTM}_{\alpha} = \hat{q}_{\alpha} - \frac{\bar{\beta}}{\xi-1}(1-\alpha)^{-\xi}, + \f] + cf. McNeil and Frey (2000). + + Note that in case extreme values of the left tail are fitted, the distribution is mirrored with respect to the + \f$y\f$ axis such that the left tail can be treated as a right tail. The computed fit parameters thus define + the Pareto distribution that fits the mirrored left tail. When quantities like a quantile or a tail mean are + computed using the fit parameters obtained from the mirrored data, the result is mirrored back, yielding the + correct result. + + For further details, see + + J. R. M. Hosking and J. R. Wallis, Parameter and quantile estimation for the generalized Pareto distribution, + Technometrics, Volume 29, 1987, p. 339-349 + + A. J. McNeil and R. Frey, Estimation of Tail-Related Risk Measures for Heteroscedastic Financial Time Series: + an Extreme Value Approach, Journal of Empirical Finance, Volume 7, 2000, p. 271-300 + + @param quantile_probability + @param pot_threshold_value + */ + template + struct peaks_over_threshold_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + // for boost::result_of + typedef boost::tuple result_type; + // for left tail fitting, mirror the extreme values + typedef mpl::int_::value ? -1 : 1> sign; + + template + peaks_over_threshold_impl(Args const &args) + : Nu_(0) + , mu_(sign::value * numeric::average(args[sample | Sample()], (std::size_t)1)) + , sigma2_(numeric::average(args[sample | Sample()], (std::size_t)1)) + , threshold_(sign::value * args[pot_threshold_value]) + , fit_parameters_(boost::make_tuple(0., 0., 0.)) + , is_dirty_(true) + { + } + + template + void operator ()(Args const &args) + { + this->is_dirty_ = true; + + if (sign::value * args[sample] > this->threshold_) + { + this->mu_ += args[sample]; + this->sigma2_ += args[sample] * args[sample]; + ++this->Nu_; + } + } + + template + result_type result(Args const &args) const + { + if (this->is_dirty_) + { + this->is_dirty_ = false; + + std::size_t cnt = count(args); + + this->mu_ = sign::value * numeric::average(this->mu_, this->Nu_); + this->sigma2_ = numeric::average(this->sigma2_, this->Nu_); + this->sigma2_ -= this->mu_ * this->mu_; + + float_type threshold_probability = numeric::average(cnt - this->Nu_, cnt); + + float_type tmp = numeric::average(( this->mu_ - this->threshold_ )*( this->mu_ - this->threshold_ ), this->sigma2_); + float_type xi_hat = 0.5 * ( 1. - tmp ); + float_type beta_hat = 0.5 * ( this->mu_ - this->threshold_ ) * ( 1. + tmp ); + float_type beta_bar = beta_hat * std::pow(1. - threshold_probability, xi_hat); + float_type u_bar = this->threshold_ - beta_bar * ( std::pow(1. - threshold_probability, -xi_hat) - 1.)/xi_hat; + this->fit_parameters_ = boost::make_tuple(u_bar, beta_bar, xi_hat); + } + + return this->fit_parameters_; + } + + private: + std::size_t Nu_; // number of samples larger than threshold + mutable float_type mu_; // mean of Nu_ largest samples + mutable float_type sigma2_; // variance of Nu_ largest samples + float_type threshold_; + mutable result_type fit_parameters_; // boost::tuple that stores fit parameters + mutable bool is_dirty_; + }; + + /////////////////////////////////////////////////////////////////////////////// + // peaks_over_threshold_prob_impl + // determines threshold from a given threshold probability using order statistics + /** + @brief Peaks over Threshold Method for Quantile and Tail Mean Estimation + + @sa peaks_over_threshold_impl + + @param quantile_probability + @param pot_threshold_probability + */ + template + struct peaks_over_threshold_prob_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + // for boost::result_of + typedef boost::tuple result_type; + // for left tail fitting, mirror the extreme values + typedef mpl::int_::value ? -1 : 1> sign; + + template + peaks_over_threshold_prob_impl(Args const &args) + : mu_(sign::value * numeric::average(args[sample | Sample()], (std::size_t)1)) + , sigma2_(numeric::average(args[sample | Sample()], (std::size_t)1)) + , threshold_probability_(args[pot_threshold_probability]) + , fit_parameters_(boost::make_tuple(0., 0., 0.)) + , is_dirty_(true) + { + } + + void operator ()(dont_care) + { + this->is_dirty_ = true; + } + + template + result_type result(Args const &args) const + { + if (this->is_dirty_) + { + this->is_dirty_ = false; + + std::size_t cnt = count(args); + + // the n'th cached sample provides an approximate threshold value u + std::size_t n = static_cast( + std::ceil( + cnt * ( ( is_same::value ) ? this->threshold_probability_ : 1. - this->threshold_probability_ ) + ) + ); + + // If n is in a valid range, return result, otherwise return NaN or throw exception + if ( n >= static_cast(tail(args).size())) + { + if (std::numeric_limits::has_quiet_NaN) + { + return boost::make_tuple( + std::numeric_limits::quiet_NaN() + , std::numeric_limits::quiet_NaN() + , std::numeric_limits::quiet_NaN() + ); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + return boost::make_tuple(Sample(0), Sample(0), Sample(0)); + } + } + else + { + float_type u = *(tail(args).begin() + n - 1) * sign::value; + + // compute mean and variance of samples above/under threshold value u + for (std::size_t i = 0; i < n; ++i) + { + mu_ += *(tail(args).begin() + i); + sigma2_ += *(tail(args).begin() + i) * (*(tail(args).begin() + i)); + } + + this->mu_ = sign::value * numeric::average(this->mu_, n); + this->sigma2_ = numeric::average(this->sigma2_, n); + this->sigma2_ -= this->mu_ * this->mu_; + + if (is_same::value) + this->threshold_probability_ = 1. - this->threshold_probability_; + + float_type tmp = numeric::average(( this->mu_ - u )*( this->mu_ - u ), this->sigma2_); + float_type xi_hat = 0.5 * ( 1. - tmp ); + float_type beta_hat = 0.5 * ( this->mu_ - u ) * ( 1. + tmp ); + float_type beta_bar = beta_hat * std::pow(1. - threshold_probability_, xi_hat); + float_type u_bar = u - beta_bar * ( std::pow(1. - threshold_probability_, -xi_hat) - 1.)/xi_hat; + this->fit_parameters_ = boost::make_tuple(u_bar, beta_bar, xi_hat); + } + } + + return this->fit_parameters_; + } + + private: + mutable float_type mu_; // mean of samples above threshold u + mutable float_type sigma2_; // variance of samples above threshold u + mutable float_type threshold_probability_; + mutable result_type fit_parameters_; // boost::tuple that stores fit parameters + mutable bool is_dirty_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::peaks_over_threshold +// +namespace tag +{ + template + struct peaks_over_threshold + : depends_on + , pot_threshold_value + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::peaks_over_threshold_impl impl; + }; + + template + struct peaks_over_threshold_prob + : depends_on > + , pot_threshold_probability + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::peaks_over_threshold_prob_impl impl; + }; + + struct abstract_peaks_over_threshold + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::peaks_over_threshold +// +namespace extract +{ + extractor const peaks_over_threshold = {}; +} + +using extract::peaks_over_threshold; + +// peaks_over_threshold(with_threshold_value) -> peaks_over_threshold +template +struct as_feature(with_threshold_value)> +{ + typedef tag::peaks_over_threshold type; +}; + +// peaks_over_threshold(with_threshold_probability) -> peaks_over_threshold_prob +template +struct as_feature(with_threshold_probability)> +{ + typedef tag::peaks_over_threshold_prob type; +}; + +template +struct feature_of > + : feature_of +{ +}; + +template +struct feature_of > + : feature_of +{ +}; + +// So that peaks_over_threshold can be automatically substituted +// with weighted_peaks_over_threshold when the weight parameter is non-void. +template +struct as_weighted_feature > +{ + typedef tag::weighted_peaks_over_threshold type; +}; + +template +struct feature_of > + : feature_of > +{}; + +// So that peaks_over_threshold_prob can be automatically substituted +// with weighted_peaks_over_threshold_prob when the weight parameter is non-void. +template +struct as_weighted_feature > +{ + typedef tag::weighted_peaks_over_threshold_prob type; +}; + +template +struct feature_of > + : feature_of > +{}; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif diff --git a/win32/include/boost/accumulators/statistics/pot_quantile.hpp b/win32/include/boost/accumulators/statistics/pot_quantile.hpp new file mode 100755 index 000000000..09dcf3470 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/pot_quantile.hpp @@ -0,0 +1,205 @@ +/////////////////////////////////////////////////////////////////////////////// +// pot_quantile.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_POT_QUANTILE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_POT_QUANTILE_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // pot_quantile_impl + // + /** + @brief Quantile Estimation based on Peaks over Threshold Method (for both left and right tails) + + Computes an estimate + \f[ + \hat{q}_{\alpha} = \bar{u} + \frac{\bar{\beta}}{\xi}\left[(1-\alpha)^{-\xi}-1\right] + \f] + for a right or left extreme quantile, \f$\bar[u]\f$, \f$\bar{\beta}\f$ and \f$\xi\f$ being the parameters of the + generalized Pareto distribution that approximates the right tail of the distribution (or the mirrored left tail, + in case the left tail is used). In the latter case, the result is mirrored back, yielding the correct result. + */ + template + struct pot_quantile_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + // for boost::result_of + typedef float_type result_type; + + pot_quantile_impl(dont_care) + : sign_((is_same::value) ? -1 : 1) + { + } + + template + result_type result(Args const &args) const + { + typedef + typename mpl::if_< + is_same + , tag::weighted_peaks_over_threshold + , tag::peaks_over_threshold + >::type + peaks_over_threshold_tag; + + extractor const some_peaks_over_threshold = {}; + + float_type u_bar = some_peaks_over_threshold(args).template get<0>(); + float_type beta_bar = some_peaks_over_threshold(args).template get<1>(); + float_type xi_hat = some_peaks_over_threshold(args).template get<2>(); + + return this->sign_ * (u_bar + beta_bar/xi_hat * ( std::pow( + is_same::value ? args[quantile_probability] : 1. - args[quantile_probability] + , -xi_hat + ) - 1.)); + } + + private: + short sign_; // if the fit parameters from the mirrored left tail extreme values are used, mirror back the result + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::pot_quantile<> +// tag::pot_quantile_prob<> +// tag::weighted_pot_quantile<> +// tag::weighted_pot_quantile_prob<> +// +namespace tag +{ + template + struct pot_quantile + : depends_on > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_quantile_impl impl; + }; + template + struct pot_quantile_prob + : depends_on > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_quantile_impl impl; + }; + template + struct weighted_pot_quantile + : depends_on > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_quantile_impl impl; + }; + template + struct weighted_pot_quantile_prob + : depends_on > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_quantile_impl impl; + }; +} + +// pot_quantile(with_threshold_value) -> pot_quantile +template +struct as_feature(with_threshold_value)> +{ + typedef tag::pot_quantile type; +}; + +// pot_quantile(with_threshold_probability) -> pot_quantile_prob +template +struct as_feature(with_threshold_probability)> +{ + typedef tag::pot_quantile_prob type; +}; + +// weighted_pot_quantile(with_threshold_value) -> weighted_pot_quantile +template +struct as_feature(with_threshold_value)> +{ + typedef tag::weighted_pot_quantile type; +}; + +// weighted_pot_quantile(with_threshold_probability) -> weighted_pot_quantile_prob +template +struct as_feature(with_threshold_probability)> +{ + typedef tag::weighted_pot_quantile_prob type; +}; + +// for the purposes of feature-based dependency resolution, +// pot_quantile and pot_quantile_prob provide +// the same feature as quantile +template +struct feature_of > + : feature_of +{ +}; + +template +struct feature_of > + : feature_of +{ +}; + +// So that pot_quantile can be automatically substituted +// with weighted_pot_quantile when the weight parameter is non-void. +template +struct as_weighted_feature > +{ + typedef tag::weighted_pot_quantile type; +}; + +template +struct feature_of > + : feature_of > +{ +}; + +// So that pot_quantile_prob can be automatically substituted +// with weighted_pot_quantile_prob when the weight parameter is non-void. +template +struct as_weighted_feature > +{ + typedef tag::weighted_pot_quantile_prob type; +}; + +template +struct feature_of > + : feature_of > +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/pot_tail_mean.hpp b/win32/include/boost/accumulators/statistics/pot_tail_mean.hpp new file mode 100755 index 000000000..daa1b3d91 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/pot_tail_mean.hpp @@ -0,0 +1,211 @@ +/////////////////////////////////////////////////////////////////////////////// +// pot_tail_mean.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_POT_TAIL_MEAN_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_POT_TAIL_MEAN_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // pot_tail_mean_impl + // + /** + @brief Estimation of the (coherent) tail mean based on the peaks over threshold method (for both left and right tails) + + Computes an estimate for the (coherent) tail mean + \f[ + \widehat{CTM}_{\alpha} = \hat{q}_{\alpha} - \frac{\bar{\beta}}{\xi-1}(1-\alpha)^{-\xi}, + \f] + where \f$\bar[u]\f$, \f$\bar{\beta}\f$ and \f$\xi\f$ are the parameters of the + generalized Pareto distribution that approximates the right tail of the distribution (or the + mirrored left tail, in case the left tail is used). In the latter case, the result is mirrored + back, yielding the correct result. + */ + template + struct pot_tail_mean_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + // for boost::result_of + typedef float_type result_type; + + pot_tail_mean_impl(dont_care) + : sign_((is_same::value) ? -1 : 1) + { + } + + template + result_type result(Args const &args) const + { + typedef + typename mpl::if_< + is_same + , tag::weighted_peaks_over_threshold + , tag::peaks_over_threshold + >::type + peaks_over_threshold_tag; + + typedef + typename mpl::if_< + is_same + , tag::weighted_pot_quantile + , tag::pot_quantile + >::type + pot_quantile_tag; + + extractor const some_peaks_over_threshold = {}; + extractor const some_pot_quantile = {}; + + float_type beta_bar = some_peaks_over_threshold(args).template get<1>(); + float_type xi_hat = some_peaks_over_threshold(args).template get<2>(); + + return some_pot_quantile(args) - this->sign_ * beta_bar/( xi_hat - 1. ) * std::pow( + is_same::value ? args[quantile_probability] : 1. - args[quantile_probability] + , -xi_hat); + } + private: + short sign_; // if the fit parameters from the mirrored left tail extreme values are used, mirror back the result + }; +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::pot_tail_mean +// tag::pot_tail_mean_prob +// +namespace tag +{ + template + struct pot_tail_mean + : depends_on, pot_quantile > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_tail_mean_impl impl; + }; + template + struct pot_tail_mean_prob + : depends_on, pot_quantile_prob > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_tail_mean_impl impl; + }; + template + struct weighted_pot_tail_mean + : depends_on, weighted_pot_quantile > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_tail_mean_impl impl; + }; + template + struct weighted_pot_tail_mean_prob + : depends_on, weighted_pot_quantile_prob > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_tail_mean_impl impl; + }; +} + +// pot_tail_mean(with_threshold_value) -> pot_tail_mean +template +struct as_feature(with_threshold_value)> +{ + typedef tag::pot_tail_mean type; +}; + +// pot_tail_mean(with_threshold_probability) -> pot_tail_mean_prob +template +struct as_feature(with_threshold_probability)> +{ + typedef tag::pot_tail_mean_prob type; +}; + +// weighted_pot_tail_mean(with_threshold_value) -> weighted_pot_tail_mean +template +struct as_feature(with_threshold_value)> +{ + typedef tag::weighted_pot_tail_mean type; +}; + +// weighted_pot_tail_mean(with_threshold_probability) -> weighted_pot_tail_mean_prob +template +struct as_feature(with_threshold_probability)> +{ + typedef tag::weighted_pot_tail_mean_prob type; +}; + +// for the purposes of feature-based dependency resolution, +// pot_tail_mean and pot_tail_mean_prob provide +// the same feature as tail_mean +template +struct feature_of > + : feature_of +{ +}; + +template +struct feature_of > + : feature_of +{ +}; + +// So that pot_tail_mean can be automatically substituted +// with weighted_pot_tail_mean when the weight parameter is non-void. +template +struct as_weighted_feature > +{ + typedef tag::weighted_pot_tail_mean type; +}; + +template +struct feature_of > + : feature_of > +{ +}; + +// So that pot_tail_mean_prob can be automatically substituted +// with weighted_pot_tail_mean_prob when the weight parameter is non-void. +template +struct as_weighted_feature > +{ + typedef tag::weighted_pot_tail_mean_prob type; +}; + +template +struct feature_of > + : feature_of > +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/skewness.hpp b/win32/include/boost/accumulators/statistics/skewness.hpp new file mode 100755 index 000000000..2ddcb9cba --- /dev/null +++ b/win32/include/boost/accumulators/statistics/skewness.hpp @@ -0,0 +1,112 @@ +/////////////////////////////////////////////////////////////////////////////// +// skewness.hpp +// +// Copyright 2006 Olivier Gygi, Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_SKEWNESS_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_SKEWNESS_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // skewness_impl + /** + @brief Skewness estimation + + The skewness of a sample distribution is defined as the ratio of the 3rd central moment and the \f$ 3/2 \f$-th power + of the 2nd central moment (the variance) of the sampless 3. The skewness can also be expressed by the simple moments: + + \f[ + \hat{g}_1 = + \frac + {\widehat{m}_n^{(3)}-3\widehat{m}_n^{(2)}\hat{\mu}_n+2\hat{\mu}_n^3} + {\left(\widehat{m}_n^{(2)} - \hat{\mu}_n^{2}\right)^{3/2}} + \f] + + where \f$ \widehat{m}_n^{(i)} \f$ are the \f$ i \f$-th moment and \f$ \hat{\mu}_n \f$ the mean (first moment) of the + \f$ n \f$ samples. + */ + template + struct skewness_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + skewness_impl(dont_care) + { + } + + template + result_type result(Args const &args) const + { + return numeric::average( + moment<3>(args) + - 3. * moment<2>(args) * mean(args) + + 2. * mean(args) * mean(args) * mean(args) + , ( moment<2>(args) - mean(args) * mean(args) ) + * std::sqrt( moment<2>(args) - mean(args) * mean(args) ) + ); + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::skewness +// +namespace tag +{ + struct skewness + : depends_on, moment<3> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::skewness_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::skewness +// +namespace extract +{ + extractor const skewness = {}; +} + +using extract::skewness; + +// So that skewness can be automatically substituted with +// weighted_skewness when the weight parameter is non-void +template<> +struct as_weighted_feature +{ + typedef tag::weighted_skewness type; +}; + +template<> +struct feature_of + : feature_of +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/stats.hpp b/win32/include/boost/accumulators/statistics/stats.hpp new file mode 100755 index 000000000..8f153564d --- /dev/null +++ b/win32/include/boost/accumulators/statistics/stats.hpp @@ -0,0 +1,29 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file stats.hpp +/// Contains the stats<> template. +/// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_STATS_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_STATS_HPP_EAN_28_10_2005 + +#include +#include +#include + +namespace boost { namespace accumulators +{ + +/////////////////////////////////////////////////////////////////////////////// +/// An MPL sequence of statistics. +template +struct stats + : mpl::vector +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/sum.hpp b/win32/include/boost/accumulators/statistics/sum.hpp new file mode 100755 index 000000000..e09f57986 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/sum.hpp @@ -0,0 +1,137 @@ +/////////////////////////////////////////////////////////////////////////////// +// sum.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_SUM_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_SUM_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // sum_impl + template + struct sum_impl + : accumulator_base + { + // for boost::result_of + typedef Sample result_type; + + template + sum_impl(Args const &args) + : sum(args[parameter::keyword::get() | Sample()]) + { + } + + template + void operator ()(Args const &args) + { + // what about overflow? + this->sum += args[parameter::keyword::get()]; + } + + result_type result(dont_care) const + { + return this->sum; + } + + private: + + Sample sum; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::sum +// tag::sum_of_weights +// tag::sum_of_variates +// +namespace tag +{ + struct sum + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::sum_impl impl; + }; + + struct sum_of_weights + : depends_on<> + { + typedef mpl::true_ is_weight_accumulator; + /// INTERNAL ONLY + /// + typedef accumulators::impl::sum_impl impl; + }; + + template + struct sum_of_variates + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef mpl::always > impl; + }; + + struct abstract_sum_of_variates + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::sum +// extract::sum_of_weights +// extract::sum_of_variates +// +namespace extract +{ + extractor const sum = {}; + extractor const sum_of_weights = {}; + extractor const sum_of_variates = {}; +} + +using extract::sum; +using extract::sum_of_weights; +using extract::sum_of_variates; + +// So that mean can be automatically substituted with +// weighted_mean when the weight parameter is non-void. +template<> +struct as_weighted_feature +{ + typedef tag::weighted_sum type; +}; + +template<> +struct feature_of + : feature_of +{}; + +template +struct feature_of > + : feature_of +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/tail.hpp b/win32/include/boost/accumulators/statistics/tail.hpp new file mode 100755 index 000000000..f5a823e10 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/tail.hpp @@ -0,0 +1,332 @@ +/////////////////////////////////////////////////////////////////////////////// +// tail.hpp +// +// Copyright 2005 Eric Niebler, Michael Gauckler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_TAIL_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_TAIL_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ +/////////////////////////////////////////////////////////////////////////////// +// cache_size named parameters +BOOST_PARAMETER_NESTED_KEYWORD(tag, right_tail_cache_size, cache_size) +BOOST_PARAMETER_NESTED_KEYWORD(tag, left_tail_cache_size, cache_size) + +namespace detail +{ + /////////////////////////////////////////////////////////////////////////////// + // tail_range + /// INTERNAL ONLY + /// + template + struct tail_range + { + typedef boost::iterator_range< + boost::reverse_iterator > + > type; + }; + + /////////////////////////////////////////////////////////////////////////////// + // make_tail_range + /// INTERNAL ONLY + /// + template + typename tail_range::type + make_tail_range(ElementIterator elem_begin, IndexIterator index_begin, IndexIterator index_end) + { + return boost::make_iterator_range( + boost::make_reverse_iterator( + boost::make_permutation_iterator(elem_begin, index_end) + ) + , boost::make_reverse_iterator( + boost::make_permutation_iterator(elem_begin, index_begin) + ) + ); + } + + /////////////////////////////////////////////////////////////////////////////// + // stat_assign_visitor + /// INTERNAL ONLY + /// + template + struct stat_assign_visitor + { + stat_assign_visitor(Args const &args, std::size_t index) + : args(args) + , index(index) + { + } + + template + void operator ()(Stat &stat) const + { + stat.assign(this->args, this->index); + } + + private: + stat_assign_visitor &operator =(stat_assign_visitor const &); + Args const &args; + std::size_t index; + }; + + /////////////////////////////////////////////////////////////////////////////// + // stat_assign + /// INTERNAL ONLY + /// + template + inline stat_assign_visitor const stat_assign(Args const &args, std::size_t index) + { + return stat_assign_visitor(args, index); + } + + /////////////////////////////////////////////////////////////////////////////// + // is_tail_variate_feature + /// INTERNAL ONLY + /// + template + struct is_tail_variate_feature + : mpl::false_ + { + }; + + /// INTERNAL ONLY + /// + template + struct is_tail_variate_feature, LeftRight> + : mpl::true_ + { + }; + + /// INTERNAL ONLY + /// + template + struct is_tail_variate_feature, LeftRight> + : mpl::true_ + { + }; + +} // namespace detail + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // tail_impl + template + struct tail_impl + : accumulator_base + { + // LeftRight must be either right or left + BOOST_MPL_ASSERT(( + mpl::or_, is_same > + )); + + typedef + typename mpl::if_< + is_same + , numeric::functional::greater + , numeric::functional::less + >::type + predicate_type; + + // for boost::result_of + typedef typename detail::tail_range< + typename std::vector::const_iterator + , std::vector::iterator + >::type result_type; + + template + tail_impl(Args const &args) + : is_sorted(false) + , indices() + , samples(args[tag::tail::cache_size], args[sample | Sample()]) + { + this->indices.reserve(this->samples.size()); + } + + tail_impl(tail_impl const &that) + : is_sorted(that.is_sorted) + , indices(that.indices) + , samples(that.samples) + { + this->indices.reserve(this->samples.size()); + } + + // This just stores the heap and the samples. + // In operator()() below, if we are adding a new sample + // to the sample cache, we force all the + // tail_variates to update also. (It's not + // good enough to wait for the accumulator_set to do it + // for us because then information about whether a sample + // was stored and where is lost, and would need to be + // queried at runtime, which would be slow.) This is + // implemented as a filtered visitation over the stats, + // which we can access because args[accumulator] gives us + // all the stats. + + template + void operator ()(Args const &args) + { + if(this->indices.size() < this->samples.size()) + { + this->indices.push_back(this->indices.size()); + this->assign(args, this->indices.back()); + } + else if(predicate_type()(args[sample], this->samples[this->indices[0]])) + { + std::pop_heap(this->indices.begin(), this->indices.end(), indirect_cmp(this->samples)); + this->assign(args, this->indices.back()); + } + } + + result_type result(dont_care) const + { + if(!this->is_sorted) + { + // Must use the same predicate here as in push_heap/pop_heap above. + std::sort_heap(this->indices.begin(), this->indices.end(), indirect_cmp(this->samples)); + // sort_heap puts elements in reverse order. Calling std::reverse + // turns the sorted sequence back into a valid heap. + std::reverse(this->indices.begin(), this->indices.end()); + this->is_sorted = true; + } + + return detail::make_tail_range( + this->samples.begin() + , this->indices.begin() + , this->indices.end() + ); + } + + private: + + struct is_tail_variate + { + template + struct apply + : detail::is_tail_variate_feature< + typename detail::feature_tag::type + , LeftRight + > + {}; + }; + + template + void assign(Args const &args, std::size_t index) + { + BOOST_ASSERT(index < this->samples.size()); + this->samples[index] = args[sample]; + std::push_heap(this->indices.begin(), this->indices.end(), indirect_cmp(this->samples)); + this->is_sorted = false; + // Tell the tail variates to store their values also + args[accumulator].template visit_if(detail::stat_assign(args, index)); + } + + /////////////////////////////////////////////////////////////////////////////// + // + struct indirect_cmp + : std::binary_function + { + indirect_cmp(std::vector const &samples) + : samples(samples) + { + } + + bool operator ()(std::size_t left, std::size_t right) const + { + return predicate_type()(this->samples[left], this->samples[right]); + } + + private: + indirect_cmp &operator =(indirect_cmp const &); + std::vector const &samples; + }; + + mutable bool is_sorted; + mutable std::vector indices; + std::vector samples; + }; + +} // namespace impl + +// TODO The templatized tag::tail below should inherit from the correct named parameter. +// The following lines provide a workaround, but there must be a better way of doing this. +template +struct tail_cache_size_named_arg +{ +}; +template<> +struct tail_cache_size_named_arg + : tag::left_tail_cache_size +{ +}; +template<> +struct tail_cache_size_named_arg + : tag::right_tail_cache_size +{ +}; + +/////////////////////////////////////////////////////////////////////////////// +// tag::tail<> +// +namespace tag +{ + template + struct tail + : depends_on<> + , tail_cache_size_named_arg + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::tail_impl impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::tail::cache_size named parameter + static boost::parameter::keyword > const cache_size; + #endif + }; + + struct abstract_tail + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::tail +// +namespace extract +{ + extractor const tail = {}; +} + +using extract::tail; + +template +struct feature_of > + : feature_of +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/tail_mean.hpp b/win32/include/boost/accumulators/statistics/tail_mean.hpp new file mode 100755 index 000000000..8ccfdf918 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/tail_mean.hpp @@ -0,0 +1,243 @@ +/////////////////////////////////////////////////////////////////////////////// +// tail_mean.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_TAIL_MEAN_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_TAIL_MEAN_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +namespace impl +{ + + /////////////////////////////////////////////////////////////////////////////// + // coherent_tail_mean_impl + // + /** + @brief Estimation of the coherent tail mean based on order statistics (for both left and right tails) + + The coherent tail mean \f$\widehat{CTM}_{n,\alpha}(X)\f$ is equal to the non-coherent tail mean \f$\widehat{NCTM}_{n,\alpha}(X)\f$ + plus a correction term that ensures coherence in case of non-continuous distributions. + + \f[ + \widehat{CTM}_{n,\alpha}^{\mathrm{right}}(X) = \widehat{NCTM}_{n,\alpha}^{\mathrm{right}}(X) + + \frac{1}{\lceil n(1-\alpha)\rceil}\hat{q}_{n,\alpha}(X)\left(1 - \alpha - \frac{1}{n}\lceil n(1-\alpha)\rceil \right) + \f] + + \f[ + \widehat{CTM}_{n,\alpha}^{\mathrm{left}}(X) = \widehat{NCTM}_{n,\alpha}^{\mathrm{left}}(X) + + \frac{1}{\lceil n\alpha\rceil}\hat{q}_{n,\alpha}(X)\left(\alpha - \frac{1}{n}\lceil n\alpha\rceil \right) + \f] + */ + template + struct coherent_tail_mean_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + // for boost::result_of + typedef float_type result_type; + + coherent_tail_mean_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + std::size_t cnt = count(args); + + std::size_t n = static_cast( + std::ceil( + cnt * ( ( is_same::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ) + ) + ); + + extractor > const some_non_coherent_tail_mean = {}; + + return some_non_coherent_tail_mean(args) + + numeric::average(quantile(args), n) + * ( + ( is_same::value ) ? args[quantile_probability] : 1. - args[quantile_probability] + - numeric::average(n, count(args)) + ); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // non_coherent_tail_mean_impl + // + /** + @brief Estimation of the (non-coherent) tail mean based on order statistics (for both left and right tails) + + An estimation of the non-coherent tail mean \f$\widehat{NCTM}_{n,\alpha}(X)\f$ is given by the mean of the + \f$\lceil n\alpha\rceil\f$ smallest samples (left tail) or the mean of the \f$\lceil n(1-\alpha)\rceil\f$ + largest samples (right tail), \f$n\f$ being the total number of samples and \f$\alpha\f$ the quantile level: + + \f[ + \widehat{NCTM}_{n,\alpha}^{\mathrm{right}}(X) = \frac{1}{\lceil n(1-\alpha)\rceil} \sum_{i=\lceil \alpha n \rceil}^n X_{i:n} + \f] + + \f[ + \widehat{NCTM}_{n,\alpha}^{\mathrm{left}}(X) = \frac{1}{\lceil n\alpha\rceil} \sum_{i=1}^{\lceil \alpha n \rceil} X_{i:n} + \f] + + It thus requires the caching of at least the \f$\lceil n\alpha\rceil\f$ smallest or the \f$\lceil n(1-\alpha)\rceil\f$ + largest samples. + + @param quantile_probability + */ + template + struct non_coherent_tail_mean_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + // for boost::result_of + typedef float_type result_type; + + non_coherent_tail_mean_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + std::size_t cnt = count(args); + + std::size_t n = static_cast( + std::ceil( + cnt * ( ( is_same::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ) + ) + ); + + // If n is in a valid range, return result, otherwise return NaN or throw exception + if (n <= static_cast(tail(args).size())) + return numeric::average( + std::accumulate( + tail(args).begin() + , tail(args).begin() + n + , Sample(0) + ) + , n + ); + else + { + if (std::numeric_limits::has_quiet_NaN) + { + return std::numeric_limits::quiet_NaN(); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + return Sample(0); + } + } + } + }; + +} // namespace impl + + +/////////////////////////////////////////////////////////////////////////////// +// tag::coherent_tail_mean<> +// tag::non_coherent_tail_mean<> +// +namespace tag +{ + template + struct coherent_tail_mean + : depends_on > + { + typedef accumulators::impl::coherent_tail_mean_impl impl; + }; + + template + struct non_coherent_tail_mean + : depends_on > + { + typedef accumulators::impl::non_coherent_tail_mean_impl impl; + }; + + struct abstract_non_coherent_tail_mean + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::non_coherent_tail_mean; +// extract::coherent_tail_mean; +// +namespace extract +{ + extractor const non_coherent_tail_mean = {}; + extractor const coherent_tail_mean = {}; +} + +using extract::non_coherent_tail_mean; +using extract::coherent_tail_mean; + +// for the purposes of feature-based dependency resolution, +// coherent_tail_mean provides the same feature as tail_mean +template +struct feature_of > + : feature_of +{ +}; + +template +struct feature_of > + : feature_of +{ +}; + +// So that non_coherent_tail_mean can be automatically substituted +// with weighted_non_coherent_tail_mean when the weight parameter is non-void. +template +struct as_weighted_feature > +{ + typedef tag::non_coherent_weighted_tail_mean type; +}; + +template +struct feature_of > + : feature_of > +{}; + +// NOTE that non_coherent_tail_mean cannot be feature-grouped with tail_mean, +// which is the base feature for coherent tail means, since (at least for +// non-continuous distributions) non_coherent_tail_mean is a different measure! + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif diff --git a/win32/include/boost/accumulators/statistics/tail_quantile.hpp b/win32/include/boost/accumulators/statistics/tail_quantile.hpp new file mode 100755 index 000000000..a93dcd044 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/tail_quantile.hpp @@ -0,0 +1,156 @@ +/////////////////////////////////////////////////////////////////////////////// +// tail_quantile.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_TAIL_QUANTILE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_TAIL_QUANTILE_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include // For ceil +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // tail_quantile_impl + // Tail quantile estimation based on order statistics + /** + @brief Tail quantile estimation based on order statistics (for both left and right tails) + + The estimation of a tail quantile \f$\hat{q}\f$ with level \f$\alpha\f$ based on order statistics requires the + chaching of at least the \f$\lceil n\alpha\rceil\f$ smallest or the \f$\lceil n(1-\alpha)\rceil\f$ largest samples, + \f$n\f$ being the total number of samples. The largest of the \f$\lceil n\alpha\rceil\f$ smallest samples or the + smallest of the \f$\lceil n(1-\alpha)\rceil\f$ largest samples provides an estimate for the quantile: + + \f[ + \hat{q}_{n,\alpha} = X_{\lceil \alpha n \rceil:n} + \f] + + @param quantile_probability + */ + template + struct tail_quantile_impl + : accumulator_base + { + // for boost::result_of + typedef Sample result_type; + + tail_quantile_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + std::size_t cnt = count(args); + + std::size_t n = static_cast( + std::ceil( + cnt * ( ( is_same::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ) + ) + ); + + // If n is in a valid range, return result, otherwise return NaN or throw exception + if ( n < static_cast(tail(args).size())) + { + // Note that the cached samples of the left are sorted in ascending order, + // whereas the samples of the right tail are sorted in descending order + return *(boost::begin(tail(args)) + n - 1); + } + else + { + if (std::numeric_limits::has_quiet_NaN) + { + return std::numeric_limits::quiet_NaN(); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + return Sample(0); + } + } + } + }; +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::tail_quantile<> +// +namespace tag +{ + template + struct tail_quantile + : depends_on > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::tail_quantile_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::tail_quantile +// +namespace extract +{ + extractor const tail_quantile = {}; +} + +using extract::tail_quantile; + +// for the purposes of feature-based dependency resolution, +// tail_quantile provide the same feature as quantile +template +struct feature_of > + : feature_of +{ +}; + +// So that tail_quantile can be automatically substituted with +// weighted_tail_quantile when the weight parameter is non-void. +template +struct as_weighted_feature > +{ + typedef tag::weighted_tail_quantile type; +}; + +template +struct feature_of > + : feature_of > +{}; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif diff --git a/win32/include/boost/accumulators/statistics/tail_variate.hpp b/win32/include/boost/accumulators/statistics/tail_variate.hpp new file mode 100755 index 000000000..8fd55930d --- /dev/null +++ b/win32/include/boost/accumulators/statistics/tail_variate.hpp @@ -0,0 +1,138 @@ +/////////////////////////////////////////////////////////////////////////////// +// tail_variate.hpp +// +// Copyright 2005 Eric Niebler, Michael Gauckler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STAT_STATISTICS_TAIL_VARIATE_HPP_EAN_28_10_2005 +#define BOOST_STAT_STATISTICS_TAIL_VARIATE_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // tail_variate_impl + template + struct tail_variate_impl + : accumulator_base + { + // for boost::result_of + typedef + typename detail::tail_range< + typename std::vector::const_iterator + , std::vector::iterator + >::type + result_type; + + template + tail_variate_impl(Args const &args) + : variates(args[tag::tail::cache_size], args[parameter::keyword::get() | VariateType()]) + { + } + + template + void assign(Args const &args, std::size_t index) + { + this->variates[index] = args[parameter::keyword::get()]; + } + + template + result_type result(Args const &args) const + { + // getting the order result causes the indices vector to be sorted. + extractor > const some_tail = {}; + return this->do_result(some_tail(args)); + } + + private: + template + result_type do_result(TailRng const &rng) const + { + return detail::make_tail_range( + this->variates.begin() + , rng.end().base().base() // the index iterator + , rng.begin().base().base() // (begin and end reversed because these are reverse iterators) + ); + } + + std::vector variates; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::tail_variate<> +// +namespace tag +{ + template + struct tail_variate + : depends_on > + { + /// INTERNAL ONLY + /// + typedef mpl::always > impl; + }; + + struct abstract_tail_variate + : depends_on<> + { + }; + + template + struct tail_weights + : depends_on > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::tail_variate_impl impl; + }; + + struct abstract_tail_weights + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::tail_variate +// extract::tail_weights +// +namespace extract +{ + extractor const tail_variate = {}; + extractor const tail_weights = {}; +} + +using extract::tail_variate; +using extract::tail_weights; + +template +struct feature_of > + : feature_of +{ +}; + +template +struct feature_of > +{ + typedef tag::abstract_tail_weights type; +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/tail_variate_means.hpp b/win32/include/boost/accumulators/statistics/tail_variate_means.hpp new file mode 100755 index 000000000..58afdc00c --- /dev/null +++ b/win32/include/boost/accumulators/statistics/tail_variate_means.hpp @@ -0,0 +1,255 @@ +/////////////////////////////////////////////////////////////////////////////// +// tail_variate_means.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_TAIL_VARIATE_MEANS_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_TAIL_VARIATE_MEANS_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /** + @brief Estimation of the absolute and relative tail variate means (for both left and right tails) + + For all \f$j\f$-th variates associated to the \f$\lceil n(1-\alpha)\rceil\f$ largest samples (or the + \f$\lceil n(1-\alpha)\rceil\f$ smallest samples in case of the left tail), the absolute tail means + \f$\widehat{ATM}_{n,\alpha}(X, j)\f$ are computed and returned as an iterator range. Alternatively, + the relative tail means \f$\widehat{RTM}_{n,\alpha}(X, j)\f$ are returned, which are the absolute + tail means normalized with the (non-coherent) sample tail mean \f$\widehat{NCTM}_{n,\alpha}(X)\f$. + + \f[ + \widehat{ATM}_{n,\alpha}^{\mathrm{right}}(X, j) = + \frac{1}{\lceil n(1-\alpha) \rceil} + \sum_{i=\lceil \alpha n \rceil}^n \xi_{j,i} + \f] + + \f[ + \widehat{ATM}_{n,\alpha}^{\mathrm{left}}(X, j) = + \frac{1}{\lceil n\alpha \rceil} + \sum_{i=1}^{\lceil n\alpha \rceil} \xi_{j,i} + \f] + + \f[ + \widehat{RTM}_{n,\alpha}^{\mathrm{right}}(X, j) = + \frac{\sum_{i=\lceil n\alpha \rceil}^n \xi_{j,i}} + {\lceil n(1-\alpha)\rceil\widehat{NCTM}_{n,\alpha}^{\mathrm{right}}(X)} + \f] + + \f[ + \widehat{RTM}_{n,\alpha}^{\mathrm{left}}(X, j) = + \frac{\sum_{i=1}^{\lceil n\alpha \rceil} \xi_{j,i}} + {\lceil n\alpha\rceil\widehat{NCTM}_{n,\alpha}^{\mathrm{left}}(X)} + \f] + */ + + /////////////////////////////////////////////////////////////////////////////// + // tail_variate_means_impl + // by default: absolute tail_variate_means + template + struct tail_variate_means_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + typedef std::vector array_type; + // for boost::result_of + typedef iterator_range result_type; + + tail_variate_means_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + std::size_t cnt = count(args); + + std::size_t n = static_cast( + std::ceil( + cnt * ( ( is_same::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ) + ) + ); + + std::size_t num_variates = tail_variate(args).begin()->size(); + + this->tail_means_.clear(); + this->tail_means_.resize(num_variates, Sample(0)); + + // If n is in a valid range, return result, otherwise return NaN or throw exception + if (n < static_cast(tail(args).size())) + { + this->tail_means_ = std::accumulate( + tail_variate(args).begin() + , tail_variate(args).begin() + n + , this->tail_means_ + , numeric::plus + ); + + float_type factor = n * ( (is_same::value) ? non_coherent_tail_mean(args) : 1. ); + + std::transform( + this->tail_means_.begin() + , this->tail_means_.end() + , this->tail_means_.begin() + , std::bind2nd(std::divides(), factor) + ); + } + else + { + if (std::numeric_limits::has_quiet_NaN) + { + std::fill( + this->tail_means_.begin() + , this->tail_means_.end() + , std::numeric_limits::quiet_NaN() + ); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + } + } + return make_iterator_range(this->tail_means_); + } + + private: + + mutable array_type tail_means_; + + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::absolute_tail_variate_means +// tag::relative_tail_variate_means +// +namespace tag +{ + template + struct absolute_tail_variate_means + : depends_on, tail_variate > + { + typedef accumulators::impl::tail_variate_means_impl impl; + }; + template + struct relative_tail_variate_means + : depends_on, tail_variate > + { + typedef accumulators::impl::tail_variate_means_impl impl; + }; + struct abstract_absolute_tail_variate_means + : depends_on<> + { + }; + struct abstract_relative_tail_variate_means + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::tail_variate_means +// extract::relative_tail_variate_means +// +namespace extract +{ + extractor const tail_variate_means = {}; + extractor const relative_tail_variate_means = {}; +} + +using extract::tail_variate_means; +using extract::relative_tail_variate_means; + +// tail_variate_means(absolute) -> absolute_tail_variate_means +template +struct as_feature(absolute)> +{ + typedef tag::absolute_tail_variate_means type; +}; + +// tail_variate_means(relative) ->relative_tail_variate_means +template +struct as_feature(relative)> +{ + typedef tag::relative_tail_variate_means type; +}; + +// Provides non-templatized extractor +template +struct feature_of > + : feature_of +{ +}; + +// Provides non-templatized extractor +template +struct feature_of > + : feature_of +{ +}; + +// So that absolute_tail_means can be automatically substituted +// with absolute_weighted_tail_means when the weight parameter is non-void. +template +struct as_weighted_feature > +{ + typedef tag::absolute_weighted_tail_variate_means type; +}; + +template +struct feature_of > + : feature_of > +{ +}; + +// So that relative_tail_means can be automatically substituted +// with relative_weighted_tail_means when the weight parameter is non-void. +template +struct as_weighted_feature > +{ + typedef tag::relative_weighted_tail_variate_means type; +}; + +template +struct feature_of > + : feature_of > +{ +}; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif diff --git a/win32/include/boost/accumulators/statistics/times2_iterator.hpp b/win32/include/boost/accumulators/statistics/times2_iterator.hpp new file mode 100755 index 000000000..942c1f8ce --- /dev/null +++ b/win32/include/boost/accumulators/statistics/times2_iterator.hpp @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////////// +// times2_iterator.hpp +// +// Copyright 2006 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_TIMES2_ITERATOR_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_TIMES2_ITERATOR_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace detail +{ + typedef transform_iterator< + std::binder1st > + , counting_iterator + > times2_iterator; + + inline times2_iterator make_times2_iterator(std::size_t i) + { + return make_transform_iterator( + make_counting_iterator(i) + , std::bind1st(std::multiplies(), 2) + ); + } + + + /////////////////////////////////////////////////////////////////////////////// + // lvalue_index_iterator + template + struct lvalue_index_iterator + : Base + { + lvalue_index_iterator(Base base) + : Base(base) + { + } + + typename Base::reference operator [](typename Base::difference_type n) const + { + return *(*this + n); + } + }; +} // namespace detail + +}} + +#endif diff --git a/win32/include/boost/accumulators/statistics/variance.hpp b/win32/include/boost/accumulators/statistics/variance.hpp new file mode 100755 index 000000000..ee518d9a6 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/variance.hpp @@ -0,0 +1,233 @@ +/////////////////////////////////////////////////////////////////////////////// +// variance.hpp +// +// Copyright 2005 Daniel Egloff, Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_VARIANCE_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_VARIANCE_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + //! Lazy calculation of variance. + /*! + Default sample variance implementation based on the second moment \f$ M_n^{(2)} \f$ moment<2>, mean and count. + \f[ + \sigma_n^2 = M_n^{(2)} - \mu_n^2. + \f] + where + \f[ + \mu_n = \frac{1}{n} \sum_{i = 1}^n x_i. + \f] + is the estimate of the sample mean and \f$n\f$ is the number of samples. + */ + template + struct lazy_variance_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + lazy_variance_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + extractor mean; + result_type tmp = mean(args); + return moment<2>(args) - tmp * tmp; + } + }; + + //! Iterative calculation of variance. + /*! + Iterative calculation of sample variance \f$\sigma_n^2\f$ according to the formula + \f[ + \sigma_n^2 = \frac{1}{n} \sum_{i = 1}^n (x_i - \mu_n)^2 = \frac{n-1}{n} \sigma_{n-1}^2 + \frac{1}{n-1}(x_n - \mu_n)^2. + \f] + where + \f[ + \mu_n = \frac{1}{n} \sum_{i = 1}^n x_i. + \f] + is the estimate of the sample mean and \f$n\f$ is the number of samples. + + Note that the sample variance is not defined for \f$n <= 1\f$. + + A simplification can be obtained by the approximate recursion + \f[ + \sigma_n^2 \approx \frac{n-1}{n} \sigma_{n-1}^2 + \frac{1}{n}(x_n - \mu_n)^2. + \f] + because the difference + \f[ + \left(\frac{1}{n-1} - \frac{1}{n}\right)(x_n - \mu_n)^2 = \frac{1}{n(n-1)}(x_n - \mu_n)^2. + \f] + converges to zero as \f$n \rightarrow \infty\f$. However, for small \f$ n \f$ the difference + can be non-negligible. + */ + template + struct variance_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + template + variance_impl(Args const &args) + : variance(numeric::average(args[sample | Sample()], numeric::one::value)) + { + } + + template + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + + if(cnt > 1) + { + extractor mean; + result_type tmp = args[parameter::keyword::get()] - mean(args); + this->variance = + numeric::average(this->variance * (cnt - 1), cnt) + + numeric::average(tmp * tmp, cnt - 1); + } + } + + result_type result(dont_care) const + { + return this->variance; + } + + private: + result_type variance; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::variance +// tag::immediate_variance +// +namespace tag +{ + struct lazy_variance + : depends_on, mean> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::lazy_variance_impl impl; + }; + + struct variance + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::variance_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::lazy_variance +// extract::variance +// +namespace extract +{ + extractor const lazy_variance = {}; + extractor const variance = {}; +} + +using extract::lazy_variance; +using extract::variance; + +// variance(lazy) -> lazy_variance +template<> +struct as_feature +{ + typedef tag::lazy_variance type; +}; + +// variance(immediate) -> variance +template<> +struct as_feature +{ + typedef tag::variance type; +}; + +// for the purposes of feature-based dependency resolution, +// immediate_variance provides the same feature as variance +template<> +struct feature_of + : feature_of +{ +}; + +// So that variance can be automatically substituted with +// weighted_variance when the weight parameter is non-void. +template<> +struct as_weighted_feature +{ + typedef tag::weighted_variance type; +}; + +// for the purposes of feature-based dependency resolution, +// weighted_variance provides the same feature as variance +template<> +struct feature_of + : feature_of +{ +}; + +// So that immediate_variance can be automatically substituted with +// immediate_weighted_variance when the weight parameter is non-void. +template<> +struct as_weighted_feature +{ + typedef tag::lazy_weighted_variance type; +}; + +// for the purposes of feature-based dependency resolution, +// immediate_weighted_variance provides the same feature as immediate_variance +template<> +struct feature_of + : feature_of +{ +}; + +//////////////////////////////////////////////////////////////////////////// +//// droppable_accumulator +//// need to specialize droppable lazy variance to cache the result at the +//// point the accumulator is dropped. +///// INTERNAL ONLY +///// +//template +//struct droppable_accumulator > +// : droppable_accumulator_base< +// with_cached_result > +// > +//{ +// template +// droppable_accumulator(Args const &args) +// : droppable_accumulator::base(args) +// { +// } +//}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/variates/covariate.hpp b/win32/include/boost/accumulators/statistics/variates/covariate.hpp new file mode 100755 index 000000000..ba92196f0 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/variates/covariate.hpp @@ -0,0 +1,21 @@ +/////////////////////////////////////////////////////////////////////////////// +// weight.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_VARIATES_COVARIATE_HPP_EAN_03_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_VARIATES_COVARIATE_HPP_EAN_03_11_2005 + +#include + +namespace boost { namespace accumulators +{ + +BOOST_PARAMETER_KEYWORD(tag, covariate1) +BOOST_PARAMETER_KEYWORD(tag, covariate2) + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_covariance.hpp b/win32/include/boost/accumulators/statistics/weighted_covariance.hpp new file mode 100755 index 000000000..ac5626b47 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_covariance.hpp @@ -0,0 +1,131 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_covariance.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_COVARIANCE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_COVARIANCE_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for numeric::outer_product() and type traits +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_covariance_impl + // + /** + @brief Weighted Covariance Estimator + + An iterative Monte Carlo estimator for the weighted covariance \f$\mathrm{Cov}(X,X')\f$, where \f$X\f$ is a sample + and \f$X'\f$ a variate, is given by: + + \f[ + \hat{c}_n = \frac{\bar{w}_n-w_n}{\bar{w}_n} \hat{c}_{n-1} + \frac{w_n}{\bar{w}_n-w_n}(X_n - \hat{\mu}_n)(X_n' - \hat{\mu}_n'), + \quad n\ge2,\quad\hat{c}_1 = 0, + \f] + + \f$\hat{\mu}_n\f$ and \f$\hat{\mu}_n'\f$ being the weighted means of the samples and variates and + \f$\bar{w}_n\f$ the sum of the \f$n\f$ first weights \f$w_i\f$. + */ + template + struct weighted_covariance_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type>::result_type weighted_sample_type; + typedef typename numeric::functional::multiplies::result_type>::result_type weighted_variate_type; + // for boost::result_of + typedef typename numeric::functional::outer_product::result_type result_type; + + template + weighted_covariance_impl(Args const &args) + : cov_( + numeric::outer_product( + numeric::average(args[sample | Sample()], (std::size_t)1) + * numeric::one::value + , numeric::average(args[parameter::keyword::get() | VariateType()], (std::size_t)1) + * numeric::one::value + ) + ) + { + } + + template + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + + if (cnt > 1) + { + extractor > const some_weighted_mean_of_variates = {}; + + this->cov_ = this->cov_ * (sum_of_weights(args) - args[weight]) / sum_of_weights(args) + + numeric::outer_product( + some_weighted_mean_of_variates(args) - args[parameter::keyword::get()] + , weighted_mean(args) - args[sample] + ) * args[weight] / (sum_of_weights(args) - args[weight]); + } + } + + result_type result(dont_care) const + { + return this->cov_; + } + + private: + result_type cov_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_covariance +// +namespace tag +{ + template + struct weighted_covariance + : depends_on > + { + typedef accumulators::impl::weighted_covariance_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_covariance +// +namespace extract +{ + extractor const weighted_covariance = {}; +} + +using extract::weighted_covariance; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_density.hpp b/win32/include/boost/accumulators/statistics/weighted_density.hpp new file mode 100755 index 000000000..453fd81df --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_density.hpp @@ -0,0 +1,219 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_density.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_DENSITY_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_DENSITY_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for named parameters density_cache_size and density_num_bins + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_density_impl + // density histogram for weighted samples + /** + @brief Histogram density estimator for weighted samples + + The histogram density estimator returns a histogram of the sample distribution. The positions and sizes of the bins + are determined using a specifiable number of cached samples (cache_size). The range between the minimum and the + maximum of the cached samples is subdivided into a specifiable number of bins (num_bins) of same size. Additionally, + an under- and an overflow bin is added to capture future under- and overflow samples. Once the bins are determined, + the cached samples and all subsequent samples are added to the correct bins. At the end, a range of std::pair is + returned, where each pair contains the position of the bin (lower bound) and the sum of the weights (normalized with the + sum of all weights). + + @param density_cache_size Number of first samples used to determine min and max. + @param density_num_bins Number of bins (two additional bins collect under- and overflow samples). + */ + template + struct weighted_density_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + typedef std::vector > histogram_type; + typedef std::vector array_type; + // for boost::result_of + typedef iterator_range result_type; + + template + weighted_density_impl(Args const &args) + : cache_size(args[density_cache_size]) + , cache(cache_size) + , num_bins(args[density_num_bins]) + , samples_in_bin(num_bins + 2, 0.) + , bin_positions(num_bins + 2) + , histogram( + num_bins + 2 + , std::make_pair( + numeric::average(args[sample | Sample()],(std::size_t)1) + , numeric::average(args[sample | Sample()],(std::size_t)1) + ) + ) + , is_dirty(true) + { + } + + template + void operator ()(Args const &args) + { + this->is_dirty = true; + + std::size_t cnt = count(args); + + // Fill up cache with cache_size first samples + if (cnt <= this->cache_size) + { + this->cache[cnt - 1] = std::make_pair(args[sample], args[weight]); + } + + // Once cache_size samples have been accumulated, create num_bins bins of same size between + // the minimum and maximum of the cached samples as well as an under- and an overflow bin. + // Store their lower bounds (bin_positions) and fill the bins with the cached samples (samples_in_bin). + if (cnt == this->cache_size) + { + float_type minimum = numeric::average((min)(args),(std::size_t)1); + float_type maximum = numeric::average((max)(args),(std::size_t)1); + float_type bin_size = numeric::average(maximum - minimum, this->num_bins); + + // determine bin positions (their lower bounds) + for (std::size_t i = 0; i < this->num_bins + 2; ++i) + { + this->bin_positions[i] = minimum + (i - 1.) * bin_size; + } + + for (typename histogram_type::const_iterator iter = this->cache.begin(); iter != this->cache.end(); ++iter) + { + if (iter->first < this->bin_positions[1]) + { + this->samples_in_bin[0] += iter->second; + } + else if (iter->first >= this->bin_positions[this->num_bins + 1]) + { + this->samples_in_bin[this->num_bins + 1] += iter->second; + } + else + { + typename array_type::iterator it = std::upper_bound( + this->bin_positions.begin() + , this->bin_positions.end() + , iter->first + ); + + std::size_t d = std::distance(this->bin_positions.begin(), it); + this->samples_in_bin[d - 1] += iter->second; + } + } + } + // Add each subsequent sample to the correct bin + else if (cnt > this->cache_size) + { + if (args[sample] < this->bin_positions[1]) + { + this->samples_in_bin[0] += args[weight]; + } + else if (args[sample] >= this->bin_positions[this->num_bins + 1]) + { + this->samples_in_bin[this->num_bins + 1] += args[weight]; + } + else + { + typename array_type::iterator it = std::upper_bound( + this->bin_positions.begin() + , this->bin_positions.end() + , args[sample] + ); + + std::size_t d = std::distance(this->bin_positions.begin(), it); + this->samples_in_bin[d - 1] += args[weight]; + } + } + } + + template + result_type result(Args const &args) const + { + if (this->is_dirty) + { + this->is_dirty = false; + + // creates a vector of std::pair where each pair i holds + // the values bin_positions[i] (x-axis of histogram) and + // samples_in_bin[i] / cnt (y-axis of histogram). + + for (std::size_t i = 0; i < this->num_bins + 2; ++i) + { + this->histogram[i] = std::make_pair(this->bin_positions[i], numeric::average(this->samples_in_bin[i], sum_of_weights(args))); + } + } + + // returns a range of pairs + return make_iterator_range(this->histogram); + } + + private: + std::size_t cache_size; // number of cached samples + histogram_type cache; // cache to store the first cache_size samples with their weights as std::pair + std::size_t num_bins; // number of bins + array_type samples_in_bin; // number of samples in each bin + array_type bin_positions; // lower bounds of bins + mutable histogram_type histogram; // histogram + mutable bool is_dirty; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_density +// +namespace tag +{ + struct weighted_density + : depends_on + , density_cache_size + , density_num_bins + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_density_impl impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + static boost::parameter::keyword const cache_size; + static boost::parameter::keyword const num_bins; + #endif + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_density +// +namespace extract +{ + extractor const weighted_density = {}; +} + +using extract::weighted_density; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_extended_p_square.hpp b/win32/include/boost/accumulators/statistics/weighted_extended_p_square.hpp new file mode 100755 index 000000000..ea44b04a7 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_extended_p_square.hpp @@ -0,0 +1,288 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_extended_p_square.hpp +// +// Copyright 2005 Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_EXTENDED_P_SQUARE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_EXTENDED_P_SQUARE_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_extended_p_square_impl + // multiple quantile estimation with weighted samples + /** + @brief Multiple quantile estimation with the extended \f$P^2\f$ algorithm for weighted samples + + This version of the extended \f$P^2\f$ algorithm extends the extended \f$P^2\f$ algorithm to + support weighted samples. The extended \f$P^2\f$ algorithm dynamically estimates several + quantiles without storing samples. Assume that \f$m\f$ quantiles + \f$\xi_{p_1}, \ldots, \xi_{p_m}\f$ are to be estimated. Instead of storing the whole sample + cumulative distribution, the algorithm maintains only \f$m+2\f$ principal markers and + \f$m+1\f$ middle markers, whose positions are updated with each sample and whose heights + are adjusted (if necessary) using a piecewise-parablic formula. The heights of the principal + markers are the current estimates of the quantiles and are returned as an iterator range. + + For further details, see + + K. E. E. Raatikainen, Simultaneous estimation of several quantiles, Simulation, Volume 49, + Number 4 (October), 1986, p. 159-164. + + The extended \f$ P^2 \f$ algorithm generalizess the \f$ P^2 \f$ algorithm of + + R. Jain and I. Chlamtac, The P^2 algorithmus for dynamic calculation of quantiles and + histograms without storing observations, Communications of the ACM, + Volume 28 (October), Number 10, 1985, p. 1076-1085. + + @param extended_p_square_probabilities A vector of quantile probabilities. + */ + template + struct weighted_extended_p_square_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type weighted_sample; + typedef typename numeric::functional::average::result_type float_type; + typedef std::vector array_type; + // for boost::result_of + typedef iterator_range< + detail::lvalue_index_iterator< + permutation_iterator< + typename array_type::const_iterator + , detail::times2_iterator + > + > + > result_type; + + template + weighted_extended_p_square_impl(Args const &args) + : probabilities( + boost::begin(args[extended_p_square_probabilities]) + , boost::end(args[extended_p_square_probabilities]) + ) + , heights(2 * probabilities.size() + 3) + , actual_positions(heights.size()) + , desired_positions(heights.size()) + { + } + + template + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + std::size_t sample_cell = 1; // k + std::size_t num_quantiles = this->probabilities.size(); + + // m+2 principal markers and m+1 middle markers + std::size_t num_markers = 2 * num_quantiles + 3; + + // first accumulate num_markers samples + if(cnt <= num_markers) + { + this->heights[cnt - 1] = args[sample]; + this->actual_positions[cnt - 1] = args[weight]; + + // complete the initialization of heights (and actual_positions) by sorting + if(cnt == num_markers) + { + // TODO: we need to sort the initial samples (in heights) in ascending order and + // sort their weights (in actual_positions) the same way. The following lines do + // it, but there must be a better and more efficient way of doing this. + typename array_type::iterator it_begin, it_end, it_min; + + it_begin = this->heights.begin(); + it_end = this->heights.end(); + + std::size_t pos = 0; + + while (it_begin != it_end) + { + it_min = std::min_element(it_begin, it_end); + std::size_t d = std::distance(it_begin, it_min); + std::swap(*it_begin, *it_min); + std::swap(this->actual_positions[pos], this->actual_positions[pos + d]); + ++it_begin; + ++pos; + } + + // calculate correct initial actual positions + for (std::size_t i = 1; i < num_markers; ++i) + { + actual_positions[i] += actual_positions[i - 1]; + } + } + } + else + { + if(args[sample] < this->heights[0]) + { + this->heights[0] = args[sample]; + this->actual_positions[0] = args[weight]; + sample_cell = 1; + } + else if(args[sample] >= this->heights[num_markers - 1]) + { + this->heights[num_markers - 1] = args[sample]; + sample_cell = num_markers - 1; + } + else + { + // find cell k = sample_cell such that heights[k-1] <= sample < heights[k] + + typedef typename array_type::iterator iterator; + iterator it = std::upper_bound( + this->heights.begin() + , this->heights.end() + , args[sample] + ); + + sample_cell = std::distance(this->heights.begin(), it); + } + + // update actual position of all markers above sample_cell + for(std::size_t i = sample_cell; i < num_markers; ++i) + { + this->actual_positions[i] += args[weight]; + } + + // compute desired positions + { + this->desired_positions[0] = this->actual_positions[0]; + this->desired_positions[num_markers - 1] = sum_of_weights(args); + this->desired_positions[1] = (sum_of_weights(args) - this->actual_positions[0]) * probabilities[0] + / 2. + this->actual_positions[0]; + this->desired_positions[num_markers - 2] = (sum_of_weights(args) - this->actual_positions[0]) + * (probabilities[num_quantiles - 1] + 1.) + / 2. + this->actual_positions[0]; + + for (std::size_t i = 0; i < num_quantiles; ++i) + { + this->desired_positions[2 * i + 2] = (sum_of_weights(args) - this->actual_positions[0]) + * probabilities[i] + this->actual_positions[0]; + } + + for (std::size_t i = 1; i < num_quantiles; ++i) + { + this->desired_positions[2 * i + 1] = (sum_of_weights(args) - this->actual_positions[0]) + * (probabilities[i - 1] + probabilities[i]) + / 2. + this->actual_positions[0]; + } + } + + // adjust heights and actual_positions of markers 1 to num_markers - 2 if necessary + for (std::size_t i = 1; i <= num_markers - 2; ++i) + { + // offset to desired position + float_type d = this->desired_positions[i] - this->actual_positions[i]; + + // offset to next position + float_type dp = this->actual_positions[i + 1] - this->actual_positions[i]; + + // offset to previous position + float_type dm = this->actual_positions[i - 1] - this->actual_positions[i]; + + // height ds + float_type hp = (this->heights[i + 1] - this->heights[i]) / dp; + float_type hm = (this->heights[i - 1] - this->heights[i]) / dm; + + if((d >= 1 && dp > 1) || (d <= -1 && dm < -1)) + { + short sign_d = static_cast(d / std::abs(d)); + + float_type h = this->heights[i] + sign_d / (dp - dm) * ((sign_d - dm)*hp + (dp - sign_d) * hm); + + // try adjusting heights[i] using p-squared formula + if(this->heights[i - 1] < h && h < this->heights[i + 1]) + { + this->heights[i] = h; + } + else + { + // use linear formula + if(d > 0) + { + this->heights[i] += hp; + } + if(d < 0) + { + this->heights[i] -= hm; + } + } + this->actual_positions[i] += sign_d; + } + } + } + } + + result_type result(dont_care) const + { + // for i in [1,probabilities.size()], return heights[i * 2] + detail::times2_iterator idx_begin = detail::make_times2_iterator(1); + detail::times2_iterator idx_end = detail::make_times2_iterator(this->probabilities.size() + 1); + + return result_type( + make_permutation_iterator(this->heights.begin(), idx_begin) + , make_permutation_iterator(this->heights.begin(), idx_end) + ); + } + + private: + array_type probabilities; // the quantile probabilities + array_type heights; // q_i + array_type actual_positions; // n_i + array_type desired_positions; // d_i + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_extended_p_square +// +namespace tag +{ + struct weighted_extended_p_square + : depends_on + , extended_p_square_probabilities + { + typedef accumulators::impl::weighted_extended_p_square_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_extended_p_square +// +namespace extract +{ + extractor const weighted_extended_p_square = {}; +} + +using extract::weighted_extended_p_square; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_kurtosis.hpp b/win32/include/boost/accumulators/statistics/weighted_kurtosis.hpp new file mode 100755 index 000000000..901aba8ec --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_kurtosis.hpp @@ -0,0 +1,103 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_kurtosis.hpp +// +// Copyright 2006 Olivier Gygi, Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_KURTOSIS_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_KURTOSIS_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_kurtosis_impl + /** + @brief Kurtosis estimation for weighted samples + + The kurtosis of a sample distribution is defined as the ratio of the 4th central moment and the square of the 2nd central + moment (the variance) of the samples, minus 3. The term \f$ -3 \f$ is added in order to ensure that the normal distribution + has zero kurtosis. The kurtosis can also be expressed by the simple moments: + + \f[ + \hat{g}_2 = + \frac + {\widehat{m}_n^{(4)}-4\widehat{m}_n^{(3)}\hat{\mu}_n+6\widehat{m}_n^{(2)}\hat{\mu}_n^2-3\hat{\mu}_n^4} + {\left(\widehat{m}_n^{(2)} - \hat{\mu}_n^{2}\right)^2} - 3, + \f] + + where \f$ \widehat{m}_n^{(i)} \f$ are the \f$ i \f$-th moment and \f$ \hat{\mu}_n \f$ the mean (first moment) of the + \f$ n \f$ samples. + + The kurtosis estimator for weighted samples is formally identical to the estimator for unweighted samples, except that + the weighted counterparts of all measures it depends on are to be taken. + */ + template + struct weighted_kurtosis_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type weighted_sample; + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + weighted_kurtosis_impl(dont_care) + { + } + + template + result_type result(Args const &args) const + { + return numeric::average( + weighted_moment<4>(args) + - 4. * weighted_moment<3>(args) * weighted_mean(args) + + 6. * weighted_moment<2>(args) * weighted_mean(args) * weighted_mean(args) + - 3. * weighted_mean(args) * weighted_mean(args) * weighted_mean(args) * weighted_mean(args) + , ( weighted_moment<2>(args) - weighted_mean(args) * weighted_mean(args) ) + * ( weighted_moment<2>(args) - weighted_mean(args) * weighted_mean(args) ) + ) - 3.; + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_kurtosis +// +namespace tag +{ + struct weighted_kurtosis + : depends_on, weighted_moment<3>, weighted_moment<4> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_kurtosis_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_kurtosis +// +namespace extract +{ + extractor const weighted_kurtosis = {}; +} + +using extract::weighted_kurtosis; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_mean.hpp b/win32/include/boost/accumulators/statistics/weighted_mean.hpp new file mode 100755 index 000000000..3e3db5215 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_mean.hpp @@ -0,0 +1,187 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_mean.hpp +// +// Copyright 2006 Eric Niebler, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MEAN_HPP_EAN_03_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MEAN_HPP_EAN_03_11_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_mean_impl + // lazy, by default + template + struct weighted_mean_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type weighted_sample; + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + weighted_mean_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + typedef + typename mpl::if_< + is_same + , tag::weighted_sum + , tag::weighted_sum_of_variates + >::type + weighted_sum_tag; + + extractor const some_weighted_sum = {}; + + return numeric::average(some_weighted_sum(args), sum_of_weights(args)); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // immediate_weighted_mean_impl + // immediate + template + struct immediate_weighted_mean_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type weighted_sample; + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + template + immediate_weighted_mean_impl(Args const &args) + : mean( + numeric::average( + args[parameter::keyword::get() | Sample()] + * numeric::one::value + , numeric::one::value + ) + ) + { + } + + template + void operator ()(Args const &args) + { + // Matthias: + // need to pass the argument pack since the weight might be an external + // accumulator set passed as a named parameter + Weight w_sum = sum_of_weights(args); + Weight w = args[weight]; + weighted_sample const &s = args[parameter::keyword::get()] * w; + this->mean = numeric::average(this->mean * (w_sum - w) + s, w_sum); + } + + result_type result(dont_care) const + { + return this->mean; + } + + private: + result_type mean; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_mean +// tag::immediate_weighted_mean +// +namespace tag +{ + struct weighted_mean + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_mean_impl impl; + }; + struct immediate_weighted_mean + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::immediate_weighted_mean_impl impl; + }; + template + struct weighted_mean_of_variates + : depends_on > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_mean_impl impl; + }; + template + struct immediate_weighted_mean_of_variates + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::immediate_weighted_mean_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_mean +// extract::weighted_mean_of_variates +// +namespace extract +{ + extractor const weighted_mean = {}; + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, weighted_mean_of_variates, (typename)(typename)) +} + +using extract::weighted_mean; +using extract::weighted_mean_of_variates; + +// weighted_mean(lazy) -> weighted_mean +template<> +struct as_feature +{ + typedef tag::weighted_mean type; +}; + +// weighted_mean(immediate) -> immediate_weighted_mean +template<> +struct as_feature +{ + typedef tag::immediate_weighted_mean type; +}; + +// weighted_mean_of_variates(lazy) -> weighted_mean_of_variates +template +struct as_feature(lazy)> +{ + typedef tag::weighted_mean_of_variates type; +}; + +// weighted_mean_of_variates(immediate) -> immediate_weighted_mean_of_variates +template +struct as_feature(immediate)> +{ + typedef tag::immediate_weighted_mean_of_variates type; +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_median.hpp b/win32/include/boost/accumulators/statistics/weighted_median.hpp new file mode 100755 index 000000000..72eb52276 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_median.hpp @@ -0,0 +1,235 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_median.hpp +// +// Copyright 2006 Eric Niebler, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MEDIAN_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MEDIAN_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_median_impl + // + /** + @brief Median estimation for weighted samples based on the \f$P^2\f$ quantile estimator + + The \f$P^2\f$ algorithm for weighted samples is invoked with a quantile probability of 0.5. + */ + template + struct weighted_median_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + weighted_median_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + return weighted_p_square_quantile_for_median(args); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // with_density_weighted_median_impl + // + /** + @brief Median estimation for weighted samples based on the density estimator + + The algorithm determines the bin in which the \f$0.5*cnt\f$-th sample lies, \f$cnt\f$ being + the total number of samples. It returns the approximate horizontal position of this sample, + based on a linear interpolation inside the bin. + */ + template + struct with_density_weighted_median_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + typedef std::vector > histogram_type; + typedef iterator_range range_type; + // for boost::result_of + typedef float_type result_type; + + template + with_density_weighted_median_impl(Args const &args) + : sum(numeric::average(args[sample | Sample()], (std::size_t)1)) + , is_dirty(true) + { + } + + void operator ()(dont_care) + { + this->is_dirty = true; + } + + template + result_type result(Args const &args) const + { + if (this->is_dirty) + { + this->is_dirty = false; + + std::size_t cnt = count(args); + range_type histogram = weighted_density(args); + typename range_type::iterator it = histogram.begin(); + while (this->sum < 0.5 * cnt) + { + this->sum += it->second * cnt; + ++it; + } + --it; + float_type over = numeric::average(this->sum - 0.5 * cnt, it->second * cnt); + this->median = it->first * over + (it + 1)->first * ( 1. - over ); + } + + return this->median; + } + + private: + mutable float_type sum; + mutable bool is_dirty; + mutable float_type median; + }; + + /////////////////////////////////////////////////////////////////////////////// + // with_p_square_cumulative_distribution_weighted_median_impl + // + /** + @brief Median estimation for weighted samples based on the \f$P^2\f$ cumulative distribution estimator + + The algorithm determines the first (leftmost) bin with a height exceeding 0.5. It + returns the approximate horizontal position of where the cumulative distribution + equals 0.5, based on a linear interpolation inside the bin. + */ + template + struct with_p_square_cumulative_distribution_weighted_median_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type weighted_sample; + typedef typename numeric::functional::average::result_type float_type; + typedef std::vector > histogram_type; + typedef iterator_range range_type; + // for boost::result_of + typedef float_type result_type; + + with_p_square_cumulative_distribution_weighted_median_impl(dont_care) + : is_dirty(true) + { + } + + void operator ()(dont_care) + { + this->is_dirty = true; + } + + template + result_type result(Args const &args) const + { + if (this->is_dirty) + { + this->is_dirty = false; + + range_type histogram = weighted_p_square_cumulative_distribution(args); + typename range_type::iterator it = histogram.begin(); + while (it->second < 0.5) + { + ++it; + } + float_type over = numeric::average(it->second - 0.5, it->second - (it - 1)->second); + this->median = it->first * over + (it + 1)->first * ( 1. - over ); + } + + return this->median; + } + private: + mutable bool is_dirty; + mutable float_type median; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_median +// tag::with_density_weighted_median +// tag::with_p_square_cumulative_distribution_weighted_median +// +namespace tag +{ + struct weighted_median + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_median_impl impl; + }; + struct with_density_weighted_median + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::with_density_weighted_median_impl impl; + }; + struct with_p_square_cumulative_distribution_weighted_median + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::with_p_square_cumulative_distribution_weighted_median_impl impl; + }; + +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_median +// +namespace extract +{ + extractor const weighted_median = {}; +} + +using extract::weighted_median; +// weighted_median(with_p_square_quantile) -> weighted_median +template<> +struct as_feature +{ + typedef tag::weighted_median type; +}; + +// weighted_median(with_density) -> with_density_weighted_median +template<> +struct as_feature +{ + typedef tag::with_density_weighted_median type; +}; + +// weighted_median(with_p_square_cumulative_distribution) -> with_p_square_cumulative_distribution_weighted_median +template<> +struct as_feature +{ + typedef tag::with_p_square_cumulative_distribution_weighted_median type; +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_moment.hpp b/win32/include/boost/accumulators/statistics/weighted_moment.hpp new file mode 100755 index 000000000..d7e946dc2 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_moment.hpp @@ -0,0 +1,96 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_moment.hpp +// +// Copyright 2006, Eric Niebler, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MOMENT_HPP_EAN_15_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MOMENT_HPP_EAN_15_11_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for pow() +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_moment_impl + template + struct weighted_moment_impl + : accumulator_base // TODO: also depends_on sum of powers + { + BOOST_MPL_ASSERT_RELATION(N::value, >, 0); + typedef typename numeric::functional::multiplies::result_type weighted_sample; + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + template + weighted_moment_impl(Args const &args) + : sum(args[sample | Sample()] * numeric::one::value) + { + } + + template + void operator ()(Args const &args) + { + this->sum += args[weight] * numeric::pow(args[sample], N()); + } + + template + result_type result(Args const &args) const + { + return numeric::average(this->sum, sum_of_weights(args)); + } + + private: + weighted_sample sum; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_moment +// +namespace tag +{ + template + struct weighted_moment + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_moment_impl, mpl::_1, mpl::_2> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_moment +// +namespace extract +{ + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, weighted_moment, (int)) +} + +using extract::weighted_moment; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_p_square_cumulative_distribution.hpp b/win32/include/boost/accumulators/statistics/weighted_p_square_cumulative_distribution.hpp new file mode 100755 index 000000000..4c9b19107 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_p_square_cumulative_distribution.hpp @@ -0,0 +1,260 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_p_square_cumulative_distribution.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for named parameter p_square_cumulative_distribution_num_cells + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_p_square_cumulative_distribution_impl + // cumulative distribution calculation (as histogram) + /** + @brief Histogram calculation of the cumulative distribution with the \f$P^2\f$ algorithm for weighted samples + + A histogram of the sample cumulative distribution is computed dynamically without storing samples + based on the \f$ P^2 \f$ algorithm for weighted samples. The returned histogram has a specifiable + amount (num_cells) equiprobable (and not equal-sized) cells. + + Note that applying importance sampling results in regions to be more and other regions to be less + accurately estimated than without importance sampling, i.e., with unweighted samples. + + For further details, see + + R. Jain and I. Chlamtac, The P^2 algorithmus for dynamic calculation of quantiles and + histograms without storing observations, Communications of the ACM, + Volume 28 (October), Number 10, 1985, p. 1076-1085. + + @param p_square_cumulative_distribution_num_cells + */ + template + struct weighted_p_square_cumulative_distribution_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type weighted_sample; + typedef typename numeric::functional::average::result_type float_type; + typedef std::vector > histogram_type; + typedef std::vector array_type; + // for boost::result_of + typedef iterator_range result_type; + + template + weighted_p_square_cumulative_distribution_impl(Args const &args) + : num_cells(args[p_square_cumulative_distribution_num_cells]) + , heights(num_cells + 1) + , actual_positions(num_cells + 1) + , desired_positions(num_cells + 1) + , histogram(num_cells + 1) + , is_dirty(true) + { + } + + template + void operator ()(Args const &args) + { + this->is_dirty = true; + + std::size_t cnt = count(args); + std::size_t sample_cell = 1; // k + std::size_t b = this->num_cells; + + // accumulate num_cells + 1 first samples + if (cnt <= b + 1) + { + this->heights[cnt - 1] = args[sample]; + this->actual_positions[cnt - 1] = args[weight]; + + // complete the initialization of heights by sorting + if (cnt == b + 1) + { + //std::sort(this->heights.begin(), this->heights.end()); + + // TODO: we need to sort the initial samples (in heights) in ascending order and + // sort their weights (in actual_positions) the same way. The following lines do + // it, but there must be a better and more efficient way of doing this. + typename array_type::iterator it_begin, it_end, it_min; + + it_begin = this->heights.begin(); + it_end = this->heights.end(); + + std::size_t pos = 0; + + while (it_begin != it_end) + { + it_min = std::min_element(it_begin, it_end); + std::size_t d = std::distance(it_begin, it_min); + std::swap(*it_begin, *it_min); + std::swap(this->actual_positions[pos], this->actual_positions[pos + d]); + ++it_begin; + ++pos; + } + + // calculate correct initial actual positions + for (std::size_t i = 1; i < b; ++i) + { + this->actual_positions[i] += this->actual_positions[i - 1]; + } + } + } + else + { + // find cell k such that heights[k-1] <= args[sample] < heights[k] and adjust extreme values + if (args[sample] < this->heights[0]) + { + this->heights[0] = args[sample]; + this->actual_positions[0] = args[weight]; + sample_cell = 1; + } + else if (this->heights[b] <= args[sample]) + { + this->heights[b] = args[sample]; + sample_cell = b; + } + else + { + typename array_type::iterator it; + it = std::upper_bound( + this->heights.begin() + , this->heights.end() + , args[sample] + ); + + sample_cell = std::distance(this->heights.begin(), it); + } + + // increment positions of markers above sample_cell + for (std::size_t i = sample_cell; i < b + 1; ++i) + { + this->actual_positions[i] += args[weight]; + } + + // determine desired marker positions + for (std::size_t i = 1; i < b + 1; ++i) + { + this->desired_positions[i] = this->actual_positions[0] + + numeric::average((i-1) * (sum_of_weights(args) - this->actual_positions[0]), b); + } + + // adjust heights of markers 2 to num_cells if necessary + for (std::size_t i = 1; i < b; ++i) + { + // offset to desire position + float_type d = this->desired_positions[i] - this->actual_positions[i]; + + // offset to next position + float_type dp = this->actual_positions[i + 1] - this->actual_positions[i]; + + // offset to previous position + float_type dm = this->actual_positions[i - 1] - this->actual_positions[i]; + + // height ds + float_type hp = (this->heights[i + 1] - this->heights[i]) / dp; + float_type hm = (this->heights[i - 1] - this->heights[i]) / dm; + + if ( ( d >= 1. && dp > 1. ) || ( d <= -1. && dm < -1. ) ) + { + short sign_d = static_cast(d / std::abs(d)); + + // try adjusting heights[i] using p-squared formula + float_type h = this->heights[i] + sign_d / (dp - dm) * ( (sign_d - dm) * hp + (dp - sign_d) * hm ); + + if ( this->heights[i - 1] < h && h < this->heights[i + 1] ) + { + this->heights[i] = h; + } + else + { + // use linear formula + if (d>0) + { + this->heights[i] += hp; + } + if (d<0) + { + this->heights[i] -= hm; + } + } + this->actual_positions[i] += sign_d; + } + } + } + } + + template + result_type result(Args const &args) const + { + if (this->is_dirty) + { + this->is_dirty = false; + + // creates a vector of std::pair where each pair i holds + // the values heights[i] (x-axis of histogram) and + // actual_positions[i] / sum_of_weights (y-axis of histogram) + + for (std::size_t i = 0; i < this->histogram.size(); ++i) + { + this->histogram[i] = std::make_pair(this->heights[i], numeric::average(this->actual_positions[i], sum_of_weights(args))); + } + } + + return make_iterator_range(this->histogram); + } + + private: + std::size_t num_cells; // number of cells b + array_type heights; // q_i + array_type actual_positions; // n_i + array_type desired_positions; // n'_i + mutable histogram_type histogram; // histogram + mutable bool is_dirty; + }; + +} // namespace detail + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_p_square_cumulative_distribution +// +namespace tag +{ + struct weighted_p_square_cumulative_distribution + : depends_on + , p_square_cumulative_distribution_num_cells + { + typedef accumulators::impl::weighted_p_square_cumulative_distribution_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_p_square_cumulative_distribution +// +namespace extract +{ + extractor const weighted_p_square_cumulative_distribution = {}; +} + +using extract::weighted_p_square_cumulative_distribution; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_p_square_quantile.hpp b/win32/include/boost/accumulators/statistics/weighted_p_square_quantile.hpp new file mode 100755 index 000000000..7d0a15c27 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_p_square_quantile.hpp @@ -0,0 +1,251 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_p_square_quantile.hpp +// +// Copyright 2005 Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_QUANTILE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_QUANTILE_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl { + /////////////////////////////////////////////////////////////////////////////// + // weighted_p_square_quantile_impl + // single quantile estimation with weighted samples + /** + @brief Single quantile estimation with the \f$P^2\f$ algorithm for weighted samples + + This version of the \f$P^2\f$ algorithm extends the \f$P^2\f$ algorithm to support weighted samples. + The \f$P^2\f$ algorithm estimates a quantile dynamically without storing samples. Instead of + storing the whole sample cumulative distribution, only five points (markers) are stored. The heights + of these markers are the minimum and the maximum of the samples and the current estimates of the + \f$(p/2)\f$-, \f$p\f$ - and \f$(1+p)/2\f$ -quantiles. Their positions are equal to the number + of samples that are smaller or equal to the markers. Each time a new sample is added, the + positions of the markers are updated and if necessary their heights are adjusted using a piecewise- + parabolic formula. + + For further details, see + + R. Jain and I. Chlamtac, The P^2 algorithmus for dynamic calculation of quantiles and + histograms without storing observations, Communications of the ACM, + Volume 28 (October), Number 10, 1985, p. 1076-1085. + + @param quantile_probability + */ + template + struct weighted_p_square_quantile_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type weighted_sample; + typedef typename numeric::functional::average::result_type float_type; + typedef array array_type; + // for boost::result_of + typedef float_type result_type; + + template + weighted_p_square_quantile_impl(Args const &args) + : p(is_same::value ? 0.5 : args[quantile_probability | 0.5]) + , heights() + , actual_positions() + , desired_positions() + { + } + + template + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + + // accumulate 5 first samples + if (cnt <= 5) + { + this->heights[cnt - 1] = args[sample]; + + // In this initialization phase, actual_positions stores the weights of the + // inital samples that are needed at the end of the initialization phase to + // compute the correct initial positions of the markers. + this->actual_positions[cnt - 1] = args[weight]; + + // complete the initialization of heights and actual_positions by sorting + if (cnt == 5) + { + // TODO: we need to sort the initial samples (in heights) in ascending order and + // sort their weights (in actual_positions) the same way. The following lines do + // it, but there must be a better and more efficient way of doing this. + typename array_type::iterator it_begin, it_end, it_min; + + it_begin = this->heights.begin(); + it_end = this->heights.end(); + + std::size_t pos = 0; + + while (it_begin != it_end) + { + it_min = std::min_element(it_begin, it_end); + std::size_t d = std::distance(it_begin, it_min); + std::swap(*it_begin, *it_min); + std::swap(this->actual_positions[pos], this->actual_positions[pos + d]); + ++it_begin; + ++pos; + } + + // calculate correct initial actual positions + for (std::size_t i = 1; i < 5; ++i) + { + this->actual_positions[i] += this->actual_positions[i - 1]; + } + } + } + else + { + std::size_t sample_cell = 1; // k + + // find cell k such that heights[k-1] <= args[sample] < heights[k] and adjust extreme values + if (args[sample] < this->heights[0]) + { + this->heights[0] = args[sample]; + this->actual_positions[0] = args[weight]; + sample_cell = 1; + } + else if (this->heights[4] <= args[sample]) + { + this->heights[4] = args[sample]; + sample_cell = 4; + } + else + { + typedef typename array_type::iterator iterator; + iterator it = std::upper_bound( + this->heights.begin() + , this->heights.end() + , args[sample] + ); + + sample_cell = std::distance(this->heights.begin(), it); + } + + // increment positions of markers above sample_cell + for (std::size_t i = sample_cell; i < 5; ++i) + { + this->actual_positions[i] += args[weight]; + } + + // update desired positions for all markers + this->desired_positions[0] = this->actual_positions[0]; + this->desired_positions[1] = (sum_of_weights(args) - this->actual_positions[0]) + * this->p/2. + this->actual_positions[0]; + this->desired_positions[2] = (sum_of_weights(args) - this->actual_positions[0]) + * this->p + this->actual_positions[0]; + this->desired_positions[3] = (sum_of_weights(args) - this->actual_positions[0]) + * (1. + this->p)/2. + this->actual_positions[0]; + this->desired_positions[4] = sum_of_weights(args); + + // adjust height and actual positions of markers 1 to 3 if necessary + for (std::size_t i = 1; i <= 3; ++i) + { + // offset to desired positions + float_type d = this->desired_positions[i] - this->actual_positions[i]; + + // offset to next position + float_type dp = this->actual_positions[i + 1] - this->actual_positions[i]; + + // offset to previous position + float_type dm = this->actual_positions[i - 1] - this->actual_positions[i]; + + // height ds + float_type hp = (this->heights[i + 1] - this->heights[i]) / dp; + float_type hm = (this->heights[i - 1] - this->heights[i]) / dm; + + if ( ( d >= 1. && dp > 1. ) || ( d <= -1. && dm < -1. ) ) + { + short sign_d = static_cast(d / std::abs(d)); + + // try adjusting heights[i] using p-squared formula + float_type h = this->heights[i] + sign_d / (dp - dm) * ( (sign_d - dm) * hp + (dp - sign_d) * hm ); + + if ( this->heights[i - 1] < h && h < this->heights[i + 1] ) + { + this->heights[i] = h; + } + else + { + // use linear formula + if (d>0) + { + this->heights[i] += hp; + } + if (d<0) + { + this->heights[i] -= hm; + } + } + this->actual_positions[i] += sign_d; + } + } + } + } + + result_type result(dont_care) const + { + return this->heights[2]; + } + + private: + float_type p; // the quantile probability p + array_type heights; // q_i + array_type actual_positions; // n_i + array_type desired_positions; // n'_i + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_p_square_quantile +// +namespace tag +{ + struct weighted_p_square_quantile + : depends_on + { + typedef accumulators::impl::weighted_p_square_quantile_impl impl; + }; + struct weighted_p_square_quantile_for_median + : depends_on + { + typedef accumulators::impl::weighted_p_square_quantile_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_p_square_quantile +// extract::weighted_p_square_quantile_for_median +// +namespace extract +{ + extractor const weighted_p_square_quantile = {}; + extractor const weighted_p_square_quantile_for_median = {}; +} + +using extract::weighted_p_square_quantile; +using extract::weighted_p_square_quantile_for_median; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_peaks_over_threshold.hpp b/win32/include/boost/accumulators/statistics/weighted_peaks_over_threshold.hpp new file mode 100755 index 000000000..a059e03f7 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_peaks_over_threshold.hpp @@ -0,0 +1,286 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_peaks_over_threshold.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_PEAKS_OVER_THRESHOLD_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_PEAKS_OVER_THRESHOLD_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for named parameters pot_threshold_value and pot_threshold_probability +#include +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +namespace impl +{ + + /////////////////////////////////////////////////////////////////////////////// + // weighted_peaks_over_threshold_impl + // works with an explicit threshold value and does not depend on order statistics of weighted samples + /** + @brief Weighted Peaks over Threshold Method for Weighted Quantile and Weighted Tail Mean Estimation + + @sa peaks_over_threshold_impl + + @param quantile_probability + @param pot_threshold_value + */ + template + struct weighted_peaks_over_threshold_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type weighted_sample; + typedef typename numeric::functional::average::result_type float_type; + // for boost::result_of + typedef boost::tuple result_type; + + template + weighted_peaks_over_threshold_impl(Args const &args) + : sign_((is_same::value) ? -1 : 1) + , mu_(sign_ * numeric::average(args[sample | Sample()], (std::size_t)1)) + , sigma2_(numeric::average(args[sample | Sample()], (std::size_t)1)) + , w_sum_(numeric::average(args[weight | Weight()], (std::size_t)1)) + , threshold_(sign_ * args[pot_threshold_value]) + , fit_parameters_(boost::make_tuple(0., 0., 0.)) + , is_dirty_(true) + { + } + + template + void operator ()(Args const &args) + { + this->is_dirty_ = true; + + if (this->sign_ * args[sample] > this->threshold_) + { + this->mu_ += args[weight] * args[sample]; + this->sigma2_ += args[weight] * args[sample] * args[sample]; + this->w_sum_ += args[weight]; + } + } + + template + result_type result(Args const &args) const + { + if (this->is_dirty_) + { + this->is_dirty_ = false; + + this->mu_ = this->sign_ * numeric::average(this->mu_, this->w_sum_); + this->sigma2_ = numeric::average(this->sigma2_, this->w_sum_); + this->sigma2_ -= this->mu_ * this->mu_; + + float_type threshold_probability = numeric::average(sum_of_weights(args) - this->w_sum_, sum_of_weights(args)); + + float_type tmp = numeric::average(( this->mu_ - this->threshold_ )*( this->mu_ - this->threshold_ ), this->sigma2_); + float_type xi_hat = 0.5 * ( 1. - tmp ); + float_type beta_hat = 0.5 * ( this->mu_ - this->threshold_ ) * ( 1. + tmp ); + float_type beta_bar = beta_hat * std::pow(1. - threshold_probability, xi_hat); + float_type u_bar = this->threshold_ - beta_bar * ( std::pow(1. - threshold_probability, -xi_hat) - 1.)/xi_hat; + this->fit_parameters_ = boost::make_tuple(u_bar, beta_bar, xi_hat); + } + + return this->fit_parameters_; + } + + private: + short sign_; // for left tail fitting, mirror the extreme values + mutable float_type mu_; // mean of samples above threshold + mutable float_type sigma2_; // variance of samples above threshold + mutable float_type w_sum_; // sum of weights of samples above threshold + float_type threshold_; + mutable result_type fit_parameters_; // boost::tuple that stores fit parameters + mutable bool is_dirty_; + }; + + /////////////////////////////////////////////////////////////////////////////// + // weighted_peaks_over_threshold_prob_impl + // determines threshold from a given threshold probability using order statistics + /** + @brief Peaks over Threshold Method for Quantile and Tail Mean Estimation + + @sa weighted_peaks_over_threshold_impl + + @param quantile_probability + @param pot_threshold_probability + */ + template + struct weighted_peaks_over_threshold_prob_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type weighted_sample; + typedef typename numeric::functional::average::result_type float_type; + // for boost::result_of + typedef boost::tuple result_type; + + template + weighted_peaks_over_threshold_prob_impl(Args const &args) + : sign_((is_same::value) ? -1 : 1) + , mu_(sign_ * numeric::average(args[sample | Sample()], (std::size_t)1)) + , sigma2_(numeric::average(args[sample | Sample()], (std::size_t)1)) + , threshold_probability_(args[pot_threshold_probability]) + , fit_parameters_(boost::make_tuple(0., 0., 0.)) + , is_dirty_(true) + { + } + + void operator ()(dont_care) + { + this->is_dirty_ = true; + } + + template + result_type result(Args const &args) const + { + if (this->is_dirty_) + { + this->is_dirty_ = false; + + float_type threshold = sum_of_weights(args) + * ( ( is_same::value ) ? this->threshold_probability_ : 1. - this->threshold_probability_ ); + + std::size_t n = 0; + Weight sum = Weight(0); + + while (sum < threshold) + { + if (n < static_cast(tail_weights(args).size())) + { + mu_ += *(tail_weights(args).begin() + n) * *(tail(args).begin() + n); + sigma2_ += *(tail_weights(args).begin() + n) * *(tail(args).begin() + n) * (*(tail(args).begin() + n)); + sum += *(tail_weights(args).begin() + n); + n++; + } + else + { + if (std::numeric_limits::has_quiet_NaN) + { + return boost::make_tuple( + std::numeric_limits::quiet_NaN() + , std::numeric_limits::quiet_NaN() + , std::numeric_limits::quiet_NaN() + ); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + return boost::make_tuple(Sample(0), Sample(0), Sample(0)); + } + } + } + + float_type u = *(tail(args).begin() + n - 1) * this->sign_; + + + this->mu_ = this->sign_ * numeric::average(this->mu_, sum); + this->sigma2_ = numeric::average(this->sigma2_, sum); + this->sigma2_ -= this->mu_ * this->mu_; + + if (is_same::value) + this->threshold_probability_ = 1. - this->threshold_probability_; + + float_type tmp = numeric::average(( this->mu_ - u )*( this->mu_ - u ), this->sigma2_); + float_type xi_hat = 0.5 * ( 1. - tmp ); + float_type beta_hat = 0.5 * ( this->mu_ - u ) * ( 1. + tmp ); + float_type beta_bar = beta_hat * std::pow(1. - threshold_probability_, xi_hat); + float_type u_bar = u - beta_bar * ( std::pow(1. - threshold_probability_, -xi_hat) - 1.)/xi_hat; + this->fit_parameters_ = boost::make_tuple(u_bar, beta_bar, xi_hat); + + } + + return this->fit_parameters_; + } + + private: + short sign_; // for left tail fitting, mirror the extreme values + mutable float_type mu_; // mean of samples above threshold u + mutable float_type sigma2_; // variance of samples above threshold u + mutable float_type threshold_probability_; + mutable result_type fit_parameters_; // boost::tuple that stores fit parameters + mutable bool is_dirty_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_peaks_over_threshold +// +namespace tag +{ + template + struct weighted_peaks_over_threshold + : depends_on + , pot_threshold_value + { + /// INTERNAL ONLY + typedef accumulators::impl::weighted_peaks_over_threshold_impl impl; + }; + + template + struct weighted_peaks_over_threshold_prob + : depends_on > + , pot_threshold_probability + { + /// INTERNAL ONLY + typedef accumulators::impl::weighted_peaks_over_threshold_prob_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_peaks_over_threshold +// +namespace extract +{ + extractor const weighted_peaks_over_threshold = {}; +} + +using extract::weighted_peaks_over_threshold; + +// weighted_peaks_over_threshold(with_threshold_value) -> weighted_peaks_over_threshold +template +struct as_feature(with_threshold_value)> +{ + typedef tag::weighted_peaks_over_threshold type; +}; + +// weighted_peaks_over_threshold(with_threshold_probability) -> weighted_peaks_over_threshold_prob +template +struct as_feature(with_threshold_probability)> +{ + typedef tag::weighted_peaks_over_threshold_prob type; +}; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_skewness.hpp b/win32/include/boost/accumulators/statistics/weighted_skewness.hpp new file mode 100755 index 000000000..f98c24234 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_skewness.hpp @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_skewness.hpp +// +// Copyright 2006 Olivier Gygi, Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_SKEWNESS_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_SKEWNESS_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_skewness_impl + /** + @brief Skewness estimation for weighted samples + + The skewness of a sample distribution is defined as the ratio of the 3rd central moment and the \f$ 3/2 \f$-th power $ + of the 2nd central moment (the variance) of the samples. The skewness can also be expressed by the simple moments: + + \f[ + \hat{g}_1 = + \frac + {\widehat{m}_n^{(3)}-3\widehat{m}_n^{(2)}\hat{\mu}_n+2\hat{\mu}_n^3} + {\left(\widehat{m}_n^{(2)} - \hat{\mu}_n^{2}\right)^{3/2}} + \f] + + where \f$ \widehat{m}_n^{(i)} \f$ are the \f$ i \f$-th moment and \f$ \hat{\mu}_n \f$ the mean (first moment) of the + \f$ n \f$ samples. + + The skewness estimator for weighted samples is formally identical to the estimator for unweighted samples, except that + the weighted counterparts of all measures it depends on are to be taken. + */ + template + struct weighted_skewness_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type weighted_sample; + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + weighted_skewness_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + return numeric::average( + weighted_moment<3>(args) + - 3. * weighted_moment<2>(args) * weighted_mean(args) + + 2. * weighted_mean(args) * weighted_mean(args) * weighted_mean(args) + , ( weighted_moment<2>(args) - weighted_mean(args) * weighted_mean(args) ) + * std::sqrt( weighted_moment<2>(args) - weighted_mean(args) * weighted_mean(args) ) + ); + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_skewness +// +namespace tag +{ + struct weighted_skewness + : depends_on, weighted_moment<3> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_skewness_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_skewness +// +namespace extract +{ + extractor const weighted_skewness = {}; +} + +using extract::weighted_skewness; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_sum.hpp b/win32/include/boost/accumulators/statistics/weighted_sum.hpp new file mode 100755 index 000000000..627bf6246 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_sum.hpp @@ -0,0 +1,113 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_sum.hpp +// +// Copyright 2006 Eric Niebler, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_SUM_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_SUM_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_sum_impl + template + struct weighted_sum_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type weighted_sample; + + // for boost::result_of + typedef weighted_sample result_type; + + template + weighted_sum_impl(Args const &args) + : weighted_sum_( + args[parameter::keyword::get() | Sample()] + * numeric::one::value + ) + { + } + + template + void operator ()(Args const &args) + { + // what about overflow? + this->weighted_sum_ += args[parameter::keyword::get()] * args[weight]; + } + + result_type result(dont_care) const + { + return this->weighted_sum_; + } + + private: + + weighted_sample weighted_sum_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_sum +// +namespace tag +{ + struct weighted_sum + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_sum_impl impl; + }; + + template + struct weighted_sum_of_variates + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_sum_impl impl; + }; + + struct abstract_weighted_sum_of_variates + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_sum +// +namespace extract +{ + extractor const weighted_sum = {}; + extractor const weighted_sum_of_variates = {}; +} + +using extract::weighted_sum; +using extract::weighted_sum_of_variates; + +template +struct feature_of > + : feature_of +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_tail_mean.hpp b/win32/include/boost/accumulators/statistics/weighted_tail_mean.hpp new file mode 100755 index 000000000..3632c1c74 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_tail_mean.hpp @@ -0,0 +1,167 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_tail_mean.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_MEAN_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_MEAN_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +namespace impl +{ + + /////////////////////////////////////////////////////////////////////////////// + // coherent_weighted_tail_mean_impl + // + // TODO + + /////////////////////////////////////////////////////////////////////////////// + // non_coherent_weighted_tail_mean_impl + // + /** + @brief Estimation of the (non-coherent) weighted tail mean based on order statistics (for both left and right tails) + + + + An estimation of the non-coherent, weighted tail mean \f$\widehat{NCTM}_{n,\alpha}(X)\f$ is given by the weighted mean + of the + + \f[ + \lambda = \inf\left\{ l \left| \frac{1}{\bar{w}_n}\sum_{i=1}^{l} w_i \geq \alpha \right. \right\} + \f] + + smallest samples (left tail) or the weighted mean of the + + \f[ + n + 1 - \rho = n + 1 - \sup\left\{ r \left| \frac{1}{\bar{w}_n}\sum_{i=r}^{n} w_i \geq (1 - \alpha) \right. \right\} + \f] + + largest samples (right tail) above a quantile \f$\hat{q}_{\alpha}\f$ of level \f$\alpha\f$, \f$n\f$ being the total number of sample + and \f$\bar{w}_n\f$ the sum of all \f$n\f$ weights: + + \f[ + \widehat{NCTM}_{n,\alpha}^{\mathrm{left}}(X) = \frac{\sum_{i=1}^{\lambda} w_i X_{i:n}}{\sum_{i=1}^{\lambda} w_i}, + \f] + + \f[ + \widehat{NCTM}_{n,\alpha}^{\mathrm{right}}(X) = \frac{\sum_{i=\rho}^n w_i X_{i:n}}{\sum_{i=\rho}^n w_i}. + \f] + + @param quantile_probability + */ + template + struct non_coherent_weighted_tail_mean_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type weighted_sample; + typedef typename numeric::functional::average::result_type float_type; + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + non_coherent_weighted_tail_mean_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + float_type threshold = sum_of_weights(args) + * ( ( is_same::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ); + + std::size_t n = 0; + Weight sum = Weight(0); + + while (sum < threshold) + { + if (n < static_cast(tail_weights(args).size())) + { + sum += *(tail_weights(args).begin() + n); + n++; + } + else + { + if (std::numeric_limits::has_quiet_NaN) + { + return std::numeric_limits::quiet_NaN(); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + return result_type(0); + } + } + } + + return numeric::average( + std::inner_product( + tail(args).begin() + , tail(args).begin() + n + , tail_weights(args).begin() + , weighted_sample(0) + ) + , sum + ); + } + }; + +} // namespace impl + + +/////////////////////////////////////////////////////////////////////////////// +// tag::non_coherent_weighted_tail_mean<> +// +namespace tag +{ + template + struct non_coherent_weighted_tail_mean + : depends_on > + { + typedef accumulators::impl::non_coherent_weighted_tail_mean_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::non_coherent_weighted_tail_mean; +// +namespace extract +{ + extractor const non_coherent_weighted_tail_mean = {}; +} + +using extract::non_coherent_weighted_tail_mean; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_tail_quantile.hpp b/win32/include/boost/accumulators/statistics/weighted_tail_quantile.hpp new file mode 100755 index 000000000..d3f582483 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_tail_quantile.hpp @@ -0,0 +1,144 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_tail_quantile.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_QUANTILE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_QUANTILE_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_tail_quantile_impl + // Tail quantile estimation based on order statistics of weighted samples + /** + @brief Tail quantile estimation based on order statistics of weighted samples (for both left and right tails) + + An estimator \f$\hat{q}\f$ of tail quantiles with level \f$\alpha\f$ based on order statistics + \f$X_{1:n} \leq X_{2:n} \leq\dots\leq X_{n:n}\f$ of weighted samples are given by \f$X_{\lambda:n}\f$ (left tail) + and \f$X_{\rho:n}\f$ (right tail), where + + \f[ + \lambda = \inf\left\{ l \left| \frac{1}{\bar{w}_n}\sum_{i=1}^{l} w_i \geq \alpha \right. \right\} + \f] + + and + + \f[ + \rho = \sup\left\{ r \left| \frac{1}{\bar{w}_n}\sum_{i=r}^{n} w_i \geq (1 - \alpha) \right. \right\}, + \f] + + \f$n\f$ being the number of samples and \f$\bar{w}_n\f$ the sum of all weights. + + @param quantile_probability + */ + template + struct weighted_tail_quantile_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + // for boost::result_of + typedef Sample result_type; + + weighted_tail_quantile_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + float_type threshold = sum_of_weights(args) + * ( ( is_same::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ); + + std::size_t n = 0; + Weight sum = Weight(0); + + while (sum < threshold) + { + if (n < static_cast(tail_weights(args).size())) + { + sum += *(tail_weights(args).begin() + n); + n++; + } + else + { + if (std::numeric_limits::has_quiet_NaN) + { + return std::numeric_limits::quiet_NaN(); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + return Sample(0); + } + } + } + + // Note that the cached samples of the left are sorted in ascending order, + // whereas the samples of the right tail are sorted in descending order + return *(boost::begin(tail(args)) + n - 1); + } + }; +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_tail_quantile<> +// +namespace tag +{ + template + struct weighted_tail_quantile + : depends_on > + { + /// INTERNAL ONLY + typedef accumulators::impl::weighted_tail_quantile_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_tail_quantile +// +namespace extract +{ + extractor const weighted_tail_quantile = {}; +} + +using extract::weighted_tail_quantile; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_tail_variate_means.hpp b/win32/include/boost/accumulators/statistics/weighted_tail_variate_means.hpp new file mode 100755 index 000000000..2c1ebad34 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_tail_variate_means.hpp @@ -0,0 +1,239 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_tail_variate_means.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_VARIATE_MEANS_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_VARIATE_MEANS_HPP_DE_01_01_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost +{ + // for _BinaryOperatrion2 in std::inner_product below + // mutliplies two values and promotes the result to double + namespace numeric { namespace functional + { + /////////////////////////////////////////////////////////////////////////////// + // numeric::functional::multiply_and_promote_to_double + template + struct multiply_and_promote_to_double + : multiplies + { + }; + }} +} + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /** + @brief Estimation of the absolute and relative weighted tail variate means (for both left and right tails) + + For all \f$j\f$-th variates associated to the + + \f[ + \lambda = \inf\left\{ l \left| \frac{1}{\bar{w}_n}\sum_{i=1}^{l} w_i \geq \alpha \right. \right\} + \f] + + smallest samples (left tail) or the weighted mean of the + + \f[ + n + 1 - \rho = n + 1 - \sup\left\{ r \left| \frac{1}{\bar{w}_n}\sum_{i=r}^{n} w_i \geq (1 - \alpha) \right. \right\} + \f] + + largest samples (right tail), the absolute weighted tail means \f$\widehat{ATM}_{n,\alpha}(X, j)\f$ + are computed and returned as an iterator range. Alternatively, the relative weighted tail means + \f$\widehat{RTM}_{n,\alpha}(X, j)\f$ are returned, which are the absolute weighted tail means + normalized with the weighted (non-coherent) sample tail mean \f$\widehat{NCTM}_{n,\alpha}(X)\f$. + + \f[ + \widehat{ATM}_{n,\alpha}^{\mathrm{right}}(X, j) = + \frac{1}{\sum_{i=\rho}^n w_i} + \sum_{i=\rho}^n w_i \xi_{j,i} + \f] + + \f[ + \widehat{ATM}_{n,\alpha}^{\mathrm{left}}(X, j) = + \frac{1}{\sum_{i=1}^{\lambda}} + \sum_{i=1}^{\lambda} w_i \xi_{j,i} + \f] + + \f[ + \widehat{RTM}_{n,\alpha}^{\mathrm{right}}(X, j) = + \frac{\sum_{i=\rho}^n w_i \xi_{j,i}} + {\sum_{i=\rho}^n w_i \widehat{NCTM}_{n,\alpha}^{\mathrm{right}}(X)} + \f] + + \f[ + \widehat{RTM}_{n,\alpha}^{\mathrm{left}}(X, j) = + \frac{\sum_{i=1}^{\lambda} w_i \xi_{j,i}} + {\sum_{i=1}^{\lambda} w_i \widehat{NCTM}_{n,\alpha}^{\mathrm{left}}(X)} + \f] + */ + + /////////////////////////////////////////////////////////////////////////////// + // weighted_tail_variate_means_impl + // by default: absolute weighted_tail_variate_means + template + struct weighted_tail_variate_means_impl + : accumulator_base + { + typedef typename numeric::functional::average::result_type float_type; + typedef typename numeric::functional::average::result_type, Weight>::result_type array_type; + // for boost::result_of + typedef iterator_range result_type; + + weighted_tail_variate_means_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + float_type threshold = sum_of_weights(args) + * ( ( is_same::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ); + + std::size_t n = 0; + Weight sum = Weight(0); + + while (sum < threshold) + { + if (n < static_cast(tail_weights(args).size())) + { + sum += *(tail_weights(args).begin() + n); + n++; + } + else + { + if (std::numeric_limits::has_quiet_NaN) + { + std::fill( + this->tail_means_.begin() + , this->tail_means_.end() + , std::numeric_limits::quiet_NaN() + ); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + } + } + } + + std::size_t num_variates = tail_variate(args).begin()->size(); + + this->tail_means_.clear(); + this->tail_means_.resize(num_variates, Sample(0)); + + this->tail_means_ = std::inner_product( + tail_variate(args).begin() + , tail_variate(args).begin() + n + , tail_weights(args).begin() + , this->tail_means_ + , numeric::functional::plus() + , numeric::functional::multiply_and_promote_to_double() + ); + + float_type factor = sum * ( (is_same::value) ? non_coherent_weighted_tail_mean(args) : 1. ); + + std::transform( + this->tail_means_.begin() + , this->tail_means_.end() + , this->tail_means_.begin() + , std::bind2nd(numeric::functional::divides(), factor) + ); + + return make_iterator_range(this->tail_means_); + } + + private: + + mutable array_type tail_means_; + + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::absolute_weighted_tail_variate_means +// tag::relative_weighted_tail_variate_means +// +namespace tag +{ + template + struct absolute_weighted_tail_variate_means + : depends_on, tail_variate, tail_weights > + { + typedef accumulators::impl::weighted_tail_variate_means_impl impl; + }; + template + struct relative_weighted_tail_variate_means + : depends_on, tail_variate, tail_weights > + { + typedef accumulators::impl::weighted_tail_variate_means_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_tail_variate_means +// extract::relative_weighted_tail_variate_means +// +namespace extract +{ + extractor const weighted_tail_variate_means = {}; + extractor const relative_weighted_tail_variate_means = {}; +} + +using extract::weighted_tail_variate_means; +using extract::relative_weighted_tail_variate_means; + +// weighted_tail_variate_means(absolute) -> absolute_weighted_tail_variate_means +template +struct as_feature(absolute)> +{ + typedef tag::absolute_weighted_tail_variate_means type; +}; + +// weighted_tail_variate_means(relative) -> relative_weighted_tail_variate_means +template +struct as_feature(relative)> +{ + typedef tag::relative_weighted_tail_variate_means type; +}; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif diff --git a/win32/include/boost/accumulators/statistics/weighted_variance.hpp b/win32/include/boost/accumulators/statistics/weighted_variance.hpp new file mode 100755 index 000000000..41b4fb286 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/weighted_variance.hpp @@ -0,0 +1,183 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_variance.hpp +// +// Copyright 2005 Daniel Egloff, Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_VARIANCE_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_VARIANCE_HPP_EAN_28_10_2005 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace impl +{ + //! Lazy calculation of variance of weighted samples. + /*! + The default implementation of the variance of weighted samples is based on the second moment + \f$\widehat{m}_n^{(2)}\f$ (weighted_moment<2>) and the mean\f$ \hat{\mu}_n\f$ (weighted_mean): + \f[ + \hat{\sigma}_n^2 = \widehat{m}_n^{(2)}-\hat{\mu}_n^2, + \f] + where \f$n\f$ is the number of samples. + */ + template + struct lazy_weighted_variance_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type weighted_sample; + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + lazy_weighted_variance_impl(dont_care) {} + + template + result_type result(Args const &args) const + { + extractor const some_mean = {}; + result_type tmp = some_mean(args); + return weighted_moment<2>(args) - tmp * tmp; + } + }; + + //! Iterative calculation of variance of weighted samples. + /*! + Iterative calculation of variance of weighted samples: + \f[ + \hat{\sigma}_n^2 = + \frac{\bar{w}_n - w_n}{\bar{w}_n}\hat{\sigma}_{n - 1}^2 + + \frac{w_n}{\bar{w}_n - w_n}\left(X_n - \hat{\mu}_n\right)^2 + ,\quad n\ge2,\quad\hat{\sigma}_0^2 = 0. + \f] + where \f$\bar{w}_n\f$ is the sum of the \f$n\f$ weights \f$w_i\f$ and \f$\hat{\mu}_n\f$ + the estimate of the mean of the weighted smaples. Note that the sample variance is not defined for + \f$n <= 1\f$. + */ + template + struct weighted_variance_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies::result_type weighted_sample; + // for boost::result_of + typedef typename numeric::functional::average::result_type result_type; + + template + weighted_variance_impl(Args const &args) + : weighted_variance(numeric::average(args[sample | Sample()], numeric::one::value)) + { + } + + template + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + + if(cnt > 1) + { + extractor const some_mean = {}; + + result_type tmp = args[parameter::keyword::get()] - some_mean(args); + + this->weighted_variance = + numeric::average(this->weighted_variance * (sum_of_weights(args) - args[weight]), sum_of_weights(args)) + + numeric::average(tmp * tmp * args[weight], sum_of_weights(args) - args[weight] ); + } + } + + result_type result(dont_care) const + { + return this->weighted_variance; + } + + private: + result_type weighted_variance; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_variance +// tag::immediate_weighted_variance +// +namespace tag +{ + struct lazy_weighted_variance + : depends_on, weighted_mean> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::lazy_weighted_variance_impl impl; + }; + + struct weighted_variance + : depends_on + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_variance_impl impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_variance +// extract::immediate_weighted_variance +// +namespace extract +{ + extractor const lazy_weighted_variance = {}; + extractor const weighted_variance = {}; +} + +using extract::lazy_weighted_variance; +using extract::weighted_variance; + +// weighted_variance(lazy) -> lazy_weighted_variance +template<> +struct as_feature +{ + typedef tag::lazy_weighted_variance type; +}; + +// weighted_variance(immediate) -> weighted_variance +template<> +struct as_feature +{ + typedef tag::weighted_variance type; +}; + +//////////////////////////////////////////////////////////////////////////// +//// droppable_accumulator +//// need to specialize droppable lazy weighted_variance to cache the result at the +//// point the accumulator is dropped. +///// INTERNAL ONLY +///// +//template +//struct droppable_accumulator > +// : droppable_accumulator_base< +// with_cached_result > +// > +//{ +// template +// droppable_accumulator(Args const &args) +// : droppable_accumulator::base(args) +// { +// } +//}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics/with_error.hpp b/win32/include/boost/accumulators/statistics/with_error.hpp new file mode 100755 index 000000000..02d9e27c1 --- /dev/null +++ b/win32/include/boost/accumulators/statistics/with_error.hpp @@ -0,0 +1,44 @@ +/////////////////////////////////////////////////////////////////////////////// +// with_error.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WITH_ERROR_HPP_EAN_01_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WITH_ERROR_HPP_EAN_01_11_2005 + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +namespace detail +{ + template + struct error_of_tag + { + typedef tag::error_of type; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// with_error +// +template +struct with_error + : mpl::transform_view< + mpl::vector + , detail::error_of_tag + > +{ +}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/accumulators/statistics_fwd.hpp b/win32/include/boost/accumulators/statistics_fwd.hpp new file mode 100755 index 000000000..7e0e2c4ab --- /dev/null +++ b/win32/include/boost/accumulators/statistics_fwd.hpp @@ -0,0 +1,397 @@ +/////////////////////////////////////////////////////////////////////////////// +// statistics_fwd.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_STATISTICS_FWD_HPP_EAN_23_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_STATISTICS_FWD_HPP_EAN_23_11_2005 + +#include // for mpl::na +#include +#include +#include +#include +#include + +namespace boost { namespace accumulators +{ + +/////////////////////////////////////////////////////////////////////////////// +// base struct and base extractor for quantiles +namespace tag +{ + struct quantile + : depends_on<> + { + typedef mpl::print impl; + }; +} +namespace extract +{ + extractor const quantile = {}; +} +using extract::quantile; + +/////////////////////////////////////////////////////////////////////////////// +// base struct and base extractor for *coherent* tail means +namespace tag +{ + struct tail_mean + : depends_on<> + { + typedef mpl::print impl; + }; +} +namespace extract +{ + extractor const tail_mean = {}; +} +using extract::tail_mean; + +namespace tag +{ + /////////////////////////////////////////////////////////////////////////////// + // Variates tags + struct weights; + struct covariate1; + struct covariate2; + + /////////////////////////////////////////////////////////////////////////////// + // Statistic tags + struct count; + template + struct covariance; + struct density; + template + struct error_of; + struct extended_p_square; + struct extended_p_square_quantile; + struct extended_p_square_quantile_quadratic; + struct kurtosis; + struct max; + struct mean; + struct immediate_mean; + struct mean_of_weights; + struct immediate_mean_of_weights; + template + struct mean_of_variates; + template + struct immediate_mean_of_variates; + struct median; + struct with_density_median; + struct with_p_square_cumulative_distribution_median; + struct min; + template + struct moment; + template + struct peaks_over_threshold; + template + struct peaks_over_threshold_prob; + template + struct pot_tail_mean; + template + struct pot_tail_mean_prob; + template + struct pot_quantile; + template + struct pot_quantile_prob; + struct p_square_cumulative_distribution; + struct p_square_quantile; + struct p_square_quantile_for_median; + struct skewness; + struct sum; + struct sum_of_weights; + template + struct sum_of_variates; + template + struct tail; + template + struct coherent_tail_mean; + template + struct non_coherent_tail_mean; + template + struct tail_quantile; + template + struct tail_variate; + template + struct tail_weights; + template + struct right_tail_variate; + template + struct left_tail_variate; + template + struct tail_variate_means; + template + struct absolute_tail_variate_means; + template + struct relative_tail_variate_means; + struct lazy_variance; + struct variance; + template + struct weighted_covariance; + struct weighted_density; + struct weighted_kurtosis; + struct weighted_mean; + struct immediate_weighted_mean; + template + struct weighted_mean_of_variates; + template + struct immediate_weighted_mean_of_variates; + struct weighted_median; + struct with_density_weighted_median; + struct with_p_square_cumulative_distribution_weighted_median; + struct weighted_extended_p_square; + struct weighted_extended_p_square_quantile; + struct weighted_extended_p_square_quantile_quadratic; + template + struct weighted_moment; + template + struct weighted_peaks_over_threshold; + template + struct weighted_peaks_over_threshold_prob; + template + struct weighted_pot_quantile; + template + struct weighted_pot_quantile_prob; + template + struct weighted_pot_tail_mean; + template + struct weighted_pot_tail_mean_prob; + struct weighted_p_square_cumulative_distribution; + struct weighted_p_square_quantile; + struct weighted_p_square_quantile_for_median; + struct weighted_skewness; + template + struct weighted_tail_quantile; + template + struct non_coherent_weighted_tail_mean; + template + struct weighted_tail_quantile; + template + struct weighted_tail_variate_means; + template + struct absolute_weighted_tail_variate_means; + template + struct relative_weighted_tail_variate_means; + struct lazy_weighted_variance; + struct weighted_variance; + struct weighted_sum; + template + struct weighted_sum_of_variates; +} // namespace tag + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // Statistics impls + struct count_impl; + + template + struct covariance_impl; + + template + struct density_impl; + + template + struct error_of_impl; + + template + struct error_of_mean_impl; + + template + struct extended_p_square_impl; + + template + struct extended_p_square_quantile_impl; + + template + struct kurtosis_impl; + + template + struct max_impl; + + template + struct median_impl; + + template + struct with_density_median_impl; + + template + struct with_p_square_cumulative_distribution_median_impl; + + template + struct min_impl; + + template + struct mean_impl; + + template + struct immediate_mean_impl; + + template + struct moment_impl; + + template + struct peaks_over_threshold_prob_impl; + + template + struct pot_quantile_impl; + + template + struct pot_tail_mean_impl; + + template + struct p_square_cumulative_distribution_impl; + + template + struct p_square_quantile_impl; + + template + struct skewness_impl; + + template + struct sum_impl; + + template + struct tail_impl; + + template + struct coherent_tail_mean_impl; + + template + struct non_coherent_tail_mean_impl; + + template + struct tail_quantile_impl; + + template + struct tail_variate_impl; + + template + struct tail_variate_means_impl; + + template + struct lazy_variance_impl; + + template + struct variance_impl; + + template + struct weighted_covariance_impl; + + template + struct weighted_density_impl; + + template + struct weighted_kurtosis_impl; + + template + struct weighted_median_impl; + + template + struct with_density_weighted_median_impl; + + template + struct with_p_square_cumulative_distribution_weighted_median_impl; + + template + struct weighted_mean_impl; + + template + struct immediate_weighted_mean_impl; + + template + struct weighted_peaks_over_threshold_impl; + + template + struct weighted_peaks_over_threshold_prob_impl; + + template + struct with_p_square_cumulative_distribution_weighted_median_impl; + + template + struct weighted_extended_p_square_impl; + + template + struct weighted_moment_impl; + + template + struct weighted_p_square_cumulative_distribution_impl; + + template + struct weighted_p_square_quantile_impl; + + template + struct weighted_skewness_impl; + + template + struct weighted_sum_impl; + + template + struct non_coherent_weighted_tail_mean_impl; + + template + struct weighted_tail_quantile_impl; + + template + struct weighted_tail_variate_means_impl; + + template + struct lazy_weighted_variance_impl; + + template + struct weighted_variance_impl; + + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// stats +// A more descriptive name for an MPL sequence of statistics. +template +struct stats; + +template +struct with_error; + +// modifiers for the mean and variance stats +struct lazy {}; +struct immediate {}; + +// modifiers for the variance stat +// struct fast {}; +// struct accurate {}; + +// modifiers for order +struct right {}; +struct left {}; +// typedef right default_order_tag_type; + +// modifiers for the tail_variate_means stat +struct absolute {}; +struct relative {}; + +// modifiers for median and weighted_median stats +struct with_density {}; +struct with_p_square_cumulative_distribution {}; +struct with_p_square_quantile {}; + +// modifiers for peaks_over_threshold stat +struct with_threshold_value {}; +struct with_threshold_probability {}; + +// modifiers for extended_p_square_quantile and weighted_extended_p_square_quantile stats +struct weighted {}; +struct unweighted {}; +struct linear {}; +struct quadratic {}; + +// modifiers for p_square_quantile +struct regular {}; +struct for_median {}; + +}} // namespace boost::accumulators + +#endif diff --git a/win32/include/boost/algorithm/minmax.hpp b/win32/include/boost/algorithm/minmax.hpp new file mode 100755 index 000000000..014a7d21a --- /dev/null +++ b/win32/include/boost/algorithm/minmax.hpp @@ -0,0 +1,47 @@ +// (C) Copyright Herve Bronnimann 2004. +// +// 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) + +/* + Revision history: + 1 July 2004 + Split the code into two headers to lessen dependence on + Boost.tuple. (Herve) + 26 June 2004 + Added the code for the boost minmax library. (Herve) +*/ + +#ifndef BOOST_ALGORITHM_MINMAX_HPP +#define BOOST_ALGORITHM_MINMAX_HPP + +/* PROPOSED STANDARD EXTENSIONS: + * + * minmax(a, b) + * Effect: (b // for using pairs with boost::cref +#include + +namespace boost { + + template + tuple< T const&, T const& > + minmax(T const& a, T const& b) { + return (b + tuple< T const&, T const& > + minmax(T const& a, T const& b, BinaryPredicate comp) { + return comp(b,a) ? make_tuple(cref(b),cref(a)) : make_tuple(cref(a),cref(b)); + } + +} // namespace boost + +#endif // BOOST_ALGORITHM_MINMAX_HPP diff --git a/win32/include/boost/algorithm/minmax_element.hpp b/win32/include/boost/algorithm/minmax_element.hpp new file mode 100755 index 000000000..996ede036 --- /dev/null +++ b/win32/include/boost/algorithm/minmax_element.hpp @@ -0,0 +1,551 @@ +// (C) Copyright Herve Bronnimann 2004. +// +// 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) + +/* + Revision history: + 1 July 2004 + Split the code into two headers to lessen dependence on + Boost.tuple. (Herve) + 26 June 2004 + Added the code for the boost minmax library. (Herve) +*/ + +#ifndef BOOST_ALGORITHM_MINMAX_ELEMENT_HPP +#define BOOST_ALGORITHM_MINMAX_ELEMENT_HPP + +/* PROPOSED STANDARD EXTENSIONS: + * + * minmax_element(first, last) + * Effect: std::make_pair( std::min_element(first, last), + * std::max_element(first, last) ); + * + * minmax_element(first, last, comp) + * Effect: std::make_pair( std::min_element(first, last, comp), + * std::max_element(first, last, comp) ); + */ + +#include // for std::pair and std::make_pair + +namespace boost { + + namespace detail { // for obtaining a uniform version of minmax_element + // that compiles with VC++ 6.0 -- avoid the iterator_traits by + // having comparison object over iterator, not over dereferenced value + + template + struct less_over_iter { + bool operator()(Iterator const& it1, + Iterator const& it2) const { return *it1 < *it2; } + }; + + template + struct binary_pred_over_iter { + explicit binary_pred_over_iter(BinaryPredicate const& p ) : m_p( p ) {} + bool operator()(Iterator const& it1, + Iterator const& it2) const { return m_p(*it1, *it2); } + private: + BinaryPredicate m_p; + }; + + // common base for the two minmax_element overloads + + template + std::pair + basic_minmax_element(ForwardIter first, ForwardIter last, Compare comp) + { + if (first == last) + return std::make_pair(last,last); + + ForwardIter min_result = first; + ForwardIter max_result = first; + + // if only one element + ForwardIter second = first; ++second; + if (second == last) + return std::make_pair(min_result, max_result); + + // treat first pair separately (only one comparison for first two elements) + ForwardIter potential_min_result = last; + if (comp(first, second)) + max_result = second; + else { + min_result = second; + potential_min_result = first; + } + + // then each element by pairs, with at most 3 comparisons per pair + first = ++second; if (first != last) ++second; + while (second != last) { + if (comp(first, second)) { + if (comp(first, min_result)) { + min_result = first; + potential_min_result = last; + } + if (comp(max_result, second)) + max_result = second; + } else { + if (comp(second, min_result)) { + min_result = second; + potential_min_result = first; + } + if (comp(max_result, first)) + max_result = first; + } + first = ++second; + if (first != last) ++second; + } + + // if odd number of elements, treat last element + if (first != last) { // odd number of elements + if (comp(first, min_result)) + min_result = first, potential_min_result = last; + else if (comp(max_result, first)) + max_result = first; + } + + // resolve min_result being incorrect with one extra comparison + // (in which case potential_min_result is necessarily the correct result) + if (potential_min_result != last + && !comp(min_result, potential_min_result)) + min_result = potential_min_result; + + return std::make_pair(min_result,max_result); + } + + } // namespace detail + + template + std::pair + minmax_element(ForwardIter first, ForwardIter last) + { + return detail::basic_minmax_element(first, last, + detail::less_over_iter() ); + } + + template + std::pair + minmax_element(ForwardIter first, ForwardIter last, BinaryPredicate comp) + { + return detail::basic_minmax_element(first, last, + detail::binary_pred_over_iter(comp) ); + } + +} + +/* PROPOSED BOOST EXTENSIONS + * In the description below, [rfirst,rlast) denotes the reversed range + * of [first,last). Even though the iterator type of first and last may + * be only a Forward Iterator, it is possible to explain the semantics + * by assuming that it is a Bidirectional Iterator. In the sequel, + * reverse(ForwardIterator&) returns the reverse_iterator adaptor. + * This is not how the functions would be implemented! + * + * first_min_element(first, last) + * Effect: std::min_element(first, last); + * + * first_min_element(first, last, comp) + * Effect: std::min_element(first, last, comp); + * + * last_min_element(first, last) + * Effect: reverse( std::min_element(reverse(last), reverse(first)) ); + * + * last_min_element(first, last, comp) + * Effect: reverse( std::min_element(reverse(last), reverse(first), comp) ); + * + * first_max_element(first, last) + * Effect: std::max_element(first, last); + * + * first_max_element(first, last, comp) + * Effect: max_element(first, last); + * + * last_max_element(first, last) + * Effect: reverse( std::max_element(reverse(last), reverse(first)) ); + * + * last_max_element(first, last, comp) + * Effect: reverse( std::max_element(reverse(last), reverse(first), comp) ); + * + * first_min_first_max_element(first, last) + * Effect: std::make_pair( first_min_element(first, last), + * first_max_element(first, last) ); + * + * first_min_first_max_element(first, last, comp) + * Effect: std::make_pair( first_min_element(first, last, comp), + * first_max_element(first, last, comp) ); + * + * first_min_last_max_element(first, last) + * Effect: std::make_pair( first_min_element(first, last), + * last_max_element(first, last) ); + * + * first_min_last_max_element(first, last, comp) + * Effect: std::make_pair( first_min_element(first, last, comp), + * last_max_element(first, last, comp) ); + * + * last_min_first_max_element(first, last) + * Effect: std::make_pair( last_min_element(first, last), + * first_max_element(first, last) ); + * + * last_min_first_max_element(first, last, comp) + * Effect: std::make_pair( last_min_element(first, last, comp), + * first_max_element(first, last, comp) ); + * + * last_min_last_max_element(first, last) + * Effect: std::make_pair( last_min_element(first, last), + * last_max_element(first, last) ); + * + * last_min_last_max_element(first, last, comp) + * Effect: std::make_pair( last_min_element(first, last, comp), + * last_max_element(first, last, comp) ); + */ + +namespace boost { + + // Min_element and max_element variants + + namespace detail { // common base for the overloads + + template + ForwardIter + basic_first_min_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + if (first == last) return last; + ForwardIter min_result = first; + while (++first != last) + if (comp(first, min_result)) + min_result = first; + return min_result; + } + + template + ForwardIter + basic_last_min_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + if (first == last) return last; + ForwardIter min_result = first; + while (++first != last) + if (!comp(min_result, first)) + min_result = first; + return min_result; + } + + template + ForwardIter + basic_first_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + if (first == last) return last; + ForwardIter max_result = first; + while (++first != last) + if (comp(max_result, first)) + max_result = first; + return max_result; + } + + template + ForwardIter + basic_last_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + if (first == last) return last; + ForwardIter max_result = first; + while (++first != last) + if (!comp(first, max_result)) + max_result = first; + return max_result; + } + + } // namespace detail + + template + ForwardIter + first_min_element(ForwardIter first, ForwardIter last) + { + return detail::basic_first_min_element(first, last, + detail::less_over_iter() ); + } + + template + ForwardIter + first_min_element(ForwardIter first, ForwardIter last, BinaryPredicate comp) + { + return detail::basic_first_min_element(first, last, + detail::binary_pred_over_iter(comp) ); + } + + template + ForwardIter + last_min_element(ForwardIter first, ForwardIter last) + { + return detail::basic_last_min_element(first, last, + detail::less_over_iter() ); + } + + template + ForwardIter + last_min_element(ForwardIter first, ForwardIter last, BinaryPredicate comp) + { + return detail::basic_last_min_element(first, last, + detail::binary_pred_over_iter(comp) ); + } + + template + ForwardIter + first_max_element(ForwardIter first, ForwardIter last) + { + return detail::basic_first_max_element(first, last, + detail::less_over_iter() ); + } + + template + ForwardIter + first_max_element(ForwardIter first, ForwardIter last, BinaryPredicate comp) + { + return detail::basic_first_max_element(first, last, + detail::binary_pred_over_iter(comp) ); + } + + template + ForwardIter + last_max_element(ForwardIter first, ForwardIter last) + { + return detail::basic_last_max_element(first, last, + detail::less_over_iter() ); + } + + template + ForwardIter + last_max_element(ForwardIter first, ForwardIter last, BinaryPredicate comp) + { + return detail::basic_last_max_element(first, last, + detail::binary_pred_over_iter(comp) ); + } + + + // Minmax_element variants -- comments removed + + namespace detail { + + template + std::pair + basic_first_min_last_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + if (first == last) + return std::make_pair(last,last); + + ForwardIter min_result = first; + ForwardIter max_result = first; + + ForwardIter second = ++first; + if (second == last) + return std::make_pair(min_result, max_result); + + if (comp(second, min_result)) + min_result = second; + else + max_result = second; + + first = ++second; if (first != last) ++second; + while (second != last) { + if (!comp(second, first)) { + if (comp(first, min_result)) + min_result = first; + if (!comp(second, max_result)) + max_result = second; + } else { + if (comp(second, min_result)) + min_result = second; + if (!comp(first, max_result)) + max_result = first; + } + first = ++second; if (first != last) ++second; + } + + if (first != last) { + if (comp(first, min_result)) + min_result = first; + else if (!comp(first, max_result)) + max_result = first; + } + + return std::make_pair(min_result, max_result); + } + + template + std::pair + basic_last_min_first_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + if (first == last) return std::make_pair(last,last); + + ForwardIter min_result = first; + ForwardIter max_result = first; + + ForwardIter second = ++first; + if (second == last) + return std::make_pair(min_result, max_result); + + if (comp(max_result, second)) + max_result = second; + else + min_result = second; + + first = ++second; if (first != last) ++second; + while (second != last) { + if (comp(first, second)) { + if (!comp(min_result, first)) + min_result = first; + if (comp(max_result, second)) + max_result = second; + } else { + if (!comp(min_result, second)) + min_result = second; + if (comp(max_result, first)) + max_result = first; + } + first = ++second; if (first != last) ++second; + } + + if (first != last) { + if (!comp(min_result, first)) + min_result = first; + else if (comp(max_result, first)) + max_result = first; + } + + return std::make_pair(min_result, max_result); + } + + template + std::pair + basic_last_min_last_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + if (first == last) return std::make_pair(last,last); + + ForwardIter min_result = first; + ForwardIter max_result = first; + + ForwardIter second = first; ++second; + if (second == last) + return std::make_pair(min_result,max_result); + + ForwardIter potential_max_result = last; + if (comp(first, second)) + max_result = second; + else { + min_result = second; + potential_max_result = second; + } + + first = ++second; if (first != last) ++second; + while (second != last) { + if (comp(first, second)) { + if (!comp(min_result, first)) + min_result = first; + if (!comp(second, max_result)) { + max_result = second; + potential_max_result = last; + } + } else { + if (!comp(min_result, second)) + min_result = second; + if (!comp(first, max_result)) { + max_result = first; + potential_max_result = second; + } + } + first = ++second; + if (first != last) ++second; + } + + if (first != last) { + if (!comp(min_result, first)) + min_result = first; + if (!comp(first, max_result)) { + max_result = first; + potential_max_result = last; + } + } + + if (potential_max_result != last + && !comp(potential_max_result, max_result)) + max_result = potential_max_result; + + return std::make_pair(min_result,max_result); + } + + } // namespace detail + + template + inline std::pair + first_min_first_max_element(ForwardIter first, ForwardIter last) + { + return minmax_element(first, last); + } + + template + inline std::pair + first_min_first_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + return minmax_element(first, last, comp); + } + + template + std::pair + first_min_last_max_element(ForwardIter first, ForwardIter last) + { + return detail::basic_first_min_last_max_element(first, last, + detail::less_over_iter() ); + } + + template + inline std::pair + first_min_last_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + return detail::basic_first_min_last_max_element(first, last, + detail::binary_pred_over_iter(comp) ); + } + + template + std::pair + last_min_first_max_element(ForwardIter first, ForwardIter last) + { + return detail::basic_last_min_first_max_element(first, last, + detail::less_over_iter() ); + } + + template + inline std::pair + last_min_first_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + return detail::basic_last_min_first_max_element(first, last, + detail::binary_pred_over_iter(comp) ); + } + + template + std::pair + last_min_last_max_element(ForwardIter first, ForwardIter last) + { + return detail::basic_last_min_last_max_element(first, last, + detail::less_over_iter() ); + } + + template + inline std::pair + last_min_last_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + return detail::basic_last_min_last_max_element(first, last, + detail::binary_pred_over_iter(comp) ); + } + +} // namespace boost + +#endif // BOOST_ALGORITHM_MINMAX_ELEMENT_HPP diff --git a/win32/include/boost/algorithm/string.hpp b/win32/include/boost/algorithm/string.hpp new file mode 100755 index 000000000..496400dbf --- /dev/null +++ b/win32/include/boost/algorithm/string.hpp @@ -0,0 +1,31 @@ +// Boost string_algo library string_algo.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2004. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_ALGO_HPP +#define BOOST_STRING_ALGO_HPP + +/*! \file + Cumulative include for string_algo library +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#endif // BOOST_STRING_ALGO_HPP diff --git a/win32/include/boost/algorithm/string/case_conv.hpp b/win32/include/boost/algorithm/string/case_conv.hpp new file mode 100755 index 000000000..d246bbb29 --- /dev/null +++ b/win32/include/boost/algorithm/string/case_conv.hpp @@ -0,0 +1,176 @@ +// Boost string_algo library case_conv.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_CASE_CONV_HPP +#define BOOST_STRING_CASE_CONV_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/*! \file + Defines sequence case-conversion algorithms. + Algorithms convert each element in the input sequence to the + desired case using provided locales. +*/ + +namespace boost { + namespace algorithm { + +// to_lower -----------------------------------------------// + + //! Convert to lower case + /*! + Each element of the input sequence is converted to lower + case. The result is a copy of the input converted to lower case. + It is returned as a sequence or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input range + \param Loc A locale used for conversion + \return + An output iterator pointing just after the last inserted character or + a copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + + */ + template + inline OutputIteratorT + to_lower_copy( + OutputIteratorT Output, + const RangeT& Input, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::detail::transform_range_copy( + Output, + as_literal(Input), + ::boost::algorithm::detail::to_lowerF< + typename range_value::type >(Loc)); + } + + //! Convert to lower case + /*! + \overload + */ + template + inline SequenceT to_lower_copy( + const SequenceT& Input, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::detail::transform_range_copy( + Input, + ::boost::algorithm::detail::to_lowerF< + typename range_value::type >(Loc)); + } + + //! Convert to lower case + /*! + Each element of the input sequence is converted to lower + case. The input sequence is modified in-place. + + \param Input A range + \param Loc a locale used for conversion + */ + template + inline void to_lower( + WritableRangeT& Input, + const std::locale& Loc=std::locale()) + { + ::boost::algorithm::detail::transform_range( + as_literal(Input), + ::boost::algorithm::detail::to_lowerF< + typename range_value::type >(Loc)); + } + +// to_upper -----------------------------------------------// + + //! Convert to upper case + /*! + Each element of the input sequence is converted to upper + case. The result is a copy of the input converted to upper case. + It is returned as a sequence or copied to the output iterator + + \param Output An output iterator to which the result will be copied + \param Input An input range + \param Loc A locale used for conversion + \return + An output iterator pointing just after the last inserted character or + a copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template + inline OutputIteratorT + to_upper_copy( + OutputIteratorT Output, + const RangeT& Input, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::detail::transform_range_copy( + Output, + as_literal(Input), + ::boost::algorithm::detail::to_upperF< + typename range_value::type >(Loc)); + } + + //! Convert to upper case + /*! + \overload + */ + template + inline SequenceT to_upper_copy( + const SequenceT& Input, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::detail::transform_range_copy( + Input, + ::boost::algorithm::detail::to_upperF< + typename range_value::type >(Loc)); + } + + //! Convert to upper case + /*! + Each element of the input sequence is converted to upper + case. The input sequence is modified in-place. + + \param Input An input range + \param Loc a locale used for conversion + */ + template + inline void to_upper( + WritableRangeT& Input, + const std::locale& Loc=std::locale()) + { + ::boost::algorithm::detail::transform_range( + as_literal(Input), + ::boost::algorithm::detail::to_upperF< + typename range_value::type >(Loc)); + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::to_lower; + using algorithm::to_lower_copy; + using algorithm::to_upper; + using algorithm::to_upper_copy; + +} // namespace boost + +#endif // BOOST_STRING_CASE_CONV_HPP diff --git a/win32/include/boost/algorithm/string/classification.hpp b/win32/include/boost/algorithm/string/classification.hpp new file mode 100755 index 000000000..f39de3301 --- /dev/null +++ b/win32/include/boost/algorithm/string/classification.hpp @@ -0,0 +1,312 @@ +// Boost string_algo library classification.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_CLASSIFICATION_HPP +#define BOOST_STRING_CLASSIFICATION_HPP + +#include +#include +#include +#include +#include +#include + + +/*! \file + Classification predicates are included in the library to give + some more convenience when using algorithms like \c trim() and \c all(). + They wrap functionality of STL classification functions ( e.g. \c std::isspace() ) + into generic functors. +*/ + +namespace boost { + namespace algorithm { + +// classification functor generator -------------------------------------// + + //! is_classified predicate + /*! + Construct the \c is_classified predicate. This predicate holds if the input is + of specified \c std::ctype category. + + \param Type A \c std::ctype category + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_classified(std::ctype_base::mask Type, const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(Type, Loc); + } + + //! is_space predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::space category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_space(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::space, Loc); + } + + //! is_alnum predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::alnum category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_alnum(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::alnum, Loc); + } + + //! is_alpha predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::alpha category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_alpha(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::alpha, Loc); + } + + //! is_cntrl predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::cntrl category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_cntrl(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::cntrl, Loc); + } + + //! is_digit predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::digit category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_digit(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::digit, Loc); + } + + //! is_graph predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::graph category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_graph(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::graph, Loc); + } + + //! is_lower predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::lower category. + + \param Loc A locale used for classification + \return An instance of \c is_classified predicate + */ + inline detail::is_classifiedF + is_lower(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::lower, Loc); + } + + //! is_print predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::print category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_print(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::print, Loc); + } + + //! is_punct predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::punct category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_punct(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::punct, Loc); + } + + //! is_upper predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::upper category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_upper(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::upper, Loc); + } + + //! is_xdigit predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::xdigit category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_xdigit(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::xdigit, Loc); + } + + //! is_any_of predicate + /*! + Construct the \c is_any_of predicate. The predicate holds if the input + is included in the specified set of characters. + + \param Set A set of characters to be recognized + \return An instance of the \c is_any_of predicate + */ + template + inline detail::is_any_ofF< + BOOST_STRING_TYPENAME range_value::type> + is_any_of( const RangeT& Set ) + { + iterator_range::type> lit_set(as_literal(Set)); + return detail::is_any_ofF::type>(lit_set); + } + + //! is_from_range predicate + /*! + Construct the \c is_from_range predicate. The predicate holds if the input + is included in the specified range. (i.e. From <= Ch <= To ) + + \param From The start of the range + \param To The end of the range + \return An instance of the \c is_from_range predicate + */ + template + inline detail::is_from_rangeF is_from_range(CharT From, CharT To) + { + return detail::is_from_rangeF(From,To); + } + + // predicate combinators ---------------------------------------------------// + + //! predicate 'and' composition predicate + /*! + Construct the \c class_and predicate. This predicate can be used + to logically combine two classification predicates. \c class_and holds, + if both predicates return true. + + \param Pred1 The first predicate + \param Pred2 The second predicate + \return An instance of the \c class_and predicate + */ + template + inline detail::pred_andF + operator&&( + const predicate_facade& Pred1, + const predicate_facade& Pred2 ) + { + // Doing the static_cast with the pointer instead of the reference + // is a workaround for some compilers which have problems with + // static_cast's of template references, i.e. CW8. /grafik/ + return detail::pred_andF( + *static_cast(&Pred1), + *static_cast(&Pred2) ); + } + + //! predicate 'or' composition predicate + /*! + Construct the \c class_or predicate. This predicate can be used + to logically combine two classification predicates. \c class_or holds, + if one of the predicates return true. + + \param Pred1 The first predicate + \param Pred2 The second predicate + \return An instance of the \c class_or predicate + */ + template + inline detail::pred_orF + operator||( + const predicate_facade& Pred1, + const predicate_facade& Pred2 ) + { + // Doing the static_cast with the pointer instead of the reference + // is a workaround for some compilers which have problems with + // static_cast's of template references, i.e. CW8. /grafik/ + return detail::pred_orF( + *static_cast(&Pred1), + *static_cast(&Pred2)); + } + + //! predicate negation operator + /*! + Construct the \c class_not predicate. This predicate represents a negation. + \c class_or holds if of the predicates return false. + + \param Pred The predicate to be negated + \return An instance of the \c class_not predicate + */ + template + inline detail::pred_notF + operator!( const predicate_facade& Pred ) + { + // Doing the static_cast with the pointer instead of the reference + // is a workaround for some compilers which have problems with + // static_cast's of template references, i.e. CW8. /grafik/ + return detail::pred_notF(*static_cast(&Pred)); + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::is_classified; + using algorithm::is_space; + using algorithm::is_alnum; + using algorithm::is_alpha; + using algorithm::is_cntrl; + using algorithm::is_digit; + using algorithm::is_graph; + using algorithm::is_lower; + using algorithm::is_upper; + using algorithm::is_print; + using algorithm::is_punct; + using algorithm::is_xdigit; + using algorithm::is_any_of; + using algorithm::is_from_range; + +} // namespace boost + +#endif // BOOST_STRING_PREDICATE_HPP diff --git a/win32/include/boost/algorithm/string/compare.hpp b/win32/include/boost/algorithm/string/compare.hpp new file mode 100755 index 000000000..f610b3643 --- /dev/null +++ b/win32/include/boost/algorithm/string/compare.hpp @@ -0,0 +1,199 @@ +// Boost string_algo library compare.hpp header file -------------------------// + +// Copyright Pavol Droba 2002-2006. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_COMPARE_HPP +#define BOOST_STRING_COMPARE_HPP + +#include +#include + +/*! \file + Defines element comparison predicates. Many algorithms in this library can + take an additional argument with a predicate used to compare elements. + This makes it possible, for instance, to have case insensitive versions + of the algorithms. +*/ + +namespace boost { + namespace algorithm { + + // is_equal functor -----------------------------------------------// + + //! is_equal functor + /*! + Standard STL equal_to only handle comparison between arguments + of the same type. This is a less restrictive version which wraps operator ==. + */ + struct is_equal + { + //! Function operator + /*! + Compare two operands for equality + */ + template< typename T1, typename T2 > + bool operator()( const T1& Arg1, const T2& Arg2 ) const + { + return Arg1==Arg2; + } + }; + + //! case insensitive version of is_equal + /*! + Case insensitive comparison predicate. Comparison is done using + specified locales. + */ + struct is_iequal + { + //! Constructor + /*! + \param Loc locales used for comparison + */ + is_iequal( const std::locale& Loc=std::locale() ) : + m_Loc( Loc ) {} + + //! Function operator + /*! + Compare two operands. Case is ignored. + */ + template< typename T1, typename T2 > + bool operator()( const T1& Arg1, const T2& Arg2 ) const + { + #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL) + return std::toupper(Arg1)==std::toupper(Arg2); + #else + return std::toupper(Arg1,m_Loc)==std::toupper(Arg2,m_Loc); + #endif + } + + private: + std::locale m_Loc; + }; + + // is_less functor -----------------------------------------------// + + //! is_less functor + /*! + Convenient version of standard std::less. Operation is templated, therefore it is + not required to specify the exact types upon the construction + */ + struct is_less + { + //! Functor operation + /*! + Compare two operands using > operator + */ + template< typename T1, typename T2 > + bool operator()( const T1& Arg1, const T2& Arg2 ) const + { + return Arg1 + bool operator()( const T1& Arg1, const T2& Arg2 ) const + { + #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL) + return std::toupper(Arg1)(Arg1,m_Loc)(Arg2,m_Loc); + #endif + } + + private: + std::locale m_Loc; + }; + + // is_not_greater functor -----------------------------------------------// + + //! is_not_greater functor + /*! + Convenient version of standard std::not_greater_to. Operation is templated, therefore it is + not required to specify the exact types upon the construction + */ + struct is_not_greater + { + //! Functor operation + /*! + Compare two operands using > operator + */ + template< typename T1, typename T2 > + bool operator()( const T1& Arg1, const T2& Arg2 ) const + { + return Arg1<=Arg2; + } + }; + + + //! case insensitive version of is_not_greater + /*! + Case insensitive comparison predicate. Comparison is done using + specified locales. + */ + struct is_not_igreater + { + //! Constructor + /*! + \param Loc locales used for comparison + */ + is_not_igreater( const std::locale& Loc=std::locale() ) : + m_Loc( Loc ) {} + + //! Function operator + /*! + Compare two operands. Case is ignored. + */ + template< typename T1, typename T2 > + bool operator()( const T1& Arg1, const T2& Arg2 ) const + { + #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL) + return std::toupper(Arg1)<=std::toupper(Arg2); + #else + return std::toupper(Arg1,m_Loc)<=std::toupper(Arg2,m_Loc); + #endif + } + + private: + std::locale m_Loc; + }; + + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::is_equal; + using algorithm::is_iequal; + using algorithm::is_less; + using algorithm::is_iless; + using algorithm::is_not_greater; + using algorithm::is_not_igreater; + +} // namespace boost + + +#endif // BOOST_STRING_COMPARE_HPP diff --git a/win32/include/boost/algorithm/string/concept.hpp b/win32/include/boost/algorithm/string/concept.hpp new file mode 100755 index 000000000..2ef4ca731 --- /dev/null +++ b/win32/include/boost/algorithm/string/concept.hpp @@ -0,0 +1,83 @@ +// Boost string_algo library concept.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_CONCEPT_HPP +#define BOOST_STRING_CONCEPT_HPP + +#include +#include +#include +#include + +/*! \file + Defines concepts used in string_algo library +*/ + +namespace boost { + namespace algorithm { + + //! Finder concept + /*! + Defines the Finder concept. Finder is a functor which selects + an arbitrary part of a string. Search is performed on + the range specified by starting and ending iterators. + + Result of the find operation must be convertible to iterator_range. + */ + template + struct FinderConcept + { + private: + typedef iterator_range range; + public: + void constraints() + { + // Operation + r=(*pF)(i,i); + } + private: + range r; + IteratorT i; + FinderT* pF; + }; // Finder_concept + + + //! Formatter concept + /*! + Defines the Formatter concept. Formatter is a functor, which + takes a result from a finder operation and transforms it + in a specific way. + + Result must be a container supported by container_traits, + or a reference to it. + */ + template + struct FormatterConcept + { + public: + void constraints() + { + // Operation + ::boost::begin((*pFo)( (*pF)(i,i) )); + ::boost::end((*pFo)( (*pF)(i,i) )); + } + private: + IteratorT i; + FinderT* pF; + FormatterT *pFo; + }; // FormatterConcept; + + } // namespace algorithm +} // namespace boost + + + + +#endif // BOOST_STRING_CONCEPT_HPP diff --git a/win32/include/boost/algorithm/string/config.hpp b/win32/include/boost/algorithm/string/config.hpp new file mode 100755 index 000000000..d10c6f5d8 --- /dev/null +++ b/win32/include/boost/algorithm/string/config.hpp @@ -0,0 +1,28 @@ +// Boost string_algo library config.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_CONFIG_HPP +#define BOOST_STRING_CONFIG_HPP + +#include +#include + +#ifdef BOOST_STRING_DEDUCED_TYPENAME +# error "macro already defined!" +#endif + +#define BOOST_STRING_TYPENAME BOOST_DEDUCED_TYPENAME + +// Metrowerks workaround +#if BOOST_WORKAROUND(__MWERKS__, <= 0x3003) // 8.x +#pragma parse_func_templ off +#endif + +#endif // BOOST_STRING_CONFIG_HPP diff --git a/win32/include/boost/algorithm/string/constants.hpp b/win32/include/boost/algorithm/string/constants.hpp new file mode 100755 index 000000000..9022d4358 --- /dev/null +++ b/win32/include/boost/algorithm/string/constants.hpp @@ -0,0 +1,36 @@ +// Boost string_algo library constants.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_CONSTANTS_HPP +#define BOOST_STRING_CONSTANTS_HPP + +namespace boost { + namespace algorithm { + + //! Token compression mode + /*! + Specifies token compression mode for the token_finder. + */ + enum token_compress_mode_type + { + token_compress_on, //!< Compress adjacent tokens + token_compress_off //!< Do not compress adjacent tokens + }; + + } // namespace algorithm + + // pull the names to the boost namespace + using algorithm::token_compress_on; + using algorithm::token_compress_off; + +} // namespace boost + +#endif // BOOST_STRING_CONSTANTS_HPP + diff --git a/win32/include/boost/algorithm/string/detail/case_conv.hpp b/win32/include/boost/algorithm/string/detail/case_conv.hpp new file mode 100755 index 000000000..39a7751c6 --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/case_conv.hpp @@ -0,0 +1,121 @@ +// Boost string_algo library string_funct.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_CASE_CONV_DETAIL_HPP +#define BOOST_STRING_CASE_CONV_DETAIL_HPP + +#include +#include +#include + +namespace boost { + namespace algorithm { + namespace detail { + +// case conversion functors -----------------------------------------------// + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(push) +#pragma warning(disable:4512) //assignment operator could not be generated +#endif + + // a tolower functor + template + struct to_lowerF : public std::unary_function + { + // Constructor + to_lowerF( const std::locale& Loc ) : m_Loc( Loc ) {} + + // Operation + CharT operator ()( CharT Ch ) const + { + #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL) + return std::tolower( Ch); + #else + return std::tolower( Ch, m_Loc ); + #endif + } + private: + const std::locale& m_Loc; + }; + + // a toupper functor + template + struct to_upperF : public std::unary_function + { + // Constructor + to_upperF( const std::locale& Loc ) : m_Loc( Loc ) {} + + // Operation + CharT operator ()( CharT Ch ) const + { + #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL) + return std::toupper( Ch); + #else + return std::toupper( Ch, m_Loc ); + #endif + } + private: + const std::locale& m_Loc; + }; + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(pop) +#endif + +// algorithm implementation ------------------------------------------------------------------------- + + // Transform a range + template + OutputIteratorT transform_range_copy( + OutputIteratorT Output, + const RangeT& Input, + FunctorT Functor) + { + return std::transform( + ::boost::begin(Input), + ::boost::end(Input), + Output, + Functor); + } + + // Transform a range (in-place) + template + void transform_range( + const RangeT& Input, + FunctorT Functor) + { + std::transform( + ::boost::begin(Input), + ::boost::end(Input), + ::boost::begin(Input), + Functor); + } + + template + inline SequenceT transform_range_copy( + const RangeT& Input, + FunctorT Functor) + { + return SequenceT( + make_transform_iterator( + ::boost::begin(Input), + Functor), + make_transform_iterator( + ::boost::end(Input), + Functor)); + } + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_CASE_CONV_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/detail/classification.hpp b/win32/include/boost/algorithm/string/detail/classification.hpp new file mode 100755 index 000000000..5628064a1 --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/classification.hpp @@ -0,0 +1,312 @@ +// Boost string_algo library classification.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_CLASSIFICATION_DETAIL_HPP +#define BOOST_STRING_CLASSIFICATION_DETAIL_HPP + +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace boost { + namespace algorithm { + namespace detail { + +// classification functors -----------------------------------------------// + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(push) +#pragma warning(disable:4512) //assignment operator could not be generated +#endif + // is_classified functor + struct is_classifiedF : + public predicate_facade + { + // Boost.Lambda support + template struct sig { typedef bool type; }; + + // Constructor from a locale + is_classifiedF(std::ctype_base::mask Type, std::locale const & Loc = std::locale()) : + m_Type(Type), m_Locale(Loc) {} + + // Operation + template + bool operator()( CharT Ch ) const + { + return std::use_facet< std::ctype >(m_Locale).is( m_Type, Ch ); + } + + #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x582) && !defined(_USE_OLD_RW_STL) + template<> + bool operator()( char const Ch ) const + { + return std::use_facet< std::ctype >(m_Locale).is( m_Type, Ch ); + } + #endif + + private: + const std::ctype_base::mask m_Type; + const std::locale m_Locale; + }; + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(pop) +#endif + + // is_any_of functor + /* + returns true if the value is from the specified set + */ + template + struct is_any_ofF : + public predicate_facade > + { + private: + // set cannot operate on const value-type + typedef typename remove_const::type set_value_type; + // Size of the static storage (size of pointer*2) + static const ::std::size_t FIXED_STORAGE_SIZE = sizeof(set_value_type*)*2; + + public: + // Boost.Lambda support + template struct sig { typedef bool type; }; + + // Constructor + template + is_any_ofF( const RangeT& Range ) : m_Size(0) + { + // Prepare storage + m_Storage.m_dynSet=0; + + std::size_t Size=::boost::distance(Range); + m_Size=Size; + set_value_type* Storage=0; + + if(m_Size<=FIXED_STORAGE_SIZE) + { + // Use fixed storage + Storage=&m_Storage.m_fixSet[0]; + } + else + { + // Use dynamic storage + m_Storage.m_dynSet=new set_value_type[m_Size]; + Storage=m_Storage.m_dynSet; + } + + // Use fixed storage + ::std::copy(::boost::begin(Range), ::boost::end(Range), Storage); + ::std::sort(Storage, Storage+m_Size); + } + + // Copy constructor + is_any_ofF(const is_any_ofF& Other) : m_Size(Other.m_Size) + { + // Prepare storage + m_Storage.m_dynSet=0; + const set_value_type* SrcStorage=0; + set_value_type* DestStorage=0; + + if(m_Size<=FIXED_STORAGE_SIZE) + { + // Use fixed storage + DestStorage=&m_Storage.m_fixSet[0]; + SrcStorage=&Other.m_Storage.m_fixSet[0]; + } + else + { + // Use dynamic storage + m_Storage.m_dynSet=new set_value_type[m_Size]; + DestStorage=m_Storage.m_dynSet; + SrcStorage=Other.m_Storage.m_dynSet; + } + + // Use fixed storage + ::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size); + } + + // Destructor + ~is_any_ofF() + { + if(m_Size>FIXED_STORAGE_SIZE && m_Storage.m_dynSet!=0) + { + delete m_Storage.m_dynSet; + } + } + + // Assignment + is_any_ofF& operator=(const is_any_ofF& Other) + { + // Prepare storage + m_Storage.m_dynSet=0; + m_Size=Other.m_Size; + const set_value_type* SrcStorage=0; + set_value_type* DestStorage=0; + + if(m_Size<=FIXED_STORAGE_SIZE) + { + // Use fixed storage + DestStorage=&m_Storage.m_fixSet[0]; + SrcStorage=&Other.m_Storage.m_fixSet[0]; + } + else + { + // Use dynamic storage + m_Storage.m_dynSet=new set_value_type[m_Size]; + DestStorage=m_Storage.m_dynSet; + SrcStorage=Other.m_Storage.m_dynSet; + } + + // Use fixed storage + ::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size); + + return *this; + } + + // Operation + template + bool operator()( Char2T Ch ) const + { + const set_value_type* Storage= + (m_Size<=FIXED_STORAGE_SIZE) + ? &m_Storage.m_fixSet[0] + : m_Storage.m_dynSet; + + return ::std::binary_search(Storage, Storage+m_Size, Ch); + } + + private: + // storage + // The actual used storage is selected on the type + union + { + set_value_type* m_dynSet; + set_value_type m_fixSet[FIXED_STORAGE_SIZE]; + } + m_Storage; + + // storage size + ::std::size_t m_Size; + }; + + // is_from_range functor + /* + returns true if the value is from the specified range. + (i.e. x>=From && x>=To) + */ + template + struct is_from_rangeF : + public predicate_facade< is_from_rangeF > + { + // Boost.Lambda support + template struct sig { typedef bool type; }; + + // Constructor + is_from_rangeF( CharT From, CharT To ) : m_From(From), m_To(To) {} + + // Operation + template + bool operator()( Char2T Ch ) const + { + return ( m_From <= Ch ) && ( Ch <= m_To ); + } + + private: + CharT m_From; + CharT m_To; + }; + + // class_and composition predicate + template + struct pred_andF : + public predicate_facade< pred_andF > + { + public: + + // Boost.Lambda support + template struct sig { typedef bool type; }; + + // Constructor + pred_andF( Pred1T Pred1, Pred2T Pred2 ) : + m_Pred1(Pred1), m_Pred2(Pred2) {} + + // Operation + template + bool operator()( CharT Ch ) const + { + return m_Pred1(Ch) && m_Pred2(Ch); + } + + private: + Pred1T m_Pred1; + Pred2T m_Pred2; + }; + + // class_or composition predicate + template + struct pred_orF : + public predicate_facade< pred_orF > + { + public: + // Boost.Lambda support + template struct sig { typedef bool type; }; + + // Constructor + pred_orF( Pred1T Pred1, Pred2T Pred2 ) : + m_Pred1(Pred1), m_Pred2(Pred2) {} + + // Operation + template + bool operator()( CharT Ch ) const + { + return m_Pred1(Ch) || m_Pred2(Ch); + } + + private: + Pred1T m_Pred1; + Pred2T m_Pred2; + }; + + // class_not composition predicate + template< typename PredT > + struct pred_notF : + public predicate_facade< pred_notF > + { + public: + // Boost.Lambda support + template struct sig { typedef bool type; }; + + // Constructor + pred_notF( PredT Pred ) : m_Pred(Pred) {} + + // Operation + template + bool operator()( CharT Ch ) const + { + return !m_Pred(Ch); + } + + private: + PredT m_Pred; + }; + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_CLASSIFICATION_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/detail/find_format.hpp b/win32/include/boost/algorithm/string/detail/find_format.hpp new file mode 100755 index 000000000..73d01535a --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/find_format.hpp @@ -0,0 +1,193 @@ +// Boost string_algo library find_format.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FIND_FORMAT_DETAIL_HPP +#define BOOST_STRING_FIND_FORMAT_DETAIL_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { + namespace algorithm { + namespace detail { + +// find_format_copy (iterator variant) implementation -------------------------------// + + template< + typename OutputIteratorT, + typename InputT, + typename FormatterT, + typename FindResultT > + inline OutputIteratorT find_format_copy_impl( + OutputIteratorT Output, + const InputT& Input, + FormatterT Formatter, + const FindResultT& FindResult ) + { + return find_format_copy_impl2( + Output, + Input, + Formatter, + FindResult, + Formatter(FindResult) ); + } + + template< + typename OutputIteratorT, + typename InputT, + typename FormatterT, + typename FindResultT, + typename FormatResultT > + inline OutputIteratorT find_format_copy_impl2( + OutputIteratorT Output, + const InputT& Input, + FormatterT Formatter, + const FindResultT& FindResult, + const FormatResultT& FormatResult ) + { + typedef find_format_store< + BOOST_STRING_TYPENAME + range_const_iterator::type, + FormatterT, + FormatResultT > store_type; + + // Create store for the find result + store_type M( FindResult, FormatResult, Formatter ); + + if ( !M ) + { + // Match not found - return original sequence + std::copy( ::boost::begin(Input), ::boost::end(Input), Output ); + return Output; + } + + // Copy the beginning of the sequence + std::copy( ::boost::begin(Input), ::boost::begin(M), Output ); + // Format find result + // Copy formated result + std::copy( ::boost::begin(M.format_result()), ::boost::end(M.format_result()), Output ); + // Copy the rest of the sequence + std::copy( M.end(), ::boost::end(Input), Output ); + + return Output; + } + +// find_format_copy implementation --------------------------------------------------// + + template< + typename InputT, + typename FormatterT, + typename FindResultT > + inline InputT find_format_copy_impl( + const InputT& Input, + FormatterT Formatter, + const FindResultT& FindResult) + { + return find_format_copy_impl2( + Input, + Formatter, + FindResult, + Formatter(FindResult) ); + } + + template< + typename InputT, + typename FormatterT, + typename FindResultT, + typename FormatResultT > + inline InputT find_format_copy_impl2( + const InputT& Input, + FormatterT Formatter, + const FindResultT& FindResult, + const FormatResultT& FormatResult) + { + typedef find_format_store< + BOOST_STRING_TYPENAME + range_const_iterator::type, + FormatterT, + FormatResultT > store_type; + + // Create store for the find result + store_type M( FindResult, FormatResult, Formatter ); + + if ( !M ) + { + // Match not found - return original sequence + return InputT( Input ); + } + + InputT Output; + // Copy the beginning of the sequence + insert( Output, ::boost::end(Output), ::boost::begin(Input), M.begin() ); + // Copy formated result + insert( Output, ::boost::end(Output), M.format_result() ); + // Copy the rest of the sequence + insert( Output, ::boost::end(Output), M.end(), ::boost::end(Input) ); + + return Output; + } + +// replace implementation ----------------------------------------------------// + + template< + typename InputT, + typename FormatterT, + typename FindResultT > + inline void find_format_impl( + InputT& Input, + FormatterT Formatter, + const FindResultT& FindResult) + { + find_format_impl2( + Input, + Formatter, + FindResult, + Formatter(FindResult) ); + } + + template< + typename InputT, + typename FormatterT, + typename FindResultT, + typename FormatResultT > + inline void find_format_impl2( + InputT& Input, + FormatterT Formatter, + const FindResultT& FindResult, + const FormatResultT& FormatResult) + { + typedef find_format_store< + BOOST_STRING_TYPENAME + range_iterator::type, + FormatterT, + FormatResultT > store_type; + + // Create store for the find result + store_type M( FindResult, FormatResult, Formatter ); + + if ( !M ) + { + // Search not found - return original sequence + return; + } + + // Replace match + replace( Input, M.begin(), M.end(), M.format_result() ); + } + + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_FIND_FORMAT_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/detail/find_format_all.hpp b/win32/include/boost/algorithm/string/detail/find_format_all.hpp new file mode 100755 index 000000000..c05c2b6fa --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/find_format_all.hpp @@ -0,0 +1,263 @@ +// Boost string_algo library find_format_all.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FIND_FORMAT_ALL_DETAIL_HPP +#define BOOST_STRING_FIND_FORMAT_ALL_DETAIL_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { + namespace algorithm { + namespace detail { + +// find_format_all_copy (iterator variant) implementation ---------------------------// + + template< + typename OutputIteratorT, + typename InputT, + typename FinderT, + typename FormatterT, + typename FindResultT > + inline OutputIteratorT find_format_all_copy_impl( + OutputIteratorT Output, + const InputT& Input, + FinderT Finder, + FormatterT Formatter, + const FindResultT& FindResult ) + { + return find_format_all_copy_impl2( + Output, + Input, + Finder, + Formatter, + FindResult, + Formatter(FindResult) ); + } + + template< + typename OutputIteratorT, + typename InputT, + typename FinderT, + typename FormatterT, + typename FindResultT, + typename FormatResultT > + inline OutputIteratorT find_format_all_copy_impl2( + OutputIteratorT Output, + const InputT& Input, + FinderT Finder, + FormatterT Formatter, + const FindResultT& FindResult, + const FormatResultT& FormatResult ) + { + typedef BOOST_STRING_TYPENAME + range_const_iterator::type input_iterator_type; + + typedef find_format_store< + input_iterator_type, + FormatterT, + FormatResultT > store_type; + + // Create store for the find result + store_type M( FindResult, FormatResult, Formatter ); + + // Initialize last match + input_iterator_type LastMatch=::boost::begin(Input); + + // Iterate through all matches + while( M ) + { + // Copy the beginning of the sequence + std::copy( LastMatch, M.begin(), Output ); + // Copy formated result + std::copy( ::boost::begin(M.format_result()), ::boost::end(M.format_result()), Output ); + + // Proceed to the next match + LastMatch=M.end(); + M=Finder( LastMatch, ::boost::end(Input) ); + } + + // Copy the rest of the sequence + std::copy( LastMatch, ::boost::end(Input), Output ); + + return Output; + } + +// find_format_all_copy implementation ----------------------------------------------// + + template< + typename InputT, + typename FinderT, + typename FormatterT, + typename FindResultT > + inline InputT find_format_all_copy_impl( + const InputT& Input, + FinderT Finder, + FormatterT Formatter, + const FindResultT& FindResult) + { + return find_format_all_copy_impl2( + Input, + Finder, + Formatter, + FindResult, + Formatter(FindResult) ); + } + + template< + typename InputT, + typename FinderT, + typename FormatterT, + typename FindResultT, + typename FormatResultT > + inline InputT find_format_all_copy_impl2( + const InputT& Input, + FinderT Finder, + FormatterT Formatter, + const FindResultT& FindResult, + const FormatResultT& FormatResult) + { + typedef BOOST_STRING_TYPENAME + range_const_iterator::type input_iterator_type; + + typedef find_format_store< + input_iterator_type, + FormatterT, + FormatResultT > store_type; + + // Create store for the find result + store_type M( FindResult, FormatResult, Formatter ); + + // Initialize last match + input_iterator_type LastMatch=::boost::begin(Input); + + // Output temporary + InputT Output; + + // Iterate through all matches + while( M ) + { + // Copy the beginning of the sequence + insert( Output, ::boost::end(Output), LastMatch, M.begin() ); + // Copy formated result + insert( Output, ::boost::end(Output), M.format_result() ); + + // Proceed to the next match + LastMatch=M.end(); + M=Finder( LastMatch, ::boost::end(Input) ); + } + + // Copy the rest of the sequence + insert( Output, ::boost::end(Output), LastMatch, ::boost::end(Input) ); + + return Output; + } + +// find_format_all implementation ------------------------------------------------// + + template< + typename InputT, + typename FinderT, + typename FormatterT, + typename FindResultT > + inline void find_format_all_impl( + InputT& Input, + FinderT Finder, + FormatterT Formatter, + FindResultT FindResult) + { + find_format_all_impl2( + Input, + Finder, + Formatter, + FindResult, + Formatter(FindResult) ); + } + + template< + typename InputT, + typename FinderT, + typename FormatterT, + typename FindResultT, + typename FormatResultT > + inline void find_format_all_impl2( + InputT& Input, + FinderT Finder, + FormatterT Formatter, + FindResultT FindResult, + FormatResultT FormatResult) + { + typedef BOOST_STRING_TYPENAME + range_iterator::type input_iterator_type; + typedef find_format_store< + input_iterator_type, + FormatterT, + FormatResultT > store_type; + + // Create store for the find result + store_type M( FindResult, FormatResult, Formatter ); + + // Instantiate replacement storage + std::deque< + BOOST_STRING_TYPENAME range_value::type> Storage; + + // Initialize replacement iterators + input_iterator_type InsertIt=::boost::begin(Input); + input_iterator_type SearchIt=::boost::begin(Input); + + while( M ) + { + // process the segment + InsertIt=process_segment( + Storage, + Input, + InsertIt, + SearchIt, + M.begin() ); + + // Adjust search iterator + SearchIt=M.end(); + + // Copy formated replace to the storage + copy_to_storage( Storage, M.format_result() ); + + // Find range for a next match + M=Finder( SearchIt, ::boost::end(Input) ); + } + + // process the last segment + InsertIt=process_segment( + Storage, + Input, + InsertIt, + SearchIt, + ::boost::end(Input) ); + + if ( Storage.empty() ) + { + // Truncate input + erase( Input, InsertIt, ::boost::end(Input) ); + } + else + { + // Copy remaining data to the end of input + insert( Input, ::boost::end(Input), Storage.begin(), Storage.end() ); + } + } + + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_FIND_FORMAT_ALL_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/detail/find_format_store.hpp b/win32/include/boost/algorithm/string/detail/find_format_store.hpp new file mode 100755 index 000000000..a91f8b2af --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/find_format_store.hpp @@ -0,0 +1,78 @@ +// Boost string_algo library find_format_store.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FIND_FORMAT_STORE_DETAIL_HPP +#define BOOST_STRING_FIND_FORMAT_STORE_DETAIL_HPP + +#include +#include + +namespace boost { + namespace algorithm { + namespace detail { + +// temporary format and find result storage --------------------------------// + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(push) +#pragma warning(disable:4512) //assignment operator could not be generated +#endif + template< + typename ForwardIteratorT, + typename FormatterT, + typename FormatResultT > + class find_format_store : + public iterator_range + { + public: + // typedefs + typedef iterator_range base_type; + typedef FormatterT formatter_type; + typedef FormatResultT format_result_type; + + public: + // Construction + find_format_store( + const base_type& FindResult, + const format_result_type& FormatResult, + const formatter_type& Formatter ) : + base_type(FindResult), + m_FormatResult(FormatResult), + m_Formatter(Formatter) {} + + // Assignment + template< typename FindResultT > + find_format_store& operator=( FindResultT FindResult ) + { + iterator_range::operator=(FindResult); + m_FormatResult=m_Formatter(FindResult); + + return *this; + } + + // Retrieve format result + const format_result_type& format_result() + { + return m_FormatResult; + } + + private: + format_result_type m_FormatResult; + const formatter_type& m_Formatter; + }; + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(pop) +#endif + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_FIND_FORMAT_STORE_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/detail/find_iterator.hpp b/win32/include/boost/algorithm/string/detail/find_iterator.hpp new file mode 100755 index 000000000..e2d27f086 --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/find_iterator.hpp @@ -0,0 +1,87 @@ +// Boost string_algo library find_iterator.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FIND_ITERATOR_DETAIL_HPP +#define BOOST_STRING_FIND_ITERATOR_DETAIL_HPP + +#include +#include +#include +#include +#include + +namespace boost { + namespace algorithm { + namespace detail { + +// find_iterator base -----------------------------------------------// + + // Find iterator base + template + class find_iterator_base + { + protected: + // typedefs + typedef IteratorT input_iterator_type; + typedef iterator_range match_type; + typedef function2< + match_type, + input_iterator_type, + input_iterator_type> finder_type; + + protected: + // Protected construction/destruction + + // Default constructor + find_iterator_base() {}; + // Copy construction + find_iterator_base( const find_iterator_base& Other ) : + m_Finder(Other.m_Finder) {} + + // Constructor + template + find_iterator_base( FinderT Finder, int ) : + m_Finder(Finder) {} + + // Destructor + ~find_iterator_base() {} + + // Find operation + match_type do_find( + input_iterator_type Begin, + input_iterator_type End ) const + { + if (!m_Finder.empty()) + { + return m_Finder(Begin,End); + } + else + { + return match_type(End,End); + } + } + + // Check + bool is_null() const + { + return m_Finder.empty(); + } + + private: + // Finder + finder_type m_Finder; + }; + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_FIND_ITERATOR_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/detail/finder.hpp b/win32/include/boost/algorithm/string/detail/finder.hpp new file mode 100755 index 000000000..2eeed229a --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/finder.hpp @@ -0,0 +1,646 @@ +// Boost string_algo library finder.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2006. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FINDER_DETAIL_HPP +#define BOOST_STRING_FINDER_DETAIL_HPP + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace boost { + namespace algorithm { + namespace detail { + + +// find first functor -----------------------------------------------// + + // find a subsequence in the sequence ( functor ) + /* + Returns a pair marking the subsequence in the sequence. + If the find fails, functor returns + */ + template + struct first_finderF + { + typedef SearchIteratorT search_iterator_type; + + // Construction + template< typename SearchT > + first_finderF( const SearchT& Search, PredicateT Comp ) : + m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {} + first_finderF( + search_iterator_type SearchBegin, + search_iterator_type SearchEnd, + PredicateT Comp ) : + m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {} + + // Operation + template< typename ForwardIteratorT > + iterator_range + operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + typedef iterator_range result_type; + typedef ForwardIteratorT input_iterator_type; + + // Outer loop + for(input_iterator_type OuterIt=Begin; + OuterIt!=End; + ++OuterIt) + { + // Sanity check + if( boost::empty(m_Search) ) + return result_type( End, End ); + + input_iterator_type InnerIt=OuterIt; + search_iterator_type SubstrIt=m_Search.begin(); + for(; + InnerIt!=End && SubstrIt!=m_Search.end(); + ++InnerIt,++SubstrIt) + { + if( !( m_Comp(*InnerIt,*SubstrIt) ) ) + break; + } + + // Substring matching succeeded + if ( SubstrIt==m_Search.end() ) + return result_type( OuterIt, InnerIt ); + } + + return result_type( End, End ); + } + + private: + iterator_range m_Search; + PredicateT m_Comp; + }; + +// find last functor -----------------------------------------------// + + // find the last match a subseqeunce in the sequence ( functor ) + /* + Returns a pair marking the subsequence in the sequence. + If the find fails, returns + */ + template + struct last_finderF + { + typedef SearchIteratorT search_iterator_type; + typedef first_finderF< + search_iterator_type, + PredicateT> first_finder_type; + + // Construction + template< typename SearchT > + last_finderF( const SearchT& Search, PredicateT Comp ) : + m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {} + last_finderF( + search_iterator_type SearchBegin, + search_iterator_type SearchEnd, + PredicateT Comp ) : + m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {} + + // Operation + template< typename ForwardIteratorT > + iterator_range + operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + typedef iterator_range result_type; + + if( boost::empty(m_Search) ) + return result_type( End, End ); + + typedef BOOST_STRING_TYPENAME boost::detail:: + iterator_traits::iterator_category category; + + return findit( Begin, End, category() ); + } + + private: + // forward iterator + template< typename ForwardIteratorT > + iterator_range + findit( + ForwardIteratorT Begin, + ForwardIteratorT End, + std::forward_iterator_tag ) const + { + typedef ForwardIteratorT input_iterator_type; + typedef iterator_range result_type; + + first_finder_type first_finder( + m_Search.begin(), m_Search.end(), m_Comp ); + + result_type M=first_finder( Begin, End ); + result_type Last=M; + + while( M ) + { + Last=M; + M=first_finder( ::boost::end(M), End ); + } + + return Last; + } + + // bidirectional iterator + template< typename ForwardIteratorT > + iterator_range + findit( + ForwardIteratorT Begin, + ForwardIteratorT End, + std::bidirectional_iterator_tag ) const + { + typedef iterator_range result_type; + typedef ForwardIteratorT input_iterator_type; + + // Outer loop + for(input_iterator_type OuterIt=End; + OuterIt!=Begin; ) + { + input_iterator_type OuterIt2=--OuterIt; + + input_iterator_type InnerIt=OuterIt2; + search_iterator_type SubstrIt=m_Search.begin(); + for(; + InnerIt!=End && SubstrIt!=m_Search.end(); + ++InnerIt,++SubstrIt) + { + if( !( m_Comp(*InnerIt,*SubstrIt) ) ) + break; + } + + // Substring matching succeeded + if( SubstrIt==m_Search.end() ) + return result_type( OuterIt2, InnerIt ); + } + + return result_type( End, End ); + } + + private: + iterator_range m_Search; + PredicateT m_Comp; + }; + +// find n-th functor -----------------------------------------------// + + // find the n-th match of a subsequence in the sequence ( functor ) + /* + Returns a pair marking the subsequence in the sequence. + If the find fails, returns + */ + template + struct nth_finderF + { + typedef SearchIteratorT search_iterator_type; + typedef first_finderF< + search_iterator_type, + PredicateT> first_finder_type; + typedef last_finderF< + search_iterator_type, + PredicateT> last_finder_type; + + // Construction + template< typename SearchT > + nth_finderF( + const SearchT& Search, + int Nth, + PredicateT Comp) : + m_Search(::boost::begin(Search), ::boost::end(Search)), + m_Nth(Nth), + m_Comp(Comp) {} + nth_finderF( + search_iterator_type SearchBegin, + search_iterator_type SearchEnd, + int Nth, + PredicateT Comp) : + m_Search(SearchBegin, SearchEnd), + m_Nth(Nth), + m_Comp(Comp) {} + + // Operation + template< typename ForwardIteratorT > + iterator_range + operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + if(m_Nth>=0) + { + return find_forward(Begin, End, m_Nth); + } + else + { + return find_backward(Begin, End, -m_Nth); + } + + } + + private: + // Implementation helpers + template< typename ForwardIteratorT > + iterator_range + find_forward( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N) const + { + typedef ForwardIteratorT input_iterator_type; + typedef iterator_range result_type; + + // Sanity check + if( boost::empty(m_Search) ) + return result_type( End, End ); + + // Instantiate find functor + first_finder_type first_finder( + m_Search.begin(), m_Search.end(), m_Comp ); + + result_type M( Begin, Begin ); + + for( unsigned int n=0; n<=N; ++n ) + { + // find next match + M=first_finder( ::boost::end(M), End ); + + if ( !M ) + { + // Subsequence not found, return + return M; + } + } + + return M; + } + + template< typename ForwardIteratorT > + iterator_range + find_backward( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N) const + { + typedef ForwardIteratorT input_iterator_type; + typedef iterator_range result_type; + + // Sanity check + if( boost::empty(m_Search) ) + return result_type( End, End ); + + // Instantiate find functor + last_finder_type last_finder( + m_Search.begin(), m_Search.end(), m_Comp ); + + result_type M( End, End ); + + for( unsigned int n=1; n<=N; ++n ) + { + // find next match + M=last_finder( Begin, ::boost::begin(M) ); + + if ( !M ) + { + // Subsequence not found, return + return M; + } + } + + return M; + } + + + private: + iterator_range m_Search; + int m_Nth; + PredicateT m_Comp; + }; + +// find head/tail implementation helpers ---------------------------// + + template + iterator_range + find_head_impl( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N, + std::forward_iterator_tag ) + { + typedef ForwardIteratorT input_iterator_type; + typedef iterator_range result_type; + + input_iterator_type It=Begin; + for( + unsigned int Index=0; + Index + iterator_range + find_head_impl( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N, + std::random_access_iterator_tag ) + { + typedef ForwardIteratorT input_iterator_type; + typedef iterator_range result_type; + + if ( (End<=Begin) || ( static_cast(End-Begin) < N ) ) + return result_type( Begin, End ); + + return result_type(Begin,Begin+N); + } + + // Find head implementation + template + iterator_range + find_head_impl( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N ) + { + typedef BOOST_STRING_TYPENAME boost::detail:: + iterator_traits::iterator_category category; + + return find_head_impl( Begin, End, N, category() ); + } + + template< typename ForwardIteratorT > + iterator_range + find_tail_impl( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N, + std::forward_iterator_tag ) + { + typedef ForwardIteratorT input_iterator_type; + typedef iterator_range result_type; + + unsigned int Index=0; + input_iterator_type It=Begin; + input_iterator_type It2=Begin; + + // Advance It2 by N increments + for( Index=0; Index + iterator_range + find_tail_impl( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N, + std::bidirectional_iterator_tag ) + { + typedef ForwardIteratorT input_iterator_type; + typedef iterator_range result_type; + + input_iterator_type It=End; + for( + unsigned int Index=0; + Index + iterator_range + find_tail_impl( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N, + std::random_access_iterator_tag ) + { + typedef ForwardIteratorT input_iterator_type; + typedef iterator_range result_type; + + if ( (End<=Begin) || ( static_cast(End-Begin) < N ) ) + return result_type( Begin, End ); + + return result_type( End-N, End ); + } + + // Operation + template< typename ForwardIteratorT > + iterator_range + find_tail_impl( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N ) + { + typedef BOOST_STRING_TYPENAME boost::detail:: + iterator_traits::iterator_category category; + + return find_tail_impl( Begin, End, N, category() ); + } + + + +// find head functor -----------------------------------------------// + + + // find a head in the sequence ( functor ) + /* + This functor find a head of the specified range. For + a specified N, the head is a subsequence of N starting + elements of the range. + */ + struct head_finderF + { + // Construction + head_finderF( int N ) : m_N(N) {} + + // Operation + template< typename ForwardIteratorT > + iterator_range + operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + if(m_N>=0) + { + return find_head_impl( Begin, End, m_N ); + } + else + { + iterator_range Res= + find_tail_impl( Begin, End, -m_N ); + + return make_iterator_range(Begin, Res.begin()); + } + } + + private: + int m_N; + }; + +// find tail functor -----------------------------------------------// + + + // find a tail in the sequence ( functor ) + /* + This functor find a tail of the specified range. For + a specified N, the head is a subsequence of N starting + elements of the range. + */ + struct tail_finderF + { + // Construction + tail_finderF( int N ) : m_N(N) {} + + // Operation + template< typename ForwardIteratorT > + iterator_range + operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + if(m_N>=0) + { + return find_tail_impl( Begin, End, m_N ); + } + else + { + iterator_range Res= + find_head_impl( Begin, End, -m_N ); + + return make_iterator_range(Res.end(), End); + } + } + + private: + int m_N; + }; + +// find token functor -----------------------------------------------// + + // find a token in a sequence ( functor ) + /* + This find functor finds a token specified be a predicate + in a sequence. It is equivalent of std::find algorithm, + with an exception that it return range instead of a single + iterator. + + If bCompress is set to true, adjacent matching tokens are + concatenated into one match. + */ + template< typename PredicateT > + struct token_finderF + { + // Construction + token_finderF( + PredicateT Pred, + token_compress_mode_type eCompress=token_compress_off ) : + m_Pred(Pred), m_eCompress(eCompress) {} + + // Operation + template< typename ForwardIteratorT > + iterator_range + operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + typedef iterator_range result_type; + + ForwardIteratorT It=std::find_if( Begin, End, m_Pred ); + + if( It==End ) + { + return result_type( End, End ); + } + else + { + ForwardIteratorT It2=It; + + if( m_eCompress==token_compress_on ) + { + // Find first non-matching character + while( It2!=End && m_Pred(*It2) ) ++It2; + } + else + { + // Advance by one position + ++It2; + } + + return result_type( It, It2 ); + } + } + + private: + PredicateT m_Pred; + token_compress_mode_type m_eCompress; + }; + +// find range functor -----------------------------------------------// + + // find a range in the sequence ( functor ) + /* + This functor actually does not perform any find operation. + It always returns given iterator range as a result. + */ + template + struct range_finderF + { + typedef ForwardIterator1T input_iterator_type; + typedef iterator_range result_type; + + // Construction + range_finderF( + input_iterator_type Begin, + input_iterator_type End ) : m_Range(Begin, End) {} + + range_finderF(const iterator_range& Range) : + m_Range(Range) {} + + // Operation + template< typename ForwardIterator2T > + iterator_range + operator()( + ForwardIterator2T, + ForwardIterator2T ) const + { +#if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 ) + return iterator_range(this->m_Range); +#elif BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + return iterator_range(m_Range.begin(), m_Range.end()); +#else + return m_Range; +#endif + } + + private: + iterator_range m_Range; + }; + + + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_FINDER_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/detail/finder_regex.hpp b/win32/include/boost/algorithm/string/detail/finder_regex.hpp new file mode 100755 index 000000000..fdf0da031 --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/finder_regex.hpp @@ -0,0 +1,122 @@ +// Boost string_algo library find_regex.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FINDER_REGEX_DETAIL_HPP +#define BOOST_STRING_FINDER_REGEX_DETAIL_HPP + +#include +#include + +#include +#include +#include + +namespace boost { + namespace algorithm { + namespace detail { + +// regex find functor -----------------------------------------------// + + // regex search result + template + struct regex_search_result : + public iterator_range + { + typedef regex_search_result type; + typedef iterator_range base_type; + typedef BOOST_STRING_TYPENAME base_type::value_type value_type; + typedef BOOST_STRING_TYPENAME base_type::difference_type difference_type; + typedef BOOST_STRING_TYPENAME base_type::const_iterator const_iterator; + typedef BOOST_STRING_TYPENAME base_type::iterator iterator; + typedef boost::match_results match_results_type; + + // Construction + + // Construction from the match result + regex_search_result( const match_results_type& MatchResults ) : + base_type( MatchResults[0].first, MatchResults[0].second ), + m_MatchResults( MatchResults ) {} + + // Construction of empty match. End iterator has to be specified + regex_search_result( IteratorT End ) : + base_type( End, End ) {} + + regex_search_result( const regex_search_result& Other ) : + base_type( Other.begin(), Other.end() ), + m_MatchResults( Other.m_MatchResults ) {} + + // Assignment + regex_search_result& operator=( const regex_search_result& Other ) + { + base_type::operator=( Other ); + m_MatchResults=Other.m_MatchResults; + return *this; + } + + // Match result retrival + const match_results_type& match_results() const + { + return m_MatchResults; + } + + private: + // Saved matchresult + match_results_type m_MatchResults; + }; + + // find_regex + /* + Regex based search functor + */ + template + struct find_regexF + { + typedef RegExT regex_type; + typedef const RegExT& regex_reference_type; + + // Construction + find_regexF( regex_reference_type Rx, match_flag_type MatchFlags = match_default ) : + m_Rx(Rx), m_MatchFlags(MatchFlags) {} + + // Operation + template< typename ForwardIteratorT > + regex_search_result + operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + typedef ForwardIteratorT input_iterator_type; + typedef regex_search_result result_type; + + // instantiate match result + match_results result; + // search for a match + if ( regex_search( Begin, End, result, m_Rx, m_MatchFlags ) ) + { + // construct a result + return result_type( result ); + } + else + { + // empty result + return result_type( End ); + } + } + + private: + regex_reference_type m_Rx; // Regexp + match_flag_type m_MatchFlags; // match flags + }; + + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_FIND_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/detail/formatter.hpp b/win32/include/boost/algorithm/string/detail/formatter.hpp new file mode 100755 index 000000000..994ab2458 --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/formatter.hpp @@ -0,0 +1,94 @@ +// Boost string_algo library formatter.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FORMATTER_DETAIL_HPP +#define BOOST_STRING_FORMATTER_DETAIL_HPP + + +#include +#include +#include +#include + +#include + +// generic replace functors -----------------------------------------------// + +namespace boost { + namespace algorithm { + namespace detail { + +// const format functor ----------------------------------------------------// + + // constant format functor + template + struct const_formatF + { + private: + typedef BOOST_STRING_TYPENAME + range_const_iterator::type format_iterator; + typedef iterator_range result_type; + + public: + // Construction + const_formatF(const RangeT& Format) : + m_Format(::boost::begin(Format), ::boost::end(Format)) {} + + // Operation +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + template + result_type& operator()(const Range2T&) + { + return m_Format; + } +#endif + + template + const result_type& operator()(const Range2T&) const + { + return m_Format; + } + + private: + result_type m_Format; + }; + +// identity format functor ----------------------------------------------------// + + // identity format functor + template + struct identity_formatF + { + // Operation + template< typename Range2T > + const RangeT& operator()(const Range2T& Replace) const + { + return RangeT(::boost::begin(Replace), ::boost::end(Replace)); + } + }; + +// empty format functor ( used by erase ) ------------------------------------// + + // empty format functor + template< typename CharT > + struct empty_formatF + { + template< typename ReplaceT > + empty_container operator()(const ReplaceT&) const + { + return empty_container(); + } + }; + + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_FORMATTER_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/detail/formatter_regex.hpp b/win32/include/boost/algorithm/string/detail/formatter_regex.hpp new file mode 100755 index 000000000..20ebc9620 --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/formatter_regex.hpp @@ -0,0 +1,61 @@ +// Boost string_algo library formatter_regex.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FORMATTER_REGEX_DETAIL_HPP +#define BOOST_STRING_FORMATTER_REGEX_DETAIL_HPP + +#include +#include +#include +#include + +namespace boost { + namespace algorithm { + namespace detail { + +// regex format functor -----------------------------------------// + + // regex format functor + template + struct regex_formatF + { + private: + typedef StringT result_type; + typedef BOOST_STRING_TYPENAME StringT::value_type char_type; + + public: + // Construction + regex_formatF( const StringT& Fmt, match_flag_type Flags=format_default ) : + m_Fmt(Fmt), m_Flags( Flags ) {} + + template + result_type operator()( + const regex_search_result& Replace ) const + { + if ( Replace.empty() ) + { + return result_type(); + } + else + { + return Replace.match_results().format( m_Fmt, m_Flags ); + } + } + private: + const StringT& m_Fmt; + match_flag_type m_Flags; + }; + + + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_FORMATTER_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/detail/predicate.hpp b/win32/include/boost/algorithm/string/detail/predicate.hpp new file mode 100755 index 000000000..ef7eb87bc --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/predicate.hpp @@ -0,0 +1,77 @@ +// Boost string_algo library predicate.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_PREDICATE_DETAIL_HPP +#define BOOST_STRING_PREDICATE_DETAIL_HPP + +#include +#include + +namespace boost { + namespace algorithm { + namespace detail { + +// ends_with predicate implementation ----------------------------------// + + template< + typename ForwardIterator1T, + typename ForwardIterator2T, + typename PredicateT> + inline bool ends_with_iter_select( + ForwardIterator1T Begin, + ForwardIterator1T End, + ForwardIterator2T SubBegin, + ForwardIterator2T SubEnd, + PredicateT Comp, + std::bidirectional_iterator_tag) + { + ForwardIterator1T it=End; + ForwardIterator2T pit=SubEnd; + for(;it!=Begin && pit!=SubBegin;) + { + if( !(Comp(*(--it),*(--pit))) ) + return false; + } + + return pit==SubBegin; + } + + template< + typename ForwardIterator1T, + typename ForwardIterator2T, + typename PredicateT> + inline bool ends_with_iter_select( + ForwardIterator1T Begin, + ForwardIterator1T End, + ForwardIterator2T SubBegin, + ForwardIterator2T SubEnd, + PredicateT Comp, + std::forward_iterator_tag) + { + if ( SubBegin==SubEnd ) + { + // empty subsequence check + return true; + } + + iterator_range Result + =last_finder( + make_iterator_range(SubBegin, SubEnd), + Comp)(Begin, End); + + return !Result.empty() && Result.end()==End; + } + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_PREDICATE_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/detail/replace_storage.hpp b/win32/include/boost/algorithm/string/detail/replace_storage.hpp new file mode 100755 index 000000000..b67bf9ba8 --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/replace_storage.hpp @@ -0,0 +1,159 @@ +// Boost string_algo library replace_storage.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_REPLACE_STORAGE_DETAIL_HPP +#define BOOST_STRING_REPLACE_STORAGE_DETAIL_HPP + +#include +#include +#include +#include +#include + +namespace boost { + namespace algorithm { + namespace detail { + +// storage handling routines -----------------------------------------------// + + template< typename StorageT, typename OutputIteratorT > + inline OutputIteratorT move_from_storage( + StorageT& Storage, + OutputIteratorT DestBegin, + OutputIteratorT DestEnd ) + { + OutputIteratorT OutputIt=DestBegin; + + while( !Storage.empty() && OutputIt!=DestEnd ) + { + *OutputIt=Storage.front(); + Storage.pop_front(); + ++OutputIt; + } + + return OutputIt; + } + + template< typename StorageT, typename WhatT > + inline void copy_to_storage( + StorageT& Storage, + const WhatT& What ) + { + Storage.insert( Storage.end(), ::boost::begin(What), ::boost::end(What) ); + } + + +// process segment routine -----------------------------------------------// + + template< bool HasStableIterators > + struct process_segment_helper + { + // Optimized version of process_segment for generic sequence + template< + typename StorageT, + typename InputT, + typename ForwardIteratorT > + ForwardIteratorT operator()( + StorageT& Storage, + InputT& /*Input*/, + ForwardIteratorT InsertIt, + ForwardIteratorT SegmentBegin, + ForwardIteratorT SegmentEnd ) + { + // Copy data from the storage until the beginning of the segment + ForwardIteratorT It=move_from_storage( Storage, InsertIt, SegmentBegin ); + + // 3 cases are possible : + // a) Storage is empty, It==SegmentBegin + // b) Storage is empty, It!=SegmentBegin + // c) Storage is not empty + + if( Storage.empty() ) + { + if( It==SegmentBegin ) + { + // Case a) everything is grand, just return end of segment + return SegmentEnd; + } + else + { + // Case b) move the segment backwards + return std::copy( SegmentBegin, SegmentEnd, It ); + } + } + else + { + // Case c) -> shift the segment to the left and keep the overlap in the storage + while( It!=SegmentEnd ) + { + // Store value into storage + Storage.push_back( *It ); + // Get the top from the storage and put it here + *It=Storage.front(); + Storage.pop_front(); + + // Advance + ++It; + } + + return It; + } + } + }; + + template<> + struct process_segment_helper< true > + { + // Optimized version of process_segment for list-like sequence + template< + typename StorageT, + typename InputT, + typename ForwardIteratorT > + ForwardIteratorT operator()( + StorageT& Storage, + InputT& Input, + ForwardIteratorT InsertIt, + ForwardIteratorT SegmentBegin, + ForwardIteratorT SegmentEnd ) + + { + // Call replace to do the job + replace( Input, InsertIt, SegmentBegin, Storage ); + // Empty the storage + Storage.clear(); + // Iterators were not changed, simply return the end of segment + return SegmentEnd; + } + }; + + // Process one segment in the replace_all algorithm + template< + typename StorageT, + typename InputT, + typename ForwardIteratorT > + inline ForwardIteratorT process_segment( + StorageT& Storage, + InputT& Input, + ForwardIteratorT InsertIt, + ForwardIteratorT SegmentBegin, + ForwardIteratorT SegmentEnd ) + { + return + process_segment_helper< + has_stable_iterators::value>()( + Storage, Input, InsertIt, SegmentBegin, SegmentEnd ); + } + + + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_REPLACE_STORAGE_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/detail/sequence.hpp b/win32/include/boost/algorithm/string/detail/sequence.hpp new file mode 100755 index 000000000..23ba23d5e --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/sequence.hpp @@ -0,0 +1,200 @@ +// Boost string_algo library sequence.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_DETAIL_SEQUENCE_HPP +#define BOOST_STRING_DETAIL_SEQUENCE_HPP + +#include +#include +#include +#include +#include + +#include + +namespace boost { + namespace algorithm { + namespace detail { + +// insert helpers -------------------------------------------------// + + template< typename InputT, typename ForwardIteratorT > + inline void insert( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator At, + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + Input.insert( At, Begin, End ); + } + + template< typename InputT, typename InsertT > + inline void insert( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator At, + const InsertT& Insert ) + { + insert( Input, At, ::boost::begin(Insert), ::boost::end(Insert) ); + } + +// erase helper ---------------------------------------------------// + + // Erase a range in the sequence + /* + Returns the iterator pointing just after the erase subrange + */ + template< typename InputT > + inline typename InputT::iterator erase( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator From, + BOOST_STRING_TYPENAME InputT::iterator To ) + { + return Input.erase( From, To ); + } + +// replace helper implementation ----------------------------------// + + // Optimized version of replace for generic sequence containers + // Assumption: insert and erase are expensive + template< bool HasConstTimeOperations > + struct replace_const_time_helper + { + template< typename InputT, typename ForwardIteratorT > + void operator()( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator From, + BOOST_STRING_TYPENAME InputT::iterator To, + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + // Copy data to the container ( as much as possible ) + ForwardIteratorT InsertIt=Begin; + BOOST_STRING_TYPENAME InputT::iterator InputIt=From; + for(; InsertIt!=End && InputIt!=To; InsertIt++, InputIt++ ) + { + *InputIt=*InsertIt; + } + + if ( InsertIt!=End ) + { + // Replace sequence is longer, insert it + Input.insert( InputIt, InsertIt, End ); + } + else + { + if ( InputIt!=To ) + { + // Replace sequence is shorter, erase the rest + Input.erase( InputIt, To ); + } + } + } + }; + + template<> + struct replace_const_time_helper< true > + { + // Const-time erase and insert methods -> use them + template< typename InputT, typename ForwardIteratorT > + void operator()( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator From, + BOOST_STRING_TYPENAME InputT::iterator To, + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + BOOST_STRING_TYPENAME InputT::iterator At=Input.erase( From, To ); + if ( Begin!=End ) + { + if(!Input.empty()) + { + Input.insert( At, Begin, End ); + } + else + { + Input.insert( Input.begin(), Begin, End ); + } + } + } + }; + + // No native replace method + template< bool HasNative > + struct replace_native_helper + { + template< typename InputT, typename ForwardIteratorT > + void operator()( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator From, + BOOST_STRING_TYPENAME InputT::iterator To, + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + replace_const_time_helper< + boost::mpl::and_< + has_const_time_insert, + has_const_time_erase >::value >()( + Input, From, To, Begin, End ); + } + }; + + // Container has native replace method + template<> + struct replace_native_helper< true > + { + template< typename InputT, typename ForwardIteratorT > + void operator()( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator From, + BOOST_STRING_TYPENAME InputT::iterator To, + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + Input.replace( From, To, Begin, End ); + } + }; + +// replace helper -------------------------------------------------// + + template< typename InputT, typename ForwardIteratorT > + inline void replace( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator From, + BOOST_STRING_TYPENAME InputT::iterator To, + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + replace_native_helper< has_native_replace::value >()( + Input, From, To, Begin, End ); + } + + template< typename InputT, typename InsertT > + inline void replace( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator From, + BOOST_STRING_TYPENAME InputT::iterator To, + const InsertT& Insert ) + { + if(From!=To) + { + replace( Input, From, To, ::boost::begin(Insert), ::boost::end(Insert) ); + } + else + { + insert( Input, From, ::boost::begin(Insert), ::boost::end(Insert) ); + } + } + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_DETAIL_SEQUENCE_HPP diff --git a/win32/include/boost/algorithm/string/detail/trim.hpp b/win32/include/boost/algorithm/string/detail/trim.hpp new file mode 100755 index 000000000..1d7f03aa6 --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/trim.hpp @@ -0,0 +1,95 @@ +// Boost string_algo library trim.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_TRIM_DETAIL_HPP +#define BOOST_STRING_TRIM_DETAIL_HPP + +#include +#include + +namespace boost { + namespace algorithm { + namespace detail { + +// trim iterator helper -----------------------------------------------// + + // Search for first non matching character from the beginning of the sequence + template< typename ForwardIteratorT, typename PredicateT > + inline ForwardIteratorT trim_begin( + ForwardIteratorT InBegin, + ForwardIteratorT InEnd, + PredicateT IsSpace ) + { + ForwardIteratorT It=InBegin; + for(; It!=InEnd; ++It ) + { + if (!IsSpace(*It)) + return It; + } + + return It; + } + + // Search for first non matching character from the end of the sequence + template< typename ForwardIteratorT, typename PredicateT > + inline ForwardIteratorT trim_end( + ForwardIteratorT InBegin, + ForwardIteratorT InEnd, + PredicateT IsSpace ) + { + typedef BOOST_STRING_TYPENAME boost::detail:: + iterator_traits::iterator_category category; + + return trim_end_iter_select( InBegin, InEnd, IsSpace, category() ); + } + + template< typename ForwardIteratorT, typename PredicateT > + inline ForwardIteratorT trim_end_iter_select( + ForwardIteratorT InBegin, + ForwardIteratorT InEnd, + PredicateT IsSpace, + std::forward_iterator_tag ) + { + ForwardIteratorT TrimIt=InBegin; + + for( ForwardIteratorT It=InBegin; It!=InEnd; ++It ) + { + if ( !IsSpace(*It) ) + { + TrimIt=It; + ++TrimIt; + } + } + + return TrimIt; + } + + template< typename ForwardIteratorT, typename PredicateT > + inline ForwardIteratorT trim_end_iter_select( + ForwardIteratorT InBegin, + ForwardIteratorT InEnd, + PredicateT IsSpace, + std::bidirectional_iterator_tag ) + { + for( ForwardIteratorT It=InEnd; It!=InBegin; ) + { + if ( !IsSpace(*(--It)) ) + return ++It; + } + + return InBegin; + } + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_TRIM_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/detail/util.hpp b/win32/include/boost/algorithm/string/detail/util.hpp new file mode 100755 index 000000000..8e03a5dbd --- /dev/null +++ b/win32/include/boost/algorithm/string/detail/util.hpp @@ -0,0 +1,106 @@ +// Boost string_algo library util.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_UTIL_DETAIL_HPP +#define BOOST_STRING_UTIL_DETAIL_HPP + +#include +#include +#include + +namespace boost { + namespace algorithm { + namespace detail { + +// empty container -----------------------------------------------// + + // empty_container + /* + This class represents always empty container, + containing elements of type CharT. + + It is supposed to be used in a const version only + */ + template< typename CharT > + struct empty_container + { + typedef empty_container type; + typedef CharT value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef const value_type& reference; + typedef const value_type& const_reference; + typedef const value_type* iterator; + typedef const value_type* const_iterator; + + + // Operations + const_iterator begin() const + { + return reinterpret_cast(0); + } + + const_iterator end() const + { + return reinterpret_cast(0); + } + + bool empty() const + { + return false; + } + + size_type size() const + { + return 0; + } + }; + +// bounded copy algorithm -----------------------------------------------// + + // Bounded version of the std::copy algorithm + template + inline OutputIteratorT bounded_copy( + InputIteratorT First, + InputIteratorT Last, + OutputIteratorT DestFirst, + OutputIteratorT DestLast ) + { + InputIteratorT InputIt=First; + OutputIteratorT OutputIt=DestFirst; + for(; InputIt!=Last && OutputIt!=DestLast; InputIt++, OutputIt++ ) + { + *OutputIt=*InputIt; + } + + return OutputIt; + } + +// iterator range utilities -----------------------------------------// + + // copy range functor + template< + typename SeqT, + typename IteratorT=BOOST_STRING_TYPENAME SeqT::const_iterator > + struct copy_iterator_rangeF : + public std::unary_function< iterator_range, SeqT > + { + SeqT operator()( const iterator_range& Range ) const + { + return copy_range(Range); + } + }; + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_UTIL_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/erase.hpp b/win32/include/boost/algorithm/string/erase.hpp new file mode 100755 index 000000000..569ee659d --- /dev/null +++ b/win32/include/boost/algorithm/string/erase.hpp @@ -0,0 +1,844 @@ +// Boost string_algo library erase.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2006. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_ERASE_HPP +#define BOOST_STRING_ERASE_HPP + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/*! \file + Defines various erase algorithms. Each algorithm removes + part(s) of the input according to a searching criteria. +*/ + +namespace boost { + namespace algorithm { + +// erase_range -------------------------------------------------------// + + //! Erase range algorithm + /*! + Remove the given range from the input. The result is a modified copy of + the input. It is returned as a sequence or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input sequence + \param SearchRange A range in the input to be removed + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template + inline OutputIteratorT erase_range_copy( + OutputIteratorT Output, + const RangeT& Input, + const iterator_range< + BOOST_STRING_TYPENAME + range_const_iterator::type>& SearchRange ) + { + return find_format_copy( + Output, + Input, + range_finder(SearchRange), + empty_formatter(Input) ); + } + + //! Erase range algorithm + /*! + \overload + */ + template + inline SequenceT erase_range_copy( + const SequenceT& Input, + const iterator_range< + BOOST_STRING_TYPENAME + range_const_iterator::type>& SearchRange ) + { + return find_format_copy( + Input, + range_finder(SearchRange), + empty_formatter(Input) ); + } + + //! Erase range algorithm + /*! + Remove the given range from the input. + The input sequence is modified in-place. + + \param Input An input sequence + \param SearchRange A range in the input to be removed + */ + template + inline void erase_range( + SequenceT& Input, + const iterator_range< + BOOST_STRING_TYPENAME + range_iterator::type>& SearchRange ) + { + find_format( + Input, + range_finder(SearchRange), + empty_formatter(Input) ); + } + +// erase_first --------------------------------------------------------// + + //! Erase first algorithm + /*! + Remove the first occurrence of the substring from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT erase_first_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search ) + { + return find_format_copy( + Output, + Input, + first_finder(Search), + empty_formatter(Input) ); + } + + //! Erase first algorithm + /*! + \overload + */ + template + inline SequenceT erase_first_copy( + const SequenceT& Input, + const RangeT& Search ) + { + return find_format_copy( + Input, + first_finder(Search), + empty_formatter(Input) ); + } + + //! Erase first algorithm + /*! + Remove the first occurrence of the substring from the input. + The input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for. + */ + template + inline void erase_first( + SequenceT& Input, + const RangeT& Search ) + { + find_format( + Input, + first_finder(Search), + empty_formatter(Input) ); + } + +// erase_first ( case insensitive ) ------------------------------------// + + //! Erase first algorithm ( case insensitive ) + /*! + Remove the first occurrence of the substring from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT ierase_first_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const std::locale& Loc=std::locale() ) + { + return find_format_copy( + Output, + Input, + first_finder(Search, is_iequal(Loc)), + empty_formatter(Input) ); + } + + //! Erase first algorithm ( case insensitive ) + /*! + \overload + */ + template + inline SequenceT ierase_first_copy( + const SequenceT& Input, + const RangeT& Search, + const std::locale& Loc=std::locale() ) + { + return find_format_copy( + Input, + first_finder(Search, is_iequal(Loc)), + empty_formatter(Input) ); + } + + //! Erase first algorithm ( case insensitive ) + /*! + Remove the first occurrence of the substring from the input. + The input sequence is modified in-place. Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for + \param Loc A locale used for case insensitive comparison + */ + template + inline void ierase_first( + SequenceT& Input, + const RangeT& Search, + const std::locale& Loc=std::locale() ) + { + find_format( + Input, + first_finder(Search, is_iequal(Loc)), + empty_formatter(Input) ); + } + +// erase_last --------------------------------------------------------// + + //! Erase last algorithm + /*! + Remove the last occurrence of the substring from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for. + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT erase_last_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search ) + { + return find_format_copy( + Output, + Input, + last_finder(Search), + empty_formatter(Input) ); + } + + //! Erase last algorithm + /*! + \overload + */ + template + inline SequenceT erase_last_copy( + const SequenceT& Input, + const RangeT& Search ) + { + return find_format_copy( + Input, + last_finder(Search), + empty_formatter(Input) ); + } + + //! Erase last algorithm + /*! + Remove the last occurrence of the substring from the input. + The input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for + */ + template + inline void erase_last( + SequenceT& Input, + const RangeT& Search ) + { + find_format( + Input, + last_finder(Search), + empty_formatter(Input) ); + } + +// erase_last ( case insensitive ) ------------------------------------// + + //! Erase last algorithm ( case insensitive ) + /*! + Remove the last occurrence of the substring from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT ierase_last_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const std::locale& Loc=std::locale() ) + { + return find_format_copy( + Output, + Input, + last_finder(Search, is_iequal(Loc)), + empty_formatter(Input) ); + } + + //! Erase last algorithm ( case insensitive ) + /*! + \overload + */ + template + inline SequenceT ierase_last_copy( + const SequenceT& Input, + const RangeT& Search, + const std::locale& Loc=std::locale() ) + { + return find_format_copy( + Input, + last_finder(Search, is_iequal(Loc)), + empty_formatter(Input) ); + } + + //! Erase last algorithm ( case insensitive ) + /*! + Remove the last occurrence of the substring from the input. + The input sequence is modified in-place. Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for + \param Loc A locale used for case insensitive comparison + */ + template + inline void ierase_last( + SequenceT& Input, + const RangeT& Search, + const std::locale& Loc=std::locale() ) + { + find_format( + Input, + last_finder(Search, is_iequal(Loc)), + empty_formatter(Input) ); + } + +// erase_nth --------------------------------------------------------------------// + + //! Erase nth algorithm + /*! + Remove the Nth occurrence of the substring in the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT erase_nth_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + int Nth ) + { + return find_format_copy( + Output, + Input, + nth_finder(Search, Nth), + empty_formatter(Input) ); + } + + //! Erase nth algorithm + /*! + \overload + */ + template + inline SequenceT erase_nth_copy( + const SequenceT& Input, + const RangeT& Search, + int Nth ) + { + return find_format_copy( + Input, + nth_finder(Search, Nth), + empty_formatter(Input) ); + } + + //! Erase nth algorithm + /*! + Remove the Nth occurrence of the substring in the input. + The input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for. + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + */ + template + inline void erase_nth( + SequenceT& Input, + const RangeT& Search, + int Nth ) + { + find_format( + Input, + nth_finder(Search, Nth), + empty_formatter(Input) ); + } + +// erase_nth ( case insensitive ) ---------------------------------------------// + + //! Erase nth algorithm ( case insensitive ) + /*! + Remove the Nth occurrence of the substring in the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for. + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT ierase_nth_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + int Nth, + const std::locale& Loc=std::locale() ) + { + return find_format_copy( + Output, + Input, + nth_finder(Search, Nth, is_iequal(Loc)), + empty_formatter(Input) ); + } + + //! Erase nth algorithm + /*! + \overload + */ + template + inline SequenceT ierase_nth_copy( + const SequenceT& Input, + const RangeT& Search, + int Nth, + const std::locale& Loc=std::locale() ) + { + return find_format_copy( + Input, + nth_finder(Search, Nth, is_iequal(Loc)), + empty_formatter(Input) ); + } + + //! Erase nth algorithm + /*! + Remove the Nth occurrence of the substring in the input. + The input sequence is modified in-place. Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for. + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + \param Loc A locale used for case insensitive comparison + */ + template + inline void ierase_nth( + SequenceT& Input, + const RangeT& Search, + int Nth, + const std::locale& Loc=std::locale() ) + { + find_format( + Input, + nth_finder(Search, Nth, is_iequal(Loc)), + empty_formatter(Input) ); + } + + +// erase_all --------------------------------------------------------// + + //! Erase all algorithm + /*! + Remove all the occurrences of the string from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + + \param Output An output iterator to which the result will be copied + \param Input An input sequence + \param Search A substring to be searched for. + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT erase_all_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search ) + { + return find_format_all_copy( + Output, + Input, + first_finder(Search), + empty_formatter(Input) ); + } + + //! Erase all algorithm + /*! + \overload + */ + template + inline SequenceT erase_all_copy( + const SequenceT& Input, + const RangeT& Search ) + { + return find_format_all_copy( + Input, + first_finder(Search), + empty_formatter(Input) ); + } + + //! Erase all algorithm + /*! + Remove all the occurrences of the string from the input. + The input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for. + */ + template + inline void erase_all( + SequenceT& Input, + const RangeT& Search ) + { + find_format_all( + Input, + first_finder(Search), + empty_formatter(Input) ); + } + +// erase_all ( case insensitive ) ------------------------------------// + + //! Erase all algorithm ( case insensitive ) + /*! + Remove all the occurrences of the string from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT ierase_all_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const std::locale& Loc=std::locale() ) + { + return find_format_all_copy( + Output, + Input, + first_finder(Search, is_iequal(Loc)), + empty_formatter(Input) ); + } + + //! Erase all algorithm ( case insensitive ) + /*! + \overload + */ + template + inline SequenceT ierase_all_copy( + const SequenceT& Input, + const RangeT& Search, + const std::locale& Loc=std::locale() ) + { + return find_format_all_copy( + Input, + first_finder(Search, is_iequal(Loc)), + empty_formatter(Input) ); + } + + //! Erase all algorithm ( case insensitive ) + /*! + Remove all the occurrences of the string from the input. + The input sequence is modified in-place. Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for. + \param Loc A locale used for case insensitive comparison + */ + template + inline void ierase_all( + SequenceT& Input, + const RangeT& Search, + const std::locale& Loc=std::locale() ) + { + find_format_all( + Input, + first_finder(Search, is_iequal(Loc)), + empty_formatter(Input) ); + } + +// erase_head --------------------------------------------------------------------// + + //! Erase head algorithm + /*! + Remove the head from the input. The head is a prefix of a sequence of given size. + If the sequence is shorter then required, the whole string is + considered to be the head. The result is a modified copy of the input. + It is returned as a sequence or copied to the output iterator. + + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param N Length of the head. + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT> + inline OutputIteratorT erase_head_copy( + OutputIteratorT Output, + const RangeT& Input, + int N ) + { + return find_format_copy( + Output, + Input, + head_finder(N), + empty_formatter( Input ) ); + } + + //! Erase head algorithm + /*! + \overload + */ + template + inline SequenceT erase_head_copy( + const SequenceT& Input, + int N ) + { + return find_format_copy( + Input, + head_finder(N), + empty_formatter( Input ) ); + } + + //! Erase head algorithm + /*! + Remove the head from the input. The head is a prefix of a sequence of given size. + If the sequence is shorter then required, the whole string is + considered to be the head. The input sequence is modified in-place. + + \param Input An input string + \param N Length of the head + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + */ + template + inline void erase_head( + SequenceT& Input, + int N ) + { + find_format( + Input, + head_finder(N), + empty_formatter( Input ) ); + } + +// erase_tail --------------------------------------------------------------------// + + //! Erase tail algorithm + /*! + Remove the tail from the input. The tail is a suffix of a sequence of given size. + If the sequence is shorter then required, the whole string is + considered to be the tail. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param N Length of the head. + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT> + inline OutputIteratorT erase_tail_copy( + OutputIteratorT Output, + const RangeT& Input, + int N ) + { + return find_format_copy( + Output, + Input, + tail_finder(N), + empty_formatter( Input ) ); + } + + //! Erase tail algorithm + /*! + \overload + */ + template + inline SequenceT erase_tail_copy( + const SequenceT& Input, + int N ) + { + return find_format_copy( + Input, + tail_finder(N), + empty_formatter( Input ) ); + } + + //! Erase tail algorithm + /*! + Remove the tail from the input. The tail is a suffix of a sequence of given size. + If the sequence is shorter then required, the whole string is + considered to be the tail. The input sequence is modified in-place. + + \param Input An input string + \param N Length of the head + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + */ + template + inline void erase_tail( + SequenceT& Input, + int N ) + { + find_format( + Input, + tail_finder(N), + empty_formatter( Input ) ); + } + + } // namespace algorithm + + // pull names into the boost namespace + using algorithm::erase_range_copy; + using algorithm::erase_range; + using algorithm::erase_first_copy; + using algorithm::erase_first; + using algorithm::ierase_first_copy; + using algorithm::ierase_first; + using algorithm::erase_last_copy; + using algorithm::erase_last; + using algorithm::ierase_last_copy; + using algorithm::ierase_last; + using algorithm::erase_nth_copy; + using algorithm::erase_nth; + using algorithm::ierase_nth_copy; + using algorithm::ierase_nth; + using algorithm::erase_all_copy; + using algorithm::erase_all; + using algorithm::ierase_all_copy; + using algorithm::ierase_all; + using algorithm::erase_head_copy; + using algorithm::erase_head; + using algorithm::erase_tail_copy; + using algorithm::erase_tail; + +} // namespace boost + + +#endif // BOOST_ERASE_HPP diff --git a/win32/include/boost/algorithm/string/find.hpp b/win32/include/boost/algorithm/string/find.hpp new file mode 100755 index 000000000..aa399a28f --- /dev/null +++ b/win32/include/boost/algorithm/string/find.hpp @@ -0,0 +1,334 @@ +// Boost string_algo library find.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FIND_HPP +#define BOOST_STRING_FIND_HPP + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/*! \file + Defines a set of find algorithms. The algorithms are searching + for a substring of the input. The result is given as an \c iterator_range + delimiting the substring. +*/ + +namespace boost { + namespace algorithm { + +// Generic find -----------------------------------------------// + + //! Generic find algorithm + /*! + Search the input using the given finder. + + \param Input A string which will be searched. + \param Finder Finder object used for searching. + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c RangeT::iterator or + \c RangeT::const_iterator, depending on the constness of + the input parameter. + */ + template + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator::type> + find( + RangeT& Input, + const FinderT& Finder) + { + iterator_range::type> lit_input(as_literal(Input)); + + return Finder(::boost::begin(lit_input),::boost::end(lit_input)); + } + +// find_first -----------------------------------------------// + + //! Find first algorithm + /*! + Search for the first occurrence of the substring in the input. + + \param Input A string which will be searched. + \param Search A substring to be searched for. + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c RangeT::iterator or + \c RangeT::const_iterator, depending on the constness of + the input parameter. + + \note This function provides the strong exception-safety guarantee + */ + template + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator::type> + find_first( + Range1T& Input, + const Range2T& Search) + { + return find(Input, first_finder(Search)); + } + + //! Find first algorithm ( case insensitive ) + /*! + Search for the first occurence of the substring in the input. + Searching is case insensitive. + + \param Input A string which will be searched. + \param Search A substring to be searched for. + \param Loc A locale used for case insensitive comparison + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c Range1T::iterator or + \c Range1T::const_iterator, depending on the constness of + the input parameter. + + \note This function provides the strong exception-safety guarantee + */ + template + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator::type> + ifind_first( + Range1T& Input, + const Range2T& Search, + const std::locale& Loc=std::locale()) + { + return find(Input, first_finder(Search,is_iequal(Loc))); + } + +// find_last -----------------------------------------------// + + //! Find last algorithm + /*! + Search for the last occurrence of the substring in the input. + + \param Input A string which will be searched. + \param Search A substring to be searched for. + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c Range1T::iterator or + \c Range1T::const_iterator, depending on the constness of + the input parameter. + + \note This function provides the strong exception-safety guarantee + */ + template + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator::type> + find_last( + Range1T& Input, + const Range2T& Search) + { + return find(Input, last_finder(Search)); + } + + //! Find last algorithm ( case insensitive ) + /*! + Search for the last match a string in the input. + Searching is case insensitive. + + \param Input A string which will be searched. + \param Search A substring to be searched for. + \param Loc A locale used for case insensitive comparison + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c Range1T::iterator or + \c Range1T::const_iterator, depending on the constness of + the input parameter. + + \note This function provides the strong exception-safety guarantee + */ + template + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator::type> + ifind_last( + Range1T& Input, + const Range2T& Search, + const std::locale& Loc=std::locale()) + { + return find(Input, last_finder(Search, is_iequal(Loc))); + } + +// find_nth ----------------------------------------------------------------------// + + //! Find n-th algorithm + /*! + Search for the n-th (zero-indexed) occurrence of the substring in the + input. + + \param Input A string which will be searched. + \param Search A substring to be searched for. + \param Nth An index (zero-indexed) of the match to be found. + For negative N, the matches are counted from the end of string. + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c Range1T::iterator or + \c Range1T::const_iterator, depending on the constness of + the input parameter. + */ + template + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator::type> + find_nth( + Range1T& Input, + const Range2T& Search, + int Nth) + { + return find(Input, nth_finder(Search,Nth)); + } + + //! Find n-th algorithm ( case insensitive ). + /*! + Search for the n-th (zero-indexed) occurrence of the substring in the + input. Searching is case insensitive. + + \param Input A string which will be searched. + \param Search A substring to be searched for. + \param Nth An index (zero-indexed) of the match to be found. + For negative N, the matches are counted from the end of string. + \param Loc A locale used for case insensitive comparison + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c Range1T::iterator or + \c Range1T::const_iterator, depending on the constness of + the input parameter. + + + \note This function provides the strong exception-safety guarantee + */ + template + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator::type> + ifind_nth( + Range1T& Input, + const Range2T& Search, + int Nth, + const std::locale& Loc=std::locale()) + { + return find(Input, nth_finder(Search,Nth,is_iequal(Loc))); + } + +// find_head ----------------------------------------------------------------------// + + //! Find head algorithm + /*! + Get the head of the input. Head is a prefix of the string of the + given size. If the input is shorter then required, whole input if considered + to be the head. + + \param Input An input string + \param N Length of the head + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c Range1T::iterator or + \c Range1T::const_iterator, depending on the constness of + the input parameter. + + \note This function provides the strong exception-safety guarantee + */ + template + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator::type> + find_head( + RangeT& Input, + int N) + { + return find(Input, head_finder(N)); + } + +// find_tail ----------------------------------------------------------------------// + + //! Find tail algorithm + /*! + Get the head of the input. Head is a suffix of the string of the + given size. If the input is shorter then required, whole input if considered + to be the tail. + + \param Input An input string + \param N Length of the tail. + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c RangeT::iterator or + \c RangeT::const_iterator, depending on the constness of + the input parameter. + + + \note This function provides the strong exception-safety guarantee + */ + template + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator::type> + find_tail( + RangeT& Input, + int N) + { + return find(Input, tail_finder(N)); + } + +// find_token --------------------------------------------------------------------// + + //! Find token algorithm + /*! + Look for a given token in the string. Token is a character that matches the + given predicate. + If the "token compress mode" is enabled, adjacent tokens are considered to be one match. + + \param Input A input string. + \param Pred An unary predicate to identify a token + \param eCompress Enable/Disable compressing of adjacent tokens + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c RangeT::iterator or + \c RangeT::const_iterator, depending on the constness of + the input parameter. + + \note This function provides the strong exception-safety guarantee + */ + template + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator::type> + find_token( + RangeT& Input, + PredicateT Pred, + token_compress_mode_type eCompress=token_compress_off) + { + return find(Input, token_finder(Pred, eCompress)); + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::find; + using algorithm::find_first; + using algorithm::ifind_first; + using algorithm::find_last; + using algorithm::ifind_last; + using algorithm::find_nth; + using algorithm::ifind_nth; + using algorithm::find_head; + using algorithm::find_tail; + using algorithm::find_token; + +} // namespace boost + + +#endif // BOOST_STRING_FIND_HPP diff --git a/win32/include/boost/algorithm/string/find_format.hpp b/win32/include/boost/algorithm/string/find_format.hpp new file mode 100755 index 000000000..971dee888 --- /dev/null +++ b/win32/include/boost/algorithm/string/find_format.hpp @@ -0,0 +1,269 @@ +// Boost string_algo library find_format.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FIND_FORMAT_HPP +#define BOOST_STRING_FIND_FORMAT_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/*! \file + Defines generic replace algorithms. Each algorithm replaces + part(s) of the input. The part to be replaced is looked up using a Finder object. + Result of finding is then used by a Formatter object to generate the replacement. +*/ + +namespace boost { + namespace algorithm { + +// generic replace -----------------------------------------------------------------// + + //! Generic replace algorithm + /*! + Use the Finder to search for a substring. Use the Formatter to format + this substring and replace it in the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input sequence + \param Finder A Finder object used to search for a match to be replaced + \param Formatter A Formatter object used to format a match + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT, + typename FinderT, + typename FormatterT> + inline OutputIteratorT find_format_copy( + OutputIteratorT Output, + const RangeT& Input, + FinderT Finder, + FormatterT Formatter ) + { + // Concept check + function_requires< + FinderConcept::type> >(); + function_requires< + FormatterConcept< + FormatterT, + FinderT,BOOST_STRING_TYPENAME range_const_iterator::type> >(); + + iterator_range::type> lit_input(as_literal(Input)); + + return detail::find_format_copy_impl( + Output, + lit_input, + Formatter, + Finder( ::boost::begin(lit_input), ::boost::end(lit_input) ) ); + } + + //! Generic replace algorithm + /*! + \overload + */ + template< + typename SequenceT, + typename FinderT, + typename FormatterT> + inline SequenceT find_format_copy( + const SequenceT& Input, + FinderT Finder, + FormatterT Formatter ) + { + // Concept check + function_requires< + FinderConcept::type> >(); + function_requires< + FormatterConcept< + FormatterT, + FinderT,BOOST_STRING_TYPENAME range_const_iterator::type> >(); + + return detail::find_format_copy_impl( + Input, + Formatter, + Finder(::boost::begin(Input), ::boost::end(Input))); + } + + //! Generic replace algorithm + /*! + Use the Finder to search for a substring. Use the Formatter to format + this substring and replace it in the input. The input is modified in-place. + + \param Input An input sequence + \param Finder A Finder object used to search for a match to be replaced + \param Formatter A Formatter object used to format a match + */ + template< + typename SequenceT, + typename FinderT, + typename FormatterT> + inline void find_format( + SequenceT& Input, + FinderT Finder, + FormatterT Formatter) + { + // Concept check + function_requires< + FinderConcept::type> >(); + function_requires< + FormatterConcept< + FormatterT, + FinderT,BOOST_STRING_TYPENAME range_const_iterator::type> >(); + + detail::find_format_impl( + Input, + Formatter, + Finder(::boost::begin(Input), ::boost::end(Input))); + } + + +// find_format_all generic ----------------------------------------------------------------// + + //! Generic replace all algorithm + /*! + Use the Finder to search for a substring. Use the Formatter to format + this substring and replace it in the input. Repeat this for all matching + substrings. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input sequence + \param Finder A Finder object used to search for a match to be replaced + \param Formatter A Formatter object used to format a match + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT, + typename FinderT, + typename FormatterT> + inline OutputIteratorT find_format_all_copy( + OutputIteratorT Output, + const RangeT& Input, + FinderT Finder, + FormatterT Formatter) + { + // Concept check + function_requires< + FinderConcept::type> >(); + function_requires< + FormatterConcept< + FormatterT, + FinderT,BOOST_STRING_TYPENAME range_const_iterator::type> >(); + + iterator_range::type> lit_input(as_literal(Input)); + + return detail::find_format_all_copy_impl( + Output, + lit_input, + Finder, + Formatter, + Finder(::boost::begin(lit_input), ::boost::end(lit_input))); + } + + //! Generic replace all algorithm + /*! + \overload + */ + template< + typename SequenceT, + typename FinderT, + typename FormatterT > + inline SequenceT find_format_all_copy( + const SequenceT& Input, + FinderT Finder, + FormatterT Formatter ) + { + // Concept check + function_requires< + FinderConcept::type> >(); + function_requires< + FormatterConcept< + FormatterT, + FinderT,BOOST_STRING_TYPENAME range_const_iterator::type> >(); + + return detail::find_format_all_copy_impl( + Input, + Finder, + Formatter, + Finder( ::boost::begin(Input), ::boost::end(Input) ) ); + } + + //! Generic replace all algorithm + /*! + Use the Finder to search for a substring. Use the Formatter to format + this substring and replace it in the input. Repeat this for all matching + substrings.The input is modified in-place. + + \param Input An input sequence + \param Finder A Finder object used to search for a match to be replaced + \param Formatter A Formatter object used to format a match + */ + template< + typename SequenceT, + typename FinderT, + typename FormatterT > + inline void find_format_all( + SequenceT& Input, + FinderT Finder, + FormatterT Formatter ) + { + // Concept check + function_requires< + FinderConcept::type> >(); + function_requires< + FormatterConcept< + FormatterT, + FinderT,BOOST_STRING_TYPENAME range_const_iterator::type> >(); + + detail::find_format_all_impl( + Input, + Finder, + Formatter, + Finder(::boost::begin(Input), ::boost::end(Input))); + + } + + } // namespace algorithm + + // pull the names to the boost namespace + using algorithm::find_format_copy; + using algorithm::find_format; + using algorithm::find_format_all_copy; + using algorithm::find_format_all; + +} // namespace boost + + +#endif // BOOST_STRING_FIND_FORMAT_HPP diff --git a/win32/include/boost/algorithm/string/find_iterator.hpp b/win32/include/boost/algorithm/string/find_iterator.hpp new file mode 100755 index 000000000..23e1bb315 --- /dev/null +++ b/win32/include/boost/algorithm/string/find_iterator.hpp @@ -0,0 +1,375 @@ +// Boost string_algo library find_iterator.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2004. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FIND_ITERATOR_HPP +#define BOOST_STRING_FIND_ITERATOR_HPP + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +/*! \file + Defines find iterator classes. Find iterator repeatedly applies a Finder + to the specified input string to search for matches. Dereferencing + the iterator yields the current match or a range between the last and the current + match depending on the iterator used. +*/ + +namespace boost { + namespace algorithm { + +// find_iterator -----------------------------------------------// + + //! find_iterator + /*! + Find iterator encapsulates a Finder and allows + for incremental searching in a string. + Each increment moves the iterator to the next match. + + Find iterator is a readable forward traversal iterator. + + Dereferencing the iterator yields an iterator_range delimiting + the current match. + */ + template + class find_iterator : + public iterator_facade< + find_iterator, + const iterator_range, + forward_traversal_tag >, + private detail::find_iterator_base + { + private: + // facade support + friend class ::boost::iterator_core_access; + + private: + // typedefs + + typedef detail::find_iterator_base base_type; + typedef BOOST_STRING_TYPENAME + base_type::input_iterator_type input_iterator_type; + typedef BOOST_STRING_TYPENAME + base_type::match_type match_type; + + public: + //! Default constructor + /*! + Construct null iterator. All null iterators are equal. + + \post eof()==true + */ + find_iterator() {} + + //! Copy constructor + /*! + Construct a copy of the find_iterator + */ + find_iterator( const find_iterator& Other ) : + base_type(Other), + m_Match(Other.m_Match), + m_End(Other.m_End) {} + + //! Constructor + /*! + Construct new find_iterator for a given finder + and a range. + */ + template + find_iterator( + IteratorT Begin, + IteratorT End, + FinderT Finder ) : + detail::find_iterator_base(Finder,0), + m_Match(Begin,Begin), + m_End(End) + { + increment(); + } + + //! Constructor + /*! + Construct new find_iterator for a given finder + and a range. + */ + template + find_iterator( + RangeT& Col, + FinderT Finder ) : + detail::find_iterator_base(Finder,0) + { + iterator_range::type> lit_col(as_literal(Col)); + m_Match=make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col)); + m_End=::boost::end(lit_col); + + increment(); + } + + private: + // iterator operations + + // dereference + const match_type& dereference() const + { + return m_Match; + } + + // increment + void increment() + { + m_Match=this->do_find(m_Match.end(),m_End); + } + + // comparison + bool equal( const find_iterator& Other ) const + { + bool bEof=eof(); + bool bOtherEof=Other.eof(); + + return bEof || bOtherEof ? bEof==bOtherEof : + ( + m_Match==Other.m_Match && + m_End==Other.m_End + ); + } + + public: + // operations + + //! Eof check + /*! + Check the eof condition. Eof condition means that + there is nothing more to be searched i.e. find_iterator + is after the last match. + */ + bool eof() const + { + return + this->is_null() || + ( + m_Match.begin() == m_End && + m_Match.end() == m_End + ); + } + + private: + // Attributes + match_type m_Match; + input_iterator_type m_End; + }; + + //! find iterator construction helper + /*! + * Construct a find iterator to iterate through the specified string + */ + template + inline find_iterator< + BOOST_STRING_TYPENAME range_iterator::type> + make_find_iterator( + RangeT& Collection, + FinderT Finder) + { + return find_iterator::type>( + Collection, Finder); + } + +// split iterator -----------------------------------------------// + + //! split_iterator + /*! + Split iterator encapsulates a Finder and allows + for incremental searching in a string. + Unlike the find iterator, split iterator iterates + through gaps between matches. + + Find iterator is a readable forward traversal iterator. + + Dereferencing the iterator yields an iterator_range delimiting + the current match. + */ + template + class split_iterator : + public iterator_facade< + split_iterator, + const iterator_range, + forward_traversal_tag >, + private detail::find_iterator_base + { + private: + // facade support + friend class ::boost::iterator_core_access; + + private: + // typedefs + + typedef detail::find_iterator_base base_type; + typedef BOOST_STRING_TYPENAME + base_type::input_iterator_type input_iterator_type; + typedef BOOST_STRING_TYPENAME + base_type::match_type match_type; + + public: + //! Default constructor + /*! + Construct null iterator. All null iterators are equal. + + \post eof()==true + */ + split_iterator() {} + //! Copy constructor + /*! + Construct a copy of the split_iterator + */ + split_iterator( const split_iterator& Other ) : + base_type(Other), + m_Match(Other.m_Match), + m_Next(Other.m_Next), + m_End(Other.m_End), + m_bEof(false) + {} + + //! Constructor + /*! + Construct new split_iterator for a given finder + and a range. + */ + template + split_iterator( + IteratorT Begin, + IteratorT End, + FinderT Finder ) : + detail::find_iterator_base(Finder,0), + m_Match(Begin,Begin), + m_Next(Begin), + m_End(End), + m_bEof(false) + { + increment(); + } + //! Constructor + /*! + Construct new split_iterator for a given finder + and a collection. + */ + template + split_iterator( + RangeT& Col, + FinderT Finder ) : + detail::find_iterator_base(Finder,0), + m_bEof(false) + { + iterator_range::type> lit_col(as_literal(Col)); + m_Match=make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col)); + m_Next=::boost::begin(lit_col); + m_End=::boost::end(lit_col); + + increment(); + } + + + private: + // iterator operations + + // dereference + const match_type& dereference() const + { + return m_Match; + } + + // increment + void increment() + { + match_type FindMatch=this->do_find( m_Next, m_End ); + + if(FindMatch.begin()==m_End && FindMatch.end()==m_End) + { + if(m_Match.end()==m_End) + { + // Mark iterator as eof + m_bEof=true; + } + } + + m_Match=match_type( m_Next, FindMatch.begin() ); + m_Next=FindMatch.end(); + } + + // comparison + bool equal( const split_iterator& Other ) const + { + bool bEof=eof(); + bool bOtherEof=Other.eof(); + + return bEof || bOtherEof ? bEof==bOtherEof : + ( + m_Match==Other.m_Match && + m_Next==Other.m_Next && + m_End==Other.m_End + ); + } + + public: + // operations + + //! Eof check + /*! + Check the eof condition. Eof condition means that + there is nothing more to be searched i.e. find_iterator + is after the last match. + */ + bool eof() const + { + return this->is_null() || m_bEof; + } + + private: + // Attributes + match_type m_Match; + input_iterator_type m_Next; + input_iterator_type m_End; + bool m_bEof; + }; + + //! split iterator construction helper + /*! + * Construct a split iterator to iterate through the specified collection + */ + template + inline split_iterator< + BOOST_STRING_TYPENAME range_iterator::type> + make_split_iterator( + RangeT& Collection, + FinderT Finder) + { + return split_iterator::type>( + Collection, Finder); + } + + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::find_iterator; + using algorithm::make_find_iterator; + using algorithm::split_iterator; + using algorithm::make_split_iterator; + +} // namespace boost + + +#endif // BOOST_STRING_FIND_ITERATOR_HPP diff --git a/win32/include/boost/algorithm/string/finder.hpp b/win32/include/boost/algorithm/string/finder.hpp new file mode 100755 index 000000000..6c6064822 --- /dev/null +++ b/win32/include/boost/algorithm/string/finder.hpp @@ -0,0 +1,270 @@ +// Boost string_algo library finder.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2006. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FINDER_HPP +#define BOOST_STRING_FINDER_HPP + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/*! \file + Defines Finder generators. Finder object is a functor which is able to + find a substring matching a specific criteria in the input. + Finders are used as a pluggable components for replace, find + and split facilities. This header contains generator functions + for finders provided in this library. +*/ + +namespace boost { + namespace algorithm { + +// Finder generators ------------------------------------------// + + //! "First" finder + /*! + Construct the \c first_finder. The finder searches for the first + occurrence of the string in a given input. + The result is given as an \c iterator_range delimiting the match. + + \param Search A substring to be searched for. + \param Comp An element comparison predicate + \return An instance of the \c first_finder object + */ + template + inline detail::first_finderF< + BOOST_STRING_TYPENAME range_const_iterator::type, + is_equal> + first_finder( const RangeT& Search ) + { + return + detail::first_finderF< + BOOST_STRING_TYPENAME + range_const_iterator::type, + is_equal>( as_literal(Search), is_equal() ) ; + } + + //! "First" finder + /*! + \overload + */ + template + inline detail::first_finderF< + BOOST_STRING_TYPENAME range_const_iterator::type, + PredicateT> + first_finder( + const RangeT& Search, PredicateT Comp ) + { + return + detail::first_finderF< + BOOST_STRING_TYPENAME + range_const_iterator::type, + PredicateT>( as_literal(Search), Comp ); + } + + //! "Last" finder + /*! + Construct the \c last_finder. The finder searches for the last + occurrence of the string in a given input. + The result is given as an \c iterator_range delimiting the match. + + \param Search A substring to be searched for. + \param Comp An element comparison predicate + \return An instance of the \c last_finder object + */ + template + inline detail::last_finderF< + BOOST_STRING_TYPENAME range_const_iterator::type, + is_equal> + last_finder( const RangeT& Search ) + { + return + detail::last_finderF< + BOOST_STRING_TYPENAME + range_const_iterator::type, + is_equal>( as_literal(Search), is_equal() ); + } + //! "Last" finder + /*! + \overload + */ + template + inline detail::last_finderF< + BOOST_STRING_TYPENAME range_const_iterator::type, + PredicateT> + last_finder( const RangeT& Search, PredicateT Comp ) + { + return + detail::last_finderF< + BOOST_STRING_TYPENAME + range_const_iterator::type, + PredicateT>( as_literal(Search), Comp ) ; + } + + //! "Nth" finder + /*! + Construct the \c nth_finder. The finder searches for the n-th (zero-indexed) + occurrence of the string in a given input. + The result is given as an \c iterator_range delimiting the match. + + \param Search A substring to be searched for. + \param Nth An index of the match to be find + \param Comp An element comparison predicate + \return An instance of the \c nth_finder object + */ + template + inline detail::nth_finderF< + BOOST_STRING_TYPENAME range_const_iterator::type, + is_equal> + nth_finder( + const RangeT& Search, + int Nth) + { + return + detail::nth_finderF< + BOOST_STRING_TYPENAME + range_const_iterator::type, + is_equal>( as_literal(Search), Nth, is_equal() ) ; + } + //! "Nth" finder + /*! + \overload + */ + template + inline detail::nth_finderF< + BOOST_STRING_TYPENAME range_const_iterator::type, + PredicateT> + nth_finder( + const RangeT& Search, + int Nth, + PredicateT Comp ) + { + return + detail::nth_finderF< + BOOST_STRING_TYPENAME + range_const_iterator::type, + PredicateT>( as_literal(Search), Nth, Comp ); + } + + //! "Head" finder + /*! + Construct the \c head_finder. The finder returns a head of a given + input. The head is a prefix of a string up to n elements in + size. If an input has less then n elements, whole input is + considered a head. + The result is given as an \c iterator_range delimiting the match. + + \param N The size of the head + \return An instance of the \c head_finder object + */ + inline detail::head_finderF + head_finder( int N ) + { + return detail::head_finderF(N); + } + + //! "Tail" finder + /*! + Construct the \c tail_finder. The finder returns a tail of a given + input. The tail is a suffix of a string up to n elements in + size. If an input has less then n elements, whole input is + considered a head. + The result is given as an \c iterator_range delimiting the match. + + \param N The size of the head + \return An instance of the \c tail_finder object + */ + inline detail::tail_finderF + tail_finder( int N ) + { + return detail::tail_finderF(N); + } + + //! "Token" finder + /*! + Construct the \c token_finder. The finder searches for a token + specified by a predicate. It is similar to std::find_if + algorithm, with an exception that it return a range of + instead of a single iterator. + + If "compress token mode" is enabled, adjacent matching tokens are + concatenated into one match. Thus the finder can be used to + search for continuous segments of characters satisfying the + given predicate. + + The result is given as an \c iterator_range delimiting the match. + + \param Pred An element selection predicate + \param eCompress Compress flag + \return An instance of the \c token_finder object + */ + template< typename PredicateT > + inline detail::token_finderF + token_finder( + PredicateT Pred, + token_compress_mode_type eCompress=token_compress_off ) + { + return detail::token_finderF( Pred, eCompress ); + } + + //! "Range" finder + /*! + Construct the \c range_finder. The finder does not perform + any operation. It simply returns the given range for + any input. + + \param Begin Beginning of the range + \param End End of the range + \param Range The range. + \return An instance of the \c range_finger object + */ + template< typename ForwardIteratorT > + inline detail::range_finderF + range_finder( + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + return detail::range_finderF( Begin, End ); + } + + //! "Range" finder + /*! + \overload + */ + template< typename ForwardIteratorT > + inline detail::range_finderF + range_finder( iterator_range Range ) + { + return detail::range_finderF( Range ); + } + + } // namespace algorithm + + // pull the names to the boost namespace + using algorithm::first_finder; + using algorithm::last_finder; + using algorithm::nth_finder; + using algorithm::head_finder; + using algorithm::tail_finder; + using algorithm::token_finder; + using algorithm::range_finder; + +} // namespace boost + + +#endif // BOOST_STRING_FINDER_HPP diff --git a/win32/include/boost/algorithm/string/formatter.hpp b/win32/include/boost/algorithm/string/formatter.hpp new file mode 100755 index 000000000..38eda1df0 --- /dev/null +++ b/win32/include/boost/algorithm/string/formatter.hpp @@ -0,0 +1,103 @@ +// Boost string_algo library formatter.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FORMATTER_HPP +#define BOOST_STRING_FORMATTER_HPP + +#include +#include +#include +#include + +#include + +/*! \file + Defines Formatter generators. Formatter is a functor which formats + a string according to given parameters. A Formatter works + in conjunction with a Finder. A Finder can provide additional information + for a specific Formatter. An example of such a cooperation is regex_finder + and regex_formatter. + + Formatters are used as pluggable components for replace facilities. + This header contains generator functions for the Formatters provided in this library. +*/ + +namespace boost { + namespace algorithm { + +// generic formatters ---------------------------------------------------------------// + + //! Constant formatter + /*! + Construct the \c const_formatter. Const formatter always returns + the same value, regardless of the parameter. + + \param Format A predefined value used as a result for formating + \return An instance of the \c const_formatter object. + */ + template + inline detail::const_formatF< + iterator_range< + BOOST_STRING_TYPENAME range_const_iterator::type> > + const_formatter(const RangeT& Format) + { + return detail::const_formatF< + iterator_range< + BOOST_STRING_TYPENAME range_const_iterator::type> >(as_literal(Format)); + } + + //! Identity formatter + /*! + Construct the \c identity_formatter. Identity formatter always returns + the parameter. + + \return An instance of the \c identity_formatter object. + */ + template + inline detail::identity_formatF< + iterator_range< + BOOST_STRING_TYPENAME range_const_iterator::type> > + identity_formatter() + { + return detail::identity_formatF< + iterator_range< + BOOST_STRING_TYPENAME range_const_iterator::type> >(); + } + + //! Empty formatter + /*! + Construct the \c empty_formatter. Empty formatter always returns an empty + sequence. + + \param Input container used to select a correct value_type for the + resulting empty_container<>. + \return An instance of the \c empty_formatter object. + */ + template + inline detail::empty_formatF< + BOOST_STRING_TYPENAME range_value::type> + empty_formatter(const RangeT&) + { + return detail::empty_formatF< + BOOST_STRING_TYPENAME range_value::type>(); + } + + + } // namespace algorithm + + // pull the names to the boost namespace + using algorithm::const_formatter; + using algorithm::identity_formatter; + using algorithm::empty_formatter; + +} // namespace boost + + +#endif // BOOST_FORMATTER_HPP diff --git a/win32/include/boost/algorithm/string/iter_find.hpp b/win32/include/boost/algorithm/string/iter_find.hpp new file mode 100755 index 000000000..e10c70c69 --- /dev/null +++ b/win32/include/boost/algorithm/string/iter_find.hpp @@ -0,0 +1,190 @@ +// Boost string_algo library iter_find.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_ITER_FIND_HPP +#define BOOST_STRING_ITER_FIND_HPP + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/*! \file + Defines generic split algorithms. Split algorithms can be + used to divide a sequence into several part according + to a given criteria. Result is given as a 'container + of containers' where elements are copies or references + to extracted parts. + + There are two algorithms provided. One iterates over matching + substrings, the other one over the gaps between these matches. +*/ + +namespace boost { + namespace algorithm { + +// iterate find ---------------------------------------------------// + + //! Iter find algorithm + /*! + This algorithm executes a given finder in iteration on the input, + until the end of input is reached, or no match is found. + Iteration is done using built-in find_iterator, so the real + searching is performed only when needed. + In each iteration new match is found and added to the result. + + \param Result A 'container container' to contain the result of search. + Both outer and inner container must have constructor taking a pair + of iterators as an argument. + Typical type of the result is + \c std::vector> + (each element of such a vector will container a range delimiting + a match). + \param Input A container which will be searched. + \param Finder A Finder object used for searching + \return A reference the result + + \note Prior content of the result will be overwritten. + */ + template< + typename SequenceSequenceT, + typename RangeT, + typename FinderT > + inline SequenceSequenceT& + iter_find( + SequenceSequenceT& Result, + RangeT& Input, + FinderT Finder ) + { + function_requires< + FinderConcept::type> >(); + + iterator_range::type> lit_input(as_literal(Input)); + + typedef BOOST_STRING_TYPENAME + range_iterator::type input_iterator_type; + typedef find_iterator find_iterator_type; + typedef detail::copy_iterator_rangeF< + BOOST_STRING_TYPENAME + range_value::type, + input_iterator_type> copy_range_type; + + input_iterator_type InputEnd=::boost::end(lit_input); + + typedef transform_iterator + transform_iter_type; + + transform_iter_type itBegin= + make_transform_iterator( + find_iterator_type( ::boost::begin(lit_input), InputEnd, Finder ), + copy_range_type()); + + transform_iter_type itEnd= + make_transform_iterator( + find_iterator_type(), + copy_range_type()); + + SequenceSequenceT Tmp(itBegin, itEnd); + + Result.swap(Tmp); + return Result; + } + +// iterate split ---------------------------------------------------// + + //! Split find algorithm + /*! + This algorithm executes a given finder in iteration on the input, + until the end of input is reached, or no match is found. + Iteration is done using built-in find_iterator, so the real + searching is performed only when needed. + Each match is used as a separator of segments. These segments are then + returned in the result. + + \param Result A 'container container' to container the result of search. + Both outer and inner container must have constructor taking a pair + of iterators as an argument. + Typical type of the result is + \c std::vector> + (each element of such a vector will container a range delimiting + a match). + \param Input A container which will be searched. + \param Finder A finder object used for searching + \return A reference the result + + \note Prior content of the result will be overwritten. + */ + template< + typename SequenceSequenceT, + typename RangeT, + typename FinderT > + inline SequenceSequenceT& + iter_split( + SequenceSequenceT& Result, + RangeT& Input, + FinderT Finder ) + { + function_requires< + FinderConcept::type> >(); + + iterator_range::type> lit_input(as_literal(Input)); + + typedef BOOST_STRING_TYPENAME + range_iterator::type input_iterator_type; + typedef split_iterator find_iterator_type; + typedef detail::copy_iterator_rangeF< + BOOST_STRING_TYPENAME + range_value::type, + input_iterator_type> copy_range_type; + + input_iterator_type InputEnd=::boost::end(lit_input); + + typedef transform_iterator + transform_iter_type; + + transform_iter_type itBegin= + make_transform_iterator( + find_iterator_type( ::boost::begin(lit_input), InputEnd, Finder ), + copy_range_type() ); + + transform_iter_type itEnd= + make_transform_iterator( + find_iterator_type(), + copy_range_type() ); + + SequenceSequenceT Tmp(itBegin, itEnd); + + Result.swap(Tmp); + return Result; + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::iter_find; + using algorithm::iter_split; + +} // namespace boost + + +#endif // BOOST_STRING_ITER_FIND_HPP diff --git a/win32/include/boost/algorithm/string/join.hpp b/win32/include/boost/algorithm/string/join.hpp new file mode 100755 index 000000000..1c7e5eae7 --- /dev/null +++ b/win32/include/boost/algorithm/string/join.hpp @@ -0,0 +1,145 @@ +// Boost string_algo library join.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2006. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_JOIN_HPP +#define BOOST_STRING_JOIN_HPP + +#include +#include +#include +#include + +/*! \file + Defines join algorithm. + + Join algorithm is a counterpart to split algorithms. + It joins strings from a 'list' by adding user defined separator. + Additionally there is a version that allows simple filtering + by providing a predicate. +*/ + +namespace boost { + namespace algorithm { + +// join --------------------------------------------------------------// + + //! Join algorithm + /*! + This algorithm joins all strings in a 'list' into one long string. + Segments are concatenated by given separator. + + \param Input A container that holds the input strings. It must be a container-of-containers. + \param Separator A string that will separate the joined segments. + \return Concatenated string. + + \note This function provides the strong exception-safety guarantee + */ + template< typename SequenceSequenceT, typename Range1T> + inline typename range_value::type + join( + const SequenceSequenceT& Input, + const Range1T& Separator) + { + // Define working types + typedef typename range_value::type ResultT; + typedef typename range_const_iterator::type InputIteratorT; + + // Parse input + InputIteratorT itBegin=::boost::begin(Input); + InputIteratorT itEnd=::boost::end(Input); + + // Construct container to hold the result + ResultT Result; + + // Append first element + if(itBegin!=itEnd) + { + detail::insert(Result, ::boost::end(Result), *itBegin); + ++itBegin; + } + + for(;itBegin!=itEnd; ++itBegin) + { + // Add separator + detail::insert(Result, ::boost::end(Result), as_literal(Separator)); + // Add element + detail::insert(Result, ::boost::end(Result), *itBegin); + } + + return Result; + } + +// join_if ----------------------------------------------------------// + + //! Conditional join algorithm + /*! + This algorithm joins all strings in a 'list' into one long string. + Segments are concatenated by given separator. Only segments that + satisfy the predicate will be added to the result. + + \param Input A container that holds the input strings. It must be a container-of-containers. + \param Separator A string that will separate the joined segments. + \param Pred A segment selection predicate + \return Concatenated string. + + \note This function provides the strong exception-safety guarantee + */ + template< typename SequenceSequenceT, typename Range1T, typename PredicateT> + inline typename range_value::type + join_if( + const SequenceSequenceT& Input, + const Range1T& Separator, + PredicateT Pred) + { + // Define working types + typedef typename range_value::type ResultT; + typedef typename range_const_iterator::type InputIteratorT; + + // Parse input + InputIteratorT itBegin=::boost::begin(Input); + InputIteratorT itEnd=::boost::end(Input); + + // Construct container to hold the result + ResultT Result; + + // Roll to the first element that will be added + while(itBegin!=itEnd && !Pred(*itBegin)) ++itBegin; + // Add this element + if(itBegin!=itEnd) + { + detail::insert(Result, ::boost::end(Result), *itBegin); + ++itBegin; + } + + for(;itBegin!=itEnd; ++itBegin) + { + if(Pred(*itBegin)) + { + // Add separator + detail::insert(Result, ::boost::end(Result), as_literal(Separator)); + // Add element + detail::insert(Result, ::boost::end(Result), *itBegin); + } + } + + return Result; + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::join; + using algorithm::join_if; + +} // namespace boost + + +#endif // BOOST_STRING_JOIN_HPP + diff --git a/win32/include/boost/algorithm/string/predicate.hpp b/win32/include/boost/algorithm/string/predicate.hpp new file mode 100755 index 000000000..6884f3af6 --- /dev/null +++ b/win32/include/boost/algorithm/string/predicate.hpp @@ -0,0 +1,475 @@ +// Boost string_algo library predicate.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_PREDICATE_HPP +#define BOOST_STRING_PREDICATE_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/*! \file boost/algorithm/string/predicate.hpp + Defines string-related predicates. + The predicates determine whether a substring is contained in the input string + under various conditions: a string starts with the substring, ends with the + substring, simply contains the substring or if both strings are equal. + Additionaly the algorithm \c all() checks all elements of a container to satisfy a + condition. + + All predicates provide the strong exception guarantee. +*/ + +namespace boost { + namespace algorithm { + +// starts_with predicate -----------------------------------------------// + + //! 'Starts with' predicate + /*! + This predicate holds when the test string is a prefix of the Input. + In other words, if the input starts with the test. + When the optional predicate is specified, it is used for character-wise + comparison. + + \param Input An input sequence + \param Test A test sequence + \param Comp An element comparison predicate + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template + inline bool starts_with( + const Range1T& Input, + const Range2T& Test, + PredicateT Comp) + { + iterator_range::type> lit_input(as_literal(Input)); + iterator_range::type> lit_test(as_literal(Test)); + + typedef BOOST_STRING_TYPENAME + range_const_iterator::type Iterator1T; + typedef BOOST_STRING_TYPENAME + range_const_iterator::type Iterator2T; + + Iterator1T InputEnd=::boost::end(lit_input); + Iterator2T TestEnd=::boost::end(lit_test); + + Iterator1T it=::boost::begin(lit_input); + Iterator2T pit=::boost::begin(lit_test); + for(; + it!=InputEnd && pit!=TestEnd; + ++it,++pit) + { + if( !(Comp(*it,*pit)) ) + return false; + } + + return pit==TestEnd; + } + + //! 'Starts with' predicate + /*! + \overload + */ + template + inline bool starts_with( + const Range1T& Input, + const Range2T& Test) + { + return starts_with(Input, Test, is_equal()); + } + + //! 'Starts with' predicate ( case insensitive ) + /*! + This predicate holds when the test string is a prefix of the Input. + In other words, if the input starts with the test. + Elements are compared case insensitively. + + \param Input An input sequence + \param Test A test sequence + \param Loc A locale used for case insensitive comparison + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template + inline bool istarts_with( + const Range1T& Input, + const Range2T& Test, + const std::locale& Loc=std::locale()) + { + return starts_with(Input, Test, is_iequal(Loc)); + } + + +// ends_with predicate -----------------------------------------------// + + //! 'Ends with' predicate + /*! + This predicate holds when the test string is a suffix of the Input. + In other words, if the input ends with the test. + When the optional predicate is specified, it is used for character-wise + comparison. + + + \param Input An input sequence + \param Test A test sequence + \param Comp An element comparison predicate + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template + inline bool ends_with( + const Range1T& Input, + const Range2T& Test, + PredicateT Comp) + { + iterator_range::type> lit_input(as_literal(Input)); + iterator_range::type> lit_test(as_literal(Test)); + + typedef BOOST_STRING_TYPENAME + range_const_iterator::type Iterator1T; + typedef BOOST_STRING_TYPENAME boost::detail:: + iterator_traits::iterator_category category; + + return detail:: + ends_with_iter_select( + ::boost::begin(lit_input), + ::boost::end(lit_input), + ::boost::begin(lit_test), + ::boost::end(lit_test), + Comp, + category()); + } + + + //! 'Ends with' predicate + /*! + \overload + */ + template + inline bool ends_with( + const Range1T& Input, + const Range2T& Test) + { + return ends_with(Input, Test, is_equal()); + } + + //! 'Ends with' predicate ( case insensitive ) + /*! + This predicate holds when the test container is a suffix of the Input. + In other words, if the input ends with the test. + Elements are compared case insensitively. + + \param Input An input sequence + \param Test A test sequence + \param Loc A locale used for case insensitive comparison + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template + inline bool iends_with( + const Range1T& Input, + const Range2T& Test, + const std::locale& Loc=std::locale()) + { + return ends_with(Input, Test, is_iequal(Loc)); + } + +// contains predicate -----------------------------------------------// + + //! 'Contains' predicate + /*! + This predicate holds when the test container is contained in the Input. + When the optional predicate is specified, it is used for character-wise + comparison. + + \param Input An input sequence + \param Test A test sequence + \param Comp An element comparison predicate + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template + inline bool contains( + const Range1T& Input, + const Range2T& Test, + PredicateT Comp) + { + iterator_range::type> lit_input(as_literal(Input)); + iterator_range::type> lit_test(as_literal(Test)); + + if (empty(lit_test)) + { + // Empty range is contained always + return true; + } + + // Use the temporary variable to make VACPP happy + bool bResult=(first_finder(lit_test,Comp)(::boost::begin(lit_input), ::boost::end(lit_input))); + return bResult; + } + + //! 'Contains' predicate + /*! + \overload + */ + template + inline bool contains( + const Range1T& Input, + const Range2T& Test) + { + return contains(Input, Test, is_equal()); + } + + //! 'Contains' predicate ( case insensitive ) + /*! + This predicate holds when the test container is contained in the Input. + Elements are compared case insensitively. + + \param Input An input sequence + \param Test A test sequence + \param Loc A locale used for case insensitive comparison + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template + inline bool icontains( + const Range1T& Input, + const Range2T& Test, + const std::locale& Loc=std::locale()) + { + return contains(Input, Test, is_iequal(Loc)); + } + +// equals predicate -----------------------------------------------// + + //! 'Equals' predicate + /*! + This predicate holds when the test container is equal to the + input container i.e. all elements in both containers are same. + When the optional predicate is specified, it is used for character-wise + comparison. + + \param Input An input sequence + \param Test A test sequence + \param Comp An element comparison predicate + \return The result of the test + + \note This is a two-way version of \c std::equal algorithm + + \note This function provides the strong exception-safety guarantee + */ + template + inline bool equals( + const Range1T& Input, + const Range2T& Test, + PredicateT Comp) + { + iterator_range::type> lit_input(as_literal(Input)); + iterator_range::type> lit_test(as_literal(Test)); + + typedef BOOST_STRING_TYPENAME + range_const_iterator::type Iterator1T; + typedef BOOST_STRING_TYPENAME + range_const_iterator::type Iterator2T; + + Iterator1T InputEnd=::boost::end(lit_input); + Iterator2T TestEnd=::boost::end(lit_test); + + Iterator1T it=::boost::begin(lit_input); + Iterator2T pit=::boost::begin(lit_test); + for(; + it!=InputEnd && pit!=TestEnd; + ++it,++pit) + { + if( !(Comp(*it,*pit)) ) + return false; + } + + return (pit==TestEnd) && (it==InputEnd); + } + + //! 'Equals' predicate + /*! + \overload + */ + template + inline bool equals( + const Range1T& Input, + const Range2T& Test) + { + return equals(Input, Test, is_equal()); + } + + //! 'Equals' predicate ( case insensitive ) + /*! + This predicate holds when the test container is equal to the + input container i.e. all elements in both containers are same. + Elements are compared case insensitively. + + \param Input An input sequence + \param Test A test sequence + \param Loc A locale used for case insensitive comparison + \return The result of the test + + \note This is a two-way version of \c std::equal algorithm + + \note This function provides the strong exception-safety guarantee + */ + template + inline bool iequals( + const Range1T& Input, + const Range2T& Test, + const std::locale& Loc=std::locale()) + { + return equals(Input, Test, is_iequal(Loc)); + } + +// lexicographical_compare predicate -----------------------------// + + //! Lexicographical compare predicate + /*! + This predicate is an overload of std::lexicographical_compare + for range arguments + + It check whether the first argument is lexicographically less + then the second one. + + If the optional predicate is specified, it is used for character-wise + comparison + + \param Arg1 First argument + \param Arg2 Second argument + \param Pred Comparison predicate + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template + inline bool lexicographical_compare( + const Range1T& Arg1, + const Range2T& Arg2, + PredicateT Pred) + { + iterator_range::type> lit_arg1(as_literal(Arg1)); + iterator_range::type> lit_arg2(as_literal(Arg2)); + + return std::lexicographical_compare( + ::boost::begin(lit_arg1), + ::boost::end(lit_arg1), + ::boost::begin(lit_arg2), + ::boost::end(lit_arg2), + Pred); + } + + //! Lexicographical compare predicate + /*! + \overload + */ + template + inline bool lexicographical_compare( + const Range1T& Arg1, + const Range2T& Arg2) + { + return lexicographical_compare(Arg1, Arg2, is_less()); + } + + //! Lexicographical compare predicate (case-insensitive) + /*! + This predicate is an overload of std::lexicographical_compare + for range arguments. + It check whether the first argument is lexicographically less + then the second one. + Elements are compared case insensitively + + + \param Arg1 First argument + \param Arg2 Second argument + \param Loc A locale used for case insensitive comparison + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template + inline bool ilexicographical_compare( + const Range1T& Arg1, + const Range2T& Arg2, + const std::locale& Loc=std::locale()) + { + return lexicographical_compare(Arg1, Arg2, is_iless(Loc)); + } + + +// all predicate -----------------------------------------------// + + //! 'All' predicate + /*! + This predicate holds it all its elements satisfy a given + condition, represented by the predicate. + + \param Input An input sequence + \param Pred A predicate + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template + inline bool all( + const RangeT& Input, + PredicateT Pred) + { + iterator_range::type> lit_input(as_literal(Input)); + + typedef BOOST_STRING_TYPENAME + range_const_iterator::type Iterator1T; + + Iterator1T InputEnd=::boost::end(lit_input); + for( Iterator1T It=::boost::begin(lit_input); It!=InputEnd; ++It) + { + if (!Pred(*It)) + return false; + } + + return true; + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::starts_with; + using algorithm::istarts_with; + using algorithm::ends_with; + using algorithm::iends_with; + using algorithm::contains; + using algorithm::icontains; + using algorithm::equals; + using algorithm::iequals; + using algorithm::all; + using algorithm::lexicographical_compare; + using algorithm::ilexicographical_compare; + +} // namespace boost + + +#endif // BOOST_STRING_PREDICATE_HPP diff --git a/win32/include/boost/algorithm/string/predicate_facade.hpp b/win32/include/boost/algorithm/string/predicate_facade.hpp new file mode 100755 index 000000000..c9d4881b4 --- /dev/null +++ b/win32/include/boost/algorithm/string/predicate_facade.hpp @@ -0,0 +1,42 @@ +// Boost string_algo library predicate_facade.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_PREDICATE_FACADE_HPP +#define BOOST_STRING_PREDICATE_FACADE_HPP + +#include + +/* + \file boost/algorith/string/predicate_facade.hpp + This file containes predicate_facade definition. This template class is used + to identify classification predicates, so they can be combined using + composition operators. +*/ + +namespace boost { + namespace algorithm { + +// predicate facade ------------------------------------------------------// + + //! Predicate facade + /*! + This class allows to recognize classification + predicates, so that they can be combined using + composition operators. + Every classification predicate must be derived from this class. + */ + template + struct predicate_facade {}; + + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_CLASSIFICATION_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string/regex.hpp b/win32/include/boost/algorithm/string/regex.hpp new file mode 100755 index 000000000..6f847a89a --- /dev/null +++ b/win32/include/boost/algorithm/string/regex.hpp @@ -0,0 +1,646 @@ +// Boost string_algo library regex.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_REGEX_HPP +#define BOOST_STRING_REGEX_HPP + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/*! \file + Defines regex variants of the algorithms. +*/ + +namespace boost { + namespace algorithm { + +// find_regex -----------------------------------------------// + + //! Find regex algorithm + /*! + Search for a substring matching the given regex in the input. + + \param Input A container which will be searched. + \param Rx A regular expression + \param Flags Regex options + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c RangeT::iterator or + \c RangeT::const_iterator, depending on the constness of + the input parameter. + + \note This function provides the strong exception-safety guarantee + */ + template< + typename RangeT, + typename CharT, + typename RegexTraitsT> + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator::type > + find_regex( + RangeT& Input, + const basic_regex& Rx, + match_flag_type Flags=match_default ) + { + iterator_range::type> lit_input(as_literal(Input)); + + return regex_finder(Rx,Flags)( + ::boost::begin(lit_input), ::boost::end(lit_input) ); + } + +// replace_regex --------------------------------------------------------------------// + + //! Replace regex algorithm + /*! + Search for a substring matching given regex and format it with + the specified format. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Rx A regular expression + \param Format Regex format definition + \param Flags Regex options + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT, + typename CharT, + typename RegexTraitsT, + typename FormatStringTraitsT, typename FormatStringAllocatorT > + inline OutputIteratorT replace_regex_copy( + OutputIteratorT Output, + const RangeT& Input, + const basic_regex& Rx, + const std::basic_string& Format, + match_flag_type Flags=match_default | format_default ) + { + return find_format_copy( + Output, + Input, + regex_finder( Rx, Flags ), + regex_formatter( Format, Flags ) ); + } + + //! Replace regex algorithm + /*! + \overload + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT, + typename FormatStringTraitsT, typename FormatStringAllocatorT > + inline SequenceT replace_regex_copy( + const SequenceT& Input, + const basic_regex& Rx, + const std::basic_string& Format, + match_flag_type Flags=match_default | format_default ) + { + return find_format_copy( + Input, + regex_finder( Rx, Flags ), + regex_formatter( Format, Flags ) ); + } + + //! Replace regex algorithm + /*! + Search for a substring matching given regex and format it with + the specified format. The input string is modified in-place. + + \param Input An input string + \param Rx A regular expression + \param Format Regex format definition + \param Flags Regex options + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT, + typename FormatStringTraitsT, typename FormatStringAllocatorT > + inline void replace_regex( + SequenceT& Input, + const basic_regex& Rx, + const std::basic_string& Format, + match_flag_type Flags=match_default | format_default ) + { + find_format( + Input, + regex_finder( Rx, Flags ), + regex_formatter( Format, Flags ) ); + } + +// replace_all_regex --------------------------------------------------------------------// + + //! Replace all regex algorithm + /*! + Format all substrings, matching given regex, with the specified format. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Rx A regular expression + \param Format Regex format definition + \param Flags Regex options + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT, + typename CharT, + typename RegexTraitsT, + typename FormatStringTraitsT, typename FormatStringAllocatorT > + inline OutputIteratorT replace_all_regex_copy( + OutputIteratorT Output, + const RangeT& Input, + const basic_regex& Rx, + const std::basic_string& Format, + match_flag_type Flags=match_default | format_default ) + { + return find_format_all_copy( + Output, + Input, + regex_finder( Rx, Flags ), + regex_formatter( Format, Flags ) ); + } + + //! Replace all regex algorithm + /*! + \overload + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT, + typename FormatStringTraitsT, typename FormatStringAllocatorT > + inline SequenceT replace_all_regex_copy( + const SequenceT& Input, + const basic_regex& Rx, + const std::basic_string& Format, + match_flag_type Flags=match_default | format_default ) + { + return find_format_all_copy( + Input, + regex_finder( Rx, Flags ), + regex_formatter( Format, Flags ) ); + } + + //! Replace all regex algorithm + /*! + Format all substrings, matching given regex, with the specified format. + The input string is modified in-place. + + \param Input An input string + \param Rx A regular expression + \param Format Regex format definition + \param Flags Regex options + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT, + typename FormatStringTraitsT, typename FormatStringAllocatorT > + inline void replace_all_regex( + SequenceT& Input, + const basic_regex& Rx, + const std::basic_string& Format, + match_flag_type Flags=match_default | format_default ) + { + find_format_all( + Input, + regex_finder( Rx, Flags ), + regex_formatter( Format, Flags ) ); + } + +// erase_regex --------------------------------------------------------------------// + + //! Erase regex algorithm + /*! + Remove a substring matching given regex from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Rx A regular expression + \param Flags Regex options + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT, + typename CharT, + typename RegexTraitsT > + inline OutputIteratorT erase_regex_copy( + OutputIteratorT Output, + const RangeT& Input, + const basic_regex& Rx, + match_flag_type Flags=match_default ) + { + return find_format_copy( + Output, + Input, + regex_finder( Rx, Flags ), + empty_formatter( Input ) ); + } + + //! Erase regex algorithm + /*! + \overload + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT > + inline SequenceT erase_regex_copy( + const SequenceT& Input, + const basic_regex& Rx, + match_flag_type Flags=match_default ) + { + return find_format_copy( + Input, + regex_finder( Rx, Flags ), + empty_formatter( Input ) ); + } + + //! Erase regex algorithm + /*! + Remove a substring matching given regex from the input. + The input string is modified in-place. + + \param Input An input string + \param Rx A regular expression + \param Flags Regex options + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT > + inline void erase_regex( + SequenceT& Input, + const basic_regex& Rx, + match_flag_type Flags=match_default ) + { + find_format( + Input, + regex_finder( Rx, Flags ), + empty_formatter( Input ) ); + } + +// erase_all_regex --------------------------------------------------------------------// + + //! Erase all regex algorithm + /*! + Erase all substrings, matching given regex, from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Rx A regular expression + \param Flags Regex options + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT, + typename CharT, + typename RegexTraitsT > + inline OutputIteratorT erase_all_regex_copy( + OutputIteratorT Output, + const RangeT& Input, + const basic_regex& Rx, + match_flag_type Flags=match_default ) + { + return find_format_all_copy( + Output, + Input, + regex_finder( Rx, Flags ), + empty_formatter( Input ) ); + } + + //! Erase all regex algorithm + /*! + \overload + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT > + inline SequenceT erase_all_regex_copy( + const SequenceT& Input, + const basic_regex& Rx, + match_flag_type Flags=match_default ) + { + return find_format_all_copy( + Input, + regex_finder( Rx, Flags ), + empty_formatter( Input ) ); + } + + //! Erase all regex algorithm + /*! + Erase all substrings, matching given regex, from the input. + The input string is modified in-place. + + \param Input An input string + \param Rx A regular expression + \param Flags Regex options + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT> + inline void erase_all_regex( + SequenceT& Input, + const basic_regex& Rx, + match_flag_type Flags=match_default ) + { + find_format_all( + Input, + regex_finder( Rx, Flags ), + empty_formatter( Input ) ); + } + +// find_all_regex ------------------------------------------------------------------// + + //! Find all regex algorithm + /*! + This algorithm finds all substrings matching the give regex + in the input. + + Each part is copied and added as a new element to the output container. + Thus the result container must be able to hold copies + of the matches (in a compatible structure like std::string) or + a reference to it (e.g. using the iterator range class). + Examples of such a container are \c std::vector + or \c std::list> + + \param Result A container that can hold copies of references to the substrings. + \param Input A container which will be searched. + \param Rx A regular expression + \param Flags Regex options + \return A reference to the result + + \note Prior content of the result will be overwritten. + + \note This function provides the strong exception-safety guarantee + */ + template< + typename SequenceSequenceT, + typename RangeT, + typename CharT, + typename RegexTraitsT > + inline SequenceSequenceT& find_all_regex( + SequenceSequenceT& Result, + const RangeT& Input, + const basic_regex& Rx, + match_flag_type Flags=match_default ) + { + return iter_find( + Result, + Input, + regex_finder(Rx,Flags) ); + } + +// split_regex ------------------------------------------------------------------// + + //! Split regex algorithm + /*! + Tokenize expression. This function is equivalent to C strtok. Input + sequence is split into tokens, separated by separators. Separator + is an every match of the given regex. + Each part is copied and added as a new element to the output container. + Thus the result container must be able to hold copies + of the matches (in a compatible structure like std::string) or + a reference to it (e.g. using the iterator range class). + Examples of such a container are \c std::vector + or \c std::list> + + \param Result A container that can hold copies of references to the substrings. + \param Input A container which will be searched. + \param Rx A regular expression + \param Flags Regex options + \return A reference to the result + + \note Prior content of the result will be overwritten. + + \note This function provides the strong exception-safety guarantee + */ + template< + typename SequenceSequenceT, + typename RangeT, + typename CharT, + typename RegexTraitsT > + inline SequenceSequenceT& split_regex( + SequenceSequenceT& Result, + const RangeT& Input, + const basic_regex& Rx, + match_flag_type Flags=match_default ) + { + return iter_split( + Result, + Input, + regex_finder(Rx,Flags) ); + } + +// join_if ------------------------------------------------------------------// + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + + //! Conditional join algorithm + /*! + This algorithm joins all strings in a 'list' into one long string. + Segments are concatenated by given separator. Only segments that + match the given regular expression will be added to the result + + This is a specialization of join_if algorithm. + + \param Input A container that holds the input strings. It must be a container-of-containers. + \param Separator A string that will separate the joined segments. + \param Rx A regular expression + \param Flags Regex options + \return Concatenated string. + + \note This function provides the strong exception-safety guarantee + */ + template< + typename SequenceSequenceT, + typename Range1T, + typename CharT, + typename RegexTraitsT > + inline typename range_value::type + join_if( + const SequenceSequenceT& Input, + const Range1T& Separator, + const basic_regex& Rx, + match_flag_type Flags=match_default ) + { + // Define working types + typedef typename range_value::type ResultT; + typedef typename range_const_iterator::type InputIteratorT; + + // Parse input + InputIteratorT itBegin=::boost::begin(Input); + InputIteratorT itEnd=::boost::end(Input); + + // Construct container to hold the result + ResultT Result; + + + // Roll to the first element that will be added + while( + itBegin!=itEnd && + !regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags)) ++itBegin; + + // Add this element + if(itBegin!=itEnd) + { + detail::insert(Result, ::boost::end(Result), *itBegin); + ++itBegin; + } + + for(;itBegin!=itEnd; ++itBegin) + { + if(regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags)) + { + // Add separator + detail::insert(Result, ::boost::end(Result), as_literal(Separator)); + // Add element + detail::insert(Result, ::boost::end(Result), *itBegin); + } + } + + return Result; + } + +#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING + + //! Conditional join algorithm + /*! + This algorithm joins all strings in a 'list' into one long string. + Segments are concatenated by given separator. Only segments that + match the given regular expression will be added to the result + + This is a specialization of join_if algorithm. + + \param Input A container that holds the input strings. It must be a container-of-containers. + \param Separator A string that will separate the joined segments. + \param Rx A regular expression + \param Flags Regex options + \return Concatenated string. + + \note This function provides the strong exception-safety guarantee + */ + template< + typename SequenceSequenceT, + typename Range1T, + typename CharT, + typename RegexTraitsT > + inline typename range_value::type + join_if_regex( + const SequenceSequenceT& Input, + const Range1T& Separator, + const basic_regex& Rx, + match_flag_type Flags=match_default ) + { + // Define working types + typedef typename range_value::type ResultT; + typedef typename range_const_iterator::type InputIteratorT; + + // Parse input + InputIteratorT itBegin=::boost::begin(Input); + InputIteratorT itEnd=::boost::end(Input); + + // Construct container to hold the result + ResultT Result; + + + // Roll to the first element that will be added + while( + itBegin!=itEnd && + !regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags)) ++itBegin; + + // Add this element + if(itBegin!=itEnd) + { + detail::insert(Result, ::boost::end(Result), *itBegin); + ++itBegin; + } + + for(;itBegin!=itEnd; ++itBegin) + { + if(regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags)) + { + // Add separator + detail::insert(Result, ::boost::end(Result), as_literal(Separator)); + // Add element + detail::insert(Result, ::boost::end(Result), *itBegin); + } + } + + return Result; + } + + +#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING + + } // namespace algorithm + + // pull names into the boost namespace + using algorithm::find_regex; + using algorithm::replace_regex; + using algorithm::replace_regex_copy; + using algorithm::replace_all_regex; + using algorithm::replace_all_regex_copy; + using algorithm::erase_regex; + using algorithm::erase_regex_copy; + using algorithm::erase_all_regex; + using algorithm::erase_all_regex_copy; + using algorithm::find_all_regex; + using algorithm::split_regex; + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + using algorithm::join_if; +#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING + using algorithm::join_if_regex; +#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +} // namespace boost + + +#endif // BOOST_STRING_REGEX_HPP diff --git a/win32/include/boost/algorithm/string/regex_find_format.hpp b/win32/include/boost/algorithm/string/regex_find_format.hpp new file mode 100755 index 000000000..9f861acdf --- /dev/null +++ b/win32/include/boost/algorithm/string/regex_find_format.hpp @@ -0,0 +1,90 @@ +// Boost string_algo library regex_find_format.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_REGEX_FIND_FORMAT_HPP +#define BOOST_STRING_REGEX_FIND_FORMAT_HPP + +#include +#include +#include +#include + +/*! \file + Defines the \c regex_finder and \c regex_formatter generators. These two functors + are designed to work together. \c regex_formatter uses additional information + about a match contained in the regex_finder search result. +*/ + +namespace boost { + namespace algorithm { + +// regex_finder -----------------------------------------------// + + //! "Regex" finder + /*! + Construct the \c regex_finder. Finder uses the regex engine to search + for a match. + Result is given in \c regex_search_result. This is an extension + of the iterator_range. In addition it containes match results + from the \c regex_search algorithm. + + \param Rx A regular expression + \param MatchFlags Regex search options + \return An instance of the \c regex_finder object + */ + template< + typename CharT, + typename RegexTraitsT> + inline detail::find_regexF< basic_regex > + regex_finder( + const basic_regex& Rx, + match_flag_type MatchFlags=match_default ) + { + return detail:: + find_regexF< + basic_regex >( Rx, MatchFlags ); + } + +// regex_formater ---------------------------------------------// + + //! Regex formatter + /*! + Construct the \c regex_formatter. Regex formatter uses the regex engine to + format a match found by the \c regex_finder. + This formatted it designed to closely cooperate with \c regex_finder. + + \param Format Regex format definition + \param Flags Format flags + \return An instance of the \c regex_formatter functor + */ + template< + typename CharT, + typename TraitsT, typename AllocT > + inline detail::regex_formatF< std::basic_string< CharT, TraitsT, AllocT > > + regex_formatter( + const std::basic_string& Format, + match_flag_type Flags=format_default ) + { + return + detail::regex_formatF< std::basic_string >( + Format, + Flags ); + } + + } // namespace algorithm + + // pull the names to the boost namespace + using algorithm::regex_finder; + using algorithm::regex_formatter; + +} // namespace boost + + +#endif // BOOST_STRING_REGEX_FIND_FORMAT_HPP diff --git a/win32/include/boost/algorithm/string/replace.hpp b/win32/include/boost/algorithm/string/replace.hpp new file mode 100755 index 000000000..c56198bbe --- /dev/null +++ b/win32/include/boost/algorithm/string/replace.hpp @@ -0,0 +1,928 @@ +// Boost string_algo library replace.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2006. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_REPLACE_HPP +#define BOOST_STRING_REPLACE_HPP + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/*! \file + Defines various replace algorithms. Each algorithm replaces + part(s) of the input according to set of searching and replace criteria. +*/ + +namespace boost { + namespace algorithm { + +// replace_range --------------------------------------------------------------------// + + //! Replace range algorithm + /*! + Replace the given range in the input string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param SearchRange A range in the input to be substituted + \param Format A substitute string + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT replace_range_copy( + OutputIteratorT Output, + const Range1T& Input, + const iterator_range< + BOOST_STRING_TYPENAME + range_const_iterator::type>& SearchRange, + const Range2T& Format) + { + return find_format_copy( + Output, + Input, + range_finder(SearchRange), + const_formatter(Format)); + } + + //! Replace range algorithm + /*! + \overload + */ + template + inline SequenceT replace_range_copy( + const SequenceT& Input, + const iterator_range< + BOOST_STRING_TYPENAME + range_const_iterator::type>& SearchRange, + const RangeT& Format) + { + return find_format_copy( + Input, + range_finder(SearchRange), + const_formatter(Format)); + } + + //! Replace range algorithm + /*! + Replace the given range in the input string. + The input sequence is modified in-place. + + \param Input An input string + \param SearchRange A range in the input to be substituted + \param Format A substitute string + */ + template + inline void replace_range( + SequenceT& Input, + const iterator_range< + BOOST_STRING_TYPENAME + range_iterator::type>& SearchRange, + const RangeT& Format) + { + find_format( + Input, + range_finder(SearchRange), + const_formatter(Format)); + } + +// replace_first --------------------------------------------------------------------// + + //! Replace first algorithm + /*! + Replace the first match of the search substring in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT replace_first_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const Range3T& Format) + { + return find_format_copy( + Output, + Input, + first_finder(Search), + const_formatter(Format) ); + } + + //! Replace first algorithm + /*! + \overload + */ + template + inline SequenceT replace_first_copy( + const SequenceT& Input, + const Range1T& Search, + const Range2T& Format ) + { + return find_format_copy( + Input, + first_finder(Search), + const_formatter(Format) ); + } + + //! Replace first algorithm + /*! + replace the first match of the search substring in the input + with the format string. The input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + */ + template + inline void replace_first( + SequenceT& Input, + const Range1T& Search, + const Range2T& Format ) + { + find_format( + Input, + first_finder(Search), + const_formatter(Format) ); + } + +// replace_first ( case insensitive ) ---------------------------------------------// + + //! Replace first algorithm ( case insensitive ) + /*! + Replace the first match of the search substring in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT ireplace_first_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const Range3T& Format, + const std::locale& Loc=std::locale() ) + { + return find_format_copy( + Output, + Input, + first_finder(Search, is_iequal(Loc)), + const_formatter(Format) ); + } + + //! Replace first algorithm ( case insensitive ) + /*! + \overload + */ + template + inline SequenceT ireplace_first_copy( + const SequenceT& Input, + const Range2T& Search, + const Range1T& Format, + const std::locale& Loc=std::locale() ) + { + return find_format_copy( + Input, + first_finder(Search, is_iequal(Loc)), + const_formatter(Format) ); + } + + //! Replace first algorithm ( case insensitive ) + /*! + Replace the first match of the search substring in the input + with the format string. Input sequence is modified in-place. + Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + */ + template + inline void ireplace_first( + SequenceT& Input, + const Range1T& Search, + const Range2T& Format, + const std::locale& Loc=std::locale() ) + { + find_format( + Input, + first_finder(Search, is_iequal(Loc)), + const_formatter(Format) ); + } + +// replace_last --------------------------------------------------------------------// + + //! Replace last algorithm + /*! + Replace the last match of the search string in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT replace_last_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const Range3T& Format ) + { + return find_format_copy( + Output, + Input, + last_finder(Search), + const_formatter(Format) ); + } + + //! Replace last algorithm + /*! + \overload + */ + template + inline SequenceT replace_last_copy( + const SequenceT& Input, + const Range1T& Search, + const Range2T& Format ) + { + return find_format_copy( + Input, + last_finder(Search), + const_formatter(Format) ); + } + + //! Replace last algorithm + /*! + Replace the last match of the search string in the input + with the format string. Input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + */ + template + inline void replace_last( + SequenceT& Input, + const Range1T& Search, + const Range2T& Format ) + { + find_format( + Input, + last_finder(Search), + const_formatter(Format) ); + } + +// replace_last ( case insensitive ) -----------------------------------------------// + + //! Replace last algorithm ( case insensitive ) + /*! + Replace the last match of the search string in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT ireplace_last_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const Range3T& Format, + const std::locale& Loc=std::locale() ) + { + return find_format_copy( + Output, + Input, + last_finder(Search, is_iequal(Loc)), + const_formatter(Format) ); + } + + //! Replace last algorithm ( case insensitive ) + /*! + \overload + */ + template + inline SequenceT ireplace_last_copy( + const SequenceT& Input, + const Range1T& Search, + const Range2T& Format, + const std::locale& Loc=std::locale() ) + { + return find_format_copy( + Input, + last_finder(Search, is_iequal(Loc)), + const_formatter(Format) ); + } + + //! Replace last algorithm ( case insensitive ) + /*! + Replace the last match of the search string in the input + with the format string.The input sequence is modified in-place. + Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + \return A reference to the modified input + */ + template + inline void ireplace_last( + SequenceT& Input, + const Range1T& Search, + const Range2T& Format, + const std::locale& Loc=std::locale() ) + { + find_format( + Input, + last_finder(Search, is_iequal(Loc)), + const_formatter(Format) ); + } + +// replace_nth --------------------------------------------------------------------// + + //! Replace nth algorithm + /*! + Replace an Nth (zero-indexed) match of the search string in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + \param Format A substitute string + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT replace_nth_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + int Nth, + const Range3T& Format ) + { + return find_format_copy( + Output, + Input, + nth_finder(Search, Nth), + const_formatter(Format) ); + } + + //! Replace nth algorithm + /*! + \overload + */ + template + inline SequenceT replace_nth_copy( + const SequenceT& Input, + const Range1T& Search, + int Nth, + const Range2T& Format ) + { + return find_format_copy( + Input, + nth_finder(Search, Nth), + const_formatter(Format) ); + } + + //! Replace nth algorithm + /*! + Replace an Nth (zero-indexed) match of the search string in the input + with the format string. Input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + \param Format A substitute string + */ + template + inline void replace_nth( + SequenceT& Input, + const Range1T& Search, + int Nth, + const Range2T& Format ) + { + find_format( + Input, + nth_finder(Search, Nth), + const_formatter(Format) ); + } + +// replace_nth ( case insensitive ) -----------------------------------------------// + + //! Replace nth algorithm ( case insensitive ) + /*! + Replace an Nth (zero-indexed) match of the search string in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT ireplace_nth_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + int Nth, + const Range3T& Format, + const std::locale& Loc=std::locale() ) + { + return find_format_copy( + Output, + Input, + nth_finder(Search, Nth, is_iequal(Loc) ), + const_formatter(Format) ); + } + + //! Replace nth algorithm ( case insensitive ) + /*! + \overload + */ + template + inline SequenceT ireplace_nth_copy( + const SequenceT& Input, + const Range1T& Search, + int Nth, + const Range2T& Format, + const std::locale& Loc=std::locale() ) + { + return find_format_copy( + Input, + nth_finder(Search, Nth, is_iequal(Loc)), + const_formatter(Format) ); + } + + //! Replace nth algorithm ( case insensitive ) + /*! + Replace an Nth (zero-indexed) match of the search string in the input + with the format string. Input sequence is modified in-place. + Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + */ + template + inline void ireplace_nth( + SequenceT& Input, + const Range1T& Search, + int Nth, + const Range2T& Format, + const std::locale& Loc=std::locale() ) + { + find_format( + Input, + nth_finder(Search, Nth, is_iequal(Loc)), + const_formatter(Format) ); + } + +// replace_all --------------------------------------------------------------------// + + //! Replace all algorithm + /*! + Replace all occurrences of the search string in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT replace_all_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const Range3T& Format ) + { + return find_format_all_copy( + Output, + Input, + first_finder(Search), + const_formatter(Format) ); + } + + //! Replace all algorithm + /*! + \overload + */ + template + inline SequenceT replace_all_copy( + const SequenceT& Input, + const Range1T& Search, + const Range2T& Format ) + { + return find_format_all_copy( + Input, + first_finder(Search), + const_formatter(Format) ); + } + + //! Replace all algorithm + /*! + Replace all occurrences of the search string in the input + with the format string. The input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \return A reference to the modified input + */ + template + inline void replace_all( + SequenceT& Input, + const Range1T& Search, + const Range2T& Format ) + { + find_format_all( + Input, + first_finder(Search), + const_formatter(Format) ); + } + +// replace_all ( case insensitive ) -----------------------------------------------// + + //! Replace all algorithm ( case insensitive ) + /*! + Replace all occurrences of the search string in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT ireplace_all_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const Range3T& Format, + const std::locale& Loc=std::locale() ) + { + return find_format_all_copy( + Output, + Input, + first_finder(Search, is_iequal(Loc)), + const_formatter(Format) ); + } + + //! Replace all algorithm ( case insensitive ) + /*! + \overload + */ + template + inline SequenceT ireplace_all_copy( + const SequenceT& Input, + const Range1T& Search, + const Range2T& Format, + const std::locale& Loc=std::locale() ) + { + return find_format_all_copy( + Input, + first_finder(Search, is_iequal(Loc)), + const_formatter(Format) ); + } + + //! Replace all algorithm ( case insensitive ) + /*! + Replace all occurrences of the search string in the input + with the format string.The input sequence is modified in-place. + Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + */ + template + inline void ireplace_all( + SequenceT& Input, + const Range1T& Search, + const Range2T& Format, + const std::locale& Loc=std::locale() ) + { + find_format_all( + Input, + first_finder(Search, is_iequal(Loc)), + const_formatter(Format) ); + } + +// replace_head --------------------------------------------------------------------// + + //! Replace head algorithm + /*! + Replace the head of the input with the given format string. + The head is a prefix of a string of given size. + If the sequence is shorter then required, whole string if + considered to be the head. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param N Length of the head. + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + \param Format A substitute string + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT replace_head_copy( + OutputIteratorT Output, + const Range1T& Input, + int N, + const Range2T& Format ) + { + return find_format_copy( + Output, + Input, + head_finder(N), + const_formatter(Format) ); + } + + //! Replace head algorithm + /*! + \overload + */ + template + inline SequenceT replace_head_copy( + const SequenceT& Input, + int N, + const RangeT& Format ) + { + return find_format_copy( + Input, + head_finder(N), + const_formatter(Format) ); + } + + //! Replace head algorithm + /*! + Replace the head of the input with the given format string. + The head is a prefix of a string of given size. + If the sequence is shorter then required, the whole string is + considered to be the head. The input sequence is modified in-place. + + \param Input An input string + \param N Length of the head. + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + \param Format A substitute string + */ + template + inline void replace_head( + SequenceT& Input, + int N, + const RangeT& Format ) + { + find_format( + Input, + head_finder(N), + const_formatter(Format) ); + } + +// replace_tail --------------------------------------------------------------------// + + //! Replace tail algorithm + /*! + Replace the tail of the input with the given format string. + The tail is a suffix of a string of given size. + If the sequence is shorter then required, whole string is + considered to be the tail. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param N Length of the tail. + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + \param Format A substitute string + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT replace_tail_copy( + OutputIteratorT Output, + const Range1T& Input, + int N, + const Range2T& Format ) + { + return find_format_copy( + Output, + Input, + tail_finder(N), + const_formatter(Format) ); + } + + //! Replace tail algorithm + /*! + \overload + */ + template + inline SequenceT replace_tail_copy( + const SequenceT& Input, + int N, + const RangeT& Format ) + { + return find_format_copy( + Input, + tail_finder(N), + const_formatter(Format) ); + } + + //! Replace tail algorithm + /*! + Replace the tail of the input with the given format sequence. + The tail is a suffix of a string of given size. + If the sequence is shorter then required, the whole string is + considered to be the tail. The input sequence is modified in-place. + + \param Input An input string + \param N Length of the tail. + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + \param Format A substitute string + */ + template + inline void replace_tail( + SequenceT& Input, + int N, + const RangeT& Format ) + { + find_format( + Input, + tail_finder(N), + const_formatter(Format) ); + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::replace_range_copy; + using algorithm::replace_range; + using algorithm::replace_first_copy; + using algorithm::replace_first; + using algorithm::ireplace_first_copy; + using algorithm::ireplace_first; + using algorithm::replace_last_copy; + using algorithm::replace_last; + using algorithm::ireplace_last_copy; + using algorithm::ireplace_last; + using algorithm::replace_nth_copy; + using algorithm::replace_nth; + using algorithm::ireplace_nth_copy; + using algorithm::ireplace_nth; + using algorithm::replace_all_copy; + using algorithm::replace_all; + using algorithm::ireplace_all_copy; + using algorithm::ireplace_all; + using algorithm::replace_head_copy; + using algorithm::replace_head; + using algorithm::replace_tail_copy; + using algorithm::replace_tail; + +} // namespace boost + +#endif // BOOST_REPLACE_HPP diff --git a/win32/include/boost/algorithm/string/sequence_traits.hpp b/win32/include/boost/algorithm/string/sequence_traits.hpp new file mode 100755 index 000000000..f9f4a9c74 --- /dev/null +++ b/win32/include/boost/algorithm/string/sequence_traits.hpp @@ -0,0 +1,193 @@ +// Boost string_algo library sequence_traits.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_SEQUENCE_TRAITS_HPP +#define BOOST_STRING_SEQUENCE_TRAITS_HPP + +#include +#include +#include + +/*! \file + Traits defined in this header are used by various algorithms to achieve + better performance for specific containers. + Traits provide fail-safe defaults. If a container supports some of these + features, it is possible to specialize the specific trait for this container. + For lacking compilers, it is possible of define an override for a specific tester + function. + + Due to a language restriction, it is not currently possible to define specializations for + stl containers without including the corresponding header. To decrease the overhead + needed by this inclusion, user can selectively include a specialization + header for a specific container. They are located in boost/algorithm/string/stl + directory. Alternatively she can include boost/algorithm/string/std_collection_traits.hpp + header which contains specializations for all stl containers. +*/ + +namespace boost { + namespace algorithm { + +// sequence traits -----------------------------------------------// + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + //! Native replace tester + /*! + Declare an override of this tester function with return + type boost::string_algo::yes_type for a sequence with this property. + + \return yes_type if the container has basic_string like native replace + method. + */ + no_type has_native_replace_tester(...); + + //! Stable iterators tester + /*! + Declare an override of this tester function with return + type boost::string_algo::yes_type for a sequence with this property. + + \return yes_type if the sequence's insert/replace/erase methods do not invalidate + existing iterators. + */ + no_type has_stable_iterators_tester(...); + + //! const time insert tester + /*! + Declare an override of this tester function with return + type boost::string_algo::yes_type for a sequence with this property. + + \return yes_type if the sequence's insert method is working in constant time + */ + no_type has_const_time_insert_tester(...); + + //! const time erase tester + /*! + Declare an override of this tester function with return + type boost::string_algo::yes_type for a sequence with this property. + + \return yes_type if the sequence's erase method is working in constant time + */ + no_type has_const_time_erase_tester(...); + +#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + //! Native replace trait + /*! + This trait specifies that the sequence has \c std::string like replace method + */ + template< typename T > + class has_native_replace + { + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + private: + static T* t; + public: + BOOST_STATIC_CONSTANT(bool, value=( + sizeof(has_native_replace_tester(t))==sizeof(yes_type) ) ); +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + public: +# if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = false }; +# else + BOOST_STATIC_CONSTANT(bool, value=false); +# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + + typedef mpl::bool_::value> type; + }; + + + //! Stable iterators trait + /*! + This trait specifies that the sequence has stable iterators. It means + that operations like insert/erase/replace do not invalidate iterators. + */ + template< typename T > + class has_stable_iterators + { +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + private: + static T* t; + public: + BOOST_STATIC_CONSTANT(bool, value=( + sizeof(has_stable_iterators_tester(t))==sizeof(yes_type) ) ); +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + public: +# if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = false }; +# else + BOOST_STATIC_CONSTANT(bool, value=false); +# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + typedef mpl::bool_::value> type; + }; + + + //! Const time insert trait + /*! + This trait specifies that the sequence's insert method has + constant time complexity. + */ + template< typename T > + class has_const_time_insert + { +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + private: + static T* t; + public: + BOOST_STATIC_CONSTANT(bool, value=( + sizeof(has_const_time_insert_tester(t))==sizeof(yes_type) ) ); +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + public: +# if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = false }; +# else + BOOST_STATIC_CONSTANT(bool, value=false); +# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + typedef mpl::bool_::value> type; + }; + + + //! Const time erase trait + /*! + This trait specifies that the sequence's erase method has + constant time complexity. + */ + template< typename T > + class has_const_time_erase + { +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + private: + static T* t; + public: + BOOST_STATIC_CONSTANT(bool, value=( + sizeof(has_const_time_erase_tester(t))==sizeof(yes_type) ) ); +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + public: +# if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = false }; +# else + BOOST_STATIC_CONSTANT(bool, value=false); +# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + typedef mpl::bool_::value> type; + }; + + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_SEQUENCE_TRAITS_HPP diff --git a/win32/include/boost/algorithm/string/split.hpp b/win32/include/boost/algorithm/string/split.hpp new file mode 100755 index 000000000..297716ec8 --- /dev/null +++ b/win32/include/boost/algorithm/string/split.hpp @@ -0,0 +1,163 @@ +// Boost string_algo library split.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2006. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_SPLIT_HPP +#define BOOST_STRING_SPLIT_HPP + +#include + +#include +#include +#include + +/*! \file + Defines basic split algorithms. + Split algorithms can be used to divide a string + into several parts according to given criteria. + + Each part is copied and added as a new element to the + output container. + Thus the result container must be able to hold copies + of the matches (in a compatible structure like std::string) or + a reference to it (e.g. using the iterator range class). + Examples of such a container are \c std::vector + or \c std::list> +*/ + +namespace boost { + namespace algorithm { + +// find_all ------------------------------------------------------------// + + //! Find all algorithm + /*! + This algorithm finds all occurrences of the search string + in the input. + + Each part is copied and added as a new element to the + output container. + Thus the result container must be able to hold copies + of the matches (in a compatible structure like std::string) or + a reference to it (e.g. using the iterator range class). + Examples of such a container are \c std::vector + or \c std::list> + + \param Result A container that can hold copies of references to the substrings + \param Input A container which will be searched. + \param Search A substring to be searched for. + \return A reference the result + + \note Prior content of the result will be overwritten. + + \note This function provides the strong exception-safety guarantee + */ + template< typename SequenceSequenceT, typename Range1T, typename Range2T > + inline SequenceSequenceT& find_all( + SequenceSequenceT& Result, + Range1T& Input, + const Range2T& Search) + { + return iter_find( + Result, + Input, + first_finder(Search) ); + } + + //! Find all algorithm ( case insensitive ) + /*! + This algorithm finds all occurrences of the search string + in the input. + Each part is copied and added as a new element to the + output container. Thus the result container must be able to hold copies + of the matches (in a compatible structure like std::string) or + a reference to it (e.g. using the iterator range class). + Examples of such a container are \c std::vector + or \c std::list> + + Searching is case insensitive. + + \param Result A container that can hold copies of references to the substrings + \param Input A container which will be searched. + \param Search A substring to be searched for. + \param Loc A locale used for case insensitive comparison + \return A reference the result + + \note Prior content of the result will be overwritten. + + \note This function provides the strong exception-safety guarantee + */ + template< typename SequenceSequenceT, typename Range1T, typename Range2T > + inline SequenceSequenceT& ifind_all( + SequenceSequenceT& Result, + Range1T& Input, + const Range2T& Search, + const std::locale& Loc=std::locale() ) + { + return iter_find( + Result, + Input, + first_finder(Search, is_iequal(Loc) ) ); + } + + +// tokenize -------------------------------------------------------------// + + //! Split algorithm + /*! + Tokenize expression. This function is equivalent to C strtok. Input + sequence is split into tokens, separated by separators. Separators + are given by means of the predicate. + + Each part is copied and added as a new element to the + output container. + Thus the result container must be able to hold copies + of the matches (in a compatible structure like std::string) or + a reference to it (e.g. using the iterator range class). + Examples of such a container are \c std::vector + or \c std::list> + + \param Result A container that can hold copies of references to the substrings + \param Input A container which will be searched. + \param Pred A predicate to identify separators. This predicate is + supposed to return true if a given element is a separator. + \param eCompress If eCompress argument is set to token_compress_on, adjacent + separators are merged together. Otherwise, every two separators + delimit a token. + \return A reference the result + + \note Prior content of the result will be overwritten. + + \note This function provides the strong exception-safety guarantee + */ + template< typename SequenceSequenceT, typename RangeT, typename PredicateT > + inline SequenceSequenceT& split( + SequenceSequenceT& Result, + RangeT& Input, + PredicateT Pred, + token_compress_mode_type eCompress=token_compress_off ) + { + return iter_split( + Result, + Input, + token_finder( Pred, eCompress ) ); + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::find_all; + using algorithm::ifind_all; + using algorithm::split; + +} // namespace boost + + +#endif // BOOST_STRING_SPLIT_HPP + diff --git a/win32/include/boost/algorithm/string/std/list_traits.hpp b/win32/include/boost/algorithm/string/std/list_traits.hpp new file mode 100755 index 000000000..3f25f6374 --- /dev/null +++ b/win32/include/boost/algorithm/string/std/list_traits.hpp @@ -0,0 +1,85 @@ +// Boost string_algo library list_traits.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_STD_LIST_TRAITS_HPP +#define BOOST_STRING_STD_LIST_TRAITS_HPP + +#include +#include +#include + +namespace boost { + namespace algorithm { + +// std::list<> traits -----------------------------------------------// + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // stable iterators tester + template + yes_type has_stable_iterators_tester( const ::std::list* ); + + // const time insert tester + template + yes_type has_const_time_insert_tester( const ::std::list* ); + + // const time erase tester + template + yes_type has_const_time_erase_tester( const ::std::list* ); + + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // stable iterators trait + template + class has_stable_iterators< ::std::list > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_::value> type; + }; + + // const time insert trait + template + class has_const_time_insert< ::std::list > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_::value> type; + }; + + // const time erase trait + template + class has_const_time_erase< ::std::list > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_::value> type; + }; +#endif + + + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_STD_LIST_TRAITS_HPP diff --git a/win32/include/boost/algorithm/string/std/rope_traits.hpp b/win32/include/boost/algorithm/string/std/rope_traits.hpp new file mode 100755 index 000000000..e9ae03a94 --- /dev/null +++ b/win32/include/boost/algorithm/string/std/rope_traits.hpp @@ -0,0 +1,101 @@ +// Boost string_algo library string_traits.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_STD_ROPE_TRAITS_HPP +#define BOOST_STRING_STD_ROPE_TRAITS_HPP + +#include +#include +#include + +namespace boost { + namespace algorithm { + +// SGI's std::rope<> traits -----------------------------------------------// + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // native replace tester + template + yes_type has_native_replace_tester( const std::rope* ); + + // stable iterators tester + template + yes_type has_stable_iterators_tester( const std::rope* ); + + // const time insert tester + template + yes_type has_const_time_insert_tester( const std::rope* ); + + // const time erase tester + template + yes_type has_const_time_erase_tester( const std::rope* ); + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // native replace trait + template + class has_native_replace< std::rope > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_ type; + }; + + // stable iterators trait + template + class has_stable_iterators< std::rope > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_ type; + }; + + // const time insert trait + template + class has_const_time_insert< std::rope > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_ type; + }; + + // const time erase trait + template + class has_const_time_erase< std::rope > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_ type; + }; +#endif + + + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_ROPE_TRAITS_HPP diff --git a/win32/include/boost/algorithm/string/std/slist_traits.hpp b/win32/include/boost/algorithm/string/std/slist_traits.hpp new file mode 100755 index 000000000..c3cfe64e6 --- /dev/null +++ b/win32/include/boost/algorithm/string/std/slist_traits.hpp @@ -0,0 +1,85 @@ +// Boost string_algo library slist_traits.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_STD_SLIST_TRAITS_HPP +#define BOOST_STRING_STD_SLIST_TRAITS_HPP + +#include +#include +#include BOOST_SLIST_HEADER +#include + +namespace boost { + namespace algorithm { + +// SGI's std::slist<> traits -----------------------------------------------// + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // stable iterators tester + template + yes_type has_stable_iterators_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist* ); + + // const time insert tester + template + yes_type has_const_time_insert_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist* ); + + // const time erase tester + template + yes_type has_const_time_erase_tester( const BOOST_STD_EXTENSION_NAMESPACE::slist* ); + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // stable iterators trait + template + class has_stable_iterators< BOOST_STD_EXTENSION_NAMESPACE::slist > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_::value> type; + }; + + // const time insert trait + template + class has_const_time_insert< BOOST_STD_EXTENSION_NAMESPACE::slist > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_::value> type; + }; + + // const time erase trait + template + class has_const_time_erase< BOOST_STD_EXTENSION_NAMESPACE::slist > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_::value> type; + }; +#endif + + + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_STD_LIST_TRAITS_HPP diff --git a/win32/include/boost/algorithm/string/std/string_traits.hpp b/win32/include/boost/algorithm/string/std/string_traits.hpp new file mode 100755 index 000000000..e67a49a0a --- /dev/null +++ b/win32/include/boost/algorithm/string/std/string_traits.hpp @@ -0,0 +1,52 @@ +// Boost string_algo library string_traits.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_STD_STRING_TRAITS_HPP +#define BOOST_STRING_STD_STRING_TRAITS_HPP + +#include +#include +#include + +namespace boost { + namespace algorithm { + +// std::basic_string<> traits -----------------------------------------------// + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // native replace tester + template + yes_type has_native_replace_tester( const std::basic_string* ); + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // native replace trait + template + class has_native_replace< std::basic_string > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true } ; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + + typedef mpl::bool_::value> type; + }; + + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_LIST_TRAITS_HPP diff --git a/win32/include/boost/algorithm/string/std_containers_traits.hpp b/win32/include/boost/algorithm/string/std_containers_traits.hpp new file mode 100755 index 000000000..28dddc751 --- /dev/null +++ b/win32/include/boost/algorithm/string/std_containers_traits.hpp @@ -0,0 +1,26 @@ +// Boost string_algo library std_containers_traits.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_STD_CONTAINERS_TRAITS_HPP +#define BOOST_STRING_STD_CONTAINERS_TRAITS_HPP + +/*!\file + This file includes sequence traits for stl containers. +*/ + +#include +#include +#include + +#ifdef BOOST_HAS_SLIST +# include +#endif + +#endif // BOOST_STRING_STD_CONTAINERS_TRAITS_HPP diff --git a/win32/include/boost/algorithm/string/trim.hpp b/win32/include/boost/algorithm/string/trim.hpp new file mode 100755 index 000000000..5fbdd0d64 --- /dev/null +++ b/win32/include/boost/algorithm/string/trim.hpp @@ -0,0 +1,398 @@ +// Boost string_algo library trim.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_TRIM_HPP +#define BOOST_STRING_TRIM_HPP + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/*! \file + Defines trim algorithms. + Trim algorithms are used to remove trailing and leading spaces from a + sequence (string). Space is recognized using given locales. + + Parametric (\c _if) variants use a predicate (functor) to select which characters + are to be trimmed.. + Functions take a selection predicate as a parameter, which is used to determine + whether a character is a space. Common predicates are provided in classification.hpp header. + +*/ + +namespace boost { + namespace algorithm { + + // left trim -----------------------------------------------// + + + //! Left trim - parametric + /*! + Remove all leading spaces from the input. + The supplied predicate is used to determine which characters are considered spaces. + The result is a trimmed copy of the input. It is returned as a sequence + or copied to the output iterator + + \param Output An output iterator to which the result will be copied + \param Input An input range + \param IsSpace An unary predicate identifying spaces + \return + An output iterator pointing just after the last inserted character or + a copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template + inline OutputIteratorT trim_left_copy_if( + OutputIteratorT Output, + const RangeT& Input, + PredicateT IsSpace) + { + iterator_range::type> lit_range(as_literal(Input)); + + std::copy( + ::boost::algorithm::detail::trim_begin( + ::boost::begin(lit_range), + ::boost::end(lit_range), + IsSpace ), + ::boost::end(lit_range), + Output); + + return Output; + } + + //! Left trim - parametric + /*! + \overload + */ + template + inline SequenceT trim_left_copy_if(const SequenceT& Input, PredicateT IsSpace) + { + return SequenceT( + ::boost::algorithm::detail::trim_begin( + ::boost::begin(Input), + ::boost::end(Input), + IsSpace ), + ::boost::end(Input)); + } + + //! Left trim - parametric + /*! + Remove all leading spaces from the input. + The result is a trimmed copy of the input. + + \param Input An input sequence + \param Loc a locale used for 'space' classification + \return A trimmed copy of the input + + \note This function provides the strong exception-safety guarantee + */ + template + inline SequenceT trim_left_copy(const SequenceT& Input, const std::locale& Loc=std::locale()) + { + return + trim_left_copy_if( + Input, + is_space(Loc)); + } + + //! Left trim + /*! + Remove all leading spaces from the input. The supplied predicate is + used to determine which characters are considered spaces. + The input sequence is modified in-place. + + \param Input An input sequence + \param IsSpace An unary predicate identifying spaces + */ + template + inline void trim_left_if(SequenceT& Input, PredicateT IsSpace) + { + Input.erase( + ::boost::begin(Input), + ::boost::algorithm::detail::trim_begin( + ::boost::begin(Input), + ::boost::end(Input), + IsSpace)); + } + + //! Left trim + /*! + Remove all leading spaces from the input. + The Input sequence is modified in-place. + + \param Input An input sequence + \param Loc A locale used for 'space' classification + */ + template + inline void trim_left(SequenceT& Input, const std::locale& Loc=std::locale()) + { + trim_left_if( + Input, + is_space(Loc)); + } + + // right trim -----------------------------------------------// + + //! Right trim - parametric + /*! + Remove all trailing spaces from the input. + The supplied predicate is used to determine which characters are considered spaces. + The result is a trimmed copy of the input. It is returned as a sequence + or copied to the output iterator + + \param Output An output iterator to which the result will be copied + \param Input An input range + \param IsSpace An unary predicate identifying spaces + \return + An output iterator pointing just after the last inserted character or + a copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template + inline OutputIteratorT trim_right_copy_if( + OutputIteratorT Output, + const RangeT& Input, + PredicateT IsSpace ) + { + iterator_range::type> lit_range(as_literal(Input)); + + std::copy( + ::boost::begin(lit_range), + ::boost::algorithm::detail::trim_end( + ::boost::begin(lit_range), + ::boost::end(lit_range), + IsSpace ), + Output ); + + return Output; + } + + //! Right trim - parametric + /*! + \overload + */ + template + inline SequenceT trim_right_copy_if(const SequenceT& Input, PredicateT IsSpace) + { + return SequenceT( + ::boost::begin(Input), + ::boost::algorithm::detail::trim_end( + ::boost::begin(Input), + ::boost::end(Input), + IsSpace) + ); + } + + //! Right trim + /*! + Remove all trailing spaces from the input. + The result is a trimmed copy of the input + + \param Input An input sequence + \param Loc A locale used for 'space' classification + \return A trimmed copy of the input + + \note This function provides the strong exception-safety guarantee + */ + template + inline SequenceT trim_right_copy(const SequenceT& Input, const std::locale& Loc=std::locale()) + { + return + trim_right_copy_if( + Input, + is_space(Loc)); + } + + + //! Right trim - parametric + /*! + Remove all trailing spaces from the input. + The supplied predicate is used to determine which characters are considered spaces. + The input sequence is modified in-place. + + \param Input An input sequence + \param IsSpace An unary predicate identifying spaces + */ + template + inline void trim_right_if(SequenceT& Input, PredicateT IsSpace) + { + Input.erase( + ::boost::algorithm::detail::trim_end( + ::boost::begin(Input), + ::boost::end(Input), + IsSpace ), + ::boost::end(Input) + ); + } + + + //! Right trim + /*! + Remove all trailing spaces from the input. + The input sequence is modified in-place. + + \param Input An input sequence + \param Loc A locale used for 'space' classification + */ + template + inline void trim_right(SequenceT& Input, const std::locale& Loc=std::locale()) + { + trim_right_if( + Input, + is_space(Loc) ); + } + + // both side trim -----------------------------------------------// + + //! Trim - parametric + /*! + Remove all trailing and leading spaces from the input. + The supplied predicate is used to determine which characters are considered spaces. + The result is a trimmed copy of the input. It is returned as a sequence + or copied to the output iterator + + \param Output An output iterator to which the result will be copied + \param Input An input range + \param IsSpace An unary predicate identifying spaces + \return + An output iterator pointing just after the last inserted character or + a copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template + inline OutputIteratorT trim_copy_if( + OutputIteratorT Output, + const RangeT& Input, + PredicateT IsSpace) + { + iterator_range::type> lit_range(as_literal(Input)); + + BOOST_STRING_TYPENAME + range_const_iterator::type TrimEnd= + ::boost::algorithm::detail::trim_end( + ::boost::begin(lit_range), + ::boost::end(lit_range), + IsSpace); + + std::copy( + detail::trim_begin( + ::boost::begin(lit_range), TrimEnd, IsSpace), + TrimEnd, + Output + ); + + return Output; + } + + //! Trim - parametric + /*! + \overload + */ + template + inline SequenceT trim_copy_if(const SequenceT& Input, PredicateT IsSpace) + { + BOOST_STRING_TYPENAME + range_const_iterator::type TrimEnd= + ::boost::algorithm::detail::trim_end( + ::boost::begin(Input), + ::boost::end(Input), + IsSpace); + + return SequenceT( + detail::trim_begin( + ::boost::begin(Input), + TrimEnd, + IsSpace), + TrimEnd + ); + } + + //! Trim + /*! + Remove all leading and trailing spaces from the input. + The result is a trimmed copy of the input + + \param Input An input sequence + \param Loc A locale used for 'space' classification + \return A trimmed copy of the input + + \note This function provides the strong exception-safety guarantee + */ + template + inline SequenceT trim_copy( const SequenceT& Input, const std::locale& Loc=std::locale() ) + { + return + trim_copy_if( + Input, + is_space(Loc) ); + } + + //! Trim + /*! + Remove all leading and trailing spaces from the input. + The supplied predicate is used to determine which characters are considered spaces. + The input sequence is modified in-place. + + \param Input An input sequence + \param IsSpace An unary predicate identifying spaces + */ + template + inline void trim_if(SequenceT& Input, PredicateT IsSpace) + { + trim_right_if( Input, IsSpace ); + trim_left_if( Input, IsSpace ); + } + + //! Trim + /*! + Remove all leading and trailing spaces from the input. + The input sequence is modified in-place. + + \param Input An input sequence + \param Loc A locale used for 'space' classification + */ + template + inline void trim(SequenceT& Input, const std::locale& Loc=std::locale()) + { + trim_if( + Input, + is_space( Loc ) ); + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::trim_left; + using algorithm::trim_left_if; + using algorithm::trim_left_copy; + using algorithm::trim_left_copy_if; + using algorithm::trim_right; + using algorithm::trim_right_if; + using algorithm::trim_right_copy; + using algorithm::trim_right_copy_if; + using algorithm::trim; + using algorithm::trim_if; + using algorithm::trim_copy; + using algorithm::trim_copy_if; + +} // namespace boost + +#endif // BOOST_STRING_TRIM_HPP diff --git a/win32/include/boost/algorithm/string/yes_no_type.hpp b/win32/include/boost/algorithm/string/yes_no_type.hpp new file mode 100755 index 000000000..4109763c1 --- /dev/null +++ b/win32/include/boost/algorithm/string/yes_no_type.hpp @@ -0,0 +1,33 @@ +// Boost string_algo library yes_no_type.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_YES_NO_TYPE_DETAIL_HPP +#define BOOST_STRING_YES_NO_TYPE_DETAIL_HPP + +namespace boost { + namespace algorithm { + + // taken from boost mailing-list + // when yes_no_type will become officially + // a part of boost distribution, this header + // will be deprecated + template struct size_descriptor + { + typedef char (& type)[I]; + }; + + typedef size_descriptor<1>::type yes_type; + typedef size_descriptor<2>::type no_type; + + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_YES_NO_TYPE_DETAIL_HPP diff --git a/win32/include/boost/algorithm/string_regex.hpp b/win32/include/boost/algorithm/string_regex.hpp new file mode 100755 index 000000000..a77d04f02 --- /dev/null +++ b/win32/include/boost/algorithm/string_regex.hpp @@ -0,0 +1,23 @@ +// Boost string_algo library string_regex.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2004. +// +// 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) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_ALGO_REGEX_HPP +#define BOOST_STRING_ALGO_REGEX_HPP + +/*! \file + Cumulative include for string_algo library. + In addtion to string.hpp contains also regex-related stuff. +*/ + +#include +#include +#include + +#endif // BOOST_STRING_ALGO_REGEX_HPP diff --git a/win32/include/boost/aligned_storage.hpp b/win32/include/boost/aligned_storage.hpp new file mode 100755 index 000000000..1120cf8bb --- /dev/null +++ b/win32/include/boost/aligned_storage.hpp @@ -0,0 +1,170 @@ +//----------------------------------------------------------------------------- +// boost aligned_storage.hpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2002-2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ALIGNED_STORAGE_HPP +#define BOOST_ALIGNED_STORAGE_HPP + +#include // for std::size_t + +#include "boost/config.hpp" +#include "boost/detail/workaround.hpp" +#include "boost/type_traits/alignment_of.hpp" +#include "boost/type_traits/type_with_alignment.hpp" +#include "boost/type_traits/is_pod.hpp" + +#include "boost/mpl/eval_if.hpp" +#include "boost/mpl/identity.hpp" + +#include "boost/type_traits/detail/bool_trait_def.hpp" + +namespace boost { + +namespace detail { namespace aligned_storage { + +BOOST_STATIC_CONSTANT( + std::size_t + , alignment_of_max_align = ::boost::alignment_of::value + ); + +// +// To be TR1 conforming this must be a POD type: +// +template < + std::size_t size_ + , std::size_t alignment_ +> +struct aligned_storage_imp +{ + union data_t + { + char buf[size_]; + + typename mpl::eval_if_c< + alignment_ == std::size_t(-1) + , mpl::identity + , type_with_alignment + >::type align_; + } data_; +}; + +}} // namespace detail::aligned_storage + +template < + std::size_t size_ + , std::size_t alignment_ = std::size_t(-1) +> +class aligned_storage +{ +private: // representation + + detail::aligned_storage::aligned_storage_imp data_; + +public: // constants + + typedef detail::aligned_storage::aligned_storage_imp type; + + BOOST_STATIC_CONSTANT( + std::size_t + , size = size_ + ); + BOOST_STATIC_CONSTANT( + std::size_t + , alignment = ( + alignment_ == std::size_t(-1) + ? ::boost::detail::aligned_storage::alignment_of_max_align + : alignment_ + ) + ); + +#if defined(__GNUC__) &&\ + (__GNUC__ > 3) ||\ + (__GNUC__ == 3 && (__GNUC_MINOR__ > 2 ||\ + (__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ >=3))) + +private: // noncopyable + + aligned_storage(const aligned_storage&); + aligned_storage& operator=(const aligned_storage&); + +#else // gcc less than 3.2.3 + +public: // _should_ be noncopyable, but GCC compiler emits error + + aligned_storage(const aligned_storage&); + aligned_storage& operator=(const aligned_storage&); + +#endif // gcc < 3.2.3 workaround + +public: // structors + + aligned_storage() + { + } + + ~aligned_storage() + { + } + +public: // accessors + + void* address() + { + return this; + } + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + + const void* address() const + { + return this; + } + +#else // MSVC6 + + const void* address() const; + +#endif // MSVC6 workaround + +}; + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + +// MSVC6 seems not to like inline functions with const void* returns, so we +// declare the following here: + +template +const void* aligned_storage::address() const +{ + return const_cast< aligned_storage* >(this)->address(); +} + +#endif // MSVC6 workaround + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +// +// Make sure that is_pod recognises aligned_storage<>::type +// as a POD (Note that aligned_storage<> itself is not a POD): +// +template +struct is_pod > + BOOST_TT_AUX_BOOL_C_BASE(true) +{ + BOOST_TT_AUX_BOOL_TRAIT_VALUE_DECL(true) +}; +#endif + + +} // namespace boost + +#include "boost/type_traits/detail/bool_trait_undef.hpp" + +#endif // BOOST_ALIGNED_STORAGE_HPP diff --git a/win32/include/boost/any.hpp b/win32/include/boost/any.hpp new file mode 100755 index 000000000..4641b26b3 --- /dev/null +++ b/win32/include/boost/any.hpp @@ -0,0 +1,237 @@ +// See http://www.boost.org/libs/any for Documentation. + +#ifndef BOOST_ANY_INCLUDED +#define BOOST_ANY_INCLUDED + +// what: variant type boost::any +// who: contributed by Kevlin Henney, +// with features contributed and bugs found by +// Ed Brey, Mark Rodgers, Peter Dimov, and James Curran +// when: July 2001 +// where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95 + +#include +#include + +#include "boost/config.hpp" +#include +#include +#include +#include + +namespace boost +{ + class any + { + public: // structors + + any() + : content(0) + { + } + + template + any(const ValueType & value) + : content(new holder(value)) + { + } + + any(const any & other) + : content(other.content ? other.content->clone() : 0) + { + } + + ~any() + { + delete content; + } + + public: // modifiers + + any & swap(any & rhs) + { + std::swap(content, rhs.content); + return *this; + } + + template + any & operator=(const ValueType & rhs) + { + any(rhs).swap(*this); + return *this; + } + + any & operator=(const any & rhs) + { + any(rhs).swap(*this); + return *this; + } + + public: // queries + + bool empty() const + { + return !content; + } + + const std::type_info & type() const + { + return content ? content->type() : typeid(void); + } + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + private: // types +#else + public: // types (public so any_cast can be non-friend) +#endif + + class placeholder + { + public: // structors + + virtual ~placeholder() + { + } + + public: // queries + + virtual const std::type_info & type() const = 0; + + virtual placeholder * clone() const = 0; + + }; + + template + class holder : public placeholder + { + public: // structors + + holder(const ValueType & value) + : held(value) + { + } + + public: // queries + + virtual const std::type_info & type() const + { + return typeid(ValueType); + } + + virtual placeholder * clone() const + { + return new holder(held); + } + + public: // representation + + ValueType held; + + private: // intentionally left unimplemented + holder & operator=(const holder &); + }; + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + + private: // representation + + template + friend ValueType * any_cast(any *); + + template + friend ValueType * unsafe_any_cast(any *); + +#else + + public: // representation (public so any_cast can be non-friend) + +#endif + + placeholder * content; + + }; + + class bad_any_cast : public std::bad_cast + { + public: + virtual const char * what() const throw() + { + return "boost::bad_any_cast: " + "failed conversion using boost::any_cast"; + } + }; + + template + ValueType * any_cast(any * operand) + { + return operand && operand->type() == typeid(ValueType) + ? &static_cast *>(operand->content)->held + : 0; + } + + template + inline const ValueType * any_cast(const any * operand) + { + return any_cast(const_cast(operand)); + } + + template + ValueType any_cast(any & operand) + { + typedef BOOST_DEDUCED_TYPENAME remove_reference::type nonref; + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // If 'nonref' is still reference type, it means the user has not + // specialized 'remove_reference'. + + // Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro + // to generate specialization of remove_reference for your class + // See type traits library documentation for details + BOOST_STATIC_ASSERT(!is_reference::value); +#endif + + nonref * result = any_cast(&operand); + if(!result) + boost::throw_exception(bad_any_cast()); + return *result; + } + + template + inline ValueType any_cast(const any & operand) + { + typedef BOOST_DEDUCED_TYPENAME remove_reference::type nonref; + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // The comment in the above version of 'any_cast' explains when this + // assert is fired and what to do. + BOOST_STATIC_ASSERT(!is_reference::value); +#endif + + return any_cast(const_cast(operand)); + } + + // Note: The "unsafe" versions of any_cast are not part of the + // public interface and may be removed at any time. They are + // required where we know what type is stored in the any and can't + // use typeid() comparison, e.g., when our types may travel across + // different shared libraries. + template + inline ValueType * unsafe_any_cast(any * operand) + { + return &static_cast *>(operand->content)->held; + } + + template + inline const ValueType * unsafe_any_cast(const any * operand) + { + return unsafe_any_cast(const_cast(operand)); + } +} + +// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved. +// +// 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) + +#endif diff --git a/win32/include/boost/archive/add_facet.hpp b/win32/include/boost/archive/add_facet.hpp new file mode 100755 index 000000000..e50543ff0 --- /dev/null +++ b/win32/include/boost/archive/add_facet.hpp @@ -0,0 +1,55 @@ +#ifndef BOOST_ARCHIVE_ADD_FACET_HPP +#define BOOST_ARCHIVE_ADD_FACET_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// add_facet.hpp + +// (C) Copyright 2003 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include + +// does STLport uses native STL for locales? +#if (defined(__SGI_STL_PORT)&& defined(_STLP_NO_OWN_IOSTREAMS)) +// and this native STL lib is old Dinkumware (has not defined _CPPLIB_VER) +# if (defined(_YVALS) && !defined(__IBMCPP__)) || !defined(_CPPLIB_VER) +# define BOOST_ARCHIVE_OLD_DINKUMWARE_BENEATH_STLPORT +# endif +#endif + +namespace boost { +namespace archive { + +template +inline std::locale * +add_facet(const std::locale &l, Facet * f){ + return + #if defined BOOST_ARCHIVE_OLD_DINKUMWARE_BENEATH_STLPORT + // std namespace used for native locale + new std::locale(std::_Addfac(l, f)); + #elif BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) // old Dinkumwar + // std namespace used for native locale + new std::locale(std::_Addfac(l, f)); + #else + // standard compatible + new std::locale(l, f); + #endif +} + +} // namespace archive +} // namespace boost + +#undef BOOST_ARCHIVE_OLD_DINKUMWARE_BENEATH_STLPORT + +#endif // BOOST_ARCHIVE_ADD_FACET_HPP diff --git a/win32/include/boost/archive/archive_exception.hpp b/win32/include/boost/archive/archive_exception.hpp new file mode 100755 index 000000000..8433f0bb8 --- /dev/null +++ b/win32/include/boost/archive/archive_exception.hpp @@ -0,0 +1,115 @@ +#ifndef BOOST_ARCHIVE_ARCHIVE_EXCEPTION_HPP +#define BOOST_ARCHIVE_ARCHIVE_EXCEPTION_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// archive/archive_exception.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// exceptions thrown by archives +// +class archive_exception : + public virtual std::exception +{ +public: + typedef enum { + no_exception, // initialized without code + other_exception, // any excepton not listed below + unregistered_class, // attempt to serialize a pointer of an + // an unregistered class + invalid_signature, // first line of archive does not contain + // expected string + unsupported_version,// archive created with library version + // subsequent to this one + pointer_conflict, // an attempt has been made to directly + // serialization::detail an object + // after having already serialzed the same + // object through a pointer. Were this permited, + // it the archive load would result in the + // creation of an extra copy of the obect. + incompatible_native_format, // attempt to read native binary format + // on incompatible platform + array_size_too_short,// array being loaded doesn't fit in array allocated + stream_error, // i/o error on stream + invalid_class_name, // class name greater than the maximum permitted. + // most likely a corrupted archive or an attempt + // to insert virus via buffer overrun method. + unregistered_cast // base - derived relationship not registered with + // void_cast_register + } exception_code; + exception_code code; + archive_exception(exception_code c) : + code(c) + {} + virtual const char *what( ) const throw( ) + { + const char *msg = "programming error"; + switch(code){ + case no_exception: + msg = "uninitialized exception"; + break; + case unregistered_class: + msg = "unregistered class"; + break; + case invalid_signature: + msg = "invalid signature"; + break; + case unsupported_version: + msg = "unsupported version"; + break; + case pointer_conflict: + msg = "pointer conflict"; + break; + case incompatible_native_format: + msg = "incompatible native format"; + break; + case array_size_too_short: + msg = "array size too short"; + break; + case stream_error: + msg = "stream error"; + break; + case invalid_class_name: + msg = "class name too long"; + break; + case unregistered_cast: + msg = "unregistered void cast"; + break; + case other_exception: + // if get here - it indicates a derived exception + // was sliced by passing by value in catch + msg = "unknown derived exception"; + break; + default: + assert(false); + break; + } + return msg; + } +protected: + archive_exception() : + code(no_exception) + {} +}; + +}// namespace archive +}// namespace boost + +#endif //BOOST_ARCHIVE_ARCHIVE_EXCEPTION_HPP diff --git a/win32/include/boost/archive/basic_archive.hpp b/win32/include/boost/archive/basic_archive.hpp new file mode 100755 index 000000000..f26a3f692 --- /dev/null +++ b/win32/include/boost/archive/basic_archive.hpp @@ -0,0 +1,120 @@ +#ifndef BOOST_ARCHIVE_BASIC_ARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_ARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_archive.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include + +#include +#include // must be the last header + +namespace boost { +namespace archive { + +BOOST_STRONG_TYPEDEF(unsigned int, version_type) +BOOST_STRONG_TYPEDEF(int, class_id_type) +BOOST_STRONG_TYPEDEF(int, class_id_optional_type) +BOOST_STRONG_TYPEDEF(int, class_id_reference_type) +BOOST_STRONG_TYPEDEF(unsigned int, object_id_type) +BOOST_STRONG_TYPEDEF(unsigned int, object_reference_type) + +struct tracking_type { + typedef bool value_type; + bool t; + explicit tracking_type(const bool t_ = false) + : t(t_) + {}; + tracking_type(const tracking_type & t_) + : t(t_.t) + {} + operator bool () const { + return t; + }; + operator bool & () { + return t; + }; + tracking_type & operator=(const bool t_){ + t = t_; + return *this; + } + bool operator==(const tracking_type & rhs) const { + return t == rhs.t; + } + bool operator==(const bool & rhs) const { + return t == rhs; + } + tracking_type & operator=(const tracking_type & rhs){ + t = rhs.t; + return *this; + } +}; + +struct class_name_type : private boost::noncopyable { + char *t; + operator const char * & () const { + return const_cast(t); + } + operator char * () { + return t; + } + explicit class_name_type(const char *key_) + : t(const_cast(key_)){} + explicit class_name_type(char *key_) + : t(key_){} + class_name_type & operator=(const class_name_type & rhs){ + t = rhs.t; + return *this; + } +}; + +enum archive_flags { + no_header = 1, // suppress archive header info + no_codecvt = 2, // suppress alteration of codecvt facet + no_xml_tag_checking = 4, // suppress checking of xml tags + no_tracking = 8, // suppress ALL tracking + flags_last = 8 +}; + +#define NULL_POINTER_TAG class_id_type(-1) + +BOOST_ARCHIVE_DECL(const char *) +ARCHIVE_SIGNATURE(); + +BOOST_ARCHIVE_DECL(unsigned char) +ARCHIVE_VERSION(); + +}// namespace archive +}// namespace boost + +#include // pops abi_suffix.hpp pragmas + +#include + +// set implementation level to primitive for all types +// used internally by the serialization library + +BOOST_CLASS_IMPLEMENTATION(boost::archive::version_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::class_id_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::class_id_reference_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::class_id_optional_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::class_name_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::object_id_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::object_reference_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::tracking_type, primitive_type) + +#endif //BOOST_ARCHIVE_BASIC_ARCHIVE_HPP diff --git a/win32/include/boost/archive/basic_binary_iarchive.hpp b/win32/include/boost/archive/basic_binary_iarchive.hpp new file mode 100755 index 000000000..32e00380f --- /dev/null +++ b/win32/include/boost/archive/basic_binary_iarchive.hpp @@ -0,0 +1,125 @@ +#ifndef BOOST_ARCHIVE_BASIC_BINARY_IARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_BINARY_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_iarchive.hpp +// +// archives stored as native binary - this should be the fastest way +// to archive the state of a group of obects. It makes no attempt to +// convert to any canonical form. + +// IN GENERAL, ARCHIVES CREATED WITH THIS CLASS WILL NOT BE READABLE +// ON PLATFORM APART FROM THE ONE THEY ARE CREATED ON + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include + +#include +#include +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +///////////////////////////////////////////////////////////////////////// +// class basic_binary_iarchive - read serialized objects from a input binary stream +template +class basic_binary_iarchive : + public detail::common_iarchive +{ +protected: +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +public: +#elif defined(BOOST_MSVC) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_iarchive; +#else + friend class detail::interface_iarchive; +#endif + // intermediate level to support override of operators + // fot templates in the absence of partial function + // template ordering. If we get here pass to base class + // note extra nonsense to sneak it pass the borland compiers + typedef detail::common_iarchive detail_common_iarchive; + template + void load_override(T & t, BOOST_PFTO int version){ + this->detail_common_iarchive::load_override(t, static_cast(version)); + } + // binary files don't include the optional information + void load_override(class_id_optional_type & /* t */, int){} + + // the following have been overridden to provide specific sizes + // for these pseudo prmitive types. + void load_override(version_type & t, int){ + // upto 255 versions + unsigned char x=0; + * this->This() >> x; + t = version_type(x); + } + void load_override(class_id_type & t, int){ + // upto 32K classes + int_least16_t x=0; + * this->This() >> x; + t = class_id_type(x); + } + void load_override(class_id_reference_type & t, int){ + // upto 32K classes + int_least16_t x=0; + * this->This() >> x; + t = class_id_reference_type(x); + } + void load_override(object_id_type & t, int){ + // upto 2G objects + uint_least32_t x=0; + * this->This() >> x; + t = object_id_type(x); + } + void load_override(object_reference_type & t, int){ + // upto 2G objects + uint_least32_t x=0; + * this->This() >> x; + t = object_reference_type(x); + } + void load_override(tracking_type & t, int){ + char x=0; + * this->This() >> x; + t = (0 != x); + } + void load_override(serialization::collection_size_type & t, int){ + unsigned int x=0; + * this->This() >> x; + t = serialization::collection_size_type(x); + } + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_override(class_name_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + init(); + + basic_binary_iarchive(unsigned int flags) : + detail::common_iarchive(flags) + {} +}; + +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_BINARY_IARCHIVE_HPP diff --git a/win32/include/boost/archive/basic_binary_iprimitive.hpp b/win32/include/boost/archive/basic_binary_iprimitive.hpp new file mode 100755 index 000000000..0dfce4758 --- /dev/null +++ b/win32/include/boost/archive/basic_binary_iprimitive.hpp @@ -0,0 +1,177 @@ +#ifndef BOOST_ARCHIVE_BINARY_IPRIMITIVE_HPP +#define BOOST_ARCHIVE_BINARY_IPRIMITIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#if defined(_MSC_VER) +#pragma warning( disable : 4800 ) +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_iprimitive.hpp +// +// archives stored as native binary - this should be the fastest way +// to archive the state of a group of obects. It makes no attempt to +// convert to any canonical form. + +// IN GENERAL, ARCHIVES CREATED WITH THIS CLASS WILL NOT BE READABLE +// ON PLATFORM APART FROM THE ONE THEY ARE CREATED ON + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include +#include // std::memcpy +#include // std::size_t +#include // basic_streambuf +#include + +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; + using ::size_t; +} // namespace std +#endif + +#include +#include +#include +//#include +//#include + +#include +#include +#include +#include +#include +#include +#include // must be the last header + +namespace boost { +namespace archive { + +///////////////////////////////////////////////////////////////////////////// +// class binary_iarchive - read serialized objects from a input binary stream +template +class basic_binary_iprimitive +{ +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + friend class load_access; +protected: +#else +public: +#endif + std::basic_streambuf & m_sb; + // return a pointer to the most derived class + Archive * This(){ + return static_cast(this); + } + + #ifndef BOOST_NO_STD_LOCALE + boost::scoped_ptr archive_locale; + basic_streambuf_locale_saver locale_saver; + #endif + + // main template for serilization of primitive types + template + void load(T & t){ + load_binary(& t, sizeof(T)); + } + + ///////////////////////////////////////////////////////// + // fundamental types that need special treatment + + // trap usage of invalid uninitialized boolean + void load(bool & t){ + load_binary(& t, sizeof(t)); + int i = t; + assert(0 == i || 1 == i); + (void)i; // warning suppression for release builds. + } + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load(std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load(std::wstring &ws); + #endif + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load(char * t); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load(wchar_t * t); + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + init(); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + basic_binary_iprimitive( + std::basic_streambuf & sb, + bool no_codecvt + ); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~basic_binary_iprimitive(); +public: + // we provide an optimized load for all fundamental types + // typedef serialization::is_bitwise_serializable + // use_array_optimization; + struct use_array_optimization { + template + struct apply : public serialization::is_bitwise_serializable {}; + }; + + // the optimized load_array dispatches to load_binary + template + void load_array(serialization::array& a, unsigned int) + { + load_binary(a.address(),a.count()*sizeof(ValueType)); + } + + void + load_binary(void *address, std::size_t count); +}; + +template +inline void +basic_binary_iprimitive::load_binary( + void *address, + std::size_t count +){ + // note: an optimizer should eliminate the following for char files + std::streamsize s = count / sizeof(Elem); + std::streamsize scount = m_sb.sgetn( + static_cast(address), + s + ); + if(scount != static_cast(s)) + boost::throw_exception( + archive_exception(archive_exception::stream_error) + ); + // note: an optimizer should eliminate the following for char files + s = count % sizeof(Elem); + if(0 < s){ +// if(is.fail()) +// boost::throw_exception(archive_exception(archive_exception::stream_error)); + Elem t; + scount = m_sb.sgetn(& t, 1); + if(scount != 1) + boost::throw_exception( + archive_exception(archive_exception::stream_error) + ); + std::memcpy(static_cast(address) + (count - s), &t, s); + } +} + +} // namespace archive +} // namespace boost + +#include // pop pragams + +#endif // BOOST_ARCHIVE_BINARY_IPRIMITIVE_HPP diff --git a/win32/include/boost/archive/basic_binary_oarchive.hpp b/win32/include/boost/archive/basic_binary_oarchive.hpp new file mode 100755 index 000000000..67037c0a9 --- /dev/null +++ b/win32/include/boost/archive/basic_binary_oarchive.hpp @@ -0,0 +1,123 @@ +#ifndef BOOST_ARCHIVE_BASIC_BINARY_OARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_BINARY_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +// archives stored as native binary - this should be the fastest way +// to archive the state of a group of obects. It makes no attempt to +// convert to any canonical form. + +// IN GENERAL, ARCHIVES CREATED WITH THIS CLASS WILL NOT BE READABLE +// ON PLATFORM APART FROM THE ONE THEY ARE CREATE ON + +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// class basic_binary_oarchive - write serialized objects to a binary output stream +// note: this archive has no pretensions to portability. Archive format +// may vary across machine architectures and compilers. About the only +// guarentee is that an archive created with this code will be readable +// by a program built with the same tools for the same machne. This class +// does have the virtue of buiding the smalles archive in the minimum amount +// of time. So under some circumstances it may be he right choice. +template +class basic_binary_oarchive : + public archive::detail::common_oarchive +{ +protected: +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +public: +#elif defined(BOOST_MSVC) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_oarchive; +#else + friend class detail::interface_oarchive; +#endif + // any datatype not specifed below will be handled by base class + typedef detail::common_oarchive detail_common_oarchive; + template + void save_override(const T & t, BOOST_PFTO int version){ + this->detail_common_oarchive::save_override(t, static_cast(version)); + } + + // binary files don't include the optional information + void save_override(const class_id_optional_type & /* t */, int){} + + void save_override(const version_type & t, int){ + // upto 255 versions + // note:t.t resolves borland ambguity + const unsigned char x = t.t; + * this->This() << x; + } + void save_override(const class_id_type & t, int){ + // upto 32K classes + const int_least16_t x = t.t; + * this->This() << x; + } + void save_override(const class_id_reference_type & t, int){ + // upto 32K classes + const int_least16_t x = t.t; + * this->This() << x; + } + void save_override(const object_id_type & t, int){ + // upto 2G objects + const uint_least32_t x = t.t; + * this->This() << x; + } + void save_override(const object_reference_type & t, int){ + // upto 2G objects + uint_least32_t x = t.t; + * this->This() << x; + } + void save_override(const tracking_type & t, int){ + const char x = t.t; + * this->This() << x; + } + + // explicitly convert to char * to avoid compile ambiguities + void save_override(const class_name_type & t, int){ + const std::string s(t); + * this->This() << s; + } + + void save_override(const serialization::collection_size_type & t, int){ + // for backward compatibility, 64 bit integer or variable length integer would be preferred + unsigned int x = t.t; + * this->This() << x; + } + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + init(); + + basic_binary_oarchive(unsigned int flags) : + detail::common_oarchive(flags) + {} +}; + +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_BASIC_BINARY_OARCHIVE_HPP diff --git a/win32/include/boost/archive/basic_binary_oprimitive.hpp b/win32/include/boost/archive/basic_binary_oprimitive.hpp new file mode 100755 index 000000000..4439da9e3 --- /dev/null +++ b/win32/include/boost/archive/basic_binary_oprimitive.hpp @@ -0,0 +1,173 @@ +#ifndef BOOST_ARCHIVE_BASIC_BINARY_OPRIMITIVE_HPP +#define BOOST_ARCHIVE_BASIC_BINARY_OPRIMITIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_oprimitive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +// archives stored as native binary - this should be the fastest way +// to archive the state of a group of obects. It makes no attempt to +// convert to any canonical form. + +// IN GENERAL, ARCHIVES CREATED WITH THIS CLASS WILL NOT BE READABLE +// ON PLATFORM APART FROM THE ONE THEY ARE CREATE ON + +#include +#include +#include +#include // basic_streambuf +#include +#include // size_t + +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include +//#include +//#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include // must be the last header + +namespace boost { +namespace archive { + +///////////////////////////////////////////////////////////////////////// +// class basic_binary_oprimitive - binary output of prmitives + +template +class basic_binary_oprimitive +{ +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + friend class save_access; +protected: +#else +public: +#endif + std::basic_streambuf & m_sb; + // return a pointer to the most derived class + Archive * This(){ + return static_cast(this); + } + #ifndef BOOST_NO_STD_LOCALE + boost::scoped_ptr archive_locale; + basic_streambuf_locale_saver locale_saver; + #endif + // default saving of primitives. + template + void save(const T & t) + { + save_binary(& t, sizeof(T)); + } + + ///////////////////////////////////////////////////////// + // fundamental types that need special treatment + + // trap usage of invalid uninitialized boolean which would + // otherwise crash on load. + void save(const bool t){ + assert(0 == static_cast(t) || 1 == static_cast(t)); + save_binary(& t, sizeof(t)); + } + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save(const std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save(const std::wstring &ws); + #endif + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save(const char * t); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save(const wchar_t * t); + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + init(); + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + basic_binary_oprimitive( + std::basic_streambuf & sb, + bool no_codecvt + ); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~basic_binary_oprimitive(); +public: + + // we provide an optimized save for all fundamental types + // typedef serialization::is_bitwise_serializable + // use_array_optimization; + // workaround without using mpl lambdas + struct use_array_optimization { + template + struct apply : public boost::serialization::is_bitwise_serializable {}; + }; + + + // the optimized save_array dispatches to save_binary + template + void save_array(boost::serialization::array const& a, unsigned int) + { + save_binary(a.address(),a.count()*sizeof(ValueType)); + } + + void save_binary(const void *address, std::size_t count); +}; + +template +inline void +basic_binary_oprimitive::save_binary( + const void *address, + std::size_t count +){ + //assert( + // static_cast((std::numeric_limits::max)()) >= count + //); + // note: if the following assertions fail + // a likely cause is that the output stream is set to "text" + // mode where by cr characters recieve special treatment. + // be sure that the output stream is opened with ios::binary + //if(os.fail()) + // boost::throw_exception(archive_exception(archive_exception::stream_error)); + // figure number of elements to output - round up + count = ( count + sizeof(Elem) - 1) + / sizeof(Elem); + std::streamsize scount = m_sb.sputn( + static_cast(address), + count + ); + if(count != static_cast(scount)) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + //os.write( + // static_cast(address), + // count + //); + //assert(os.good()); +} + +} //namespace boost +} //namespace archive + +#include // pop pragams + +#endif // BOOST_ARCHIVE_BASIC_BINARY_OPRIMITIVE_HPP diff --git a/win32/include/boost/archive/basic_streambuf_locale_saver.hpp b/win32/include/boost/archive/basic_streambuf_locale_saver.hpp new file mode 100755 index 000000000..c546d92b2 --- /dev/null +++ b/win32/include/boost/archive/basic_streambuf_locale_saver.hpp @@ -0,0 +1,60 @@ +#ifndef BOOST_ARCHIVE_BASIC_STREAMBUF_LOCALE_SAVER_HPP +#define BOOST_ARCHIVE_BASIC_STREAMBUF_LOCALE_SAVER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_streambuf_local_saver.hpp + +// (C) Copyright 2005 Robert Ramey - http://www.rrsd.com + +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +// note derived from boost/io/ios_state.hpp +// Copyright 2002, 2005 Daryle Walker. Use, modification, and distribution +// are subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or a copy at .) + +// See for the library's home page. + +#ifndef BOOST_NO_STD_LOCALE + +#include // for std::locale +#include // for std::basic_streambuf + +namespace boost{ +namespace archive{ + +template < typename Ch, class Tr > +class basic_streambuf_locale_saver +{ +public: + typedef ::std::basic_streambuf state_type; + typedef ::std::locale aspect_type; + explicit basic_streambuf_locale_saver( state_type &s ) + : s_save_( s ), a_save_( s.getloc() ) + {} + basic_streambuf_locale_saver( state_type &s, aspect_type const &a ) + : s_save_( s ), a_save_( s.pubimbue(a) ) + {} + ~basic_streambuf_locale_saver() + { this->restore(); } + void restore() + { s_save_.pubimbue( a_save_ ); } +private: + state_type & s_save_; + aspect_type const a_save_; +}; + +} // archive +} // boost + +#endif // BOOST_NO_STD_LOCALE +#endif // BOOST_ARCHIVE_BASIC_STREAMBUF_LOCALE_SAVER_HPP diff --git a/win32/include/boost/archive/basic_text_iarchive.hpp b/win32/include/boost/archive/basic_text_iarchive.hpp new file mode 100755 index 000000000..f33722532 --- /dev/null +++ b/win32/include/boost/archive/basic_text_iarchive.hpp @@ -0,0 +1,84 @@ +#ifndef BOOST_ARCHIVE_BASIC_TEXT_IARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_TEXT_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +// archives stored as text - note these ar templated on the basic +// stream templates to accommodate wide (and other?) kind of characters +// +// note the fact that on libraries without wide characters, ostream is +// is not a specialization of basic_ostream which in fact is not defined +// in such cases. So we can't use basic_ostream but rather +// use two template parameters + +#include +#include +#include + +#include +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +///////////////////////////////////////////////////////////////////////// +// class basic_text_iarchive - read serialized objects from a input text stream +template +class basic_text_iarchive : + public detail::common_iarchive +{ +protected: +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +public: +#elif defined(BOOST_MSVC) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_iarchive; +#else + friend class detail::interface_iarchive; +#endif + // intermediate level to support override of operators + // fot templates in the absence of partial function + // template ordering + typedef detail::common_iarchive detail_common_iarchive; + template + void load_override(T & t, BOOST_PFTO int) + { + this->detail_common_iarchive::load_override(t, 0); + } + // text file don't include the optional information + void load_override(class_id_optional_type & /*t*/, int){} + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_override(class_name_type & t, int); + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + init(void); + + basic_text_iarchive(unsigned int flags) : + detail::common_iarchive(flags) + {} + ~basic_text_iarchive(){} +}; + +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_TEXT_IARCHIVE_HPP diff --git a/win32/include/boost/archive/basic_text_iprimitive.hpp b/win32/include/boost/archive/basic_text_iprimitive.hpp new file mode 100755 index 000000000..bc4fc9cde --- /dev/null +++ b/win32/include/boost/archive/basic_text_iprimitive.hpp @@ -0,0 +1,134 @@ +#ifndef BOOST_ARCHIVE_BASIC_TEXT_IPRIMITIVE_HPP +#define BOOST_ARCHIVE_BASIC_TEXT_IPRIMITIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_iprimitive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +// archives stored as text - note these ar templated on the basic +// stream templates to accommodate wide (and other?) kind of characters +// +// note the fact that on libraries without wide characters, ostream is +// is not a specialization of basic_ostream which in fact is not defined +// in such cases. So we can't use basic_ostream but rather +// use two template parameters + +#include +#include +#include // size_t + +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; + #if ! defined(BOOST_DINKUMWARE_STDLIB) && ! defined(__SGI_STL_PORT) + using ::locale; + #endif +} // namespace std +#endif + +#include +#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) +#include +#endif + +#include +#include +#include +#include + +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +///////////////////////////////////////////////////////////////////////// +// class basic_text_iarchive - load serialized objects from a input text stream +template +class basic_text_iprimitive +{ +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +protected: +#else +public: +#endif + IStream &is; + io::ios_flags_saver flags_saver; + io::ios_precision_saver precision_saver; + + #ifndef BOOST_NO_STD_LOCALE + boost::scoped_ptr archive_locale; + io::basic_ios_locale_saver< + BOOST_DEDUCED_TYPENAME IStream::char_type, BOOST_DEDUCED_TYPENAME IStream::traits_type + > locale_saver; + #endif + + template + void load(T & t) + { + if(is.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + is >> t; + } + void load(unsigned char & t) + { + if(is.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + unsigned short int i; + is >> i; + t = static_cast(i); + } + void load(signed char & t) + { + if(is.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + signed short int i; + is >> i; + t = static_cast(i); + } + void load(char & t) + { + if(is.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + short int i; + is >> i; + t = static_cast(i); + } + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + void load(wchar_t & t) + { + if(is.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + unsigned i; + is >> i; + t = static_cast(i); + } + #endif + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + basic_text_iprimitive(IStream &is, bool no_codecvt); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~basic_text_iprimitive(); +public: + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_binary(void *address, std::size_t count); +}; + +} // namespace archive +} // namespace boost + +#include // pop pragams + +#endif // BOOST_ARCHIVE_BASIC_TEXT_IPRIMITIVE_HPP diff --git a/win32/include/boost/archive/basic_text_oarchive.hpp b/win32/include/boost/archive/basic_text_oarchive.hpp new file mode 100755 index 000000000..3fbce2ff3 --- /dev/null +++ b/win32/include/boost/archive/basic_text_oarchive.hpp @@ -0,0 +1,134 @@ +#ifndef BOOST_ARCHIVE_BASIC_TEXT_OARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_TEXT_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +// archives stored as text - note these ar templated on the basic +// stream templates to accommodate wide (and other?) kind of characters +// +// note the fact that on libraries without wide characters, ostream is +// is not a specialization of basic_ostream which in fact is not defined +// in such cases. So we can't use basic_ostream but rather +// use two template parameters + +#include +#include +#include +#include + +#include +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +///////////////////////////////////////////////////////////////////////// +// class basic_text_oarchive +template +class basic_text_oarchive : + public detail::common_oarchive +{ +protected: +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ +|| BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x560)) +public: +#elif defined(BOOST_MSVC) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_oarchive; +#else + friend class detail::interface_oarchive; +#endif + enum { + none, + eol, + space + } delimiter; + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + newtoken(); + + void newline(){ + delimiter = eol; + } + + // default processing - kick back to base class. Note the + // extra stuff to get it passed borland compilers + typedef detail::common_oarchive detail_common_oarchive; + template + void save_override(T & t, BOOST_PFTO int){ + this->detail_common_oarchive::save_override(t, 0); + } + + // start new objects on a new line + void save_override(const object_id_type & t, int){ + this->This()->newline(); + // note extra .t to funciton with Borland 5.51 compiler + // and invoke prmitive to underlying value + this->This()->save(t.t); + } + + void save_override(const object_reference_type & t, int){ + this->This()->newline(); + // note extra .t to funciton with Borland 5.51 compiler + // and invoke prmitive to underlying value + this->This()->save(t.t); + } + + // note the following four overrides are necessary for some borland + // compilers(5.51) which don't handle BOOST_STRONG_TYPE properly. + void save_override(const version_type & t, int){ + // note:t.t resolves borland ambguity + const unsigned int x = t.t; + * this->This() << x; + } + void save_override(const class_id_type & t, int){ + // note:t.t resolves borland ambguity + const int x = t.t; + * this->This() << x; + } + void save_override(const class_id_reference_type & t, int){ + // note:t.t resolves borland ambguity + const int x = t.t; + * this->This() << x; + } + + // text file don't include the optional information + void save_override(const class_id_optional_type & /* t */, int){} + + void save_override(const class_name_type & t, int){ + const std::string s(t); + * this->This() << s; + } + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + init(); + + basic_text_oarchive(unsigned int flags) : + detail::common_oarchive(flags), + delimiter(none) + {} + ~basic_text_oarchive(){} +}; + +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_TEXT_OARCHIVE_HPP diff --git a/win32/include/boost/archive/basic_text_oprimitive.hpp b/win32/include/boost/archive/basic_text_oprimitive.hpp new file mode 100755 index 000000000..d6ed7e587 --- /dev/null +++ b/win32/include/boost/archive/basic_text_oprimitive.hpp @@ -0,0 +1,169 @@ +#ifndef BOOST_ARCHIVE_BASIC_TEXT_OPRIMITIVE_HPP +#define BOOST_ARCHIVE_BASIC_TEXT_OPRIMITIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_oprimitive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +// archives stored as text - note these ar templated on the basic +// stream templates to accommodate wide (and other?) kind of characters +// +// note the fact that on libraries without wide characters, ostream is +// is not a specialization of basic_ostream which in fact is not defined +// in such cases. So we can't use basic_ostream but rather +// use two template parameters + +#include +#include +#include // isnan +#include +#include // size_t + +#include +#include +#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) +#include +#endif + +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; + #if ! defined(BOOST_DINKUMWARE_STDLIB) && ! defined(__SGI_STL_PORT) + using ::locale; + #endif +} // namespace std +#endif + +#include +#include +#include +#include +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +class save_access; + +///////////////////////////////////////////////////////////////////////// +// class basic_text_oprimitive - output of prmitives to stream +template +class basic_text_oprimitive +{ +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +protected: +#else +public: +#endif + OStream &os; + io::ios_flags_saver flags_saver; + io::ios_precision_saver precision_saver; + + #ifndef BOOST_NO_STD_LOCALE + boost::scoped_ptr archive_locale; + io::basic_ios_locale_saver< + BOOST_DEDUCED_TYPENAME OStream::char_type, BOOST_DEDUCED_TYPENAME OStream::traits_type + > locale_saver; + #endif + + // default saving of primitives. + template + void save(const T &t){ + if(os.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + os << t; + } + + ///////////////////////////////////////////////////////// + // fundamental types that need special treatment + void save(const bool t){ + // trap usage of invalid uninitialized boolean which would + // otherwise crash on load. + assert(0 == static_cast(t) || 1 == static_cast(t)); + if(os.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + os << t; + } + void save(const signed char t) + { + if(os.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + os << static_cast(t); + } + void save(const unsigned char t) + { + if(os.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + os << static_cast(t); + } + void save(const char t) + { + if(os.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + os << static_cast(t); + } + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + void save(const wchar_t t) + { + if(os.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + os << static_cast(t); + } + #endif + void save(const float t) + { + // must be a user mistake - can't serialize un-initialized data + if(os.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + os << std::setprecision(std::numeric_limits::digits10 + 2); + os << t; + } + void save(const double t) + { + // must be a user mistake - can't serialize un-initialized data + if(os.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + os << std::setprecision(std::numeric_limits::digits10 + 2); + os << t; + } + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + basic_text_oprimitive(OStream & os, bool no_codecvt); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~basic_text_oprimitive(); +public: + // unformatted append of one character + void put(int c){ + if(os.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + os.put(c); + } + // unformatted append of null terminated string + void put(const char * s){ + if(os.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + while('\0' != *s) + os.put(*s++); + } + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_binary(const void *address, std::size_t count); +}; + +} //namespace boost +} //namespace archive + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_TEXT_OPRIMITIVE_HPP diff --git a/win32/include/boost/archive/basic_xml_archive.hpp b/win32/include/boost/archive/basic_xml_archive.hpp new file mode 100755 index 000000000..f79ecc722 --- /dev/null +++ b/win32/include/boost/archive/basic_xml_archive.hpp @@ -0,0 +1,67 @@ +#ifndef BOOST_ARCHIVE_BASIC_XML_TEXT_ARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_XML_TEXT_ARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_xml_archive.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +// constant strings used in xml i/o + +extern +BOOST_ARCHIVE_DECL(const char *) +OBJECT_ID(); + +extern +BOOST_ARCHIVE_DECL(const char *) +OBJECT_REFERENCE(); + +extern +BOOST_ARCHIVE_DECL(const char *) +CLASS_ID(); + +extern +BOOST_ARCHIVE_DECL(const char *) +CLASS_ID_REFERENCE(); + +extern +BOOST_ARCHIVE_DECL(const char *) +CLASS_NAME(); + +extern +BOOST_ARCHIVE_DECL(const char *) +TRACKING(); + +extern +BOOST_ARCHIVE_DECL(const char *) +VERSION(); + +extern +BOOST_ARCHIVE_DECL(const char *) +SIGNATURE(); + +}// namespace archive +}// namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_XML_TEXT_ARCHIVE_HPP + diff --git a/win32/include/boost/archive/basic_xml_iarchive.hpp b/win32/include/boost/archive/basic_xml_iarchive.hpp new file mode 100755 index 000000000..385facf13 --- /dev/null +++ b/win32/include/boost/archive/basic_xml_iarchive.hpp @@ -0,0 +1,118 @@ +#ifndef BOOST_ARCHIVE_BASIC_XML_IARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_XML_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_xml_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include + +#include + +#include +#include + +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +///////////////////////////////////////////////////////////////////////// +// class xml_iarchive - read serialized objects from a input text stream +template +class basic_xml_iarchive : + public detail::common_iarchive +{ +protected: +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +public: +#elif defined(BOOST_MSVC) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_oarchive; +#else + friend class detail::interface_oarchive; +#endif + unsigned int depth; + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_start(const char *name); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_end(const char *name); + + // Anything not an attribute and not a name-value pair is an + // should be trapped here. + template + void load_override(T & t, BOOST_PFTO int) + { + // If your program fails to compile here, its most likely due to + // not specifying an nvp wrapper around the variable to + // be serialized. + BOOST_MPL_ASSERT((serialization::is_wrapper)); + this->detail_common_iarchive::load_override(t, 0); + } + + // Anything not an attribute - see below - should be a name value + // pair and be processed here + typedef detail::common_iarchive detail_common_iarchive; + template + void load_override( + #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + const + #endif + boost::serialization::nvp & t, + int + ){ + load_start(t.name()); + this->detail_common_iarchive::load_override(t.value(), 0); + load_end(t.name()); + } + + // specific overrides for attributes - handle as + // primitives. These are not name-value pairs + // so they have to be intercepted here and passed on to load. + // although the class_id is included in the xml text file in order + // to make the file self describing, it isn't used when loading + // an xml archive. So we can skip it here. Note: we MUST override + // it otherwise it will be loaded as a normal primitive w/o tag and + // leaving the archive in an undetermined state + void load_override(class_id_optional_type & /* t */, int){} + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_override(object_id_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_override(version_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_override(class_id_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_override(tracking_type & t, int); + // class_name_type can't be handled here as it depends upon the + // char type used by the stream. So require the derived implementation + // handle this. + // void load_override(class_name_type & t, int); + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + basic_xml_iarchive(unsigned int flags); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~basic_xml_iarchive(); +}; + +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_XML_IARCHIVE_HPP diff --git a/win32/include/boost/archive/basic_xml_oarchive.hpp b/win32/include/boost/archive/basic_xml_oarchive.hpp new file mode 100755 index 000000000..90773dbaf --- /dev/null +++ b/win32/include/boost/archive/basic_xml_oarchive.hpp @@ -0,0 +1,137 @@ +#ifndef BOOST_ARCHIVE_BASIC_XML_OARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_XML_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_xml_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include + +#include + +#include +#include +#include + +#include + +#include // must be the last header + + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// class basic_xml_oarchive - write serialized objects to a xml output stream +template +class basic_xml_oarchive : + public detail::common_oarchive +{ +protected: +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +public: +#elif defined(BOOST_MSVC) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_oarchive; + friend class save_access; +#else + friend class detail::interface_oarchive; + friend class save_access; +#endif + // special stuff for xml output + unsigned int depth; + bool indent_next; + bool pending_preamble; + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + indent(); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + init(); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + write_attribute( + const char *attribute_name, + int t, + const char *conjunction = "=\"" + ); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + write_attribute( + const char *attribute_name, + const char *key + ); + // helpers used below + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_start(const char *name); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_end(const char *name); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + end_preamble(); + + // Anything not an attribute and not a name-value pair is an + // error and should be trapped here. + template + void save_override(T & t, BOOST_PFTO int) + { + // If your program fails to compile here, its most likely due to + // not specifying an nvp wrapper around the variable to + // be serialized. + BOOST_MPL_ASSERT((serialization::is_wrapper)); + this->detail_common_oarchive::save_override(t, 0); + } + + // special treatment for name-value pairs. + typedef detail::common_oarchive detail_common_oarchive; + template + void save_override( + #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + const + #endif + ::boost::serialization::nvp & t, + int + ){ + save_start(t.name()); + this->detail_common_oarchive::save_override(t.const_value(), 0); + save_end(t.name()); + } + + // specific overrides for attributes - not name value pairs so we + // want to trap them before the above "fall through" + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const object_id_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const object_reference_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const version_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const class_id_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const class_id_optional_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const class_id_reference_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const class_name_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const tracking_type & t, int); + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + basic_xml_oarchive(unsigned int flags); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~basic_xml_oarchive(); +}; + +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_XML_OARCHIVE_HPP diff --git a/win32/include/boost/archive/binary_iarchive.hpp b/win32/include/boost/archive/binary_iarchive.hpp new file mode 100755 index 000000000..a6b1c1c48 --- /dev/null +++ b/win32/include/boost/archive/binary_iarchive.hpp @@ -0,0 +1,93 @@ +#ifndef BOOST_ARCHIVE_BINARY_IARCHIVE_HPP +#define BOOST_ARCHIVE_BINARY_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include + +namespace boost { +namespace archive { + +// do not derive from the classes below. If you want to extend this functionality +// via inhertance, derived from text_iarchive_impl instead. This will +// preserve correct static polymorphism. + +// same as binary_iarchive below - without the shared_ptr_helper +class naked_binary_iarchive : + public binary_iarchive_impl< + boost::archive::naked_binary_iarchive, + std::istream::char_type, + std::istream::traits_type + > +{ +public: + naked_binary_iarchive(std::istream & is, unsigned int flags = 0) : + binary_iarchive_impl< + naked_binary_iarchive, std::istream::char_type, std::istream::traits_type + >(is, flags) + {} + naked_binary_iarchive(std::streambuf & bsb, unsigned int flags = 0) : + binary_iarchive_impl< + naked_binary_iarchive, std::istream::char_type, std::istream::traits_type + >(bsb, flags) + {} +}; + +} // namespace archive +} // namespace boost + +// note special treatment of shared_ptr. This type needs a special +// structure associated with every archive. We created a "mix-in" +// class to provide this functionality. Since shared_ptr holds a +// special esteem in the boost library - we included it here by default. +#include + +namespace boost { +namespace archive { + +// do not derive from this class. If you want to extend this functionality +// via inhertance, derived from binary_iarchive_impl instead. This will +// preserve correct static polymorphism. +class binary_iarchive : + public binary_iarchive_impl< + boost::archive::binary_iarchive, + std::istream::char_type, + std::istream::traits_type + >, + public detail::shared_ptr_helper +{ +public: + binary_iarchive(std::istream & is, unsigned int flags = 0) : + binary_iarchive_impl< + binary_iarchive, std::istream::char_type, std::istream::traits_type + >(is, flags) + {} + binary_iarchive(std::streambuf & bsb, unsigned int flags = 0) : + binary_iarchive_impl< + binary_iarchive, std::istream::char_type, std::istream::traits_type + >(bsb, flags) + {} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::binary_iarchive) +BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::archive::binary_iarchive) + +#endif // BOOST_ARCHIVE_BINARY_IARCHIVE_HPP diff --git a/win32/include/boost/archive/binary_iarchive_impl.hpp b/win32/include/boost/archive/binary_iarchive_impl.hpp new file mode 100755 index 000000000..6c5165c64 --- /dev/null +++ b/win32/include/boost/archive/binary_iarchive_impl.hpp @@ -0,0 +1,87 @@ +#ifndef BOOST_ARCHIVE_BINARY_IARCHIVE_IMPL_HPP +#define BOOST_ARCHIVE_BINARY_IARCHIVE_IMPL_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_iarchive_impl.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include +#include + +namespace boost { +namespace archive { + +template +class binary_iarchive_impl : + public basic_binary_iprimitive, + public basic_binary_iarchive +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + friend class detail::interface_iarchive; + friend class basic_binary_iarchive; + friend class load_access; +protected: +#endif + // note: the following should not needed - but one compiler (vc 7.1) + // fails to compile one test (test_shared_ptr) without it !!! + // make this protected so it can be called from a derived archive + template + void load_override(T & t, BOOST_PFTO int){ + this->basic_binary_iarchive::load_override(t, 0L); + } + void init(unsigned int flags){ + if(0 != (flags & no_header)) + return; + #if ! defined(__MWERKS__) + this->basic_binary_iarchive::init(); + this->basic_binary_iprimitive::init(); + #else + basic_binary_iarchive::init(); + basic_binary_iprimitive::init(); + #endif + } + binary_iarchive_impl( + std::basic_streambuf & bsb, + unsigned int flags + ) : + basic_binary_iprimitive( + bsb, + 0 != (flags & no_codecvt) + ), + basic_binary_iarchive(flags) + { + init(flags); + } + binary_iarchive_impl( + std::basic_istream & is, + unsigned int flags + ) : + basic_binary_iprimitive( + * is.rdbuf(), + 0 != (flags & no_codecvt) + ), + basic_binary_iarchive(flags) + { + init(flags); + } +}; + +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_BINARY_IARCHIVE_IMPL_HPP diff --git a/win32/include/boost/archive/binary_oarchive.hpp b/win32/include/boost/archive/binary_oarchive.hpp new file mode 100755 index 000000000..fbbec5175 --- /dev/null +++ b/win32/include/boost/archive/binary_oarchive.hpp @@ -0,0 +1,55 @@ +#ifndef BOOST_ARCHIVE_BINARY_OARCHIVE_HPP +#define BOOST_ARCHIVE_BINARY_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include + +namespace boost { +namespace archive { + +// do not derive from this class. If you want to extend this functionality +// via inhertance, derived from binary_oarchive_impl instead. This will +// preserve correct static polymorphism. +class binary_oarchive : + public binary_oarchive_impl< + binary_oarchive, std::ostream::char_type, std::ostream::traits_type + > +{ +public: + binary_oarchive(std::ostream & os, unsigned int flags = 0) : + binary_oarchive_impl< + binary_oarchive, std::ostream::char_type, std::ostream::traits_type + >(os, flags) + {} + binary_oarchive(std::streambuf & bsb, unsigned int flags = 0) : + binary_oarchive_impl< + binary_oarchive, std::ostream::char_type, std::ostream::traits_type + >(bsb, flags) + {} +}; + +typedef binary_oarchive naked_binary_oarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::binary_oarchive) +BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::archive::binary_oarchive) + +#endif // BOOST_ARCHIVE_BINARY_OARCHIVE_HPP diff --git a/win32/include/boost/archive/binary_oarchive_impl.hpp b/win32/include/boost/archive/binary_oarchive_impl.hpp new file mode 100755 index 000000000..95216b68c --- /dev/null +++ b/win32/include/boost/archive/binary_oarchive_impl.hpp @@ -0,0 +1,87 @@ +#ifndef BOOST_ARCHIVE_BINARY_OARCHIVE_IMPL_HPP +#define BOOST_ARCHIVE_BINARY_OARCHIVE_IMPL_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_oarchive_impl.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include +#include + +namespace boost { +namespace archive { + +template +class binary_oarchive_impl : + public basic_binary_oprimitive, + public basic_binary_oarchive +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + friend class detail::interface_oarchive; + friend class basic_binary_oarchive; + friend class save_access; +protected: +#endif + // note: the following should not needed - but one compiler (vc 7.1) + // fails to compile one test (test_shared_ptr) without it !!! + // make this protected so it can be called from a derived archive + template + void save_override(T & t, BOOST_PFTO int){ + this->basic_binary_oarchive::save_override(t, 0L); + } + void init(unsigned int flags) { + if(0 != (flags & no_header)) + return; + #if ! defined(__MWERKS__) + this->basic_binary_oarchive::init(); + this->basic_binary_oprimitive::init(); + #else + basic_binary_oarchive::init(); + basic_binary_oprimitive::init(); + #endif + } + binary_oarchive_impl( + std::basic_streambuf & bsb, + unsigned int flags + ) : + basic_binary_oprimitive( + bsb, + 0 != (flags & no_codecvt) + ), + basic_binary_oarchive(flags) + { + init(flags); + } + binary_oarchive_impl( + std::basic_ostream & os, + unsigned int flags + ) : + basic_binary_oprimitive( + * os.rdbuf(), + 0 != (flags & no_codecvt) + ), + basic_binary_oarchive(flags) + { + init(flags); + } +}; + +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_BINARY_OARCHIVE_IMPL_HPP diff --git a/win32/include/boost/archive/binary_wiarchive.hpp b/win32/include/boost/archive/binary_wiarchive.hpp new file mode 100755 index 000000000..780621bd5 --- /dev/null +++ b/win32/include/boost/archive/binary_wiarchive.hpp @@ -0,0 +1,92 @@ +#ifndef BOOST_ARCHIVE_BINARY_WIARCHIVE_HPP +#define BOOST_ARCHIVE_BINARY_WIARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_wiarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include // wistream +#include + +namespace boost { +namespace archive { + +// same as binary_wiarchive below - without the shared_ptr_helper +class naked_binary_wiarchive : + public binary_iarchive_impl< + boost::archive::naked_binary_wiarchive, + std::wistream::char_type, + std::wistream::traits_type + > +{ +public: + naked_binary_wiarchive(std::wistream & is, unsigned int flags = 0) : + binary_iarchive_impl< + naked_binary_wiarchive, + std::wistream::char_type, + std::wistream::traits_type + >(is, flags) + {} + naked_binary_wiarchive(std::wstreambuf & bsb, unsigned int flags = 0) : + binary_iarchive_impl< + naked_binary_wiarchive, + std::wistream::char_type, + std::wistream::traits_type + >(bsb, flags) + {} +}; + +} // namespace archive +} // namespace boost + +// note special treatment of shared_ptr. This type needs a special +// structure associated with every archive. We created a "mix-in" +// class to provide this functionality. Since shared_ptr holds a +// special esteem in the boost library - we included it here by default. +#include + +namespace boost { +namespace archive { + +class binary_wiarchive : + public binary_iarchive_impl< + binary_wiarchive, std::wistream::char_type, std::wistream::traits_type + > +{ +public: + binary_wiarchive(std::wistream & is, unsigned int flags = 0) : + binary_iarchive_impl< + binary_wiarchive, std::wistream::char_type, std::wistream::traits_type + >(is, flags) + {} + binary_wiarchive(std::wstreambuf & bsb, unsigned int flags = 0) : + binary_iarchive_impl< + binary_wiarchive, std::wistream::char_type, std::wistream::traits_type + >(bsb, flags) + {} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::binary_wiarchive) + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_BINARY_WIARCHIVE_HPP diff --git a/win32/include/boost/archive/binary_woarchive.hpp b/win32/include/boost/archive/binary_woarchive.hpp new file mode 100755 index 000000000..e39382a51 --- /dev/null +++ b/win32/include/boost/archive/binary_woarchive.hpp @@ -0,0 +1,60 @@ +#ifndef BOOST_ARCHIVE_BINARY_WOARCHIVE_HPP +#define BOOST_ARCHIVE_BINARY_WOARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_woarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include +#include + +namespace boost { +namespace archive { + +// do not derive from this class. If you want to extend this functionality +// via inhertance, derived from binary_oarchive_impl instead. This will +// preserve correct static polymorphism. +class binary_woarchive : + public binary_oarchive_impl< + binary_woarchive, std::wostream::char_type, std::wostream::traits_type + > +{ +public: + binary_woarchive(std::wostream & os, unsigned int flags = 0) : + binary_oarchive_impl< + binary_woarchive, std::wostream::char_type, std::wostream::traits_type + >(os, flags) + {} + binary_woarchive(std::wstreambuf & bsb, unsigned int flags = 0) : + binary_oarchive_impl< + binary_woarchive, std::wostream::char_type, std::wostream::traits_type + >(bsb, flags) + {} +}; + +typedef binary_woarchive naked_binary_woarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::binary_woarchive) + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_BINARY_WOARCHIVE_HPP diff --git a/win32/include/boost/archive/codecvt_null.hpp b/win32/include/boost/archive/codecvt_null.hpp new file mode 100755 index 000000000..06a941c3d --- /dev/null +++ b/win32/include/boost/archive/codecvt_null.hpp @@ -0,0 +1,83 @@ +#ifndef BOOST_ARCHIVE_CODECVT_NULL_HPP +#define BOOST_ARCHIVE_CODECVT_NULL_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// codecvt_null.hpp: + +// (C) Copyright 2004 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include // NULL, size_t +#include // for mbstate_t +#include +#include + +#if defined(BOOST_NO_STDC_NAMESPACE) + using ::codecvt; + using ::mbstate_t; + using ::size_t +#endif + +namespace boost { +namespace archive { + +template +class codecvt_null; + +template<> +class codecvt_null : public std::codecvt +{ + virtual bool do_always_noconv() const throw() { + return true; + } +public: + explicit codecvt_null(std::size_t no_locale_manage = 0) : + std::codecvt(no_locale_manage) + {} +}; + +template<> +class codecvt_null : public std::codecvt +{ + virtual BOOST_WARCHIVE_DECL(std::codecvt_base::result) + do_out( + std::mbstate_t & state, + const wchar_t * first1, + const wchar_t * last1, + const wchar_t * & next1, + char * first2, + char * last2, + char * & next2 + ) const; + virtual BOOST_WARCHIVE_DECL(std::codecvt_base::result) + do_in( + std::mbstate_t & state, + const char * first1, + const char * last1, + const char * & next1, + wchar_t * first2, + wchar_t * last2, + wchar_t * & next2 + ) const; + virtual int do_encoding( ) const throw( ){ + return sizeof(wchar_t) / sizeof(char); + } + virtual int do_max_length( ) const throw( ){ + return do_encoding(); + } +}; + +} // namespace archive +} // namespace boost + +#endif //BOOST_ARCHIVE_CODECVT_NULL_HPP diff --git a/win32/include/boost/archive/detail/abi_prefix.hpp b/win32/include/boost/archive/detail/abi_prefix.hpp new file mode 100755 index 000000000..093a10914 --- /dev/null +++ b/win32/include/boost/archive/detail/abi_prefix.hpp @@ -0,0 +1,20 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// abi_prefix.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include // must be the last header +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4251 4231 4660 4275) +#endif + +#if defined( __BORLANDC__ ) +#pragma nopushoptwarn +#endif + diff --git a/win32/include/boost/archive/detail/abi_suffix.hpp b/win32/include/boost/archive/detail/abi_suffix.hpp new file mode 100755 index 000000000..be85290c7 --- /dev/null +++ b/win32/include/boost/archive/detail/abi_suffix.hpp @@ -0,0 +1,19 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// abi_suffix.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#if defined( __BORLANDC__ ) +#pragma nopushoptwarn +#endif + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +#include // pops abi_suffix.hpp pragmas + diff --git a/win32/include/boost/archive/detail/archive_pointer_iserializer.hpp b/win32/include/boost/archive/detail/archive_pointer_iserializer.hpp new file mode 100755 index 000000000..1a73c4142 --- /dev/null +++ b/win32/include/boost/archive/detail/archive_pointer_iserializer.hpp @@ -0,0 +1,92 @@ +#ifndef BOOST_ARCHIVE_ARCHIVE_POINTER_ISERIALIZER_POINTER_HPP +#define BOOST_ARCHIVE_ARCHIVE_POINTER_ISERIALIZER_POINTER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// archive_pointer_iserializer.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include // NULL +#include +#include + +#include +#include + +#include // must be the last header + +namespace boost { + +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { +namespace detail { + +template +class archive_pointer_iserializer : + public basic_pointer_iserializer { +protected: + explicit BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + archive_pointer_iserializer( + const boost::serialization::extended_type_info & eti + ); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + // account for bogus gcc warning + #if defined(__GNUC__) + virtual + #endif + ~archive_pointer_iserializer(); +public: + virtual const basic_iserializer & get_basic_serializer() const + // mscvc 6.0 requires template functions to be implemented. For this + // reason we can't make abstract. + #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || defined(__MWERKS__) + { + assert(false); + return *static_cast(NULL); + } + #else + = 0; + #endif + virtual void load_object_ptr( + basic_iarchive & ar, + void * & x, + const unsigned int file_version + ) const + #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || defined(__MWERKS__) + { + assert(false); + } + #else + = 0; + #endif + // return the type_extended load pointer corresponding to a given + // type_info. returns NULL if there is no such instance. This + // would indicate that the no object of the specified type was loaded + // any where in the code. + static BOOST_ARCHIVE_OR_WARCHIVE_DECL(const basic_pointer_iserializer *) + find( + const boost::serialization::extended_type_info & eti + ); +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_ARCHIVE_POINTER_ISERIALIZER_POINTER_HPP diff --git a/win32/include/boost/archive/detail/archive_pointer_oserializer.hpp b/win32/include/boost/archive/detail/archive_pointer_oserializer.hpp new file mode 100755 index 000000000..04b47b674 --- /dev/null +++ b/win32/include/boost/archive/detail/archive_pointer_oserializer.hpp @@ -0,0 +1,66 @@ +#ifndef BOOST_ARCHIVE_ARCHIVE_POINTER_OSERIALIZER_POINTER_HPP +#define BOOST_ARCHIVE_ARCHIVE_POINTER_OSERIALIZER_POINTER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// archive_pointer_oserializer.hpp: extenstion of type_info required for +// serialization. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include + +#include // must be the last header + +namespace boost { + +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { +namespace detail { + +template +class archive_pointer_oserializer : + public basic_pointer_oserializer { +protected: + explicit BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + archive_pointer_oserializer( + const boost::serialization::extended_type_info & eti + ); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + // account for bogus gcc warning + #if defined(__GNUC__) + virtual + #endif + ~archive_pointer_oserializer(); +public: + // return the type_extended save pointer corresponding to a give + // type_info. returns NULL, if there is no such instance. This + // would indicate that the no object of the specified type was saved + // any where in the code. + static BOOST_ARCHIVE_OR_WARCHIVE_DECL(const basic_pointer_oserializer *) + find( + const boost::serialization::extended_type_info & eti + ); +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_ARCHIVE_POINTER_OSERIALIZER_POINTER_HPP diff --git a/win32/include/boost/archive/detail/auto_link_archive.hpp b/win32/include/boost/archive/detail/auto_link_archive.hpp new file mode 100755 index 000000000..801c5849f --- /dev/null +++ b/win32/include/boost/archive/detail/auto_link_archive.hpp @@ -0,0 +1,48 @@ +#ifndef BOOST_ARCHIVE_DETAIL_AUTO_LINK_ARCHIVE_HPP +#define BOOST_ARCHIVE_DETAIL_AUTO_LINK_ARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// auto_link_archive.hpp +// +// (c) Copyright Robert Ramey 2004 +// Use, modification, and distribution is subject to 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) + +// See library home page at http://www.boost.org/libs/serialization + +//----------------------------------------------------------------------------// + +// This header implements separate compilation features as described in +// http://www.boost.org/more/separate_compilation.html + +// enable automatic library variant selection ------------------------------// + +#include + +#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_SERIALIZATION_NO_LIB) \ +&& !defined(BOOST_ARCHIVE_SOURCE) && !defined(BOOST_WARCHIVE_SOURCE) \ +&& !defined(BOOST_SERIALIZATION_SOURCE) + + // Set the name of our library, this will get undef'ed by auto_link.hpp + // once it's done with it: + // + #define BOOST_LIB_NAME boost_serialization + // + // If we're importing code from a dll, then tell auto_link.hpp about it: + // + #if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SERIALIZATION_DYN_LINK) + # define BOOST_DYN_LINK + #endif + // + // And include the header that does the work: + // + #include +#endif // auto-linking disabled + +#endif // ARCHIVE_DETAIL_AUTO_LINK_ARCHIVE_HPP diff --git a/win32/include/boost/archive/detail/auto_link_warchive.hpp b/win32/include/boost/archive/detail/auto_link_warchive.hpp new file mode 100755 index 000000000..5183ce705 --- /dev/null +++ b/win32/include/boost/archive/detail/auto_link_warchive.hpp @@ -0,0 +1,47 @@ +#ifndef BOOST_ARCHIVE_DETAIL_AUTO_LINK_WARCHIVE_HPP +#define BOOST_ARCHIVE_DETAIL_AUTO_LINK_WARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// auto_link_warchive.hpp +// +// (c) Copyright Robert Ramey 2004 +// Use, modification, and distribution is subject to 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) + +// See library home page at http://www.boost.org/libs/serialization + +//----------------------------------------------------------------------------// + +// This header implements separate compilation features as described in +// http://www.boost.org/more/separate_compilation.html + +// enable automatic library variant selection ------------------------------// + +#include + +#if !defined(BOOST_WARCHIVE_SOURCE) \ +&& !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_SERIALIZATION_NO_LIB) + +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it: +// +#define BOOST_LIB_NAME boost_wserialization +// +// If we're importing code from a dll, then tell auto_link.hpp about it: +// +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SERIALIZATION_DYN_LINK) +# define BOOST_DYN_LINK +#endif +// +// And include the header that does the work: +// +#include +#endif // auto-linking disabled + +#endif // ARCHIVE_DETAIL_AUTO_LINK_ARCHIVE_HPP diff --git a/win32/include/boost/archive/detail/basic_archive_impl.hpp b/win32/include/boost/archive/detail/basic_archive_impl.hpp new file mode 100755 index 000000000..dd01cffd5 --- /dev/null +++ b/win32/include/boost/archive/detail/basic_archive_impl.hpp @@ -0,0 +1,48 @@ +#ifndef BOOST_ARCHIVE_DETAIL_BASIC_ARCHIVE_IMPL_HPP +#define BOOST_ARCHIVE_DETAIL_BASIC_ARCHIVE_IMPL_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_archive_impl.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +// can't use this - much as I'd like to as borland doesn't support it +// #include + +#include + +#include // must be the last header + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { +namespace detail { + +////////////////////////////////////////////////////////////////////// +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_archive_impl +{ +}; + +} // namespace detail +} // namespace serialization +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif //BOOST_ARCHIVE_DETAIL_BASIC_ARCHIVE_IMPL_HPP + + + diff --git a/win32/include/boost/archive/detail/basic_config.hpp b/win32/include/boost/archive/detail/basic_config.hpp new file mode 100755 index 000000000..601d3412e --- /dev/null +++ b/win32/include/boost/archive/detail/basic_config.hpp @@ -0,0 +1,45 @@ +#ifndef BOOST_ARCHIVE_DETAIL_BASIC_CONFIG_HPP +#define BOOST_ARCHIVE_DETAIL_BASIC_CONFIG_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// basic_config.hpp ---------------------------------------------// + +// (c) Copyright Robert Ramey 2004 +// Use, modification, and distribution is subject to 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) + +// See library home page at http://www.boost.org/libs/serialization + +//----------------------------------------------------------------------------// + +// This header implements separate compilation features as described in +// http://www.boost.org/more/separate_compilation.html + +#include + +#ifdef BOOST_HAS_DECLSPEC // defined in config system +// we need to import/export our code only if the user has specifically +// asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost +// libraries to be dynamically linked, or BOOST_ARCHIVE_DYN_LINK +// if they want just this one to be dynamically linked: +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_ARCHIVE_DYN_LINK) +// export if this is our own source, otherwise import: +#ifdef BOOST_ARCHIVE_SOURCE +# define BOOST_ARCHIVE_DECL __declspec(dllexport) +#else +# define BOOST_ARCHIVE_DECL __declspec(dllimport) +#endif // BOOST_ARCHIVE_SOURCE +#endif // DYN_LINK +#endif // BOOST_HAS_DECLSPEC +// +// if BOOST_ARCHIVE_DECL isn't defined yet define it now: +#ifndef BOOST_ARCHIVE_DECL +#define BOOST_ARCHIVE_DECL +#endif + +#endif // BOOST_ARCHIVE_DETAIL_BASIC_CONFIG_HPP diff --git a/win32/include/boost/archive/detail/basic_iarchive.hpp b/win32/include/boost/archive/detail/basic_iarchive.hpp new file mode 100755 index 000000000..c54f5f874 --- /dev/null +++ b/win32/include/boost/archive/detail/basic_iarchive.hpp @@ -0,0 +1,108 @@ +#ifndef BOOST_ARCHIVE_DETAIL_BASIC_IARCHIVE_HPP +#define BOOST_ARCHIVE_DETAIL_BASIC_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_iarchive.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +// can't use this - much as I'd like to as borland doesn't support it +// #include + +#include +#include +#include +#include +#include +#include // must be the last header + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { +namespace detail { + +class basic_iarchive_impl; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iserializer; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer; +////////////////////////////////////////////////////////////////////// +// class basic_iarchive - read serialized objects from a input stream +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive +{ + friend class basic_iarchive_impl; + // hide implementation of this class to minimize header conclusion + // in client code. I couldn't used scoped pointer with borland + // boost::scoped_ptr pimpl; + basic_iarchive_impl * pimpl; + + virtual void vload(version_type &t) = 0; + virtual void vload(object_id_type &t) = 0; + virtual void vload(class_id_type &t) = 0; + virtual void vload(class_id_optional_type &t) = 0; + virtual void vload(class_name_type &t) = 0; + virtual void vload(tracking_type &t) = 0; +protected: + basic_iarchive(unsigned int flags); + // account for bogus gcc warning + #if defined(__GNUC__) + virtual + #endif + ~basic_iarchive(); +public: + // note: NOT part of the public API. + void next_object_pointer(void *t); + void register_basic_serializer( + const /* BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) */ basic_iserializer & bis + ); + void load_object( + void *t, + const /* BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) */ basic_iserializer & bis + ); + const /* BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) */ basic_pointer_iserializer * + load_pointer( + void * & t, + const /* BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) */ + basic_pointer_iserializer * bpis_ptr, + const /* BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) */ + basic_pointer_iserializer * (*finder)( + const boost::serialization::extended_type_info & eti + ) + ); + // real public API starts here + void + set_library_version(unsigned int archive_library_version); + unsigned int + get_library_version() const; + unsigned int + get_flags() const; + void + reset_object_address(const void * new_address, const void * old_address); + void + delete_created_pointers(); +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +// required by smart_cast for compilers not implementing +// partial template specialization +BOOST_TT_BROKEN_COMPILER_SPEC( + boost::archive::detail::basic_iarchive +) + +#include // pops abi_suffix.hpp pragmas + +#endif //BOOST_ARCHIVE_DETAIL_BASIC_IARCHIVE_HPP diff --git a/win32/include/boost/archive/detail/basic_iserializer.hpp b/win32/include/boost/archive/detail/basic_iserializer.hpp new file mode 100755 index 000000000..f0b70af67 --- /dev/null +++ b/win32/include/boost/archive/detail/basic_iserializer.hpp @@ -0,0 +1,86 @@ +#ifndef BOOST_ARCHIVE_DETAIL_BASIC_ISERIALIZER_HPP +#define BOOST_ARCHIVE_DETAIL_BASIC_ISERIALIZER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_iserializer.hpp: extenstion of type_info required for serialization. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include // NULL +#include + +#include +#include +#include +#include // must be the last header + +namespace boost { + +namespace serialization { + class extended_type_info; +} // namespace serialization + +// forward declarations +namespace archive { +namespace detail { + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer; + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iserializer : + public basic_serializer +{ +private: + basic_pointer_iserializer *m_bpis; +protected: + explicit basic_iserializer( + const boost::serialization::extended_type_info & type + ); + // account for bogus gcc warning + #if defined(__GNUC__) + virtual + #endif + ~basic_iserializer(); +public: + bool serialized_as_pointer() const { + return m_bpis != NULL; + } + void set_bpis(basic_pointer_iserializer *bpis){ + m_bpis = bpis; + } + const basic_pointer_iserializer * get_bpis_ptr() const { + return m_bpis; + } + virtual void load_object_data( + basic_iarchive & ar, + void *x, + const unsigned int file_version + ) const = 0; + // returns true if class_info should be saved + virtual bool class_info() const = 0 ; + // returns true if objects should be tracked + virtual bool tracking(const unsigned int) const = 0 ; + // returns class version + virtual unsigned int version() const = 0 ; + // returns true if this class is polymorphic + virtual bool is_polymorphic() const = 0; + virtual void destroy(/*const*/ void *address) const = 0 ; +}; + +} // namespae detail +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_DETAIL_BASIC_ISERIALIZER_HPP diff --git a/win32/include/boost/archive/detail/basic_oarchive.hpp b/win32/include/boost/archive/detail/basic_oarchive.hpp new file mode 100755 index 000000000..df90ed938 --- /dev/null +++ b/win32/include/boost/archive/detail/basic_oarchive.hpp @@ -0,0 +1,103 @@ +#ifndef BOOST_ARCHIVE_BASIC_OARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_oarchive.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include // NULL +#include + +// can't use this - much as I'd like to as borland doesn't support it +// #include + +#include +#include + +#include // must be the last header + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { +namespace detail { + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive_impl; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer; +////////////////////////////////////////////////////////////////////// +// class basic_oarchive - write serialized objects to an output stream +class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive +{ + friend class basic_oarchive_impl; + // hide implementation of this class to minimize header conclusion + // in client code. note: borland can't use scoped_ptr + //boost::scoped_ptr pimpl; + basic_oarchive_impl * pimpl; + + // overload these to bracket object attributes. Used to implement + // xml archives + virtual void vsave(const version_type t) = 0; + virtual void vsave(const object_id_type t) = 0; + virtual void vsave(const object_reference_type t) = 0; + virtual void vsave(const class_id_type t) = 0; + virtual void vsave(const class_id_optional_type t) = 0; + virtual void vsave(const class_id_reference_type t) = 0; + virtual void vsave(const class_name_type & t) = 0; + virtual void vsave(const tracking_type t) = 0; +protected: + basic_oarchive(unsigned int flags = 0); + // account for bogus gcc warning + #if defined(__GNUC__) + virtual + #endif + ~basic_oarchive(); +public: + // note: NOT part of the public interface + void register_basic_serializer( + const basic_oserializer & bos + ); + void save_object( + const void *x, + const basic_oserializer & bos + ); + void save_pointer( + const void * t, + const basic_pointer_oserializer * bpos_ptr + ); + void save_null_pointer(){ + vsave(NULL_POINTER_TAG); + } + // real public interface starts here + void end_preamble(); // default implementation does nothing + unsigned int get_library_version() const; + unsigned int get_flags() const; +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +// required by smart_cast for compilers not implementing +// partial template specialization +BOOST_TT_BROKEN_COMPILER_SPEC( + boost::archive::detail::basic_oarchive +) + +#include // pops abi_suffix.hpp pragmas + +#endif //BOOST_ARCHIVE_BASIC_OARCHIVE_HPP diff --git a/win32/include/boost/archive/detail/basic_oserializer.hpp b/win32/include/boost/archive/detail/basic_oserializer.hpp new file mode 100755 index 000000000..f67b357f5 --- /dev/null +++ b/win32/include/boost/archive/detail/basic_oserializer.hpp @@ -0,0 +1,83 @@ +#ifndef BOOST_SERIALIZATION_BASIC_OSERIALIZER_HPP +#define BOOST_SERIALIZATION_BASIC_OSERIALIZER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_oserializer.hpp: extenstion of type_info required for serialization. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include // NULL +#include + +#include +#include + +#include // must be the last header + +namespace boost { + +namespace serialization { + class extended_type_info; +} // namespace serialization + +// forward declarations +namespace archive { +namespace detail { + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer; + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer : + public basic_serializer +{ +private: + basic_pointer_oserializer *m_bpos; +protected: + explicit basic_oserializer( + const boost::serialization::extended_type_info & type_ + ); + // account for bogus gcc warning + #if defined(__GNUC__) + virtual + #endif + ~basic_oserializer(); +public: + bool serialized_as_pointer() const { + return m_bpos != NULL; + } + void set_bpos(basic_pointer_oserializer *bpos){ + m_bpos = bpos; + } + const basic_pointer_oserializer * get_bpos() const { + return m_bpos; + } + virtual void save_object_data( + basic_oarchive & ar, const void * x + ) const = 0; + // returns true if class_info should be saved + virtual bool class_info() const = 0; + // returns true if objects should be tracked + virtual bool tracking(const unsigned int flags) const = 0; + // returns class version + virtual unsigned int version() const = 0; + // returns true if this class is polymorphic + virtual bool is_polymorphic() const = 0; +}; + +} // namespace detail +} // namespace serialization +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_SERIALIZATION_BASIC_OSERIALIZER_HPP diff --git a/win32/include/boost/archive/detail/basic_pointer_iserializer.hpp b/win32/include/boost/archive/detail/basic_pointer_iserializer.hpp new file mode 100755 index 000000000..7b33898ec --- /dev/null +++ b/win32/include/boost/archive/detail/basic_pointer_iserializer.hpp @@ -0,0 +1,64 @@ +#ifndef BOOST_ARCHIVE_BASIC_POINTER_ISERIALIZER_HPP +#define BOOST_ARCHIVE_BASIC_POINTER_ISERIALIZER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_pointer_oserializer.hpp: extenstion of type_info required for +// serialization. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. +#include +#include +#include + +#include // must be the last header + +namespace boost { + +namespace serialization { + class extended_type_info; +} // namespace serialization + +// forward declarations +namespace archive { +namespace detail { + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iserializer; + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer + : public basic_serializer { +protected: + explicit basic_pointer_iserializer( + const boost::serialization::extended_type_info & type_ + ); + // account for bogus gcc warning + #if defined(__GNUC__) + virtual + #endif + ~basic_pointer_iserializer(); +public: + virtual const basic_iserializer & get_basic_serializer() const = 0; + virtual void load_object_ptr( + basic_iarchive & ar, + void * & x, + const unsigned int file_version + ) const = 0; +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_POINTER_ISERIALIZER_HPP diff --git a/win32/include/boost/archive/detail/basic_pointer_oserializer.hpp b/win32/include/boost/archive/detail/basic_pointer_oserializer.hpp new file mode 100755 index 000000000..1b97dbcfa --- /dev/null +++ b/win32/include/boost/archive/detail/basic_pointer_oserializer.hpp @@ -0,0 +1,62 @@ +#ifndef BOOST_ARCHIVE_BASIC_POINTER_OSERIALIZER_HPP +#define BOOST_ARCHIVE_BASIC_POINTER_OSERIALIZER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_pointer_oserializer.hpp: extenstion of type_info required for +// serialization. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. +#include +#include +#include + +#include // must be the last header + +namespace boost { + +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { +namespace detail { + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer; + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer : + public basic_serializer { +protected: + explicit basic_pointer_oserializer( + const boost::serialization::extended_type_info & type_ + ); +public: + // account for bogus gcc warning + #if defined(__GNUC__) + virtual + #endif + ~basic_pointer_oserializer(); + virtual const basic_oserializer & get_basic_serializer() const = 0; + virtual void save_object_ptr( + basic_oarchive & ar, + const void * x + ) const = 0; +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_POINTER_OSERIALIZER_HPP diff --git a/win32/include/boost/archive/detail/basic_serializer.hpp b/win32/include/boost/archive/detail/basic_serializer.hpp new file mode 100755 index 000000000..04b0a8a49 --- /dev/null +++ b/win32/include/boost/archive/detail/basic_serializer.hpp @@ -0,0 +1,63 @@ +#ifndef BOOST_ARCHIVE_BASIC_SERIALIZER_HPP +#define BOOST_ARCHIVE_BASIC_SERIALIZER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_serializer.hpp: extenstion of type_info required for serialization. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include // NULL + +#include +#include +#include + +namespace boost { +namespace archive { +namespace detail { + +class basic_serializer : private boost::noncopyable +{ + const boost::serialization::extended_type_info & m_eti; +protected: + explicit basic_serializer( + const boost::serialization::extended_type_info & eti + ) : + m_eti(eti) + { + assert(NULL != & eti); + } +public: + const boost::serialization::extended_type_info & get_eti() const { + return m_eti; + } +}; + +inline bool +operator<(const basic_serializer & lhs, const basic_serializer & rhs) { + return & lhs.get_eti() < & rhs.get_eti(); +} + +class basic_serializer_arg : public basic_serializer { +public: + basic_serializer_arg(const serialization::extended_type_info & eti) : + basic_serializer(eti) + {} +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_BASIC_SERIALIZER_HPP diff --git a/win32/include/boost/archive/detail/basic_serializer_map.hpp b/win32/include/boost/archive/detail/basic_serializer_map.hpp new file mode 100755 index 000000000..71ce6029f --- /dev/null +++ b/win32/include/boost/archive/detail/basic_serializer_map.hpp @@ -0,0 +1,59 @@ +#ifndef BOOST_TYPEINFO_EXTENDED_MAP_HPP +#define BOOST_TYPEINFO_EXTENDED_MAP_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_serializer_map.hpp: extenstion of type_info required for serialization. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include + +#include +#include +#include + +#include // must be the last header + +namespace boost { +namespace serialization { + class extended_type_info; +} + +namespace archive { +namespace detail { + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_serializer; + +bool operator<(const basic_serializer & lhs, const basic_serializer & rhs); + +struct BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) type_info_pointer_compare +{ + bool operator()( + const basic_serializer * lhs, const basic_serializer * rhs + ) const { + return *lhs < *rhs; + } +}; + +typedef BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) std::set< + const basic_serializer *, + type_info_pointer_compare +> basic_serializer_map; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_TYPEINFO_EXTENDED_MAP_HPP diff --git a/win32/include/boost/archive/detail/common_iarchive.hpp b/win32/include/boost/archive/detail/common_iarchive.hpp new file mode 100755 index 000000000..1b0fc058b --- /dev/null +++ b/win32/include/boost/archive/detail/common_iarchive.hpp @@ -0,0 +1,77 @@ +#ifndef BOOST_ARCHIVE_DETAIL_COMMON_IARCHIVE_HPP +#define BOOST_ARCHIVE_DETAIL_COMMON_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// common_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include +#include +#include + +namespace boost { +namespace archive { +namespace detail { + +// note: referred to as Curiously Recurring Template Patter (CRTP) +template +class common_iarchive : + public basic_iarchive, + public interface_iarchive +{ + friend class interface_iarchive; +private: + virtual void vload(version_type & t){ + * this->This() >> t; + } + virtual void vload(object_id_type & t){ + * this->This() >> t; + } + virtual void vload(class_id_type & t){ + * this->This() >> t; + } + virtual void vload(class_id_optional_type & t){ + * this->This() >> t; + } + virtual void vload(tracking_type & t){ + * this->This() >> t; + } + virtual void vload(class_name_type &s){ + * this->This() >> s; + } +protected: + // default processing - invoke serialization library + template + void load_override(T & t, BOOST_PFTO int){ + archive::load(* this->This(), t); + } + // default implementations of functions which emit start/end tags for + // archive types that require them. + void load_start(const char * /*name*/){} + void load_end(const char * /*name*/){} + // default archive initialization + common_iarchive(unsigned int flags = 0) : + basic_iarchive(flags), + interface_iarchive() + {} +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_DETAIL_COMMON_IARCHIVE_HPP + diff --git a/win32/include/boost/archive/detail/common_oarchive.hpp b/win32/include/boost/archive/detail/common_oarchive.hpp new file mode 100755 index 000000000..d7112ff45 --- /dev/null +++ b/win32/include/boost/archive/detail/common_oarchive.hpp @@ -0,0 +1,78 @@ +#ifndef BOOST_ARCHIVE_DETAIL_COMMON_OARCHIVE_HPP +#define BOOST_ARCHIVE_DETAIL_COMMON_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// common_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include +#include + +namespace boost { +namespace archive { +namespace detail { + +// note: referred to as Curiously Recurring Template Patter (CRTP) +template +class common_oarchive : + public basic_oarchive, + public interface_oarchive +{ + friend class interface_oarchive; +private: + virtual void vsave(const version_type t){ + * this->This() << t; + } + virtual void vsave(const object_id_type t){ + * this->This() << t; + } + virtual void vsave(const object_reference_type t){ + * this->This() << t; + } + virtual void vsave(const class_id_type t){ + * this->This() << t; + } + virtual void vsave(const class_id_reference_type t){ + * this->This() << t; + } + virtual void vsave(const class_id_optional_type t){ + * this->This() << t; + } + virtual void vsave(const class_name_type & t){ + * this->This() << t; + } + virtual void vsave(const tracking_type t){ + * this->This() << t; + } +protected: + // default processing - invoke serialization library + template + void save_override(T & t, BOOST_PFTO int){ + archive::save(* this->This(), t); + } + void save_start(const char * /*name*/){} + void save_end(const char * /*name*/){} + common_oarchive(unsigned int flags = 0) : + basic_oarchive(flags), + interface_oarchive() + {} +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_DETAIL_COMMON_OARCHIVE_HPP diff --git a/win32/include/boost/archive/detail/decl.hpp b/win32/include/boost/archive/detail/decl.hpp new file mode 100755 index 000000000..f12f77389 --- /dev/null +++ b/win32/include/boost/archive/detail/decl.hpp @@ -0,0 +1,79 @@ +#ifndef BOOST_ARCHIVE_DETAIL_DECL_HPP +#define BOOST_ARCHIVE_DETAIL_DECL_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2///////// 3/////////4/////////5/////////6/////////7/////////8 +// decl.hpp +// +// (c) Copyright Robert Ramey 2004 +// Use, modification, and distribution is subject to 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) + +// See library home page at http://www.boost.org/libs/serialization + +//----------------------------------------------------------------------------// + +// This header implements separate compilation features as described in +// http://www.boost.org/more/separate_compilation.html + +#include +#include + +#if defined(BOOST_HAS_DECLSPEC) + #if (defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SERIALIZATION_DYN_LINK)) + #if defined(BOOST_ARCHIVE_SOURCE) + #if defined(__BORLANDC__) + #define BOOST_ARCHIVE_DECL(T) T __export + #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) T __export + #else + #define BOOST_ARCHIVE_DECL(T) __declspec(dllexport) T + #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) __declspec(dllexport) T + #endif + #else + #if defined(__BORLANDC__) + #define BOOST_ARCHIVE_DECL(T) T __import + #else + #define BOOST_ARCHIVE_DECL(T) __declspec(dllimport) T + #endif + #endif + #if defined(BOOST_WARCHIVE_SOURCE) + #if defined(__BORLANDC__) + #define BOOST_WARCHIVE_DECL(T) T __export + #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) T __export + #else + #define BOOST_WARCHIVE_DECL(T) __declspec(dllexport) T + #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) __declspec(dllexport) T + #endif + #else + #if defined(__BORLANDC__) + #define BOOST_WARCHIVE_DECL(T) T __import + #else + #define BOOST_WARCHIVE_DECL(T) __declspec(dllimport) T + #endif + #endif + #if !defined(BOOST_WARCHIVE_SOURCE) && !defined(BOOST_ARCHIVE_SOURCE) + #if defined(__BORLANDC__) + #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) T __import + #else + #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) __declspec(dllimport) T + #endif + #endif + #endif +#endif // BOOST_HAS_DECLSPEC + +#if ! defined(BOOST_ARCHIVE_DECL) + #define BOOST_ARCHIVE_DECL(T) T +#endif +#if ! defined(BOOST_WARCHIVE_DECL) + #define BOOST_WARCHIVE_DECL(T) T +#endif +#if ! defined(BOOST_ARCHIVE_OR_WARCHIVE_DECL) + #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) T +#endif + +#endif // BOOST_ARCHIVE_DETAIL_DECL_HPP diff --git a/win32/include/boost/archive/detail/interface_iarchive.hpp b/win32/include/boost/archive/detail/interface_iarchive.hpp new file mode 100755 index 000000000..2576b8660 --- /dev/null +++ b/win32/include/boost/archive/detail/interface_iarchive.hpp @@ -0,0 +1,78 @@ +#ifndef BOOST_ARCHIVE_DETAIL_INTERFACE_IARCHIVE_HPP +#define BOOST_ARCHIVE_DETAIL_INTERFACE_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// interface_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. +#include +#include // NULL +#include +#include +#include +#include +#include +#include // must be the last header + +namespace boost { +namespace archive { +namespace detail { + +class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer; + +template +class interface_iarchive +{ +protected: + interface_iarchive(){}; +public: + ///////////////////////////////////////////////////////// + // archive public interface + typedef mpl::bool_ is_loading; + typedef mpl::bool_ is_saving; + + // return a pointer to the most derived class + Archive * This(){ + return static_cast(this); + } + + template + const basic_pointer_iserializer * + register_type(T * = NULL){ + const basic_pointer_iserializer & bpis = + boost::serialization::singleton< + pointer_iserializer + >::get_const_instance(); + this->This()->register_basic_serializer(bpis.get_basic_serializer()); + return & bpis; + } + template + Archive & operator>>(T & t){ + this->This()->load_override(t, 0); + return * this->This(); + } + + // the & operator + template + Archive & operator&(T & t){ + return *(this->This()) >> t; + } +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_DETAIL_INTERFACE_IARCHIVE_HPP diff --git a/win32/include/boost/archive/detail/interface_oarchive.hpp b/win32/include/boost/archive/detail/interface_oarchive.hpp new file mode 100755 index 000000000..7ea65bdfa --- /dev/null +++ b/win32/include/boost/archive/detail/interface_oarchive.hpp @@ -0,0 +1,85 @@ +#ifndef BOOST_ARCHIVE_DETAIL_INTERFACE_OARCHIVE_HPP +#define BOOST_ARCHIVE_DETAIL_INTERFACE_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// interface_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. +#include +#include // NULL +#include +#include + +#include +#include +#include // must be the last header + +#include + +namespace boost { +namespace archive { +namespace detail { + +class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer; + +template +class interface_oarchive +{ +protected: + interface_oarchive(){}; +public: + ///////////////////////////////////////////////////////// + // archive public interface + typedef mpl::bool_ is_loading; + typedef mpl::bool_ is_saving; + + // return a pointer to the most derived class + Archive * This(){ + return static_cast(this); + } + + template + const basic_pointer_oserializer * + register_type(const T * = NULL){ + const basic_pointer_oserializer & bpos = + boost::serialization::singleton< + pointer_oserializer + >::get_const_instance(); + this->This()->register_basic_serializer(bpos.get_basic_serializer()); + return & bpos; + } + + template + Archive & operator<<(T & t){ + this->This()->save_override(t, 0); + return * this->This(); + } + + // the & operator + template + Archive & operator&(T & t){ + #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + return * this->This() << const_cast(t); + #else + return * this->This() << t; + #endif + } +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_DETAIL_INTERFACE_IARCHIVE_HPP diff --git a/win32/include/boost/archive/detail/iserializer.hpp b/win32/include/boost/archive/detail/iserializer.hpp new file mode 100755 index 000000000..b91a15f94 --- /dev/null +++ b/win32/include/boost/archive/detail/iserializer.hpp @@ -0,0 +1,549 @@ +#ifndef BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP +#define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#pragma inline_depth(511) +#pragma inline_recursion(on) +#endif + +#if defined(__MWERKS__) +#pragma inline_depth(511) +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// iserializer.hpp: interface for serialization system. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include // for placement new +#include // for auto_ptr +#include // size_t, NULL + +#include +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO + #include + #endif +// the following is need only for dynamic cast of polymorphic pointers +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { + +// an accessor to permit friend access to archives. Needed because +// some compilers don't handle friend templates completely +class load_access { +public: + template + static void load_primitive(Archive &ar, T &t){ + ar.load(t); + } +}; + +namespace detail { + +template +class iserializer : public basic_iserializer +{ +private: + virtual void destroy(/*const*/ void *address) const { + boost::serialization::access::destroy(static_cast(address)); + } + // private constructor to inhibit any existence other than the + // static one +public: + explicit iserializer() : + basic_iserializer( + boost::serialization::type_info_implementation::type + ::get_const_instance() + ) + {} + virtual BOOST_DLLEXPORT void load_object_data( + basic_iarchive & ar, + void *x, + const unsigned int file_version + ) const BOOST_USED; + virtual bool class_info() const { + return boost::serialization::implementation_level::value + >= boost::serialization::object_class_info; + } + virtual bool tracking(const unsigned int /* flags */) const { + return boost::serialization::tracking_level::value + == boost::serialization::track_always + || ( boost::serialization::tracking_level::value + == boost::serialization::track_selectively + && serialized_as_pointer()); + } + virtual unsigned int version() const { + return ::boost::serialization::version::value; + } + virtual bool is_polymorphic() const { + return boost::is_polymorphic::value; + } + virtual ~iserializer(){}; +}; + +template +BOOST_DLLEXPORT void iserializer::load_object_data( + basic_iarchive & ar, + void *x, + const unsigned int file_version +) const { + // make sure call is routed through the higest interface that might + // be specialized by the user. + boost::serialization::serialize_adl( + boost::smart_cast_reference(ar), + * static_cast(x), + file_version + ); +} + +template +class pointer_iserializer + : public archive_pointer_iserializer +{ +private: + virtual const basic_iserializer & get_basic_serializer() const { + return boost::serialization::singleton< + iserializer + >::get_const_instance(); + } + BOOST_DLLEXPORT virtual void load_object_ptr( + basic_iarchive & ar, + void * & x, + const unsigned int file_version + ) const BOOST_USED; +public: + pointer_iserializer(); +}; + +// note trick to be sure that operator new is using class specific +// version if such exists. Due to Peter Dimov. +// note: the following fails if T has no default constructor. +// otherwise it would have been ideal +//struct heap_allocator : public T +//{ +// T * invoke(){ +// return ::new(sizeof(T)); +// } +//} + +// note: this should really be a member of the load_ptr function +// below but some compilers still complain about this. +template +struct heap_allocator +{ + #if 0 + // note: this fails on msvc 7.0 and gcc 3.2 + template struct test; + typedef char* yes; + typedef int* no; + template + yes has_op_new(U*, test* = 0); + no has_op_new(...); + + template + T * new_operator(U); + + T * new_operator(yes){ + return (T::operator new)(sizeof(T)); + } + T * new_operator(no){ + return static_cast(operator new(sizeof(T))); + } + static T * invoke(){ + return new_operator(has_op_new(static_cast(NULL))); + } + #else + // while this doesn't handle operator new overload for class T + static T * invoke(){ + return static_cast(operator new(sizeof(T))); + } + #endif +}; + +// due to Martin Ecker +template +class auto_ptr_with_deleter +{ +public: + explicit auto_ptr_with_deleter(T* p) : + m_p(p) + {} + ~auto_ptr_with_deleter(){ + if (m_p) + boost::serialization::access::destroy(m_p); + } + T* get() const { + return m_p; + } + + T* release() { + T* p = m_p; + m_p = NULL; + return p; + } +private: + T* m_p; +}; + +template +BOOST_DLLEXPORT void pointer_iserializer::load_object_ptr( + basic_iarchive & ar, + void * & x, + const unsigned int file_version +) const +{ + Archive & ar_impl = boost::smart_cast_reference(ar); + + auto_ptr_with_deleter ap(heap_allocator::invoke()); + if(NULL == ap.get()) + boost::throw_exception(std::bad_alloc()) ; + + T * t = ap.get(); + x = t; + + // catch exception during load_construct_data so that we don't + // automatically delete the t which is most likely not fully + // constructed + BOOST_TRY { + // this addresses an obscure situtation that occurs when + // load_constructor de-serializes something through a pointer. + ar.next_object_pointer(t); + boost::serialization::load_construct_data_adl( + ar_impl, + t, + file_version + ); + } + BOOST_CATCH(...){ + ap.release(); + BOOST_RETHROW; + } + BOOST_CATCH_END + + ar_impl >> boost::serialization::make_nvp(NULL, * t); + ap.release(); +} + +template +pointer_iserializer::pointer_iserializer() : + archive_pointer_iserializer( + boost::serialization::type_info_implementation::type + ::get_const_instance() + ) +{ + boost::serialization::singleton< + iserializer + >::get_mutable_instance().set_bpis(this); +} + +template +struct load_non_pointer_type { + // note this bounces the call right back to the archive + // with no runtime overhead + struct load_primitive { + static void invoke(Archive & ar, T & t){ + load_access::load_primitive(ar, t); + } + }; + // note this bounces the call right back to the archive + // with no runtime overhead + struct load_only { + static void invoke(Archive & ar, T & t){ + // short cut to user's serializer + // make sure call is routed through the higest interface that might + // be specialized by the user. + boost::serialization::serialize_adl( + ar, t, boost::serialization::version::value + ); + } + }; + + // note this save class information including version + // and serialization level to the archive + struct load_standard { + static void invoke(Archive &ar, T &t){ + //BOOST_STATIC_ASSERT(! boost::is_const::value); + // borland - for some reason T is const here - even though + // its not called that way - so fix it her + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type typex; + void * x = & const_cast(t); + ar.load_object( + x, + boost::serialization::singleton< + iserializer + >::get_const_instance() + ); + } + }; + + struct load_conditional { + static void invoke(Archive &ar, T &t){ + //if(0 == (ar.get_flags() & no_tracking)) + load_standard::invoke(ar, t); + //else + // load_only::invoke(ar, t); + } + }; + + typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< + // if its primitive + mpl::equal_to< + boost::serialization::implementation_level, + mpl::int_ + >, + mpl::identity, + // else + BOOST_DEDUCED_TYPENAME mpl::eval_if< + // class info / version + mpl::greater_equal< + boost::serialization::implementation_level, + mpl::int_ + >, + // do standard load + mpl::identity, + // else + BOOST_DEDUCED_TYPENAME mpl::eval_if< + // no tracking + mpl::equal_to< + boost::serialization::tracking_level, + mpl::int_ + >, + // do a fast load + mpl::identity, + // else + // do a fast load only tracking is turned off + mpl::identity + > > >::type typex; + + static void invoke(Archive & ar, T &t){ + // check that we're not trying to serialize something that + // has been marked not to be serialized. If this your program + // traps here, you've tried to serialize a class whose trait + // has been marked "non-serializable". Either reset the trait + // (see level.hpp) or change program not to serialize items of this class + BOOST_STATIC_ASSERT(( + mpl::greater_equal< + boost::serialization::implementation_level, + mpl::int_ + >::value + )); + typex::invoke(ar, t); + } +}; + +template +struct load_pointer_type { + template + struct abstract + { + static const basic_pointer_iserializer * register_type(Archive & /* ar */){ + // it has? to be polymorphic + BOOST_STATIC_ASSERT(boost::is_polymorphic::value); + return static_cast(NULL); + } + }; + + template + struct non_abstract + { + static const basic_pointer_iserializer * register_type(Archive & ar){ + return ar.register_type(static_cast(NULL)); + } + }; + + template + static const basic_pointer_iserializer * register_type(Archive &ar, T & /*t*/){ + // there should never be any need to load an abstract polymorphic + // class pointer. Inhibiting code generation for this + // permits abstract base classes to be used - note: exception + // virtual serialize functions used for plug-ins + typedef BOOST_DEDUCED_TYPENAME + mpl::eval_if< + boost::serialization::is_abstract, + mpl::identity >, + mpl::identity > + >::type typex; + return typex::register_type(ar); + } + + template + static T * pointer_tweak( + const boost::serialization::extended_type_info & eti, + void * t, + T & + ) { + // tweak the pointer back to the base class + return static_cast( + boost::serialization::void_upcast( + eti, + boost::serialization::type_info_implementation::type + ::get_const_instance(), + t + ) + ); + } + + static void invoke(Archive & ar, Tptr & t){ + const basic_pointer_iserializer * bpis_ptr = register_type(ar, *t); + const basic_pointer_iserializer * newbpis_ptr = ar.load_pointer( + * reinterpret_cast(&t), + bpis_ptr, + archive_pointer_iserializer::find + ); + // if the pointer isn't that of the base class + if(newbpis_ptr != bpis_ptr){ + t = pointer_tweak(newbpis_ptr->get_eti(), t, *t); + } + } +}; + +template +struct load_enum_type { + static void invoke(Archive &ar, T &t){ + // convert integers to correct enum to load + int i; + ar >> boost::serialization::make_nvp(NULL, i); + t = static_cast(i); + } +}; + +template +struct load_array_type { + static void invoke(Archive &ar, T &t){ + typedef BOOST_DEDUCED_TYPENAME remove_extent::type value_type; + + // convert integers to correct enum to load + int current_count = sizeof(t) / ( + static_cast(static_cast(&t[1])) + - static_cast(static_cast(&t[0])) + ); + int count; + ar >> BOOST_SERIALIZATION_NVP(count); + if(count > current_count) + boost::throw_exception(archive::archive_exception( + boost::archive::archive_exception::array_size_too_short + )); + ar >> serialization::make_array(static_cast(&t[0]),count); + } +}; + +} // detail + +template +inline void load(Archive &ar, T &t){ + // if this assertion trips. It means we're trying to load a + // const object with a compiler that doesn't have correct + // funtion template ordering. On other compilers, this is + // handled below. + BOOST_STATIC_ASSERT(! boost::is_const::value); + typedef + BOOST_DEDUCED_TYPENAME mpl::eval_if, + mpl::identity > + ,//else + BOOST_DEDUCED_TYPENAME mpl::eval_if, + mpl::identity > + ,//else + BOOST_DEDUCED_TYPENAME mpl::eval_if, + mpl::identity > + ,//else + mpl::identity > + > + > + >::type typex; + typex::invoke(ar, t); +} + +// BORLAND +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560)) +// borland has a couple of problems +// a) if function is partiall specialized - see below +// const paramters are transformed to non-const ones +// b) implementation of base_object can't be made to work +// correctly which results in all base_object s being const. +// So, strip off the const for borland. This breaks the trap +// for loading const objects - but I see no alternative +template +inline void load(Archive &ar, const T & t){ + load(ar, const_cast(t)); +} +#endif + +// let wrappers through. +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +template +inline void load_wrapper(Archive &ar, const T&t, mpl::true_){ + boost::archive::load(ar, const_cast(t)); +} + +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560)) +template +inline void load(Archive &ar, const T&t){ + load_wrapper(ar,t,serialization::is_wrapper()); +} +#endif +#endif + +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP diff --git a/win32/include/boost/archive/detail/oserializer.hpp b/win32/include/boost/archive/detail/oserializer.hpp new file mode 100755 index 000000000..6d12ffb4b --- /dev/null +++ b/win32/include/boost/archive/detail/oserializer.hpp @@ -0,0 +1,544 @@ +#ifndef BOOST_ARCHIVE_OSERIALIZER_HPP +#define BOOST_ARCHIVE_OSERIALIZER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#pragma inline_depth(511) +#pragma inline_recursion(on) +#endif + +#if defined(__MWERKS__) +#pragma inline_depth(511) +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// oserializer.hpp: interface for serialization system. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include // NULL + +#include +#include +#include +#include +#include +#include + +#include +#include +//#include +#include +//#include +#include +#include +#include + +#include +#include +//#include +#include +#include +#include +#include +//#include +//#include +#include + + #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO + #include + #endif +// the following is need only for dynamic cast of polymorphic pointers +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { + +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { + +// an accessor to permit friend access to archives. Needed because +// some compilers don't handle friend templates completely +class save_access { +public: + template + static void end_preamble(Archive & ar){ + ar.end_preamble(); + } + template + static void save_primitive(Archive & ar, const T & t){ + ar.end_preamble(); + ar.save(t); + } +}; + +namespace detail { + +template +class oserializer : public basic_oserializer +{ +private: + // private constructor to inhibit any existence other than the + // static one +public: + explicit BOOST_DLLEXPORT oserializer() : + basic_oserializer( + boost::serialization::type_info_implementation::type + ::get_const_instance() + ) + {} + virtual BOOST_DLLEXPORT void save_object_data( + basic_oarchive & ar, + const void *x + ) const BOOST_USED; + virtual bool class_info() const { + return boost::serialization::implementation_level::value + >= boost::serialization::object_class_info; + } + virtual bool tracking(const unsigned int /* flags */) const { + return boost::serialization::tracking_level::value == boost::serialization::track_always + || (boost::serialization::tracking_level::value == boost::serialization::track_selectively + && serialized_as_pointer()); + } + virtual unsigned int version() const { + return ::boost::serialization::version::value; + } + virtual bool is_polymorphic() const { + return boost::is_polymorphic::value; + } + virtual ~oserializer(){} +}; + +template +BOOST_DLLEXPORT void oserializer::save_object_data( + basic_oarchive & ar, + const void *x +) const { + // make sure call is routed through the highest interface that might + // be specialized by the user. + BOOST_STATIC_ASSERT(boost::is_const::value == false); + boost::serialization::serialize_adl( + boost::smart_cast_reference(ar), + * static_cast(const_cast(x)), + version() + ); +} + +template +class pointer_oserializer + : public archive_pointer_oserializer +{ + const basic_oserializer & get_basic_serializer() const; +private: + virtual BOOST_DLLEXPORT void save_object_ptr( + basic_oarchive & ar, + const void * x + ) const BOOST_USED; +public: + explicit BOOST_DLLEXPORT pointer_oserializer() BOOST_USED; +}; + +template +const basic_oserializer & +pointer_oserializer::get_basic_serializer() const { + return boost::serialization::singleton< + oserializer + >::get_const_instance(); +} + +template +BOOST_DLLEXPORT void pointer_oserializer::save_object_ptr( + basic_oarchive & ar, + const void * x +) const { + assert(NULL != x); + // make sure call is routed through the highest interface that might + // be specialized by the user. + T * t = static_cast(const_cast(x)); + const unsigned int file_version = boost::serialization::version::value; + Archive & ar_impl = boost::smart_cast_reference(ar); + boost::serialization::save_construct_data_adl( + ar_impl, + t, + file_version + ); + ar_impl << boost::serialization::make_nvp(NULL, * t); +} + +template +BOOST_DLLEXPORT pointer_oserializer::pointer_oserializer() : + archive_pointer_oserializer( + boost::serialization::type_info_implementation::type + ::get_const_instance() + ) +{ + // make sure appropriate member function is instantiated + boost::serialization::singleton< + oserializer + >::get_mutable_instance().set_bpos(this); +} + +template +struct save_non_pointer_type { + // note this bounces the call right back to the archive + // with no runtime overhead + struct save_primitive { + static void invoke(Archive & ar, const T & t){ + save_access::save_primitive(ar, t); + } + }; + // same as above but passes through serialization + struct save_only { + static void invoke(Archive & ar, const T & t){ + // make sure call is routed through the highest interface that might + // be specialized by the user. + boost::serialization::serialize_adl( + ar, + const_cast(t), + ::boost::serialization::version::value + ); + } + }; + // adds class information to the archive. This includes + // serialization level and class version + struct save_standard { + static void invoke(Archive &ar, const T & t){ + ar.save_object( + & t, + boost::serialization::singleton< + oserializer + >::get_const_instance() + ); + } + }; + + // adds class information to the archive. This includes + // serialization level and class version + struct save_conditional { + static void invoke(Archive &ar, const T &t){ + //if(0 == (ar.get_flags() & no_tracking)) + save_standard::invoke(ar, t); + //else + // save_only::invoke(ar, t); + } + }; + + typedef + BOOST_DEDUCED_TYPENAME mpl::eval_if< + // if its primitive + mpl::equal_to< + boost::serialization::implementation_level, + mpl::int_ + >, + mpl::identity, + // else + BOOST_DEDUCED_TYPENAME mpl::eval_if< + // class info / version + mpl::greater_equal< + boost::serialization::implementation_level, + mpl::int_ + >, + // do standard save + mpl::identity, + // else + BOOST_DEDUCED_TYPENAME mpl::eval_if< + // no tracking + mpl::equal_to< + boost::serialization::tracking_level, + mpl::int_ + >, + // do a fast save + mpl::identity, + // else + // do a fast save only tracking is turned off + mpl::identity + > > >::type typex; + + static void invoke(Archive & ar, const T & t){ + // check that we're not trying to serialize something that + // has been marked not to be serialized. If this your program + // traps here, you've tried to serialize a class whose trait + // has been marked "non-serializable". Either reset the trait + // (see level.hpp) or change program not to serialize items of this class + BOOST_STATIC_ASSERT(( + mpl::greater_equal< + boost::serialization::implementation_level, + mpl::int_ + >::value + )); + typex::invoke(ar, t); + }; +}; + +template +struct save_pointer_type { + template + struct abstract + { + static const basic_pointer_oserializer * register_type(Archive & /* ar */){ + // it has? to be polymorphic + BOOST_STATIC_ASSERT(boost::is_polymorphic::value); + return NULL; + } + }; + + template + struct non_abstract + { + static const basic_pointer_oserializer * register_type(Archive & ar){ + return ar.register_type(static_cast(NULL)); + } + }; + + template + static const basic_pointer_oserializer * register_type(Archive &ar, T & /*t*/){ + // there should never be any need to save an abstract polymorphic + // class pointer. Inhibiting code generation for this + // permits abstract base classes to be used - note: exception + // virtual serialize functions used for plug-ins + typedef + BOOST_DEDUCED_TYPENAME mpl::eval_if< + boost::serialization::is_abstract, + mpl::identity >, + mpl::identity > + >::type typex; + return typex::register_type(ar); + } + + template + struct non_polymorphic + { + static void save( + Archive &ar, + T & t + ){ + const basic_pointer_oserializer & bpos = + boost::serialization::singleton< + pointer_oserializer + >::get_const_instance(); + // save the requested pointer type + ar.save_pointer(& t, & bpos); + } + }; + + template + struct polymorphic + { + static void save( + Archive &ar, + T & t + ){ + BOOST_DEDUCED_TYPENAME + boost::serialization::type_info_implementation::type const + & i = boost::serialization::type_info_implementation::type + ::get_const_instance(); + + boost::serialization::extended_type_info const * const this_type = & i; + + // retrieve the true type of the object pointed to + // if this assertion fails its an error in this library + assert(NULL != this_type); + + const boost::serialization::extended_type_info * true_type = + i.get_derived_extended_type_info(t); + + // note:if this exception is thrown, be sure that derived pointer + // is either registered or exported. + if(NULL == true_type){ + boost::throw_exception( + archive_exception(archive_exception::unregistered_class) + ); + } + + // if its not a pointer to a more derived type + const void *vp = static_cast(&t); + if(*this_type == *true_type){ + const basic_pointer_oserializer * bpos = register_type(ar, t); + ar.save_pointer(vp, bpos); + return; + } + // convert pointer to more derived type. if this is thrown + // it means that the base/derived relationship hasn't be registered + vp = serialization::void_downcast( + *true_type, + *this_type, + static_cast(&t) + ); + if(NULL == vp){ + boost::throw_exception( + archive_exception(archive_exception::unregistered_cast) + ); + } + + // since true_type is valid, and this only gets made if the + // pointer oserializer object has been created, this should never + // fail + const basic_pointer_oserializer * bpos + = archive_pointer_oserializer::find(* true_type); + assert(NULL != bpos); + if(NULL == bpos) + boost::throw_exception( + archive_exception(archive_exception::unregistered_class) + ); + ar.save_pointer(vp, bpos); + } + }; + + // out of line selector works around borland quirk + template + struct conditional { + typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< + is_polymorphic, + mpl::identity >, + mpl::identity > + >::type type; + }; + + // used to convert TPtr in to a pointer to a T + template + static void save( + Archive & ar, + const T & t + ){ + conditional::type::save(ar, const_cast(t)); + } + + template + static void const_check(T & t){ + BOOST_STATIC_ASSERT(! boost::is_const::value); + } + + static void invoke(Archive &ar, const TPtr t){ + #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // if your program traps here, its because you tried to do + // something like ar << t where t is a pointer to a const value + // void f3(A const* a, text_oarchive& oa) + // { + // oa << a; + // } + // with a compiler which doesn't support remove_const + // const_check(* t); + #else + // otherwise remove the const + #endif + register_type(ar, * t); + if(NULL == t){ + basic_oarchive & boa = boost::smart_cast_reference(ar); + boa.save_null_pointer(); + save_access::end_preamble(ar); + return; + } + save(ar, * t); + }; +}; + +template +struct save_enum_type +{ + static void invoke(Archive &ar, const T &t){ + // convert enum to integers on save + const int i = static_cast(t); + ar << boost::serialization::make_nvp(NULL, i); + } +}; + +template +struct save_array_type +{ + static void invoke(Archive &ar, const T &t){ + typedef BOOST_DEDUCED_TYPENAME boost::remove_extent::type value_type; + + save_access::end_preamble(ar); + // consider alignment + int count = sizeof(t) / ( + static_cast(static_cast(&t[1])) + - static_cast(static_cast(&t[0])) + ); + ar << BOOST_SERIALIZATION_NVP(count); + ar << serialization::make_array(static_cast(&t[0]),count); + } +}; + +} // detail + +template +inline void save(Archive & ar, const T &t){ + typedef + BOOST_DEDUCED_TYPENAME mpl::eval_if, + mpl::identity >, + //else + BOOST_DEDUCED_TYPENAME mpl::eval_if, + mpl::identity >, + //else + BOOST_DEDUCED_TYPENAME mpl::eval_if, + mpl::identity >, + //else + mpl::identity > + > + > + >::type typex; + typex::invoke(ar, t); +} + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +template +struct check_tracking { + typedef BOOST_DEDUCED_TYPENAME mpl::if_< + // if its never tracked. + BOOST_DEDUCED_TYPENAME mpl::equal_to< + serialization::tracking_level, + mpl::int_ + >, + // it better not be a pointer + mpl::not_ >, + //else + // otherwise if it might be tracked. So there shouldn't + // be any problem making a const + is_const + >::type typex; + BOOST_STATIC_CONSTANT(bool, value = typex::value); +}; + +template +inline void save(Archive & ar, T &t){ + // if your program traps here, it indicates that your doing one of the following: + // a) serializing an object of a type marked "track_never" through a pointer. + // b) saving an non-const object of a type not markd "track_never) + // Either of these conditions may be an indicator of an error usage of the + // serialization library and should be double checked. See documentation on + // object tracking. Also, see the "rationale" section of the documenation + // for motivation for this checking. + BOOST_STATIC_WARNING(check_tracking::value); + save(ar, const_cast(t)); +} +#endif + +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_OSERIALIZER_HPP diff --git a/win32/include/boost/archive/detail/polymorphic_iarchive_route.hpp b/win32/include/boost/archive/detail/polymorphic_iarchive_route.hpp new file mode 100755 index 000000000..f7dbddb51 --- /dev/null +++ b/win32/include/boost/archive/detail/polymorphic_iarchive_route.hpp @@ -0,0 +1,196 @@ +#ifndef BOOST_ARCHIVE_DETAIL_POLYMORPHIC_IARCHIVE_ROUTE_HPP +#define BOOST_ARCHIVE_DETAIL_POLYMORPHIC_IARCHIVE_ROUTE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_iarchive_route.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include + +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include +#include +#include +#include // must be the last header + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization +namespace archive { +namespace detail{ + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iserializer; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer; + +template +class polymorphic_iarchive_route : + public polymorphic_iarchive, + // note: gcc dynamic cross cast fails if the the derivation below is + // not public. I think this is a mistake. + public /*protected*/ ArchiveImplementation, + private boost::noncopyable +{ +private: + // these are used by the serialization library. + virtual void load_object( + void *t, + const basic_iserializer & bis + ){ + ArchiveImplementation::load_object(t, bis); + } + virtual const basic_pointer_iserializer * load_pointer( + void * & t, + const basic_pointer_iserializer * bpis_ptr, + const basic_pointer_iserializer * (*finder)( + const boost::serialization::extended_type_info & type + ) + ){ + return ArchiveImplementation::load_pointer(t, bpis_ptr, finder); + } + virtual void set_library_version(unsigned int archive_library_version){ + ArchiveImplementation::set_library_version(archive_library_version); + } + virtual unsigned int get_library_version() const{ + return ArchiveImplementation::get_library_version(); + } + virtual unsigned int get_flags() const { + return ArchiveImplementation::get_flags(); + } + virtual void delete_created_pointers(){ + ArchiveImplementation::delete_created_pointers(); + } + virtual void reset_object_address( + const void * new_address, + const void * old_address + ){ + ArchiveImplementation::reset_object_address(new_address, old_address); + } + virtual void load_binary(void * t, std::size_t size){ + ArchiveImplementation::load_binary(t, size); + } + // primitive types the only ones permitted by polymorphic archives + virtual void load(bool & t){ + ArchiveImplementation::load(t); + } + virtual void load(char & t){ + ArchiveImplementation::load(t); + } + virtual void load(signed char & t){ + ArchiveImplementation::load(t); + } + virtual void load(unsigned char & t){ + ArchiveImplementation::load(t); + } + #ifndef BOOST_NO_CWCHAR + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + virtual void load(wchar_t & t){ + ArchiveImplementation::load(t); + } + #endif + #endif + virtual void load(short & t){ + ArchiveImplementation::load(t); + } + virtual void load(unsigned short & t){ + ArchiveImplementation::load(t); + } + virtual void load(int & t){ + ArchiveImplementation::load(t); + } + virtual void load(unsigned int & t){ + ArchiveImplementation::load(t); + } + virtual void load(long & t){ + ArchiveImplementation::load(t); + } + virtual void load(unsigned long & t){ + ArchiveImplementation::load(t); + } + #if !defined(BOOST_NO_INTRINSIC_INT64_T) + virtual void load(boost::int64_t & t){ + ArchiveImplementation::load(t); + } + virtual void load(boost::uint64_t & t){ + ArchiveImplementation::load(t); + } + #endif + virtual void load(float & t){ + ArchiveImplementation::load(t); + } + virtual void load(double & t){ + ArchiveImplementation::load(t); + } + virtual void load(std::string & t){ + ArchiveImplementation::load(t); + } + #ifndef BOOST_NO_STD_WSTRING + virtual void load(std::wstring & t){ + ArchiveImplementation::load(t); + } + #endif + // used for xml and other tagged formats default does nothing + virtual void load_start(const char * name){ + ArchiveImplementation::load_start(name); + } + virtual void load_end(const char * name){ + ArchiveImplementation::load_end(name); + } + + virtual void register_basic_serializer(const basic_iserializer & bis){ + ArchiveImplementation::register_basic_serializer(bis); + } +public: + // this can't be inheriteded because they appear in mulitple + // parents + typedef mpl::bool_ is_loading; + typedef mpl::bool_ is_saving; + // the >> operator + template + polymorphic_iarchive & operator>>(T & t){ + return polymorphic_iarchive::operator>>(t); + } + + // the & operator + template + polymorphic_iarchive & operator&(T & t){ + return polymorphic_iarchive::operator&(t); + } + + // all current archives take a stream as constructor argument + template + polymorphic_iarchive_route( + std::basic_istream<_Elem, _Tr> & is, + unsigned int flags = 0 + ) : + ArchiveImplementation(is, flags) + {} + virtual ~polymorphic_iarchive_route(){}; +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_DETAIL_POLYMORPHIC_IARCHIVE_DISPATCH_HPP diff --git a/win32/include/boost/archive/detail/polymorphic_oarchive_route.hpp b/win32/include/boost/archive/detail/polymorphic_oarchive_route.hpp new file mode 100755 index 000000000..aebd04b52 --- /dev/null +++ b/win32/include/boost/archive/detail/polymorphic_oarchive_route.hpp @@ -0,0 +1,184 @@ +#ifndef BOOST_ARCHIVE_DETAIL_POLYMORPHIC_OARCHIVE_ROUTE_HPP +#define BOOST_ARCHIVE_DETAIL_POLYMORPHIC_OARCHIVE_ROUTE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_oarchive_route.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include +#include +#include // size_t + +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include +#include // must be the last header + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization +namespace archive { +namespace detail{ + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer; + +template +class polymorphic_oarchive_route : + public polymorphic_oarchive, + // note: gcc dynamic cross cast fails if the the derivation below is + // not public. I think this is a mistake. + public /*protected*/ ArchiveImplementation, + private boost::noncopyable +{ +private: + // these are used by the serialization library. + virtual void save_object( + const void *x, + const detail::basic_oserializer & bos + ){ + ArchiveImplementation::save_object(x, bos); + } + virtual void save_pointer( + const void * t, + const detail::basic_pointer_oserializer * bpos_ptr + ){ + ArchiveImplementation::save_pointer(t, bpos_ptr); + } + virtual void save_null_pointer(){ + ArchiveImplementation::save_null_pointer(); + } + // primitive types the only ones permitted by polymorphic archives + virtual void save(const bool t){ + ArchiveImplementation::save(t); + } + virtual void save(const char t){ + ArchiveImplementation::save(t); + } + virtual void save(const signed char t){ + ArchiveImplementation::save(t); + } + virtual void save(const unsigned char t){ + ArchiveImplementation::save(t); + } + #ifndef BOOST_NO_CWCHAR + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + virtual void save(const wchar_t t){ + ArchiveImplementation::save(t); + } + #endif + #endif + virtual void save(const short t){ + ArchiveImplementation::save(t); + } + virtual void save(const unsigned short t){ + ArchiveImplementation::save(t); + } + virtual void save(const int t){ + ArchiveImplementation::save(t); + } + virtual void save(const unsigned int t){ + ArchiveImplementation::save(t); + } + virtual void save(const long t){ + ArchiveImplementation::save(t); + } + virtual void save(const unsigned long t){ + ArchiveImplementation::save(t); + } + #if !defined(BOOST_NO_INTRINSIC_INT64_T) + virtual void save(const boost::int64_t t){ + ArchiveImplementation::save(t); + } + virtual void save(const boost::uint64_t t){ + ArchiveImplementation::save(t); + } + #endif + virtual void save(const float t){ + ArchiveImplementation::save(t); + } + virtual void save(const double t){ + ArchiveImplementation::save(t); + } + virtual void save(const std::string & t){ + ArchiveImplementation::save(t); + } + #ifndef BOOST_NO_STD_WSTRING + virtual void save(const std::wstring & t){ + ArchiveImplementation::save(t); + } + #endif + virtual unsigned int get_library_version() const{ + return ArchiveImplementation::get_library_version(); + } + virtual unsigned int get_flags() const { + return ArchiveImplementation::get_flags(); + } + virtual void save_binary(const void * t, std::size_t size){ + ArchiveImplementation::save_binary(t, size); + } + // used for xml and other tagged formats default does nothing + virtual void save_start(const char * name){ + ArchiveImplementation::save_start(name); + } + virtual void save_end(const char * name){ + ArchiveImplementation::save_end(name); + } + virtual void end_preamble(){ + ArchiveImplementation::end_preamble(); + } + virtual void register_basic_serializer(const detail::basic_oserializer & bos){ + ArchiveImplementation::register_basic_serializer(bos); + } +public: + // this can't be inheriteded because they appear in mulitple + // parents + typedef mpl::bool_ is_loading; + typedef mpl::bool_ is_saving; + // the << operator + template + polymorphic_oarchive & operator<<(T & t){ + return polymorphic_oarchive::operator<<(t); + } + // the & operator + template + polymorphic_oarchive & operator&(T & t){ + return polymorphic_oarchive::operator&(t); + } + // all current archives take a stream as constructor argument + template + polymorphic_oarchive_route( + std::basic_ostream<_Elem, _Tr> & os, + unsigned int flags = 0 + ) : + ArchiveImplementation(os, flags) + {} + virtual ~polymorphic_oarchive_route(){}; +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_DETAIL_POLYMORPHIC_OARCHIVE_DISPATCH_HPP diff --git a/win32/include/boost/archive/detail/register_archive.hpp b/win32/include/boost/archive/detail/register_archive.hpp new file mode 100755 index 000000000..616070959 --- /dev/null +++ b/win32/include/boost/archive/detail/register_archive.hpp @@ -0,0 +1,53 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_ARCHIVE_DETAIL_REGISTER_ARCHIVE_DWA2006521_HPP +# define BOOST_ARCHIVE_DETAIL_REGISTER_ARCHIVE_DWA2006521_HPP + +namespace boost { namespace archive { namespace detail { + +// No instantiate_ptr_serialization overloads generated by +// BOOST_SERIALIZATION_REGISTER_ARCHIVE that lexically follow the call +// will be seen *unless* they are in an associated namespace of one of +// the arguments, so we pass one of these along to make sure this +// namespace is considered. See temp.dep.candidate (14.6.4.2) in the +// standard. +struct adl_tag {}; + +template +struct ptr_serialization_support; + +// We could've just used ptr_serialization_support, above, but using +// it with only a forward declaration causes vc6/7 to complain about a +// missing instantiate member, even if it has one. This is just a +// friendly layer of indirection. +template +struct _ptr_serialization_support + : ptr_serialization_support +{ + typedef int type; +}; + +// This function gets called, but its only purpose is to participate +// in overload resolution with the functions declared by +// BOOST_SERIALIZATION_REGISTER_ARCHIVE, below. +template +void instantiate_ptr_serialization(Serializable*, int, adl_tag ) {} + +// The function declaration generated by this macro never actually +// gets called, but its return type gets instantiated, and that's +// enough to cause registration of serialization functions between +// Archive and any exported Serializable type. See also: +// boost/serialization/export.hpp +# define BOOST_SERIALIZATION_REGISTER_ARCHIVE(Archive) \ +namespace boost { namespace archive { namespace detail { \ + \ +template \ +BOOST_DEDUCED_TYPENAME _ptr_serialization_support::type \ +instantiate_ptr_serialization( Serializable*, Archive*, adl_tag ); \ + \ +}}} + +}}} // namespace boost::archive::detail + +#endif // BOOST_ARCHIVE_DETAIL_INSTANTIATE_SERIALIZE_DWA2006521_HPP diff --git a/win32/include/boost/archive/detail/utf8_codecvt_facet.hpp b/win32/include/boost/archive/detail/utf8_codecvt_facet.hpp new file mode 100755 index 000000000..5718c3d69 --- /dev/null +++ b/win32/include/boost/archive/detail/utf8_codecvt_facet.hpp @@ -0,0 +1,21 @@ +// Copyright (c) 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu) +// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu). +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ARCHIVE_DETAIL_UTF8_CODECVT_FACET_HPP +#define BOOST_ARCHIVE_DETAIL_UTF8_CODECVT_FACET_HPP + +#define BOOST_UTF8_BEGIN_NAMESPACE \ + namespace boost { namespace archive { namespace detail { +#define BOOST_UTF8_DECL +#define BOOST_UTF8_END_NAMESPACE }}} + +#include + +#undef BOOST_UTF8_END_NAMESPACE +#undef BOOST_UTF8_DECL +#undef BOOST_UTF8_BEGIN_NAMESPACE + +#endif // BOOST_ARCHIVE_DETAIL_UTF8_CODECVT_FACET_HPP diff --git a/win32/include/boost/archive/dinkumware.hpp b/win32/include/boost/archive/dinkumware.hpp new file mode 100755 index 000000000..59afd69ce --- /dev/null +++ b/win32/include/boost/archive/dinkumware.hpp @@ -0,0 +1,224 @@ +#ifndef BOOST_ARCHIVE_DINKUMWARE_HPP +#define BOOST_ARCHIVE_DINKUMWARE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// dinkumware.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +// this file adds a couple of things that are missing from the dinkumware +// implementation of the standard library. + +#include +#include + +#include +#include + +namespace std { + +// define i/o operators for 64 bit integers +template +basic_ostream & +operator<<(basic_ostream & os, boost::uint64_t t){ + // octal rendering of 64 bit number would be 22 octets + eos + CharType d[23]; + unsigned int radix; + + if(os.flags() & (int)std::ios_base::hex) + radix = 16; + else + if(os.flags() & (int)std::ios_base::oct) + radix = 8; + else + //if(s.flags() & (int)std::ios_base::dec) + radix = 10; + unsigned int i = 0; + do{ + unsigned int j = t % radix; + d[i++] = j + ((j < 10) ? '0' : ('a' - 10)); + t /= radix; + } + while(t > 0); + d[i--] = '\0'; + + // reverse digits + unsigned int j = 0; + while(j < i){ + CharType k = d[i]; + d[i] = d[j]; + d[j] = k; + --i;++j; + } + os << d; + return os; + +} + +template +basic_ostream & +operator<<(basic_ostream &os, boost::int64_t t){ + if(0 <= t){ + os << static_cast(t); + } + else{ + os.put('-'); + os << -t; + } + return os; +} + +template +basic_istream & +operator>>(basic_istream &is, boost::int64_t & t){ + CharType d; + do{ + d = is.get(); + } + while(::isspace(d)); + bool negative = (d == '-'); + if(negative) + d = is.get(); + unsigned int radix; + if(is.flags() & (int)std::ios_base::hex) + radix = 16; + else + if(is.flags() & (int)std::ios_base::oct) + radix = 8; + else + //if(s.flags() & (int)std::ios_base::dec) + radix = 10; + t = 0; + do{ + if('0' <= d && d <= '9') + t = t * radix + (d - '0'); + else + if('a' <= d && d <= 'f') + t = t * radix + (d - 'a' + 10); + else + break; + d = is.get(); + } + while(!is.fail()); + // restore the delimiter + is.putback(d); + is.clear(); + if(negative) + t = -t; + return is; +} + +template +basic_istream & +operator>>(basic_istream &is, boost::uint64_t & t){ + boost::int64_t it; + is >> it; + t = it; + return is; +} + +//#endif + +template<> +class back_insert_iterator > : public + iterator +{ +public: + typedef basic_string container_type; + typedef container_type::reference reference; + + explicit back_insert_iterator(container_type & s) + : container(& s) + {} // construct with container + + back_insert_iterator & operator=( + container_type::const_reference Val_ + ){ // push value into container + //container->push_back(Val_); + *container += Val_; + return (*this); + } + + back_insert_iterator & operator*(){ + return (*this); + } + + back_insert_iterator & operator++(){ + // pretend to preincrement + return (*this); + } + + back_insert_iterator operator++(int){ + // pretend to postincrement + return (*this); + } + +protected: + container_type *container; // pointer to container +}; + +template +inline back_insert_iterator > back_inserter( + basic_string & s +){ + return (std::back_insert_iterator >(s)); +} + +template<> +class back_insert_iterator > : public + iterator +{ +public: + typedef basic_string container_type; + typedef container_type::reference reference; + + explicit back_insert_iterator(container_type & s) + : container(& s) + {} // construct with container + + back_insert_iterator & operator=( + container_type::const_reference Val_ + ){ // push value into container + //container->push_back(Val_); + *container += Val_; + return (*this); + } + + back_insert_iterator & operator*(){ + return (*this); + } + + back_insert_iterator & operator++(){ + // pretend to preincrement + return (*this); + } + + back_insert_iterator operator++(int){ + // pretend to postincrement + return (*this); + } + +protected: + container_type *container; // pointer to container +}; + +template +inline back_insert_iterator > back_inserter( + basic_string & s +){ + return (std::back_insert_iterator >(s)); +} + +} // namespace std + +#endif //BOOST_ARCHIVE_DINKUMWARE_HPP diff --git a/win32/include/boost/archive/impl/archive_pointer_iserializer.ipp b/win32/include/boost/archive/impl/archive_pointer_iserializer.ipp new file mode 100755 index 000000000..f51bed92c --- /dev/null +++ b/win32/include/boost/archive/impl/archive_pointer_iserializer.ipp @@ -0,0 +1,82 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// pointer_iserializer.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include +#include // msvc 6.0 needs this for warning suppression +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include +#include +#include + +namespace boost { +namespace archive { +namespace detail { + +namespace { // anon + template + class iserializer_map : public basic_serializer_map + { + }; +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +archive_pointer_iserializer::archive_pointer_iserializer( + const boost::serialization::extended_type_info & eti +) : + basic_pointer_iserializer(eti) +{ + std::pair::iterator, bool> result; + result = serialization::singleton< + iserializer_map + >::get_mutable_instance().insert(this); + assert(result.second); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(const basic_pointer_iserializer *) +archive_pointer_iserializer::find( + const boost::serialization::extended_type_info & eti +){ + const basic_serializer_arg bs(eti); + BOOST_DEDUCED_TYPENAME iserializer_map::const_iterator it; + it = boost::serialization::singleton< + iserializer_map + >::get_const_instance().find(& bs); + assert( + it + != + boost::serialization::singleton< + iserializer_map + >::get_const_instance().end() + ); + return static_cast(*it); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +archive_pointer_iserializer::~archive_pointer_iserializer(){ + std::size_t count; + count = serialization::singleton< + iserializer_map + >::get_mutable_instance().erase(this); + assert(count); +} + +} // namespace detail +} // namespace archive +} // namespace boost diff --git a/win32/include/boost/archive/impl/archive_pointer_oserializer.ipp b/win32/include/boost/archive/impl/archive_pointer_oserializer.ipp new file mode 100755 index 000000000..bc435ff04 --- /dev/null +++ b/win32/include/boost/archive/impl/archive_pointer_oserializer.ipp @@ -0,0 +1,82 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// archive_pointer_oserializer.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include + +#include // msvc 6.0 needs this for warning suppression + +#include +#include +#include + +namespace boost { +namespace archive { +namespace detail { + +namespace { // anon + template + class oserializer_map : public basic_serializer_map + { + }; +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +archive_pointer_oserializer::archive_pointer_oserializer( + const boost::serialization::extended_type_info & eti +) : + basic_pointer_oserializer(eti) +{ + std::pair< + BOOST_DEDUCED_TYPENAME oserializer_map::iterator, + bool + > result; + result = serialization::singleton< + oserializer_map + >::get_mutable_instance().insert(this); + assert(result.second); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(const basic_pointer_oserializer *) +archive_pointer_oserializer::find( + const boost::serialization::extended_type_info & eti +){ + const basic_serializer_arg bs(eti); + basic_serializer_map::const_iterator it; + it = boost::serialization::singleton< + oserializer_map + >::get_const_instance().find(& bs); + assert( + it + != + boost::serialization::singleton< + oserializer_map + >::get_const_instance().end() + ); + return static_cast(*it); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +archive_pointer_oserializer::~archive_pointer_oserializer(){ + // note: we need to check that the map still exists as we can't depend + // on static variables being constructed in a specific sequence + unsigned int count; + count = serialization::singleton< + oserializer_map + >::get_mutable_instance().erase(this); + assert(count); +} + +} // namespace detail +} // namespace archive +} // namespace boost diff --git a/win32/include/boost/archive/impl/basic_binary_iarchive.ipp b/win32/include/boost/archive/impl/basic_binary_iarchive.ipp new file mode 100755 index 000000000..e72c39968 --- /dev/null +++ b/win32/include/boost/archive/impl/basic_binary_iarchive.ipp @@ -0,0 +1,79 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_iarchive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. +#include +#include +#include +#include + +#include // for BOOST_DEDUCED_TYPENAME +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; +} +#endif + +#include + +#include + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation of binary_binary_archive +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_iarchive::load_override(class_name_type & t, int){ + std::string cn; + cn.reserve(BOOST_SERIALIZATION_MAX_KEY_SIZE); + load_override(cn, 0); + if(cn.size() > (BOOST_SERIALIZATION_MAX_KEY_SIZE - 1)) + boost::throw_exception( + archive_exception(archive_exception::invalid_class_name) + ); + std::memcpy(t, cn.data(), cn.size()); + // borland tweak + t.t[cn.size()] = '\0'; +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_iarchive::init(){ + // read signature in an archive version independent manner + std::string file_signature; + * this->This() >> file_signature; + if(file_signature != ARCHIVE_SIGNATURE()) + boost::throw_exception( + archive_exception(archive_exception::invalid_signature) + ); + + // make sure the version of the reading archive library can + // support the format of the archive being read + version_type input_library_version; + * this->This() >> input_library_version; + + #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) + this->set_library_version(input_library_version); + #else + #if ! BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + detail:: + #endif + basic_iarchive::set_library_version(input_library_version); + #endif + + // extra little .t is to get around borland quirk + if(ARCHIVE_VERSION() < input_library_version.t) + boost::throw_exception( + archive_exception(archive_exception::unsupported_version) + ); +} + +} // namespace archive +} // namespace boost diff --git a/win32/include/boost/archive/impl/basic_binary_iprimitive.ipp b/win32/include/boost/archive/impl/basic_binary_iprimitive.ipp new file mode 100755 index 000000000..3522a0765 --- /dev/null +++ b/win32/include/boost/archive/impl/basic_binary_iprimitive.ipp @@ -0,0 +1,196 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_iprimitive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include // size_t, NULL +#include // memcpy + +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; + using ::memcpy; +} // namespace std +#endif + +#include // fixup for RogueWave + +#include +#include + +#include +#include +#include + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// implementation of basic_binary_iprimitive + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_iprimitive::init() +{ + // Detect attempts to pass native binary archives across + // incompatible platforms. This is not fool proof but its + // better than nothing. + unsigned char size; + this->This()->load(size); + if(sizeof(int) != size) + boost::throw_exception( + archive_exception(archive_exception::incompatible_native_format) + ); + this->This()->load(size); + if(sizeof(long) != size) + boost::throw_exception( + archive_exception(archive_exception::incompatible_native_format) + ); + this->This()->load(size); + if(sizeof(float) != size) + boost::throw_exception( + archive_exception(archive_exception::incompatible_native_format) + ); + this->This()->load(size); + if(sizeof(double) != size) + boost::throw_exception( + archive_exception(archive_exception::incompatible_native_format) + ); + + // for checking endian + int i; + this->This()->load(i); + if(1 != i) + boost::throw_exception( + archive_exception(archive_exception::incompatible_native_format) + ); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_iprimitive::load(wchar_t * ws) +{ + std::size_t l; + this->This()->load(l); + load_binary(ws, l * sizeof(wchar_t) / sizeof(char)); + ws[l / sizeof(wchar_t)] = L'\0'; +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_iprimitive::load(std::string & s) +{ + std::size_t l; + this->This()->load(l); + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != s.data()) + #endif + s.resize(l); + // note breaking a rule here - could be a problem on some platform + if(0 < l) + load_binary(&(*s.begin()), l); +} + +#ifndef BOOST_NO_CWCHAR +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_iprimitive::load(char * s) +{ + std::size_t l; + this->This()->load(l); + load_binary(s, l); + s[l] = '\0'; +} +#endif + +#ifndef BOOST_NO_STD_WSTRING +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_iprimitive::load(std::wstring & ws) +{ + std::size_t l; + this->This()->load(l); + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != ws.data()) + #endif + ws.resize(l); + // note breaking a rule here - is could be a problem on some platform + load_binary(const_cast(ws.data()), l * sizeof(wchar_t) / sizeof(char)); +} +#endif + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_binary_iprimitive::basic_binary_iprimitive( + std::basic_streambuf & sb, + bool no_codecvt +) : +#ifndef BOOST_NO_STD_LOCALE + m_sb(sb), + archive_locale(NULL), + locale_saver(m_sb) +{ + if(! no_codecvt){ + archive_locale.reset( + boost::archive::add_facet( + std::locale::classic(), + new codecvt_null + ) + ); + m_sb.pubimbue(* archive_locale); + } +} +#else + m_sb(sb) +{} +#endif + +// some libraries including stl and libcomo fail if the +// buffer isn't flushed before the code_cvt facet is changed. +// I think this is a bug. We explicity invoke sync to when +// we're done with the streambuf to work around this problem. +// Note that sync is a protected member of stream buff so we +// have to invoke it through a contrived derived class. +namespace detail { +// note: use "using" to get past msvc bug +using namespace std; +template +class input_streambuf_access : public std::basic_streambuf { + public: + virtual int sync(){ +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) + return this->basic_streambuf::sync(); +#else + return this->basic_streambuf::sync(); +#endif + } +}; +} // detail + +// scoped_ptr requires that archive_locale be a complete type at time of +// destruction so define destructor here rather than in the header +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_binary_iprimitive::~basic_binary_iprimitive(){ + // push back unread characters + int result = static_cast &>( + m_sb + ).sync(); + if(0 != result){ + boost::throw_exception( + archive_exception(archive_exception::stream_error) + ); + } +} + +} // namespace archive +} // namespace boost diff --git a/win32/include/boost/archive/impl/basic_binary_oarchive.ipp b/win32/include/boost/archive/impl/basic_binary_oarchive.ipp new file mode 100755 index 000000000..3d47d38e5 --- /dev/null +++ b/win32/include/boost/archive/impl/basic_binary_oarchive.ipp @@ -0,0 +1,46 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_oarchive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. +#include +#include +#include +#include + +#include // for BOOST_DEDUCED_TYPENAME +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; +} +#endif + +#include + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation of binary_binary_oarchive + +template +#if !defined(__BORLANDC__) +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +#else +void +#endif +basic_binary_oarchive::init(){ + // write signature in an archive version independent manner + const std::string file_signature(ARCHIVE_SIGNATURE()); + * this->This() << file_signature; + // write library version + const version_type v(ARCHIVE_VERSION()); + * this->This() << v; +} + +} // namespace archive +} // namespace boost diff --git a/win32/include/boost/archive/impl/basic_binary_oprimitive.ipp b/win32/include/boost/archive/impl/basic_binary_oprimitive.ipp new file mode 100755 index 000000000..4c42c2553 --- /dev/null +++ b/win32/include/boost/archive/impl/basic_binary_oprimitive.ipp @@ -0,0 +1,166 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_oprimitive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include // NULL +#include + +#include + +#if defined(BOOST_NO_STDC_NAMESPACE) && ! defined(__LIBCOMO__) +namespace std{ + using ::strlen; +} // namespace std +#endif + + +#ifndef BOOST_NO_CWCHAR +#include +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ using ::wcslen; } +#endif +#endif + +#include + +#include +#include +#include +#include +#include + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// implementation of basic_binary_oprimitive + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_oprimitive::init() +{ + // record native sizes of fundamental types + // this is to permit detection of attempts to pass + // native binary archives accross incompatible machines. + // This is not foolproof but its better than nothing. + this->This()->save(static_cast(sizeof(int))); + this->This()->save(static_cast(sizeof(long))); + this->This()->save(static_cast(sizeof(float))); + this->This()->save(static_cast(sizeof(double))); + // for checking endianness + this->This()->save(int(1)); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_oprimitive::save(const char * s) +{ + std::size_t l = std::strlen(s); + this->This()->save(l); + save_binary(s, l); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_oprimitive::save(const std::string &s) +{ + std::size_t l = static_cast(s.size()); + this->This()->save(l); + save_binary(s.data(), l); +} + +#ifndef BOOST_NO_CWCHAR +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_oprimitive::save(const wchar_t * ws) +{ + std::size_t l = std::wcslen(ws); + this->This()->save(l); + save_binary(ws, l * sizeof(wchar_t) / sizeof(char)); +} + +#ifndef BOOST_NO_STD_WSTRING +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_oprimitive::save(const std::wstring &ws) +{ + std::size_t l = ws.size(); + this->This()->save(l); + save_binary(ws.data(), l * sizeof(wchar_t) / sizeof(char)); +} +#endif +#endif + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_binary_oprimitive::basic_binary_oprimitive( + std::basic_streambuf & sb, + bool no_codecvt +) : +#ifndef BOOST_NO_STD_LOCALE + m_sb(sb), + archive_locale(NULL), + locale_saver(m_sb) +{ + if(! no_codecvt){ + archive_locale.reset( + add_facet( + std::locale::classic(), + new codecvt_null + ) + ); + m_sb.pubimbue(* archive_locale); + } +} +#else + m_sb(sb) +{} +#endif + +// some libraries including stl and libcomo fail if the +// buffer isn't flushed before the code_cvt facet is changed. +// I think this is a bug. We explicity invoke sync to when +// we're done with the streambuf to work around this problem. +// Note that sync is a protected member of stream buff so we +// have to invoke it through a contrived derived class. +namespace detail { +// note: use "using" to get past msvc bug +using namespace std; +template +class output_streambuf_access : public std::basic_streambuf { + public: + virtual int sync(){ +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) + return this->basic_streambuf::sync(); +#else + return this->basic_streambuf::sync(); +#endif + } +}; +} // detail + +// scoped_ptr requires that g be a complete type at time of +// destruction so define destructor here rather than in the header +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_binary_oprimitive::~basic_binary_oprimitive(){ + // flush buffer + int result = static_cast &>( + m_sb + ).sync(); + if(0 != result){ + boost::throw_exception( + archive_exception(archive_exception::stream_error) + ); + } +} + +} // namespace archive +} // namespace boost diff --git a/win32/include/boost/archive/impl/basic_text_iarchive.ipp b/win32/include/boost/archive/impl/basic_text_iarchive.ipp new file mode 100755 index 000000000..458183c31 --- /dev/null +++ b/win32/include/boost/archive/impl/basic_text_iarchive.ipp @@ -0,0 +1,79 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_iarchive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. +#include +#include +#include +#include + +#include // for BOOST_DEDUCED_TYPENAME +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; +} +#endif + +#include + +#include + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation of text_text_archive +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_text_iarchive::load_override(class_name_type & t, int){ + std::string cn; + cn.reserve(BOOST_SERIALIZATION_MAX_KEY_SIZE); + load_override(cn, 0); + if(cn.size() > (BOOST_SERIALIZATION_MAX_KEY_SIZE - 1)) + boost::throw_exception( + archive_exception(archive_exception::invalid_class_name) + ); + std::memcpy(t, cn.data(), cn.size()); + // borland tweak + t.t[cn.size()] = '\0'; +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_text_iarchive::init(void){ + // read signature in an archive version independent manner + std::string file_signature; + * this->This() >> file_signature; + if(file_signature != ARCHIVE_SIGNATURE()) + boost::throw_exception( + archive_exception(archive_exception::invalid_signature) + ); + + // make sure the version of the reading archive library can + // support the format of the archive being read + version_type input_library_version; + * this->This() >> input_library_version; + + #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) + this->set_library_version(input_library_version); + #else + #if ! BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + detail:: + #endif + basic_iarchive::set_library_version(input_library_version.t); + #endif + + // extra little .t is to get around borland quirk + if(ARCHIVE_VERSION() < input_library_version.t) + boost::throw_exception( + archive_exception(archive_exception::unsupported_version) + ); +} + +} // namespace archive +} // namespace boost diff --git a/win32/include/boost/archive/impl/basic_text_iprimitive.ipp b/win32/include/boost/archive/impl/basic_text_iprimitive.ipp new file mode 100755 index 000000000..d4d147309 --- /dev/null +++ b/win32/include/boost/archive/impl/basic_text_iprimitive.ipp @@ -0,0 +1,131 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_iprimitive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include // size_t +#include // NULL + +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace archive { + +// translate base64 text into binary and copy into buffer +// until buffer is full. +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_text_iprimitive::load_binary( + void *address, + std::size_t count +){ + typedef BOOST_DEDUCED_TYPENAME IStream::char_type CharType; + + if(0 == count) + return; + + assert( + static_cast((std::numeric_limits::max)()) + > (count + sizeof(CharType) - 1)/sizeof(CharType) + ); + + if(is.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + // convert from base64 to binary + typedef BOOST_DEDUCED_TYPENAME + iterators::transform_width< + iterators::binary_from_base64< + iterators::remove_whitespace< + iterators::istream_iterator + > + ,CharType + > + ,8 + ,6 + ,CharType + > + binary; + + binary ti_begin = binary( + BOOST_MAKE_PFTO_WRAPPER( + iterators::istream_iterator(is) + ) + ); + + char * caddr = static_cast(address); + std::size_t padding = 2 - count % 3; + + // take care that we don't increment anymore than necessary + while(--count > 0){ + *caddr++ = static_cast(*ti_begin); + ++ti_begin; + } + *caddr++ = static_cast(*ti_begin); + + if(padding > 1) + ++ti_begin; + if(padding > 2) + ++ti_begin; +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_text_iprimitive::basic_text_iprimitive( + IStream &is_, + bool no_codecvt +) : +#ifndef BOOST_NO_STD_LOCALE + is(is_), + flags_saver(is_), + precision_saver(is_), + archive_locale(NULL), + locale_saver(is_) +{ + if(! no_codecvt){ + archive_locale.reset( + add_facet( + std::locale::classic(), + new codecvt_null + ) + ); + is.imbue(* archive_locale); + } + is >> std::noboolalpha; +} +#else + is(is_), + flags_saver(is_), + precision_saver(is_) +{} +#endif + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_text_iprimitive::~basic_text_iprimitive(){ + is.sync(); +} + +} // namespace archive +} // namespace boost diff --git a/win32/include/boost/archive/impl/basic_text_oarchive.ipp b/win32/include/boost/archive/impl/basic_text_oarchive.ipp new file mode 100755 index 000000000..dffadb637 --- /dev/null +++ b/win32/include/boost/archive/impl/basic_text_oarchive.ipp @@ -0,0 +1,62 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_oarchive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. +#include +#include +#include + +#include // for BOOST_DEDUCED_TYPENAME +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; +} +#endif + +#include + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation of basic_text_oarchive + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_text_oarchive::newtoken() +{ + switch(delimiter){ + default: + assert(false); + break; + case eol: + this->This()->put('\n'); + delimiter = space; + break; + case space: + this->This()->put(' '); + break; + case none: + delimiter = space; + break; + } +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_text_oarchive::init(){ + // write signature in an archive version independent manner + const std::string file_signature(ARCHIVE_SIGNATURE()); + * this->This() << file_signature; + // write library version + const version_type v(ARCHIVE_VERSION()); + * this->This() << v; +} + +} // namespace archive +} // namespace boost diff --git a/win32/include/boost/archive/impl/basic_text_oprimitive.ipp b/win32/include/boost/archive/impl/basic_text_oprimitive.ipp new file mode 100755 index 000000000..28b929338 --- /dev/null +++ b/win32/include/boost/archive/impl/basic_text_oprimitive.ipp @@ -0,0 +1,111 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_oprimitive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include // NULL +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace archive { + +// translate to base64 and copy in to buffer. +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_text_oprimitive::save_binary( + const void *address, + std::size_t count +){ + typedef BOOST_DEDUCED_TYPENAME OStream::char_type CharType; + + if(0 == count) + return; + + if(os.fail()) + boost::throw_exception(archive_exception(archive_exception::stream_error)); + + os.put('\n'); + + typedef + boost::archive::iterators::insert_linebreaks< + boost::archive::iterators::base64_from_binary< + boost::archive::iterators::transform_width< + const char *, + 6, + 8 + > + > + ,72 + ,const char // cwpro8 needs this + > + base64_text; + + boost::archive::iterators::ostream_iterator oi(os); + std::copy( + base64_text(BOOST_MAKE_PFTO_WRAPPER(static_cast(address))), + base64_text( + BOOST_MAKE_PFTO_WRAPPER(static_cast(address) + count) + ), + oi + ); + std::size_t padding = 2 - count % 3; + if(padding > 1) + *oi = '='; + if(padding > 2) + *oi = '='; + +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_text_oprimitive::basic_text_oprimitive( + OStream & os_, + bool no_codecvt +) : +#ifndef BOOST_NO_STD_LOCALE + os(os_), + flags_saver(os_), + precision_saver(os_), + archive_locale(NULL), + locale_saver(os_) +{ + if(! no_codecvt){ + archive_locale.reset( + add_facet( + std::locale::classic(), + new codecvt_null + ) + ); + os.imbue(* archive_locale); + } + os << std::noboolalpha; +} +#else + os(os_), + flags_saver(os_), + precision_saver(os_) +{} +#endif + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_text_oprimitive::~basic_text_oprimitive(){ + os << std::endl; +} + +} //namespace boost +} //namespace archive diff --git a/win32/include/boost/archive/impl/basic_xml_grammar.hpp b/win32/include/boost/archive/impl/basic_xml_grammar.hpp new file mode 100755 index 000000000..efd4ac311 --- /dev/null +++ b/win32/include/boost/archive/impl/basic_xml_grammar.hpp @@ -0,0 +1,191 @@ +#ifndef BOOST_ARCHIVE_BASIC_XML_GRAMMAR_HPP +#define BOOST_ARCHIVE_BASIC_XML_GRAMMAR_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_xml_grammar.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +// this module is derived from simplexml.cpp - an example shipped as part of +// the spirit parser. This example contains the following notice: +/*============================================================================= + simplexml.cpp + + Spirit V1.3 + URL: http://spirit.sourceforge.net/ + + Copyright (c) 2001, Daniel C. Nuffer + + This software is provided 'as-is', without any express or implied + warranty. In no event will the copyright holder be held liable for + any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product documentation + would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +=============================================================================*/ +#include + +#include +#include + +// supress noise +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) +# pragma warning (disable : 4786) // too long name, harmless warning +#endif + +//#define BOOST_SPIRIT_DEBUG +//#include +#include +#include + +// the following hack is to evade a bogus error generated by using the +// word "arg" when bind.hpp has been included +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) +#define arg xarg +#endif + +#include + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) +#undef arg +#endif + +#include +#include +#include + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// XML grammar parsing + +template +class basic_xml_grammar : public boost::spirit::grammar > +{ +public: + // The following is not necessary according to DR45, but at least + // one compiler (Compaq C++ 6.5 in strict_ansi mode) chokes otherwise. + struct return_values; + friend struct return_values; + +private: + typedef BOOST_DEDUCED_TYPENAME std::basic_istream IStream; + typedef BOOST_DEDUCED_TYPENAME std::basic_string StringType; + typedef BOOST_DEDUCED_TYPENAME boost::spirit::chset chset_t; + typedef BOOST_DEDUCED_TYPENAME boost::spirit::chlit chlit_t; + typedef BOOST_DEDUCED_TYPENAME boost::spirit::scanner< + BOOST_DEDUCED_TYPENAME std::basic_string::iterator + > scanner_t; + typedef BOOST_DEDUCED_TYPENAME boost::spirit::rule rule_t; + // Start grammar definition + rule_t + Reference, + Eq, + STag, + ETag, + LetterOrUnderscoreOrColon, + AttValue, + CharRef1, + CharRef2, + CharRef, + AmpRef, + LTRef, + GTRef, + AposRef, + QuoteRef, + CharData, + CharDataChars, + content, + AmpName, + LTName, + GTName, + ClassNameChar, + ClassName, + Name, + XMLDecl, + XMLDeclChars, + DocTypeDecl, + DocTypeDeclChars, + ClassIDAttribute, + ObjectIDAttribute, + ClassNameAttribute, + TrackingAttribute, + VersionAttribute, + UnusedAttribute, + Attribute, + SignatureAttribute, + SerializationWrapper, + NameHead, + NameTail, + AttributeList, + S; + + // XML Character classes + chset_t + BaseChar, + Ideographic, + Char, + Letter, + Digit, + CombiningChar, + Extender, + Sch, + NameChar; + + void init_chset(); + + bool my_parse( + IStream & is, + const rule_t &rule_, + const CharType delimiter = L'>' + ); +public: + struct return_values { + StringType object_name; + StringType contents; + class_id_type class_id; + object_id_type object_id; + version_type version; + tracking_type tracking_level; + StringType class_name; + return_values() : + version(0), + tracking_level(false) + {} + } rv; + bool parse_start_tag(IStream & is) ; + bool parse_end_tag(IStream & is); + bool parse_string(IStream & is, StringType & s); + void init(IStream & is); + void windup(IStream & is); + basic_xml_grammar(); +}; + + +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_BASIC_XML_GRAMMAR_HPP diff --git a/win32/include/boost/archive/impl/basic_xml_iarchive.ipp b/win32/include/boost/archive/impl/basic_xml_iarchive.ipp new file mode 100755 index 000000000..b58ac98ae --- /dev/null +++ b/win32/include/boost/archive/impl/basic_xml_iarchive.ipp @@ -0,0 +1,111 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_xml_iarchive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include // NULL +#include + +#include + +#include +#include + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation of xml_text_archive + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_iarchive::load_start(const char *name){ + // if there's no name + if(NULL == name) + return; + bool result = this->This()->gimpl->parse_start_tag(this->This()->get_is()); + if(true != result){ + boost::throw_exception( + archive_exception(archive_exception::stream_error) + ); + } + // don't check start tag at highest level + ++depth; + return; +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_iarchive::load_end(const char *name){ + // if there's no name + if(NULL == name) + return; + bool result = this->This()->gimpl->parse_end_tag(this->This()->get_is()); + if(true != result){ + boost::throw_exception( + archive_exception(archive_exception::stream_error) + ); + } + + // don't check start tag at highest level + if(0 == --depth) + return; + + if(0 == (this->get_flags() & no_xml_tag_checking)){ + // double check that the tag matches what is expected - useful for debug + if(0 != name[this->This()->gimpl->rv.object_name.size()] + || ! std::equal( + this->This()->gimpl->rv.object_name.begin(), + this->This()->gimpl->rv.object_name.end(), + name + ) + ){ + boost::throw_exception( + archive_exception(archive_exception::stream_error) + ); + } + } +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_iarchive::load_override(object_id_type & t, int){ + t = this->This()->gimpl->rv.object_id; +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_iarchive::load_override(version_type & t, int){ + t = this->This()->gimpl->rv.version; +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_iarchive::load_override(class_id_type & t, int){ + t = this->This()->gimpl->rv.class_id; +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_iarchive::load_override(tracking_type & t, int){ + t = this->This()->gimpl->rv.tracking_level; +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_xml_iarchive::basic_xml_iarchive(unsigned int flags) : + detail::common_iarchive(flags), + depth(0) +{} +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_xml_iarchive::~basic_xml_iarchive(){} + +} // namespace archive +} // namespace boost diff --git a/win32/include/boost/archive/impl/basic_xml_oarchive.ipp b/win32/include/boost/archive/impl/basic_xml_oarchive.ipp new file mode 100755 index 000000000..13d7bfd24 --- /dev/null +++ b/win32/include/boost/archive/impl/basic_xml_oarchive.ipp @@ -0,0 +1,275 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_xml_oarchive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include // NULL +#include +#if defined(BOOST_NO_STDC_NAMESPACE) && ! defined(__LIBCOMO__) +namespace std{ + using ::strlen; +} // namespace std +#endif + +#include +#include +#include +#include + +namespace boost { +namespace archive { + +namespace detail { +template +struct XML_name { + void operator()(CharType t) const{ + const unsigned char lookup_table[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0, // -. + 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, // 0-9 + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // A- + 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1, // -Z _ + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // a- + 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, // -z + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + }; + if((unsigned)t > 127) + return; + if(0 == lookup_table[(unsigned)t]) + boost::throw_exception( + xml_archive_exception( + xml_archive_exception::xml_archive_tag_name_error + ) + ); + } +}; + +} // namespace detail + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implemenations of functions common to both types of xml output + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::write_attribute( + const char *attribute_name, + int t, + const char *conjunction +){ + this->This()->put(' '); + this->This()->put(attribute_name); + this->This()->put(conjunction); + this->This()->save(t); + this->This()->put('"'); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::write_attribute( + const char *attribute_name, + const char *key +){ + this->This()->put(' '); + this->This()->put(attribute_name); + this->This()->put("=\""); + this->This()->save(key); + this->This()->put('"'); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::indent(){ + int i; + for(i = depth; i-- > 0;) + this->This()->put('\t'); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::save_start(const char *name) +{ + if(NULL == name) + return; + + // be sure name has no invalid characters + std::for_each(name, name + std::strlen(name), detail::XML_name()); + + end_preamble(); + if(depth > 0){ + this->This()->put('\n'); + indent(); + } + ++depth; + this->This()->put('<'); + this->This()->save(name); + pending_preamble = true; + indent_next = false; +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::save_end(const char *name) +{ + if(NULL == name) + return; + + // be sure name has no invalid characters + std::for_each(name, name + std::strlen(name), detail::XML_name()); + + end_preamble(); + --depth; + if(indent_next){ + this->This()->put('\n'); + indent(); + } + indent_next = true; + this->This()->put("This()->save(name); + this->This()->put('>'); + if(0 == depth) + this->This()->put('\n'); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::end_preamble(){ + if(pending_preamble){ + this->This()->put('>'); + pending_preamble = false; + } +} +#if 0 +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::save_override(const object_id_type & t, int) +{ + int i = t.t; // extra .t is for borland + write_attribute(OBJECT_ID(), i, "=\"_"); +} +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::save_override( + const object_reference_type & t, + int +){ + int i = t.t; // extra .t is for borland + write_attribute(OBJECT_REFERENCE(), i, "=\"_"); +} +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::save_override(const version_type & t, int) +{ + int i = t.t; // extra .t is for borland + write_attribute(VERSION(), i); +} +#endif + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::save_override(const object_id_type & t, int) +{ + // borland doesn't do conversion of STRONG_TYPEDEFs very well + const unsigned int i = t; + write_attribute(OBJECT_ID(), i, "=\"_"); +} +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::save_override( + const object_reference_type & t, + int +){ + const unsigned int i = t; + write_attribute(OBJECT_REFERENCE(), i, "=\"_"); +} +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::save_override(const version_type & t, int) +{ + const unsigned int i = t; + write_attribute(VERSION(), i); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::save_override(const class_id_type & t, int) +{ + write_attribute(CLASS_ID(), t); +} +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::save_override( + const class_id_reference_type & t, + int +){ + write_attribute(CLASS_ID_REFERENCE(), t); +} +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::save_override( + const class_id_optional_type & t, + int +){ + write_attribute(CLASS_ID(), t); +} +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::save_override(const class_name_type & t, int) +{ + const char * key = t; + if(NULL == key) + return; + write_attribute(CLASS_NAME(), key); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::save_override(const tracking_type & t, int) +{ + write_attribute(TRACKING(), t.t); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive::init(){ + // xml header + this->This()->put("\n"); + this->This()->put("\n"); + // xml document wrapper - outer root + this->This()->put("This()->put(">\n"); +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_xml_oarchive::basic_xml_oarchive(unsigned int flags) : + detail::common_oarchive(flags), + depth(0), + indent_next(false), + pending_preamble(false) +{ +} + +template +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_xml_oarchive::~basic_xml_oarchive(){ + if(0 == (this->get_flags() & no_header)){ + BOOST_TRY{ + this->This()->put("\n"); + } + BOOST_CATCH(...){} + BOOST_CATCH_END + } +} + +} // namespace archive +} // namespace boost diff --git a/win32/include/boost/archive/impl/text_iarchive_impl.ipp b/win32/include/boost/archive/impl/text_iarchive_impl.ipp new file mode 100755 index 000000000..dde385cd1 --- /dev/null +++ b/win32/include/boost/archive/impl/text_iarchive_impl.ipp @@ -0,0 +1,128 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_iarchive_impl.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +////////////////////////////////////////////////////////////////////// +// implementation of basic_text_iprimitive overrides for the combination +// of template parameters used to implement a text_iprimitive + +#include // size_t, NULL +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include // RogueWave + +#include + +namespace boost { +namespace archive { + +template +BOOST_ARCHIVE_DECL(void) +text_iarchive_impl::load(char *s) +{ + std::size_t size; + * this->This() >> size; + // skip separating space + is.get(); + // Works on all tested platforms + is.read(s, size); + s[size] = '\0'; +} + +template +BOOST_ARCHIVE_DECL(void) +text_iarchive_impl::load(std::string &s) +{ + std::size_t size; + * this->This() >> size; + // skip separating space + is.get(); + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != s.data()) + #endif + s.resize(size); + if(0 < size) + is.read(&(*s.begin()), size); +} + +#ifndef BOOST_NO_CWCHAR +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template +BOOST_ARCHIVE_DECL(void) +text_iarchive_impl::load(wchar_t *ws) +{ + std::size_t size; + * this->This() >> size; + // skip separating space + is.get(); + is.read((char *)ws, size * sizeof(wchar_t)/sizeof(char)); + ws[size] = L'\0'; +} +#endif // BOOST_NO_INTRINSIC_WCHAR_T + +#ifndef BOOST_NO_STD_WSTRING +template +BOOST_ARCHIVE_DECL(void) +text_iarchive_impl::load(std::wstring &ws) +{ + std::size_t size; + * this->This() >> size; + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != ws.data()) + #endif + ws.resize(size); + // skip separating space + is.get(); + is.read((char *)ws.data(), size * sizeof(wchar_t)/sizeof(char)); +} + +#endif // BOOST_NO_STD_WSTRING +#endif // BOOST_NO_CWCHAR + +template +BOOST_ARCHIVE_DECL(void) +text_iarchive_impl::load_override(class_name_type & t, int){ + basic_text_iarchive::load_override(t, 0); +} + +template +BOOST_ARCHIVE_DECL(void) +text_iarchive_impl::init(){ + basic_text_iarchive::init(); +} + +template +BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) +text_iarchive_impl::text_iarchive_impl( + std::istream & is, + unsigned int flags +) : + basic_text_iprimitive( + is, + 0 != (flags & no_codecvt) + ), + basic_text_iarchive(flags) +{ + if(0 == (flags & no_header)) + #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) + this->init(); + #else + this->basic_text_iarchive::init(); + #endif +} + +} // namespace archive +} // namespace boost diff --git a/win32/include/boost/archive/impl/text_oarchive_impl.ipp b/win32/include/boost/archive/impl/text_oarchive_impl.ipp new file mode 100755 index 000000000..d66c737e2 --- /dev/null +++ b/win32/include/boost/archive/impl/text_oarchive_impl.ipp @@ -0,0 +1,124 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_oarchive_impl.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include +#include // size_t + +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#ifndef BOOST_NO_CWCHAR +#include +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ using ::wcslen; } +#endif +#endif + +#include +#include + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// implementation of basic_text_oprimitive overrides for the combination +// of template parameters used to create a text_oprimitive + +template +BOOST_ARCHIVE_DECL(void) +text_oarchive_impl::save(const char * s) +{ + const std::size_t len = std::ostream::traits_type::length(s); + *this->This() << len; + this->This()->newtoken(); + os << s; +} + +template +BOOST_ARCHIVE_DECL(void) +text_oarchive_impl::save(const std::string &s) +{ + const std::size_t size = s.size(); + *this->This() << size; + this->This()->newtoken(); + os << s; +} + +#ifndef BOOST_NO_CWCHAR +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template +BOOST_ARCHIVE_DECL(void) +text_oarchive_impl::save(const wchar_t * ws) +{ + const std::size_t l = std::wcslen(ws); + * this->This() << l; + this->This()->newtoken(); + os.write((const char *)ws, l * sizeof(wchar_t)/sizeof(char)); +} +#endif + +#ifndef BOOST_NO_STD_WSTRING +template +BOOST_ARCHIVE_DECL(void) +text_oarchive_impl::save(const std::wstring &ws) +{ + const std::size_t l = ws.size(); + * this->This() << l; + this->This()->newtoken(); + os.write((const char *)(ws.data()), l * sizeof(wchar_t)/sizeof(char)); +} +#endif +#endif // BOOST_NO_CWCHAR + +template +BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) +text_oarchive_impl::text_oarchive_impl( + std::ostream & os, + unsigned int flags +) : + basic_text_oprimitive( + os, + 0 != (flags & no_codecvt) + ), + basic_text_oarchive(flags) +{ + if(0 == (flags & no_header)) + #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) + this->init(); + #else + this->basic_text_oarchive::init(); + #endif +} + +template +BOOST_ARCHIVE_DECL(void) +text_oarchive_impl::save_binary(const void *address, std::size_t count){ + put('\n'); + this->end_preamble(); + #if ! defined(__MWERKS__) + this->basic_text_oprimitive::save_binary( + #else + this->basic_text_oprimitive::save_binary( + #endif + address, + count + ); + this->delimiter = this->eol; +} + +} // namespace archive +} // namespace boost + diff --git a/win32/include/boost/archive/impl/text_wiarchive_impl.ipp b/win32/include/boost/archive/impl/text_wiarchive_impl.ipp new file mode 100755 index 000000000..2eade7577 --- /dev/null +++ b/win32/include/boost/archive/impl/text_wiarchive_impl.ipp @@ -0,0 +1,118 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_text_wiarchive_impl.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include // size_t, NULL + +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include // fixup for RogueWave + +#ifndef BOOST_NO_STD_WSTREAMBUF +#include + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// implementation of wiprimtives functions +// +template +BOOST_WARCHIVE_DECL(void) +text_wiarchive_impl::load(char *s) +{ + std::size_t size; + * this->This() >> size; + // skip separating space + is.get(); + while(size-- > 0){ + *s++ = is.narrow(is.get(), '\0'); + } + *s = '\0'; +} + +template +BOOST_WARCHIVE_DECL(void) +text_wiarchive_impl::load(std::string &s) +{ + std::size_t size; + * this->This() >> size; + // skip separating space + is.get(); + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != s.data()) + #endif + s.resize(0); + s.reserve(size); + while(size-- > 0){ + int x = is.narrow(is.get(), '\0'); + s += x; + } +} + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template +BOOST_WARCHIVE_DECL(void) +text_wiarchive_impl::load(wchar_t *s) +{ + std::size_t size; + * this->This() >> size; + // skip separating space + is.get(); + // Works on all tested platforms + is.read(s, size); + s[size] = L'\0'; +} +#endif + +#ifndef BOOST_NO_STD_WSTRING +template +BOOST_WARCHIVE_DECL(void) +text_wiarchive_impl::load(std::wstring &ws) +{ + std::size_t size; + * this->This() >> size; + // skip separating space + is.get(); + // borland complains about resize + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != ws.data()) + #endif + ws.resize(size); + // note breaking a rule here - is this a problem on some platform + is.read(const_cast(ws.data()), size); +} +#endif + +template +BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) +text_wiarchive_impl::text_wiarchive_impl( + std::wistream & is, + unsigned int flags +) : + basic_text_iprimitive( + is, + 0 != (flags & no_codecvt) + ), + basic_text_iarchive(flags) +{ + if(0 == (flags & no_header)) + basic_text_iarchive::init(); +} + +} // archive +} // boost + +#endif // BOOST_NO_STD_WSTREAMBUF diff --git a/win32/include/boost/archive/impl/text_woarchive_impl.ipp b/win32/include/boost/archive/impl/text_woarchive_impl.ipp new file mode 100755 index 000000000..0d0a9ffa6 --- /dev/null +++ b/win32/include/boost/archive/impl/text_woarchive_impl.ipp @@ -0,0 +1,85 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_woarchive_impl.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#ifndef BOOST_NO_STD_WSTREAMBUF + +#include +#include // size_t +#if defined(BOOST_NO_STDC_NAMESPACE) && ! defined(__LIBCOMO__) +namespace std{ + using ::strlen; + using ::size_t; +} // namespace std +#endif + +#include + +#include + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// implementation of woarchive functions +// +template +BOOST_WARCHIVE_DECL(void) +text_woarchive_impl::save(const char *s) +{ + // note: superfluous local variable fixes borland warning + const std::size_t size = std::strlen(s); + * this->This() << size; + this->This()->newtoken(); + while(*s != '\0') + os.put(os.widen(*s++)); +} + +template +BOOST_WARCHIVE_DECL(void) +text_woarchive_impl::save(const std::string &s) +{ + const std::size_t size = s.size(); + * this->This() << size; + this->This()->newtoken(); + const char * cptr = s.data(); + for(std::size_t i = size; i-- > 0;) + os.put(os.widen(*cptr++)); +} + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template +BOOST_WARCHIVE_DECL(void) +text_woarchive_impl::save(const wchar_t *ws) +{ + const std::size_t size = std::wostream::traits_type::length(ws); + * this->This() << size; + this->This()->newtoken(); + os.write(ws, size); +} +#endif + +#ifndef BOOST_NO_STD_WSTRING +template +BOOST_WARCHIVE_DECL(void) +text_woarchive_impl::save(const std::wstring &ws) +{ + const std::size_t size = ws.length(); + * this->This() << size; + this->This()->newtoken(); + os.write(ws.data(), size); +} +#endif + +} // namespace archive +} // namespace boost + +#endif + diff --git a/win32/include/boost/archive/impl/xml_iarchive_impl.ipp b/win32/include/boost/archive/impl/xml_iarchive_impl.ipp new file mode 100755 index 000000000..b671b370e --- /dev/null +++ b/win32/include/boost/archive/impl/xml_iarchive_impl.ipp @@ -0,0 +1,202 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_iarchive_impl.cpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include // memcpy +#include // NULL +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; +} // namespace std +#endif + +#ifndef BOOST_NO_CWCHAR +#include // mbtowc +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::mbtowc; + } // namespace std +#endif +#endif // BOOST_NO_CWCHAR + +#include // RogueWave and Dinkumware +#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) +#include +#endif + +#include + +#include +#include +#include +#include + +#include "basic_xml_grammar.hpp" + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implemenations of functions specific to char archives + +// wide char stuff used by char archives + +#ifndef BOOST_NO_CWCHAR +#ifndef BOOST_NO_STD_WSTRING +template +BOOST_ARCHIVE_DECL(void) +xml_iarchive_impl::load(std::wstring &ws){ + std::string s; + bool result = gimpl->parse_string(is, s); + if(! result) + boost::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); + + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != ws.data()) + #endif + ws.resize(0); + const char * start = s.data(); + const char * end = start + s.size(); + while(start < end){ + wchar_t wc; + int resultx = std::mbtowc(&wc, start, end - start); + if(0 < resultx){ + start += resultx; + ws += wc; + continue; + } + boost::throw_exception( + iterators::dataflow_exception( + iterators::dataflow_exception::invalid_conversion + ) + ); + } +} +#endif // BOOST_NO_STD_WSTRING + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template +BOOST_ARCHIVE_DECL(void) +xml_iarchive_impl::load(wchar_t * ws){ + std::string s; + bool result = gimpl->parse_string(is, s); + if(! result) + boost::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); + + const char * start = s.data(); + const char * end = start + s.size(); + while(start < end){ + wchar_t wc; + int result = std::mbtowc(&wc, start, end - start); + if(0 < result){ + start += result; + *ws++ = wc; + continue; + } + boost::throw_exception( + iterators::dataflow_exception( + iterators::dataflow_exception::invalid_conversion + ) + ); + } + *ws = L'\0'; +} +#endif + +#endif // BOOST_NO_CWCHAR + +template +BOOST_ARCHIVE_DECL(void) +xml_iarchive_impl::load(std::string &s){ + bool result = gimpl->parse_string(is, s); + if(! result) + boost::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); +} + +template +BOOST_ARCHIVE_DECL(void) +xml_iarchive_impl::load(char * s){ + std::string tstring; + bool result = gimpl->parse_string(is, tstring); + if(! result) + boost::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); + std::memcpy(s, tstring.data(), tstring.size()); + s[tstring.size()] = 0; +} + +template +BOOST_ARCHIVE_DECL(void) +xml_iarchive_impl::load_override(class_name_type & t, int){ + const std::string & s = gimpl->rv.class_name; + if(s.size() > BOOST_SERIALIZATION_MAX_KEY_SIZE - 1) + boost::throw_exception( + archive_exception(archive_exception::invalid_class_name) + ); + char * tptr = t; + std::memcpy(tptr, s.data(), s.size()); + tptr[s.size()] = '\0'; +} + +template +BOOST_ARCHIVE_DECL(void) +xml_iarchive_impl::init(){ + gimpl->init(is); + this->set_library_version(gimpl->rv.version); +} + +template +BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) +xml_iarchive_impl::xml_iarchive_impl( + std::istream &is_, + unsigned int flags +) : + basic_text_iprimitive( + is_, + 0 != (flags & no_codecvt) + ), + basic_xml_iarchive(flags), + gimpl(new xml_grammar()) +{ + if(0 == (flags & no_header)){ + BOOST_TRY{ + init(); + } + BOOST_CATCH(...){ + delete gimpl; + #ifndef BOOST_NO_EXCEPTIONS + throw; // re-throw + #endif + } + BOOST_CATCH_END + } +} + +template +BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) +xml_iarchive_impl::~xml_iarchive_impl(){ + if(0 == (this->get_flags() & no_header)){ + BOOST_TRY{ + gimpl->windup(is); + } + BOOST_CATCH(...){} + BOOST_CATCH_END + } + delete gimpl; +} +} // namespace archive +} // namespace boost diff --git a/win32/include/boost/archive/impl/xml_oarchive_impl.ipp b/win32/include/boost/archive/impl/xml_oarchive_impl.ipp new file mode 100755 index 000000000..20b218934 --- /dev/null +++ b/win32/include/boost/archive/impl/xml_oarchive_impl.ipp @@ -0,0 +1,117 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_oarchive_impl.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// 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) + +#include +#include +#include +#include + +#include // strlen +#include // msvc 6.0 needs this to suppress warnings +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::strlen; +} // namespace std +#endif + +#include +#include + +#ifndef BOOST_NO_CWCHAR +#include +#include +#endif + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implemenations of functions specific to char archives + +// wide char stuff used by char archives +#ifndef BOOST_NO_CWCHAR +// copy chars to output escaping to xml and translating wide chars to mb chars +template +void save_iterator(std::ostream &os, InputIterator begin, InputIterator end){ + typedef boost::archive::iterators::mb_from_wchar< + boost::archive::iterators::xml_escape + > translator; + std::copy( + translator(BOOST_MAKE_PFTO_WRAPPER(begin)), + translator(BOOST_MAKE_PFTO_WRAPPER(end)), + boost::archive::iterators::ostream_iterator(os) + ); +} + +#ifndef BOOST_NO_STD_WSTRING +template +BOOST_ARCHIVE_DECL(void) +xml_oarchive_impl::save(const std::wstring & ws){ +// at least one library doesn't typedef value_type for strings +// so rather than using string directly make a pointer iterator out of it +// save_iterator(os, ws.data(), ws.data() + std::wcslen(ws.data())); + save_iterator(os, ws.data(), ws.data() + ws.size()); +} +#endif + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template +BOOST_ARCHIVE_DECL(void) +xml_oarchive_impl::save(const wchar_t * ws){ + save_iterator(os, ws, ws + std::wcslen(ws)); +} +#endif + +#endif // BOOST_NO_CWCHAR + +template +BOOST_ARCHIVE_DECL(void) +xml_oarchive_impl::save(const std::string & s){ +// at least one library doesn't typedef value_type for strings +// so rather than using string directly make a pointer iterator out of it + typedef boost::archive::iterators::xml_escape< + const char * + > xml_escape_translator; + std::copy( + xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s.data())), + xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s.data()+ s.size())), + boost::archive::iterators::ostream_iterator(os) + ); +} + +template +BOOST_ARCHIVE_DECL(void) +xml_oarchive_impl::save(const char * s){ + typedef boost::archive::iterators::xml_escape< + const char * + > xml_escape_translator; + std::copy( + xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s)), + xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s + std::strlen(s))), + boost::archive::iterators::ostream_iterator(os) + ); +} + +template +BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) +xml_oarchive_impl::xml_oarchive_impl( + std::ostream & os_, + unsigned int flags +) : + basic_text_oprimitive( + os_, + 0 != (flags & no_codecvt) + ), + basic_xml_oarchive(flags) +{ + if(0 == (flags & no_header)) + this->init(); +} + +} // namespace archive +} // namespace boost diff --git a/win32/include/boost/archive/impl/xml_wiarchive_impl.ipp b/win32/include/boost/archive/impl/xml_wiarchive_impl.ipp new file mode 100755 index 000000000..eda7d3290 --- /dev/null +++ b/win32/include/boost/archive/impl/xml_wiarchive_impl.ipp @@ -0,0 +1,204 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_wiprimitive.cpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include // for BOOST_DEDUCED_TYPENAME + +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; +} //std +#endif + +#include // msvc 6.0 needs this to suppress warnings +#ifndef BOOST_NO_STD_WSTREAMBUF + +#include +#include + +#include // Dinkumware and RogueWave +#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include "basic_xml_grammar.hpp" + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implemenations of functions specific to wide char archives + +namespace { // anonymous + +void copy_to_ptr(char * s, const std::wstring & ws){ + std::copy( + iterators::mb_from_wchar( + BOOST_MAKE_PFTO_WRAPPER(ws.begin()) + ), + iterators::mb_from_wchar( + BOOST_MAKE_PFTO_WRAPPER(ws.end()) + ), + s + ); + s[ws.size()] = 0; +} + +} // anonymous + +template +BOOST_WARCHIVE_DECL(void) +xml_wiarchive_impl::load(std::string & s){ + std::wstring ws; + bool result = gimpl->parse_string(is, ws); + if(! result) + boost::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != s.data()) + #endif + s.resize(0); + s.reserve(ws.size()); + std::copy( + iterators::mb_from_wchar( + BOOST_MAKE_PFTO_WRAPPER(ws.begin()) + ), + iterators::mb_from_wchar( + BOOST_MAKE_PFTO_WRAPPER(ws.end()) + ), + std::back_inserter(s) + ); +} + +#ifndef BOOST_NO_STD_WSTRING +template +BOOST_WARCHIVE_DECL(void) +xml_wiarchive_impl::load(std::wstring & ws){ + bool result = gimpl->parse_string(is, ws); + if(! result) + boost::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); +} +#endif + +template +BOOST_WARCHIVE_DECL(void) +xml_wiarchive_impl::load(char * s){ + std::wstring ws; + bool result = gimpl->parse_string(is, ws); + if(! result) + boost::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); + copy_to_ptr(s, ws); +} + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template +BOOST_WARCHIVE_DECL(void) +xml_wiarchive_impl::load(wchar_t * ws){ + std::wstring twstring; + bool result = gimpl->parse_string(is, twstring); + if(! result) + boost::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); + std::memcpy(ws, twstring.c_str(), twstring.size()); + ws[twstring.size()] = L'\0'; +} +#endif + +template +BOOST_WARCHIVE_DECL(void) +xml_wiarchive_impl::load_override(class_name_type & t, int){ + const std::wstring & ws = gimpl->rv.class_name; + if(ws.size() > BOOST_SERIALIZATION_MAX_KEY_SIZE - 1) + boost::throw_exception( + archive_exception(archive_exception::invalid_class_name) + ); + copy_to_ptr(t, ws); +} + +template +BOOST_WARCHIVE_DECL(void) +xml_wiarchive_impl::init(){ + gimpl->init(is); + this->set_library_version(gimpl->rv.version); +} + +template +BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) +xml_wiarchive_impl::xml_wiarchive_impl( + std::wistream &is_, + unsigned int flags +) : + basic_text_iprimitive( + is_, + true // don't change the codecvt - use the one below + ), + basic_xml_iarchive(flags), + gimpl(new xml_wgrammar()) +{ + if(0 == (flags & no_codecvt)){ + archive_locale.reset( + add_facet( + std::locale::classic(), + new boost::archive::detail::utf8_codecvt_facet + ) + ); + is.imbue(* archive_locale); + } + if(0 == (flags & no_header)){ + BOOST_TRY{ + this->init(); + } + BOOST_CATCH(...){ + delete gimpl; + #ifndef BOOST_NO_EXCEPTIONS + throw; // re-throw + #endif + } + BOOST_CATCH_END + } +} + +template +BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) +xml_wiarchive_impl::~xml_wiarchive_impl(){ + if(0 == (this->get_flags() & no_header)){ + BOOST_TRY{ + gimpl->windup(is); + } + BOOST_CATCH(...){} + BOOST_CATCH_END + } + delete gimpl; +} + +} // namespace archive +} // namespace boost + +#endif // BOOST_NO_STD_WSTREAMBUF diff --git a/win32/include/boost/archive/impl/xml_woarchive_impl.ipp b/win32/include/boost/archive/impl/xml_woarchive_impl.ipp new file mode 100755 index 000000000..f1869b639 --- /dev/null +++ b/win32/include/boost/archive/impl/xml_woarchive_impl.ipp @@ -0,0 +1,160 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_woarchive_impl.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// 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) + +#include +#ifndef BOOST_NO_STD_WSTREAMBUF + +#include +#include +#include +#include + +#include // msvc 6.0 needs this to suppress warnings + // for BOOST_DEDUCED_TYPENAME +#include // strlen +#include // mbtowc +#include // wcslen + +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::strlen; + #if ! defined(BOOST_NO_INTRINSIC_WCHAR_T) + using ::mbtowc; + using ::wcslen; + #endif +} // namespace std +#endif + +#include +#include + +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implemenations of functions specific to wide char archives + +// copy chars to output escaping to xml and widening characters as we go +template +void save_iterator(std::wostream &os, InputIterator begin, InputIterator end){ + typedef iterators::wchar_from_mb< + iterators::xml_escape + > xmbtows; + std::copy( + xmbtows(BOOST_MAKE_PFTO_WRAPPER(begin)), + xmbtows(BOOST_MAKE_PFTO_WRAPPER(end)), + boost::archive::iterators::ostream_iterator(os) + ); +} + +template +BOOST_WARCHIVE_DECL(void) +xml_woarchive_impl::save(const std::string & s){ + // note: we don't use s.begin() and s.end() because dinkumware + // doesn't have string::value_type defined. So use a wrapper + // around these values to implement the definitions. + const char * begin = s.data(); + const char * end = begin + s.size(); + save_iterator(os, begin, end); +} + +#ifndef BOOST_NO_STD_WSTRING +template +BOOST_WARCHIVE_DECL(void) +xml_woarchive_impl::save(const std::wstring & ws){ +#if 0 + typedef iterators::xml_escape xmbtows; + std::copy( + xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.begin())), + xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.end())), + boost::archive::iterators::ostream_iterator(os) + ); +#endif + typedef iterators::xml_escape xmbtows; + std::copy( + xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.data())), + xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.data() + ws.size())), + boost::archive::iterators::ostream_iterator(os) + ); +} +#endif //BOOST_NO_STD_WSTRING + +template +BOOST_WARCHIVE_DECL(void) +xml_woarchive_impl::save(const char * s){ + save_iterator(os, s, s + std::strlen(s)); +} + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template +BOOST_WARCHIVE_DECL(void) +xml_woarchive_impl::save(const wchar_t * ws){ + os << ws; + typedef iterators::xml_escape xmbtows; + std::copy( + xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws)), + xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws + std::wcslen(ws))), + boost::archive::iterators::ostream_iterator(os) + ); +} +#endif + +template +BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) +xml_woarchive_impl::xml_woarchive_impl( + std::wostream & os_, + unsigned int flags +) : + basic_text_oprimitive( + os_, + true // don't change the codecvt - use the one below + ), + basic_xml_oarchive(flags) +{ + // Standard behavior is that imbue can be called + // a) before output is invoked or + // b) after flush has been called. This prevents one-to-many + // transforms (such as one to many transforms from getting + // mixed up. Unfortunately, STLPort doesn't respect b) above + // so the restoration of the original archive locale done by + // the locale_saver doesn't get processed, + // before the current one is destroyed. + // so the codecvt doesn't get replaced with the orginal + // so closing the stream invokes codecvt::do_unshift + // so it crashes because the corresponding locale that contained + // the codecvt isn't around any more. + // we can hack around this by using a static codecvt that never + // gets destroyed. + if(0 == (flags & no_codecvt)){ + boost::archive::detail::utf8_codecvt_facet *pfacet; + #if defined(__SGI_STL_PORT) + static boost::archive::detail::utf8_codecvt_facet + facet(static_cast(1)); + pfacet = & facet; + #else + pfacet = new boost::archive::detail::utf8_codecvt_facet; + #endif + archive_locale.reset(add_facet(std::locale::classic(), pfacet)); + os.imbue(* archive_locale); + } + if(0 == (flags & no_header)) + this->init(); +} + +} // namespace archive +} // namespace boost + +#endif //BOOST_NO_STD_WSTREAMBUF diff --git a/win32/include/boost/archive/iterators/base64_exception.hpp b/win32/include/boost/archive/iterators/base64_exception.hpp new file mode 100755 index 000000000..48a67c459 --- /dev/null +++ b/win32/include/boost/archive/iterators/base64_exception.hpp @@ -0,0 +1,68 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_BASE64_EXCEPTION_HPP +#define BOOST_ARCHIVE_ITERATORS_BASE64_EXCEPTION_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// base64_exception.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#ifndef BOOST_NO_EXCEPTIONS +#include + +#include + +namespace boost { +namespace archive { +namespace iterators { + +////////////////////////////////////////////////////////////////////// +// exceptions thrown by base64s +// +class base64_exception : public std::exception +{ +public: + typedef enum { + invalid_code, // attempt to encode a value > 6 bits + invalid_character, // decode a value not in base64 char set + other_exception + } exception_code; + exception_code code; + + base64_exception(exception_code c = other_exception) : code(c) + {} + + virtual const char *what( ) const throw( ) + { + const char *msg = "unknown exception code"; + switch(code){ + case invalid_code: + msg = "attempt to encode a value > 6 bits"; + break; + case invalid_character: + msg = "attempt to decode a value not in base64 char set"; + break; + default: + assert(false); + break; + } + return msg; + } +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif //BOOST_NO_EXCEPTIONS +#endif //BOOST_ARCHIVE_ITERATORS_ARCHIVE_EXCEPTION_HPP diff --git a/win32/include/boost/archive/iterators/base64_from_binary.hpp b/win32/include/boost/archive/iterators/base64_from_binary.hpp new file mode 100755 index 000000000..347c5204b --- /dev/null +++ b/win32/include/boost/archive/iterators/base64_from_binary.hpp @@ -0,0 +1,105 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_BASE64_FROM_BINARY_HPP +#define BOOST_ARCHIVE_ITERATORS_BASE64_FROM_BINARY_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// base64_from_binary.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include + +#include // for BOOST_DEDUCED_TYPENAME +#include + +#include +#include + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// convert binary integers to base64 characters + +namespace detail { + +template +struct from_6_bit { + typedef CharType result_type; + CharType operator()(CharType t) const{ + const char * lookup_table = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "+/"; + assert(t < 64); + return lookup_table[t]; + } +}; + +} // namespace detail + +// note: what we would like to do is +// template +// typedef transform_iterator< +// from_6_bit, +// transform_width +// > base64_from_binary; +// but C++ won't accept this. Rather than using a "type generator" and +// using a different syntax, make a derivation which should be equivalent. +// +// Another issue addressed here is that the transform_iterator doesn't have +// a templated constructor. This makes it incompatible with the dataflow +// ideal. This is also addressed here. + +//template +template< + class Base, + class CharType = BOOST_DEDUCED_TYPENAME boost::iterator_value::type +> +class base64_from_binary : + public transform_iterator< + detail::from_6_bit, + Base + > +{ + friend class boost::iterator_core_access; + typedef transform_iterator< + BOOST_DEDUCED_TYPENAME detail::from_6_bit, + Base + > super_t; + +public: + // make composible buy using templated constructor + template + base64_from_binary(BOOST_PFTO_WRAPPER(T) start) : + super_t( + Base(BOOST_MAKE_PFTO_WRAPPER(static_cast(start))), + detail::from_6_bit() + ) + {} + // intel 7.1 doesn't like default copy constructor + base64_from_binary(const base64_from_binary & rhs) : + super_t( + Base(rhs.base_reference()), + detail::from_6_bit() + ) + {} +// base64_from_binary(){}; +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_BASE64_FROM_BINARY_HPP diff --git a/win32/include/boost/archive/iterators/binary_from_base64.hpp b/win32/include/boost/archive/iterators/binary_from_base64.hpp new file mode 100755 index 000000000..db49439fa --- /dev/null +++ b/win32/include/boost/archive/iterators/binary_from_base64.hpp @@ -0,0 +1,120 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_BINARY_FROM_BASE64_HPP +#define BOOST_ARCHIVE_ITERATORS_BINARY_FROM_BASE64_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_from_base64.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include + +#include // for BOOST_DEDUCED_TYPENAME +#include +#include +#include + +#include +#include + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// convert base64 characters to binary data + +namespace detail { + +template +struct to_6_bit { + typedef CharType result_type; + CharType operator()(CharType t) const{ + const char lookup_table[] = { + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, + 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, + 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, + -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, + 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1 + }; + // metrowerks trips this assertion - how come? + #if ! defined(__MWERKS__) + BOOST_STATIC_ASSERT(128 == sizeof(lookup_table)); + #endif + signed char value = -1; + if((unsigned)t <= 127) + value = lookup_table[(unsigned)t]; + if(-1 == value) + boost::throw_exception( + dataflow_exception(dataflow_exception::invalid_base64_character) + ); + return value; + } +}; + +} // namespace detail + +// note: what we would like to do is +// template +// typedef transform_iterator< +// from_6_bit, +// transform_width +// > base64_from_binary; +// but C++ won't accept this. Rather than using a "type generator" and +// using a different syntax, make a derivation which should be equivalent. +// +// Another issue addressed here is that the transform_iterator doesn't have +// a templated constructor. This makes it incompatible with the dataflow +// ideal. This is also addressed here. + +template< + class Base, + class CharType = BOOST_DEDUCED_TYPENAME boost::iterator_value::type +> +class binary_from_base64 : public + transform_iterator< + detail::to_6_bit, + Base + > +{ + friend class boost::iterator_core_access; + typedef transform_iterator< + detail::to_6_bit, + Base + > super_t; +public: + // make composible buy using templated constructor + template + binary_from_base64(BOOST_PFTO_WRAPPER(T) start) : + super_t( + Base(BOOST_MAKE_PFTO_WRAPPER(static_cast(start))), + detail::to_6_bit() + ) + {} + // intel 7.1 doesn't like default copy constructor + binary_from_base64(const binary_from_base64 & rhs) : + super_t( + Base(rhs.base_reference()), + detail::to_6_bit() + ) + {} +// binary_from_base64(){}; +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_BINARY_FROM_BASE64_HPP diff --git a/win32/include/boost/archive/iterators/dataflow.hpp b/win32/include/boost/archive/iterators/dataflow.hpp new file mode 100755 index 000000000..6a88a2358 --- /dev/null +++ b/win32/include/boost/archive/iterators/dataflow.hpp @@ -0,0 +1,104 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_DATAFLOW_HPP +#define BOOST_ARCHIVE_ITERATORS_DATAFLOW_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// dataflow.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include + +#include // for BOOST_DEDUCED_TYPENAME + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace archive { +namespace iterators { + +// poor man's tri-state +struct tri_state { + enum state_enum { + is_false = false, + is_true = true, + is_indeterminant, + } m_state; + // convert to bool + operator bool (){ + assert(is_indeterminant != m_state); + return is_true == m_state ? true : false; + } + // assign from bool + tri_state & operator=(bool rhs) { + m_state = rhs ? is_true : is_false; + } + tri_state(bool rhs) : + m_state(rhs ? is_true : is_false) + {} + tri_state(state_enum state) : + m_state(state) + {} + bool operator==(const tri_state & rhs) const { + return m_state == rhs.m_state; + } + bool operator!=(const tri_state & rhs) const { + return m_state != rhs.m_state; + } +}; + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implement functions common to dataflow iterators +template +class dataflow { + bool m_eoi; +protected: + // test for iterator equality + tri_state equal(const Derived & rhs) const { + if(m_eoi && rhs.m_eoi) + return true; + if(m_eoi || rhs.m_eoi) + return false; + return tri_state(tri_state::is_indeterminant); + } + void eoi(bool tf){ + m_eoi = tf; + } + bool eoi() const { + return m_eoi; + } +public: + dataflow(bool tf) : + m_eoi(tf) + {} + dataflow() : // used for iterator end + m_eoi(true) + {} +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_DATAFLOW_HPP diff --git a/win32/include/boost/archive/iterators/dataflow_exception.hpp b/win32/include/boost/archive/iterators/dataflow_exception.hpp new file mode 100755 index 000000000..7492f518e --- /dev/null +++ b/win32/include/boost/archive/iterators/dataflow_exception.hpp @@ -0,0 +1,80 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_DATAFLOW_EXCEPTION_HPP +#define BOOST_ARCHIVE_ITERATORS_DATAFLOW_EXCEPTION_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// dataflow_exception.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#ifndef BOOST_NO_EXCEPTIONS +#include + +#include + +namespace boost { +namespace archive { +namespace iterators { + +////////////////////////////////////////////////////////////////////// +// exceptions thrown by dataflows +// +class dataflow_exception : public std::exception +{ +public: + typedef enum { + invalid_6_bitcode, + invalid_base64_character, + invalid_xml_escape_sequence, + comparison_not_permitted, + invalid_conversion, + other_exception + } exception_code; + exception_code code; + + dataflow_exception(exception_code c = other_exception) : code(c) + {} + + virtual const char *what( ) const throw( ) + { + const char *msg = "unknown exception code"; + switch(code){ + case invalid_6_bitcode: + msg = "attempt to encode a value > 6 bits"; + break; + case invalid_base64_character: + msg = "attempt to decode a value not in base64 char set"; + break; + case invalid_xml_escape_sequence: + msg = "invalid xml escape_sequence"; + break; + case comparison_not_permitted: + msg = "cannot invoke iterator comparison now"; + break; + case invalid_conversion: + msg = "invalid multbyte/wide char conversion"; + break; + default: + assert(false); + break; + } + return msg; + } +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif //BOOST_NO_EXCEPTIONS +#endif //BOOST_ARCHIVE_ITERATORS_DATAFLOW_EXCEPTION_HPP diff --git a/win32/include/boost/archive/iterators/escape.hpp b/win32/include/boost/archive/iterators/escape.hpp new file mode 100755 index 000000000..bb3b6a386 --- /dev/null +++ b/win32/include/boost/archive/iterators/escape.hpp @@ -0,0 +1,115 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_ESCAPE_HPP +#define BOOST_ARCHIVE_ITERATORS_ESCAPE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// escape.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include // NULL + +#include // for BOOST_DEDUCED_TYPENAME +#include +#include + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// insert escapes into text + +template +class escape : + public boost::iterator_adaptor< + Derived, + Base, + BOOST_DEDUCED_TYPENAME boost::iterator_value::type, + single_pass_traversal_tag, + BOOST_DEDUCED_TYPENAME boost::iterator_value::type + > +{ + typedef BOOST_DEDUCED_TYPENAME boost::iterator_value::type base_value_type; + typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference::type reference_type; + friend class boost::iterator_core_access; + + typedef BOOST_DEDUCED_TYPENAME boost::iterator_adaptor< + Derived, + Base, + base_value_type, + single_pass_traversal_tag, + base_value_type + > super_t; + + typedef escape this_t; + + void dereference_impl() { + m_current_value = static_cast(this)->fill(m_bnext, m_bend); + m_full = true; + } + + //Access the value referred to + reference_type dereference() const { + if(!m_full) + const_cast(this)->dereference_impl(); + return m_current_value; + } + + bool equal(const this_t & rhs) const { + if(m_full){ + if(! rhs.m_full) + const_cast(& rhs)->dereference_impl(); + } + else{ + if(rhs.m_full) + const_cast(this)->dereference_impl(); + } + if(m_bnext != rhs.m_bnext) + return false; + if(this->base_reference() != rhs.base_reference()) + return false; + return true; + } + + void increment(){ + if(++m_bnext < m_bend){ + m_current_value = *m_bnext; + return; + } + ++(this->base_reference()); + m_bnext = NULL; + m_bend = NULL; + m_full = false; + } + + // buffer to handle pending characters + const base_value_type *m_bnext; + const base_value_type *m_bend; + bool m_full; + BOOST_DEDUCED_TYPENAME boost::iterator_value::type m_current_value; +public: + escape(Base base) : + super_t(base), + m_bnext(NULL), + m_bend(NULL), + m_full(false) + { + } +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_ESCAPE_HPP diff --git a/win32/include/boost/archive/iterators/head_iterator.hpp b/win32/include/boost/archive/iterators/head_iterator.hpp new file mode 100755 index 000000000..08e08a3ef --- /dev/null +++ b/win32/include/boost/archive/iterators/head_iterator.hpp @@ -0,0 +1,81 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_HEAD_ITERATOR_HPP +#define BOOST_ARCHIVE_ITERATORS_HEAD_ITERATOR_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// head_iterator.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include + +namespace boost { +namespace archive { +namespace iterators { + +template +class head_iterator + : public boost::iterator_adaptor< + head_iterator, + Base, + use_default, + single_pass_traversal_tag + > +{ +private: + friend class iterator_core_access; + typedef boost::iterator_adaptor< + head_iterator, + Base, + use_default, + single_pass_traversal_tag + > super_t; + + typedef head_iterator this_t; + typedef BOOST_DEDUCED_TYPENAME super_t::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME super_t::reference reference_type; + + reference_type dereference_impl(){ + if(! m_end){ + while(! m_predicate(* base_reference())) + ++ base_reference(); + m_end = true; + } + return * base_reference(); + } + + reference_type dereference() const { + return const_cast(this)->dereference_impl(); + } + + void increment(){ + ++base_reference(); + } + Predicate m_predicate; + bool m_end; +public: + template + head_iterator(Predicate f, T start) : + super_t(Base(start)), + m_predicate(f), + m_end(false) + {} + +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_HEAD_ITERATOR_HPP diff --git a/win32/include/boost/archive/iterators/insert_linebreaks.hpp b/win32/include/boost/archive/iterators/insert_linebreaks.hpp new file mode 100755 index 000000000..ee57bfca2 --- /dev/null +++ b/win32/include/boost/archive/iterators/insert_linebreaks.hpp @@ -0,0 +1,101 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_INSERT_LINEBREAKS_HPP +#define BOOST_ARCHIVE_ITERATORS_INSERT_LINEBREAKS_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// insert_linebreaks.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include + +#include // for BOOST_DEDUCED_TYPENAME +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ using ::memcpy; } +#endif + +#include + +#include +#include + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// insert line break every N characters +template< + class Base, + int N, + class CharType = BOOST_DEDUCED_TYPENAME boost::iterator_value::type +> +class insert_linebreaks : + public iterator_adaptor< + insert_linebreaks, + Base, + CharType, + single_pass_traversal_tag, + CharType + > +{ +private: + friend class boost::iterator_core_access; + typedef iterator_adaptor< + insert_linebreaks, + Base, + CharType, + single_pass_traversal_tag, + CharType + > super_t; + + bool equal(const insert_linebreaks & rhs) const { + return +// m_count == rhs.m_count +// && base_reference() == rhs.base_reference() + this->base_reference() == rhs.base_reference() + ; + } + + void increment() { + if(m_count == N){ + m_count = 0; + return; + } + ++m_count; + ++(this->base_reference()); + } + CharType dereference() const { + if(m_count == N) + return '\n'; + return * (this->base_reference()); + } + unsigned int m_count; +public: + // make composible buy using templated constructor + template + insert_linebreaks(BOOST_PFTO_WRAPPER(T) start) : + super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast(start)))), + m_count(0) + {} + // intel 7.1 doesn't like default copy constructor + insert_linebreaks(const insert_linebreaks & rhs) : + super_t(rhs.base_reference()), + m_count(rhs.m_count) + {} +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_INSERT_LINEBREAKS_HPP diff --git a/win32/include/boost/archive/iterators/istream_iterator.hpp b/win32/include/boost/archive/iterators/istream_iterator.hpp new file mode 100755 index 000000000..1a462efce --- /dev/null +++ b/win32/include/boost/archive/iterators/istream_iterator.hpp @@ -0,0 +1,95 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_ISTREAM_ITERATOR_HPP +#define BOOST_ARCHIVE_ITERATORS_ISTREAM_ITERATOR_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// istream_iterator.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +// note: this is a custom version of the standard istream_iterator. +// This is necessary as the standard version doesn't work as expected +// for wchar_t based streams on systems for which wchar_t not a true +// type but rather a synonym for some integer type. + +#include // NULL +#include +#include + +namespace boost { +namespace archive { +namespace iterators { + +// given a type, make an input iterator based on a pointer to that type +template +class istream_iterator : + public boost::iterator_facade< + istream_iterator, + Elem, + std::input_iterator_tag, + Elem + > +{ + friend class boost::iterator_core_access; + typedef istream_iterator this_t ; + typedef BOOST_DEDUCED_TYPENAME boost::iterator_facade< + istream_iterator, + Elem, + std::input_iterator_tag, + Elem + > super_t; + typedef BOOST_DEDUCED_TYPENAME std::basic_istream istream_type; + + //Access the value referred to + Elem dereference() const { + return m_current_value; + } + + bool equal(const this_t & rhs) const { + // note: only works for comparison against end of stream + return m_istream == rhs.m_istream; + } + + void increment(){ + if(NULL != m_istream){ + m_current_value = m_istream->get(); + if(! m_istream->good()){ + const_cast(this)->m_istream = NULL; + } + } + } + + istream_type *m_istream; + Elem m_current_value; +public: + istream_iterator(istream_type & is) : + m_istream(& is) + { + increment(); + } + + istream_iterator() : + m_istream(NULL) + {} + + istream_iterator(const istream_iterator & rhs) : + m_istream(rhs.m_istream), + m_current_value(rhs.m_current_value) + {} + +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_ISTREAM_ITERATOR_HPP diff --git a/win32/include/boost/archive/iterators/mb_from_wchar.hpp b/win32/include/boost/archive/iterators/mb_from_wchar.hpp new file mode 100755 index 000000000..5464900ac --- /dev/null +++ b/win32/include/boost/archive/iterators/mb_from_wchar.hpp @@ -0,0 +1,136 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_MB_FROM_WCHAR_HPP +#define BOOST_ARCHIVE_ITERATORS_MB_FROM_WCHAR_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// mb_from_wchar.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include // size_t +#include // for wctomb() + +#include // for BOOST_DEDUCED_TYPENAME +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; + using ::wctomb; +} // namespace std +#endif + +#include +#include + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// class used by text archives to translate wide strings and to char +// strings of the currently selected locale +template // the input iterator +class mb_from_wchar + : public boost::iterator_adaptor< + mb_from_wchar, + Base, + wchar_t, + single_pass_traversal_tag, + char + > +{ + friend class boost::iterator_core_access; + + typedef BOOST_DEDUCED_TYPENAME boost::iterator_adaptor< + mb_from_wchar, + Base, + wchar_t, + single_pass_traversal_tag, + char + > super_t; + + typedef mb_from_wchar this_t; + + char dereference_impl() { + if(! m_full){ + fill(); + m_full = true; + } + return m_buffer[m_bnext]; + } + char dereference() const { + return (const_cast(this))->dereference_impl(); + } + + // test for iterator equality + bool equal(const mb_from_wchar & rhs) const { + // once the value is filled, the base_reference has been incremented + // so don't permit comparison anymore. + return + 0 == m_bend + && 0 == m_bnext + && this->base_reference() == rhs.base_reference() + ; + } + + void fill(){ + wchar_t value = * this->base_reference(); + #if (defined(__MINGW32__) && ((__MINGW32_MAJOR_VERSION > 3) \ + || ((__MINGW32_MAJOR_VERSION == 3) && (__MINGW32_MINOR_VERSION >= 8)))) + m_bend = std::wcrtomb(m_buffer, value, 0); + #else + m_bend = std::wctomb(m_buffer, value); + #endif + assert(-1 != m_bend); + assert((std::size_t)m_bend <= sizeof(m_buffer)); + assert(m_bend > 0); + m_bnext = 0; + } + + void increment(){ + if(++m_bnext < m_bend) + return; + m_bend = + m_bnext = 0; + ++(this->base_reference()); + m_full = false; + } + + // buffer to handle pending characters + int m_bend; + int m_bnext; + char m_buffer[9]; + bool m_full; + +public: + // make composible buy using templated constructor + template + mb_from_wchar(BOOST_PFTO_WRAPPER(T) start) : + super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast(start)))), + m_bend(0), + m_bnext(0), + m_full(false) + {} + // intel 7.1 doesn't like default copy constructor + mb_from_wchar(const mb_from_wchar & rhs) : + super_t(rhs.base_reference()), + m_bend(rhs.m_bend), + m_bnext(rhs.m_bnext), + m_full(rhs.m_full) + {} +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_MB_FROM_WCHAR_HPP diff --git a/win32/include/boost/archive/iterators/ostream_iterator.hpp b/win32/include/boost/archive/iterators/ostream_iterator.hpp new file mode 100755 index 000000000..791529f1c --- /dev/null +++ b/win32/include/boost/archive/iterators/ostream_iterator.hpp @@ -0,0 +1,83 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_OSTREAM_ITERATOR_HPP +#define BOOST_ARCHIVE_ITERATORS_OSTREAM_ITERATOR_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// ostream_iterator.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +// note: this is a custom version of the standard ostream_iterator. +// This is necessary as the standard version doesn't work as expected +// for wchar_t based streams on systems for which wchar_t not a true +// type but rather a synonym for some integer type. + +#include +#include + +namespace boost { +namespace archive { +namespace iterators { + +// given a type, make an input iterator based on a pointer to that type +template +class ostream_iterator : + public boost::iterator_facade< + ostream_iterator, + Elem, + std::output_iterator_tag, + ostream_iterator & + > +{ + friend class boost::iterator_core_access; + typedef ostream_iterator this_t ; + typedef Elem char_type; + typedef std::basic_ostream ostream_type; + + //emulate the behavior of std::ostream + ostream_iterator & dereference() const { + return const_cast(*this); + } + bool equal(const this_t & rhs) const { + return m_ostream == rhs.m_ostream; + } + void increment(){} +protected: + ostream_type *m_ostream; + void put_val(char_type e){ + if(NULL != m_ostream){ + m_ostream->put(e); + if(! m_ostream->good()) + m_ostream = NULL; + } + } +public: + this_t & operator=(char_type c){ + put_val(c); + return *this; + } + ostream_iterator(ostream_type & os) : + m_ostream (& os) + {} + ostream_iterator() : + m_ostream (NULL) + {} + ostream_iterator(const ostream_iterator & rhs) : + m_ostream (rhs.m_ostream) + {} +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_OSTREAM_ITERATOR_HPP diff --git a/win32/include/boost/archive/iterators/remove_whitespace.hpp b/win32/include/boost/archive/iterators/remove_whitespace.hpp new file mode 100755 index 000000000..207edc6fa --- /dev/null +++ b/win32/include/boost/archive/iterators/remove_whitespace.hpp @@ -0,0 +1,169 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_REMOVE_WHITESPACE_HPP +#define BOOST_ARCHIVE_ITERATORS_REMOVE_WHITESPACE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// remove_whitespace.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include + +#include // for BOOST_DEDUCED_TYPENAME + +#include + +#include +#include + +//#include +//#if ! BOOST_WORKAROUND(BOOST_MSVC, <=1300) + +// here is the default standard implementation of the functor used +// by the filter iterator to remove spaces. Unfortunately usage +// of this implementation in combination with spirit trips a bug +// VC 6.5. The only way I can find to work around it is to +// implement a special non-standard version for this platform + +#ifndef BOOST_NO_CWCTYPE +#include // iswspace +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ using ::iswspace; } +#endif +#endif + +#include // isspace +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ using ::isspace; } +#endif + +#if defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER) +// this is required for the RW STL on Linux and Tru64. +#undef isspace +#undef iswspace +#endif + +//#endif // BOOST_WORKAROUND + +namespace { // anonymous + +template +struct remove_whitespace_predicate; + +template<> +struct remove_whitespace_predicate +{ + bool operator()(unsigned char t){ + return ! std::isspace(t); + } +}; + +#ifndef BOOST_NO_CWCHAR +template<> +struct remove_whitespace_predicate +{ + bool operator()(wchar_t t){ + return ! std::iswspace(t); + } +}; +#endif + +} // namespace anonymous + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// convert base64 file data (including whitespace and padding) to binary + +namespace boost { +namespace archive { +namespace iterators { + +// custom version of filter iterator which doesn't look ahead further than +// necessary + +template +class filter_iterator + : public boost::iterator_adaptor< + filter_iterator, + Base, + use_default, + single_pass_traversal_tag + > +{ + friend class boost::iterator_core_access; + typedef BOOST_DEDUCED_TYPENAME boost::iterator_adaptor< + filter_iterator, + Base, + use_default, + single_pass_traversal_tag + > super_t; + typedef filter_iterator this_t; + typedef BOOST_DEDUCED_TYPENAME super_t::reference reference_type; + + reference_type dereference_impl(){ + if(! m_full){ + while(! m_predicate(* this->base_reference())) + ++(this->base_reference()); + m_full = true; + } + return * this->base_reference(); + } + + reference_type dereference() const { + return const_cast(this)->dereference_impl(); + } + + Predicate m_predicate; + bool m_full; +public: + // note: this function is public only because comeau compiler complained + // I don't know if this is because the compiler is wrong or what + void increment(){ + m_full = false; + ++(this->base_reference()); + } + filter_iterator(Base start) : + super_t(start), + m_full(false) + {} + filter_iterator(){} +}; + +template +class remove_whitespace : + public filter_iterator< + remove_whitespace_predicate, + Base + > +{ + friend class boost::iterator_core_access; + typedef filter_iterator< + remove_whitespace_predicate, + Base + > super_t; +public: +// remove_whitespace(){} // why is this needed? + // make composible buy using templated constructor + template + remove_whitespace(BOOST_PFTO_WRAPPER(T) start) : + super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast(start)))) + {} + // intel 7.1 doesn't like default copy constructor + remove_whitespace(const remove_whitespace & rhs) : + super_t(rhs.base_reference()) + {} +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_REMOVE_WHITESPACE_HPP diff --git a/win32/include/boost/archive/iterators/transform_width.hpp b/win32/include/boost/archive/iterators/transform_width.hpp new file mode 100755 index 000000000..8353d56b7 --- /dev/null +++ b/win32/include/boost/archive/iterators/transform_width.hpp @@ -0,0 +1,168 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP +#define BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// transform_width.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +// iterator which takes elements of x bits and returns elements of y bits. +// used to change streams of 8 bit characters into streams of 6 bit characters. +// and vice-versa for implementing base64 encodeing/decoding. Be very careful +// when using and end iterator. end is only reliable detected when the input +// stream length is some common multiple of x and y. E.G. Base64 6 bit +// character and 8 bit bytes. Lowest common multiple is 24 => 4 6 bit characters +// or 3 8 bit characters + +#include // for BOOST_DEDUCED_TYPENAME & PTFO +#include + +#include +#include + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// class used by text archives to translate char strings to wchar_t +// strings of the currently selected locale +template< + class Base, + int BitsOut, + int BitsIn, + class CharType = BOOST_DEDUCED_TYPENAME boost::iterator_value::type // output character +> +class transform_width : + public boost::iterator_adaptor< + transform_width, + Base, + CharType, + single_pass_traversal_tag, + CharType + > +{ + friend class boost::iterator_core_access; + typedef BOOST_DEDUCED_TYPENAME boost::iterator_adaptor< + transform_width, + Base, + CharType, + single_pass_traversal_tag, + CharType + > super_t; + + typedef transform_width this_t; + typedef BOOST_DEDUCED_TYPENAME iterator_value::type base_value_type; + + CharType fill(); + + CharType dereference_impl(){ + if(! m_full){ + m_current_value = fill(); + m_full = true; + } + return m_current_value; + } + + CharType dereference() const { + return const_cast(this)->dereference_impl(); + } + + // test for iterator equality + bool equal(const this_t & rhs) const { + return + this->base_reference() == rhs.base_reference(); + ; + } + + void increment(){ + m_displacement += BitsOut; + + while(m_displacement >= BitsIn){ + m_displacement -= BitsIn; + if(0 == m_displacement) + m_bufferfull = false; + if(! m_bufferfull){ + // note: suspect that this is not invoked for borland + ++(this->base_reference()); + } + } + m_full = false; + } + + CharType m_current_value; + // number of bits left in current input character buffer + unsigned int m_displacement; + base_value_type m_buffer; + // flag to current output character is ready - just used to save time + bool m_full; + // flag to indicate that m_buffer has data + bool m_bufferfull; + +public: + // make composible buy using templated constructor + template + transform_width(BOOST_PFTO_WRAPPER(T) start) : + super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast(start)))), + m_displacement(0), + m_full(false), + m_bufferfull(false) + {} + // intel 7.1 doesn't like default copy constructor + transform_width(const transform_width & rhs) : + super_t(rhs.base_reference()), + m_current_value(rhs.m_current_value), + m_displacement(rhs.m_displacement), + m_buffer(rhs.m_buffer), + m_full(rhs.m_full), + m_bufferfull(rhs.m_bufferfull) + {} +}; + +template +CharType transform_width::fill(){ + CharType retval = 0; + unsigned int missing_bits = BitsOut; + for(;;){ + unsigned int bcount; + if(! m_bufferfull){ + m_buffer = * this->base_reference(); + m_bufferfull = true; + bcount = BitsIn; + } + else + bcount = BitsIn - m_displacement; + unsigned int i = (std::min)(bcount, missing_bits); + // shift interesting bits to least significant position + unsigned int j = m_buffer >> (bcount - i); + // strip off uninteresting bits + // (note presumption of two's complement arithmetic) + j &= ~(-(1 << i)); + // append then interesting bits to the output value + retval <<= i; + retval |= j; + missing_bits -= i; + if(0 == missing_bits) + break; + // note: suspect that this is not invoked for borland 5.51 + ++(this->base_reference()); + m_bufferfull = false; + } + return retval; +} + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP diff --git a/win32/include/boost/archive/iterators/unescape.hpp b/win32/include/boost/archive/iterators/unescape.hpp new file mode 100755 index 000000000..49f5263c7 --- /dev/null +++ b/win32/include/boost/archive/iterators/unescape.hpp @@ -0,0 +1,94 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_UNESCAPE_HPP +#define BOOST_ARCHIVE_ITERATORS_UNESCAPE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// unescape.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include + +#include // for BOOST_DEDUCED_TYPENAME +#include +//#include +#include + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// class used by text archives to translate char strings to wchar_t +// strings of the currently selected locale +template +class unescape + : public boost::iterator_adaptor< + unescape, + Base, + BOOST_DEDUCED_TYPENAME pointee::type, + single_pass_traversal_tag, + BOOST_DEDUCED_TYPENAME pointee::type + > +{ + friend class boost::iterator_core_access; + typedef BOOST_DEDUCED_TYPENAME boost::iterator_adaptor< + unescape, + Base, + BOOST_DEDUCED_TYPENAME pointee::type, + single_pass_traversal_tag, + BOOST_DEDUCED_TYPENAME pointee::type + > super_t; + + typedef unescape this_t; + typedef BOOST_DEDUCED_TYPENAME super_t::reference reference_type; +public: + // gcc 3.4.1 - linux required that this be public + typedef BOOST_DEDUCED_TYPENAME super_t::value_type value_type; +private: + + reference_type dereference_impl() { + if(! m_full){ + m_current_value = static_cast(this)->drain(); + m_full = true; + } + return m_current_value; + } + + reference_type dereference() const { + return const_cast(this)->dereference_impl(); + } + + // value_type is const char - can't be const fix later + value_type m_current_value; + bool m_full; + + void increment(){ + ++(this->base_reference()); + dereference_impl(); + m_full = false; + }; + +public: + + unescape(Base base) : + super_t(base), + m_full(false) + {} + +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_UNESCAPE_HPP diff --git a/win32/include/boost/archive/iterators/wchar_from_mb.hpp b/win32/include/boost/archive/iterators/wchar_from_mb.hpp new file mode 100755 index 000000000..f2fd54767 --- /dev/null +++ b/win32/include/boost/archive/iterators/wchar_from_mb.hpp @@ -0,0 +1,129 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP +#define BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// wchar_from_mb.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include // size_t +#include // mblen + +#include // for BOOST_DEDUCED_TYPENAME +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::mblen; + using ::mbtowc; +} // namespace std +#endif + +#include +#include + +#include +#include + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// class used by text archives to translate char strings to wchar_t +// strings of the currently selected locale +template +class wchar_from_mb + : public boost::iterator_adaptor< + wchar_from_mb, + Base, + wchar_t, + single_pass_traversal_tag, + wchar_t + > +{ + friend class boost::iterator_core_access; + typedef BOOST_DEDUCED_TYPENAME boost::iterator_adaptor< + wchar_from_mb, + Base, + wchar_t, + single_pass_traversal_tag, + wchar_t + > super_t; + + typedef wchar_from_mb this_t; + + wchar_t drain(); + + wchar_t dereference_impl() { + if(! m_full){ + m_current_value = drain(); + m_full = true; + } + return m_current_value; + } + + wchar_t dereference() const { + return const_cast(this)->dereference_impl(); + } + + void increment(){ + dereference_impl(); + m_full = false; + ++(this->base_reference()); + }; + + wchar_t m_current_value; + bool m_full; + +public: + // make composible buy using templated constructor + template + wchar_from_mb(BOOST_PFTO_WRAPPER(T) start) : + super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast(start)))), + m_full(false) + {} + // intel 7.1 doesn't like default copy constructor + wchar_from_mb(const wchar_from_mb & rhs) : + super_t(rhs.base_reference()), + m_full(rhs.m_full) + {} +}; + +template +wchar_t wchar_from_mb::drain(){ + char buffer[9]; + char * bptr = buffer; + char val; + for(std::size_t i = 0; i++ < (unsigned)MB_CUR_MAX;){ + val = * this->base_reference(); + *bptr++ = val; + int result = std::mblen(buffer, i); + if(-1 != result) + break; + ++(this->base_reference()); + } + wchar_t retval; + int result = std::mbtowc(& retval, buffer, MB_CUR_MAX); + if(0 >= result) + boost::throw_exception(iterators::dataflow_exception( + iterators::dataflow_exception::invalid_conversion + )); + return retval; +} + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP diff --git a/win32/include/boost/archive/iterators/xml_escape.hpp b/win32/include/boost/archive/iterators/xml_escape.hpp new file mode 100755 index 000000000..5c168206b --- /dev/null +++ b/win32/include/boost/archive/iterators/xml_escape.hpp @@ -0,0 +1,125 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_XML_ESCAPE_HPP +#define BOOST_ARCHIVE_ITERATORS_XML_ESCAPE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_escape.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include + +#include // for BOOST_DEDUCED_TYPENAME +#include + +#include + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// insert escapes into xml text + +template +class xml_escape + : public escape, Base> +{ + friend class boost::iterator_core_access; + + typedef escape, Base> super_t; + +public: + char fill(const char * & bstart, const char * & bend); + wchar_t fill(const wchar_t * & bstart, const wchar_t * & bend); + + template + xml_escape(BOOST_PFTO_WRAPPER(T) start) : + super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast(start)))) + {} + // intel 7.1 doesn't like default copy constructor + xml_escape(const xml_escape & rhs) : + super_t(rhs.base_reference()) + {} +}; + +template +char xml_escape::fill( + const char * & bstart, + const char * & bend +){ + char current_value = * this->base_reference(); + switch(current_value){ + case '<': + bstart = "<"; + bend = bstart + 4; + break; + case '>': + bstart = ">"; + bend = bstart + 4; + break; + case '&': + bstart = "&"; + bend = bstart + 5; + break; + case '"': + bstart = """; + bend = bstart + 6; + break; + case '\'': + bstart = "'"; + bend = bstart + 6; + break; + default: + return current_value; + } + return *bstart; +} + +template +wchar_t xml_escape::fill( + const wchar_t * & bstart, + const wchar_t * & bend +){ + wchar_t current_value = * this->base_reference(); + switch(current_value){ + case '<': + bstart = L"<"; + bend = bstart + 4; + break; + case '>': + bstart = L">"; + bend = bstart + 4; + break; + case '&': + bstart = L"&"; + bend = bstart + 5; + break; + case '"': + bstart = L"""; + bend = bstart + 6; + break; + case '\'': + bstart = L"'"; + bend = bstart + 6; + break; + default: + return current_value; + } + return *bstart; +} + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_XML_ESCAPE_HPP diff --git a/win32/include/boost/archive/iterators/xml_unescape.hpp b/win32/include/boost/archive/iterators/xml_unescape.hpp new file mode 100755 index 000000000..2f40ab056 --- /dev/null +++ b/win32/include/boost/archive/iterators/xml_unescape.hpp @@ -0,0 +1,118 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP +#define BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_unescape.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include + +#include // for BOOST_DEDUCED_TYPENAME +#include +#include + +#include +#include + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// replace &??? xml escape sequences with the corresponding characters +template +class xml_unescape + : public unescape, Base> +{ + friend class boost::iterator_core_access; + typedef xml_unescape this_t; + typedef unescape super_t; + typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference reference_type; + + reference_type dereference() const { + return unescape, Base>::dereference(); + } +public: + void drain_residue(const char *literal); + int drain(); + + template + xml_unescape(BOOST_PFTO_WRAPPER(T) start) : + super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast(start)))) + {} + // intel 7.1 doesn't like default copy constructor + xml_unescape(const xml_unescape & rhs) : + super_t(rhs.base_reference()) + {} +}; + +template +void xml_unescape::drain_residue(const char * literal){ + do{ + if(* literal != * ++(this->base_reference())) + boost::throw_exception( + dataflow_exception( + dataflow_exception::invalid_xml_escape_sequence + ) + ); + } + while('\0' != * ++literal); +} + +// note key constraint on this function is that can't "look ahead" any +// more than necessary into base iterator. Doing so would alter the base +// iterator refenence which would make subsequent iterator comparisons +// incorrect and thereby break the composiblity of iterators. +template +int xml_unescape::drain(){ + int retval = * this->base_reference(); + if('&' != retval){ + return retval; + } + retval = * ++(this->base_reference()); + switch(retval){ + case 'l': // < + drain_residue("t;"); + retval = '<'; + break; + case 'g': // > + drain_residue("t;"); + retval = '>'; + break; + case 'a': + retval = * ++(this->base_reference()); + switch(retval){ + case 'p': // ' + drain_residue("os;"); + retval = '\''; + break; + case 'm': // & + drain_residue("p;"); + retval = '&'; + break; + } + break; + case 'q': + drain_residue("uot;"); + retval = '"'; + break; + } + return retval; +} + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP diff --git a/win32/include/boost/archive/iterators/xml_unescape_exception.hpp b/win32/include/boost/archive/iterators/xml_unescape_exception.hpp new file mode 100755 index 000000000..ebc34681a --- /dev/null +++ b/win32/include/boost/archive/iterators/xml_unescape_exception.hpp @@ -0,0 +1,49 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_EXCEPTION_HPP +#define BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_EXCEPTION_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_unescape_exception.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#ifndef BOOST_NO_EXCEPTIONS +#include + +#include + +namespace boost { +namespace archive { +namespace iterators { + +////////////////////////////////////////////////////////////////////// +// exceptions thrown by xml_unescapes +// +class xml_unescape_exception : public std::exception +{ +public: + xml_unescape_exception() + {} + + virtual const char *what( ) const throw( ) + { + return "xml contained un-recognized escape code"; + } +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif //BOOST_NO_EXCEPTIONS +#endif //BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_EXCEPTION_HPP diff --git a/win32/include/boost/archive/polymorphic_binary_iarchive.hpp b/win32/include/boost/archive/polymorphic_binary_iarchive.hpp new file mode 100755 index 000000000..e62c2a0ba --- /dev/null +++ b/win32/include/boost/archive/polymorphic_binary_iarchive.hpp @@ -0,0 +1,45 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_BINARY_IARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_BINARY_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_binary_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include + +namespace boost { +namespace archive { + +class polymorphic_binary_iarchive : + public detail::polymorphic_iarchive_route +{ +public: + polymorphic_binary_iarchive(std::istream & is, unsigned int flags = 0) : + detail::polymorphic_iarchive_route(is, flags) + {} + ~polymorphic_binary_iarchive(){} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_binary_iarchive +) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_BINARY_IARCHIVE_HPP + diff --git a/win32/include/boost/archive/polymorphic_binary_oarchive.hpp b/win32/include/boost/archive/polymorphic_binary_oarchive.hpp new file mode 100755 index 000000000..bc06136d6 --- /dev/null +++ b/win32/include/boost/archive/polymorphic_binary_oarchive.hpp @@ -0,0 +1,43 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_BINARY_OARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_BINARY_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_binary_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include + +namespace boost { +namespace archive { + +typedef detail::polymorphic_oarchive_route< + binary_oarchive_impl< + naked_binary_oarchive, + std::ostream::char_type, + std::ostream::traits_type + > + > polymorphic_binary_oarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_binary_oarchive +) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_BINARY_OARCHIVE_HPP + diff --git a/win32/include/boost/archive/polymorphic_iarchive.hpp b/win32/include/boost/archive/polymorphic_iarchive.hpp new file mode 100755 index 000000000..a6a9b15c9 --- /dev/null +++ b/win32/include/boost/archive/polymorphic_iarchive.hpp @@ -0,0 +1,188 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_IARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include // std::size_t +#include // ULONG_MAX +#include + +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include +#include + +#include +#include +#include +#include +#include + +// determine if its necessary to handle (u)int64_t specifically +// i.e. that its not a synonym for (unsigned) long +// if there is no 64 bit int or if its the same as a long +// we shouldn't define separate functions for int64 data types. +#if defined(BOOST_NO_INT64_T) + #define BOOST_NO_INTRINSIC_INT64_T +#else + #if defined(ULONG_MAX) + #if(ULONG_MAX != 0xffffffff && ULONG_MAX == 18446744073709551615u) // 2**64 - 1 + #define BOOST_NO_INTRINSIC_INT64_T + #endif + #else + #define BOOST_NO_INTRINSIC_INT64_T + #endif +#endif + +namespace boost { +template +class shared_ptr; +namespace serialization { + class extended_type_info; +} // namespace serialization +namespace archive { +namespace detail { + class basic_iarchive; + class basic_iserializer; +} + +class polymorphic_iarchive; + +class polymorphic_iarchive_impl : + public detail::interface_iarchive +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + friend class detail::interface_iarchive; + friend class load_access; +#endif + // primitive types the only ones permitted by polymorphic archives + virtual void load(bool & t) = 0; + + virtual void load(char & t) = 0; + virtual void load(signed char & t) = 0; + virtual void load(unsigned char & t) = 0; + #ifndef BOOST_NO_CWCHAR + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + virtual void load(wchar_t & t) = 0; + #endif + #endif + virtual void load(short & t) = 0; + virtual void load(unsigned short & t) = 0; + virtual void load(int & t) = 0; + virtual void load(unsigned int & t) = 0; + virtual void load(long & t) = 0; + virtual void load(unsigned long & t) = 0; + + #if !defined(BOOST_NO_INTRINSIC_INT64_T) + virtual void load(boost::int64_t & t) = 0; + virtual void load(boost::uint64_t & t) = 0; + #endif + virtual void load(float & t) = 0; + virtual void load(double & t) = 0; + + // string types are treated as primitives + virtual void load(std::string & t) = 0; + #ifndef BOOST_NO_STD_WSTRING + virtual void load(std::wstring & t) = 0; + #endif + + // used for xml and other tagged formats + virtual void load_start(const char * name) = 0; + virtual void load_end(const char * name) = 0; + virtual void register_basic_serializer(const detail::basic_iserializer & bis) = 0; + + // msvc and borland won't automatically pass these to the base class so + // make it explicit here + template + void load_override(T & t, BOOST_PFTO int) + { + archive::load(* this->This(), t); + } + // special treatment for name-value pairs. + template + void load_override( + #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + const + #endif + boost::serialization::nvp & t, + int + ){ + load_start(t.name()); + archive::load(* this->This(), t.value()); + load_end(t.name()); + } +protected: + virtual ~polymorphic_iarchive_impl(){}; +public: + // utility function implemented by all legal archives + virtual void set_library_version(unsigned int archive_library_version) = 0; + virtual unsigned int get_library_version() const = 0; + virtual unsigned int get_flags() const = 0; + virtual void delete_created_pointers() = 0; + virtual void reset_object_address( + const void * new_address, + const void * old_address + ) = 0; + + virtual void load_binary(void * t, std::size_t size) = 0; + + // these are used by the serialization library implementation. + virtual void load_object( + void *t, + const detail::basic_iserializer & bis + ) = 0; + virtual const detail::basic_pointer_iserializer * load_pointer( + void * & t, + const detail::basic_pointer_iserializer * bpis_ptr, + const detail::basic_pointer_iserializer * (*finder)( + const boost::serialization::extended_type_info & type + ) + ) = 0; +}; + +} // namespace archive +} // namespace boost + +// note special treatment of shared_ptr. This type needs a special +// structure associated with every archive. We created a "mix-in" +// class to provide this functionality. Since shared_ptr holds a +// special esteem in the boost library - we included it here by default. +#include + +namespace boost { +namespace archive { + +class polymorphic_iarchive : + public polymorphic_iarchive_impl, + public detail::shared_ptr_helper +{ +public: + virtual ~polymorphic_iarchive(){}; +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::polymorphic_iarchive) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_IARCHIVE_HPP diff --git a/win32/include/boost/archive/polymorphic_oarchive.hpp b/win32/include/boost/archive/polymorphic_oarchive.hpp new file mode 100755 index 000000000..fb3818f03 --- /dev/null +++ b/win32/include/boost/archive/polymorphic_oarchive.hpp @@ -0,0 +1,165 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_OARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include // size_t +#include // ULONG_MAX +#include + +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include +#include +#include +#include +#include +#include + +// determine if its necessary to handle (u)int64_t specifically +// i.e. that its not a synonym for (unsigned) long +// if there is no 64 bit int or if its the same as a long +// we shouldn't define separate functions for int64 data types. +#if defined(BOOST_NO_INT64_T) + #define BOOST_NO_INTRINSIC_INT64_T +#else + #if defined(ULONG_MAX) + #if(ULONG_MAX != 0xffffffff && ULONG_MAX == 18446744073709551615u) // 2**64 - 1 + #define BOOST_NO_INTRINSIC_INT64_T + #endif + #else + #define BOOST_NO_INTRINSIC_INT64_T + #endif +#endif + +namespace boost { +template +class shared_ptr; +namespace serialization { + class extended_type_info; +} // namespace serialization +namespace archive { +namespace detail { + class basic_oarchive; + class basic_oserializer; +} + +class polymorphic_oarchive; + +class polymorphic_oarchive_impl : + public detail::interface_oarchive +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + friend class detail::interface_oarchive; + friend class save_access; +#endif + // primitive types the only ones permitted by polymorphic archives + virtual void save(const bool t) = 0; + + virtual void save(const char t) = 0; + virtual void save(const signed char t) = 0; + virtual void save(const unsigned char t) = 0; + #ifndef BOOST_NO_CWCHAR + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + virtual void save(const wchar_t t) = 0; + #endif + #endif + virtual void save(const short t) = 0; + virtual void save(const unsigned short t) = 0; + virtual void save(const int t) = 0; + virtual void save(const unsigned int t) = 0; + virtual void save(const long t) = 0; + virtual void save(const unsigned long t) = 0; + #if !defined(BOOST_NO_INTRINSIC_INT64_T) + virtual void save(const boost::int64_t t) = 0; + virtual void save(const boost::uint64_t t) = 0; + #endif + virtual void save(const float t) = 0; + virtual void save(const double t) = 0; + + // string types are treated as primitives + virtual void save(const std::string & t) = 0; + #ifndef BOOST_NO_STD_WSTRING + virtual void save(const std::wstring & t) = 0; + #endif + + virtual void save_null_pointer() = 0; + // used for xml and other tagged formats + virtual void save_start(const char * name) = 0; + virtual void save_end(const char * name) = 0; + virtual void register_basic_serializer(const detail::basic_oserializer & bos) = 0; + + virtual void end_preamble() = 0; + + // msvc and borland won't automatically pass these to the base class so + // make it explicit here + template + void save_override(T & t, BOOST_PFTO int) + { + archive::save(* this->This(), t); + } + // special treatment for name-value pairs. + template + void save_override( + #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + const + #endif + ::boost::serialization::nvp & t, int + ){ + save_start(t.name()); + archive::save(* this->This(), t.const_value()); + save_end(t.name()); + } +protected: + virtual ~polymorphic_oarchive_impl(){}; +public: + // utility functions implemented by all legal archives + virtual unsigned int get_flags() const = 0; + virtual unsigned int get_library_version() const = 0; + virtual void save_binary(const void * t, std::size_t size) = 0; + + virtual void save_object( + const void *x, + const detail::basic_oserializer & bos + ) = 0; + virtual void save_pointer( + const void * t, + const detail::basic_pointer_oserializer * bpos_ptr + ) = 0; +}; + +// note: preserve naming symmetry +class polymorphic_oarchive : + public polymorphic_oarchive_impl +{ +public: + virtual ~polymorphic_oarchive(){}; +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::polymorphic_oarchive) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_OARCHIVE_HPP diff --git a/win32/include/boost/archive/polymorphic_text_iarchive.hpp b/win32/include/boost/archive/polymorphic_text_iarchive.hpp new file mode 100755 index 000000000..7ba1eca9f --- /dev/null +++ b/win32/include/boost/archive/polymorphic_text_iarchive.hpp @@ -0,0 +1,45 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_TEXT_IARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_TEXT_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_text_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include + +namespace boost { +namespace archive { + +class polymorphic_text_iarchive : + public detail::polymorphic_iarchive_route +{ +public: + polymorphic_text_iarchive(std::istream & is, unsigned int flags = 0) : + detail::polymorphic_iarchive_route(is, flags) + {} + ~polymorphic_text_iarchive(){} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_text_iarchive +) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_TEXT_IARCHIVE_HPP + diff --git a/win32/include/boost/archive/polymorphic_text_oarchive.hpp b/win32/include/boost/archive/polymorphic_text_oarchive.hpp new file mode 100755 index 000000000..8fa8e6d1f --- /dev/null +++ b/win32/include/boost/archive/polymorphic_text_oarchive.hpp @@ -0,0 +1,39 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_TEXT_OARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_TEXT_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_text_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include + +namespace boost { +namespace archive { + +typedef detail::polymorphic_oarchive_route< + text_oarchive_impl +> polymorphic_text_oarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_text_oarchive +) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_TEXT_OARCHIVE_HPP + diff --git a/win32/include/boost/archive/polymorphic_text_wiarchive.hpp b/win32/include/boost/archive/polymorphic_text_wiarchive.hpp new file mode 100755 index 000000000..acf4ca0a4 --- /dev/null +++ b/win32/include/boost/archive/polymorphic_text_wiarchive.hpp @@ -0,0 +1,44 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_TEXT_WIARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_TEXT_WIARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_text_wiarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include +#include + +namespace boost { +namespace archive { + +typedef detail::polymorphic_iarchive_route< + text_wiarchive_impl +> polymorphic_text_wiarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_text_wiarchive +) + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_POLYMORPHIC_TEXT_WIARCHIVE_HPP + diff --git a/win32/include/boost/archive/polymorphic_text_woarchive.hpp b/win32/include/boost/archive/polymorphic_text_woarchive.hpp new file mode 100755 index 000000000..1c467ba6e --- /dev/null +++ b/win32/include/boost/archive/polymorphic_text_woarchive.hpp @@ -0,0 +1,44 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_TEXT_WOARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_TEXT_WOARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_text_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include +#include + +namespace boost { +namespace archive { + +typedef detail::polymorphic_oarchive_route< + text_woarchive_impl +> polymorphic_text_woarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_text_woarchive +) + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_POLYMORPHIC_TEXT_WOARCHIVE_HPP + diff --git a/win32/include/boost/archive/polymorphic_xml_iarchive.hpp b/win32/include/boost/archive/polymorphic_xml_iarchive.hpp new file mode 100755 index 000000000..8db42688a --- /dev/null +++ b/win32/include/boost/archive/polymorphic_xml_iarchive.hpp @@ -0,0 +1,45 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_XML_IARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_XML_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_xml_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include + +namespace boost { +namespace archive { + +class polymorphic_xml_iarchive : + public detail::polymorphic_iarchive_route +{ +public: + polymorphic_xml_iarchive(std::istream & is, unsigned int flags = 0) : + detail::polymorphic_iarchive_route(is, flags) + {} + ~polymorphic_xml_iarchive(){} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_xml_iarchive +) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_XML_IARCHIVE_HPP + diff --git a/win32/include/boost/archive/polymorphic_xml_oarchive.hpp b/win32/include/boost/archive/polymorphic_xml_oarchive.hpp new file mode 100755 index 000000000..87b4bf86d --- /dev/null +++ b/win32/include/boost/archive/polymorphic_xml_oarchive.hpp @@ -0,0 +1,39 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_XML_OARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_XML_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_xml_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include + +namespace boost { +namespace archive { + +typedef detail::polymorphic_oarchive_route< + xml_oarchive_impl +> polymorphic_xml_oarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_xml_oarchive +) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_XML_OARCHIVE_HPP + diff --git a/win32/include/boost/archive/polymorphic_xml_wiarchive.hpp b/win32/include/boost/archive/polymorphic_xml_wiarchive.hpp new file mode 100755 index 000000000..0f7320d8e --- /dev/null +++ b/win32/include/boost/archive/polymorphic_xml_wiarchive.hpp @@ -0,0 +1,44 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_XML_WIARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_XML_WIARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_xml_wiarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include +#include + +namespace boost { +namespace archive { + +typedef detail::polymorphic_iarchive_route< + xml_wiarchive_impl +> polymorphic_xml_wiarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_xml_wiarchive +) + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_POLYMORPHIC_XML_WIARCHIVE_HPP + diff --git a/win32/include/boost/archive/polymorphic_xml_woarchive.hpp b/win32/include/boost/archive/polymorphic_xml_woarchive.hpp new file mode 100755 index 000000000..14c8b8082 --- /dev/null +++ b/win32/include/boost/archive/polymorphic_xml_woarchive.hpp @@ -0,0 +1,44 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_XML_WOARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_XML_WOARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_xml_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include +#include + +namespace boost { +namespace archive { + +typedef detail::polymorphic_oarchive_route< + xml_woarchive_impl +> polymorphic_xml_woarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_xml_woarchive +) + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_POLYMORPHIC_XML_WOARCHIVE_HPP + diff --git a/win32/include/boost/archive/shared_ptr_helper.hpp b/win32/include/boost/archive/shared_ptr_helper.hpp new file mode 100755 index 000000000..f44880bd3 --- /dev/null +++ b/win32/include/boost/archive/shared_ptr_helper.hpp @@ -0,0 +1,157 @@ +#ifndef BOOST_ARCHIVE_SHARED_PTR_HELPER_HPP +#define BOOST_ARCHIVE_SHARED_PTR_HELPER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// shared_ptr_helper.hpp: serialization for boost shared pointer + +// (C) Copyright 2004 Robert Ramey and Martin Ecker +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include +#include // NULL + +#include +#include +#include +#include +#include + +#include + +namespace boost_132 { + template class shared_ptr; +} +namespace boost { + template class shared_ptr; + namespace serialization { + class extended_type_info; + template + inline void load( + Archive & ar, + boost::shared_ptr &t, + const unsigned int file_version + ); + } + +namespace archive{ +namespace detail { + +struct null_deleter { + void operator()(void const *) const {} +}; + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// a common class for holding various types of shared pointers + +class shared_ptr_helper { + typedef std::map > collection_type; + typedef collection_type::const_iterator iterator_type; + // list of shared_pointers create accessable by raw pointer. This + // is used to "match up" shared pointers loaded at different + // points in the archive. Note, we delay construction until + // it is actually used since this is by default included as + // a "mix-in" even if shared_ptr isn't used. + collection_type * m_pointers; + +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + template + friend inline void boost::serialization::load( + Archive & ar, + boost::shared_ptr &t, + const unsigned int file_version + ); +#endif + + // list of loaded pointers. This is used to be sure that the pointers + // stay around long enough to be "matched" with other pointers loaded + // by the same archive. These are created with a "null_deleter" so that + // when this list is destroyed - the underlaying raw pointers are not + // destroyed. This has to be done because the pointers are also held by + // new system which is disjoint from this set. This is implemented + // by a change in load_construct_data below. It makes this file suitable + // only for loading pointers into a 1.33 or later boost system. + std::list > * m_pointers_132; + + // return a void pointer to the most derived type + template + const void * object_identifier(T * t) const { + const boost::serialization::extended_type_info * true_type + = boost::serialization::type_info_implementation::type + ::get_const_instance().get_derived_extended_type_info(*t); + // note:if this exception is thrown, be sure that derived pointer + // is either registered or exported. + if(NULL == true_type) + boost::throw_exception( + boost::archive::archive_exception( + boost::archive::archive_exception::unregistered_class + ) + ); + const boost::serialization::extended_type_info * this_type + = & boost::serialization::type_info_implementation::type + ::get_const_instance(); + const void * vp = void_downcast( + *true_type, + *this_type, + static_cast(t) + ); + return vp; + } +public: + template + void reset(shared_ptr & s, T * r){ + if(NULL == r){ + s.reset(); + return; + } + // get pointer to the most derived object. This is effectively + // the object identifer + const void * od = object_identifier(r); + + if(NULL == m_pointers) + m_pointers = new collection_type; + + iterator_type it = m_pointers->find(od); + + if(it == m_pointers->end()){ + s.reset(r); + m_pointers->insert(collection_type::value_type(od,s)); + } + else{ + s = static_pointer_cast((*it).second); + } + } + void append(const boost_132::shared_ptr & t){ + if(NULL == m_pointers_132) + m_pointers_132 = new std::list >; + m_pointers_132->push_back(t); + } +public: + shared_ptr_helper() : + m_pointers(NULL), + m_pointers_132(NULL) + {} + ~shared_ptr_helper(){ + if(NULL != m_pointers) + delete m_pointers; + if(NULL != m_pointers_132) + delete m_pointers_132; + } +}; + +} // namespace detail +} // namespace serialization +} // namespace boost + +#endif // BOOST_ARCHIVE_SHARED_PTR_HELPER_HPP diff --git a/win32/include/boost/archive/text_iarchive.hpp b/win32/include/boost/archive/text_iarchive.hpp new file mode 100755 index 000000000..a71173da2 --- /dev/null +++ b/win32/include/boost/archive/text_iarchive.hpp @@ -0,0 +1,123 @@ +#ifndef BOOST_ARCHIVE_TEXT_IARCHIVE_HPP +#define BOOST_ARCHIVE_TEXT_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include + +#include +#include +#include +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +template +class text_iarchive_impl : + public basic_text_iprimitive, + public basic_text_iarchive +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + friend class detail::interface_iarchive; + friend class basic_text_iarchive; + friend class load_access; +protected: +#endif + template + void load(T & t){ + basic_text_iprimitive::load(t); + } + BOOST_ARCHIVE_DECL(void) + load(char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_ARCHIVE_DECL(void) + load(wchar_t * t); + #endif + BOOST_ARCHIVE_DECL(void) + load(std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_ARCHIVE_DECL(void) + load(std::wstring &ws); + #endif + // note: the following should not needed - but one compiler (vc 7.1) + // fails to compile one test (test_shared_ptr) without it !!! + // make this protected so it can be called from a derived archive + template + void load_override(T & t, BOOST_PFTO int){ + basic_text_iarchive::load_override(t, 0); + } + BOOST_ARCHIVE_DECL(void) + load_override(class_name_type & t, int); + BOOST_ARCHIVE_DECL(void) + init(); + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) + text_iarchive_impl(std::istream & is, unsigned int flags); + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) + ~text_iarchive_impl(){}; +}; + +// do not derive from the classes below. If you want to extend this functionality +// via inhertance, derived from text_iarchive_impl instead. This will +// preserve correct static polymorphism. + +// same as text_iarchive below - without the shared_ptr_helper +class naked_text_iarchive : + public text_iarchive_impl +{ +public: + naked_text_iarchive(std::istream & is, unsigned int flags = 0) : + text_iarchive_impl(is, flags) + {} + ~naked_text_iarchive(){} +}; + +} // namespace archive +} // namespace boost + +// note special treatment of shared_ptr. This type needs a special +// structure associated with every archive. We created a "mix-in" +// class to provide this functionality. Since shared_ptr holds a +// special esteem in the boost library - we included it here by default. +#include + +namespace boost { +namespace archive { + +class text_iarchive : + public text_iarchive_impl, + public detail::shared_ptr_helper +{ +public: + text_iarchive(std::istream & is, unsigned int flags = 0) : + text_iarchive_impl(is, flags) + {} + ~text_iarchive(){} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::text_iarchive) + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_TEXT_IARCHIVE_HPP diff --git a/win32/include/boost/archive/text_oarchive.hpp b/win32/include/boost/archive/text_oarchive.hpp new file mode 100755 index 000000000..c54bc5ac2 --- /dev/null +++ b/win32/include/boost/archive/text_oarchive.hpp @@ -0,0 +1,101 @@ +#ifndef BOOST_ARCHIVE_TEXT_OARCHIVE_HPP +#define BOOST_ARCHIVE_TEXT_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include // std::size_t + +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include +#include +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +template +class text_oarchive_impl : + /* protected ? */ public basic_text_oprimitive, + public basic_text_oarchive +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + friend class detail::interface_oarchive; + friend class basic_text_oarchive; + friend class save_access; +protected: +#endif + template + void save(const T & t){ + this->newtoken(); + basic_text_oprimitive::save(t); + } + BOOST_ARCHIVE_DECL(void) + save(const char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_ARCHIVE_DECL(void) + save(const wchar_t * t); + #endif + BOOST_ARCHIVE_DECL(void) + save(const std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_ARCHIVE_DECL(void) + save(const std::wstring &ws); + #endif + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) + text_oarchive_impl(std::ostream & os, unsigned int flags); + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) + ~text_oarchive_impl(){}; +public: + BOOST_ARCHIVE_DECL(void) + save_binary(const void *address, std::size_t count); +}; + +// do not derive from this class. If you want to extend this functionality +// via inhertance, derived from text_oarchive_impl instead. This will +// preserve correct static polymorphism. +class text_oarchive : + public text_oarchive_impl +{ +public: + + text_oarchive(std::ostream & os, unsigned int flags = 0) : + text_oarchive_impl(os, flags) + {} + ~text_oarchive(){} +}; + +typedef text_oarchive naked_text_oarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::text_oarchive) + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_TEXT_OARCHIVE_HPP diff --git a/win32/include/boost/archive/text_wiarchive.hpp b/win32/include/boost/archive/text_wiarchive.hpp new file mode 100755 index 000000000..a1f138368 --- /dev/null +++ b/win32/include/boost/archive/text_wiarchive.hpp @@ -0,0 +1,122 @@ +#ifndef BOOST_ARCHIVE_TEXT_WIARCHIVE_HPP +#define BOOST_ARCHIVE_TEXT_WIARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_wiarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include + +#include +#include +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +template +class text_wiarchive_impl : + public basic_text_iprimitive, + public basic_text_iarchive +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + friend class detail::interface_iarchive; + friend class basic_text_iarchive; + friend class load_access; +protected: +#endif + template + void load(T & t){ + basic_text_iprimitive::load(t); + } + BOOST_WARCHIVE_DECL(void) + load(char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_WARCHIVE_DECL(void) + load(wchar_t * t); + #endif + BOOST_WARCHIVE_DECL(void) + load(std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_WARCHIVE_DECL(void) + load(std::wstring &ws); + #endif + // note: the following should not needed - but one compiler (vc 7.1) + // fails to compile one test (test_shared_ptr) without it !!! + template + void load_override(T & t, BOOST_PFTO int){ + basic_text_iarchive::load_override(t, 0); + } + BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) + text_wiarchive_impl(std::wistream & is, unsigned int flags); + ~text_wiarchive_impl(){}; +}; + +// do not derive from the classes below. If you want to extend this functionality +// via inhertance, derived from text_iarchive_impl instead. This will +// preserve correct static polymorphism. + +// same as text_wiarchive below - without the shared_ptr_helper +class naked_text_wiarchive : + public text_wiarchive_impl +{ +public: + naked_text_wiarchive(std::wistream & is, unsigned int flags = 0) : + text_wiarchive_impl(is, flags) + {} + ~naked_text_wiarchive(){} +}; + +} // namespace archive +} // namespace boost + +// note special treatment of shared_ptr. This type needs a special +// structure associated with every archive. We created a "mix-in" +// class to provide this functionality. Since shared_ptr holds a +// special esteem in the boost library - we included it here by default. +#include + +namespace boost { +namespace archive { + +class text_wiarchive : + public text_wiarchive_impl, + public detail::shared_ptr_helper +{ +public: + text_wiarchive(std::wistream & is, unsigned int flags = 0) : + text_wiarchive_impl(is, flags) + {} + ~text_wiarchive(){} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::text_wiarchive) + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_TEXT_WIARCHIVE_HPP diff --git a/win32/include/boost/archive/text_woarchive.hpp b/win32/include/boost/archive/text_woarchive.hpp new file mode 100755 index 000000000..10e91201e --- /dev/null +++ b/win32/include/boost/archive/text_woarchive.hpp @@ -0,0 +1,128 @@ +#ifndef BOOST_ARCHIVE_TEXT_WOARCHIVE_HPP +#define BOOST_ARCHIVE_TEXT_WOARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_woarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include + +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include +#include // size_t + +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include +#include +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +template +class text_woarchive_impl : + public basic_text_oprimitive, + public basic_text_oarchive +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + friend class detail::interface_oarchive; + friend class basic_text_oarchive; + friend class save_access; +protected: +#endif + template + void save(const T & t){ + this->newtoken(); + basic_text_oprimitive::save(t); + } + BOOST_WARCHIVE_DECL(void) + save(const char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_WARCHIVE_DECL(void) + save(const wchar_t * t); + #endif + BOOST_WARCHIVE_DECL(void) + save(const std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_WARCHIVE_DECL(void) + save(const std::wstring &ws); + #endif + text_woarchive_impl(std::wostream & os, unsigned int flags) : + basic_text_oprimitive( + os, + 0 != (flags & no_codecvt) + ), + basic_text_oarchive(flags) + { + if(0 == (flags & no_header)) + basic_text_oarchive::init(); + } +public: + void save_binary(const void *address, std::size_t count){ + put(L'\n'); + this->end_preamble(); + #if ! defined(__MWERKS__) + this->basic_text_oprimitive::save_binary( + #else + this->basic_text_oprimitive::save_binary( + #endif + address, + count + ); + put(L'\n'); + this->delimiter = this->none; + } + +}; + +// we use the following because we can't use +// typedef text_oarchive_impl > text_oarchive; + +// do not derive from this class. If you want to extend this functionality +// via inhertance, derived from text_oarchive_impl instead. This will +// preserve correct static polymorphism. +class text_woarchive : + public text_woarchive_impl +{ +public: + text_woarchive(std::wostream & os, unsigned int flags = 0) : + text_woarchive_impl(os, flags) + {} + ~text_woarchive(){} +}; + +typedef text_woarchive naked_text_woarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::text_woarchive) + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_TEXT_WOARCHIVE_HPP diff --git a/win32/include/boost/archive/tmpdir.hpp b/win32/include/boost/archive/tmpdir.hpp new file mode 100755 index 000000000..3d5920457 --- /dev/null +++ b/win32/include/boost/archive/tmpdir.hpp @@ -0,0 +1,50 @@ +#ifndef BOOST_ARCHIVE_TMPDIR_HPP +#define BOOST_ARCHIVE_TMPDIR_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// tmpdir.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include // getenv +#include // NULL +#include + +#include +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { + using ::getenv; +} +#endif + +namespace boost { +namespace archive { + +inline char * tmpdir(){ + char *dirname; + dirname = std::getenv("TMP"); + if(NULL == dirname) + dirname = std::getenv("TMPDIR"); + if(NULL == dirname) + dirname = std::getenv("TEMP"); + if(NULL == dirname){ + //assert(false); // no temp directory found + dirname = "."; + } + return dirname; +} + +} // archive +} // boost + +#endif // BOOST_ARCHIVE_TMPDIR_HPP diff --git a/win32/include/boost/archive/wcslen.hpp b/win32/include/boost/archive/wcslen.hpp new file mode 100755 index 000000000..88c4ba280 --- /dev/null +++ b/win32/include/boost/archive/wcslen.hpp @@ -0,0 +1,56 @@ +#ifndef BOOST_ARCHIVE_WCSLEN_HPP +#define BOOST_ARCHIVE_WCSLEN_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// wcslen.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include // size_t +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#ifndef BOOST_NO_CWCHAR + +// a couple of libraries which include wchar_t don't include +// wcslen + +#if defined(BOOST_DINKUMWARE_STDLIB) && BOOST_DINKUMWARE_STDLIB < 306 \ +|| defined(__LIBCOMO__) + +namespace std { +inline std::size_t wcslen(const wchar_t * ws) +{ + const wchar_t * eows = ws; + while(* eows != 0) + ++eows; + return eows - ws; +} +} // namespace std + +#else + +#include +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ using ::wcslen; } +#endif + +#endif // wcslen + +#endif //BOOST_NO_CWCHAR + +#endif //BOOST_ARCHIVE_WCSLEN_HPP diff --git a/win32/include/boost/archive/xml_archive_exception.hpp b/win32/include/boost/archive/xml_archive_exception.hpp new file mode 100755 index 000000000..81d7ab0b6 --- /dev/null +++ b/win32/include/boost/archive/xml_archive_exception.hpp @@ -0,0 +1,66 @@ +#ifndef BOOST_ARCHIVE_XML_ARCHIVE_EXCEPTION_HPP +#define BOOST_ARCHIVE_XML_ARCHIVE_EXCEPTION_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_archive_exception.hpp: + +// (C) Copyright 2007 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#include + +#include + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// exceptions thrown by xml archives +// +class xml_archive_exception : + public virtual archive_exception +{ +public: + typedef enum { + xml_archive_parsing_error, // see save_register + xml_archive_tag_mismatch, + xml_archive_tag_name_error + } exception_code; + exception_code code; + xml_archive_exception(exception_code c) + {} + virtual const char *what( ) const throw( ) + { + const char *msg; + switch(code){ + case xml_archive_parsing_error: + msg = "unrecognized XML syntax"; + break; + case xml_archive_tag_mismatch: + msg = "XML start/end tag mismatch"; + break; + case xml_archive_tag_name_error: + msg = "Invalid XML tag name"; + break; + default: + msg = archive_exception::what(); + break; + } + return msg; + } +}; + +}// namespace archive +}// namespace boost + +#endif //BOOST_XML_ARCHIVE_ARCHIVE_EXCEPTION_HPP diff --git a/win32/include/boost/archive/xml_iarchive.hpp b/win32/include/boost/archive/xml_iarchive.hpp new file mode 100755 index 000000000..a44ee8e9e --- /dev/null +++ b/win32/include/boost/archive/xml_iarchive.hpp @@ -0,0 +1,132 @@ +#ifndef BOOST_ARCHIVE_XML_IARCHIVE_HPP +#define BOOST_ARCHIVE_XML_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include + +//#include +#include +#include +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +template +class basic_xml_grammar; +typedef basic_xml_grammar xml_grammar; + +template +class xml_iarchive_impl : + public basic_text_iprimitive, + public basic_xml_iarchive +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + friend class detail::interface_iarchive; + friend class basic_xml_iarchive; + friend class load_access; +protected: +#endif + // instances of micro xml parser to parse start preambles + // scoped_ptr doesn't play nice with borland - so use a naked pointer + // scoped_ptr gimpl; + xml_grammar *gimpl; + + std::istream & get_is(){ + return is; + } + template + void load(T & t){ + basic_text_iprimitive::load(t); + } + BOOST_ARCHIVE_DECL(void) + load(char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_ARCHIVE_DECL(void) + load(wchar_t * t); + #endif + BOOST_ARCHIVE_DECL(void) + load(std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_ARCHIVE_DECL(void) + load(std::wstring &ws); + #endif + template + void load_override(T & t, BOOST_PFTO int){ + basic_xml_iarchive::load_override(t, 0); + } + BOOST_ARCHIVE_DECL(void) + load_override(class_name_type & t, int); + BOOST_ARCHIVE_DECL(void) + init(); + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) + xml_iarchive_impl(std::istream & is, unsigned int flags); + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) + ~xml_iarchive_impl(); +}; + +// do not derive from the classes below. If you want to extend this functionality +// via inhertance, derived from text_iarchive_impl instead. This will +// preserve correct static polymorphism. + +// same as xml_iarchive below - without the shared_ptr_helper +class naked_xml_iarchive : + public xml_iarchive_impl +{ +public: + naked_xml_iarchive(std::istream & is, unsigned int flags = 0) : + xml_iarchive_impl(is, flags) + {} + ~naked_xml_iarchive(){} +}; + +} // namespace archive +} // namespace boost + +// note special treatment of shared_ptr. This type needs a special +// structure associated with every archive. We created a "mix-in" +// class to provide this functionality. Since shared_ptr holds a +// special esteem in the boost library - we included it here by default. +#include + +namespace boost { +namespace archive { + +class xml_iarchive : + public xml_iarchive_impl, + public detail::shared_ptr_helper +{ +public: + xml_iarchive(std::istream & is, unsigned int flags = 0) : + xml_iarchive_impl(is, flags) + {} + ~xml_iarchive(){}; +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::xml_iarchive) + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_XML_IARCHIVE_HPP diff --git a/win32/include/boost/archive/xml_oarchive.hpp b/win32/include/boost/archive/xml_oarchive.hpp new file mode 100755 index 000000000..fa067d456 --- /dev/null +++ b/win32/include/boost/archive/xml_oarchive.hpp @@ -0,0 +1,114 @@ +#ifndef BOOST_ARCHIVE_XML_OARCHIVE_HPP +#define BOOST_ARCHIVE_XML_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include + +#include // size_t +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include +#include +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +template +class xml_oarchive_impl : + public basic_text_oprimitive, + public basic_xml_oarchive +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + friend class detail::interface_oarchive; + friend class basic_xml_oarchive; + friend class save_access; +protected: +#endif + //void end_preamble(){ + // basic_xml_oarchive::end_preamble(); + //} + template + void save(const T & t){ + basic_text_oprimitive::save(t); + } + BOOST_ARCHIVE_DECL(void) + save(const char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_ARCHIVE_DECL(void) + save(const wchar_t * t); + #endif + BOOST_ARCHIVE_DECL(void) + save(const std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_ARCHIVE_DECL(void) + save(const std::wstring &ws); + #endif + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) + xml_oarchive_impl(std::ostream & os, unsigned int flags); + ~xml_oarchive_impl(){} +public: + void save_binary(const void *address, std::size_t count){ + this->end_preamble(); + #if ! defined(__MWERKS__) + this->basic_text_oprimitive::save_binary( + #else + this->basic_text_oprimitive::save_binary( + #endif + address, + count + ); + this->indent_next = true; + } +}; + +// we use the following because we can't use +// typedef xml_oarchive_impl > xml_oarchive; + +// do not derive from this class. If you want to extend this functionality +// via inhertance, derived from xml_oarchive_impl instead. This will +// preserve correct static polymorphism. +class xml_oarchive : + public xml_oarchive_impl +{ +public: + xml_oarchive(std::ostream & os, unsigned int flags = 0) : + xml_oarchive_impl(os, flags) + {} + ~xml_oarchive(){} +}; + +typedef xml_oarchive naked_xml_oarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::xml_oarchive) + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_XML_OARCHIVE_HPP diff --git a/win32/include/boost/archive/xml_wiarchive.hpp b/win32/include/boost/archive/xml_wiarchive.hpp new file mode 100755 index 000000000..d4001e180 --- /dev/null +++ b/win32/include/boost/archive/xml_wiarchive.hpp @@ -0,0 +1,137 @@ +#ifndef BOOST_ARCHIVE_XML_WIARCHIVE_HPP +#define BOOST_ARCHIVE_XML_WIARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_wiarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include + +//#include +#include +#include +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +template +class basic_xml_grammar; +typedef basic_xml_grammar xml_wgrammar; + +template +class xml_wiarchive_impl : + public basic_text_iprimitive, + public basic_xml_iarchive +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + friend class detail::interface_iarchive; + friend class basic_xml_iarchive; + friend class load_access; +protected: +#endif + // instances of micro xml parser to parse start preambles + // scoped_ptr doesn't play nice with borland - so use a naked pointer + // scoped_ptr gimpl; + xml_wgrammar *gimpl; + std::wistream & get_is(){ + return is; + } + template + void load(T & t){ + basic_text_iprimitive::load(t); + } + BOOST_WARCHIVE_DECL(void) + load(char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_WARCHIVE_DECL(void) + load(wchar_t * t); + #endif + BOOST_WARCHIVE_DECL(void) + load(std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_WARCHIVE_DECL(void) + load(std::wstring &ws); + #endif + template + void load_override(T & t, BOOST_PFTO int){ + basic_xml_iarchive::load_override(t, 0); + } + BOOST_WARCHIVE_DECL(void) + load_override(class_name_type & t, int); + BOOST_WARCHIVE_DECL(void) + init(); + BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) + xml_wiarchive_impl(std::wistream & is, unsigned int flags) ; + BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~xml_wiarchive_impl(); +}; + +// do not derive from the classes below. If you want to extend this functionality +// via inhertance, derived from xml_wiarchive_impl instead. This will +// preserve correct static polymorphism. + +// same as xml_wiarchive below - without the shared_ptr_helper +class naked_xml_wiarchive : + public xml_wiarchive_impl +{ +public: + naked_xml_wiarchive(std::wistream & is, unsigned int flags = 0) : + xml_wiarchive_impl(is, flags) + {} + ~naked_xml_wiarchive(){} +}; + +} // namespace archive +} // namespace boost + +// note special treatment of shared_ptr. This type needs a special +// structure associated with every archive. We created a "mix-in" +// class to provide this functionality. Since shared_ptr holds a +// special esteem in the boost library - we included it here by default. +#include + +namespace boost { +namespace archive { + +class xml_wiarchive : + public xml_wiarchive_impl, + public detail::shared_ptr_helper +{ +public: + xml_wiarchive(std::wistream & is, unsigned int flags = 0) : + xml_wiarchive_impl(is, flags) + {} + ~xml_wiarchive(){} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::xml_wiarchive) + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_XML_WIARCHIVE_HPP diff --git a/win32/include/boost/archive/xml_woarchive.hpp b/win32/include/boost/archive/xml_woarchive.hpp new file mode 100755 index 000000000..9cd48d9a9 --- /dev/null +++ b/win32/include/boost/archive/xml_woarchive.hpp @@ -0,0 +1,129 @@ +#ifndef BOOST_ARCHIVE_XML_WOARCHIVE_HPP +#define BOOST_ARCHIVE_XML_WOARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_woarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include // size_t +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include + +#include +#include +#include + +#include // must be the last header + +namespace boost { +namespace archive { + +#if 0 +BOOST_WARCHIVE_DECL(std::wostream &) +operator<<(std::wostream &os, const char *t); + +BOOST_WARCHIVE_DECL(std::wostream &) +operator<<(std::wostream &os, const char t); +#endif + +template +class xml_woarchive_impl : + public basic_text_oprimitive, + public basic_xml_oarchive +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + friend class detail::interface_oarchive; + friend class basic_xml_oarchive; + friend class save_access; +protected: +#endif + //void end_preamble(){ + // basic_xml_oarchive::end_preamble(); + //} + template + void + save(const T & t){ + basic_text_oprimitive::save(t); + } + BOOST_WARCHIVE_DECL(void) + save(const char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_WARCHIVE_DECL(void) + save(const wchar_t * t); + #endif + BOOST_WARCHIVE_DECL(void) + save(const std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_WARCHIVE_DECL(void) + save(const std::wstring &ws); + #endif + BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) + xml_woarchive_impl(std::wostream & os, unsigned int flags); + ~xml_woarchive_impl(){} +public: + void + save_binary(const void *address, std::size_t count){ + this->end_preamble(); + #if ! defined(__MWERKS__) + this->basic_text_oprimitive::save_binary( + #else + this->basic_text_oprimitive::save_binary( + #endif + address, + count + ); + this->indent_next = true; + } +}; + +// we use the following because we can't use +// typedef xml_woarchive_impl > xml_woarchive; + +// do not derive from this class. If you want to extend this functionality +// via inhertance, derived from xml_woarchive_impl instead. This will +// preserve correct static polymorphism. +class xml_woarchive : + public xml_woarchive_impl +{ +public: + xml_woarchive(std::wostream & os, unsigned int flags = 0) : + xml_woarchive_impl(os, flags) + {} + ~xml_woarchive(){} +}; + +typedef xml_woarchive naked_xml_woarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::xml_woarchive) + +#include // pops abi_suffix.hpp pragmas + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_XML_OARCHIVE_HPP diff --git a/win32/include/boost/array.hpp b/win32/include/boost/array.hpp new file mode 100755 index 000000000..3239776c8 --- /dev/null +++ b/win32/include/boost/array.hpp @@ -0,0 +1,321 @@ +/* The following code declares class array, + * an STL container (as wrapper) for arrays of constant size. + * + * See + * http://www.boost.org/libs/array/ + * for documentation. + * + * The original author site is at: http://www.josuttis.com/ + * + * (C) Copyright Nicolai M. Josuttis 2001. + * + * 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) + * + * 29 Jan 2004 - c_array() added, BOOST_NO_PRIVATE_IN_AGGREGATE removed (Nico Josuttis) + * 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries. + * 05 Aug 2001 - minor update (Nico Josuttis) + * 20 Jan 2001 - STLport fix (Beman Dawes) + * 29 Sep 2000 - Initial Revision (Nico Josuttis) + * + * Jan 29, 2004 + */ +#ifndef BOOST_ARRAY_HPP +#define BOOST_ARRAY_HPP + +#include +#include +#include + +// Handles broken standard libraries better than +#include +#include +#include + +// FIXES for broken compilers +#include + + +namespace boost { + + template + class array { + public: + T elems[N]; // fixed-size array of elements of type T + + public: + // type definitions + typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; + typedef T& reference; + typedef const T& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // iterator support + iterator begin() { return elems; } + const_iterator begin() const { return elems; } + iterator end() { return elems+N; } + const_iterator end() const { return elems+N; } + + // reverse iterator support +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; +#elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310) + // workaround for broken reverse_iterator in VC7 + typedef std::reverse_iterator > reverse_iterator; + typedef std::reverse_iterator > const_reverse_iterator; +#else + // workaround for broken reverse_iterator implementations + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; +#endif + + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + // operator[] + reference operator[](size_type i) + { + BOOST_ASSERT( i < N && "out of range" ); + return elems[i]; + } + + const_reference operator[](size_type i) const + { + BOOST_ASSERT( i < N && "out of range" ); + return elems[i]; + } + + // at() with range check + reference at(size_type i) { rangecheck(i); return elems[i]; } + const_reference at(size_type i) const { rangecheck(i); return elems[i]; } + + // front() and back() + reference front() + { + return elems[0]; + } + + const_reference front() const + { + return elems[0]; + } + + reference back() + { + return elems[N-1]; + } + + const_reference back() const + { + return elems[N-1]; + } + + // size is constant + static size_type size() { return N; } + static bool empty() { return false; } + static size_type max_size() { return N; } + enum { static_size = N }; + + // swap (note: linear complexity) + void swap (array& y) { + std::swap_ranges(begin(),end(),y.begin()); + } + + // direct access to data (read-only) + const T* data() const { return elems; } + T* data() { return elems; } + + // use array as C array (direct read/write access to data) + T* c_array() { return elems; } + + // assignment with type conversion + template + array& operator= (const array& rhs) { + std::copy(rhs.begin(),rhs.end(), begin()); + return *this; + } + + // assign one value to all elements + void assign (const T& value) + { + std::fill_n(begin(),size(),value); + } + + // check range (may be private because it is static) + static void rangecheck (size_type i) { + if (i >= size()) { + throw std::out_of_range("array<>: index out of range"); + } + } + + }; + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + template< class T > + class array< T, 0 > { + + public: + // type definitions + typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; + typedef T& reference; + typedef const T& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // iterator support + iterator begin() { return iterator( reinterpret_cast< T * >( this ) ); } + const_iterator begin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); } + iterator end() { return begin(); } + const_iterator end() const { return begin(); } + + // reverse iterator support +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; +#elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310) + // workaround for broken reverse_iterator in VC7 + typedef std::reverse_iterator > reverse_iterator; + typedef std::reverse_iterator > const_reverse_iterator; +#else + // workaround for broken reverse_iterator implementations + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; +#endif + + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + // operator[] + reference operator[](size_type i) + { + return failed_rangecheck(); + } + + const_reference operator[](size_type i) const + { + return failed_rangecheck(); + } + + // at() with range check + reference at(size_type i) { return failed_rangecheck(); } + const_reference at(size_type i) const { return failed_rangecheck(); } + + // front() and back() + reference front() + { + return failed_rangecheck(); + } + + const_reference front() const + { + return failed_rangecheck(); + } + + reference back() + { + return failed_rangecheck(); + } + + const_reference back() const + { + return failed_rangecheck(); + } + + // size is constant + static size_type size() { return 0; } + static bool empty() { return true; } + static size_type max_size() { return 0; } + enum { static_size = 0 }; + + void swap (array& y) { + } + + // direct access to data (read-only) + const T* data() const { return 0; } + T* data() { return 0; } + + // use array as C array (direct read/write access to data) + T* c_array() { return 0; } + + // assignment with type conversion + template + array& operator= (const array& ) { + return *this; + } + + // assign one value to all elements + void assign (const T& ) { } + + // check range (may be private because it is static) + static reference failed_rangecheck () { + std::out_of_range e("attempt to access element of an empty array"); + boost::throw_exception(e); + // + // We need to return something here to keep + // some compilers happy: however we will never + // actually get here.... + // + static T placeholder; + return placeholder; + } + }; +#endif + + // comparisons + template + bool operator== (const array& x, const array& y) { + return std::equal(x.begin(), x.end(), y.begin()); + } + template + bool operator< (const array& x, const array& y) { + return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end()); + } + template + bool operator!= (const array& x, const array& y) { + return !(x==y); + } + template + bool operator> (const array& x, const array& y) { + return y + bool operator<= (const array& x, const array& y) { + return !(y + bool operator>= (const array& x, const array& y) { + return !(x + inline void swap (array& x, array& y) { + x.swap(y); + } + +} /* namespace boost */ + +#endif /*BOOST_ARRAY_HPP*/ diff --git a/win32/include/boost/asio.hpp b/win32/include/boost/asio.hpp new file mode 100755 index 000000000..4e13af6b9 --- /dev/null +++ b/win32/include/boost/asio.hpp @@ -0,0 +1,99 @@ +// +// asio.hpp +// ~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// 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) +// +// See www.boost.org/libs/asio for documentation. +// + +#ifndef BOOST_ASIO_HPP +#define BOOST_ASIO_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // BOOST_ASIO_HPP diff --git a/win32/include/boost/asio/basic_datagram_socket.hpp b/win32/include/boost/asio/basic_datagram_socket.hpp new file mode 100755 index 000000000..f65765ebc --- /dev/null +++ b/win32/include/boost/asio/basic_datagram_socket.hpp @@ -0,0 +1,805 @@ +// +// basic_datagram_socket.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP +#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Provides datagram-oriented socket functionality. +/** + * The basic_datagram_socket class template provides asynchronous and blocking + * datagram-oriented socket functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template > +class basic_datagram_socket + : public basic_socket +{ +public: + /// The native representation of a socket. + typedef typename DatagramSocketService::native_type native_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct a basic_datagram_socket without opening it. + /** + * This constructor creates a datagram socket without opening it. The open() + * function must be called before data can be sent or received on the socket. + * + * @param io_service The io_service object that the datagram socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + */ + explicit basic_datagram_socket(boost::asio::io_service& io_service) + : basic_socket(io_service) + { + } + + /// Construct and open a basic_datagram_socket. + /** + * This constructor creates and opens a datagram socket. + * + * @param io_service The io_service object that the datagram socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_datagram_socket(boost::asio::io_service& io_service, + const protocol_type& protocol) + : basic_socket(io_service, protocol) + { + } + + /// Construct a basic_datagram_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a datagram socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param io_service The io_service object that the datagram socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param endpoint An endpoint on the local machine to which the datagram + * socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_datagram_socket(boost::asio::io_service& io_service, + const endpoint_type& endpoint) + : basic_socket(io_service, endpoint) + { + } + + /// Construct a basic_datagram_socket on an existing native socket. + /** + * This constructor creates a datagram socket object to hold an existing + * native socket. + * + * @param io_service The io_service object that the datagram socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_datagram_socket(boost::asio::io_service& io_service, + const protocol_type& protocol, const native_type& native_socket) + : basic_socket( + io_service, protocol, native_socket) + { + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the datagram socket. The function + * call will block until the data has been sent successfully or an error + * occurs. + * + * @param buffers One ore more data buffers to be sent on the socket. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected datagram socket. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code socket.send(boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t send(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.send(this->implementation, buffers, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the datagram socket. The function + * call will block until the data has been sent successfully or an error + * occurs. + * + * @param buffers One ore more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected datagram socket. + */ + template + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->service.send( + this->implementation, buffers, flags, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the datagram socket. The function + * call will block until the data has been sent successfully or an error + * occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected datagram socket. + */ + template + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->service.send(this->implementation, buffers, flags, ec); + } + + /// Start an asynchronous send on a connected socket. + /** + * This function is used to send data on the datagram socket. The function + * call will block until the data has been sent successfully or an error + * occurs. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_send operation can only be used with a connected socket. + * Use the async_send_to function to send data on an unconnected datagram + * socket. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_send(const ConstBufferSequence& buffers, WriteHandler handler) + { + this->service.async_send(this->implementation, buffers, 0, handler); + } + + /// Start an asynchronous send on a connected socket. + /** + * This function is used to send data on the datagram socket. The function + * call will block until the data has been sent successfully or an error + * occurs. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_send operation can only be used with a connected socket. + * Use the async_send_to function to send data on an unconnected datagram + * socket. + */ + template + void async_send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, WriteHandler handler) + { + this->service.async_send(this->implementation, buffers, flags, handler); + } + + /// Send a datagram to the specified endpoint. + /** + * This function is used to send a datagram to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::ip::udp::endpoint destination( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.send_to(boost::asio::buffer(data, size), destination); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination) + { + boost::system::error_code ec; + std::size_t s = this->service.send_to( + this->implementation, buffers, destination, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Send a datagram to the specified endpoint. + /** + * This function is used to send a datagram to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->service.send_to( + this->implementation, buffers, destination, flags, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Send a datagram to the specified endpoint. + /** + * This function is used to send a datagram to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + boost::system::error_code& ec) + { + return this->service.send_to(this->implementation, + buffers, destination, flags, ec); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send a datagram to the specified + * remote endpoint. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param destination The remote endpoint to which the data will be sent. + * Copies will be made of the endpoint as required. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::ip::udp::endpoint destination( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.async_send_to( + * boost::asio::buffer(data, size), destination, handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, WriteHandler handler) + { + this->service.async_send_to(this->implementation, buffers, destination, 0, + handler); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send a datagram to the specified + * remote endpoint. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param destination The remote endpoint to which the data will be sent. + * Copies will be made of the endpoint as required. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template + void async_send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + WriteHandler handler) + { + this->service.async_send_to(this->implementation, buffers, destination, + flags, handler); + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the datagram socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected datagram + * socket. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code socket.receive(boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t receive(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.receive( + this->implementation, buffers, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the datagram socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected datagram + * socket. + */ + template + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->service.receive( + this->implementation, buffers, flags, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the datagram socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected datagram + * socket. + */ + template + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->service.receive(this->implementation, buffers, flags, ec); + } + + /// Start an asynchronous receive on a connected socket. + /** + * This function is used to asynchronously receive data from the datagram + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_receive operation can only be used with a connected socket. + * Use the async_receive_from function to receive data on an unconnected + * datagram socket. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_receive(const MutableBufferSequence& buffers, ReadHandler handler) + { + this->service.async_receive(this->implementation, buffers, 0, handler); + } + + /// Start an asynchronous receive on a connected socket. + /** + * This function is used to asynchronously receive data from the datagram + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_receive operation can only be used with a connected socket. + * Use the async_receive_from function to receive data on an unconnected + * datagram socket. + */ + template + void async_receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, ReadHandler handler) + { + this->service.async_receive(this->implementation, buffers, flags, handler); + } + + /// Receive a datagram with the endpoint of the sender. + /** + * This function is used to receive a datagram. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * boost::asio::ip::udp::endpoint sender_endpoint; + * socket.receive_from( + * boost::asio::buffer(data, size), sender_endpoint); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint) + { + boost::system::error_code ec; + std::size_t s = this->service.receive_from( + this->implementation, buffers, sender_endpoint, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Receive a datagram with the endpoint of the sender. + /** + * This function is used to receive a datagram. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->service.receive_from( + this->implementation, buffers, sender_endpoint, flags, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Receive a datagram with the endpoint of the sender. + /** + * This function is used to receive a datagram. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + boost::system::error_code& ec) + { + return this->service.receive_from(this->implementation, buffers, + sender_endpoint, flags, ec); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive a datagram. The function + * call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. Ownership of the sender_endpoint object + * is retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code socket.async_receive_from( + * boost::asio::buffer(data, size), 0, sender_endpoint, handler); @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, ReadHandler handler) + { + this->service.async_receive_from(this->implementation, buffers, + sender_endpoint, 0, handler); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive a datagram. The function + * call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. Ownership of the sender_endpoint object + * is retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template + void async_receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + ReadHandler handler) + { + this->service.async_receive_from(this->implementation, buffers, + sender_endpoint, flags, handler); + } +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP diff --git a/win32/include/boost/asio/basic_deadline_timer.hpp b/win32/include/boost/asio/basic_deadline_timer.hpp new file mode 100755 index 000000000..3282f66d0 --- /dev/null +++ b/win32/include/boost/asio/basic_deadline_timer.hpp @@ -0,0 +1,383 @@ +// +// basic_deadline_timer.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_DEADLINE_TIMER_HPP +#define BOOST_ASIO_BASIC_DEADLINE_TIMER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Provides waitable timer functionality. +/** + * The basic_deadline_timer class template provides the ability to perform a + * blocking or asynchronous wait for a timer to expire. + * + * Most applications will use the boost::asio::deadline_timer typedef. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Examples + * Performing a blocking wait: + * @code + * // Construct a timer without setting an expiry time. + * boost::asio::deadline_timer timer(io_service); + * + * // Set an expiry time relative to now. + * timer.expires_from_now(boost::posix_time::seconds(5)); + * + * // Wait for the timer to expire. + * timer.wait(); + * @endcode + * + * @par + * Performing an asynchronous wait: + * @code + * void handler(const boost::system::error_code& error) + * { + * if (!error) + * { + * // Timer expired. + * } + * } + * + * ... + * + * // Construct a timer with an absolute expiry time. + * boost::asio::deadline_timer timer(io_service, + * boost::posix_time::time_from_string("2005-12-07 23:59:59.000")); + * + * // Start an asynchronous wait. + * timer.async_wait(handler); + * @endcode + * + * @par Changing an active deadline_timer's expiry time + * + * Changing the expiry time of a timer while there are pending asynchronous + * waits causes those wait operations to be cancelled. To ensure that the action + * associated with the timer is performed only once, use something like this: + * used: + * + * @code + * void on_some_event() + * { + * if (my_timer.expires_from_now(seconds(5)) > 0) + * { + * // We managed to cancel the timer. Start new asynchronous wait. + * my_timer.async_wait(on_timeout); + * } + * else + * { + * // Too late, timer has already expired! + * } + * } + * + * void on_timeout(const boost::system::error_code& e) + * { + * if (e != boost::asio::error::operation_aborted) + * { + * // Timer was not cancelled, take necessary action. + * } + * } + * @endcode + * + * @li The boost::asio::basic_deadline_timer::expires_from_now() function + * cancels any pending asynchronous waits, and returns the number of + * asynchronous waits that were cancelled. If it returns 0 then you were too + * late and the wait handler has already been executed, or will soon be + * executed. If it returns 1 then the wait handler was successfully cancelled. + * + * @li If a wait handler is cancelled, the boost::system::error_code passed to + * it contains the value boost::asio::error::operation_aborted. + */ +template , + typename TimerService = deadline_timer_service > +class basic_deadline_timer + : public basic_io_object +{ +public: + /// The time traits type. + typedef TimeTraits traits_type; + + /// The time type. + typedef typename traits_type::time_type time_type; + + /// The duration type. + typedef typename traits_type::duration_type duration_type; + + /// Constructor. + /** + * This constructor creates a timer without setting an expiry time. The + * expires_at() or expires_from_now() functions must be called to set an + * expiry time before the timer can be waited on. + * + * @param io_service The io_service object that the timer will use to dispatch + * handlers for any asynchronous operations performed on the timer. + */ + explicit basic_deadline_timer(boost::asio::io_service& io_service) + : basic_io_object(io_service) + { + } + + /// Constructor to set a particular expiry time as an absolute time. + /** + * This constructor creates a timer and sets the expiry time. + * + * @param io_service The io_service object that the timer will use to dispatch + * handlers for any asynchronous operations performed on the timer. + * + * @param expiry_time The expiry time to be used for the timer, expressed + * as an absolute time. + */ + basic_deadline_timer(boost::asio::io_service& io_service, + const time_type& expiry_time) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.expires_at(this->implementation, expiry_time, ec); + boost::asio::detail::throw_error(ec); + } + + /// Constructor to set a particular expiry time relative to now. + /** + * This constructor creates a timer and sets the expiry time. + * + * @param io_service The io_service object that the timer will use to dispatch + * handlers for any asynchronous operations performed on the timer. + * + * @param expiry_time The expiry time to be used for the timer, relative to + * now. + */ + basic_deadline_timer(boost::asio::io_service& io_service, + const duration_type& expiry_time) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.expires_from_now(this->implementation, expiry_time, ec); + boost::asio::detail::throw_error(ec); + } + + /// Cancel any asynchronous operations that are waiting on the timer. + /** + * This function forces the completion of any pending asynchronous wait + * operations against the timer. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * Cancelling the timer does not change the expiry time. + * + * @return The number of asynchronous operations that were cancelled. + * + * @throws boost::system::system_error Thrown on failure. + */ + std::size_t cancel() + { + boost::system::error_code ec; + std::size_t s = this->service.cancel(this->implementation, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Cancel any asynchronous operations that are waiting on the timer. + /** + * This function forces the completion of any pending asynchronous wait + * operations against the timer. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * Cancelling the timer does not change the expiry time. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of asynchronous operations that were cancelled. + */ + std::size_t cancel(boost::system::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + + /// Get the timer's expiry time as an absolute time. + /** + * This function may be used to obtain the timer's current expiry time. + * Whether the timer has expired or not does not affect this value. + */ + time_type expires_at() const + { + return this->service.expires_at(this->implementation); + } + + /// Set the timer's expiry time as an absolute time. + /** + * This function sets the expiry time. Any pending asynchronous wait + * operations will be cancelled. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * @param expiry_time The expiry time to be used for the timer. + * + * @return The number of asynchronous operations that were cancelled. + * + * @throws boost::system::system_error Thrown on failure. + */ + std::size_t expires_at(const time_type& expiry_time) + { + boost::system::error_code ec; + std::size_t s = this->service.expires_at( + this->implementation, expiry_time, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Set the timer's expiry time as an absolute time. + /** + * This function sets the expiry time. Any pending asynchronous wait + * operations will be cancelled. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * @param expiry_time The expiry time to be used for the timer. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of asynchronous operations that were cancelled. + */ + std::size_t expires_at(const time_type& expiry_time, + boost::system::error_code& ec) + { + return this->service.expires_at(this->implementation, expiry_time, ec); + } + + /// Get the timer's expiry time relative to now. + /** + * This function may be used to obtain the timer's current expiry time. + * Whether the timer has expired or not does not affect this value. + */ + duration_type expires_from_now() const + { + return this->service.expires_from_now(this->implementation); + } + + /// Set the timer's expiry time relative to now. + /** + * This function sets the expiry time. Any pending asynchronous wait + * operations will be cancelled. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * @param expiry_time The expiry time to be used for the timer. + * + * @return The number of asynchronous operations that were cancelled. + * + * @throws boost::system::system_error Thrown on failure. + */ + std::size_t expires_from_now(const duration_type& expiry_time) + { + boost::system::error_code ec; + std::size_t s = this->service.expires_from_now( + this->implementation, expiry_time, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Set the timer's expiry time relative to now. + /** + * This function sets the expiry time. Any pending asynchronous wait + * operations will be cancelled. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * @param expiry_time The expiry time to be used for the timer. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of asynchronous operations that were cancelled. + */ + std::size_t expires_from_now(const duration_type& expiry_time, + boost::system::error_code& ec) + { + return this->service.expires_from_now( + this->implementation, expiry_time, ec); + } + + /// Perform a blocking wait on the timer. + /** + * This function is used to wait for the timer to expire. This function + * blocks and does not return until the timer has expired. + * + * @throws boost::system::system_error Thrown on failure. + */ + void wait() + { + boost::system::error_code ec; + this->service.wait(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Perform a blocking wait on the timer. + /** + * This function is used to wait for the timer to expire. This function + * blocks and does not return until the timer has expired. + * + * @param ec Set to indicate what error occurred, if any. + */ + void wait(boost::system::error_code& ec) + { + this->service.wait(this->implementation, ec); + } + + /// Start an asynchronous wait on the timer. + /** + * This function may be used to initiate an asynchronous wait against the + * timer. It always returns immediately. + * + * For each call to async_wait(), the supplied handler will be called exactly + * once. The handler will be called when: + * + * @li The timer has expired. + * + * @li The timer was cancelled, in which case the handler is passed the error + * code boost::asio::error::operation_aborted. + * + * @param handler The handler to be called when the timer expires. Copies + * will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template + void async_wait(WaitHandler handler) + { + this->service.async_wait(this->implementation, handler); + } +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BASIC_DEADLINE_TIMER_HPP diff --git a/win32/include/boost/asio/basic_io_object.hpp b/win32/include/boost/asio/basic_io_object.hpp new file mode 100755 index 000000000..1ee466910 --- /dev/null +++ b/win32/include/boost/asio/basic_io_object.hpp @@ -0,0 +1,99 @@ +// +// basic_io_object.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_IO_OBJECT_HPP +#define BOOST_ASIO_BASIC_IO_OBJECT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include + +namespace boost { +namespace asio { + +/// Base class for all I/O objects. +template +class basic_io_object + : private noncopyable +{ +public: + /// The type of the service that will be used to provide I/O operations. + typedef IoObjectService service_type; + + /// The underlying implementation type of I/O object. + typedef typename service_type::implementation_type implementation_type; + + /// (Deprecated: use get_io_service().) Get the io_service associated with + /// the object. + /** + * This function may be used to obtain the io_service object that the I/O + * object uses to dispatch handlers for asynchronous operations. + * + * @return A reference to the io_service object that the I/O object will use + * to dispatch handlers. Ownership is not transferred to the caller. + */ + boost::asio::io_service& io_service() + { + return service.get_io_service(); + } + + /// Get the io_service associated with the object. + /** + * This function may be used to obtain the io_service object that the I/O + * object uses to dispatch handlers for asynchronous operations. + * + * @return A reference to the io_service object that the I/O object will use + * to dispatch handlers. Ownership is not transferred to the caller. + */ + boost::asio::io_service& get_io_service() + { + return service.get_io_service(); + } + +protected: + /// Construct a basic_io_object. + /** + * Performs: + * @code service.construct(implementation); @endcode + */ + explicit basic_io_object(boost::asio::io_service& io_service) + : service(boost::asio::use_service(io_service)) + { + service.construct(implementation); + } + + /// Protected destructor to prevent deletion through this type. + /** + * Performs: + * @code service.destroy(implementation); @endcode + */ + ~basic_io_object() + { + service.destroy(implementation); + } + + /// The service associated with the I/O object. + service_type& service; + + /// The underlying implementation of the I/O object. + implementation_type implementation; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BASIC_IO_OBJECT_HPP diff --git a/win32/include/boost/asio/basic_raw_socket.hpp b/win32/include/boost/asio/basic_raw_socket.hpp new file mode 100755 index 000000000..97d333b58 --- /dev/null +++ b/win32/include/boost/asio/basic_raw_socket.hpp @@ -0,0 +1,800 @@ +// +// basic_raw_socket.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_RAW_SOCKET_HPP +#define BOOST_ASIO_BASIC_RAW_SOCKET_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Provides raw-oriented socket functionality. +/** + * The basic_raw_socket class template provides asynchronous and blocking + * raw-oriented socket functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template > +class basic_raw_socket + : public basic_socket +{ +public: + /// The native representation of a socket. + typedef typename RawSocketService::native_type native_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct a basic_raw_socket without opening it. + /** + * This constructor creates a raw socket without opening it. The open() + * function must be called before data can be sent or received on the socket. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + */ + explicit basic_raw_socket(boost::asio::io_service& io_service) + : basic_socket(io_service) + { + } + + /// Construct and open a basic_raw_socket. + /** + * This constructor creates and opens a raw socket. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_raw_socket(boost::asio::io_service& io_service, + const protocol_type& protocol) + : basic_socket(io_service, protocol) + { + } + + /// Construct a basic_raw_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a raw socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param endpoint An endpoint on the local machine to which the raw + * socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_raw_socket(boost::asio::io_service& io_service, + const endpoint_type& endpoint) + : basic_socket(io_service, endpoint) + { + } + + /// Construct a basic_raw_socket on an existing native socket. + /** + * This constructor creates a raw socket object to hold an existing + * native socket. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_raw_socket(boost::asio::io_service& io_service, + const protocol_type& protocol, const native_type& native_socket) + : basic_socket( + io_service, protocol, native_socket) + { + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One ore more data buffers to be sent on the socket. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected raw socket. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code socket.send(boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t send(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.send(this->implementation, buffers, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One ore more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected raw socket. + */ + template + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->service.send( + this->implementation, buffers, flags, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected raw socket. + */ + template + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->service.send(this->implementation, buffers, flags, ec); + } + + /// Start an asynchronous send on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_send operation can only be used with a connected socket. + * Use the async_send_to function to send data on an unconnected raw + * socket. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_send(const ConstBufferSequence& buffers, WriteHandler handler) + { + this->service.async_send(this->implementation, buffers, 0, handler); + } + + /// Start an asynchronous send on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_send operation can only be used with a connected socket. + * Use the async_send_to function to send data on an unconnected raw + * socket. + */ + template + void async_send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, WriteHandler handler) + { + this->service.async_send(this->implementation, buffers, flags, handler); + } + + /// Send raw data to the specified endpoint. + /** + * This function is used to send raw data to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::ip::udp::endpoint destination( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.send_to(boost::asio::buffer(data, size), destination); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination) + { + boost::system::error_code ec; + std::size_t s = this->service.send_to( + this->implementation, buffers, destination, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Send raw data to the specified endpoint. + /** + * This function is used to send raw data to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->service.send_to( + this->implementation, buffers, destination, flags, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Send raw data to the specified endpoint. + /** + * This function is used to send raw data to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. + */ + template + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + boost::system::error_code& ec) + { + return this->service.send_to(this->implementation, + buffers, destination, flags, ec); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send raw data to the specified + * remote endpoint. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param destination The remote endpoint to which the data will be sent. + * Copies will be made of the endpoint as required. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::ip::udp::endpoint destination( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.async_send_to( + * boost::asio::buffer(data, size), destination, handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, WriteHandler handler) + { + this->service.async_send_to(this->implementation, buffers, destination, 0, + handler); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send raw data to the specified + * remote endpoint. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param destination The remote endpoint to which the data will be sent. + * Copies will be made of the endpoint as required. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template + void async_send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + WriteHandler handler) + { + this->service.async_send_to(this->implementation, buffers, destination, + flags, handler); + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the raw socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected raw + * socket. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code socket.receive(boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t receive(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.receive( + this->implementation, buffers, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the raw socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected raw + * socket. + */ + template + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->service.receive( + this->implementation, buffers, flags, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the raw socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected raw + * socket. + */ + template + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->service.receive(this->implementation, buffers, flags, ec); + } + + /// Start an asynchronous receive on a connected socket. + /** + * This function is used to asynchronously receive data from the raw + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_receive operation can only be used with a connected socket. + * Use the async_receive_from function to receive data on an unconnected + * raw socket. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_receive(const MutableBufferSequence& buffers, ReadHandler handler) + { + this->service.async_receive(this->implementation, buffers, 0, handler); + } + + /// Start an asynchronous receive on a connected socket. + /** + * This function is used to asynchronously receive data from the raw + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_receive operation can only be used with a connected socket. + * Use the async_receive_from function to receive data on an unconnected + * raw socket. + */ + template + void async_receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, ReadHandler handler) + { + this->service.async_receive(this->implementation, buffers, flags, handler); + } + + /// Receive raw data with the endpoint of the sender. + /** + * This function is used to receive raw data. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * boost::asio::ip::udp::endpoint sender_endpoint; + * socket.receive_from( + * boost::asio::buffer(data, size), sender_endpoint); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint) + { + boost::system::error_code ec; + std::size_t s = this->service.receive_from( + this->implementation, buffers, sender_endpoint, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Receive raw data with the endpoint of the sender. + /** + * This function is used to receive raw data. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->service.receive_from( + this->implementation, buffers, sender_endpoint, flags, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Receive raw data with the endpoint of the sender. + /** + * This function is used to receive raw data. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. + */ + template + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + boost::system::error_code& ec) + { + return this->service.receive_from(this->implementation, buffers, + sender_endpoint, flags, ec); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive raw data. The function + * call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. Ownership of the sender_endpoint object + * is retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code socket.async_receive_from( + * boost::asio::buffer(data, size), 0, sender_endpoint, handler); @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, ReadHandler handler) + { + this->service.async_receive_from(this->implementation, buffers, + sender_endpoint, 0, handler); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive raw data. The function + * call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. Ownership of the sender_endpoint object + * is retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template + void async_receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + ReadHandler handler) + { + this->service.async_receive_from(this->implementation, buffers, + sender_endpoint, flags, handler); + } +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BASIC_RAW_SOCKET_HPP diff --git a/win32/include/boost/asio/basic_serial_port.hpp b/win32/include/boost/asio/basic_serial_port.hpp new file mode 100755 index 000000000..b73812bbf --- /dev/null +++ b/win32/include/boost/asio/basic_serial_port.hpp @@ -0,0 +1,610 @@ +// +// basic_serial_port.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SERIAL_PORT_HPP +#define BOOST_ASIO_BASIC_SERIAL_PORT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { + +/// Provides serial port functionality. +/** + * The basic_serial_port class template provides functionality that is common + * to all serial ports. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_serial_port + : public basic_io_object, + public serial_port_base +{ +public: + /// The native representation of a serial port. + typedef typename SerialPortService::native_type native_type; + + /// A basic_serial_port is always the lowest layer. + typedef basic_serial_port lowest_layer_type; + + /// Construct a basic_serial_port without opening it. + /** + * This constructor creates a serial port without opening it. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + */ + explicit basic_serial_port(boost::asio::io_service& io_service) + : basic_io_object(io_service) + { + } + + /// Construct and open a basic_serial_port. + /** + * This constructor creates and opens a serial port for the specified device + * name. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + * + * @param device The platform-specific device name for this serial + * port. + */ + explicit basic_serial_port(boost::asio::io_service& io_service, + const char* device) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.open(this->implementation, device, ec); + boost::asio::detail::throw_error(ec); + } + + /// Construct and open a basic_serial_port. + /** + * This constructor creates and opens a serial port for the specified device + * name. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + * + * @param device The platform-specific device name for this serial + * port. + */ + explicit basic_serial_port(boost::asio::io_service& io_service, + const std::string& device) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.open(this->implementation, device, ec); + boost::asio::detail::throw_error(ec); + } + + /// Construct a basic_serial_port on an existing native serial port. + /** + * This constructor creates a serial port object to hold an existing native + * serial port. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + * + * @param native_serial_port A native serial port. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_serial_port(boost::asio::io_service& io_service, + const native_type& native_serial_port) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.assign(this->implementation, native_serial_port, ec); + boost::asio::detail::throw_error(ec); + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_serial_port cannot contain any further layers, it + * simply returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Open the serial port using the specified device name. + /** + * This function opens the serial port for the specified device name. + * + * @param device The platform-specific device name. + * + * @throws boost::system::system_error Thrown on failure. + */ + void open(const std::string& device) + { + boost::system::error_code ec; + this->service.open(this->implementation, device, ec); + boost::asio::detail::throw_error(ec); + } + + /// Open the serial port using the specified device name. + /** + * This function opens the serial port using the given platform-specific + * device name. + * + * @param device The platform-specific device name. + * + * @param ec Set the indicate what error occurred, if any. + */ + boost::system::error_code open(const std::string& device, + boost::system::error_code& ec) + { + return this->service.open(this->implementation, device, ec); + } + + /// Assign an existing native serial port to the serial port. + /* + * This function opens the serial port to hold an existing native serial port. + * + * @param native_serial_port A native serial port. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const native_type& native_serial_port) + { + boost::system::error_code ec; + this->service.assign(this->implementation, native_serial_port, ec); + boost::asio::detail::throw_error(ec); + } + + /// Assign an existing native serial port to the serial port. + /* + * This function opens the serial port to hold an existing native serial port. + * + * @param native_serial_port A native serial port. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code assign(const native_type& native_serial_port, + boost::system::error_code& ec) + { + return this->service.assign(this->implementation, native_serial_port, ec); + } + + /// Determine whether the serial port is open. + bool is_open() const + { + return this->service.is_open(this->implementation); + } + + /// Close the serial port. + /** + * This function is used to close the serial port. Any asynchronous read or + * write operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void close() + { + boost::system::error_code ec; + this->service.close(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Close the serial port. + /** + * This function is used to close the serial port. Any asynchronous read or + * write operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code close(boost::system::error_code& ec) + { + return this->service.close(this->implementation, ec); + } + + /// Get the native serial port representation. + /** + * This function may be used to obtain the underlying representation of the + * serial port. This is intended to allow access to native serial port + * functionality that is not otherwise provided. + */ + native_type native() + { + return this->service.native(this->implementation); + } + + /// Cancel all asynchronous operations associated with the serial port. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void cancel() + { + boost::system::error_code ec; + this->service.cancel(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Cancel all asynchronous operations associated with the serial port. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code cancel(boost::system::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + + /// Send a break sequence to the serial port. + /** + * This function causes a break sequence of platform-specific duration to be + * sent out the serial port. + * + * @throws boost::system::system_error Thrown on failure. + */ + void send_break() + { + boost::system::error_code ec; + this->service.send_break(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Send a break sequence to the serial port. + /** + * This function causes a break sequence of platform-specific duration to be + * sent out the serial port. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code send_break(boost::system::error_code& ec) + { + return this->service.send_break(this->implementation, ec); + } + + /// Set an option on the serial port. + /** + * This function is used to set an option on the serial port. + * + * @param option The option value to be set on the serial port. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa SettableSerialPortOption @n + * boost::asio::serial_port_base::baud_rate @n + * boost::asio::serial_port_base::flow_control @n + * boost::asio::serial_port_base::parity @n + * boost::asio::serial_port_base::stop_bits @n + * boost::asio::serial_port_base::character_size + */ + template + void set_option(const SettableSerialPortOption& option) + { + boost::system::error_code ec; + this->service.set_option(this->implementation, option, ec); + boost::asio::detail::throw_error(ec); + } + + /// Set an option on the serial port. + /** + * This function is used to set an option on the serial port. + * + * @param option The option value to be set on the serial port. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa SettableSerialPortOption @n + * boost::asio::serial_port_base::baud_rate @n + * boost::asio::serial_port_base::flow_control @n + * boost::asio::serial_port_base::parity @n + * boost::asio::serial_port_base::stop_bits @n + * boost::asio::serial_port_base::character_size + */ + template + boost::system::error_code set_option(const SettableSerialPortOption& option, + boost::system::error_code& ec) + { + return this->service.set_option(this->implementation, option, ec); + } + + /// Get an option from the serial port. + /** + * This function is used to get the current value of an option on the serial + * port. + * + * @param option The option value to be obtained from the serial port. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa GettableSerialPortOption @n + * boost::asio::serial_port_base::baud_rate @n + * boost::asio::serial_port_base::flow_control @n + * boost::asio::serial_port_base::parity @n + * boost::asio::serial_port_base::stop_bits @n + * boost::asio::serial_port_base::character_size + */ + template + void get_option(GettableSerialPortOption& option) + { + boost::system::error_code ec; + this->service.get_option(this->implementation, option, ec); + boost::asio::detail::throw_error(ec); + } + + /// Get an option from the serial port. + /** + * This function is used to get the current value of an option on the serial + * port. + * + * @param option The option value to be obtained from the serial port. + * + * @param ec Set to indicate what error occured, if any. + * + * @sa GettableSerialPortOption @n + * boost::asio::serial_port_base::baud_rate @n + * boost::asio::serial_port_base::flow_control @n + * boost::asio::serial_port_base::parity @n + * boost::asio::serial_port_base::stop_bits @n + * boost::asio::serial_port_base::character_size + */ + template + boost::system::error_code get_option(GettableSerialPortOption& option, + boost::system::error_code& ec) + { + return this->service.get_option(this->implementation, option, ec); + } + + /// Write some data to the serial port. + /** + * This function is used to write data to the serial port. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the serial port. + * + * @returns The number of bytes written. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.write_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.write_some(this->implementation, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Write some data to the serial port. + /** + * This function is used to write data to the serial port. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the serial port. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->service.write_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the serial port. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be written to the serial port. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.async_write_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_write_some(const ConstBufferSequence& buffers, + WriteHandler handler) + { + this->service.async_write_some(this->implementation, buffers, handler); + } + + /// Read some data from the serial port. + /** + * This function is used to read data from the serial port. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.read_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.read_some(this->implementation, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Read some data from the serial port. + /** + * This function is used to read data from the serial port. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->service.read_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the serial port. + * The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.async_read_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_read_some(const MutableBufferSequence& buffers, + ReadHandler handler) + { + this->service.async_read_some(this->implementation, buffers, handler); + } +}; + +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_BASIC_SERIAL_PORT_HPP diff --git a/win32/include/boost/asio/basic_socket.hpp b/win32/include/boost/asio/basic_socket.hpp new file mode 100755 index 000000000..60161d06b --- /dev/null +++ b/win32/include/boost/asio/basic_socket.hpp @@ -0,0 +1,1051 @@ +// +// basic_socket.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SOCKET_HPP +#define BOOST_ASIO_BASIC_SOCKET_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Provides socket functionality. +/** + * The basic_socket class template provides functionality that is common to both + * stream-oriented and datagram-oriented sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_socket + : public basic_io_object, + public socket_base +{ +public: + /// The native representation of a socket. + typedef typename SocketService::native_type native_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// A basic_socket is always the lowest layer. + typedef basic_socket lowest_layer_type; + + /// Construct a basic_socket without opening it. + /** + * This constructor creates a socket without opening it. + * + * @param io_service The io_service object that the socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + */ + explicit basic_socket(boost::asio::io_service& io_service) + : basic_io_object(io_service) + { + } + + /// Construct and open a basic_socket. + /** + * This constructor creates and opens a socket. + * + * @param io_service The io_service object that the socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket(boost::asio::io_service& io_service, + const protocol_type& protocol) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.open(this->implementation, protocol, ec); + boost::asio::detail::throw_error(ec); + } + + /// Construct a basic_socket, opening it and binding it to the given local + /// endpoint. + /** + * This constructor creates a socket and automatically opens it bound to the + * specified endpoint on the local machine. The protocol used is the protocol + * associated with the given endpoint. + * + * @param io_service The io_service object that the socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket(boost::asio::io_service& io_service, + const endpoint_type& endpoint) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.open(this->implementation, endpoint.protocol(), ec); + boost::asio::detail::throw_error(ec); + this->service.bind(this->implementation, endpoint, ec); + boost::asio::detail::throw_error(ec); + } + + /// Construct a basic_socket on an existing native socket. + /** + * This constructor creates a socket object to hold an existing native socket. + * + * @param io_service The io_service object that the socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket A native socket. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket(boost::asio::io_service& io_service, + const protocol_type& protocol, const native_type& native_socket) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.assign(this->implementation, protocol, native_socket, ec); + boost::asio::detail::throw_error(ec); + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_socket cannot contain any further layers, it simply + * returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Open the socket using the specified protocol. + /** + * This function opens the socket so that it will use the specified protocol. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * socket.open(boost::asio::ip::tcp::v4()); + * @endcode + */ + void open(const protocol_type& protocol = protocol_type()) + { + boost::system::error_code ec; + this->service.open(this->implementation, protocol, ec); + boost::asio::detail::throw_error(ec); + } + + /// Open the socket using the specified protocol. + /** + * This function opens the socket so that it will use the specified protocol. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * boost::system::error_code ec; + * socket.open(boost::asio::ip::tcp::v4(), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code open(const protocol_type& protocol, + boost::system::error_code& ec) + { + return this->service.open(this->implementation, protocol, ec); + } + + /// Assign an existing native socket to the socket. + /* + * This function opens the socket to hold an existing native socket. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_socket A native socket. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const protocol_type& protocol, const native_type& native_socket) + { + boost::system::error_code ec; + this->service.assign(this->implementation, protocol, native_socket, ec); + boost::asio::detail::throw_error(ec); + } + + /// Assign an existing native socket to the socket. + /* + * This function opens the socket to hold an existing native socket. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_socket A native socket. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code assign(const protocol_type& protocol, + const native_type& native_socket, boost::system::error_code& ec) + { + return this->service.assign(this->implementation, + protocol, native_socket, ec); + } + + /// Determine whether the socket is open. + bool is_open() const + { + return this->service.is_open(this->implementation); + } + + /// Close the socket. + /** + * This function is used to close the socket. Any asynchronous send, receive + * or connect operations will be cancelled immediately, and will complete + * with the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note For portable behaviour with respect to graceful closure of a + * connected socket, call shutdown() before closing the socket. + */ + void close() + { + boost::system::error_code ec; + this->service.close(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Close the socket. + /** + * This function is used to close the socket. Any asynchronous send, receive + * or connect operations will be cancelled immediately, and will complete + * with the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::system::error_code ec; + * socket.close(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + * + * @note For portable behaviour with respect to graceful closure of a + * connected socket, call shutdown() before closing the socket. + */ + boost::system::error_code close(boost::system::error_code& ec) + { + return this->service.close(this->implementation, ec); + } + + /// Get the native socket representation. + /** + * This function may be used to obtain the underlying representation of the + * socket. This is intended to allow access to native socket functionality + * that is not otherwise provided. + */ + native_type native() + { + return this->service.native(this->implementation); + } + + /// Cancel all asynchronous operations associated with the socket. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note Calls to cancel() will always fail with + * boost::asio::error::operation_not_supported when run on Windows XP, Windows + * Server 2003, and earlier versions of Windows, unless + * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has + * two issues that should be considered before enabling its use: + * + * @li It will only cancel asynchronous operations that were initiated in the + * current thread. + * + * @li It can appear to complete without error, but the request to cancel the + * unfinished operations may be silently ignored by the operating system. + * Whether it works or not seems to depend on the drivers that are installed. + * + * For portable cancellation, consider using one of the following + * alternatives: + * + * @li Disable asio's I/O completion port backend by defining + * BOOST_ASIO_DISABLE_IOCP. + * + * @li Use the close() function to simultaneously cancel the outstanding + * operations and close the socket. + * + * When running on Windows Vista, Windows Server 2008, and later, the + * CancelIoEx function is always used. This function does not have the + * problems described above. + */ +#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ + && !defined(BOOST_ASIO_ENABLE_CANCELIO) + __declspec(deprecated("By default, this function always fails with " + "operation_not_supported when used on Windows XP, Windows Server 2003, " + "or earlier. Consult documentation for details.")) +#endif + void cancel() + { + boost::system::error_code ec; + this->service.cancel(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Cancel all asynchronous operations associated with the socket. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note Calls to cancel() will always fail with + * boost::asio::error::operation_not_supported when run on Windows XP, Windows + * Server 2003, and earlier versions of Windows, unless + * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has + * two issues that should be considered before enabling its use: + * + * @li It will only cancel asynchronous operations that were initiated in the + * current thread. + * + * @li It can appear to complete without error, but the request to cancel the + * unfinished operations may be silently ignored by the operating system. + * Whether it works or not seems to depend on the drivers that are installed. + * + * For portable cancellation, consider using one of the following + * alternatives: + * + * @li Disable asio's I/O completion port backend by defining + * BOOST_ASIO_DISABLE_IOCP. + * + * @li Use the close() function to simultaneously cancel the outstanding + * operations and close the socket. + * + * When running on Windows Vista, Windows Server 2008, and later, the + * CancelIoEx function is always used. This function does not have the + * problems described above. + */ +#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ + && !defined(BOOST_ASIO_ENABLE_CANCELIO) + __declspec(deprecated("By default, this function always fails with " + "operation_not_supported when used on Windows XP, Windows Server 2003, " + "or earlier. Consult documentation for details.")) +#endif + boost::system::error_code cancel(boost::system::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + + /// Determine whether the socket is at the out-of-band data mark. + /** + * This function is used to check whether the socket input is currently + * positioned at the out-of-band data mark. + * + * @return A bool indicating whether the socket is at the out-of-band data + * mark. + * + * @throws boost::system::system_error Thrown on failure. + */ + bool at_mark() const + { + boost::system::error_code ec; + bool b = this->service.at_mark(this->implementation, ec); + boost::asio::detail::throw_error(ec); + return b; + } + + /// Determine whether the socket is at the out-of-band data mark. + /** + * This function is used to check whether the socket input is currently + * positioned at the out-of-band data mark. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return A bool indicating whether the socket is at the out-of-band data + * mark. + */ + bool at_mark(boost::system::error_code& ec) const + { + return this->service.at_mark(this->implementation, ec); + } + + /// Determine the number of bytes available for reading. + /** + * This function is used to determine the number of bytes that may be read + * without blocking. + * + * @return The number of bytes that may be read without blocking, or 0 if an + * error occurs. + * + * @throws boost::system::system_error Thrown on failure. + */ + std::size_t available() const + { + boost::system::error_code ec; + std::size_t s = this->service.available(this->implementation, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Determine the number of bytes available for reading. + /** + * This function is used to determine the number of bytes that may be read + * without blocking. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of bytes that may be read without blocking, or 0 if an + * error occurs. + */ + std::size_t available(boost::system::error_code& ec) const + { + return this->service.available(this->implementation, ec); + } + + /// Bind the socket to the given local endpoint. + /** + * This function binds the socket to the specified endpoint on the local + * machine. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * socket.open(boost::asio::ip::tcp::v4()); + * socket.bind(boost::asio::ip::tcp::endpoint( + * boost::asio::ip::tcp::v4(), 12345)); + * @endcode + */ + void bind(const endpoint_type& endpoint) + { + boost::system::error_code ec; + this->service.bind(this->implementation, endpoint, ec); + boost::asio::detail::throw_error(ec); + } + + /// Bind the socket to the given local endpoint. + /** + * This function binds the socket to the specified endpoint on the local + * machine. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * socket.open(boost::asio::ip::tcp::v4()); + * boost::system::error_code ec; + * socket.bind(boost::asio::ip::tcp::endpoint( + * boost::asio::ip::tcp::v4(), 12345), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code bind(const endpoint_type& endpoint, + boost::system::error_code& ec) + { + return this->service.bind(this->implementation, endpoint, ec); + } + + /// Connect the socket to the specified endpoint. + /** + * This function is used to connect a socket to the specified remote endpoint. + * The function call will block until the connection is successfully made or + * an error occurs. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * boost::asio::ip::tcp::endpoint endpoint( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.connect(endpoint); + * @endcode + */ + void connect(const endpoint_type& peer_endpoint) + { + boost::system::error_code ec; + if (!is_open()) + { + this->service.open(this->implementation, peer_endpoint.protocol(), ec); + boost::asio::detail::throw_error(ec); + } + this->service.connect(this->implementation, peer_endpoint, ec); + boost::asio::detail::throw_error(ec); + } + + /// Connect the socket to the specified endpoint. + /** + * This function is used to connect a socket to the specified remote endpoint. + * The function call will block until the connection is successfully made or + * an error occurs. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * boost::asio::ip::tcp::endpoint endpoint( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * boost::system::error_code ec; + * socket.connect(endpoint, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code connect(const endpoint_type& peer_endpoint, + boost::system::error_code& ec) + { + if (!is_open()) + { + if (this->service.open(this->implementation, + peer_endpoint.protocol(), ec)) + { + return ec; + } + } + + return this->service.connect(this->implementation, peer_endpoint, ec); + } + + /// Start an asynchronous connect. + /** + * This function is used to asynchronously connect a socket to the specified + * remote endpoint. The function call always returns immediately. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. Copies will be made of the endpoint object as required. + * + * @param handler The handler to be called when the connection operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * @code + * void connect_handler(const boost::system::error_code& error) + * { + * if (!error) + * { + * // Connect succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::socket socket(io_service); + * boost::asio::ip::tcp::endpoint endpoint( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.async_connect(endpoint, connect_handler); + * @endcode + */ + template + void async_connect(const endpoint_type& peer_endpoint, ConnectHandler handler) + { + if (!is_open()) + { + boost::system::error_code ec; + if (this->service.open(this->implementation, + peer_endpoint.protocol(), ec)) + { + this->get_io_service().post( + boost::asio::detail::bind_handler(handler, ec)); + return; + } + } + + this->service.async_connect(this->implementation, peer_endpoint, handler); + } + + /// Set an option on the socket. + /** + * This function is used to set an option on the socket. + * + * @param option The new option value to be set on the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa SettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Setting the IPPROTO_TCP/TCP_NODELAY option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::no_delay option(true); + * socket.set_option(option); + * @endcode + */ + template + void set_option(const SettableSocketOption& option) + { + boost::system::error_code ec; + this->service.set_option(this->implementation, option, ec); + boost::asio::detail::throw_error(ec); + } + + /// Set an option on the socket. + /** + * This function is used to set an option on the socket. + * + * @param option The new option value to be set on the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa SettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Setting the IPPROTO_TCP/TCP_NODELAY option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::no_delay option(true); + * boost::system::error_code ec; + * socket.set_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template + boost::system::error_code set_option(const SettableSocketOption& option, + boost::system::error_code& ec) + { + return this->service.set_option(this->implementation, option, ec); + } + + /// Get an option from the socket. + /** + * This function is used to get the current value of an option on the socket. + * + * @param option The option value to be obtained from the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa GettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::socket::keep_alive option; + * socket.get_option(option); + * bool is_set = option.get(); + * @endcode + */ + template + void get_option(GettableSocketOption& option) const + { + boost::system::error_code ec; + this->service.get_option(this->implementation, option, ec); + boost::asio::detail::throw_error(ec); + } + + /// Get an option from the socket. + /** + * This function is used to get the current value of an option on the socket. + * + * @param option The option value to be obtained from the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa GettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::socket::keep_alive option; + * boost::system::error_code ec; + * socket.get_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * bool is_set = option.get(); + * @endcode + */ + template + boost::system::error_code get_option(GettableSocketOption& option, + boost::system::error_code& ec) const + { + return this->service.get_option(this->implementation, option, ec); + } + + /// Perform an IO control command on the socket. + /** + * This function is used to execute an IO control command on the socket. + * + * @param command The IO control command to be performed on the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa IoControlCommand @n + * boost::asio::socket_base::bytes_readable @n + * boost::asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::socket::bytes_readable command; + * socket.io_control(command); + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template + void io_control(IoControlCommand& command) + { + boost::system::error_code ec; + this->service.io_control(this->implementation, command, ec); + boost::asio::detail::throw_error(ec); + } + + /// Perform an IO control command on the socket. + /** + * This function is used to execute an IO control command on the socket. + * + * @param command The IO control command to be performed on the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa IoControlCommand @n + * boost::asio::socket_base::bytes_readable @n + * boost::asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::socket::bytes_readable command; + * boost::system::error_code ec; + * socket.io_control(command, ec); + * if (ec) + * { + * // An error occurred. + * } + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template + boost::system::error_code io_control(IoControlCommand& command, + boost::system::error_code& ec) + { + return this->service.io_control(this->implementation, command, ec); + } + + /// Get the local endpoint of the socket. + /** + * This function is used to obtain the locally bound endpoint of the socket. + * + * @returns An object that represents the local endpoint of the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); + * @endcode + */ + endpoint_type local_endpoint() const + { + boost::system::error_code ec; + endpoint_type ep = this->service.local_endpoint(this->implementation, ec); + boost::asio::detail::throw_error(ec); + return ep; + } + + /// Get the local endpoint of the socket. + /** + * This function is used to obtain the locally bound endpoint of the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns An object that represents the local endpoint of the socket. + * Returns a default-constructed endpoint object if an error occurred. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::system::error_code ec; + * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + endpoint_type local_endpoint(boost::system::error_code& ec) const + { + return this->service.local_endpoint(this->implementation, ec); + } + + /// Get the remote endpoint of the socket. + /** + * This function is used to obtain the remote endpoint of the socket. + * + * @returns An object that represents the remote endpoint of the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); + * @endcode + */ + endpoint_type remote_endpoint() const + { + boost::system::error_code ec; + endpoint_type ep = this->service.remote_endpoint(this->implementation, ec); + boost::asio::detail::throw_error(ec); + return ep; + } + + /// Get the remote endpoint of the socket. + /** + * This function is used to obtain the remote endpoint of the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns An object that represents the remote endpoint of the socket. + * Returns a default-constructed endpoint object if an error occurred. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::system::error_code ec; + * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + endpoint_type remote_endpoint(boost::system::error_code& ec) const + { + return this->service.remote_endpoint(this->implementation, ec); + } + + /// Disable sends or receives on the socket. + /** + * This function is used to disable send operations, receive operations, or + * both. + * + * @param what Determines what types of operation will no longer be allowed. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * Shutting down the send side of the socket: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send); + * @endcode + */ + void shutdown(shutdown_type what) + { + boost::system::error_code ec; + this->service.shutdown(this->implementation, what, ec); + boost::asio::detail::throw_error(ec); + } + + /// Disable sends or receives on the socket. + /** + * This function is used to disable send operations, receive operations, or + * both. + * + * @param what Determines what types of operation will no longer be allowed. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * Shutting down the send side of the socket: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::system::error_code ec; + * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code shutdown(shutdown_type what, + boost::system::error_code& ec) + { + return this->service.shutdown(this->implementation, what, ec); + } + +protected: + /// Protected destructor to prevent deletion through this type. + ~basic_socket() + { + } +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BASIC_SOCKET_HPP diff --git a/win32/include/boost/asio/basic_socket_acceptor.hpp b/win32/include/boost/asio/basic_socket_acceptor.hpp new file mode 100755 index 000000000..307b27dad --- /dev/null +++ b/win32/include/boost/asio/basic_socket_acceptor.hpp @@ -0,0 +1,826 @@ +// +// basic_socket_acceptor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_HPP +#define BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Provides the ability to accept new connections. +/** + * The basic_socket_acceptor class template is used for accepting new socket + * connections. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Example + * Opening a socket acceptor with the SO_REUSEADDR option enabled: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port); + * acceptor.open(endpoint.protocol()); + * acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + * acceptor.bind(endpoint); + * acceptor.listen(); + * @endcode + */ +template > +class basic_socket_acceptor + : public basic_io_object, + public socket_base +{ +public: + /// The native representation of an acceptor. + typedef typename SocketAcceptorService::native_type native_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct an acceptor without opening it. + /** + * This constructor creates an acceptor without opening it to listen for new + * connections. The open() function must be called before the acceptor can + * accept new socket connections. + * + * @param io_service The io_service object that the acceptor will use to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + */ + explicit basic_socket_acceptor(boost::asio::io_service& io_service) + : basic_io_object(io_service) + { + } + + /// Construct an open acceptor. + /** + * This constructor creates an acceptor and automatically opens it. + * + * @param io_service The io_service object that the acceptor will use to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket_acceptor(boost::asio::io_service& io_service, + const protocol_type& protocol) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.open(this->implementation, protocol, ec); + boost::asio::detail::throw_error(ec); + } + + /// Construct an acceptor opened on the given endpoint. + /** + * This constructor creates an acceptor and automatically opens it to listen + * for new connections on the specified endpoint. + * + * @param io_service The io_service object that the acceptor will use to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + * + * @param endpoint An endpoint on the local machine on which the acceptor + * will listen for new connections. + * + * @param reuse_addr Whether the constructor should set the socket option + * socket_base::reuse_address. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This constructor is equivalent to the following code: + * @code + * basic_socket_acceptor acceptor(io_service); + * acceptor.open(endpoint.protocol()); + * if (reuse_addr) + * acceptor.set_option(socket_base::reuse_address(true)); + * acceptor.bind(endpoint); + * acceptor.listen(listen_backlog); + * @endcode + */ + basic_socket_acceptor(boost::asio::io_service& io_service, + const endpoint_type& endpoint, bool reuse_addr = true) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.open(this->implementation, endpoint.protocol(), ec); + boost::asio::detail::throw_error(ec); + if (reuse_addr) + { + this->service.set_option(this->implementation, + socket_base::reuse_address(true), ec); + boost::asio::detail::throw_error(ec); + } + this->service.bind(this->implementation, endpoint, ec); + boost::asio::detail::throw_error(ec); + this->service.listen(this->implementation, + socket_base::max_connections, ec); + boost::asio::detail::throw_error(ec); + } + + /// Construct a basic_socket_acceptor on an existing native acceptor. + /** + * This constructor creates an acceptor object to hold an existing native + * acceptor. + * + * @param io_service The io_service object that the acceptor will use to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_acceptor A native acceptor. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket_acceptor(boost::asio::io_service& io_service, + const protocol_type& protocol, const native_type& native_acceptor) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.assign(this->implementation, protocol, native_acceptor, ec); + boost::asio::detail::throw_error(ec); + } + + /// Open the acceptor using the specified protocol. + /** + * This function opens the socket acceptor so that it will use the specified + * protocol. + * + * @param protocol An object specifying which protocol is to be used. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * acceptor.open(boost::asio::ip::tcp::v4()); + * @endcode + */ + void open(const protocol_type& protocol = protocol_type()) + { + boost::system::error_code ec; + this->service.open(this->implementation, protocol, ec); + boost::asio::detail::throw_error(ec); + } + + /// Open the acceptor using the specified protocol. + /** + * This function opens the socket acceptor so that it will use the specified + * protocol. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * boost::system::error_code ec; + * acceptor.open(boost::asio::ip::tcp::v4(), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code open(const protocol_type& protocol, + boost::system::error_code& ec) + { + return this->service.open(this->implementation, protocol, ec); + } + + /// Assigns an existing native acceptor to the acceptor. + /* + * This function opens the acceptor to hold an existing native acceptor. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_acceptor A native acceptor. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const protocol_type& protocol, const native_type& native_acceptor) + { + boost::system::error_code ec; + this->service.assign(this->implementation, protocol, native_acceptor, ec); + boost::asio::detail::throw_error(ec); + } + + /// Assigns an existing native acceptor to the acceptor. + /* + * This function opens the acceptor to hold an existing native acceptor. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_acceptor A native acceptor. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code assign(const protocol_type& protocol, + const native_type& native_acceptor, boost::system::error_code& ec) + { + return this->service.assign(this->implementation, + protocol, native_acceptor, ec); + } + + /// Determine whether the acceptor is open. + bool is_open() const + { + return this->service.is_open(this->implementation); + } + + /// Bind the acceptor to the given local endpoint. + /** + * This function binds the socket acceptor to the specified endpoint on the + * local machine. + * + * @param endpoint An endpoint on the local machine to which the socket + * acceptor will be bound. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * acceptor.open(boost::asio::ip::tcp::v4()); + * acceptor.bind(boost::asio::ip::tcp::endpoint(12345)); + * @endcode + */ + void bind(const endpoint_type& endpoint) + { + boost::system::error_code ec; + this->service.bind(this->implementation, endpoint, ec); + boost::asio::detail::throw_error(ec); + } + + /// Bind the acceptor to the given local endpoint. + /** + * This function binds the socket acceptor to the specified endpoint on the + * local machine. + * + * @param endpoint An endpoint on the local machine to which the socket + * acceptor will be bound. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * acceptor.open(boost::asio::ip::tcp::v4()); + * boost::system::error_code ec; + * acceptor.bind(boost::asio::ip::tcp::endpoint(12345), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code bind(const endpoint_type& endpoint, + boost::system::error_code& ec) + { + return this->service.bind(this->implementation, endpoint, ec); + } + + /// Place the acceptor into the state where it will listen for new + /// connections. + /** + * This function puts the socket acceptor into the state where it may accept + * new connections. + * + * @param backlog The maximum length of the queue of pending connections. + * + * @throws boost::system::system_error Thrown on failure. + */ + void listen(int backlog = socket_base::max_connections) + { + boost::system::error_code ec; + this->service.listen(this->implementation, backlog, ec); + boost::asio::detail::throw_error(ec); + } + + /// Place the acceptor into the state where it will listen for new + /// connections. + /** + * This function puts the socket acceptor into the state where it may accept + * new connections. + * + * @param backlog The maximum length of the queue of pending connections. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::system::error_code ec; + * acceptor.listen(boost::asio::socket_base::max_connections, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code listen(int backlog, boost::system::error_code& ec) + { + return this->service.listen(this->implementation, backlog, ec); + } + + /// Close the acceptor. + /** + * This function is used to close the acceptor. Any asynchronous accept + * operations will be cancelled immediately. + * + * A subsequent call to open() is required before the acceptor can again be + * used to again perform socket accept operations. + * + * @throws boost::system::system_error Thrown on failure. + */ + void close() + { + boost::system::error_code ec; + this->service.close(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Close the acceptor. + /** + * This function is used to close the acceptor. Any asynchronous accept + * operations will be cancelled immediately. + * + * A subsequent call to open() is required before the acceptor can again be + * used to again perform socket accept operations. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::system::error_code ec; + * acceptor.close(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code close(boost::system::error_code& ec) + { + return this->service.close(this->implementation, ec); + } + + /// Get the native acceptor representation. + /** + * This function may be used to obtain the underlying representation of the + * acceptor. This is intended to allow access to native acceptor functionality + * that is not otherwise provided. + */ + native_type native() + { + return this->service.native(this->implementation); + } + + /// Cancel all asynchronous operations associated with the acceptor. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void cancel() + { + boost::system::error_code ec; + this->service.cancel(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Cancel all asynchronous operations associated with the acceptor. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code cancel(boost::system::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + + /// Set an option on the acceptor. + /** + * This function is used to set an option on the acceptor. + * + * @param option The new option value to be set on the acceptor. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa SettableSocketOption @n + * boost::asio::socket_base::reuse_address + * boost::asio::socket_base::enable_connection_aborted + * + * @par Example + * Setting the SOL_SOCKET/SO_REUSEADDR option: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::acceptor::reuse_address option(true); + * acceptor.set_option(option); + * @endcode + */ + template + void set_option(const SettableSocketOption& option) + { + boost::system::error_code ec; + this->service.set_option(this->implementation, option, ec); + boost::asio::detail::throw_error(ec); + } + + /// Set an option on the acceptor. + /** + * This function is used to set an option on the acceptor. + * + * @param option The new option value to be set on the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa SettableSocketOption @n + * boost::asio::socket_base::reuse_address + * boost::asio::socket_base::enable_connection_aborted + * + * @par Example + * Setting the SOL_SOCKET/SO_REUSEADDR option: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::acceptor::reuse_address option(true); + * boost::system::error_code ec; + * acceptor.set_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template + boost::system::error_code set_option(const SettableSocketOption& option, + boost::system::error_code& ec) + { + return this->service.set_option(this->implementation, option, ec); + } + + /// Get an option from the acceptor. + /** + * This function is used to get the current value of an option on the + * acceptor. + * + * @param option The option value to be obtained from the acceptor. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa GettableSocketOption @n + * boost::asio::socket_base::reuse_address + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::acceptor::reuse_address option; + * acceptor.get_option(option); + * bool is_set = option.get(); + * @endcode + */ + template + void get_option(GettableSocketOption& option) + { + boost::system::error_code ec; + this->service.get_option(this->implementation, option, ec); + boost::asio::detail::throw_error(ec); + } + + /// Get an option from the acceptor. + /** + * This function is used to get the current value of an option on the + * acceptor. + * + * @param option The option value to be obtained from the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa GettableSocketOption @n + * boost::asio::socket_base::reuse_address + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::acceptor::reuse_address option; + * boost::system::error_code ec; + * acceptor.get_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * bool is_set = option.get(); + * @endcode + */ + template + boost::system::error_code get_option(GettableSocketOption& option, + boost::system::error_code& ec) + { + return this->service.get_option(this->implementation, option, ec); + } + + /// Get the local endpoint of the acceptor. + /** + * This function is used to obtain the locally bound endpoint of the acceptor. + * + * @returns An object that represents the local endpoint of the acceptor. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(); + * @endcode + */ + endpoint_type local_endpoint() const + { + boost::system::error_code ec; + endpoint_type ep = this->service.local_endpoint(this->implementation, ec); + boost::asio::detail::throw_error(ec); + return ep; + } + + /// Get the local endpoint of the acceptor. + /** + * This function is used to obtain the locally bound endpoint of the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns An object that represents the local endpoint of the acceptor. + * Returns a default-constructed endpoint object if an error occurred and the + * error handler did not throw an exception. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::system::error_code ec; + * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + endpoint_type local_endpoint(boost::system::error_code& ec) const + { + return this->service.local_endpoint(this->implementation, ec); + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer into the + * given socket. The function call will block until a new connection has been + * accepted successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::socket socket(io_service); + * acceptor.accept(socket); + * @endcode + */ + template + void accept(basic_socket& peer) + { + boost::system::error_code ec; + this->service.accept(this->implementation, peer, 0, ec); + boost::asio::detail::throw_error(ec); + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer into the + * given socket. The function call will block until a new connection has been + * accepted successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::soocket socket(io_service); + * boost::system::error_code ec; + * acceptor.accept(socket, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template + boost::system::error_code accept( + basic_socket& peer, + boost::system::error_code& ec) + { + return this->service.accept(this->implementation, peer, 0, ec); + } + + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection into a + * socket. The function call always returns immediately. + * + * @param peer The socket into which the new connection will be accepted. + * Ownership of the peer object is retained by the caller, which must + * guarantee that it is valid until the handler is called. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * @code + * void accept_handler(const boost::system::error_code& error) + * { + * if (!error) + * { + * // Accept succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::socket socket(io_service); + * acceptor.async_accept(socket, accept_handler); + * @endcode + */ + template + void async_accept(basic_socket& peer, + AcceptHandler handler) + { + this->service.async_accept(this->implementation, peer, 0, handler); + } + + /// Accept a new connection and obtain the endpoint of the peer + /** + * This function is used to accept a new connection from a peer into the + * given socket, and additionally provide the endpoint of the remote peer. + * The function call will block until a new connection has been accepted + * successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @param peer_endpoint An endpoint object which will receive the endpoint of + * the remote peer. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::socket socket(io_service); + * boost::asio::ip::tcp::endpoint endpoint; + * acceptor.accept(socket, endpoint); + * @endcode + */ + template + void accept(basic_socket& peer, + endpoint_type& peer_endpoint) + { + boost::system::error_code ec; + this->service.accept(this->implementation, peer, &peer_endpoint, ec); + boost::asio::detail::throw_error(ec); + } + + /// Accept a new connection and obtain the endpoint of the peer + /** + * This function is used to accept a new connection from a peer into the + * given socket, and additionally provide the endpoint of the remote peer. + * The function call will block until a new connection has been accepted + * successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @param peer_endpoint An endpoint object which will receive the endpoint of + * the remote peer. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::socket socket(io_service); + * boost::asio::ip::tcp::endpoint endpoint; + * boost::system::error_code ec; + * acceptor.accept(socket, endpoint, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template + boost::system::error_code accept( + basic_socket& peer, + endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + return this->service.accept(this->implementation, peer, &peer_endpoint, ec); + } + + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection into a + * socket, and additionally obtain the endpoint of the remote peer. The + * function call always returns immediately. + * + * @param peer The socket into which the new connection will be accepted. + * Ownership of the peer object is retained by the caller, which must + * guarantee that it is valid until the handler is called. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. Ownership of the peer_endpoint object is + * retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template + void async_accept(basic_socket& peer, + endpoint_type& peer_endpoint, AcceptHandler handler) + { + this->service.async_accept(this->implementation, + peer, &peer_endpoint, handler); + } +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_HPP diff --git a/win32/include/boost/asio/basic_socket_iostream.hpp b/win32/include/boost/asio/basic_socket_iostream.hpp new file mode 100755 index 000000000..b262632b0 --- /dev/null +++ b/win32/include/boost/asio/basic_socket_iostream.hpp @@ -0,0 +1,150 @@ +// +// basic_socket_iostream.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP +#define BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#if !defined(BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY) +#define BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY 5 +#endif // !defined(BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY) + +// A macro that should expand to: +// template +// explicit basic_socket_iostream(T1 x1, ..., Tn xn) +// : basic_iostream(&this->boost::base_from_member< +// basic_socket_streambuf >::member) +// { +// if (rdbuf()->connect(x1, ..., xn) == 0) +// this->setstate(std::ios_base::failbit); +// } +// This macro should only persist within this file. + +#define BOOST_ASIO_PRIVATE_CTR_DEF(z, n, data) \ + template \ + explicit basic_socket_iostream(BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \ + : std::basic_iostream(&this->boost::base_from_member< \ + basic_socket_streambuf >::member) \ + { \ + tie(this); \ + if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \ + this->setstate(std::ios_base::failbit); \ + } \ + /**/ + +// A macro that should expand to: +// template +// void connect(T1 x1, ..., Tn xn) +// { +// if (rdbuf()->connect(x1, ..., xn) == 0) +// this->setstate(std::ios_base::failbit); +// } +// This macro should only persist within this file. + +#define BOOST_ASIO_PRIVATE_CONNECT_DEF(z, n, data) \ + template \ + void connect(BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \ + { \ + if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \ + this->setstate(std::ios_base::failbit); \ + } \ + /**/ + +namespace boost { +namespace asio { + +/// Iostream interface for a socket. +template > +class basic_socket_iostream + : public boost::base_from_member< + basic_socket_streambuf >, + public std::basic_iostream +{ +public: + /// Construct a basic_socket_iostream without establishing a connection. + basic_socket_iostream() + : std::basic_iostream(&this->boost::base_from_member< + basic_socket_streambuf >::member) + { + tie(this); + } + +#if defined(GENERATING_DOCUMENTATION) + /// Establish a connection to an endpoint corresponding to a resolver query. + /** + * This constructor automatically establishes a connection based on the + * supplied resolver query parameters. The arguments are used to construct + * a resolver query object. + */ + template + explicit basic_socket_iostream(T1 t1, ..., TN tn); +#else + BOOST_PP_REPEAT_FROM_TO( + 1, BOOST_PP_INC(BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY), + BOOST_ASIO_PRIVATE_CTR_DEF, _ ) +#endif + +#if defined(GENERATING_DOCUMENTATION) + /// Establish a connection to an endpoint corresponding to a resolver query. + /** + * This function automatically establishes a connection based on the supplied + * resolver query parameters. The arguments are used to construct a resolver + * query object. + */ + template + void connect(T1 t1, ..., TN tn); +#else + BOOST_PP_REPEAT_FROM_TO( + 1, BOOST_PP_INC(BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY), + BOOST_ASIO_PRIVATE_CONNECT_DEF, _ ) +#endif + + /// Close the connection. + void close() + { + if (rdbuf()->close() == 0) + this->setstate(std::ios_base::failbit); + } + + /// Return a pointer to the underlying streambuf. + basic_socket_streambuf* rdbuf() const + { + return const_cast*>( + &this->boost::base_from_member< + basic_socket_streambuf >::member); + } +}; + +} // namespace asio +} // namespace boost + +#undef BOOST_ASIO_PRIVATE_CTR_DEF +#undef BOOST_ASIO_PRIVATE_CONNECT_DEF + +#include + +#endif // BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP diff --git a/win32/include/boost/asio/basic_socket_streambuf.hpp b/win32/include/boost/asio/basic_socket_streambuf.hpp new file mode 100755 index 000000000..8f13f5730 --- /dev/null +++ b/win32/include/boost/asio/basic_socket_streambuf.hpp @@ -0,0 +1,286 @@ +// +// basic_socket_streambuf.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP +#define BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if !defined(BOOST_ASIO_SOCKET_STREAMBUF_MAX_ARITY) +#define BOOST_ASIO_SOCKET_STREAMBUF_MAX_ARITY 5 +#endif // !defined(BOOST_ASIO_SOCKET_STREAMBUF_MAX_ARITY) + +// A macro that should expand to: +// template +// basic_socket_streambuf* connect( +// T1 x1, ..., Tn xn) +// { +// init_buffers(); +// boost::system::error_code ec; +// this->basic_socket::close(ec); +// typedef typename Protocol::resolver_query resolver_query; +// resolver_query query(x1, ..., xn); +// resolve_and_connect(query, ec); +// return !ec ? this : 0; +// } +// This macro should only persist within this file. + +#define BOOST_ASIO_PRIVATE_CONNECT_DEF( z, n, data ) \ + template \ + basic_socket_streambuf* connect( \ + BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \ + { \ + init_buffers(); \ + boost::system::error_code ec; \ + this->basic_socket::close(ec); \ + typedef typename Protocol::resolver_query resolver_query; \ + resolver_query query(BOOST_PP_ENUM_PARAMS(n, x)); \ + resolve_and_connect(query, ec); \ + return !ec ? this : 0; \ + } \ + /**/ + +namespace boost { +namespace asio { + +/// Iostream streambuf for a socket. +template > +class basic_socket_streambuf + : public std::streambuf, + private boost::base_from_member, + public basic_socket +{ +public: + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct a basic_socket_streambuf without establishing a connection. + basic_socket_streambuf() + : basic_socket( + boost::base_from_member::member), + unbuffered_(false) + { + init_buffers(); + } + + /// Destructor flushes buffered data. + virtual ~basic_socket_streambuf() + { + if (pptr() != pbase()) + overflow(traits_type::eof()); + } + + /// Establish a connection. + /** + * This function establishes a connection to the specified endpoint. + * + * @return \c this if a connection was successfully established, a null + * pointer otherwise. + */ + basic_socket_streambuf* connect( + const endpoint_type& endpoint) + { + init_buffers(); + boost::system::error_code ec; + this->basic_socket::close(ec); + this->basic_socket::connect(endpoint, ec); + return !ec ? this : 0; + } + +#if defined(GENERATING_DOCUMENTATION) + /// Establish a connection. + /** + * This function automatically establishes a connection based on the supplied + * resolver query parameters. The arguments are used to construct a resolver + * query object. + * + * @return \c this if a connection was successfully established, a null + * pointer otherwise. + */ + template + basic_socket_streambuf* connect( + T1 t1, ..., TN tn); +#else + BOOST_PP_REPEAT_FROM_TO( + 1, BOOST_PP_INC(BOOST_ASIO_SOCKET_STREAMBUF_MAX_ARITY), + BOOST_ASIO_PRIVATE_CONNECT_DEF, _ ) +#endif + + /// Close the connection. + /** + * @return \c this if a connection was successfully established, a null + * pointer otherwise. + */ + basic_socket_streambuf* close() + { + boost::system::error_code ec; + sync(); + this->basic_socket::close(ec); + if (!ec) + init_buffers(); + return !ec ? this : 0; + } + +protected: + int_type underflow() + { + if (gptr() == egptr()) + { + boost::system::error_code ec; + std::size_t bytes_transferred = this->service.receive( + this->implementation, + boost::asio::buffer(boost::asio::buffer(get_buffer_) + putback_max), + 0, ec); + if (ec) + return traits_type::eof(); + setg(get_buffer_.begin(), get_buffer_.begin() + putback_max, + get_buffer_.begin() + putback_max + bytes_transferred); + return traits_type::to_int_type(*gptr()); + } + else + { + return traits_type::eof(); + } + } + + int_type overflow(int_type c) + { + if (unbuffered_) + { + if (traits_type::eq_int_type(c, traits_type::eof())) + { + // Nothing to do. + return traits_type::not_eof(c); + } + else + { + // Send the single character immediately. + boost::system::error_code ec; + char_type ch = traits_type::to_char_type(c); + this->service.send(this->implementation, + boost::asio::buffer(&ch, sizeof(char_type)), 0, ec); + if (ec) + return traits_type::eof(); + return c; + } + } + else + { + // Send all data in the output buffer. + boost::asio::const_buffer buffer = + boost::asio::buffer(pbase(), pptr() - pbase()); + while (boost::asio::buffer_size(buffer) > 0) + { + boost::system::error_code ec; + std::size_t bytes_transferred = this->service.send( + this->implementation, boost::asio::buffer(buffer), + 0, ec); + if (ec) + return traits_type::eof(); + buffer = buffer + bytes_transferred; + } + setp(put_buffer_.begin(), put_buffer_.end()); + + // If the new character is eof then our work here is done. + if (traits_type::eq_int_type(c, traits_type::eof())) + return traits_type::not_eof(c); + + // Add the new character to the output buffer. + *pptr() = traits_type::to_char_type(c); + pbump(1); + return c; + } + } + + int sync() + { + return overflow(traits_type::eof()); + } + + std::streambuf* setbuf(char_type* s, std::streamsize n) + { + if (pptr() == pbase() && s == 0 && n == 0) + { + unbuffered_ = true; + setp(0, 0); + return this; + } + + return 0; + } + +private: + void init_buffers() + { + setg(get_buffer_.begin(), + get_buffer_.begin() + putback_max, + get_buffer_.begin() + putback_max); + if (unbuffered_) + setp(0, 0); + else + setp(put_buffer_.begin(), put_buffer_.end()); + } + + void resolve_and_connect(const typename Protocol::resolver_query& query, + boost::system::error_code& ec) + { + typedef typename Protocol::resolver resolver_type; + typedef typename Protocol::resolver_iterator iterator_type; + resolver_type resolver( + boost::base_from_member::member); + iterator_type i = resolver.resolve(query, ec); + if (!ec) + { + iterator_type end; + ec = boost::asio::error::host_not_found; + while (ec && i != end) + { + this->basic_socket::close(); + this->basic_socket::connect(*i, ec); + ++i; + } + } + } + + enum { putback_max = 8 }; + enum { buffer_size = 512 }; + boost::array get_buffer_; + boost::array put_buffer_; + bool unbuffered_; +}; + +} // namespace asio +} // namespace boost + +#undef BOOST_ASIO_PRIVATE_CONNECT_DEF + +#include + +#endif // BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP diff --git a/win32/include/boost/asio/basic_stream_socket.hpp b/win32/include/boost/asio/basic_stream_socket.hpp new file mode 100755 index 000000000..6737e077c --- /dev/null +++ b/win32/include/boost/asio/basic_stream_socket.hpp @@ -0,0 +1,720 @@ +// +// basic_stream_socket.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_STREAM_SOCKET_HPP +#define BOOST_ASIO_BASIC_STREAM_SOCKET_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Provides stream-oriented socket functionality. +/** + * The basic_stream_socket class template provides asynchronous and blocking + * stream-oriented socket functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template > +class basic_stream_socket + : public basic_socket +{ +public: + /// The native representation of a socket. + typedef typename StreamSocketService::native_type native_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct a basic_stream_socket without opening it. + /** + * This constructor creates a stream socket without opening it. The socket + * needs to be opened and then connected or accepted before data can be sent + * or received on it. + * + * @param io_service The io_service object that the stream socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + */ + explicit basic_stream_socket(boost::asio::io_service& io_service) + : basic_socket(io_service) + { + } + + /// Construct and open a basic_stream_socket. + /** + * This constructor creates and opens a stream socket. The socket needs to be + * connected or accepted before data can be sent or received on it. + * + * @param io_service The io_service object that the stream socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_stream_socket(boost::asio::io_service& io_service, + const protocol_type& protocol) + : basic_socket(io_service, protocol) + { + } + + /// Construct a basic_stream_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a stream socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param io_service The io_service object that the stream socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the stream + * socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_stream_socket(boost::asio::io_service& io_service, + const endpoint_type& endpoint) + : basic_socket(io_service, endpoint) + { + } + + /// Construct a basic_stream_socket on an existing native socket. + /** + * This constructor creates a stream socket object to hold an existing native + * socket. + * + * @param io_service The io_service object that the stream socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_stream_socket(boost::asio::io_service& io_service, + const protocol_type& protocol, const native_type& native_socket) + : basic_socket( + io_service, protocol, native_socket) + { + } + + /// Send some data on the socket. + /** + * This function is used to send data on the stream socket. The function + * call will block until one or more bytes of the data has been sent + * successfully, or an until error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref write function if you need to ensure that all data + * is written before the blocking operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.send(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t send(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.send( + this->implementation, buffers, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Send some data on the socket. + /** + * This function is used to send data on the stream socket. The function + * call will block until one or more bytes of the data has been sent + * successfully, or an until error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref write function if you need to ensure that all data + * is written before the blocking operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.send(boost::asio::buffer(data, size), 0); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->service.send( + this->implementation, buffers, flags, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Send some data on the socket. + /** + * This function is used to send data on the stream socket. The function + * call will block until one or more bytes of the data has been sent + * successfully, or an until error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. Returns 0 if an error occurred. + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref write function if you need to ensure that all data + * is written before the blocking operation completes. + */ + template + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->service.send(this->implementation, buffers, flags, ec); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send data on the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_send(const ConstBufferSequence& buffers, WriteHandler handler) + { + this->service.async_send(this->implementation, buffers, 0, handler); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send data on the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(boost::asio::buffer(data, size), 0, handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, WriteHandler handler) + { + this->service.async_send(this->implementation, buffers, flags, handler); + } + + /// Receive some data on the socket. + /** + * This function is used to receive data on the stream socket. The function + * call will block until one or more bytes of data has been received + * successfully, or until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.receive(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t receive(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.receive(this->implementation, buffers, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Receive some data on the socket. + /** + * This function is used to receive data on the stream socket. The function + * call will block until one or more bytes of data has been received + * successfully, or until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.receive(boost::asio::buffer(data, size), 0); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->service.receive( + this->implementation, buffers, flags, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the stream socket. The function + * call will block until one or more bytes of data has been received + * successfully, or until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. Returns 0 if an error occurred. + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + */ + template + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->service.receive(this->implementation, buffers, flags, ec); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive data from the stream + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref async_read function if you need to ensure + * that the requested amount of data is received before the asynchronous + * operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_receive(const MutableBufferSequence& buffers, ReadHandler handler) + { + this->service.async_receive(this->implementation, buffers, 0, handler); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive data from the stream + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref async_read function if you need to ensure + * that the requested amount of data is received before the asynchronous + * operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(boost::asio::buffer(data, size), 0, handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, ReadHandler handler) + { + this->service.async_receive(this->implementation, buffers, flags, handler); + } + + /// Write some data to the socket. + /** + * This function is used to write data to the stream socket. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the socket. + * + * @returns The number of bytes written. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * socket.write_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.send(this->implementation, buffers, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Write some data to the socket. + /** + * This function is used to write data to the stream socket. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->service.send(this->implementation, buffers, 0, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be written to the socket. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_write_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_write_some(const ConstBufferSequence& buffers, + WriteHandler handler) + { + this->service.async_send(this->implementation, buffers, 0, handler); + } + + /// Read some data from the socket. + /** + * This function is used to read data from the stream socket. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * socket.read_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.receive(this->implementation, buffers, 0, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Read some data from the socket. + /** + * This function is used to read data from the stream socket. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->service.receive(this->implementation, buffers, 0, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_read_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_read_some(const MutableBufferSequence& buffers, + ReadHandler handler) + { + this->service.async_receive(this->implementation, buffers, 0, handler); + } +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BASIC_STREAM_SOCKET_HPP diff --git a/win32/include/boost/asio/basic_streambuf.hpp b/win32/include/boost/asio/basic_streambuf.hpp new file mode 100755 index 000000000..a8066a1d1 --- /dev/null +++ b/win32/include/boost/asio/basic_streambuf.hpp @@ -0,0 +1,200 @@ +// +// basic_streambuf.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_STREAMBUF_HPP +#define BOOST_ASIO_BASIC_STREAMBUF_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { + +/// Automatically resizable buffer class based on std::streambuf. +template > +class basic_streambuf + : public std::streambuf, + private noncopyable +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The type used to represent the get area as a list of buffers. + typedef implementation_defined const_buffers_type; + + /// The type used to represent the put area as a list of buffers. + typedef implementation_defined mutable_buffers_type; +#else + typedef boost::asio::const_buffers_1 const_buffers_type; + typedef boost::asio::mutable_buffers_1 mutable_buffers_type; +#endif + + /// Construct a buffer with a specified maximum size. + explicit basic_streambuf( + std::size_t max_size = (std::numeric_limits::max)(), + const Allocator& allocator = Allocator()) + : max_size_(max_size), + buffer_(allocator) + { + std::size_t pend = (std::min)(max_size_, buffer_delta); + buffer_.resize((std::max)(pend, 1)); + setg(&buffer_[0], &buffer_[0], &buffer_[0]); + setp(&buffer_[0], &buffer_[0] + pend); + } + + /// Return the size of the get area in characters. + std::size_t size() const + { + return pptr() - gptr(); + } + + /// Return the maximum size of the buffer. + std::size_t max_size() const + { + return max_size_; + } + + /// Get a list of buffers that represents the get area. + const_buffers_type data() const + { + return boost::asio::buffer(boost::asio::const_buffer(gptr(), + (pptr() - gptr()) * sizeof(char_type))); + } + + /// Get a list of buffers that represents the put area, with the given size. + mutable_buffers_type prepare(std::size_t size) + { + reserve(size); + return boost::asio::buffer(boost::asio::mutable_buffer( + pptr(), size * sizeof(char_type))); + } + + /// Move the start of the put area by the specified number of characters. + void commit(std::size_t n) + { + if (pptr() + n > epptr()) + n = epptr() - pptr(); + pbump(static_cast(n)); + } + + /// Move the start of the get area by the specified number of characters. + void consume(std::size_t n) + { + if (gptr() + n > pptr()) + n = pptr() - gptr(); + gbump(static_cast(n)); + } + +protected: + enum { buffer_delta = 128 }; + + int_type underflow() + { + if (gptr() < pptr()) + { + setg(&buffer_[0], gptr(), pptr()); + return traits_type::to_int_type(*gptr()); + } + else + { + return traits_type::eof(); + } + } + + int_type overflow(int_type c) + { + if (!traits_type::eq_int_type(c, traits_type::eof())) + { + if (pptr() == epptr()) + { + std::size_t buffer_size = pptr() - gptr(); + if (buffer_size < max_size_ && max_size_ - buffer_size < buffer_delta) + { + reserve(max_size_ - buffer_size); + } + else + { + reserve(buffer_delta); + } + } + + *pptr() = traits_type::to_char_type(c); + pbump(1); + return c; + } + + return traits_type::not_eof(c); + } + + void reserve(std::size_t n) + { + // Get current stream positions as offsets. + std::size_t gnext = gptr() - &buffer_[0]; + std::size_t gend = egptr() - &buffer_[0]; + std::size_t pnext = pptr() - &buffer_[0]; + std::size_t pend = epptr() - &buffer_[0]; + + // Check if there is already enough space in the put area. + if (n <= pend - pnext) + { + return; + } + + // Shift existing contents of get area to start of buffer. + if (gnext > 0) + { + std::rotate(&buffer_[0], &buffer_[0] + gnext, &buffer_[0] + pend); + gend -= gnext; + pnext -= gnext; + } + + // Ensure buffer is large enough to hold at least the specified size. + if (n > pend - pnext) + { + if (n <= max_size_ && pnext <= max_size_ - n) + { + buffer_.resize((std::max)(pnext + n, 1)); + } + else + { + throw std::length_error("boost::asio::streambuf too long"); + } + } + + // Update stream positions. + setg(&buffer_[0], &buffer_[0], &buffer_[0] + gend); + setp(&buffer_[0] + pnext, &buffer_[0] + pnext + n); + } + +private: + std::size_t max_size_; + std::vector buffer_; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BASIC_STREAMBUF_HPP diff --git a/win32/include/boost/asio/buffer.hpp b/win32/include/boost/asio/buffer.hpp new file mode 100755 index 000000000..a33cb140a --- /dev/null +++ b/win32/include/boost/asio/buffer.hpp @@ -0,0 +1,1042 @@ +// +// buffer.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFER_HPP +#define BOOST_ASIO_BUFFER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_MSVC) +# if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0) +# if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING) +# define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING +# endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING) +# endif // defined(_HAS_ITERATOR_DEBUGGING) +#endif // defined(BOOST_MSVC) + +#if defined(__GNUC__) +# if defined(_GLIBCXX_DEBUG) +# if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING) +# define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING +# endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING) +# endif // defined(_GLIBCXX_DEBUG) +#endif // defined(__GNUC__) + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) +# include +# include +# include +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + +namespace boost { +namespace asio { + +class mutable_buffer; +class const_buffer; + +namespace detail { +void* buffer_cast_helper(const mutable_buffer&); +const void* buffer_cast_helper(const const_buffer&); +std::size_t buffer_size_helper(const mutable_buffer&); +std::size_t buffer_size_helper(const const_buffer&); +} // namespace detail + +/// Holds a buffer that can be modified. +/** + * The mutable_buffer class provides a safe representation of a buffer that can + * be modified. It does not own the underlying data, and so is cheap to copy or + * assign. + */ +class mutable_buffer +{ +public: + /// Construct an empty buffer. + mutable_buffer() + : data_(0), + size_(0) + { + } + + /// Construct a buffer to represent a given memory range. + mutable_buffer(void* data, std::size_t size) + : data_(data), + size_(size) + { + } + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + mutable_buffer(void* data, std::size_t size, + boost::function debug_check) + : data_(data), + size_(size), + debug_check_(debug_check) + { + } + + const boost::function& get_debug_check() const + { + return debug_check_; + } +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + +private: + friend void* boost::asio::detail::buffer_cast_helper( + const mutable_buffer& b); + friend std::size_t boost::asio::detail::buffer_size_helper( + const mutable_buffer& b); + + void* data_; + std::size_t size_; + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + boost::function debug_check_; +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING +}; + +namespace detail { + +inline void* buffer_cast_helper(const mutable_buffer& b) +{ +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + if (b.size_ && b.debug_check_) + b.debug_check_(); +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + return b.data_; +} + +inline std::size_t buffer_size_helper(const mutable_buffer& b) +{ + return b.size_; +} + +} // namespace detail + +/// Cast a non-modifiable buffer to a specified pointer to POD type. +/** + * @relates mutable_buffer + */ +template +inline PointerToPodType buffer_cast(const mutable_buffer& b) +{ + return static_cast(detail::buffer_cast_helper(b)); +} + +/// Get the number of bytes in a non-modifiable buffer. +/** + * @relates mutable_buffer + */ +inline std::size_t buffer_size(const mutable_buffer& b) +{ + return detail::buffer_size_helper(b); +} + +/// Create a new modifiable buffer that is offset from the start of another. +/** + * @relates mutable_buffer + */ +inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start) +{ + if (start > buffer_size(b)) + return mutable_buffer(); + char* new_data = buffer_cast(b) + start; + std::size_t new_size = buffer_size(b) - start; + return mutable_buffer(new_data, new_size +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , b.get_debug_check() +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + ); +} + +/// Create a new modifiable buffer that is offset from the start of another. +/** + * @relates mutable_buffer + */ +inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b) +{ + if (start > buffer_size(b)) + return mutable_buffer(); + char* new_data = buffer_cast(b) + start; + std::size_t new_size = buffer_size(b) - start; + return mutable_buffer(new_data, new_size +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , b.get_debug_check() +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + ); +} + +/// Adapts a single modifiable buffer so that it meets the requirements of the +/// MutableBufferSequence concept. +class mutable_buffers_1 + : public mutable_buffer +{ +public: + /// The type for each element in the list of buffers. + typedef mutable_buffer value_type; + + /// A random-access iterator type that may be used to read elements. + typedef const mutable_buffer* const_iterator; + + /// Construct to represent a given memory range. + mutable_buffers_1(void* data, std::size_t size) + : mutable_buffer(data, size) + { + } + + /// Construct to represent a single modifiable buffer. + explicit mutable_buffers_1(const mutable_buffer& b) + : mutable_buffer(b) + { + } + + /// Get a random-access iterator to the first element. + const_iterator begin() const + { + return this; + } + + /// Get a random-access iterator for one past the last element. + const_iterator end() const + { + return begin() + 1; + } +}; + +/// Holds a buffer that cannot be modified. +/** + * The const_buffer class provides a safe representation of a buffer that cannot + * be modified. It does not own the underlying data, and so is cheap to copy or + * assign. + */ +class const_buffer +{ +public: + /// Construct an empty buffer. + const_buffer() + : data_(0), + size_(0) + { + } + + /// Construct a buffer to represent a given memory range. + const_buffer(const void* data, std::size_t size) + : data_(data), + size_(size) + { + } + + /// Construct a non-modifiable buffer from a modifiable one. + const_buffer(const mutable_buffer& b) + : data_(boost::asio::detail::buffer_cast_helper(b)), + size_(boost::asio::detail::buffer_size_helper(b)) +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , debug_check_(b.get_debug_check()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + { + } + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + const_buffer(const void* data, std::size_t size, + boost::function debug_check) + : data_(data), + size_(size), + debug_check_(debug_check) + { + } + + const boost::function& get_debug_check() const + { + return debug_check_; + } +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + +private: + friend const void* boost::asio::detail::buffer_cast_helper( + const const_buffer& b); + friend std::size_t boost::asio::detail::buffer_size_helper( + const const_buffer& b); + + const void* data_; + std::size_t size_; + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + boost::function debug_check_; +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING +}; + +namespace detail { + +inline const void* buffer_cast_helper(const const_buffer& b) +{ +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + if (b.size_ && b.debug_check_) + b.debug_check_(); +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + return b.data_; +} + +inline std::size_t buffer_size_helper(const const_buffer& b) +{ + return b.size_; +} + +} // namespace detail + +/// Cast a non-modifiable buffer to a specified pointer to POD type. +/** + * @relates const_buffer + */ +template +inline PointerToPodType buffer_cast(const const_buffer& b) +{ + return static_cast(detail::buffer_cast_helper(b)); +} + +/// Get the number of bytes in a non-modifiable buffer. +/** + * @relates const_buffer + */ +inline std::size_t buffer_size(const const_buffer& b) +{ + return detail::buffer_size_helper(b); +} + +/// Create a new non-modifiable buffer that is offset from the start of another. +/** + * @relates const_buffer + */ +inline const_buffer operator+(const const_buffer& b, std::size_t start) +{ + if (start > buffer_size(b)) + return const_buffer(); + const char* new_data = buffer_cast(b) + start; + std::size_t new_size = buffer_size(b) - start; + return const_buffer(new_data, new_size +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , b.get_debug_check() +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + ); +} + +/// Create a new non-modifiable buffer that is offset from the start of another. +/** + * @relates const_buffer + */ +inline const_buffer operator+(std::size_t start, const const_buffer& b) +{ + if (start > buffer_size(b)) + return const_buffer(); + const char* new_data = buffer_cast(b) + start; + std::size_t new_size = buffer_size(b) - start; + return const_buffer(new_data, new_size +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , b.get_debug_check() +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + ); +} + +/// Adapts a single non-modifiable buffer so that it meets the requirements of +/// the ConstBufferSequence concept. +class const_buffers_1 + : public const_buffer +{ +public: + /// The type for each element in the list of buffers. + typedef const_buffer value_type; + + /// A random-access iterator type that may be used to read elements. + typedef const const_buffer* const_iterator; + + /// Construct to represent a given memory range. + const_buffers_1(const void* data, std::size_t size) + : const_buffer(data, size) + { + } + + /// Construct to represent a single non-modifiable buffer. + explicit const_buffers_1(const const_buffer& b) + : const_buffer(b) + { + } + + /// Get a random-access iterator to the first element. + const_iterator begin() const + { + return this; + } + + /// Get a random-access iterator for one past the last element. + const_iterator end() const + { + return begin() + 1; + } +}; + +/// An implementation of both the ConstBufferSequence and MutableBufferSequence +/// concepts to represent a null buffer sequence. +class null_buffers +{ +public: + /// The type for each element in the list of buffers. + typedef mutable_buffer value_type; + + /// A random-access iterator type that may be used to read elements. + typedef const mutable_buffer* const_iterator; + + /// Get a random-access iterator to the first element. + const_iterator begin() const + { + return &buf_; + } + + /// Get a random-access iterator for one past the last element. + const_iterator end() const + { + return &buf_; + } + +private: + mutable_buffer buf_; +}; + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) +namespace detail { + +template +class buffer_debug_check +{ +public: + buffer_debug_check(Iterator iter) + : iter_(iter) + { + } + + ~buffer_debug_check() + { +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) + // MSVC's string iterator checking may crash in a std::string::iterator + // object's destructor when the iterator points to an already-destroyed + // std::string object, unless the iterator is cleared first. + iter_ = Iterator(); +#endif // BOOST_WORKAROUND(BOOST_MSVC, >= 1400) + } + + void operator()() + { + *iter_; + } + +private: + Iterator iter_; +}; + +} // namespace detail +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + +/** @defgroup buffer boost::asio::buffer + * + * @brief The boost::asio::buffer function is used to create a buffer object to + * represent raw memory, an array of POD elements, a vector of POD elements, + * or a std::string. + * + * A buffer object represents a contiguous region of memory as a 2-tuple + * consisting of a pointer and size in bytes. A tuple of the form {void*, + * size_t} specifies a mutable (modifiable) region of memory. Similarly, a + * tuple of the form {const void*, size_t} specifies a const + * (non-modifiable) region of memory. These two forms correspond to the classes + * mutable_buffer and const_buffer, respectively. To mirror C++'s conversion + * rules, a mutable_buffer is implicitly convertible to a const_buffer, and the + * opposite conversion is not permitted. + * + * The simplest use case involves reading or writing a single buffer of a + * specified size: + * + * @code sock.send(boost::asio::buffer(data, size)); @endcode + * + * In the above example, the return value of boost::asio::buffer meets the + * requirements of the ConstBufferSequence concept so that it may be directly + * passed to the socket's write function. A buffer created for modifiable + * memory also meets the requirements of the MutableBufferSequence concept. + * + * An individual buffer may be created from a builtin array, std::vector or + * boost::array of POD elements. This helps prevent buffer overruns by + * automatically determining the size of the buffer: + * + * @code char d1[128]; + * size_t bytes_transferred = sock.receive(boost::asio::buffer(d1)); + * + * std::vector d2(128); + * bytes_transferred = sock.receive(boost::asio::buffer(d2)); + * + * boost::array d3; + * bytes_transferred = sock.receive(boost::asio::buffer(d3)); @endcode + * + * In all three cases above, the buffers created are exactly 128 bytes long. + * Note that a vector is @e never automatically resized when creating or using + * a buffer. The buffer size is determined using the vector's size() + * member function, and not its capacity. + * + * @par Accessing Buffer Contents + * + * The contents of a buffer may be accessed using the boost::asio::buffer_size + * and boost::asio::buffer_cast functions: + * + * @code boost::asio::mutable_buffer b1 = ...; + * std::size_t s1 = boost::asio::buffer_size(b1); + * unsigned char* p1 = boost::asio::buffer_cast(b1); + * + * boost::asio::const_buffer b2 = ...; + * std::size_t s2 = boost::asio::buffer_size(b2); + * const void* p2 = boost::asio::buffer_cast(b2); @endcode + * + * The boost::asio::buffer_cast function permits violations of type safety, so + * uses of it in application code should be carefully considered. + * + * @par Buffer Invalidation + * + * A buffer object does not have any ownership of the memory it refers to. It + * is the responsibility of the application to ensure the memory region remains + * valid until it is no longer required for an I/O operation. When the memory + * is no longer available, the buffer is said to have been invalidated. + * + * For the boost::asio::buffer overloads that accept an argument of type + * std::vector, the buffer objects returned are invalidated by any vector + * operation that also invalidates all references, pointers and iterators + * referring to the elements in the sequence (C++ Std, 23.2.4) + * + * For the boost::asio::buffer overloads that accept an argument of type + * std::string, the buffer objects returned are invalidated according to the + * rules defined for invalidation of references, pointers and iterators + * referring to elements of the sequence (C++ Std, 21.3). + * + * @par Buffer Arithmetic + * + * Buffer objects may be manipulated using simple arithmetic in a safe way + * which helps prevent buffer overruns. Consider an array initialised as + * follows: + * + * @code boost::array a = { 'a', 'b', 'c', 'd', 'e' }; @endcode + * + * A buffer object @c b1 created using: + * + * @code b1 = boost::asio::buffer(a); @endcode + * + * represents the entire array, { 'a', 'b', 'c', 'd', 'e' }. An + * optional second argument to the boost::asio::buffer function may be used to + * limit the size, in bytes, of the buffer: + * + * @code b2 = boost::asio::buffer(a, 3); @endcode + * + * such that @c b2 represents the data { 'a', 'b', 'c' }. Even if the + * size argument exceeds the actual size of the array, the size of the buffer + * object created will be limited to the array size. + * + * An offset may be applied to an existing buffer to create a new one: + * + * @code b3 = b1 + 2; @endcode + * + * where @c b3 will set to represent { 'c', 'd', 'e' }. If the offset + * exceeds the size of the existing buffer, the newly created buffer will be + * empty. + * + * Both an offset and size may be specified to create a buffer that corresponds + * to a specific range of bytes within an existing buffer: + * + * @code b4 = boost::asio::buffer(b1 + 1, 3); @endcode + * + * so that @c b4 will refer to the bytes { 'b', 'c', 'd' }. + * + * @par Buffers and Scatter-Gather I/O + * + * To read or write using multiple buffers (i.e. scatter-gather I/O), multiple + * buffer objects may be assigned into a container that supports the + * MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts: + * + * @code + * char d1[128]; + * std::vector d2(128); + * boost::array d3; + * + * boost::array bufs1 = { + * boost::asio::buffer(d1), + * boost::asio::buffer(d2), + * boost::asio::buffer(d3) }; + * bytes_transferred = sock.receive(bufs1); + * + * std::vector bufs2; + * bufs2.push_back(boost::asio::buffer(d1)); + * bufs2.push_back(boost::asio::buffer(d2)); + * bufs2.push_back(boost::asio::buffer(d3)); + * bytes_transferred = sock.send(bufs2); @endcode + */ +/*@{*/ + +/// Create a new modifiable buffer from an existing buffer. +/** + * @returns mutable_buffers_1(b). + */ +inline mutable_buffers_1 buffer(const mutable_buffer& b) +{ + return mutable_buffers_1(b); +} + +/// Create a new modifiable buffer from an existing buffer. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * buffer_cast(b), + * min(buffer_size(b), max_size_in_bytes)); @endcode + */ +inline mutable_buffers_1 buffer(const mutable_buffer& b, + std::size_t max_size_in_bytes) +{ + return mutable_buffers_1( + mutable_buffer(buffer_cast(b), + buffer_size(b) < max_size_in_bytes + ? buffer_size(b) : max_size_in_bytes +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , b.get_debug_check() +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/// Create a new non-modifiable buffer from an existing buffer. +/** + * @returns const_buffers_1(b). + */ +inline const_buffers_1 buffer(const const_buffer& b) +{ + return const_buffers_1(b); +} + +/// Create a new non-modifiable buffer from an existing buffer. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * buffer_cast(b), + * min(buffer_size(b), max_size_in_bytes)); @endcode + */ +inline const_buffers_1 buffer(const const_buffer& b, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(buffer_cast(b), + buffer_size(b) < max_size_in_bytes + ? buffer_size(b) : max_size_in_bytes +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , b.get_debug_check() +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/// Create a new modifiable buffer that represents the given memory range. +/** + * @returns mutable_buffers_1(data, size_in_bytes). + */ +inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes) +{ + return mutable_buffers_1(mutable_buffer(data, size_in_bytes)); +} + +/// Create a new non-modifiable buffer that represents the given memory range. +/** + * @returns const_buffers_1(data, size_in_bytes). + */ +inline const_buffers_1 buffer(const void* data, + std::size_t size_in_bytes) +{ + return const_buffers_1(const_buffer(data, size_in_bytes)); +} + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * static_cast(data), + * N * sizeof(PodType)); @endcode + */ +template +inline mutable_buffers_1 buffer(PodType (&data)[N]) +{ + return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType))); +} + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * static_cast(data), + * min(N * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template +inline mutable_buffers_1 buffer(PodType (&data)[N], + std::size_t max_size_in_bytes) +{ + return mutable_buffers_1( + mutable_buffer(data, + N * sizeof(PodType) < max_size_in_bytes + ? N * sizeof(PodType) : max_size_in_bytes)); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * static_cast(data), + * N * sizeof(PodType)); @endcode + */ +template +inline const_buffers_1 buffer(const PodType (&data)[N]) +{ + return const_buffers_1(const_buffer(data, N * sizeof(PodType))); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * static_cast(data), + * min(N * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template +inline const_buffers_1 buffer(const PodType (&data)[N], + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data, + N * sizeof(PodType) < max_size_in_bytes + ? N * sizeof(PodType) : max_size_in_bytes)); +} + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) \ + || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) + +// Borland C++ and Sun Studio think the overloads: +// +// unspecified buffer(boost::array& array ...); +// +// and +// +// unspecified buffer(boost::array& array ...); +// +// are ambiguous. This will be worked around by using a buffer_types traits +// class that contains typedefs for the appropriate buffer and container +// classes, based on whether PodType is const or non-const. + +namespace detail { + +template +struct buffer_types_base; + +template <> +struct buffer_types_base +{ + typedef mutable_buffer buffer_type; + typedef mutable_buffers_1 container_type; +}; + +template <> +struct buffer_types_base +{ + typedef const_buffer buffer_type; + typedef const_buffers_1 container_type; +}; + +template +struct buffer_types + : public buffer_types_base::value> +{ +}; + +} // namespace detail + +template +inline typename detail::buffer_types::container_type +buffer(boost::array& data) +{ + typedef typename boost::asio::detail::buffer_types::buffer_type + buffer_type; + typedef typename boost::asio::detail::buffer_types::container_type + container_type; + return container_type( + buffer_type(data.c_array(), data.size() * sizeof(PodType))); +} + +template +inline typename detail::buffer_types::container_type +buffer(boost::array& data, std::size_t max_size_in_bytes) +{ + typedef typename boost::asio::detail::buffer_types::buffer_type + buffer_type; + typedef typename boost::asio::detail::buffer_types::container_type + container_type; + return container_type( + buffer_type(data.c_array(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) + // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template +inline mutable_buffers_1 buffer(boost::array& data) +{ + return mutable_buffers_1( + mutable_buffer(data.c_array(), data.size() * sizeof(PodType))); +} + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template +inline mutable_buffers_1 buffer(boost::array& data, + std::size_t max_size_in_bytes) +{ + return mutable_buffers_1( + mutable_buffer(data.c_array(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template +inline const_buffers_1 buffer(boost::array& data) +{ + return const_buffers_1( + const_buffer(data.data(), data.size() * sizeof(PodType))); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template +inline const_buffers_1 buffer(boost::array& data, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) + // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template +inline const_buffers_1 buffer(const boost::array& data) +{ + return const_buffers_1( + const_buffer(data.data(), data.size() * sizeof(PodType))); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template +inline const_buffers_1 buffer(const boost::array& data, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +/// Create a new modifiable buffer that represents the given POD vector. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.size() ? &data[0] : 0, + * data.size() * sizeof(PodType)); @endcode + * + * @note The buffer is invalidated by any vector operation that would also + * invalidate iterators. + */ +template +inline mutable_buffers_1 buffer(std::vector& data) +{ + return mutable_buffers_1( + mutable_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check< + typename std::vector::iterator + >(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/// Create a new modifiable buffer that represents the given POD vector. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.size() ? &data[0] : 0, + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + * + * @note The buffer is invalidated by any vector operation that would also + * invalidate iterators. + */ +template +inline mutable_buffers_1 buffer(std::vector& data, + std::size_t max_size_in_bytes) +{ + return mutable_buffers_1( + mutable_buffer(data.size() ? &data[0] : 0, + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check< + typename std::vector::iterator + >(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/// Create a new non-modifiable buffer that represents the given POD vector. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.size() ? &data[0] : 0, + * data.size() * sizeof(PodType)); @endcode + * + * @note The buffer is invalidated by any vector operation that would also + * invalidate iterators. + */ +template +inline const_buffers_1 buffer( + const std::vector& data) +{ + return const_buffers_1( + const_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check< + typename std::vector::const_iterator + >(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/// Create a new non-modifiable buffer that represents the given POD vector. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.size() ? &data[0] : 0, + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + * + * @note The buffer is invalidated by any vector operation that would also + * invalidate iterators. + */ +template +inline const_buffers_1 buffer( + const std::vector& data, std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.size() ? &data[0] : 0, + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check< + typename std::vector::const_iterator + >(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/// Create a new non-modifiable buffer that represents the given string. +/** + * @returns const_buffers_1(data.data(), data.size()). + * + * @note The buffer is invalidated by any non-const operation called on the + * given string object. + */ +inline const_buffers_1 buffer(const std::string& data) +{ + return const_buffers_1(const_buffer(data.data(), data.size() +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/// Create a new non-modifiable buffer that represents the given string. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size(), max_size_in_bytes)); @endcode + * + * @note The buffer is invalidated by any non-const operation called on the + * given string object. + */ +inline const_buffers_1 buffer(const std::string& data, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.data(), + data.size() < max_size_in_bytes + ? data.size() : max_size_in_bytes +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/*@}*/ + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BUFFER_HPP diff --git a/win32/include/boost/asio/buffered_read_stream.hpp b/win32/include/boost/asio/buffered_read_stream.hpp new file mode 100755 index 000000000..f1700ee18 --- /dev/null +++ b/win32/include/boost/asio/buffered_read_stream.hpp @@ -0,0 +1,416 @@ +// +// buffered_read_stream.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERED_READ_STREAM_HPP +#define BOOST_ASIO_BUFFERED_READ_STREAM_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Adds buffering to the read-related operations of a stream. +/** + * The buffered_read_stream class template can be used to add buffering to the + * synchronous and asynchronous read operations of a stream. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, Sync_Read_Stream, SyncWriteStream. + */ +template +class buffered_read_stream + : private noncopyable +{ +public: + /// The type of the next layer. + typedef typename boost::remove_reference::type next_layer_type; + + /// The type of the lowest layer. + typedef typename next_layer_type::lowest_layer_type lowest_layer_type; + +#if defined(GENERATING_DOCUMENTATION) + /// The default buffer size. + static const std::size_t default_buffer_size = implementation_defined; +#else + BOOST_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024); +#endif + + /// Construct, passing the specified argument to initialise the next layer. + template + explicit buffered_read_stream(Arg& a) + : next_layer_(a), + storage_(default_buffer_size) + { + } + + /// Construct, passing the specified argument to initialise the next layer. + template + buffered_read_stream(Arg& a, std::size_t buffer_size) + : next_layer_(a), + storage_(buffer_size) + { + } + + /// Get a reference to the next layer. + next_layer_type& next_layer() + { + return next_layer_; + } + + /// Get a reference to the lowest layer. + lowest_layer_type& lowest_layer() + { + return next_layer_.lowest_layer(); + } + + /// (Deprecated: use get_io_service().) Get the io_service associated with + /// the object. + boost::asio::io_service& io_service() + { + return next_layer_.get_io_service(); + } + + /// Get the io_service associated with the object. + boost::asio::io_service& get_io_service() + { + return next_layer_.get_io_service(); + } + + /// Close the stream. + void close() + { + next_layer_.close(); + } + + /// Close the stream. + boost::system::error_code close(boost::system::error_code& ec) + { + return next_layer_.close(ec); + } + + /// Write the given data to the stream. Returns the number of bytes written. + /// Throws an exception on failure. + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + return next_layer_.write_some(buffers); + } + + /// Write the given data to the stream. Returns the number of bytes written, + /// or 0 if an error occurred. + template + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return next_layer_.write_some(buffers, ec); + } + + /// Start an asynchronous write. The data being written must be valid for the + /// lifetime of the asynchronous operation. + template + void async_write_some(const ConstBufferSequence& buffers, + WriteHandler handler) + { + next_layer_.async_write_some(buffers, handler); + } + + /// Fill the buffer with some data. Returns the number of bytes placed in the + /// buffer as a result of the operation. Throws an exception on failure. + std::size_t fill() + { + detail::buffer_resize_guard + resize_guard(storage_); + std::size_t previous_size = storage_.size(); + storage_.resize(storage_.capacity()); + storage_.resize(previous_size + next_layer_.read_some(buffer( + storage_.data() + previous_size, + storage_.size() - previous_size))); + resize_guard.commit(); + return storage_.size() - previous_size; + } + + /// Fill the buffer with some data. Returns the number of bytes placed in the + /// buffer as a result of the operation, or 0 if an error occurred. + std::size_t fill(boost::system::error_code& ec) + { + detail::buffer_resize_guard + resize_guard(storage_); + std::size_t previous_size = storage_.size(); + storage_.resize(storage_.capacity()); + storage_.resize(previous_size + next_layer_.read_some(buffer( + storage_.data() + previous_size, + storage_.size() - previous_size), + ec)); + resize_guard.commit(); + return storage_.size() - previous_size; + } + + template + class fill_handler + { + public: + fill_handler(boost::asio::io_service& io_service, + detail::buffered_stream_storage& storage, + std::size_t previous_size, ReadHandler handler) + : io_service_(io_service), + storage_(storage), + previous_size_(previous_size), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + storage_.resize(previous_size_ + bytes_transferred); + io_service_.dispatch(detail::bind_handler( + handler_, ec, bytes_transferred)); + } + + private: + boost::asio::io_service& io_service_; + detail::buffered_stream_storage& storage_; + std::size_t previous_size_; + ReadHandler handler_; + }; + + /// Start an asynchronous fill. + template + void async_fill(ReadHandler handler) + { + std::size_t previous_size = storage_.size(); + storage_.resize(storage_.capacity()); + next_layer_.async_read_some( + buffer( + storage_.data() + previous_size, + storage_.size() - previous_size), + fill_handler(get_io_service(), + storage_, previous_size, handler)); + } + + /// Read some data from the stream. Returns the number of bytes read. Throws + /// an exception on failure. + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + if (storage_.empty()) + fill(); + return copy(buffers); + } + + /// Read some data from the stream. Returns the number of bytes read or 0 if + /// an error occurred. + template + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + ec = boost::system::error_code(); + if (storage_.empty() && !fill(ec)) + return 0; + return copy(buffers); + } + + template + class read_some_handler + { + public: + read_some_handler(boost::asio::io_service& io_service, + detail::buffered_stream_storage& storage, + const MutableBufferSequence& buffers, ReadHandler handler) + : io_service_(io_service), + storage_(storage), + buffers_(buffers), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, std::size_t) + { + if (ec || storage_.empty()) + { + std::size_t length = 0; + io_service_.dispatch(detail::bind_handler(handler_, ec, length)); + } + else + { + using namespace std; // For memcpy. + + std::size_t bytes_avail = storage_.size(); + std::size_t bytes_copied = 0; + + typename MutableBufferSequence::const_iterator iter = buffers_.begin(); + typename MutableBufferSequence::const_iterator end = buffers_.end(); + for (; iter != end && bytes_avail > 0; ++iter) + { + std::size_t max_length = buffer_size(*iter); + std::size_t length = (max_length < bytes_avail) + ? max_length : bytes_avail; + memcpy(buffer_cast(*iter), + storage_.data() + bytes_copied, length); + bytes_copied += length; + bytes_avail -= length; + } + + storage_.consume(bytes_copied); + io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied)); + } + } + + private: + boost::asio::io_service& io_service_; + detail::buffered_stream_storage& storage_; + MutableBufferSequence buffers_; + ReadHandler handler_; + }; + + /// Start an asynchronous read. The buffer into which the data will be read + /// must be valid for the lifetime of the asynchronous operation. + template + void async_read_some(const MutableBufferSequence& buffers, + ReadHandler handler) + { + if (storage_.empty()) + { + async_fill(read_some_handler( + get_io_service(), storage_, buffers, handler)); + } + else + { + std::size_t length = copy(buffers); + get_io_service().post(detail::bind_handler( + handler, boost::system::error_code(), length)); + } + } + + /// Peek at the incoming data on the stream. Returns the number of bytes read. + /// Throws an exception on failure. + template + std::size_t peek(const MutableBufferSequence& buffers) + { + if (storage_.empty()) + fill(); + return peek_copy(buffers); + } + + /// Peek at the incoming data on the stream. Returns the number of bytes read, + /// or 0 if an error occurred. + template + std::size_t peek(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + ec = boost::system::error_code(); + if (storage_.empty() && !fill(ec)) + return 0; + return peek_copy(buffers); + } + + /// Determine the amount of data that may be read without blocking. + std::size_t in_avail() + { + return storage_.size(); + } + + /// Determine the amount of data that may be read without blocking. + std::size_t in_avail(boost::system::error_code& ec) + { + ec = boost::system::error_code(); + return storage_.size(); + } + +private: + /// Copy data out of the internal buffer to the specified target buffer. + /// Returns the number of bytes copied. + template + std::size_t copy(const MutableBufferSequence& buffers) + { + using namespace std; // For memcpy. + + std::size_t bytes_avail = storage_.size(); + std::size_t bytes_copied = 0; + + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + for (; iter != end && bytes_avail > 0; ++iter) + { + std::size_t max_length = buffer_size(*iter); + std::size_t length = (max_length < bytes_avail) + ? max_length : bytes_avail; + memcpy(buffer_cast(*iter), storage_.data() + bytes_copied, length); + bytes_copied += length; + bytes_avail -= length; + } + + storage_.consume(bytes_copied); + return bytes_copied; + } + + /// Copy data from the internal buffer to the specified target buffer, without + /// removing the data from the internal buffer. Returns the number of bytes + /// copied. + template + std::size_t peek_copy(const MutableBufferSequence& buffers) + { + using namespace std; // For memcpy. + + std::size_t bytes_avail = storage_.size(); + std::size_t bytes_copied = 0; + + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + for (; iter != end && bytes_avail > 0; ++iter) + { + std::size_t max_length = buffer_size(*iter); + std::size_t length = (max_length < bytes_avail) + ? max_length : bytes_avail; + memcpy(buffer_cast(*iter), storage_.data() + bytes_copied, length); + bytes_copied += length; + bytes_avail -= length; + } + + return bytes_copied; + } + + /// The next layer. + Stream next_layer_; + + // The data in the buffer. + detail::buffered_stream_storage storage_; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BUFFERED_READ_STREAM_HPP diff --git a/win32/include/boost/asio/buffered_read_stream_fwd.hpp b/win32/include/boost/asio/buffered_read_stream_fwd.hpp new file mode 100755 index 000000000..5e358e029 --- /dev/null +++ b/win32/include/boost/asio/buffered_read_stream_fwd.hpp @@ -0,0 +1,31 @@ +// +// buffered_read_stream_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERED_READ_STREAM_FWD_HPP +#define BOOST_ASIO_BUFFERED_READ_STREAM_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +namespace boost { +namespace asio { + +template +class buffered_read_stream; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BUFFERED_READ_STREAM_FWD_HPP diff --git a/win32/include/boost/asio/buffered_stream.hpp b/win32/include/boost/asio/buffered_stream.hpp new file mode 100755 index 000000000..45a7a6c11 --- /dev/null +++ b/win32/include/boost/asio/buffered_stream.hpp @@ -0,0 +1,252 @@ +// +// buffered_stream.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERED_STREAM_HPP +#define BOOST_ASIO_BUFFERED_STREAM_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Adds buffering to the read- and write-related operations of a stream. +/** + * The buffered_stream class template can be used to add buffering to the + * synchronous and asynchronous read and write operations of a stream. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template +class buffered_stream + : private noncopyable +{ +public: + /// The type of the next layer. + typedef typename boost::remove_reference::type next_layer_type; + + /// The type of the lowest layer. + typedef typename next_layer_type::lowest_layer_type lowest_layer_type; + + /// Construct, passing the specified argument to initialise the next layer. + template + explicit buffered_stream(Arg& a) + : inner_stream_impl_(a), + stream_impl_(inner_stream_impl_) + { + } + + /// Construct, passing the specified argument to initialise the next layer. + template + explicit buffered_stream(Arg& a, std::size_t read_buffer_size, + std::size_t write_buffer_size) + : inner_stream_impl_(a, write_buffer_size), + stream_impl_(inner_stream_impl_, read_buffer_size) + { + } + + /// Get a reference to the next layer. + next_layer_type& next_layer() + { + return stream_impl_.next_layer().next_layer(); + } + + /// Get a reference to the lowest layer. + lowest_layer_type& lowest_layer() + { + return stream_impl_.lowest_layer(); + } + + /// (Deprecated: use get_io_service().) Get the io_service associated with + /// the object. + boost::asio::io_service& io_service() + { + return stream_impl_.get_io_service(); + } + + /// Get the io_service associated with the object. + boost::asio::io_service& get_io_service() + { + return stream_impl_.get_io_service(); + } + + /// Close the stream. + void close() + { + stream_impl_.close(); + } + + /// Close the stream. + boost::system::error_code close(boost::system::error_code& ec) + { + return stream_impl_.close(ec); + } + + /// Flush all data from the buffer to the next layer. Returns the number of + /// bytes written to the next layer on the last write operation. Throws an + /// exception on failure. + std::size_t flush() + { + return stream_impl_.next_layer().flush(); + } + + /// Flush all data from the buffer to the next layer. Returns the number of + /// bytes written to the next layer on the last write operation, or 0 if an + /// error occurred. + std::size_t flush(boost::system::error_code& ec) + { + return stream_impl_.next_layer().flush(ec); + } + + /// Start an asynchronous flush. + template + void async_flush(WriteHandler handler) + { + return stream_impl_.next_layer().async_flush(handler); + } + + /// Write the given data to the stream. Returns the number of bytes written. + /// Throws an exception on failure. + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + return stream_impl_.write_some(buffers); + } + + /// Write the given data to the stream. Returns the number of bytes written, + /// or 0 if an error occurred. + template + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return stream_impl_.write_some(buffers, ec); + } + + /// Start an asynchronous write. The data being written must be valid for the + /// lifetime of the asynchronous operation. + template + void async_write_some(const ConstBufferSequence& buffers, + WriteHandler handler) + { + stream_impl_.async_write_some(buffers, handler); + } + + /// Fill the buffer with some data. Returns the number of bytes placed in the + /// buffer as a result of the operation. Throws an exception on failure. + std::size_t fill() + { + return stream_impl_.fill(); + } + + /// Fill the buffer with some data. Returns the number of bytes placed in the + /// buffer as a result of the operation, or 0 if an error occurred. + std::size_t fill(boost::system::error_code& ec) + { + return stream_impl_.fill(ec); + } + + /// Start an asynchronous fill. + template + void async_fill(ReadHandler handler) + { + stream_impl_.async_fill(handler); + } + + /// Read some data from the stream. Returns the number of bytes read. Throws + /// an exception on failure. + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + return stream_impl_.read_some(buffers); + } + + /// Read some data from the stream. Returns the number of bytes read or 0 if + /// an error occurred. + template + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return stream_impl_.read_some(buffers, ec); + } + + /// Start an asynchronous read. The buffer into which the data will be read + /// must be valid for the lifetime of the asynchronous operation. + template + void async_read_some(const MutableBufferSequence& buffers, + ReadHandler handler) + { + stream_impl_.async_read_some(buffers, handler); + } + + /// Peek at the incoming data on the stream. Returns the number of bytes read. + /// Throws an exception on failure. + template + std::size_t peek(const MutableBufferSequence& buffers) + { + return stream_impl_.peek(buffers); + } + + /// Peek at the incoming data on the stream. Returns the number of bytes read, + /// or 0 if an error occurred. + template + std::size_t peek(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return stream_impl_.peek(buffers, ec); + } + + /// Determine the amount of data that may be read without blocking. + std::size_t in_avail() + { + return stream_impl_.in_avail(); + } + + /// Determine the amount of data that may be read without blocking. + std::size_t in_avail(boost::system::error_code& ec) + { + return stream_impl_.in_avail(ec); + } + +private: + // The buffered write stream. + typedef buffered_write_stream write_stream_type; + write_stream_type inner_stream_impl_; + + // The buffered read stream. + typedef buffered_read_stream read_stream_type; + read_stream_type stream_impl_; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BUFFERED_STREAM_HPP diff --git a/win32/include/boost/asio/buffered_stream_fwd.hpp b/win32/include/boost/asio/buffered_stream_fwd.hpp new file mode 100755 index 000000000..b67430bbe --- /dev/null +++ b/win32/include/boost/asio/buffered_stream_fwd.hpp @@ -0,0 +1,31 @@ +// +// buffered_stream_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERED_STREAM_FWD_HPP +#define BOOST_ASIO_BUFFERED_STREAM_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +namespace boost { +namespace asio { + +template +class buffered_stream; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BUFFERED_STREAM_FWD_HPP diff --git a/win32/include/boost/asio/buffered_write_stream.hpp b/win32/include/boost/asio/buffered_write_stream.hpp new file mode 100755 index 000000000..6ff703a7f --- /dev/null +++ b/win32/include/boost/asio/buffered_write_stream.hpp @@ -0,0 +1,370 @@ +// +// buffered_write_stream.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERED_WRITE_STREAM_HPP +#define BOOST_ASIO_BUFFERED_WRITE_STREAM_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Adds buffering to the write-related operations of a stream. +/** + * The buffered_write_stream class template can be used to add buffering to the + * synchronous and asynchronous write operations of a stream. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template +class buffered_write_stream + : private noncopyable +{ +public: + /// The type of the next layer. + typedef typename boost::remove_reference::type next_layer_type; + + /// The type of the lowest layer. + typedef typename next_layer_type::lowest_layer_type lowest_layer_type; + +#if defined(GENERATING_DOCUMENTATION) + /// The default buffer size. + static const std::size_t default_buffer_size = implementation_defined; +#else + BOOST_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024); +#endif + + /// Construct, passing the specified argument to initialise the next layer. + template + explicit buffered_write_stream(Arg& a) + : next_layer_(a), + storage_(default_buffer_size) + { + } + + /// Construct, passing the specified argument to initialise the next layer. + template + buffered_write_stream(Arg& a, std::size_t buffer_size) + : next_layer_(a), + storage_(buffer_size) + { + } + + /// Get a reference to the next layer. + next_layer_type& next_layer() + { + return next_layer_; + } + + /// Get a reference to the lowest layer. + lowest_layer_type& lowest_layer() + { + return next_layer_.lowest_layer(); + } + + /// (Deprecated: use get_io_service().) Get the io_service associated with + /// the object. + boost::asio::io_service& io_service() + { + return next_layer_.get_io_service(); + } + + /// Get the io_service associated with the object. + boost::asio::io_service& get_io_service() + { + return next_layer_.get_io_service(); + } + + /// Close the stream. + void close() + { + next_layer_.close(); + } + + /// Close the stream. + boost::system::error_code close(boost::system::error_code& ec) + { + return next_layer_.close(ec); + } + + /// Flush all data from the buffer to the next layer. Returns the number of + /// bytes written to the next layer on the last write operation. Throws an + /// exception on failure. + std::size_t flush() + { + std::size_t bytes_written = write(next_layer_, + buffer(storage_.data(), storage_.size())); + storage_.consume(bytes_written); + return bytes_written; + } + + /// Flush all data from the buffer to the next layer. Returns the number of + /// bytes written to the next layer on the last write operation, or 0 if an + /// error occurred. + std::size_t flush(boost::system::error_code& ec) + { + std::size_t bytes_written = write(next_layer_, + buffer(storage_.data(), storage_.size()), + transfer_all(), ec); + storage_.consume(bytes_written); + return bytes_written; + } + + template + class flush_handler + { + public: + flush_handler(boost::asio::io_service& io_service, + detail::buffered_stream_storage& storage, WriteHandler handler) + : io_service_(io_service), + storage_(storage), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_written) + { + storage_.consume(bytes_written); + io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_written)); + } + + private: + boost::asio::io_service& io_service_; + detail::buffered_stream_storage& storage_; + WriteHandler handler_; + }; + + /// Start an asynchronous flush. + template + void async_flush(WriteHandler handler) + { + async_write(next_layer_, buffer(storage_.data(), storage_.size()), + flush_handler(get_io_service(), storage_, handler)); + } + + /// Write the given data to the stream. Returns the number of bytes written. + /// Throws an exception on failure. + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + if (storage_.size() == storage_.capacity()) + flush(); + return copy(buffers); + } + + /// Write the given data to the stream. Returns the number of bytes written, + /// or 0 if an error occurred and the error handler did not throw. + template + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + ec = boost::system::error_code(); + if (storage_.size() == storage_.capacity() && !flush(ec)) + return 0; + return copy(buffers); + } + + template + class write_some_handler + { + public: + write_some_handler(boost::asio::io_service& io_service, + detail::buffered_stream_storage& storage, + const ConstBufferSequence& buffers, WriteHandler handler) + : io_service_(io_service), + storage_(storage), + buffers_(buffers), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, std::size_t) + { + if (ec) + { + std::size_t length = 0; + io_service_.dispatch(detail::bind_handler(handler_, ec, length)); + } + else + { + using namespace std; // For memcpy. + + std::size_t orig_size = storage_.size(); + std::size_t space_avail = storage_.capacity() - orig_size; + std::size_t bytes_copied = 0; + + typename ConstBufferSequence::const_iterator iter = buffers_.begin(); + typename ConstBufferSequence::const_iterator end = buffers_.end(); + for (; iter != end && space_avail > 0; ++iter) + { + std::size_t bytes_avail = buffer_size(*iter); + std::size_t length = (bytes_avail < space_avail) + ? bytes_avail : space_avail; + storage_.resize(orig_size + bytes_copied + length); + memcpy(storage_.data() + orig_size + bytes_copied, + buffer_cast(*iter), length); + bytes_copied += length; + space_avail -= length; + } + + io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied)); + } + } + + private: + boost::asio::io_service& io_service_; + detail::buffered_stream_storage& storage_; + ConstBufferSequence buffers_; + WriteHandler handler_; + }; + + /// Start an asynchronous write. The data being written must be valid for the + /// lifetime of the asynchronous operation. + template + void async_write_some(const ConstBufferSequence& buffers, + WriteHandler handler) + { + if (storage_.size() == storage_.capacity()) + { + async_flush(write_some_handler( + get_io_service(), storage_, buffers, handler)); + } + else + { + std::size_t bytes_copied = copy(buffers); + get_io_service().post(detail::bind_handler( + handler, boost::system::error_code(), bytes_copied)); + } + } + + /// Read some data from the stream. Returns the number of bytes read. Throws + /// an exception on failure. + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + return next_layer_.read_some(buffers); + } + + /// Read some data from the stream. Returns the number of bytes read or 0 if + /// an error occurred. + template + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return next_layer_.read_some(buffers, ec); + } + + /// Start an asynchronous read. The buffer into which the data will be read + /// must be valid for the lifetime of the asynchronous operation. + template + void async_read_some(const MutableBufferSequence& buffers, + ReadHandler handler) + { + next_layer_.async_read_some(buffers, handler); + } + + /// Peek at the incoming data on the stream. Returns the number of bytes read. + /// Throws an exception on failure. + template + std::size_t peek(const MutableBufferSequence& buffers) + { + return next_layer_.peek(buffers); + } + + /// Peek at the incoming data on the stream. Returns the number of bytes read, + /// or 0 if an error occurred. + template + std::size_t peek(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return next_layer_.peek(buffers, ec); + } + + /// Determine the amount of data that may be read without blocking. + std::size_t in_avail() + { + return next_layer_.in_avail(); + } + + /// Determine the amount of data that may be read without blocking. + std::size_t in_avail(boost::system::error_code& ec) + { + return next_layer_.in_avail(ec); + } + +private: + /// Copy data into the internal buffer from the specified source buffer. + /// Returns the number of bytes copied. + template + std::size_t copy(const ConstBufferSequence& buffers) + { + using namespace std; // For memcpy. + + std::size_t orig_size = storage_.size(); + std::size_t space_avail = storage_.capacity() - orig_size; + std::size_t bytes_copied = 0; + + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + for (; iter != end && space_avail > 0; ++iter) + { + std::size_t bytes_avail = buffer_size(*iter); + std::size_t length = (bytes_avail < space_avail) + ? bytes_avail : space_avail; + storage_.resize(orig_size + bytes_copied + length); + memcpy(storage_.data() + orig_size + bytes_copied, + buffer_cast(*iter), length); + bytes_copied += length; + space_avail -= length; + } + + return bytes_copied; + } + + /// The next layer. + Stream next_layer_; + + // The data in the buffer. + detail::buffered_stream_storage storage_; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BUFFERED_WRITE_STREAM_HPP diff --git a/win32/include/boost/asio/buffered_write_stream_fwd.hpp b/win32/include/boost/asio/buffered_write_stream_fwd.hpp new file mode 100755 index 000000000..d40fefe8d --- /dev/null +++ b/win32/include/boost/asio/buffered_write_stream_fwd.hpp @@ -0,0 +1,31 @@ +// +// buffered_write_stream_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERED_WRITE_STREAM_FWD_HPP +#define BOOST_ASIO_BUFFERED_WRITE_STREAM_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +namespace boost { +namespace asio { + +template +class buffered_write_stream; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BUFFERED_WRITE_STREAM_FWD_HPP diff --git a/win32/include/boost/asio/buffers_iterator.hpp b/win32/include/boost/asio/buffers_iterator.hpp new file mode 100755 index 000000000..d4cfbcb6f --- /dev/null +++ b/win32/include/boost/asio/buffers_iterator.hpp @@ -0,0 +1,320 @@ +// +// buffers_iterator.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERS_ITERATOR_HPP +#define BOOST_ASIO_BUFFERS_ITERATOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { + +namespace detail +{ + template + struct buffers_iterator_types_helper; + + template <> + struct buffers_iterator_types_helper + { + typedef const_buffer buffer_type; + template + struct byte_type + { + typedef typename boost::add_const::type type; + }; + }; + + template <> + struct buffers_iterator_types_helper + { + typedef mutable_buffer buffer_type; + template + struct byte_type + { + typedef ByteType type; + }; + }; + + template + struct buffers_iterator_types + { + enum + { + is_mutable = boost::is_convertible< + typename BufferSequence::value_type, mutable_buffer>::value + }; + typedef buffers_iterator_types_helper helper; + typedef typename helper::buffer_type buffer_type; + typedef typename helper::template byte_type::type byte_type; + }; +} + +/// A random access iterator over the bytes in a buffer sequence. +template +class buffers_iterator + : public boost::iterator_facade< + buffers_iterator, + typename detail::buffers_iterator_types< + BufferSequence, ByteType>::byte_type, + boost::random_access_traversal_tag> +{ +private: + typedef typename detail::buffers_iterator_types< + BufferSequence, ByteType>::buffer_type buffer_type; + typedef typename detail::buffers_iterator_types< + BufferSequence, ByteType>::byte_type byte_type; + +public: + /// Default constructor. Creates an iterator in an undefined state. + buffers_iterator() + : current_buffer_(), + current_buffer_position_(0), + begin_(), + current_(), + end_(), + position_(0) + { + } + + /// Construct an iterator representing the beginning of the buffers' data. + static buffers_iterator begin(const BufferSequence& buffers) + { + buffers_iterator new_iter; + new_iter.begin_ = buffers.begin(); + new_iter.current_ = buffers.begin(); + new_iter.end_ = buffers.end(); + while (new_iter.current_ != new_iter.end_) + { + new_iter.current_buffer_ = *new_iter.current_; + if (boost::asio::buffer_size(new_iter.current_buffer_) > 0) + break; + ++new_iter.current_; + } + return new_iter; + } + + /// Construct an iterator representing the end of the buffers' data. + static buffers_iterator end(const BufferSequence& buffers) + { + buffers_iterator new_iter; + new_iter.begin_ = buffers.begin(); + new_iter.current_ = buffers.begin(); + new_iter.end_ = buffers.end(); + while (new_iter.current_ != new_iter.end_) + { + buffer_type buffer = *new_iter.current_; + new_iter.position_ += boost::asio::buffer_size(buffer); + ++new_iter.current_; + } + return new_iter; + } + +private: + friend class boost::iterator_core_access; + + // Dereference the iterator. + byte_type& dereference() const + { + return buffer_cast(current_buffer_)[current_buffer_position_]; + } + + // Compare two iterators for equality. + bool equal(const buffers_iterator& other) const + { + return position_ == other.position_; + } + + // Increment the iterator. + void increment() + { + BOOST_ASSERT(current_ != end_ && "iterator out of bounds"); + ++position_; + + // Check if the increment can be satisfied by the current buffer. + ++current_buffer_position_; + if (current_buffer_position_ != boost::asio::buffer_size(current_buffer_)) + return; + + // Find the next non-empty buffer. + ++current_; + current_buffer_position_ = 0; + while (current_ != end_) + { + current_buffer_ = *current_; + if (boost::asio::buffer_size(current_buffer_) > 0) + return; + ++current_; + } + } + + // Decrement the iterator. + void decrement() + { + BOOST_ASSERT(position_ > 0 && "iterator out of bounds"); + --position_; + + // Check if the decrement can be satisfied by the current buffer. + if (current_buffer_position_ != 0) + { + --current_buffer_position_; + return; + } + + // Find the previous non-empty buffer. + typename BufferSequence::const_iterator iter = current_; + while (iter != begin_) + { + --iter; + buffer_type buffer = *iter; + std::size_t buffer_size = boost::asio::buffer_size(buffer); + if (buffer_size > 0) + { + current_ = iter; + current_buffer_ = buffer; + current_buffer_position_ = buffer_size - 1; + return; + } + } + } + + // Advance the iterator by the specified distance. + void advance(std::ptrdiff_t n) + { + if (n > 0) + { + BOOST_ASSERT(current_ != end_ && "iterator out of bounds"); + for (;;) + { + std::ptrdiff_t current_buffer_balance + = boost::asio::buffer_size(current_buffer_) + - current_buffer_position_; + + // Check if the advance can be satisfied by the current buffer. + if (current_buffer_balance > n) + { + position_ += n; + current_buffer_position_ += n; + return; + } + + // Update position. + n -= current_buffer_balance; + position_ += current_buffer_balance; + + // Move to next buffer. If it is empty then it will be skipped on the + // next iteration of this loop. + if (++current_ == end_) + { + BOOST_ASSERT(n == 0 && "iterator out of bounds"); + current_buffer_ = buffer_type(); + current_buffer_position_ = 0; + return; + } + current_buffer_ = *current_; + current_buffer_position_ = 0; + } + } + else if (n < 0) + { + std::size_t abs_n = -n; + BOOST_ASSERT(position_ >= abs_n && "iterator out of bounds"); + for (;;) + { + // Check if the advance can be satisfied by the current buffer. + if (current_buffer_position_ >= abs_n) + { + position_ -= abs_n; + current_buffer_position_ -= abs_n; + return; + } + + // Update position. + abs_n -= current_buffer_position_; + position_ -= current_buffer_position_; + + // Check if we've reached the beginning of the buffers. + if (current_ == begin_) + { + BOOST_ASSERT(abs_n == 0 && "iterator out of bounds"); + current_buffer_position_ = 0; + return; + } + + // Find the previous non-empty buffer. + typename BufferSequence::const_iterator iter = current_; + while (iter != begin_) + { + --iter; + buffer_type buffer = *iter; + std::size_t buffer_size = boost::asio::buffer_size(buffer); + if (buffer_size > 0) + { + current_ = iter; + current_buffer_ = buffer; + current_buffer_position_ = buffer_size; + break; + } + } + } + } + } + + // Determine the distance between two iterators. + std::ptrdiff_t distance_to(const buffers_iterator& other) const + { + return other.position_ - position_; + } + + buffer_type current_buffer_; + std::size_t current_buffer_position_; + typename BufferSequence::const_iterator begin_; + typename BufferSequence::const_iterator current_; + typename BufferSequence::const_iterator end_; + std::size_t position_; +}; + +/// Construct an iterator representing the beginning of the buffers' data. +template +inline buffers_iterator buffers_begin( + const BufferSequence& buffers) +{ + return buffers_iterator::begin(buffers); +} + +/// Construct an iterator representing the end of the buffers' data. +template +inline buffers_iterator buffers_end( + const BufferSequence& buffers) +{ + return buffers_iterator::end(buffers); +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_BUFFERS_ITERATOR_HPP diff --git a/win32/include/boost/asio/completion_condition.hpp b/win32/include/boost/asio/completion_condition.hpp new file mode 100755 index 000000000..05e848df8 --- /dev/null +++ b/win32/include/boost/asio/completion_condition.hpp @@ -0,0 +1,147 @@ +// +// completion_condition.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_COMPLETION_CONDITION_HPP +#define BOOST_ASIO_COMPLETION_CONDITION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { + +namespace detail { + +class transfer_all_t +{ +public: + typedef bool result_type; + + template + bool operator()(const Error& err, std::size_t) + { + return !!err; + } +}; + +class transfer_at_least_t +{ +public: + typedef bool result_type; + + explicit transfer_at_least_t(std::size_t minimum) + : minimum_(minimum) + { + } + + template + bool operator()(const Error& err, std::size_t bytes_transferred) + { + return !!err || bytes_transferred >= minimum_; + } + +private: + std::size_t minimum_; +}; + +} // namespace detail + +/** + * @defgroup completion_condition Completion Condition Function Objects + * + * Function objects used for determining when a read or write operation should + * complete. + */ +/*@{*/ + +/// Return a completion condition function object that indicates that a read or +/// write operation should continue until all of the data has been transferred, +/// or until an error occurs. +/** + * This function is used to create an object, of unspecified type, that meets + * CompletionCondition requirements. + * + * @par Example + * Reading until a buffer is full: + * @code + * boost::array buf; + * boost::system::error_code ec; + * std::size_t n = boost::asio::read( + * sock, boost::asio::buffer(buf), + * boost::asio::transfer_all(), ec); + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * // n == 128 + * } + * @endcode + */ +#if defined(GENERATING_DOCUMENTATION) +unspecified transfer_all(); +#else +inline detail::transfer_all_t transfer_all() +{ + return detail::transfer_all_t(); +} +#endif + +/// Return a completion condition function object that indicates that a read or +/// write operation should continue until a minimum number of bytes has been +/// transferred, or until an error occurs. +/** + * This function is used to create an object, of unspecified type, that meets + * CompletionCondition requirements. + * + * @par Example + * Reading until a buffer is full or contains at least 64 bytes: + * @code + * boost::array buf; + * boost::system::error_code ec; + * std::size_t n = boost::asio::read( + * sock, boost::asio::buffer(buf), + * boost::asio::transfer_at_least(64), ec); + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * // n >= 64 && n <= 128 + * } + * @endcode + */ +#if defined(GENERATING_DOCUMENTATION) +unspecified transfer_at_least(std::size_t minimum); +#else +inline detail::transfer_at_least_t transfer_at_least(std::size_t minimum) +{ + return detail::transfer_at_least_t(minimum); +} +#endif + +/*@}*/ + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_COMPLETION_CONDITION_HPP diff --git a/win32/include/boost/asio/datagram_socket_service.hpp b/win32/include/boost/asio/datagram_socket_service.hpp new file mode 100755 index 000000000..2f362ffa5 --- /dev/null +++ b/win32/include/boost/asio/datagram_socket_service.hpp @@ -0,0 +1,325 @@ +// +// datagram_socket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP +#define BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Default service implementation for a datagram socket. +template +class datagram_socket_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base > +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + +private: + // The type of the platform-specific implementation. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef detail::win_iocp_socket_service service_impl_type; +#elif defined(BOOST_ASIO_HAS_EPOLL) + typedef detail::reactive_socket_service< + Protocol, detail::epoll_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_KQUEUE) + typedef detail::reactive_socket_service< + Protocol, detail::kqueue_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_DEV_POLL) + typedef detail::reactive_socket_service< + Protocol, detail::dev_poll_reactor > service_impl_type; +#else + typedef detail::reactive_socket_service< + Protocol, detail::select_reactor > service_impl_type; +#endif + +public: + /// The type of a datagram socket. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef typename service_impl_type::implementation_type implementation_type; +#endif + + /// The native socket type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef typename service_impl_type::native_type native_type; +#endif + + /// Construct a new datagram socket service for the specified io_service. + explicit datagram_socket_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + datagram_socket_service >(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new datagram socket implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a datagram socket implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + // Open a new datagram socket implementation. + boost::system::error_code open(implementation_type& impl, + const protocol_type& protocol, boost::system::error_code& ec) + { + if (protocol.type() == SOCK_DGRAM) + service_impl_.open(impl, protocol, ec); + else + ec = boost::asio::error::invalid_argument; + return ec; + } + + /// Assign an existing native socket to a datagram socket. + boost::system::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_type& native_socket, + boost::system::error_code& ec) + { + return service_impl_.assign(impl, protocol, native_socket, ec); + } + + /// Determine whether the socket is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a datagram socket implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native socket implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the socket. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Determine whether the socket is at the out-of-band data mark. + bool at_mark(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.at_mark(impl, ec); + } + + /// Determine the number of bytes available for reading. + std::size_t available(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.available(impl, ec); + } + + // Bind the datagram socket to the specified local endpoint. + boost::system::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, boost::system::error_code& ec) + { + return service_impl_.bind(impl, endpoint, ec); + } + + /// Connect the datagram socket to the specified endpoint. + boost::system::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + return service_impl_.connect(impl, peer_endpoint, ec); + } + + /// Start an asynchronous connect. + template + void async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, ConnectHandler handler) + { + service_impl_.async_connect(impl, peer_endpoint, handler); + } + + /// Set a socket option. + template + boost::system::error_code set_option(implementation_type& impl, + const SettableSocketOption& option, boost::system::error_code& ec) + { + return service_impl_.set_option(impl, option, ec); + } + + /// Get a socket option. + template + boost::system::error_code get_option(const implementation_type& impl, + GettableSocketOption& option, boost::system::error_code& ec) const + { + return service_impl_.get_option(impl, option, ec); + } + + /// Perform an IO control command on the socket. + template + boost::system::error_code io_control(implementation_type& impl, + IoControlCommand& command, boost::system::error_code& ec) + { + return service_impl_.io_control(impl, command, ec); + } + + /// Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.local_endpoint(impl, ec); + } + + /// Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.remote_endpoint(impl, ec); + } + + /// Disable sends or receives on the socket. + boost::system::error_code shutdown(implementation_type& impl, + socket_base::shutdown_type what, boost::system::error_code& ec) + { + return service_impl_.shutdown(impl, what, ec); + } + + /// Send the given data to the peer. + template + std::size_t send(implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.send(impl, buffers, flags, ec); + } + + /// Start an asynchronous send. + template + void async_send(implementation_type& impl, const ConstBufferSequence& buffers, + socket_base::message_flags flags, WriteHandler handler) + { + service_impl_.async_send(impl, buffers, flags, handler); + } + + /// Send a datagram to the specified endpoint. + template + std::size_t send_to(implementation_type& impl, + const ConstBufferSequence& buffers, const endpoint_type& destination, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.send_to(impl, buffers, destination, flags, ec); + } + + /// Start an asynchronous send. + template + void async_send_to(implementation_type& impl, + const ConstBufferSequence& buffers, const endpoint_type& destination, + socket_base::message_flags flags, WriteHandler handler) + { + service_impl_.async_send_to(impl, buffers, destination, flags, handler); + } + + /// Receive some data from the peer. + template + std::size_t receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.receive(impl, buffers, flags, ec); + } + + /// Start an asynchronous receive. + template + void async_receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, ReadHandler handler) + { + service_impl_.async_receive(impl, buffers, flags, handler); + } + + /// Receive a datagram with the endpoint of the sender. + template + std::size_t receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.receive_from(impl, buffers, sender_endpoint, flags, + ec); + } + + /// Start an asynchronous receive that will get the endpoint of the sender. + template + void async_receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, ReadHandler handler) + { + service_impl_.async_receive_from(impl, buffers, sender_endpoint, flags, + handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP diff --git a/win32/include/boost/asio/deadline_timer.hpp b/win32/include/boost/asio/deadline_timer.hpp new file mode 100755 index 000000000..c5807b476 --- /dev/null +++ b/win32/include/boost/asio/deadline_timer.hpp @@ -0,0 +1,39 @@ +// +// deadline_timer.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DEADLINE_TIMER_HPP +#define BOOST_ASIO_DEADLINE_TIMER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include // Must come before posix_time. + +#include +#include +#include + +#include + +namespace boost { +namespace asio { + +/// Typedef for the typical usage of timer. +typedef basic_deadline_timer deadline_timer; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DEADLINE_TIMER_HPP diff --git a/win32/include/boost/asio/deadline_timer_service.hpp b/win32/include/boost/asio/deadline_timer_service.hpp new file mode 100755 index 000000000..56bc78e1d --- /dev/null +++ b/win32/include/boost/asio/deadline_timer_service.hpp @@ -0,0 +1,170 @@ +// +// deadline_timer_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DEADLINE_TIMER_SERVICE_HPP +#define BOOST_ASIO_DEADLINE_TIMER_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Default service implementation for a timer. +template > +class deadline_timer_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base< + deadline_timer_service > +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + + /// The time traits type. + typedef TimeTraits traits_type; + + /// The time type. + typedef typename traits_type::time_type time_type; + + /// The duration type. + typedef typename traits_type::duration_type duration_type; + +private: + // The type of the platform-specific implementation. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef detail::deadline_timer_service< + traits_type, detail::win_iocp_io_service> service_impl_type; +#elif defined(BOOST_ASIO_HAS_EPOLL) + typedef detail::deadline_timer_service< + traits_type, detail::epoll_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_KQUEUE) + typedef detail::deadline_timer_service< + traits_type, detail::kqueue_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_DEV_POLL) + typedef detail::deadline_timer_service< + traits_type, detail::dev_poll_reactor > service_impl_type; +#else + typedef detail::deadline_timer_service< + traits_type, detail::select_reactor > service_impl_type; +#endif + +public: + /// The implementation type of the deadline timer. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef typename service_impl_type::implementation_type implementation_type; +#endif + + /// Construct a new timer service for the specified io_service. + explicit deadline_timer_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + deadline_timer_service >(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new timer implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a timer implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Cancel any asynchronous wait operations associated with the timer. + std::size_t cancel(implementation_type& impl, boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Get the expiry time for the timer as an absolute time. + time_type expires_at(const implementation_type& impl) const + { + return service_impl_.expires_at(impl); + } + + /// Set the expiry time for the timer as an absolute time. + std::size_t expires_at(implementation_type& impl, + const time_type& expiry_time, boost::system::error_code& ec) + { + return service_impl_.expires_at(impl, expiry_time, ec); + } + + /// Get the expiry time for the timer relative to now. + duration_type expires_from_now(const implementation_type& impl) const + { + return service_impl_.expires_from_now(impl); + } + + /// Set the expiry time for the timer relative to now. + std::size_t expires_from_now(implementation_type& impl, + const duration_type& expiry_time, boost::system::error_code& ec) + { + return service_impl_.expires_from_now(impl, expiry_time, ec); + } + + // Perform a blocking wait on the timer. + void wait(implementation_type& impl, boost::system::error_code& ec) + { + service_impl_.wait(impl, ec); + } + + // Start an asynchronous wait on the timer. + template + void async_wait(implementation_type& impl, WaitHandler handler) + { + service_impl_.async_wait(impl, handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DEADLINE_TIMER_SERVICE_HPP diff --git a/win32/include/boost/asio/detail/bind_handler.hpp b/win32/include/boost/asio/detail/bind_handler.hpp new file mode 100755 index 000000000..6f5f4df6c --- /dev/null +++ b/win32/include/boost/asio/detail/bind_handler.hpp @@ -0,0 +1,351 @@ +// +// bind_handler.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_BIND_HANDLER_HPP +#define BOOST_ASIO_DETAIL_BIND_HANDLER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class binder1 +{ +public: + binder1(const Handler& handler, const Arg1& arg1) + : handler_(handler), + arg1_(arg1) + { + } + + void operator()() + { + handler_(arg1_); + } + + void operator()() const + { + handler_(arg1_); + } + +//private: + Handler handler_; + Arg1 arg1_; +}; + +template +inline void* asio_handler_allocate(std::size_t size, + binder1* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); +} + +template +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder1* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); +} + +template +inline void asio_handler_invoke(const Function& function, + binder1* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); +} + +template +inline binder1 bind_handler(const Handler& handler, + const Arg1& arg1) +{ + return binder1(handler, arg1); +} + +template +class binder2 +{ +public: + binder2(const Handler& handler, const Arg1& arg1, const Arg2& arg2) + : handler_(handler), + arg1_(arg1), + arg2_(arg2) + { + } + + void operator()() + { + handler_(arg1_, arg2_); + } + + void operator()() const + { + handler_(arg1_, arg2_); + } + +//private: + Handler handler_; + Arg1 arg1_; + Arg2 arg2_; +}; + +template +inline void* asio_handler_allocate(std::size_t size, + binder2* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); +} + +template +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder2* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); +} + +template +inline void asio_handler_invoke(const Function& function, + binder2* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); +} + +template +inline binder2 bind_handler(const Handler& handler, + const Arg1& arg1, const Arg2& arg2) +{ + return binder2(handler, arg1, arg2); +} + +template +class binder3 +{ +public: + binder3(const Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3) + : handler_(handler), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3) + { + } + + void operator()() + { + handler_(arg1_, arg2_, arg3_); + } + + void operator()() const + { + handler_(arg1_, arg2_, arg3_); + } + +//private: + Handler handler_; + Arg1 arg1_; + Arg2 arg2_; + Arg3 arg3_; +}; + +template +inline void* asio_handler_allocate(std::size_t size, + binder3* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); +} + +template +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder3* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); +} + +template +inline void asio_handler_invoke(const Function& function, + binder3* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); +} + +template +inline binder3 bind_handler(const Handler& handler, + const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) +{ + return binder3(handler, arg1, arg2, arg3); +} + +template +class binder4 +{ +public: + binder4(const Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4) + : handler_(handler), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3), + arg4_(arg4) + { + } + + void operator()() + { + handler_(arg1_, arg2_, arg3_, arg4_); + } + + void operator()() const + { + handler_(arg1_, arg2_, arg3_, arg4_); + } + +//private: + Handler handler_; + Arg1 arg1_; + Arg2 arg2_; + Arg3 arg3_; + Arg4 arg4_; +}; + +template +inline void* asio_handler_allocate(std::size_t size, + binder4* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); +} + +template +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder4* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); +} + +template +inline void asio_handler_invoke(const Function& function, + binder4* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); +} + +template +inline binder4 bind_handler( + const Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4) +{ + return binder4(handler, arg1, arg2, arg3, + arg4); +} + +template +class binder5 +{ +public: + binder5(const Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) + : handler_(handler), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3), + arg4_(arg4), + arg5_(arg5) + { + } + + void operator()() + { + handler_(arg1_, arg2_, arg3_, arg4_, arg5_); + } + + void operator()() const + { + handler_(arg1_, arg2_, arg3_, arg4_, arg5_); + } + +//private: + Handler handler_; + Arg1 arg1_; + Arg2 arg2_; + Arg3 arg3_; + Arg4 arg4_; + Arg5 arg5_; +}; + +template +inline void* asio_handler_allocate(std::size_t size, + binder5* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); +} + +template +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder5* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); +} + +template +inline void asio_handler_invoke(const Function& function, + binder5* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); +} + +template +inline binder5 bind_handler( + const Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) +{ + return binder5(handler, arg1, arg2, + arg3, arg4, arg5); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_BIND_HANDLER_HPP diff --git a/win32/include/boost/asio/detail/buffer_resize_guard.hpp b/win32/include/boost/asio/detail/buffer_resize_guard.hpp new file mode 100755 index 000000000..f90de2339 --- /dev/null +++ b/win32/include/boost/asio/detail/buffer_resize_guard.hpp @@ -0,0 +1,72 @@ +// +// buffer_resize_guard.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP +#define BOOST_ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +// Helper class to manage buffer resizing in an exception safe way. +template +class buffer_resize_guard +{ +public: + // Constructor. + buffer_resize_guard(Buffer& buffer) + : buffer_(buffer), + old_size_(buffer.size()) + { + } + + // Destructor rolls back the buffer resize unless commit was called. + ~buffer_resize_guard() + { + if (old_size_ + != std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()) + { + buffer_.resize(old_size_); + } + } + + // Commit the resize transaction. + void commit() + { + old_size_ + = std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION(); + } + +private: + // The buffer being managed. + Buffer& buffer_; + + // The size of the buffer at the time the guard was constructed. + size_t old_size_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP diff --git a/win32/include/boost/asio/detail/buffered_stream_storage.hpp b/win32/include/boost/asio/detail/buffered_stream_storage.hpp new file mode 100755 index 000000000..cab4a20f1 --- /dev/null +++ b/win32/include/boost/asio/detail/buffered_stream_storage.hpp @@ -0,0 +1,129 @@ +// +// buffered_stream_storage.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP +#define BOOST_ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +class buffered_stream_storage +{ +public: + // The type of the bytes stored in the buffer. + typedef unsigned char byte_type; + + // The type used for offsets into the buffer. + typedef std::size_t size_type; + + // Constructor. + explicit buffered_stream_storage(std::size_t capacity) + : begin_offset_(0), + end_offset_(0), + buffer_(capacity) + { + } + + /// Clear the buffer. + void clear() + { + begin_offset_ = 0; + end_offset_ = 0; + } + + // Return a pointer to the beginning of the unread data. + byte_type* data() + { + return &buffer_[0] + begin_offset_; + } + + // Return a pointer to the beginning of the unread data. + const byte_type* data() const + { + return &buffer_[0] + begin_offset_; + } + + // Is there no unread data in the buffer. + bool empty() const + { + return begin_offset_ == end_offset_; + } + + // Return the amount of unread data the is in the buffer. + size_type size() const + { + return end_offset_ - begin_offset_; + } + + // Resize the buffer to the specified length. + void resize(size_type length) + { + assert(length <= capacity()); + if (begin_offset_ + length <= capacity()) + { + end_offset_ = begin_offset_ + length; + } + else + { + using namespace std; // For memmove. + memmove(&buffer_[0], &buffer_[0] + begin_offset_, size()); + end_offset_ = length; + begin_offset_ = 0; + } + } + + // Return the maximum size for data in the buffer. + size_type capacity() const + { + return buffer_.size(); + } + + // Consume multiple bytes from the beginning of the buffer. + void consume(size_type count) + { + assert(begin_offset_ + count <= end_offset_); + begin_offset_ += count; + if (empty()) + clear(); + } + +private: + // The offset to the beginning of the unread data. + size_type begin_offset_; + + // The offset to the end of the unread data. + size_type end_offset_; + + // The data in the buffer. + std::vector buffer_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP diff --git a/win32/include/boost/asio/detail/call_stack.hpp b/win32/include/boost/asio/detail/call_stack.hpp new file mode 100755 index 000000000..55c097f7d --- /dev/null +++ b/win32/include/boost/asio/detail/call_stack.hpp @@ -0,0 +1,92 @@ +// +// call_stack.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_CALL_STACK_HPP +#define BOOST_ASIO_DETAIL_CALL_STACK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +// Helper class to determine whether or not the current thread is inside an +// invocation of io_service::run() for a specified io_service object. +template +class call_stack +{ +public: + // Context class automatically pushes an owner on to the stack. + class context + : private noncopyable + { + public: + // Push the owner on to the stack. + explicit context(Owner* d) + : owner_(d), + next_(call_stack::top_) + { + call_stack::top_ = this; + } + + // Pop the owner from the stack. + ~context() + { + call_stack::top_ = next_; + } + + private: + friend class call_stack; + + // The owner associated with the context. + Owner* owner_; + + // The next element in the stack. + context* next_; + }; + + friend class context; + + // Determine whether the specified owner is on the stack. + static bool contains(Owner* d) + { + context* elem = top_; + while (elem) + { + if (elem->owner_ == d) + return true; + elem = elem->next_; + } + return false; + } + +private: + // The top of the stack of calls for the current thread. + static tss_ptr top_; +}; + +template +tss_ptr::context> +call_stack::top_; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_CALL_STACK_HPP diff --git a/win32/include/boost/asio/detail/const_buffers_iterator.hpp b/win32/include/boost/asio/detail/const_buffers_iterator.hpp new file mode 100755 index 000000000..c09e5461b --- /dev/null +++ b/win32/include/boost/asio/detail/const_buffers_iterator.hpp @@ -0,0 +1,153 @@ +// +// const_buffers_iterator.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP +#define BOOST_ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +// A proxy iterator for a sub-range in a list of buffers. +template +class const_buffers_iterator + : public boost::iterator_facade, + const char, boost::bidirectional_traversal_tag> +{ +public: + // Default constructor creates an iterator in an undefined state. + const_buffers_iterator() + { + } + + // Create an iterator for the specified position. + const_buffers_iterator(const ConstBufferSequence& buffers, + std::size_t position) + : begin_(buffers.begin()), + current_(buffers.begin()), + end_(buffers.end()), + position_(0) + { + while (current_ != end_) + { + current_buffer_ = *current_; + std::size_t buffer_size = boost::asio::buffer_size(current_buffer_); + if (position - position_ < buffer_size) + { + current_buffer_position_ = position - position_; + position_ = position; + return; + } + position_ += buffer_size; + ++current_; + } + current_buffer_ = boost::asio::const_buffer(); + current_buffer_position_ = 0; + } + + std::size_t position() const + { + return position_; + } + +private: + friend class boost::iterator_core_access; + + void increment() + { + if (current_ == end_) + return; + + ++position_; + + ++current_buffer_position_; + if (current_buffer_position_ != boost::asio::buffer_size(current_buffer_)) + return; + + ++current_; + current_buffer_position_ = 0; + while (current_ != end_) + { + current_buffer_ = *current_; + if (boost::asio::buffer_size(current_buffer_) > 0) + return; + ++current_; + } + } + + void decrement() + { + if (position_ == 0) + return; + + --position_; + + if (current_buffer_position_ != 0) + { + --current_buffer_position_; + return; + } + + typename ConstBufferSequence::const_iterator iter = current_; + while (iter != begin_) + { + --iter; + boost::asio::const_buffer buffer = *iter; + std::size_t buffer_size = boost::asio::buffer_size(buffer); + if (buffer_size > 0) + { + current_ = iter; + current_buffer_ = buffer; + current_buffer_position_ = buffer_size - 1; + return; + } + } + } + + bool equal(const const_buffers_iterator& other) const + { + return position_ == other.position_; + } + + const char& dereference() const + { + return boost::asio::buffer_cast( + current_buffer_)[current_buffer_position_]; + } + + boost::asio::const_buffer current_buffer_; + std::size_t current_buffer_position_; + typename ConstBufferSequence::const_iterator begin_; + typename ConstBufferSequence::const_iterator current_; + typename ConstBufferSequence::const_iterator end_; + std::size_t position_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP diff --git a/win32/include/boost/asio/detail/consuming_buffers.hpp b/win32/include/boost/asio/detail/consuming_buffers.hpp new file mode 100755 index 000000000..0f50dccc4 --- /dev/null +++ b/win32/include/boost/asio/detail/consuming_buffers.hpp @@ -0,0 +1,227 @@ +// +// consuming_buffers.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP +#define BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +// A proxy iterator for a sub-range in a list of buffers. +template +class consuming_buffers_iterator + : public boost::iterator_facade< + consuming_buffers_iterator, + const Buffer, boost::forward_traversal_tag> +{ +public: + // Default constructor creates an end iterator. + consuming_buffers_iterator() + : at_end_(true) + { + } + + // Construct with a buffer for the first entry and an iterator + // range for the remaining entries. + consuming_buffers_iterator(bool at_end, const Buffer& first, + Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder) + : at_end_(at_end), + first_(buffer(first, max_size)), + begin_remainder_(begin_remainder), + end_remainder_(end_remainder), + offset_(0) + { + } + +private: + friend class boost::iterator_core_access; + + enum { max_size = 65536 }; + + void increment() + { + if (!at_end_) + { + if (begin_remainder_ == end_remainder_ + || offset_ + buffer_size(first_) >= max_size) + { + at_end_ = true; + } + else + { + offset_ += buffer_size(first_); + first_ = buffer(*begin_remainder_++, max_size - offset_); + } + } + } + + bool equal(const consuming_buffers_iterator& other) const + { + if (at_end_ && other.at_end_) + return true; + return !at_end_ && !other.at_end_ + && buffer_cast(first_) + == buffer_cast(other.first_) + && buffer_size(first_) == buffer_size(other.first_) + && begin_remainder_ == other.begin_remainder_ + && end_remainder_ == other.end_remainder_; + } + + const Buffer& dereference() const + { + return first_; + } + + bool at_end_; + Buffer first_; + Buffer_Iterator begin_remainder_; + Buffer_Iterator end_remainder_; + std::size_t offset_; +}; + +// A proxy for a sub-range in a list of buffers. +template +class consuming_buffers +{ +public: + // The type for each element in the list of buffers. + typedef Buffer value_type; + + // A forward-only iterator type that may be used to read elements. + typedef consuming_buffers_iterator + const_iterator; + + // Construct to represent the entire list of buffers. + consuming_buffers(const Buffers& buffers) + : buffers_(buffers), + at_end_(buffers_.begin() == buffers_.end()), + first_(*buffers_.begin()), + begin_remainder_(buffers_.begin()) + { + if (!at_end_) + ++begin_remainder_; + } + + // Copy constructor. + consuming_buffers(const consuming_buffers& other) + : buffers_(other.buffers_), + at_end_(other.at_end_), + first_(other.first_), + begin_remainder_(buffers_.begin()) + { + typename Buffers::const_iterator first = other.buffers_.begin(); + typename Buffers::const_iterator second = other.begin_remainder_; + std::advance(begin_remainder_, std::distance(first, second)); + } + + // Assignment operator. + consuming_buffers& operator=(const consuming_buffers& other) + { + buffers_ = other.buffers_; + at_end_ = other.at_end_; + first_ = other.first_; + begin_remainder_ = buffers_.begin(); + typename Buffers::const_iterator first = other.buffers_.begin(); + typename Buffers::const_iterator second = other.begin_remainder_; + std::advance(begin_remainder_, std::distance(first, second)); + return *this; + } + + // Get a forward-only iterator to the first element. + const_iterator begin() const + { + return const_iterator(at_end_, first_, begin_remainder_, buffers_.end()); + } + + // Get a forward-only iterator for one past the last element. + const_iterator end() const + { + return const_iterator(); + } + + // Consume the specified number of bytes from the buffers. + void consume(std::size_t size) + { + // Remove buffers from the start until the specified size is reached. + while (size > 0 && !at_end_) + { + if (buffer_size(first_) <= size) + { + size -= buffer_size(first_); + if (begin_remainder_ == buffers_.end()) + at_end_ = true; + else + first_ = *begin_remainder_++; + } + else + { + first_ = first_ + size; + size = 0; + } + } + + // Remove any more empty buffers at the start. + while (!at_end_ && buffer_size(first_) == 0) + { + if (begin_remainder_ == buffers_.end()) + at_end_ = true; + else + first_ = *begin_remainder_++; + } + } + +private: + Buffers buffers_; + bool at_end_; + Buffer first_; + typename Buffers::const_iterator begin_remainder_; +}; + +// Specialisation for null_buffers to ensure that the null_buffers type is +// always passed through to the underlying read or write operation. +template +class consuming_buffers + : public boost::asio::null_buffers +{ +public: + consuming_buffers(const boost::asio::null_buffers&) + { + // No-op. + } + + void consume(std::size_t) + { + // No-op. + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP diff --git a/win32/include/boost/asio/detail/deadline_timer_service.hpp b/win32/include/boost/asio/detail/deadline_timer_service.hpp new file mode 100755 index 000000000..1e5f3bf41 --- /dev/null +++ b/win32/include/boost/asio/detail/deadline_timer_service.hpp @@ -0,0 +1,202 @@ +// +// deadline_timer_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP +#define BOOST_ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class deadline_timer_service + : public boost::asio::detail::service_base< + deadline_timer_service > +{ +public: + // The time type. + typedef typename Time_Traits::time_type time_type; + + // The duration type. + typedef typename Time_Traits::duration_type duration_type; + + // The implementation type of the timer. This type is dependent on the + // underlying implementation of the timer service. + struct implementation_type + : private boost::asio::detail::noncopyable + { + time_type expiry; + bool might_have_pending_waits; + }; + + // Constructor. + deadline_timer_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + deadline_timer_service >(io_service), + scheduler_(boost::asio::use_service(io_service)) + { + scheduler_.add_timer_queue(timer_queue_); + } + + // Destructor. + ~deadline_timer_service() + { + scheduler_.remove_timer_queue(timer_queue_); + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Construct a new timer implementation. + void construct(implementation_type& impl) + { + impl.expiry = time_type(); + impl.might_have_pending_waits = false; + } + + // Destroy a timer implementation. + void destroy(implementation_type& impl) + { + boost::system::error_code ec; + cancel(impl, ec); + } + + // Cancel any asynchronous wait operations associated with the timer. + std::size_t cancel(implementation_type& impl, boost::system::error_code& ec) + { + if (!impl.might_have_pending_waits) + { + ec = boost::system::error_code(); + return 0; + } + std::size_t count = scheduler_.cancel_timer(timer_queue_, &impl); + impl.might_have_pending_waits = false; + ec = boost::system::error_code(); + return count; + } + + // Get the expiry time for the timer as an absolute time. + time_type expires_at(const implementation_type& impl) const + { + return impl.expiry; + } + + // Set the expiry time for the timer as an absolute time. + std::size_t expires_at(implementation_type& impl, + const time_type& expiry_time, boost::system::error_code& ec) + { + std::size_t count = cancel(impl, ec); + impl.expiry = expiry_time; + ec = boost::system::error_code(); + return count; + } + + // Get the expiry time for the timer relative to now. + duration_type expires_from_now(const implementation_type& impl) const + { + return Time_Traits::subtract(expires_at(impl), Time_Traits::now()); + } + + // Set the expiry time for the timer relative to now. + std::size_t expires_from_now(implementation_type& impl, + const duration_type& expiry_time, boost::system::error_code& ec) + { + return expires_at(impl, + Time_Traits::add(Time_Traits::now(), expiry_time), ec); + } + + // Perform a blocking wait on the timer. + void wait(implementation_type& impl, boost::system::error_code& ec) + { + time_type now = Time_Traits::now(); + while (Time_Traits::less_than(now, impl.expiry)) + { + boost::posix_time::time_duration timeout = + Time_Traits::to_posix_duration(Time_Traits::subtract(impl.expiry, now)); + ::timeval tv; + tv.tv_sec = timeout.total_seconds(); + tv.tv_usec = timeout.total_microseconds() % 1000000; + boost::system::error_code ec; + socket_ops::select(0, 0, 0, 0, &tv, ec); + now = Time_Traits::now(); + } + ec = boost::system::error_code(); + } + + template + class wait_handler : + public handler_base_from_member + { + public: + wait_handler(boost::asio::io_service& io_service, Handler handler) + : handler_base_from_member(handler), + io_service_(io_service), + work_(io_service) + { + } + + void operator()(const boost::system::error_code& result) + { + io_service_.post(detail::bind_handler(this->handler_, result)); + } + + private: + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + }; + + // Start an asynchronous wait on the timer. + template + void async_wait(implementation_type& impl, Handler handler) + { + impl.might_have_pending_waits = true; + scheduler_.schedule_timer(timer_queue_, impl.expiry, + wait_handler(this->get_io_service(), handler), &impl); + } + +private: + // The queue of timers. + timer_queue timer_queue_; + + // The object that schedules and executes timers. Usually a reactor. + Timer_Scheduler& scheduler_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP diff --git a/win32/include/boost/asio/detail/descriptor_ops.hpp b/win32/include/boost/asio/detail/descriptor_ops.hpp new file mode 100755 index 000000000..d9fe67e9c --- /dev/null +++ b/win32/include/boost/asio/detail/descriptor_ops.hpp @@ -0,0 +1,140 @@ +// +// descriptor_ops.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_HPP +#define BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +namespace boost { +namespace asio { +namespace detail { +namespace descriptor_ops { + +inline void clear_error(boost::system::error_code& ec) +{ + errno = 0; + ec = boost::system::error_code(); +} + +template +inline ReturnType error_wrapper(ReturnType return_value, + boost::system::error_code& ec) +{ + ec = boost::system::error_code(errno, + boost::asio::error::get_system_category()); + return return_value; +} + +inline int open(const char* path, int flags, boost::system::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::open(path, flags), ec); +} + +inline int close(int d, boost::system::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::close(d), ec); +} + +typedef iovec buf; + +inline void init_buf(buf& b, void* data, size_t size) +{ + b.iov_base = data; + b.iov_len = size; +} + +inline void init_buf(buf& b, const void* data, size_t size) +{ + b.iov_base = const_cast(data); + b.iov_len = size; +} + +inline int scatter_read(int d, buf* bufs, size_t count, + boost::system::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::readv(d, bufs, static_cast(count)), ec); +} + +inline int gather_write(int d, const buf* bufs, size_t count, + boost::system::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::writev(d, bufs, static_cast(count)), ec); +} + +inline int ioctl(int d, long cmd, ioctl_arg_type* arg, + boost::system::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::ioctl(d, cmd, arg), ec); +} + +inline int fcntl(int d, long cmd, boost::system::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::fcntl(d, cmd), ec); +} + +inline int fcntl(int d, long cmd, long arg, boost::system::error_code& ec) +{ + clear_error(ec); + return error_wrapper(::fcntl(d, cmd, arg), ec); +} + +inline int poll_read(int d, boost::system::error_code& ec) +{ + clear_error(ec); + pollfd fds; + fds.fd = d; + fds.events = POLLIN; + fds.revents = 0; + clear_error(ec); + return error_wrapper(::poll(&fds, 1, -1), ec); +} + +inline int poll_write(int d, boost::system::error_code& ec) +{ + clear_error(ec); + pollfd fds; + fds.fd = d; + fds.events = POLLOUT; + fds.revents = 0; + clear_error(ec); + return error_wrapper(::poll(&fds, 1, -1), ec); +} + +} // namespace descriptor_ops +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include + +#endif // BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_HPP diff --git a/win32/include/boost/asio/detail/dev_poll_reactor.hpp b/win32/include/boost/asio/detail/dev_poll_reactor.hpp new file mode 100755 index 000000000..962601131 --- /dev/null +++ b/win32/include/boost/asio/detail/dev_poll_reactor.hpp @@ -0,0 +1,667 @@ +// +// dev_poll_reactor.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_HPP +#define BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_DEV_POLL) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class dev_poll_reactor + : public boost::asio::detail::service_base > +{ +public: + // Per-descriptor data. + struct per_descriptor_data + { + }; + + // Constructor. + dev_poll_reactor(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + dev_poll_reactor >(io_service), + mutex_(), + dev_poll_fd_(do_dev_poll_create()), + wait_in_progress_(false), + interrupter_(), + read_op_queue_(), + write_op_queue_(), + except_op_queue_(), + pending_cancellations_(), + stop_thread_(false), + thread_(0), + shutdown_(false) + { + // Start the reactor's internal thread only if needed. + if (Own_Thread) + { + boost::asio::detail::signal_blocker sb; + thread_ = new boost::asio::detail::thread( + bind_handler(&dev_poll_reactor::call_run_thread, this)); + } + + // Add the interrupter's descriptor to /dev/poll. + ::pollfd ev = { 0 }; + ev.fd = interrupter_.read_descriptor(); + ev.events = POLLIN | POLLERR; + ev.revents = 0; + ::write(dev_poll_fd_, &ev, sizeof(ev)); + } + + // Destructor. + ~dev_poll_reactor() + { + shutdown_service(); + ::close(dev_poll_fd_); + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + shutdown_ = true; + stop_thread_ = true; + lock.unlock(); + + if (thread_) + { + interrupter_.interrupt(); + thread_->join(); + delete thread_; + thread_ = 0; + } + + read_op_queue_.destroy_operations(); + write_op_queue_.destroy_operations(); + except_op_queue_.destroy_operations(); + + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + timer_queues_[i]->destroy_timers(); + timer_queues_.clear(); + } + + // Register a socket with the reactor. Returns 0 on success, system error + // code on failure. + int register_descriptor(socket_type, per_descriptor_data&) + { + return 0; + } + + // Start a new read operation. The handler object will be invoked when the + // given descriptor is ready to be read, or an error has occurred. + template + void start_read_op(socket_type descriptor, per_descriptor_data&, + Handler handler, bool allow_speculative_read = true) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + return; + + if (allow_speculative_read) + { + if (!read_op_queue_.has_operation(descriptor)) + { + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + } + } + + if (read_op_queue_.enqueue_operation(descriptor, handler)) + { + ::pollfd& ev = add_pending_event_change(descriptor); + ev.events = POLLIN | POLLERR | POLLHUP; + if (write_op_queue_.has_operation(descriptor)) + ev.events |= POLLOUT; + if (except_op_queue_.has_operation(descriptor)) + ev.events |= POLLPRI; + interrupter_.interrupt(); + } + } + + // Start a new write operation. The handler object will be invoked when the + // given descriptor is ready to be written, or an error has occurred. + template + void start_write_op(socket_type descriptor, per_descriptor_data&, + Handler handler, bool allow_speculative_write = true) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + return; + + if (allow_speculative_write) + { + if (!write_op_queue_.has_operation(descriptor)) + { + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + } + } + + if (write_op_queue_.enqueue_operation(descriptor, handler)) + { + ::pollfd& ev = add_pending_event_change(descriptor); + ev.events = POLLOUT | POLLERR | POLLHUP; + if (read_op_queue_.has_operation(descriptor)) + ev.events |= POLLIN; + if (except_op_queue_.has_operation(descriptor)) + ev.events |= POLLPRI; + interrupter_.interrupt(); + } + } + + // Start a new exception operation. The handler object will be invoked when + // the given descriptor has exception information, or an error has occurred. + template + void start_except_op(socket_type descriptor, + per_descriptor_data&, Handler handler) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + return; + + if (except_op_queue_.enqueue_operation(descriptor, handler)) + { + ::pollfd& ev = add_pending_event_change(descriptor); + ev.events = POLLPRI | POLLERR | POLLHUP; + if (read_op_queue_.has_operation(descriptor)) + ev.events |= POLLIN; + if (write_op_queue_.has_operation(descriptor)) + ev.events |= POLLOUT; + interrupter_.interrupt(); + } + } + + // Start a new write operation. The handler object will be invoked when the + // information available, or an error has occurred. + template + void start_connect_op(socket_type descriptor, + per_descriptor_data&, Handler handler) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + return; + + if (write_op_queue_.enqueue_operation(descriptor, handler)) + { + ::pollfd& ev = add_pending_event_change(descriptor); + ev.events = POLLOUT | POLLERR | POLLHUP; + if (read_op_queue_.has_operation(descriptor)) + ev.events |= POLLIN; + if (except_op_queue_.has_operation(descriptor)) + ev.events |= POLLPRI; + interrupter_.interrupt(); + } + } + + // Cancel all operations associated with the given descriptor. The + // handlers associated with the descriptor will be invoked with the + // operation_aborted error. + void cancel_ops(socket_type descriptor, per_descriptor_data&) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + cancel_ops_unlocked(descriptor); + } + + // Cancel any operations that are running against the descriptor and remove + // its registration from the reactor. + void close_descriptor(socket_type descriptor, per_descriptor_data&) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // Remove the descriptor from /dev/poll. + ::pollfd& ev = add_pending_event_change(descriptor); + ev.events = POLLREMOVE; + interrupter_.interrupt(); + + // Cancel any outstanding operations associated with the descriptor. + cancel_ops_unlocked(descriptor); + } + + // Add a new timer queue to the reactor. + template + void add_timer_queue(timer_queue& timer_queue) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + timer_queues_.push_back(&timer_queue); + } + + // Remove a timer queue from the reactor. + template + void remove_timer_queue(timer_queue& timer_queue) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + { + if (timer_queues_[i] == &timer_queue) + { + timer_queues_.erase(timer_queues_.begin() + i); + return; + } + } + } + + // Schedule a timer in the given timer queue to expire at the specified + // absolute time. The handler object will be invoked when the timer expires. + template + void schedule_timer(timer_queue& timer_queue, + const typename Time_Traits::time_type& time, Handler handler, void* token) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (!shutdown_) + if (timer_queue.enqueue_timer(time, handler, token)) + interrupter_.interrupt(); + } + + // Cancel the timer associated with the given token. Returns the number of + // handlers that have been posted or dispatched. + template + std::size_t cancel_timer(timer_queue& timer_queue, void* token) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + std::size_t n = timer_queue.cancel_timer(token); + if (n > 0) + interrupter_.interrupt(); + return n; + } + +private: + friend class task_io_service >; + + // Run /dev/poll once until interrupted or events are ready to be dispatched. + void run(bool block) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // Dispatch any operation cancellations that were made while the select + // loop was not running. + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + timer_queues_[i]->dispatch_cancellations(); + + // Check if the thread is supposed to stop. + if (stop_thread_) + { + complete_operations_and_timers(lock); + return; + } + + // We can return immediately if there's no work to do and the reactor is + // not supposed to block. + if (!block && read_op_queue_.empty() && write_op_queue_.empty() + && except_op_queue_.empty() && all_timer_queues_are_empty()) + { + complete_operations_and_timers(lock); + return; + } + + // Write the pending event registration changes to the /dev/poll descriptor. + std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size(); + errno = 0; + int result = ::write(dev_poll_fd_, + &pending_event_changes_[0], events_size); + if (result != static_cast(events_size)) + { + for (std::size_t i = 0; i < pending_event_changes_.size(); ++i) + { + int descriptor = pending_event_changes_[i].fd; + boost::system::error_code ec = boost::system::error_code( + errno, boost::asio::error::get_system_category()); + read_op_queue_.perform_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); + except_op_queue_.perform_all_operations(descriptor, ec); + } + } + pending_event_changes_.clear(); + pending_event_change_index_.clear(); + + int timeout = block ? get_timeout() : 0; + wait_in_progress_ = true; + lock.unlock(); + + // Block on the /dev/poll descriptor. + ::pollfd events[128] = { { 0 } }; + ::dvpoll dp = { 0 }; + dp.dp_fds = events; + dp.dp_nfds = 128; + dp.dp_timeout = timeout; + int num_events = ::ioctl(dev_poll_fd_, DP_POLL, &dp); + + lock.lock(); + wait_in_progress_ = false; + + // Block signals while performing operations. + boost::asio::detail::signal_blocker sb; + + // Dispatch the waiting events. + for (int i = 0; i < num_events; ++i) + { + int descriptor = events[i].fd; + if (descriptor == interrupter_.read_descriptor()) + { + interrupter_.reset(); + } + else + { + bool more_reads = false; + bool more_writes = false; + bool more_except = false; + boost::system::error_code ec; + + // Exception operations must be processed first to ensure that any + // out-of-band data is read before normal data. + if (events[i].events & (POLLPRI | POLLERR | POLLHUP)) + more_except = except_op_queue_.perform_operation(descriptor, ec); + else + more_except = except_op_queue_.has_operation(descriptor); + + if (events[i].events & (POLLIN | POLLERR | POLLHUP)) + more_reads = read_op_queue_.perform_operation(descriptor, ec); + else + more_reads = read_op_queue_.has_operation(descriptor); + + if (events[i].events & (POLLOUT | POLLERR | POLLHUP)) + more_writes = write_op_queue_.perform_operation(descriptor, ec); + else + more_writes = write_op_queue_.has_operation(descriptor); + + if ((events[i].events & (POLLERR | POLLHUP)) != 0 + && (events[i].events & ~(POLLERR | POLLHUP)) == 0 + && !more_except && !more_reads && !more_writes) + { + // If we have an event and no operations associated with the + // descriptor then we need to delete the descriptor from /dev/poll. + // The poll operation can produce POLLHUP or POLLERR events when there + // is no operation pending, so if we do not remove the descriptor we + // can end up in a tight polling loop. + ::pollfd ev = { 0 }; + ev.fd = descriptor; + ev.events = POLLREMOVE; + ev.revents = 0; + ::write(dev_poll_fd_, &ev, sizeof(ev)); + } + else + { + ::pollfd ev = { 0 }; + ev.fd = descriptor; + ev.events = POLLERR | POLLHUP; + if (more_reads) + ev.events |= POLLIN; + if (more_writes) + ev.events |= POLLOUT; + if (more_except) + ev.events |= POLLPRI; + ev.revents = 0; + int result = ::write(dev_poll_fd_, &ev, sizeof(ev)); + if (result != sizeof(ev)) + { + ec = boost::system::error_code(errno, + boost::asio::error::get_system_category()); + read_op_queue_.perform_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); + except_op_queue_.perform_all_operations(descriptor, ec); + } + } + } + } + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + { + timer_queues_[i]->dispatch_timers(); + timer_queues_[i]->dispatch_cancellations(); + } + + // Issue any pending cancellations. + for (size_t i = 0; i < pending_cancellations_.size(); ++i) + cancel_ops_unlocked(pending_cancellations_[i]); + pending_cancellations_.clear(); + + complete_operations_and_timers(lock); + } + + // Run the select loop in the thread. + void run_thread() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + while (!stop_thread_) + { + lock.unlock(); + run(true); + lock.lock(); + } + } + + // Entry point for the select loop thread. + static void call_run_thread(dev_poll_reactor* reactor) + { + reactor->run_thread(); + } + + // Interrupt the select loop. + void interrupt() + { + interrupter_.interrupt(); + } + + // Create the /dev/poll file descriptor. Throws an exception if the descriptor + // cannot be created. + static int do_dev_poll_create() + { + int fd = ::open("/dev/poll", O_RDWR); + if (fd == -1) + { + boost::throw_exception( + boost::system::system_error( + boost::system::error_code(errno, + boost::asio::error::get_system_category()), + "/dev/poll")); + } + return fd; + } + + // Check if all timer queues are empty. + bool all_timer_queues_are_empty() const + { + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + if (!timer_queues_[i]->empty()) + return false; + return true; + } + + // Get the timeout value for the /dev/poll DP_POLL operation. The timeout + // value is returned as a number of milliseconds. A return value of -1 + // indicates that the poll should block indefinitely. + int get_timeout() + { + if (all_timer_queues_are_empty()) + return -1; + + // By default we will wait no longer than 5 minutes. This will ensure that + // any changes to the system clock are detected after no longer than this. + boost::posix_time::time_duration minimum_wait_duration + = boost::posix_time::minutes(5); + + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + { + boost::posix_time::time_duration wait_duration + = timer_queues_[i]->wait_duration(); + if (wait_duration < minimum_wait_duration) + minimum_wait_duration = wait_duration; + } + + if (minimum_wait_duration > boost::posix_time::time_duration()) + { + int milliseconds = minimum_wait_duration.total_milliseconds(); + return milliseconds > 0 ? milliseconds : 1; + } + else + { + return 0; + } + } + + // Cancel all operations associated with the given descriptor. The do_cancel + // function of the handler objects will be invoked. This function does not + // acquire the dev_poll_reactor's mutex. + void cancel_ops_unlocked(socket_type descriptor) + { + bool interrupt = read_op_queue_.cancel_operations(descriptor); + interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt; + interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt; + if (interrupt) + interrupter_.interrupt(); + } + + // Clean up operations and timers. We must not hold the lock since the + // destructors may make calls back into this reactor. We make a copy of the + // vector of timer queues since the original may be modified while the lock + // is not held. + void complete_operations_and_timers( + boost::asio::detail::mutex::scoped_lock& lock) + { + timer_queues_for_cleanup_ = timer_queues_; + lock.unlock(); + read_op_queue_.complete_operations(); + write_op_queue_.complete_operations(); + except_op_queue_.complete_operations(); + for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) + timer_queues_for_cleanup_[i]->complete_timers(); + } + + // Add a pending event entry for the given descriptor. + ::pollfd& add_pending_event_change(int descriptor) + { + hash_map::iterator iter + = pending_event_change_index_.find(descriptor); + if (iter == pending_event_change_index_.end()) + { + std::size_t index = pending_event_changes_.size(); + pending_event_changes_.reserve(pending_event_changes_.size() + 1); + pending_event_change_index_.insert(std::make_pair(descriptor, index)); + pending_event_changes_.push_back(::pollfd()); + pending_event_changes_[index].fd = descriptor; + pending_event_changes_[index].revents = 0; + return pending_event_changes_[index]; + } + else + { + return pending_event_changes_[iter->second]; + } + } + + // Mutex to protect access to internal data. + boost::asio::detail::mutex mutex_; + + // The /dev/poll file descriptor. + int dev_poll_fd_; + + // Vector of /dev/poll events waiting to be written to the descriptor. + std::vector< ::pollfd> pending_event_changes_; + + // Hash map to associate a descriptor with a pending event change index. + hash_map pending_event_change_index_; + + // Whether the DP_POLL operation is currently in progress + bool wait_in_progress_; + + // The interrupter is used to break a blocking DP_POLL operation. + select_interrupter interrupter_; + + // The queue of read operations. + reactor_op_queue read_op_queue_; + + // The queue of write operations. + reactor_op_queue write_op_queue_; + + // The queue of except operations. + reactor_op_queue except_op_queue_; + + // The timer queues. + std::vector timer_queues_; + + // A copy of the timer queues, used when cleaning up timers. The copy is + // stored as a class data member to avoid unnecessary memory allocation. + std::vector timer_queues_for_cleanup_; + + // The descriptors that are pending cancellation. + std::vector pending_cancellations_; + + // Does the reactor loop thread need to stop. + bool stop_thread_; + + // The thread that is running the reactor loop. + boost::asio::detail::thread* thread_; + + // Whether the service has been shut down. + bool shutdown_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_DEV_POLL) + +#include + +#endif // BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_HPP diff --git a/win32/include/boost/asio/detail/dev_poll_reactor_fwd.hpp b/win32/include/boost/asio/detail/dev_poll_reactor_fwd.hpp new file mode 100755 index 000000000..4a102ce0c --- /dev/null +++ b/win32/include/boost/asio/detail/dev_poll_reactor_fwd.hpp @@ -0,0 +1,42 @@ +// +// dev_poll_reactor_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP +#define BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if !defined(BOOST_ASIO_DISABLE_DEV_POLL) +#if defined(__sun) // This service is only supported on Solaris. + +// Define this to indicate that /dev/poll is supported on the target platform. +#define BOOST_ASIO_HAS_DEV_POLL 1 + +namespace boost { +namespace asio { +namespace detail { + +template +class dev_poll_reactor; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(__sun) +#endif // !defined(BOOST_ASIO_DISABLE_DEV_POLL) + +#include + +#endif // BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP diff --git a/win32/include/boost/asio/detail/epoll_reactor.hpp b/win32/include/boost/asio/detail/epoll_reactor.hpp new file mode 100755 index 000000000..f7768e303 --- /dev/null +++ b/win32/include/boost/asio/detail/epoll_reactor.hpp @@ -0,0 +1,723 @@ +// +// epoll_reactor.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_EPOLL_REACTOR_HPP +#define BOOST_ASIO_DETAIL_EPOLL_REACTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_EPOLL) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class epoll_reactor + : public boost::asio::detail::service_base > +{ +public: + // Per-descriptor data. + struct per_descriptor_data + { + bool allow_speculative_read; + bool allow_speculative_write; + }; + + // Constructor. + epoll_reactor(boost::asio::io_service& io_service) + : boost::asio::detail::service_base >(io_service), + mutex_(), + epoll_fd_(do_epoll_create()), + wait_in_progress_(false), + interrupter_(), + read_op_queue_(), + write_op_queue_(), + except_op_queue_(), + pending_cancellations_(), + stop_thread_(false), + thread_(0), + shutdown_(false), + need_epoll_wait_(true) + { + // Start the reactor's internal thread only if needed. + if (Own_Thread) + { + boost::asio::detail::signal_blocker sb; + thread_ = new boost::asio::detail::thread( + bind_handler(&epoll_reactor::call_run_thread, this)); + } + + // Add the interrupter's descriptor to epoll. + epoll_event ev = { 0, { 0 } }; + ev.events = EPOLLIN | EPOLLERR; + ev.data.fd = interrupter_.read_descriptor(); + epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev); + } + + // Destructor. + ~epoll_reactor() + { + shutdown_service(); + close(epoll_fd_); + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + shutdown_ = true; + stop_thread_ = true; + lock.unlock(); + + if (thread_) + { + interrupter_.interrupt(); + thread_->join(); + delete thread_; + thread_ = 0; + } + + read_op_queue_.destroy_operations(); + write_op_queue_.destroy_operations(); + except_op_queue_.destroy_operations(); + + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + timer_queues_[i]->destroy_timers(); + timer_queues_.clear(); + } + + // Register a socket with the reactor. Returns 0 on success, system error + // code on failure. + int register_descriptor(socket_type descriptor, + per_descriptor_data& descriptor_data) + { + // No need to lock according to epoll documentation. + + descriptor_data.allow_speculative_read = true; + descriptor_data.allow_speculative_write = true; + + epoll_event ev = { 0, { 0 } }; + ev.events = 0; + ev.data.fd = descriptor; + int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); + if (result != 0) + return errno; + return 0; + } + + // Start a new read operation. The handler object will be invoked when the + // given descriptor is ready to be read, or an error has occurred. + template + void start_read_op(socket_type descriptor, + per_descriptor_data& descriptor_data, + Handler handler, bool allow_speculative_read = true) + { + if (allow_speculative_read && descriptor_data.allow_speculative_read) + { + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + + // We only get one shot at a speculative read in this function. + allow_speculative_read = false; + } + + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + return; + + if (!allow_speculative_read) + need_epoll_wait_ = true; + else if (!read_op_queue_.has_operation(descriptor)) + { + // Speculative reads are ok as there are no queued read operations. + descriptor_data.allow_speculative_read = true; + + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + } + + // Speculative reads are not ok as there will be queued read operations. + descriptor_data.allow_speculative_read = false; + + if (read_op_queue_.enqueue_operation(descriptor, handler)) + { + epoll_event ev = { 0, { 0 } }; + ev.events = EPOLLIN | EPOLLERR | EPOLLHUP; + if (write_op_queue_.has_operation(descriptor)) + ev.events |= EPOLLOUT; + if (except_op_queue_.has_operation(descriptor)) + ev.events |= EPOLLPRI; + ev.data.fd = descriptor; + + int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); + if (result != 0 && errno == ENOENT) + result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); + if (result != 0) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + read_op_queue_.perform_all_operations(descriptor, ec); + } + } + } + + // Start a new write operation. The handler object will be invoked when the + // given descriptor is ready to be written, or an error has occurred. + template + void start_write_op(socket_type descriptor, + per_descriptor_data& descriptor_data, + Handler handler, bool allow_speculative_write = true) + { + if (allow_speculative_write && descriptor_data.allow_speculative_write) + { + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + + // We only get one shot at a speculative write in this function. + allow_speculative_write = false; + } + + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + return; + + if (!allow_speculative_write) + need_epoll_wait_ = true; + else if (!write_op_queue_.has_operation(descriptor)) + { + // Speculative writes are ok as there are no queued write operations. + descriptor_data.allow_speculative_write = true; + + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + } + + // Speculative writes are not ok as there will be queued write operations. + descriptor_data.allow_speculative_write = false; + + if (write_op_queue_.enqueue_operation(descriptor, handler)) + { + epoll_event ev = { 0, { 0 } }; + ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP; + if (read_op_queue_.has_operation(descriptor)) + ev.events |= EPOLLIN; + if (except_op_queue_.has_operation(descriptor)) + ev.events |= EPOLLPRI; + ev.data.fd = descriptor; + + int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); + if (result != 0 && errno == ENOENT) + result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); + if (result != 0) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + write_op_queue_.perform_all_operations(descriptor, ec); + } + } + } + + // Start a new exception operation. The handler object will be invoked when + // the given descriptor has exception information, or an error has occurred. + template + void start_except_op(socket_type descriptor, + per_descriptor_data&, Handler handler) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + return; + + if (except_op_queue_.enqueue_operation(descriptor, handler)) + { + epoll_event ev = { 0, { 0 } }; + ev.events = EPOLLPRI | EPOLLERR | EPOLLHUP; + if (read_op_queue_.has_operation(descriptor)) + ev.events |= EPOLLIN; + if (write_op_queue_.has_operation(descriptor)) + ev.events |= EPOLLOUT; + ev.data.fd = descriptor; + + int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); + if (result != 0 && errno == ENOENT) + result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); + if (result != 0) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + except_op_queue_.perform_all_operations(descriptor, ec); + } + } + } + + // Start a new write operation. The handler object will be invoked when the + // given descriptor is ready for writing or an error has occurred. Speculative + // writes are not allowed. + template + void start_connect_op(socket_type descriptor, + per_descriptor_data& descriptor_data, Handler handler) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + return; + + // Speculative writes are not ok as there will be queued write operations. + descriptor_data.allow_speculative_write = false; + + if (write_op_queue_.enqueue_operation(descriptor, handler)) + { + epoll_event ev = { 0, { 0 } }; + ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP; + if (read_op_queue_.has_operation(descriptor)) + ev.events |= EPOLLIN; + if (except_op_queue_.has_operation(descriptor)) + ev.events |= EPOLLPRI; + ev.data.fd = descriptor; + + int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); + if (result != 0 && errno == ENOENT) + result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); + if (result != 0) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + write_op_queue_.perform_all_operations(descriptor, ec); + } + } + } + + // Cancel all operations associated with the given descriptor. The + // handlers associated with the descriptor will be invoked with the + // operation_aborted error. + void cancel_ops(socket_type descriptor, per_descriptor_data&) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + cancel_ops_unlocked(descriptor); + } + + // Cancel any operations that are running against the descriptor and remove + // its registration from the reactor. + void close_descriptor(socket_type descriptor, per_descriptor_data&) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // Remove the descriptor from epoll. + epoll_event ev = { 0, { 0 } }; + epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev); + + // Cancel any outstanding operations associated with the descriptor. + cancel_ops_unlocked(descriptor); + } + + // Add a new timer queue to the reactor. + template + void add_timer_queue(timer_queue& timer_queue) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + timer_queues_.push_back(&timer_queue); + } + + // Remove a timer queue from the reactor. + template + void remove_timer_queue(timer_queue& timer_queue) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + { + if (timer_queues_[i] == &timer_queue) + { + timer_queues_.erase(timer_queues_.begin() + i); + return; + } + } + } + + // Schedule a timer in the given timer queue to expire at the specified + // absolute time. The handler object will be invoked when the timer expires. + template + void schedule_timer(timer_queue& timer_queue, + const typename Time_Traits::time_type& time, Handler handler, void* token) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (!shutdown_) + if (timer_queue.enqueue_timer(time, handler, token)) + interrupter_.interrupt(); + } + + // Cancel the timer associated with the given token. Returns the number of + // handlers that have been posted or dispatched. + template + std::size_t cancel_timer(timer_queue& timer_queue, void* token) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + std::size_t n = timer_queue.cancel_timer(token); + if (n > 0) + interrupter_.interrupt(); + return n; + } + +private: + friend class task_io_service >; + + // Run epoll once until interrupted or events are ready to be dispatched. + void run(bool block) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // Dispatch any operation cancellations that were made while the select + // loop was not running. + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + timer_queues_[i]->dispatch_cancellations(); + + // Check if the thread is supposed to stop. + if (stop_thread_) + { + complete_operations_and_timers(lock); + return; + } + + // We can return immediately if there's no work to do and the reactor is + // not supposed to block. + if (!block && read_op_queue_.empty() && write_op_queue_.empty() + && except_op_queue_.empty() && all_timer_queues_are_empty()) + { + complete_operations_and_timers(lock); + return; + } + + int timeout = block ? get_timeout() : 0; + wait_in_progress_ = true; + lock.unlock(); + + // Block on the epoll descriptor. + epoll_event events[128]; + int num_events = (block || need_epoll_wait_) + ? epoll_wait(epoll_fd_, events, 128, timeout) + : 0; + + lock.lock(); + wait_in_progress_ = false; + + // Block signals while performing operations. + boost::asio::detail::signal_blocker sb; + + // Dispatch the waiting events. + for (int i = 0; i < num_events; ++i) + { + int descriptor = events[i].data.fd; + if (descriptor == interrupter_.read_descriptor()) + { + interrupter_.reset(); + } + else + { + bool more_reads = false; + bool more_writes = false; + bool more_except = false; + boost::system::error_code ec; + + // Exception operations must be processed first to ensure that any + // out-of-band data is read before normal data. + if (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP)) + more_except = except_op_queue_.perform_operation(descriptor, ec); + else + more_except = except_op_queue_.has_operation(descriptor); + + if (events[i].events & (EPOLLIN | EPOLLERR | EPOLLHUP)) + more_reads = read_op_queue_.perform_operation(descriptor, ec); + else + more_reads = read_op_queue_.has_operation(descriptor); + + if (events[i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) + more_writes = write_op_queue_.perform_operation(descriptor, ec); + else + more_writes = write_op_queue_.has_operation(descriptor); + + if ((events[i].events & (EPOLLERR | EPOLLHUP)) != 0 + && (events[i].events & ~(EPOLLERR | EPOLLHUP)) == 0 + && !more_except && !more_reads && !more_writes) + { + // If we have an event and no operations associated with the + // descriptor then we need to delete the descriptor from epoll. The + // epoll_wait system call can produce EPOLLHUP or EPOLLERR events + // when there is no operation pending, so if we do not remove the + // descriptor we can end up in a tight loop of repeated + // calls to epoll_wait. + epoll_event ev = { 0, { 0 } }; + epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev); + } + else + { + epoll_event ev = { 0, { 0 } }; + ev.events = EPOLLERR | EPOLLHUP; + if (more_reads) + ev.events |= EPOLLIN; + if (more_writes) + ev.events |= EPOLLOUT; + if (more_except) + ev.events |= EPOLLPRI; + ev.data.fd = descriptor; + int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); + if (result != 0 && errno == ENOENT) + result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); + if (result != 0) + { + ec = boost::system::error_code(errno, + boost::asio::error::get_system_category()); + read_op_queue_.perform_all_operations(descriptor, ec); + write_op_queue_.perform_all_operations(descriptor, ec); + except_op_queue_.perform_all_operations(descriptor, ec); + } + } + } + } + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + { + timer_queues_[i]->dispatch_timers(); + timer_queues_[i]->dispatch_cancellations(); + } + + // Issue any pending cancellations. + for (size_t i = 0; i < pending_cancellations_.size(); ++i) + cancel_ops_unlocked(pending_cancellations_[i]); + pending_cancellations_.clear(); + + // Determine whether epoll_wait should be called when the reactor next runs. + need_epoll_wait_ = !read_op_queue_.empty() + || !write_op_queue_.empty() || !except_op_queue_.empty(); + + complete_operations_and_timers(lock); + } + + // Run the select loop in the thread. + void run_thread() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + while (!stop_thread_) + { + lock.unlock(); + run(true); + lock.lock(); + } + } + + // Entry point for the select loop thread. + static void call_run_thread(epoll_reactor* reactor) + { + reactor->run_thread(); + } + + // Interrupt the select loop. + void interrupt() + { + interrupter_.interrupt(); + } + + // The hint to pass to epoll_create to size its data structures. + enum { epoll_size = 20000 }; + + // Create the epoll file descriptor. Throws an exception if the descriptor + // cannot be created. + static int do_epoll_create() + { + int fd = epoll_create(epoll_size); + if (fd == -1) + { + boost::throw_exception( + boost::system::system_error( + boost::system::error_code(errno, + boost::asio::error::get_system_category()), + "epoll")); + } + return fd; + } + + // Check if all timer queues are empty. + bool all_timer_queues_are_empty() const + { + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + if (!timer_queues_[i]->empty()) + return false; + return true; + } + + // Get the timeout value for the epoll_wait call. The timeout value is + // returned as a number of milliseconds. A return value of -1 indicates + // that epoll_wait should block indefinitely. + int get_timeout() + { + if (all_timer_queues_are_empty()) + return -1; + + // By default we will wait no longer than 5 minutes. This will ensure that + // any changes to the system clock are detected after no longer than this. + boost::posix_time::time_duration minimum_wait_duration + = boost::posix_time::minutes(5); + + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + { + boost::posix_time::time_duration wait_duration + = timer_queues_[i]->wait_duration(); + if (wait_duration < minimum_wait_duration) + minimum_wait_duration = wait_duration; + } + + if (minimum_wait_duration > boost::posix_time::time_duration()) + { + int milliseconds = minimum_wait_duration.total_milliseconds(); + return milliseconds > 0 ? milliseconds : 1; + } + else + { + return 0; + } + } + + // Cancel all operations associated with the given descriptor. The do_cancel + // function of the handler objects will be invoked. This function does not + // acquire the epoll_reactor's mutex. + void cancel_ops_unlocked(socket_type descriptor) + { + bool interrupt = read_op_queue_.cancel_operations(descriptor); + interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt; + interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt; + if (interrupt) + interrupter_.interrupt(); + } + + // Clean up operations and timers. We must not hold the lock since the + // destructors may make calls back into this reactor. We make a copy of the + // vector of timer queues since the original may be modified while the lock + // is not held. + void complete_operations_and_timers( + boost::asio::detail::mutex::scoped_lock& lock) + { + timer_queues_for_cleanup_ = timer_queues_; + lock.unlock(); + read_op_queue_.complete_operations(); + write_op_queue_.complete_operations(); + except_op_queue_.complete_operations(); + for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) + timer_queues_for_cleanup_[i]->complete_timers(); + } + + // Mutex to protect access to internal data. + boost::asio::detail::mutex mutex_; + + // The epoll file descriptor. + int epoll_fd_; + + // Whether the epoll_wait call is currently in progress + bool wait_in_progress_; + + // The interrupter is used to break a blocking epoll_wait call. + select_interrupter interrupter_; + + // The queue of read operations. + reactor_op_queue read_op_queue_; + + // The queue of write operations. + reactor_op_queue write_op_queue_; + + // The queue of except operations. + reactor_op_queue except_op_queue_; + + // The timer queues. + std::vector timer_queues_; + + // A copy of the timer queues, used when cleaning up timers. The copy is + // stored as a class data member to avoid unnecessary memory allocation. + std::vector timer_queues_for_cleanup_; + + // The descriptors that are pending cancellation. + std::vector pending_cancellations_; + + // Does the reactor loop thread need to stop. + bool stop_thread_; + + // The thread that is running the reactor loop. + boost::asio::detail::thread* thread_; + + // Whether the service has been shut down. + bool shutdown_; + + // Whether we need to call epoll_wait the next time the reactor is run. + bool need_epoll_wait_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_EPOLL) + +#include + +#endif // BOOST_ASIO_DETAIL_EPOLL_REACTOR_HPP diff --git a/win32/include/boost/asio/detail/epoll_reactor_fwd.hpp b/win32/include/boost/asio/detail/epoll_reactor_fwd.hpp new file mode 100755 index 000000000..809c70d3b --- /dev/null +++ b/win32/include/boost/asio/detail/epoll_reactor_fwd.hpp @@ -0,0 +1,49 @@ +// +// epoll_reactor_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP +#define BOOST_ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if !defined(BOOST_ASIO_DISABLE_EPOLL) +#if defined(__linux__) // This service is only supported on Linux. + +#include +#include +#include + +#if LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45) // Only kernels >= 2.5.45. + +// Define this to indicate that epoll is supported on the target platform. +#define BOOST_ASIO_HAS_EPOLL 1 + +namespace boost { +namespace asio { +namespace detail { + +template +class epoll_reactor; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45) +#endif // defined(__linux__) +#endif // !defined(BOOST_ASIO_DISABLE_EPOLL) + +#include + +#endif // BOOST_ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP diff --git a/win32/include/boost/asio/detail/event.hpp b/win32/include/boost/asio/detail/event.hpp new file mode 100755 index 000000000..e06edd42e --- /dev/null +++ b/win32/include/boost/asio/detail/event.hpp @@ -0,0 +1,52 @@ +// +// event.hpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_EVENT_HPP +#define BOOST_ASIO_DETAIL_EVENT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if !defined(BOOST_HAS_THREADS) +# include +#elif defined(BOOST_WINDOWS) +# include +#elif defined(BOOST_HAS_PTHREADS) +# include +#else +# error Only Windows and POSIX are supported! +#endif + +namespace boost { +namespace asio { +namespace detail { + +#if !defined(BOOST_HAS_THREADS) +typedef null_event event; +#elif defined(BOOST_WINDOWS) +typedef win_event event; +#elif defined(BOOST_HAS_PTHREADS) +typedef posix_event event; +#endif + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_EVENT_HPP diff --git a/win32/include/boost/asio/detail/fd_set_adapter.hpp b/win32/include/boost/asio/detail/fd_set_adapter.hpp new file mode 100755 index 000000000..b365b2725 --- /dev/null +++ b/win32/include/boost/asio/detail/fd_set_adapter.hpp @@ -0,0 +1,43 @@ +// +// fd_set_adapter.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_FD_SET_ADAPTER_HPP +#define BOOST_ASIO_DETAIL_FD_SET_ADAPTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +typedef win_fd_set_adapter fd_set_adapter; +#else +typedef posix_fd_set_adapter fd_set_adapter; +#endif + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_FD_SET_ADAPTER_HPP diff --git a/win32/include/boost/asio/detail/handler_alloc_helpers.hpp b/win32/include/boost/asio/detail/handler_alloc_helpers.hpp new file mode 100755 index 000000000..1fd39e5ec --- /dev/null +++ b/win32/include/boost/asio/detail/handler_alloc_helpers.hpp @@ -0,0 +1,258 @@ +// +// handler_alloc_helpers.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP +#define BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include + +// Calls to asio_handler_allocate and asio_handler_deallocate must be made from +// a namespace that does not contain any overloads of these functions. The +// boost_asio_handler_alloc_helpers namespace is defined here for that purpose. +namespace boost_asio_handler_alloc_helpers { + +template +inline void* allocate(std::size_t s, Handler* h) +{ +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + return ::operator new(s); +#else + using namespace boost::asio; + return asio_handler_allocate(s, h); +#endif +} + +template +inline void deallocate(void* p, std::size_t s, Handler* h) +{ +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + ::operator delete(p); +#else + using namespace boost::asio; + asio_handler_deallocate(p, s, h); +#endif +} + +} // namespace boost_asio_handler_alloc_helpers + +namespace boost { +namespace asio { +namespace detail { + +// Traits for handler allocation. +template +struct handler_alloc_traits +{ + typedef Handler handler_type; + typedef Object value_type; + typedef Object* pointer_type; + BOOST_STATIC_CONSTANT(std::size_t, value_size = sizeof(Object)); +}; + +template +class handler_ptr; + +// Helper class to provide RAII on uninitialised handler memory. +template +class raw_handler_ptr + : private noncopyable +{ +public: + typedef typename Alloc_Traits::handler_type handler_type; + typedef typename Alloc_Traits::value_type value_type; + typedef typename Alloc_Traits::pointer_type pointer_type; + BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size); + + // Constructor allocates the memory. + raw_handler_ptr(handler_type& handler) + : handler_(handler), + pointer_(static_cast( + boost_asio_handler_alloc_helpers::allocate(value_size, &handler_))) + { + } + + // Destructor automatically deallocates memory, unless it has been stolen by + // a handler_ptr object. + ~raw_handler_ptr() + { + if (pointer_) + boost_asio_handler_alloc_helpers::deallocate( + pointer_, value_size, &handler_); + } + +private: + friend class handler_ptr; + handler_type& handler_; + pointer_type pointer_; +}; + +// Helper class to provide RAII on uninitialised handler memory. +template +class handler_ptr + : private noncopyable +{ +public: + typedef typename Alloc_Traits::handler_type handler_type; + typedef typename Alloc_Traits::value_type value_type; + typedef typename Alloc_Traits::pointer_type pointer_type; + BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size); + typedef raw_handler_ptr raw_ptr_type; + + // Take ownership of existing memory. + handler_ptr(handler_type& handler, pointer_type pointer) + : handler_(handler), + pointer_(pointer) + { + } + + // Construct object in raw memory and take ownership if construction succeeds. + handler_ptr(raw_ptr_type& raw_ptr) + : handler_(raw_ptr.handler_), + pointer_(new (raw_ptr.pointer_) value_type) + { + raw_ptr.pointer_ = 0; + } + + // Construct object in raw memory and take ownership if construction succeeds. + template + handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1) + : handler_(raw_ptr.handler_), + pointer_(new (raw_ptr.pointer_) value_type(a1)) + { + raw_ptr.pointer_ = 0; + } + + // Construct object in raw memory and take ownership if construction succeeds. + template + handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2) + : handler_(raw_ptr.handler_), + pointer_(new (raw_ptr.pointer_) value_type(a1, a2)) + { + raw_ptr.pointer_ = 0; + } + + // Construct object in raw memory and take ownership if construction succeeds. + template + handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3) + : handler_(raw_ptr.handler_), + pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3)) + { + raw_ptr.pointer_ = 0; + } + + // Construct object in raw memory and take ownership if construction succeeds. + template + handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4) + : handler_(raw_ptr.handler_), + pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4)) + { + raw_ptr.pointer_ = 0; + } + + // Construct object in raw memory and take ownership if construction succeeds. + template + handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4, + Arg5& a5) + : handler_(raw_ptr.handler_), + pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5)) + { + raw_ptr.pointer_ = 0; + } + + // Construct object in raw memory and take ownership if construction succeeds. + template + handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4, + Arg5& a5, Arg6& a6) + : handler_(raw_ptr.handler_), + pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6)) + { + raw_ptr.pointer_ = 0; + } + + // Construct object in raw memory and take ownership if construction succeeds. + template + handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4, + Arg5& a5, Arg6& a6, Arg7& a7) + : handler_(raw_ptr.handler_), + pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6, a7)) + { + raw_ptr.pointer_ = 0; + } + + // Construct object in raw memory and take ownership if construction succeeds. + template + handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4, + Arg5& a5, Arg6& a6, Arg7& a7, Arg8& a8) + : handler_(raw_ptr.handler_), + pointer_(new (raw_ptr.pointer_) value_type( + a1, a2, a3, a4, a5, a6, a7, a8)) + { + raw_ptr.pointer_ = 0; + } + + // Destructor automatically deallocates memory, unless it has been released. + ~handler_ptr() + { + reset(); + } + + // Get the memory. + pointer_type get() const + { + return pointer_; + } + + // Release ownership of the memory. + pointer_type release() + { + pointer_type tmp = pointer_; + pointer_ = 0; + return tmp; + } + + // Explicitly destroy and deallocate the memory. + void reset() + { + if (pointer_) + { + pointer_->value_type::~value_type(); + boost_asio_handler_alloc_helpers::deallocate( + pointer_, value_size, &handler_); + pointer_ = 0; + } + } + +private: + handler_type& handler_; + pointer_type pointer_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP diff --git a/win32/include/boost/asio/detail/handler_base_from_member.hpp b/win32/include/boost/asio/detail/handler_base_from_member.hpp new file mode 100755 index 000000000..e778fe549 --- /dev/null +++ b/win32/include/boost/asio/detail/handler_base_from_member.hpp @@ -0,0 +1,78 @@ +// +// handler_base_from_member.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP +#define BOOST_ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +// Base class for classes that need a handler data member. Forwards the custom +// allocation and invocation hooks to the contained handler. +template +class handler_base_from_member +{ +public: + handler_base_from_member(Handler handler) + : handler_(handler) + { + } + +//protected: + Handler handler_; + +protected: + // Protected destructor to prevent deletion through this type. + ~handler_base_from_member() + { + } +}; + +template +inline void* asio_handler_allocate(std::size_t size, + handler_base_from_member* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); +} + +template +inline void asio_handler_deallocate(void* pointer, std::size_t size, + handler_base_from_member* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); +} + +template +inline void asio_handler_invoke(const Function& function, + handler_base_from_member* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP diff --git a/win32/include/boost/asio/detail/handler_invoke_helpers.hpp b/win32/include/boost/asio/detail/handler_invoke_helpers.hpp new file mode 100755 index 000000000..cca70df6e --- /dev/null +++ b/win32/include/boost/asio/detail/handler_invoke_helpers.hpp @@ -0,0 +1,47 @@ +// +// handler_invoke_helpers.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP +#define BOOST_ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include + +// Calls to asio_handler_invoke must be made from a namespace that does not +// contain overloads of this function. The boost_asio_handler_invoke_helpers +// namespace is defined here for that purpose. +namespace boost_asio_handler_invoke_helpers { + +template +inline void invoke(const Function& function, Context* context) +{ +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + Function tmp(function); + tmp(); +#else + using namespace boost::asio; + asio_handler_invoke(function, context); +#endif +} + +} // namespace boost_asio_handler_invoke_helpers + +#include + +#endif // BOOST_ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP diff --git a/win32/include/boost/asio/detail/handler_queue.hpp b/win32/include/boost/asio/detail/handler_queue.hpp new file mode 100755 index 000000000..9e4175d79 --- /dev/null +++ b/win32/include/boost/asio/detail/handler_queue.hpp @@ -0,0 +1,231 @@ +// +// handler_queue.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_HANDLER_QUEUE_HPP +#define BOOST_ASIO_DETAIL_HANDLER_QUEUE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +class handler_queue + : private noncopyable +{ +public: + // Base class for handlers in the queue. + class handler + : private noncopyable + { + public: + void invoke() + { + invoke_func_(this); + } + + void destroy() + { + destroy_func_(this); + } + + protected: + typedef void (*invoke_func_type)(handler*); + typedef void (*destroy_func_type)(handler*); + + handler(invoke_func_type invoke_func, + destroy_func_type destroy_func) + : next_(0), + invoke_func_(invoke_func), + destroy_func_(destroy_func) + { + } + + ~handler() + { + } + + private: + friend class handler_queue; + handler* next_; + invoke_func_type invoke_func_; + destroy_func_type destroy_func_; + }; + + // Smart point to manager handler lifetimes. + class scoped_ptr + : private noncopyable + { + public: + explicit scoped_ptr(handler* h) + : handler_(h) + { + } + + ~scoped_ptr() + { + if (handler_) + handler_->destroy(); + } + + handler* get() const + { + return handler_; + } + + handler* release() + { + handler* tmp = handler_; + handler_ = 0; + return tmp; + } + + private: + handler* handler_; + }; + + // Constructor. + handler_queue() + : front_(0), + back_(0) + { + } + + // Wrap a handler to be pushed into the queue. + template + static handler* wrap(Handler h) + { + // Allocate and construct an object to wrap the handler. + typedef handler_wrapper value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(h); + handler_ptr ptr(raw_ptr, h); + return ptr.release(); + } + + // Get the handler at the front of the queue. + handler* front() + { + return front_; + } + + // Pop a handler from the front of the queue. + void pop() + { + if (front_) + { + handler* tmp = front_; + front_ = front_->next_; + if (front_ == 0) + back_ = 0; + tmp->next_= 0; + } + } + + // Push a handler on to the back of the queue. + void push(handler* h) + { + h->next_ = 0; + if (back_) + { + back_->next_ = h; + back_ = h; + } + else + { + front_ = back_ = h; + } + } + + // Whether the queue is empty. + bool empty() const + { + return front_ == 0; + } + +private: + // Template wrapper for handlers. + template + class handler_wrapper + : public handler + { + public: + handler_wrapper(Handler h) + : handler( + &handler_wrapper::do_call, + &handler_wrapper::do_destroy), + handler_(h) + { + } + + static void do_call(handler* base) + { + // Take ownership of the handler object. + typedef handler_wrapper this_type; + this_type* h(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(h->handler_, h); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(h->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Make the upcall. + boost_asio_handler_invoke_helpers::invoke(handler, &handler); + } + + static void do_destroy(handler* base) + { + // Take ownership of the handler object. + typedef handler_wrapper this_type; + this_type* h(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(h->handler_, h); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(h->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + private: + Handler handler_; + }; + + // The front of the queue. + handler* front_; + + // The back of the queue. + handler* back_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_HANDLER_QUEUE_HPP diff --git a/win32/include/boost/asio/detail/hash_map.hpp b/win32/include/boost/asio/detail/hash_map.hpp new file mode 100755 index 000000000..ce9c80d94 --- /dev/null +++ b/win32/include/boost/asio/detail/hash_map.hpp @@ -0,0 +1,239 @@ +// +// hash_map.hpp +// ~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_HASH_MAP_HPP +#define BOOST_ASIO_DETAIL_HASH_MAP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +inline std::size_t calculate_hash_value(const T& t) +{ + return boost::hash_value(t); +} + +#if defined(_WIN64) +inline std::size_t calculate_hash_value(SOCKET s) +{ + return static_cast(s); +} +#endif // defined(_WIN64) + +// Note: assumes K and V are POD types. +template +class hash_map + : private noncopyable +{ +public: + // The type of a value in the map. + typedef std::pair value_type; + + // The type of a non-const iterator over the hash map. + typedef typename std::list::iterator iterator; + + // The type of a const iterator over the hash map. + typedef typename std::list::const_iterator const_iterator; + + // Constructor. + hash_map() + { + // Initialise all buckets to empty. + for (size_t i = 0; i < num_buckets; ++i) + buckets_[i].first = buckets_[i].last = values_.end(); + } + + // Get an iterator for the beginning of the map. + iterator begin() + { + return values_.begin(); + } + + // Get an iterator for the beginning of the map. + const_iterator begin() const + { + return values_.begin(); + } + + // Get an iterator for the end of the map. + iterator end() + { + return values_.end(); + } + + // Get an iterator for the end of the map. + const_iterator end() const + { + return values_.end(); + } + + // Check whether the map is empty. + bool empty() const + { + return values_.empty(); + } + + // Find an entry in the map. + iterator find(const K& k) + { + size_t bucket = calculate_hash_value(k) % num_buckets; + iterator it = buckets_[bucket].first; + if (it == values_.end()) + return values_.end(); + iterator end = buckets_[bucket].last; + ++end; + while (it != end) + { + if (it->first == k) + return it; + ++it; + } + return values_.end(); + } + + // Find an entry in the map. + const_iterator find(const K& k) const + { + size_t bucket = calculate_hash_value(k) % num_buckets; + const_iterator it = buckets_[bucket].first; + if (it == values_.end()) + return it; + const_iterator end = buckets_[bucket].last; + ++end; + while (it != end) + { + if (it->first == k) + return it; + ++it; + } + return values_.end(); + } + + // Insert a new entry into the map. + std::pair insert(const value_type& v) + { + size_t bucket = calculate_hash_value(v.first) % num_buckets; + iterator it = buckets_[bucket].first; + if (it == values_.end()) + { + buckets_[bucket].first = buckets_[bucket].last = + values_insert(values_.end(), v); + return std::pair(buckets_[bucket].last, true); + } + iterator end = buckets_[bucket].last; + ++end; + while (it != end) + { + if (it->first == v.first) + return std::pair(it, false); + ++it; + } + buckets_[bucket].last = values_insert(end, v); + return std::pair(buckets_[bucket].last, true); + } + + // Erase an entry from the map. + void erase(iterator it) + { + assert(it != values_.end()); + + size_t bucket = calculate_hash_value(it->first) % num_buckets; + bool is_first = (it == buckets_[bucket].first); + bool is_last = (it == buckets_[bucket].last); + if (is_first && is_last) + buckets_[bucket].first = buckets_[bucket].last = values_.end(); + else if (is_first) + ++buckets_[bucket].first; + else if (is_last) + --buckets_[bucket].last; + + values_erase(it); + } + + // Remove all entries from the map. + void clear() + { + // Clear the values. + values_.clear(); + + // Initialise all buckets to empty. + for (size_t i = 0; i < num_buckets; ++i) + buckets_[i].first = buckets_[i].last = values_.end(); + } + +private: + // Insert an element into the values list by splicing from the spares list, + // if a spare is available, and otherwise by inserting a new element. + iterator values_insert(iterator it, const value_type& v) + { + if (spares_.empty()) + { + return values_.insert(it, v); + } + else + { + spares_.front() = v; + values_.splice(it, spares_, spares_.begin()); + return --it; + } + } + + // Erase an element from the values list by splicing it to the spares list. + void values_erase(iterator it) + { + *it = value_type(); + spares_.splice(spares_.begin(), values_, it); + } + + // The list of all values in the hash map. + std::list values_; + + // The list of spare nodes waiting to be recycled. Assumes that POD types only + // are stored in the hash map. + std::list spares_; + + // The type for a bucket in the hash table. + struct bucket_type + { + iterator first; + iterator last; + }; + + // The number of buckets in the hash. + enum { num_buckets = 1021 }; + + // The buckets in the hash. + bucket_type buckets_[num_buckets]; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_HASH_MAP_HPP diff --git a/win32/include/boost/asio/detail/indirect_handler_queue.hpp b/win32/include/boost/asio/detail/indirect_handler_queue.hpp new file mode 100755 index 000000000..117494560 --- /dev/null +++ b/win32/include/boost/asio/detail/indirect_handler_queue.hpp @@ -0,0 +1,293 @@ +// +// indirect_handler_queue.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP +#define BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if defined(_MSC_VER) && (_MSC_VER >= 1310) +extern "C" void _ReadWriteBarrier(); +# pragma intrinsic(_ReadWriteBarrier) +#endif // defined(_MSC_VER) && (_MSC_VER >= 1310) + +namespace boost { +namespace asio { +namespace detail { + +class indirect_handler_queue + : private noncopyable +{ +public: + class handler; + + // Element for a node in the queue. + class node + { + public: + node() + : version_(0), + handler_(0), + next_(0) + { + } + + private: + friend class indirect_handler_queue; + unsigned long version_; + handler* handler_; + node* next_; + }; + + // Base class for handlers in the queue. + class handler + : private noncopyable + { + public: + void invoke() + { + invoke_func_(this); + } + + void destroy() + { + destroy_func_(this); + } + + protected: + typedef void (*invoke_func_type)(handler*); + typedef void (*destroy_func_type)(handler*); + + handler(invoke_func_type invoke_func, + destroy_func_type destroy_func) + : node_(new node), + invoke_func_(invoke_func), + destroy_func_(destroy_func) + { + } + + ~handler() + { + if (node_) + delete node_; + } + + private: + friend class indirect_handler_queue; + node* node_; + invoke_func_type invoke_func_; + destroy_func_type destroy_func_; + }; + + // Smart point to manager handler lifetimes. + class scoped_ptr + : private noncopyable + { + public: + explicit scoped_ptr(handler* h) + : handler_(h) + { + } + + ~scoped_ptr() + { + if (handler_) + handler_->destroy(); + } + + handler* get() const + { + return handler_; + } + + handler* release() + { + handler* tmp = handler_; + handler_ = 0; + return tmp; + } + + private: + handler* handler_; + }; + + // Constructor. + indirect_handler_queue() + : front_(new node), + back_(front_), + next_version_(1) + { + } + + // Destructor. + ~indirect_handler_queue() + { + while (front_) + { + node* tmp = front_; + front_ = front_->next_; + delete tmp; + } + } + + // Wrap a handler to be pushed into the queue. + template + static handler* wrap(Handler h) + { + // Allocate and construct an object to wrap the handler. + typedef handler_wrapper value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(h); + handler_ptr ptr(raw_ptr, h); + return ptr.release(); + } + + // Determine whether the queue has something ready to pop. + bool poppable() + { + return front_->next_ != 0; + } + + // The version number at the front of the queue. + unsigned long front_version() + { + return front_->version_; + } + + // The version number at the back of the queue. + unsigned long back_version() + { + return back_->version_; + } + + // Pop a handler from the front of the queue. + handler* pop() + { + node* n = front_; + node* new_front = n->next_; + if (new_front) + { + handler* h = new_front->handler_; + h->node_ = n; + new_front->handler_ = 0; + front_ = new_front; + return h; + } + return 0; + } + + // Push a handler on to the back of the queue. + void push(handler* h) + { + node* n = h->node_; + h->node_ = 0; + n->version_ = next_version_; + next_version_ += 2; + n->handler_ = h; + n->next_ = 0; + memory_barrier(); + back_->next_ = n; + back_ = n; + } + +private: + // Template wrapper for handlers. + template + class handler_wrapper + : public handler + { + public: + handler_wrapper(Handler h) + : handler( + &handler_wrapper::do_call, + &handler_wrapper::do_destroy), + handler_(h) + { + } + + static void do_call(handler* base) + { + // Take ownership of the handler object. + typedef handler_wrapper this_type; + this_type* h(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(h->handler_, h); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(h->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Make the upcall. + boost_asio_handler_invoke_helpers::invoke(handler, &handler); + } + + static void do_destroy(handler* base) + { + // Take ownership of the handler object. + typedef handler_wrapper this_type; + this_type* h(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(h->handler_, h); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(h->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + private: + Handler handler_; + }; + + // Helper function to create a memory barrier. + static void memory_barrier() + { +#if defined(_GLIBCXX_WRITE_MEM_BARRIER) + _GLIBCXX_WRITE_MEM_BARRIER; +#elif defined(_MSC_VER) && (_MSC_VER >= 1310) + _ReadWriteBarrier(); +#else +# error memory barrier required +#endif + } + + // The front of the queue. + node* front_; + + // The back of the queue. + node* back_; + + // The next version counter to be assigned to a node. + unsigned long next_version_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP diff --git a/win32/include/boost/asio/detail/io_control.hpp b/win32/include/boost/asio/detail/io_control.hpp new file mode 100755 index 000000000..395d83a8a --- /dev/null +++ b/win32/include/boost/asio/detail/io_control.hpp @@ -0,0 +1,139 @@ +// +// io_control.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IO_CONTROL_HPP +#define BOOST_ASIO_DETAIL_IO_CONTROL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { +namespace io_control { + +// IO control command for non-blocking I/O. +class non_blocking_io +{ +public: + // Default constructor. + non_blocking_io() + : value_(0) + { + } + + // Construct with a specific command value. + non_blocking_io(bool value) + : value_(value ? 1 : 0) + { + } + + // Get the name of the IO control command. + int name() const + { + return FIONBIO; + } + + // Set the value of the I/O control command. + void set(bool value) + { + value_ = value ? 1 : 0; + } + + // Get the current value of the I/O control command. + bool get() const + { + return value_ != 0; + } + + // Get the address of the command data. + detail::ioctl_arg_type* data() + { + return &value_; + } + + // Get the address of the command data. + const detail::ioctl_arg_type* data() const + { + return &value_; + } + +private: + detail::ioctl_arg_type value_; +}; + +// I/O control command for getting number of bytes available. +class bytes_readable +{ +public: + // Default constructor. + bytes_readable() + : value_(0) + { + } + + // Construct with a specific command value. + bytes_readable(std::size_t value) + : value_(static_cast(value)) + { + } + + // Get the name of the IO control command. + int name() const + { + return FIONREAD; + } + + // Set the value of the I/O control command. + void set(std::size_t value) + { + value_ = static_cast(value); + } + + // Get the current value of the I/O control command. + std::size_t get() const + { + return static_cast(value_); + } + + // Get the address of the command data. + detail::ioctl_arg_type* data() + { + return &value_; + } + + // Get the address of the command data. + const detail::ioctl_arg_type* data() const + { + return &value_; + } + +private: + detail::ioctl_arg_type value_; +}; + +} // namespace io_control +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_IO_CONTROL_HPP diff --git a/win32/include/boost/asio/detail/kqueue_reactor.hpp b/win32/include/boost/asio/detail/kqueue_reactor.hpp new file mode 100755 index 000000000..20131dd73 --- /dev/null +++ b/win32/include/boost/asio/detail/kqueue_reactor.hpp @@ -0,0 +1,704 @@ +// +// kqueue_reactor.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_KQUEUE_REACTOR_HPP +#define BOOST_ASIO_DETAIL_KQUEUE_REACTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_KQUEUE) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Older versions of Mac OS X may not define EV_OOBAND. +#if !defined(EV_OOBAND) +# define EV_OOBAND EV_FLAG1 +#endif // !defined(EV_OOBAND) + +namespace boost { +namespace asio { +namespace detail { + +template +class kqueue_reactor + : public boost::asio::detail::service_base > +{ +public: + // Per-descriptor data. + struct per_descriptor_data + { + bool allow_speculative_read; + bool allow_speculative_write; + }; + + // Constructor. + kqueue_reactor(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + kqueue_reactor >(io_service), + mutex_(), + kqueue_fd_(do_kqueue_create()), + wait_in_progress_(false), + interrupter_(), + read_op_queue_(), + write_op_queue_(), + except_op_queue_(), + pending_cancellations_(), + stop_thread_(false), + thread_(0), + shutdown_(false), + need_kqueue_wait_(true) + { + // Start the reactor's internal thread only if needed. + if (Own_Thread) + { + boost::asio::detail::signal_blocker sb; + thread_ = new boost::asio::detail::thread( + bind_handler(&kqueue_reactor::call_run_thread, this)); + } + + // Add the interrupter's descriptor to the kqueue. + struct kevent event; + EV_SET(&event, interrupter_.read_descriptor(), + EVFILT_READ, EV_ADD, 0, 0, 0); + ::kevent(kqueue_fd_, &event, 1, 0, 0, 0); + } + + // Destructor. + ~kqueue_reactor() + { + shutdown_service(); + close(kqueue_fd_); + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + shutdown_ = true; + stop_thread_ = true; + lock.unlock(); + + if (thread_) + { + interrupter_.interrupt(); + thread_->join(); + delete thread_; + thread_ = 0; + } + + read_op_queue_.destroy_operations(); + write_op_queue_.destroy_operations(); + except_op_queue_.destroy_operations(); + + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + timer_queues_[i]->destroy_timers(); + timer_queues_.clear(); + } + + // Register a socket with the reactor. Returns 0 on success, system error + // code on failure. + int register_descriptor(socket_type, per_descriptor_data& descriptor_data) + { + descriptor_data.allow_speculative_read = true; + descriptor_data.allow_speculative_write = true; + + return 0; + } + + // Start a new read operation. The handler object will be invoked when the + // given descriptor is ready to be read, or an error has occurred. + template + void start_read_op(socket_type descriptor, + per_descriptor_data& descriptor_data, Handler handler, + bool allow_speculative_read = true) + { + if (allow_speculative_read && descriptor_data.allow_speculative_read) + { + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + + // We only get one shot at a speculative read in this function. + allow_speculative_read = false; + } + + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + return; + + if (!allow_speculative_read) + need_kqueue_wait_ = true; + else if (!read_op_queue_.has_operation(descriptor)) + { + // Speculative reads are ok as there are no queued read operations. + descriptor_data.allow_speculative_read = true; + + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + } + + // Speculative reads are not ok as there will be queued read operations. + descriptor_data.allow_speculative_read = false; + + if (read_op_queue_.enqueue_operation(descriptor, handler)) + { + struct kevent event; + EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); + if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + read_op_queue_.perform_all_operations(descriptor, ec); + } + } + } + + // Start a new write operation. The handler object will be invoked when the + // given descriptor is ready to be written, or an error has occurred. + template + void start_write_op(socket_type descriptor, + per_descriptor_data& descriptor_data, Handler handler, + bool allow_speculative_write = true) + { + if (allow_speculative_write && descriptor_data.allow_speculative_write) + { + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + + // We only get one shot at a speculative write in this function. + allow_speculative_write = false; + } + + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + return; + + if (!allow_speculative_write) + need_kqueue_wait_ = true; + else if (!write_op_queue_.has_operation(descriptor)) + { + // Speculative writes are ok as there are no queued write operations. + descriptor_data.allow_speculative_write = true; + + boost::system::error_code ec; + std::size_t bytes_transferred = 0; + if (handler.perform(ec, bytes_transferred)) + { + handler.complete(ec, bytes_transferred); + return; + } + } + + // Speculative writes are not ok as there will be queued write operations. + descriptor_data.allow_speculative_write = false; + + if (write_op_queue_.enqueue_operation(descriptor, handler)) + { + struct kevent event; + EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); + if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + write_op_queue_.perform_all_operations(descriptor, ec); + } + } + } + + // Start a new exception operation. The handler object will be invoked when + // the given descriptor has exception information, or an error has occurred. + template + void start_except_op(socket_type descriptor, + per_descriptor_data&, Handler handler) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + return; + + if (except_op_queue_.enqueue_operation(descriptor, handler)) + { + struct kevent event; + if (read_op_queue_.has_operation(descriptor)) + EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); + else + EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0); + if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + except_op_queue_.perform_all_operations(descriptor, ec); + } + } + } + + // Start a new write operation. The handler object will be invoked when the + // given descriptor is ready to be written, or an error has occurred. + template + void start_connect_op(socket_type descriptor, + per_descriptor_data& descriptor_data, Handler handler) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + return; + + // Speculative writes are not ok as there will be queued write operations. + descriptor_data.allow_speculative_write = false; + + if (write_op_queue_.enqueue_operation(descriptor, handler)) + { + struct kevent event; + EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); + if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + write_op_queue_.perform_all_operations(descriptor, ec); + } + } + } + + // Cancel all operations associated with the given descriptor. The + // handlers associated with the descriptor will be invoked with the + // operation_aborted error. + void cancel_ops(socket_type descriptor, per_descriptor_data&) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + cancel_ops_unlocked(descriptor); + } + + // Cancel any operations that are running against the descriptor and remove + // its registration from the reactor. + void close_descriptor(socket_type descriptor, per_descriptor_data&) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // Remove the descriptor from kqueue. + struct kevent event[2]; + EV_SET(&event[0], descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0); + EV_SET(&event[1], descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0); + ::kevent(kqueue_fd_, event, 2, 0, 0, 0); + + // Cancel any outstanding operations associated with the descriptor. + cancel_ops_unlocked(descriptor); + } + + // Add a new timer queue to the reactor. + template + void add_timer_queue(timer_queue& timer_queue) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + timer_queues_.push_back(&timer_queue); + } + + // Remove a timer queue from the reactor. + template + void remove_timer_queue(timer_queue& timer_queue) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + { + if (timer_queues_[i] == &timer_queue) + { + timer_queues_.erase(timer_queues_.begin() + i); + return; + } + } + } + + // Schedule a timer in the given timer queue to expire at the specified + // absolute time. The handler object will be invoked when the timer expires. + template + void schedule_timer(timer_queue& timer_queue, + const typename Time_Traits::time_type& time, Handler handler, void* token) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (!shutdown_) + if (timer_queue.enqueue_timer(time, handler, token)) + interrupter_.interrupt(); + } + + // Cancel the timer associated with the given token. Returns the number of + // handlers that have been posted or dispatched. + template + std::size_t cancel_timer(timer_queue& timer_queue, void* token) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + std::size_t n = timer_queue.cancel_timer(token); + if (n > 0) + interrupter_.interrupt(); + return n; + } + +private: + friend class task_io_service >; + + // Run the kqueue loop. + void run(bool block) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // Dispatch any operation cancellations that were made while the select + // loop was not running. + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + timer_queues_[i]->dispatch_cancellations(); + + // Check if the thread is supposed to stop. + if (stop_thread_) + { + complete_operations_and_timers(lock); + return; + } + + // We can return immediately if there's no work to do and the reactor is + // not supposed to block. + if (!block && read_op_queue_.empty() && write_op_queue_.empty() + && except_op_queue_.empty() && all_timer_queues_are_empty()) + { + complete_operations_and_timers(lock); + return; + } + + // Determine how long to block while waiting for events. + timespec timeout_buf = { 0, 0 }; + timespec* timeout = block ? get_timeout(timeout_buf) : &timeout_buf; + + wait_in_progress_ = true; + lock.unlock(); + + // Block on the kqueue descriptor. + struct kevent events[128]; + int num_events = (block || need_kqueue_wait_) + ? kevent(kqueue_fd_, 0, 0, events, 128, timeout) + : 0; + + lock.lock(); + wait_in_progress_ = false; + + // Block signals while performing operations. + boost::asio::detail::signal_blocker sb; + + // Dispatch the waiting events. + for (int i = 0; i < num_events; ++i) + { + int descriptor = events[i].ident; + if (descriptor == interrupter_.read_descriptor()) + { + interrupter_.reset(); + } + else if (events[i].filter == EVFILT_READ) + { + // Dispatch operations associated with the descriptor. + bool more_reads = false; + bool more_except = false; + if (events[i].flags & EV_ERROR) + { + boost::system::error_code error( + events[i].data, boost::asio::error::get_system_category()); + except_op_queue_.perform_all_operations(descriptor, error); + read_op_queue_.perform_all_operations(descriptor, error); + } + else if (events[i].flags & EV_OOBAND) + { + boost::system::error_code error; + more_except = except_op_queue_.perform_operation(descriptor, error); + if (events[i].data > 0) + more_reads = read_op_queue_.perform_operation(descriptor, error); + else + more_reads = read_op_queue_.has_operation(descriptor); + } + else + { + boost::system::error_code error; + more_reads = read_op_queue_.perform_operation(descriptor, error); + more_except = except_op_queue_.has_operation(descriptor); + } + + // Update the descriptor in the kqueue. + struct kevent event; + if (more_reads) + EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); + else if (more_except) + EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0); + else + EV_SET(&event, descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0); + if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) + { + boost::system::error_code error(errno, + boost::asio::error::get_system_category()); + except_op_queue_.perform_all_operations(descriptor, error); + read_op_queue_.perform_all_operations(descriptor, error); + } + } + else if (events[i].filter == EVFILT_WRITE) + { + // Dispatch operations associated with the descriptor. + bool more_writes = false; + if (events[i].flags & EV_ERROR) + { + boost::system::error_code error( + events[i].data, boost::asio::error::get_system_category()); + write_op_queue_.perform_all_operations(descriptor, error); + } + else + { + boost::system::error_code error; + more_writes = write_op_queue_.perform_operation(descriptor, error); + } + + // Update the descriptor in the kqueue. + struct kevent event; + if (more_writes) + EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); + else + EV_SET(&event, descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0); + if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) + { + boost::system::error_code error(errno, + boost::asio::error::get_system_category()); + write_op_queue_.perform_all_operations(descriptor, error); + } + } + } + + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + { + timer_queues_[i]->dispatch_timers(); + timer_queues_[i]->dispatch_cancellations(); + } + + // Issue any pending cancellations. + for (std::size_t i = 0; i < pending_cancellations_.size(); ++i) + cancel_ops_unlocked(pending_cancellations_[i]); + pending_cancellations_.clear(); + + // Determine whether kqueue needs to be called next time the reactor is run. + need_kqueue_wait_ = !read_op_queue_.empty() + || !write_op_queue_.empty() || !except_op_queue_.empty(); + + complete_operations_and_timers(lock); + } + + // Run the select loop in the thread. + void run_thread() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + while (!stop_thread_) + { + lock.unlock(); + run(true); + lock.lock(); + } + } + + // Entry point for the select loop thread. + static void call_run_thread(kqueue_reactor* reactor) + { + reactor->run_thread(); + } + + // Interrupt the select loop. + void interrupt() + { + interrupter_.interrupt(); + } + + // Create the kqueue file descriptor. Throws an exception if the descriptor + // cannot be created. + static int do_kqueue_create() + { + int fd = kqueue(); + if (fd == -1) + { + boost::throw_exception( + boost::system::system_error( + boost::system::error_code(errno, + boost::asio::error::get_system_category()), + "kqueue")); + } + return fd; + } + + // Check if all timer queues are empty. + bool all_timer_queues_are_empty() const + { + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + if (!timer_queues_[i]->empty()) + return false; + return true; + } + + // Get the timeout value for the kevent call. + timespec* get_timeout(timespec& ts) + { + if (all_timer_queues_are_empty()) + return 0; + + // By default we will wait no longer than 5 minutes. This will ensure that + // any changes to the system clock are detected after no longer than this. + boost::posix_time::time_duration minimum_wait_duration + = boost::posix_time::minutes(5); + + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + { + boost::posix_time::time_duration wait_duration + = timer_queues_[i]->wait_duration(); + if (wait_duration < minimum_wait_duration) + minimum_wait_duration = wait_duration; + } + + if (minimum_wait_duration > boost::posix_time::time_duration()) + { + ts.tv_sec = minimum_wait_duration.total_seconds(); + ts.tv_nsec = minimum_wait_duration.total_nanoseconds() % 1000000000; + } + else + { + ts.tv_sec = 0; + ts.tv_nsec = 0; + } + + return &ts; + } + + // Cancel all operations associated with the given descriptor. The do_cancel + // function of the handler objects will be invoked. This function does not + // acquire the kqueue_reactor's mutex. + void cancel_ops_unlocked(socket_type descriptor) + { + bool interrupt = read_op_queue_.cancel_operations(descriptor); + interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt; + interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt; + if (interrupt) + interrupter_.interrupt(); + } + + // Clean up operations and timers. We must not hold the lock since the + // destructors may make calls back into this reactor. We make a copy of the + // vector of timer queues since the original may be modified while the lock + // is not held. + void complete_operations_and_timers( + boost::asio::detail::mutex::scoped_lock& lock) + { + timer_queues_for_cleanup_ = timer_queues_; + lock.unlock(); + read_op_queue_.complete_operations(); + write_op_queue_.complete_operations(); + except_op_queue_.complete_operations(); + for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) + timer_queues_for_cleanup_[i]->complete_timers(); + } + + // Mutex to protect access to internal data. + boost::asio::detail::mutex mutex_; + + // The kqueue file descriptor. + int kqueue_fd_; + + // Whether the kqueue wait call is currently in progress + bool wait_in_progress_; + + // The interrupter is used to break a blocking kevent call. + select_interrupter interrupter_; + + // The queue of read operations. + reactor_op_queue read_op_queue_; + + // The queue of write operations. + reactor_op_queue write_op_queue_; + + // The queue of except operations. + reactor_op_queue except_op_queue_; + + // The timer queues. + std::vector timer_queues_; + + // A copy of the timer queues, used when cleaning up timers. The copy is + // stored as a class data member to avoid unnecessary memory allocation. + std::vector timer_queues_for_cleanup_; + + // The descriptors that are pending cancellation. + std::vector pending_cancellations_; + + // Does the reactor loop thread need to stop. + bool stop_thread_; + + // The thread that is running the reactor loop. + boost::asio::detail::thread* thread_; + + // Whether the service has been shut down. + bool shutdown_; + + // Whether we need to call kqueue the next time the reactor is run. + bool need_kqueue_wait_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_KQUEUE) + +#include + +#endif // BOOST_ASIO_DETAIL_KQUEUE_REACTOR_HPP diff --git a/win32/include/boost/asio/detail/kqueue_reactor_fwd.hpp b/win32/include/boost/asio/detail/kqueue_reactor_fwd.hpp new file mode 100755 index 000000000..f4d8ec06e --- /dev/null +++ b/win32/include/boost/asio/detail/kqueue_reactor_fwd.hpp @@ -0,0 +1,43 @@ +// +// kqueue_reactor_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP +#define BOOST_ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if !defined(BOOST_ASIO_DISABLE_KQUEUE) +#if defined(__MACH__) && defined(__APPLE__) + +// Define this to indicate that epoll is supported on the target platform. +#define BOOST_ASIO_HAS_KQUEUE 1 + +namespace boost { +namespace asio { +namespace detail { + +template +class kqueue_reactor; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(__MACH__) && defined(__APPLE__) +#endif // !defined(BOOST_ASIO_DISABLE_KQUEUE) + +#include + +#endif // BOOST_ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP diff --git a/win32/include/boost/asio/detail/local_free_on_block_exit.hpp b/win32/include/boost/asio/detail/local_free_on_block_exit.hpp new file mode 100755 index 000000000..8e45ad76e --- /dev/null +++ b/win32/include/boost/asio/detail/local_free_on_block_exit.hpp @@ -0,0 +1,61 @@ +// +// local_free_on_block_exit.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP +#define BOOST_ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +class local_free_on_block_exit + : private noncopyable +{ +public: + // Constructor blocks all signals for the calling thread. + explicit local_free_on_block_exit(void* p) + : p_(p) + { + } + + // Destructor restores the previous signal mask. + ~local_free_on_block_exit() + { + ::LocalFree(p_); + } + +private: + void* p_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + +#include + +#endif // BOOST_ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP diff --git a/win32/include/boost/asio/detail/mutex.hpp b/win32/include/boost/asio/detail/mutex.hpp new file mode 100755 index 000000000..5d5340d90 --- /dev/null +++ b/win32/include/boost/asio/detail/mutex.hpp @@ -0,0 +1,52 @@ +// +// mutex.hpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_MUTEX_HPP +#define BOOST_ASIO_DETAIL_MUTEX_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if !defined(BOOST_HAS_THREADS) +# include +#elif defined(BOOST_WINDOWS) +# include +#elif defined(BOOST_HAS_PTHREADS) +# include +#else +# error Only Windows and POSIX are supported! +#endif + +namespace boost { +namespace asio { +namespace detail { + +#if !defined(BOOST_HAS_THREADS) +typedef null_mutex mutex; +#elif defined(BOOST_WINDOWS) +typedef win_mutex mutex; +#elif defined(BOOST_HAS_PTHREADS) +typedef posix_mutex mutex; +#endif + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_MUTEX_HPP diff --git a/win32/include/boost/asio/detail/noncopyable.hpp b/win32/include/boost/asio/detail/noncopyable.hpp new file mode 100755 index 000000000..953496550 --- /dev/null +++ b/win32/include/boost/asio/detail/noncopyable.hpp @@ -0,0 +1,57 @@ +// +// noncopyable.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_NONCOPYABLE_HPP +#define BOOST_ASIO_DETAIL_NONCOPYABLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +// Redefine the noncopyable class for Borland C++ since that compiler does not +// apply the empty base optimisation unless the base class contains a dummy +// char data member. +class noncopyable +{ +protected: + noncopyable() {} + ~noncopyable() {} +private: + noncopyable(const noncopyable&); + const noncopyable& operator=(const noncopyable&); + char dummy_; +}; +#else +using boost::noncopyable; +#endif + +} // namespace detail + +using boost::asio::detail::noncopyable; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_NONCOPYABLE_HPP diff --git a/win32/include/boost/asio/detail/null_event.hpp b/win32/include/boost/asio/detail/null_event.hpp new file mode 100755 index 000000000..c2383154b --- /dev/null +++ b/win32/include/boost/asio/detail/null_event.hpp @@ -0,0 +1,73 @@ +// +// null_event.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_NULL_EVENT_HPP +#define BOOST_ASIO_DETAIL_NULL_EVENT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if !defined(BOOST_HAS_THREADS) + +#include + +namespace boost { +namespace asio { +namespace detail { + +class null_event + : private noncopyable +{ +public: + // Constructor. + null_event() + { + } + + // Destructor. + ~null_event() + { + } + + // Signal the event. + template + void signal(Lock&) + { + } + + // Reset the event. + template + void clear(Lock&) + { + } + + // Wait for the event to become signalled. + template + void wait(Lock&) + { + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_HAS_THREADS) + +#include + +#endif // BOOST_ASIO_DETAIL_NULL_EVENT_HPP diff --git a/win32/include/boost/asio/detail/null_mutex.hpp b/win32/include/boost/asio/detail/null_mutex.hpp new file mode 100755 index 000000000..45fbce844 --- /dev/null +++ b/win32/include/boost/asio/detail/null_mutex.hpp @@ -0,0 +1,68 @@ +// +// null_mutex.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_NULL_MUTEX_HPP +#define BOOST_ASIO_DETAIL_NULL_MUTEX_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if !defined(BOOST_HAS_THREADS) + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +class null_mutex + : private noncopyable +{ +public: + typedef boost::asio::detail::scoped_lock scoped_lock; + + // Constructor. + null_mutex() + { + } + + // Destructor. + ~null_mutex() + { + } + + // Lock the mutex. + void lock() + { + } + + // Unlock the mutex. + void unlock() + { + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_HAS_THREADS) + +#include + +#endif // BOOST_ASIO_DETAIL_NULL_MUTEX_HPP diff --git a/win32/include/boost/asio/detail/null_signal_blocker.hpp b/win32/include/boost/asio/detail/null_signal_blocker.hpp new file mode 100755 index 000000000..1f49257f5 --- /dev/null +++ b/win32/include/boost/asio/detail/null_signal_blocker.hpp @@ -0,0 +1,65 @@ +// +// null_signal_blocker.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP +#define BOOST_ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if !defined(BOOST_HAS_THREADS) + +#include + +namespace boost { +namespace asio { +namespace detail { + +class null_signal_blocker + : private noncopyable +{ +public: + // Constructor blocks all signals for the calling thread. + null_signal_blocker() + { + } + + // Destructor restores the previous signal mask. + ~null_signal_blocker() + { + } + + // Block all signals for the calling thread. + void block() + { + } + + // Restore the previous signal mask. + void unblock() + { + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_HAS_THREADS) + +#include + +#endif // BOOST_ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP diff --git a/win32/include/boost/asio/detail/null_thread.hpp b/win32/include/boost/asio/detail/null_thread.hpp new file mode 100755 index 000000000..477a95e15 --- /dev/null +++ b/win32/include/boost/asio/detail/null_thread.hpp @@ -0,0 +1,73 @@ +// +// null_thread.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_NULL_THREAD_HPP +#define BOOST_ASIO_DETAIL_NULL_THREAD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#if !defined(BOOST_HAS_THREADS) + +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +class null_thread + : private noncopyable +{ +public: + // The purpose of the thread. + enum purpose { internal, external }; + + // Constructor. + template + null_thread(Function f, purpose = internal) + { + boost::system::system_error e( + boost::asio::error::operation_not_supported, "thread"); + boost::throw_exception(e); + } + + // Destructor. + ~null_thread() + { + } + + // Wait for the thread to exit. + void join() + { + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_HAS_THREADS) + +#include + +#endif // BOOST_ASIO_DETAIL_NULL_THREAD_HPP diff --git a/win32/include/boost/asio/detail/null_tss_ptr.hpp b/win32/include/boost/asio/detail/null_tss_ptr.hpp new file mode 100755 index 000000000..5be696149 --- /dev/null +++ b/win32/include/boost/asio/detail/null_tss_ptr.hpp @@ -0,0 +1,72 @@ +// +// null_tss_ptr.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_NULL_TSS_PTR_HPP +#define BOOST_ASIO_DETAIL_NULL_TSS_PTR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if !defined(BOOST_HAS_THREADS) + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class null_tss_ptr + : private noncopyable +{ +public: + // Constructor. + null_tss_ptr() + : value_(0) + { + } + + // Destructor. + ~null_tss_ptr() + { + } + + // Get the value. + operator T*() const + { + return value_; + } + + // Set the value. + void operator=(T* value) + { + value_ = value; + } + +private: + T* value_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_HAS_THREADS) + +#include + +#endif // BOOST_ASIO_DETAIL_NULL_TSS_PTR_HPP diff --git a/win32/include/boost/asio/detail/old_win_sdk_compat.hpp b/win32/include/boost/asio/detail/old_win_sdk_compat.hpp new file mode 100755 index 000000000..6c62309db --- /dev/null +++ b/win32/include/boost/asio/detail/old_win_sdk_compat.hpp @@ -0,0 +1,342 @@ +// +// old_win_sdk_compat.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP +#define BOOST_ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + +// Guess whether we are building against on old Platform SDK. +#if !defined(IN6ADDR_ANY_INIT) +#define BOOST_ASIO_HAS_OLD_WIN_SDK 1 +#endif // !defined(IN6ADDR_ANY_INIT) + +#if defined(BOOST_ASIO_HAS_OLD_WIN_SDK) + +// Emulation of types that are missing from old Platform SDKs. +// +// N.B. this emulation is also used if building for a Windows 2000 target with +// a recent (i.e. Vista or later) SDK, as the SDK does not provide IPv6 support +// in that case. + +namespace boost { +namespace asio { +namespace detail { + +enum +{ + sockaddr_storage_maxsize = 128, // Maximum size. + sockaddr_storage_alignsize = (sizeof(__int64)), // Desired alignment. + sockaddr_storage_pad1size = (sockaddr_storage_alignsize - sizeof(short)), + sockaddr_storage_pad2size = (sockaddr_storage_maxsize - + (sizeof(short) + sockaddr_storage_pad1size + sockaddr_storage_alignsize)) +}; + +struct sockaddr_storage_emulation +{ + short ss_family; + char __ss_pad1[sockaddr_storage_pad1size]; + __int64 __ss_align; + char __ss_pad2[sockaddr_storage_pad2size]; +}; + +struct in6_addr_emulation +{ + union + { + u_char Byte[16]; + u_short Word[8]; + } u; +}; + +#if !defined(s6_addr) +# define _S6_un u +# define _S6_u8 Byte +# define s6_addr _S6_un._S6_u8 +#endif // !defined(s6_addr) + +struct sockaddr_in6_emulation +{ + short sin6_family; + u_short sin6_port; + u_long sin6_flowinfo; + in6_addr_emulation sin6_addr; + u_long sin6_scope_id; +}; + +struct ipv6_mreq_emulation +{ + in6_addr_emulation ipv6mr_multiaddr; + unsigned int ipv6mr_interface; +}; + +#if !defined(IN6ADDR_ANY_INIT) +# define IN6ADDR_ANY_INIT { 0 } +#endif + +#if !defined(IN6ADDR_LOOPBACK_INIT) +# define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } +#endif + +struct addrinfo_emulation +{ + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + char* ai_canonname; + sockaddr* ai_addr; + addrinfo_emulation* ai_next; +}; + +#if !defined(AI_PASSIVE) +# define AI_PASSIVE 0x1 +#endif + +#if !defined(AI_CANONNAME) +# define AI_CANONNAME 0x2 +#endif + +#if !defined(AI_NUMERICHOST) +# define AI_NUMERICHOST 0x4 +#endif + +#if !defined(EAI_AGAIN) +# define EAI_AGAIN WSATRY_AGAIN +#endif + +#if !defined(EAI_BADFLAGS) +# define EAI_BADFLAGS WSAEINVAL +#endif + +#if !defined(EAI_FAIL) +# define EAI_FAIL WSANO_RECOVERY +#endif + +#if !defined(EAI_FAMILY) +# define EAI_FAMILY WSAEAFNOSUPPORT +#endif + +#if !defined(EAI_MEMORY) +# define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY +#endif + +#if !defined(EAI_NODATA) +# define EAI_NODATA WSANO_DATA +#endif + +#if !defined(EAI_NONAME) +# define EAI_NONAME WSAHOST_NOT_FOUND +#endif + +#if !defined(EAI_SERVICE) +# define EAI_SERVICE WSATYPE_NOT_FOUND +#endif + +#if !defined(EAI_SOCKTYPE) +# define EAI_SOCKTYPE WSAESOCKTNOSUPPORT +#endif + +#if !defined(NI_NOFQDN) +# define NI_NOFQDN 0x01 +#endif + +#if !defined(NI_NUMERICHOST) +# define NI_NUMERICHOST 0x02 +#endif + +#if !defined(NI_NAMEREQD) +# define NI_NAMEREQD 0x04 +#endif + +#if !defined(NI_NUMERICSERV) +# define NI_NUMERICSERV 0x08 +#endif + +#if !defined(NI_DGRAM) +# define NI_DGRAM 0x10 +#endif + +#if !defined(IPPROTO_IPV6) +# define IPPROTO_IPV6 41 +#endif + +#if !defined(IPV6_UNICAST_HOPS) +# define IPV6_UNICAST_HOPS 4 +#endif + +#if !defined(IPV6_MULTICAST_IF) +# define IPV6_MULTICAST_IF 9 +#endif + +#if !defined(IPV6_MULTICAST_HOPS) +# define IPV6_MULTICAST_HOPS 10 +#endif + +#if !defined(IPV6_MULTICAST_LOOP) +# define IPV6_MULTICAST_LOOP 11 +#endif + +#if !defined(IPV6_JOIN_GROUP) +# define IPV6_JOIN_GROUP 12 +#endif + +#if !defined(IPV6_LEAVE_GROUP) +# define IPV6_LEAVE_GROUP 13 +#endif + +inline int IN6_IS_ADDR_UNSPECIFIED(const in6_addr_emulation* a) +{ + return ((a->s6_addr[0] == 0) + && (a->s6_addr[1] == 0) + && (a->s6_addr[2] == 0) + && (a->s6_addr[3] == 0) + && (a->s6_addr[4] == 0) + && (a->s6_addr[5] == 0) + && (a->s6_addr[6] == 0) + && (a->s6_addr[7] == 0) + && (a->s6_addr[8] == 0) + && (a->s6_addr[9] == 0) + && (a->s6_addr[10] == 0) + && (a->s6_addr[11] == 0) + && (a->s6_addr[12] == 0) + && (a->s6_addr[13] == 0) + && (a->s6_addr[14] == 0) + && (a->s6_addr[15] == 0)); +} + +inline int IN6_IS_ADDR_LOOPBACK(const in6_addr_emulation* a) +{ + return ((a->s6_addr[0] == 0) + && (a->s6_addr[1] == 0) + && (a->s6_addr[2] == 0) + && (a->s6_addr[3] == 0) + && (a->s6_addr[4] == 0) + && (a->s6_addr[5] == 0) + && (a->s6_addr[6] == 0) + && (a->s6_addr[7] == 0) + && (a->s6_addr[8] == 0) + && (a->s6_addr[9] == 0) + && (a->s6_addr[10] == 0) + && (a->s6_addr[11] == 0) + && (a->s6_addr[12] == 0) + && (a->s6_addr[13] == 0) + && (a->s6_addr[14] == 0) + && (a->s6_addr[15] == 1)); +} + +inline int IN6_IS_ADDR_MULTICAST(const in6_addr_emulation* a) +{ + return (a->s6_addr[0] == 0xff); +} + +inline int IN6_IS_ADDR_LINKLOCAL(const in6_addr_emulation* a) +{ + return ((a->s6_addr[0] == 0xfe) && ((a->s6_addr[1] & 0xc0) == 0x80)); +} + +inline int IN6_IS_ADDR_SITELOCAL(const in6_addr_emulation* a) +{ + return ((a->s6_addr[0] == 0xfe) && ((a->s6_addr[1] & 0xc0) == 0xc0)); +} + +inline int IN6_IS_ADDR_V4MAPPED(const in6_addr_emulation* a) +{ + return ((a->s6_addr[0] == 0) + && (a->s6_addr[1] == 0) + && (a->s6_addr[2] == 0) + && (a->s6_addr[3] == 0) + && (a->s6_addr[4] == 0) + && (a->s6_addr[5] == 0) + && (a->s6_addr[6] == 0) + && (a->s6_addr[7] == 0) + && (a->s6_addr[8] == 0) + && (a->s6_addr[9] == 0) + && (a->s6_addr[10] == 0xff) + && (a->s6_addr[11] == 0xff)); +} + +inline int IN6_IS_ADDR_V4COMPAT(const in6_addr_emulation* a) +{ + return ((a->s6_addr[0] == 0) + && (a->s6_addr[1] == 0) + && (a->s6_addr[2] == 0) + && (a->s6_addr[3] == 0) + && (a->s6_addr[4] == 0) + && (a->s6_addr[5] == 0) + && (a->s6_addr[6] == 0) + && (a->s6_addr[7] == 0) + && (a->s6_addr[8] == 0) + && (a->s6_addr[9] == 0) + && (a->s6_addr[10] == 0xff) + && (a->s6_addr[11] == 0xff) + && !((a->s6_addr[12] == 0) + && (a->s6_addr[13] == 0) + && (a->s6_addr[14] == 0) + && ((a->s6_addr[15] == 0) || (a->s6_addr[15] == 1)))); +} + +inline int IN6_IS_ADDR_MC_NODELOCAL(const in6_addr_emulation* a) +{ + return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 1); +} + +inline int IN6_IS_ADDR_MC_LINKLOCAL(const in6_addr_emulation* a) +{ + return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 2); +} + +inline int IN6_IS_ADDR_MC_SITELOCAL(const in6_addr_emulation* a) +{ + return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 5); +} + +inline int IN6_IS_ADDR_MC_ORGLOCAL(const in6_addr_emulation* a) +{ + return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 8); +} + +inline int IN6_IS_ADDR_MC_GLOBAL(const in6_addr_emulation* a) +{ + return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 0xe); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_OLD_WIN_SDK) + +// Even newer Platform SDKs that support IPv6 may not define IPV6_V6ONLY. +#if !defined(IPV6_V6ONLY) +# define IPV6_V6ONLY 27 +#endif + +// Some SDKs (e.g. Windows CE) don't define IPPROTO_ICMPV6. +#if !defined(IPPROTO_ICMPV6) +# define IPPROTO_ICMPV6 58 +#endif + +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + +#include + +#endif // BOOST_ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP diff --git a/win32/include/boost/asio/detail/pipe_select_interrupter.hpp b/win32/include/boost/asio/detail/pipe_select_interrupter.hpp new file mode 100755 index 000000000..88115bee0 --- /dev/null +++ b/win32/include/boost/asio/detail/pipe_select_interrupter.hpp @@ -0,0 +1,116 @@ +// +// pipe_select_interrupter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP +#define BOOST_ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +class pipe_select_interrupter +{ +public: + // Constructor. + pipe_select_interrupter() + { + int pipe_fds[2]; + if (pipe(pipe_fds) == 0) + { + read_descriptor_ = pipe_fds[0]; + ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); + write_descriptor_ = pipe_fds[1]; + ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK); + } + else + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + boost::system::system_error e(ec, "pipe_select_interrupter"); + boost::throw_exception(e); + } + } + + // Destructor. + ~pipe_select_interrupter() + { + if (read_descriptor_ != -1) + ::close(read_descriptor_); + if (write_descriptor_ != -1) + ::close(write_descriptor_); + } + + // Interrupt the select call. + void interrupt() + { + char byte = 0; + ::write(write_descriptor_, &byte, 1); + } + + // Reset the select interrupt. Returns true if the call was interrupted. + bool reset() + { + char data[1024]; + int bytes_read = ::read(read_descriptor_, data, sizeof(data)); + bool was_interrupted = (bytes_read > 0); + while (bytes_read == sizeof(data)) + bytes_read = ::read(read_descriptor_, data, sizeof(data)); + return was_interrupted; + } + + // Get the read descriptor to be passed to select. + int read_descriptor() const + { + return read_descriptor_; + } + +private: + // The read end of a connection used to interrupt the select call. This file + // descriptor is passed to select such that when it is time to stop, a single + // byte will be written on the other end of the connection and this + // descriptor will become readable. + int read_descriptor_; + + // The write end of a connection used to interrupt the select call. A single + // byte may be written to this to wake up the select which is waiting for the + // other end to become readable. + int write_descriptor_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include + +#endif // BOOST_ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP diff --git a/win32/include/boost/asio/detail/pop_options.hpp b/win32/include/boost/asio/detail/pop_options.hpp new file mode 100755 index 000000000..6cf2c5e53 --- /dev/null +++ b/win32/include/boost/asio/detail/pop_options.hpp @@ -0,0 +1,88 @@ +// +// pop_options.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// 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) +// + +// No header guard + +#if defined(__COMO__) + +// Comeau C++ + +#elif defined(__DMC__) + +// Digital Mars C++ + +#elif defined(__INTEL_COMPILER) || defined(__ICL) \ + || defined(__ICC) || defined(__ECC) + +// Intel C++ + +#elif defined(__GNUC__) + +// GNU C++ + +# if defined(__MINGW32__) || defined(__CYGWIN__) +# pragma pack (pop) +# endif + +#elif defined(__KCC) + +// Kai C++ + +#elif defined(__sgi) + +// SGI MIPSpro C++ + +#elif defined(__DECCXX) + +// Compaq Tru64 Unix cxx + +#elif defined(__ghs) + +// Greenhills C++ + +#elif defined(__BORLANDC__) + +// Borland C++ + +# pragma option pop +# pragma nopushoptwarn +# pragma nopackwarning + +#elif defined(__MWERKS__) + +// Metrowerks CodeWarrior + +#elif defined(__SUNPRO_CC) + +// Sun Workshop Compiler C++ + +#elif defined(__HP_aCC) + +// HP aCC + +#elif defined(__MRC__) || defined(__SC__) + +// MPW MrCpp or SCpp + +#elif defined(__IBMCPP__) + +// IBM Visual Age + +#elif defined(_MSC_VER) + +// Microsoft Visual C++ +// +// Must remain the last #elif since some other vendors (Metrowerks, for example) +// also #define _MSC_VER + +# pragma warning (pop) +# pragma pack (pop) + +#endif diff --git a/win32/include/boost/asio/detail/posix_event.hpp b/win32/include/boost/asio/detail/posix_event.hpp new file mode 100755 index 000000000..72d3ada54 --- /dev/null +++ b/win32/include/boost/asio/detail/posix_event.hpp @@ -0,0 +1,106 @@ +// +// posix_event.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_POSIX_EVENT_HPP +#define BOOST_ASIO_DETAIL_POSIX_EVENT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#if defined(BOOST_HAS_PTHREADS) + +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +class posix_event + : private noncopyable +{ +public: + // Constructor. + posix_event() + : signalled_(false) + { + int error = ::pthread_cond_init(&cond_, 0); + if (error != 0) + { + boost::system::system_error e( + boost::system::error_code(error, + boost::asio::error::get_system_category()), + "event"); + boost::throw_exception(e); + } + } + + // Destructor. + ~posix_event() + { + ::pthread_cond_destroy(&cond_); + } + + // Signal the event. + template + void signal(Lock& lock) + { + BOOST_ASSERT(lock.locked()); + (void)lock; + signalled_ = true; + ::pthread_cond_signal(&cond_); // Ignore EINVAL. + } + + // Reset the event. + template + void clear(Lock& lock) + { + BOOST_ASSERT(lock.locked()); + (void)lock; + signalled_ = false; + } + + // Wait for the event to become signalled. + template + void wait(Lock& lock) + { + BOOST_ASSERT(lock.locked()); + while (!signalled_) + ::pthread_cond_wait(&cond_, &lock.mutex().mutex_); // Ignore EINVAL. + } + +private: + ::pthread_cond_t cond_; + bool signalled_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_HAS_PTHREADS) + +#include + +#endif // BOOST_ASIO_DETAIL_POSIX_EVENT_HPP diff --git a/win32/include/boost/asio/detail/posix_fd_set_adapter.hpp b/win32/include/boost/asio/detail/posix_fd_set_adapter.hpp new file mode 100755 index 000000000..d7a2e55f9 --- /dev/null +++ b/win32/include/boost/asio/detail/posix_fd_set_adapter.hpp @@ -0,0 +1,79 @@ +// +// posix_fd_set_adapter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP +#define BOOST_ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +namespace boost { +namespace asio { +namespace detail { + +// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements. +class posix_fd_set_adapter +{ +public: + posix_fd_set_adapter() + : max_descriptor_(invalid_socket) + { + using namespace std; // Needed for memset on Solaris. + FD_ZERO(&fd_set_); + } + + bool set(socket_type descriptor) + { + if (descriptor < (socket_type)FD_SETSIZE) + { + if (max_descriptor_ == invalid_socket || descriptor > max_descriptor_) + max_descriptor_ = descriptor; + FD_SET(descriptor, &fd_set_); + return true; + } + return false; + } + + bool is_set(socket_type descriptor) const + { + return FD_ISSET(descriptor, &fd_set_) != 0; + } + + operator fd_set*() + { + return &fd_set_; + } + + socket_type max_descriptor() const + { + return max_descriptor_; + } + +private: + mutable fd_set fd_set_; + socket_type max_descriptor_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include + +#endif // BOOST_ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP diff --git a/win32/include/boost/asio/detail/posix_mutex.hpp b/win32/include/boost/asio/detail/posix_mutex.hpp new file mode 100755 index 000000000..e9bba40af --- /dev/null +++ b/win32/include/boost/asio/detail/posix_mutex.hpp @@ -0,0 +1,109 @@ +// +// posix_mutex.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_POSIX_MUTEX_HPP +#define BOOST_ASIO_DETAIL_POSIX_MUTEX_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#if defined(BOOST_HAS_PTHREADS) + +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +class posix_event; + +class posix_mutex + : private noncopyable +{ +public: + typedef boost::asio::detail::scoped_lock scoped_lock; + + // Constructor. + posix_mutex() + { + int error = ::pthread_mutex_init(&mutex_, 0); + if (error != 0) + { + boost::system::system_error e( + boost::system::error_code(error, + boost::asio::error::get_system_category()), + "mutex"); + boost::throw_exception(e); + } + } + + // Destructor. + ~posix_mutex() + { + ::pthread_mutex_destroy(&mutex_); + } + + // Lock the mutex. + void lock() + { + int error = ::pthread_mutex_lock(&mutex_); + if (error != 0) + { + boost::system::system_error e( + boost::system::error_code(error, + boost::asio::error::get_system_category()), + "mutex"); + boost::throw_exception(e); + } + } + + // Unlock the mutex. + void unlock() + { + int error = ::pthread_mutex_unlock(&mutex_); + if (error != 0) + { + boost::system::system_error e( + boost::system::error_code(error, + boost::asio::error::get_system_category()), + "mutex"); + boost::throw_exception(e); + } + } + +private: + friend class posix_event; + ::pthread_mutex_t mutex_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_HAS_PTHREADS) + +#include + +#endif // BOOST_ASIO_DETAIL_POSIX_MUTEX_HPP diff --git a/win32/include/boost/asio/detail/posix_signal_blocker.hpp b/win32/include/boost/asio/detail/posix_signal_blocker.hpp new file mode 100755 index 000000000..caa4ea5dd --- /dev/null +++ b/win32/include/boost/asio/detail/posix_signal_blocker.hpp @@ -0,0 +1,92 @@ +// +// posix_signal_blocker.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP +#define BOOST_ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if defined(BOOST_HAS_PTHREADS) + +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class posix_signal_blocker + : private noncopyable +{ +public: + // Constructor blocks all signals for the calling thread. + posix_signal_blocker() + : blocked_(false) + { + sigset_t new_mask; + sigfillset(&new_mask); + blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0); + } + + // Destructor restores the previous signal mask. + ~posix_signal_blocker() + { + if (blocked_) + pthread_sigmask(SIG_SETMASK, &old_mask_, 0); + } + + // Block all signals for the calling thread. + void block() + { + if (!blocked_) + { + sigset_t new_mask; + sigfillset(&new_mask); + blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0); + } + } + + // Restore the previous signal mask. + void unblock() + { + if (blocked_) + blocked_ = (pthread_sigmask(SIG_SETMASK, &old_mask_, 0) != 0); + } + +private: + // Have signals been blocked. + bool blocked_; + + // The previous signal mask. + sigset_t old_mask_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_HAS_PTHREADS) + +#include + +#endif // BOOST_ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP diff --git a/win32/include/boost/asio/detail/posix_thread.hpp b/win32/include/boost/asio/detail/posix_thread.hpp new file mode 100755 index 000000000..fc997f5d4 --- /dev/null +++ b/win32/include/boost/asio/detail/posix_thread.hpp @@ -0,0 +1,134 @@ +// +// posix_thread.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_POSIX_THREAD_HPP +#define BOOST_ASIO_DETAIL_POSIX_THREAD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#if defined(BOOST_HAS_PTHREADS) + +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +extern "C" void* asio_detail_posix_thread_function(void* arg); + +class posix_thread + : private noncopyable +{ +public: + // The purpose of the thread. + enum purpose { internal, external }; + + // Constructor. + template + posix_thread(Function f, purpose = internal) + : joined_(false) + { + std::auto_ptr arg(new func(f)); + int error = ::pthread_create(&thread_, 0, + asio_detail_posix_thread_function, arg.get()); + if (error != 0) + { + boost::system::system_error e( + boost::system::error_code(error, + boost::asio::error::get_system_category()), + "thread"); + boost::throw_exception(e); + } + arg.release(); + } + + // Destructor. + ~posix_thread() + { + if (!joined_) + ::pthread_detach(thread_); + } + + // Wait for the thread to exit. + void join() + { + if (!joined_) + { + ::pthread_join(thread_, 0); + joined_ = true; + } + } + +private: + friend void* asio_detail_posix_thread_function(void* arg); + + class func_base + { + public: + virtual ~func_base() {} + virtual void run() = 0; + }; + + template + class func + : public func_base + { + public: + func(Function f) + : f_(f) + { + } + + virtual void run() + { + f_(); + } + + private: + Function f_; + }; + + ::pthread_t thread_; + bool joined_; +}; + +inline void* asio_detail_posix_thread_function(void* arg) +{ + std::auto_ptr f( + static_cast(arg)); + f->run(); + return 0; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_HAS_PTHREADS) + +#include + +#endif // BOOST_ASIO_DETAIL_POSIX_THREAD_HPP diff --git a/win32/include/boost/asio/detail/posix_tss_ptr.hpp b/win32/include/boost/asio/detail/posix_tss_ptr.hpp new file mode 100755 index 000000000..db3fd7be6 --- /dev/null +++ b/win32/include/boost/asio/detail/posix_tss_ptr.hpp @@ -0,0 +1,90 @@ +// +// posix_tss_ptr.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_POSIX_TSS_PTR_HPP +#define BOOST_ASIO_DETAIL_POSIX_TSS_PTR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#if defined(BOOST_HAS_PTHREADS) + +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class posix_tss_ptr + : private noncopyable +{ +public: + // Constructor. + posix_tss_ptr() + { + int error = ::pthread_key_create(&tss_key_, 0); + if (error != 0) + { + boost::system::system_error e( + boost::system::error_code(error, + boost::asio::error::get_system_category()), + "tss"); + boost::throw_exception(e); + } + } + + // Destructor. + ~posix_tss_ptr() + { + ::pthread_key_delete(tss_key_); + } + + // Get the value. + operator T*() const + { + return static_cast(::pthread_getspecific(tss_key_)); + } + + // Set the value. + void operator=(T* value) + { + ::pthread_setspecific(tss_key_, value); + } + +private: + // Thread-specific storage to allow unlocked access to determine whether a + // thread is a member of the pool. + pthread_key_t tss_key_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_HAS_PTHREADS) + +#include + +#endif // BOOST_ASIO_DETAIL_POSIX_TSS_PTR_HPP diff --git a/win32/include/boost/asio/detail/push_options.hpp b/win32/include/boost/asio/detail/push_options.hpp new file mode 100755 index 000000000..8837928a8 --- /dev/null +++ b/win32/include/boost/asio/detail/push_options.hpp @@ -0,0 +1,114 @@ +// +// push_options.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// 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) +// + +// No header guard + +#if defined(__COMO__) + +// Comeau C++ + +#elif defined(__DMC__) + +// Digital Mars C++ + +#elif defined(__INTEL_COMPILER) || defined(__ICL) \ + || defined(__ICC) || defined(__ECC) + +// Intel C++ + +#elif defined(__GNUC__) + +// GNU C++ + +# if defined(__MINGW32__) || defined(__CYGWIN__) +# pragma pack (push, 8) +# endif + +#elif defined(__KCC) + +// Kai C++ + +#elif defined(__sgi) + +// SGI MIPSpro C++ + +#elif defined(__DECCXX) + +// Compaq Tru64 Unix cxx + +#elif defined(__ghs) + +// Greenhills C++ + +#elif defined(__BORLANDC__) + +// Borland C++ + +# pragma option push -a8 -b -Ve- -Vx- -w-inl -vi- +# pragma nopushoptwarn +# pragma nopackwarning +# if !defined(__MT__) +# error Multithreaded RTL must be selected. +# endif // !defined(__MT__) + +#elif defined(__MWERKS__) + +// Metrowerks CodeWarrior + +#elif defined(__SUNPRO_CC) + +// Sun Workshop Compiler C++ + +#elif defined(__HP_aCC) + +// HP aCC + +#elif defined(__MRC__) || defined(__SC__) + +// MPW MrCpp or SCpp + +#elif defined(__IBMCPP__) + +// IBM Visual Age + +#elif defined(_MSC_VER) + +// Microsoft Visual C++ +// +// Must remain the last #elif since some other vendors (Metrowerks, for example) +// also #define _MSC_VER + +# pragma warning (disable:4103) +# pragma warning (push) +# pragma warning (disable:4127) +# pragma warning (disable:4244) +# pragma warning (disable:4355) +# pragma warning (disable:4512) +# pragma warning (disable:4675) +# if defined(_M_IX86) && defined(_Wp64) +// The /Wp64 option is broken. If you want to check 64 bit portability, use a +// 64 bit compiler! +# pragma warning (disable:4311) +# pragma warning (disable:4312) +# endif // defined(_M_IX86) && defined(_Wp64) +# pragma pack (push, 8) +// Note that if the /Og optimisation flag is enabled with MSVC6, the compiler +// has a tendency to incorrectly optimise away some calls to member template +// functions, even though those functions contain code that should not be +// optimised away! Therefore we will always disable this optimisation option +// for the MSVC6 compiler. +# if (_MSC_VER < 1300) +# pragma optimize ("g", off) +# endif +# if !defined(_MT) +# error Multithreaded RTL must be selected. +# endif // !defined(_MT) + +#endif diff --git a/win32/include/boost/asio/detail/reactive_descriptor_service.hpp b/win32/include/boost/asio/detail/reactive_descriptor_service.hpp new file mode 100755 index 000000000..61884d929 --- /dev/null +++ b/win32/include/boost/asio/detail/reactive_descriptor_service.hpp @@ -0,0 +1,711 @@ +// +// reactive_descriptor_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +namespace boost { +namespace asio { +namespace detail { + +template +class reactive_descriptor_service + : public boost::asio::detail::service_base< + reactive_descriptor_service > +{ +public: + // The native type of a descriptor. + typedef int native_type; + + // The implementation type of the descriptor. + class implementation_type + : private boost::asio::detail::noncopyable + { + public: + // Default constructor. + implementation_type() + : descriptor_(-1), + flags_(0) + { + } + + private: + // Only this service will have access to the internal values. + friend class reactive_descriptor_service; + + // The native descriptor representation. + int descriptor_; + + enum + { + user_set_non_blocking = 1, // The user wants a non-blocking descriptor. + internal_non_blocking = 2 // The descriptor has been set non-blocking. + }; + + // Flags indicating the current state of the descriptor. + unsigned char flags_; + + // Per-descriptor data used by the reactor. + typename Reactor::per_descriptor_data reactor_data_; + }; + + // The maximum number of buffers to support in a single operation. + enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; + + // Constructor. + reactive_descriptor_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + reactive_descriptor_service >(io_service), + reactor_(boost::asio::use_service(io_service)) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Construct a new descriptor implementation. + void construct(implementation_type& impl) + { + impl.descriptor_ = -1; + impl.flags_ = 0; + } + + // Destroy a descriptor implementation. + void destroy(implementation_type& impl) + { + if (impl.descriptor_ != -1) + { + reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_); + + if (impl.flags_ & implementation_type::internal_non_blocking) + { + ioctl_arg_type non_blocking = 0; + boost::system::error_code ignored_ec; + descriptor_ops::ioctl(impl.descriptor_, + FIONBIO, &non_blocking, ignored_ec); + impl.flags_ &= ~implementation_type::internal_non_blocking; + } + + boost::system::error_code ignored_ec; + descriptor_ops::close(impl.descriptor_, ignored_ec); + + impl.descriptor_ = -1; + } + } + + // Assign a native descriptor to a descriptor implementation. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_descriptor, boost::system::error_code& ec) + { + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + if (int err = reactor_.register_descriptor( + native_descriptor, impl.reactor_data_)) + { + ec = boost::system::error_code(err, + boost::asio::error::get_system_category()); + return ec; + } + + impl.descriptor_ = native_descriptor; + impl.flags_ = 0; + ec = boost::system::error_code(); + return ec; + } + + // Determine whether the descriptor is open. + bool is_open(const implementation_type& impl) const + { + return impl.descriptor_ != -1; + } + + // Destroy a descriptor implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + if (is_open(impl)) + { + reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_); + + if (impl.flags_ & implementation_type::internal_non_blocking) + { + ioctl_arg_type non_blocking = 0; + boost::system::error_code ignored_ec; + descriptor_ops::ioctl(impl.descriptor_, + FIONBIO, &non_blocking, ignored_ec); + impl.flags_ &= ~implementation_type::internal_non_blocking; + } + + if (descriptor_ops::close(impl.descriptor_, ec) == -1) + return ec; + + impl.descriptor_ = -1; + } + + ec = boost::system::error_code(); + return ec; + } + + // Get the native descriptor representation. + native_type native(const implementation_type& impl) const + { + return impl.descriptor_; + } + + // Cancel all operations associated with the descriptor. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + reactor_.cancel_ops(impl.descriptor_, impl.reactor_data_); + ec = boost::system::error_code(); + return ec; + } + + // Perform an IO control command on the descriptor. + template + boost::system::error_code io_control(implementation_type& impl, + IO_Control_Command& command, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + if (command.name() == static_cast(FIONBIO)) + { + if (command.get()) + impl.flags_ |= implementation_type::user_set_non_blocking; + else + impl.flags_ &= ~implementation_type::user_set_non_blocking; + ec = boost::system::error_code(); + } + else + { + descriptor_ops::ioctl(impl.descriptor_, command.name(), + static_cast(command.data()), ec); + } + return ec; + } + + // Write some data to the descriptor. + template + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Copy buffers into array. + descriptor_ops::buf bufs[max_buffers]; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + descriptor_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to read_some 0 bytes on a stream is a no-op. + if (total_buffer_size == 0) + { + ec = boost::system::error_code(); + return 0; + } + + // Make descriptor non-blocking if user wants non-blocking. + if (impl.flags_ & implementation_type::user_set_non_blocking) + { + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + if (descriptor_ops::ioctl(impl.descriptor_, + FIONBIO, &non_blocking, ec)) + return 0; + impl.flags_ |= implementation_type::internal_non_blocking; + } + } + + // Send the data. + for (;;) + { + // Try to complete the operation without blocking. + int bytes_sent = descriptor_ops::gather_write( + impl.descriptor_, bufs, i, ec); + + // Check if operation succeeded. + if (bytes_sent >= 0) + return bytes_sent; + + // Operation failed. + if ((impl.flags_ & implementation_type::user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for descriptor to become ready. + if (descriptor_ops::poll_write(impl.descriptor_, ec) < 0) + return 0; + } + } + + // Wait until data can be written without blocking. + size_t write_some(implementation_type& impl, + const null_buffers&, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for descriptor to become ready. + descriptor_ops::poll_write(impl.descriptor_, ec); + + return 0; + } + + template + class write_operation : + public handler_base_from_member + { + public: + write_operation(int descriptor, boost::asio::io_service& io_service, + const ConstBufferSequence& buffers, Handler handler) + : handler_base_from_member(handler), + descriptor_(descriptor), + io_service_(io_service), + work_(io_service), + buffers_(buffers) + { + } + + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) + { + // Check whether the operation was successful. + if (ec) + { + bytes_transferred = 0; + return true; + } + + // Copy buffers into array. + descriptor_ops::buf bufs[max_buffers]; + typename ConstBufferSequence::const_iterator iter = buffers_.begin(); + typename ConstBufferSequence::const_iterator end = buffers_.end(); + size_t i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + descriptor_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + } + + // Write the data. + int bytes = descriptor_ops::gather_write(descriptor_, bufs, i, ec); + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + bytes_transferred = (bytes < 0 ? 0 : bytes); + return true; + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + + private: + int descriptor_; + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + ConstBufferSequence buffers_; + }; + + // Start an asynchronous write. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + // Determine total size of buffers. + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to read_some 0 bytes on a stream is a no-op. + if (total_buffer_size == 0) + { + this->get_io_service().post(bind_handler(handler, + boost::system::error_code(), 0)); + return; + } + + // Make descriptor non-blocking. + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + boost::system::error_code ec; + if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) + { + this->get_io_service().post(bind_handler(handler, ec, 0)); + return; + } + impl.flags_ |= implementation_type::internal_non_blocking; + } + + reactor_.start_write_op(impl.descriptor_, impl.reactor_data_, + write_operation( + impl.descriptor_, this->get_io_service(), buffers, handler)); + } + } + + template + class null_buffers_operation : + public handler_base_from_member + { + public: + null_buffers_operation(boost::asio::io_service& io_service, Handler handler) + : handler_base_from_member(handler), + work_(io_service) + { + } + + bool perform(boost::system::error_code&, + std::size_t& bytes_transferred) + { + bytes_transferred = 0; + return true; + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + work_.get_io_service().post(bind_handler( + this->handler_, ec, bytes_transferred)); + } + + private: + boost::asio::io_service::work work_; + }; + + // Start an asynchronous wait until data can be written without blocking. + template + void async_write_some(implementation_type& impl, + const null_buffers&, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + reactor_.start_write_op(impl.descriptor_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + + // Read some data from the stream. Returns the number of bytes read. + template + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Copy buffers into array. + descriptor_ops::buf bufs[max_buffers]; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + descriptor_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to read_some 0 bytes on a stream is a no-op. + if (total_buffer_size == 0) + { + ec = boost::system::error_code(); + return 0; + } + + // Make descriptor non-blocking if user wants non-blocking. + if (impl.flags_ & implementation_type::user_set_non_blocking) + { + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) + return 0; + impl.flags_ |= implementation_type::internal_non_blocking; + } + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + int bytes_read = descriptor_ops::scatter_read( + impl.descriptor_, bufs, i, ec); + + // Check if operation succeeded. + if (bytes_read > 0) + return bytes_read; + + // Check for EOF. + if (bytes_read == 0) + { + ec = boost::asio::error::eof; + return 0; + } + + // Operation failed. + if ((impl.flags_ & implementation_type::user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for descriptor to become ready. + if (descriptor_ops::poll_read(impl.descriptor_, ec) < 0) + return 0; + } + } + + // Wait until data can be read without blocking. + size_t read_some(implementation_type& impl, + const null_buffers&, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for descriptor to become ready. + descriptor_ops::poll_read(impl.descriptor_, ec); + + return 0; + } + + template + class read_operation : + public handler_base_from_member + { + public: + read_operation(int descriptor, boost::asio::io_service& io_service, + const MutableBufferSequence& buffers, Handler handler) + : handler_base_from_member(handler), + descriptor_(descriptor), + io_service_(io_service), + work_(io_service), + buffers_(buffers) + { + } + + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) + { + // Check whether the operation was successful. + if (ec) + { + bytes_transferred = 0; + return true; + } + + // Copy buffers into array. + descriptor_ops::buf bufs[max_buffers]; + typename MutableBufferSequence::const_iterator iter = buffers_.begin(); + typename MutableBufferSequence::const_iterator end = buffers_.end(); + size_t i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + descriptor_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + } + + // Read some data. + int bytes = descriptor_ops::scatter_read(descriptor_, bufs, i, ec); + if (bytes == 0) + ec = boost::asio::error::eof; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + bytes_transferred = (bytes < 0 ? 0 : bytes); + return true; + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + + private: + int descriptor_; + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + MutableBufferSequence buffers_; + }; + + // Start an asynchronous read. The buffer for the data being read must be + // valid for the lifetime of the asynchronous operation. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + // Determine total size of buffers. + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to read_some 0 bytes on a stream is a no-op. + if (total_buffer_size == 0) + { + this->get_io_service().post(bind_handler(handler, + boost::system::error_code(), 0)); + return; + } + + // Make descriptor non-blocking. + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + boost::system::error_code ec; + if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec)) + { + this->get_io_service().post(bind_handler(handler, ec, 0)); + return; + } + impl.flags_ |= implementation_type::internal_non_blocking; + } + + reactor_.start_read_op(impl.descriptor_, impl.reactor_data_, + read_operation( + impl.descriptor_, this->get_io_service(), buffers, handler)); + } + } + + // Wait until data can be read without blocking. + template + void async_read_some(implementation_type& impl, + const null_buffers&, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + reactor_.start_read_op(impl.descriptor_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + +private: + // The selector that performs event demultiplexing for the service. + Reactor& reactor_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include + +#endif // BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP diff --git a/win32/include/boost/asio/detail/reactive_serial_port_service.hpp b/win32/include/boost/asio/detail/reactive_serial_port_service.hpp new file mode 100755 index 000000000..69dc899a0 --- /dev/null +++ b/win32/include/boost/asio/detail/reactive_serial_port_service.hpp @@ -0,0 +1,270 @@ +// +// reactive_serial_port_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +// Extend reactive_descriptor_service to provide serial port support. +template +class reactive_serial_port_service + : public boost::asio::detail::service_base< + reactive_serial_port_service > +{ +public: + // The native type of a stream handle. + typedef typename reactive_descriptor_service::native_type + native_type; + + // The implementation type of the stream handle. + typedef typename reactive_descriptor_service::implementation_type + implementation_type; + + reactive_serial_port_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + reactive_serial_port_service>(io_service), + descriptor_service_(boost::asio::use_service< + reactive_descriptor_service >(io_service)) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Construct a new handle implementation. + void construct(implementation_type& impl) + { + descriptor_service_.construct(impl); + } + + // Destroy a handle implementation. + void destroy(implementation_type& impl) + { + descriptor_service_.destroy(impl); + } + + // Open the serial port using the specified device name. + boost::system::error_code open(implementation_type& impl, + const std::string& device, boost::system::error_code& ec) + { + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + int fd = descriptor_ops::open(device.c_str(), + O_RDWR | O_NONBLOCK | O_NOCTTY, ec); + if (fd < 0) + return ec; + + int s = descriptor_ops::fcntl(fd, F_GETFL, ec); + if (s >= 0) + s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec); + if (s < 0) + { + boost::system::error_code ignored_ec; + descriptor_ops::close(fd, ignored_ec); + return ec; + } + + // Set up default serial port options. + termios ios; + descriptor_ops::clear_error(ec); + s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec); + if (s >= 0) + { +#if defined(_BSD_SOURCE) + ::cfmakeraw(&ios); +#else + ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK + | ISTRIP | INLCR | IGNCR | ICRNL | IXON); + ios.c_oflag &= ~OPOST; + ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + ios.c_cflag &= ~(CSIZE | PARENB); + ios.c_cflag |= CS8; +#endif + ios.c_iflag |= IGNPAR; + ios.c_cflag |= CREAD | CLOCAL; + descriptor_ops::clear_error(ec); + s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec); + } + if (s < 0) + { + boost::system::error_code ignored_ec; + descriptor_ops::close(fd, ignored_ec); + return ec; + } + + // We're done. Take ownership of the serial port descriptor. + if (descriptor_service_.assign(impl, fd, ec)) + { + boost::system::error_code ignored_ec; + descriptor_ops::close(fd, ignored_ec); + } + + return ec; + } + + // Assign a native handle to a handle implementation. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_descriptor, boost::system::error_code& ec) + { + return descriptor_service_.assign(impl, native_descriptor, ec); + } + + // Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return descriptor_service_.is_open(impl); + } + + // Destroy a handle implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return descriptor_service_.close(impl, ec); + } + + // Get the native handle representation. + native_type native(implementation_type& impl) + { + return descriptor_service_.native(impl); + } + + // Cancel all operations associated with the handle. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return descriptor_service_.cancel(impl, ec); + } + + // Set an option on the serial port. + template + boost::system::error_code set_option(implementation_type& impl, + const SettableSerialPortOption& option, boost::system::error_code& ec) + { + termios ios; + descriptor_ops::clear_error(ec); + descriptor_ops::error_wrapper(::tcgetattr( + descriptor_service_.native(impl), &ios), ec); + if (ec) + return ec; + + if (option.store(ios, ec)) + return ec; + + descriptor_ops::clear_error(ec); + descriptor_ops::error_wrapper(::tcsetattr( + descriptor_service_.native(impl), TCSANOW, &ios), ec); + return ec; + } + + // Get an option from the serial port. + template + boost::system::error_code get_option(const implementation_type& impl, + GettableSerialPortOption& option, boost::system::error_code& ec) const + { + termios ios; + descriptor_ops::clear_error(ec); + descriptor_ops::error_wrapper(::tcgetattr( + descriptor_service_.native(impl), &ios), ec); + if (ec) + return ec; + + return option.load(ios, ec); + } + + // Send a break sequence to the serial port. + boost::system::error_code send_break(implementation_type& impl, + boost::system::error_code& ec) + { + descriptor_ops::clear_error(ec); + descriptor_ops::error_wrapper(::tcsendbreak( + descriptor_service_.native(impl), 0), ec); + return ec; + } + + // Write the given data. Returns the number of bytes sent. + template + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return descriptor_service_.write_some(impl, buffers, ec); + } + + // Start an asynchronous write. The data being written must be valid for the + // lifetime of the asynchronous operation. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, Handler handler) + { + descriptor_service_.async_write_some(impl, buffers, handler); + } + + // Read some data. Returns the number of bytes received. + template + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return descriptor_service_.read_some(impl, buffers, ec); + } + + // Start an asynchronous read. The buffer for the data being received must be + // valid for the lifetime of the asynchronous operation. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, Handler handler) + { + descriptor_service_.async_read_some(impl, buffers, handler); + } + +private: + // The handle service used for initiating asynchronous operations. + reactive_descriptor_service& descriptor_service_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include + +#endif // BOOST_ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP diff --git a/win32/include/boost/asio/detail/reactive_socket_service.hpp b/win32/include/boost/asio/detail/reactive_socket_service.hpp new file mode 100755 index 000000000..41133c05c --- /dev/null +++ b/win32/include/boost/asio/detail/reactive_socket_service.hpp @@ -0,0 +1,1782 @@ +// +// reactive_socket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP +#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class reactive_socket_service + : public boost::asio::detail::service_base< + reactive_socket_service > +{ +public: + // The protocol type. + typedef Protocol protocol_type; + + // The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + // The native type of a socket. + typedef socket_type native_type; + + // The implementation type of the socket. + class implementation_type + : private boost::asio::detail::noncopyable + { + public: + // Default constructor. + implementation_type() + : socket_(invalid_socket), + flags_(0), + protocol_(endpoint_type().protocol()) + { + } + + private: + // Only this service will have access to the internal values. + friend class reactive_socket_service; + + // The native socket representation. + socket_type socket_; + + enum + { + user_set_non_blocking = 1, // The user wants a non-blocking socket. + internal_non_blocking = 2, // The socket has been set non-blocking. + enable_connection_aborted = 4, // User wants connection_aborted errors. + user_set_linger = 8 // The user set the linger option. + }; + + // Flags indicating the current state of the socket. + unsigned char flags_; + + // The protocol associated with the socket. + protocol_type protocol_; + + // Per-descriptor data used by the reactor. + typename Reactor::per_descriptor_data reactor_data_; + }; + + // The maximum number of buffers to support in a single operation. + enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; + + // Constructor. + reactive_socket_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + reactive_socket_service >(io_service), + reactor_(boost::asio::use_service(io_service)) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Construct a new socket implementation. + void construct(implementation_type& impl) + { + impl.socket_ = invalid_socket; + impl.flags_ = 0; + } + + // Destroy a socket implementation. + void destroy(implementation_type& impl) + { + if (impl.socket_ != invalid_socket) + { + reactor_.close_descriptor(impl.socket_, impl.reactor_data_); + + if (impl.flags_ & implementation_type::internal_non_blocking) + { + ioctl_arg_type non_blocking = 0; + boost::system::error_code ignored_ec; + socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec); + impl.flags_ &= ~implementation_type::internal_non_blocking; + } + + if (impl.flags_ & implementation_type::user_set_linger) + { + ::linger opt; + opt.l_onoff = 0; + opt.l_linger = 0; + boost::system::error_code ignored_ec; + socket_ops::setsockopt(impl.socket_, + SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec); + } + + boost::system::error_code ignored_ec; + socket_ops::close(impl.socket_, ignored_ec); + + impl.socket_ = invalid_socket; + } + } + + // Open a new socket implementation. + boost::system::error_code open(implementation_type& impl, + const protocol_type& protocol, boost::system::error_code& ec) + { + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + socket_holder sock(socket_ops::socket(protocol.family(), + protocol.type(), protocol.protocol(), ec)); + if (sock.get() == invalid_socket) + return ec; + + if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_)) + { + ec = boost::system::error_code(err, + boost::asio::error::get_system_category()); + return ec; + } + + impl.socket_ = sock.release(); + impl.flags_ = 0; + impl.protocol_ = protocol; + ec = boost::system::error_code(); + return ec; + } + + // Assign a native socket to a socket implementation. + boost::system::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_type& native_socket, + boost::system::error_code& ec) + { + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + if (int err = reactor_.register_descriptor( + native_socket, impl.reactor_data_)) + { + ec = boost::system::error_code(err, + boost::asio::error::get_system_category()); + return ec; + } + + impl.socket_ = native_socket; + impl.flags_ = 0; + impl.protocol_ = protocol; + ec = boost::system::error_code(); + return ec; + } + + // Determine whether the socket is open. + bool is_open(const implementation_type& impl) const + { + return impl.socket_ != invalid_socket; + } + + // Destroy a socket implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + if (is_open(impl)) + { + reactor_.close_descriptor(impl.socket_, impl.reactor_data_); + + if (impl.flags_ & implementation_type::internal_non_blocking) + { + ioctl_arg_type non_blocking = 0; + boost::system::error_code ignored_ec; + socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec); + impl.flags_ &= ~implementation_type::internal_non_blocking; + } + + if (socket_ops::close(impl.socket_, ec) == socket_error_retval) + return ec; + + impl.socket_ = invalid_socket; + } + + ec = boost::system::error_code(); + return ec; + } + + // Get the native socket representation. + native_type native(implementation_type& impl) + { + return impl.socket_; + } + + // Cancel all operations associated with the socket. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + reactor_.cancel_ops(impl.socket_, impl.reactor_data_); + ec = boost::system::error_code(); + return ec; + } + + // Determine whether the socket is at the out-of-band data mark. + bool at_mark(const implementation_type& impl, + boost::system::error_code& ec) const + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return false; + } + + boost::asio::detail::ioctl_arg_type value = 0; + socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec); +#if defined(ENOTTY) + if (ec.value() == ENOTTY) + ec = boost::asio::error::not_socket; +#endif // defined(ENOTTY) + return ec ? false : value != 0; + } + + // Determine the number of bytes available for reading. + std::size_t available(const implementation_type& impl, + boost::system::error_code& ec) const + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + boost::asio::detail::ioctl_arg_type value = 0; + socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec); +#if defined(ENOTTY) + if (ec.value() == ENOTTY) + ec = boost::asio::error::not_socket; +#endif // defined(ENOTTY) + return ec ? static_cast(0) : static_cast(value); + } + + // Bind the socket to the specified local endpoint. + boost::system::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); + return ec; + } + + // Place the socket into the state where it will listen for new connections. + boost::system::error_code listen(implementation_type& impl, int backlog, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + socket_ops::listen(impl.socket_, backlog, ec); + return ec; + } + + // Set a socket option. + template + boost::system::error_code set_option(implementation_type& impl, + const Option& option, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + if (option.level(impl.protocol_) == custom_socket_option_level + && option.name(impl.protocol_) == enable_connection_aborted_option) + { + if (option.size(impl.protocol_) != sizeof(int)) + { + ec = boost::asio::error::invalid_argument; + } + else + { + if (*reinterpret_cast(option.data(impl.protocol_))) + impl.flags_ |= implementation_type::enable_connection_aborted; + else + impl.flags_ &= ~implementation_type::enable_connection_aborted; + ec = boost::system::error_code(); + } + return ec; + } + else + { + if (option.level(impl.protocol_) == SOL_SOCKET + && option.name(impl.protocol_) == SO_LINGER) + { + impl.flags_ |= implementation_type::user_set_linger; + } + + socket_ops::setsockopt(impl.socket_, + option.level(impl.protocol_), option.name(impl.protocol_), + option.data(impl.protocol_), option.size(impl.protocol_), ec); + +#if defined(__MACH__) && defined(__APPLE__) \ +|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) + // To implement portable behaviour for SO_REUSEADDR with UDP sockets we + // need to also set SO_REUSEPORT on BSD-based platforms. + if (!ec && impl.protocol_.type() == SOCK_DGRAM + && option.level(impl.protocol_) == SOL_SOCKET + && option.name(impl.protocol_) == SO_REUSEADDR) + { + boost::system::error_code ignored_ec; + socket_ops::setsockopt(impl.socket_, SOL_SOCKET, SO_REUSEPORT, + option.data(impl.protocol_), option.size(impl.protocol_), + ignored_ec); + } +#endif + + return ec; + } + } + + // Set a socket option. + template + boost::system::error_code get_option(const implementation_type& impl, + Option& option, boost::system::error_code& ec) const + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + if (option.level(impl.protocol_) == custom_socket_option_level + && option.name(impl.protocol_) == enable_connection_aborted_option) + { + if (option.size(impl.protocol_) != sizeof(int)) + { + ec = boost::asio::error::invalid_argument; + } + else + { + int* target = reinterpret_cast(option.data(impl.protocol_)); + if (impl.flags_ & implementation_type::enable_connection_aborted) + *target = 1; + else + *target = 0; + option.resize(impl.protocol_, sizeof(int)); + ec = boost::system::error_code(); + } + return ec; + } + else + { + size_t size = option.size(impl.protocol_); + socket_ops::getsockopt(impl.socket_, + option.level(impl.protocol_), option.name(impl.protocol_), + option.data(impl.protocol_), &size, ec); + if (!ec) + option.resize(impl.protocol_, size); + return ec; + } + } + + // Perform an IO control command on the socket. + template + boost::system::error_code io_control(implementation_type& impl, + IO_Control_Command& command, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + if (command.name() == static_cast(FIONBIO)) + { + if (command.get()) + impl.flags_ |= implementation_type::user_set_non_blocking; + else + impl.flags_ &= ~implementation_type::user_set_non_blocking; + ec = boost::system::error_code(); + } + else + { + socket_ops::ioctl(impl.socket_, command.name(), + static_cast(command.data()), ec); + } + return ec; + } + + // Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return endpoint_type(); + } + + endpoint_type endpoint; + std::size_t addr_len = endpoint.capacity(); + if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) + return endpoint_type(); + endpoint.resize(addr_len); + return endpoint; + } + + // Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return endpoint_type(); + } + + endpoint_type endpoint; + std::size_t addr_len = endpoint.capacity(); + if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec)) + return endpoint_type(); + endpoint.resize(addr_len); + return endpoint; + } + + /// Disable sends or receives on the socket. + boost::system::error_code shutdown(implementation_type& impl, + socket_base::shutdown_type what, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + socket_ops::shutdown(impl.socket_, what, ec); + return ec; + } + + // Send the given data to the peer. + template + size_t send(implementation_type& impl, const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Copy buffers into array. + socket_ops::buf bufs[max_buffers]; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + socket_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to receive 0 bytes on a stream socket is a no-op. + if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) + { + ec = boost::system::error_code(); + return 0; + } + + // Make socket non-blocking if user wants non-blocking. + if (impl.flags_ & implementation_type::user_set_non_blocking) + { + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) + return 0; + impl.flags_ |= implementation_type::internal_non_blocking; + } + } + + // Send the data. + for (;;) + { + // Try to complete the operation without blocking. + int bytes_sent = socket_ops::send(impl.socket_, bufs, i, flags, ec); + + // Check if operation succeeded. + if (bytes_sent >= 0) + return bytes_sent; + + // Operation failed. + if ((impl.flags_ & implementation_type::user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_write(impl.socket_, ec) < 0) + return 0; + } + } + + // Wait until data can be sent without blocking. + size_t send(implementation_type& impl, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, ec); + + return 0; + } + + template + class send_operation : + public handler_base_from_member + { + public: + send_operation(socket_type socket, boost::asio::io_service& io_service, + const ConstBufferSequence& buffers, socket_base::message_flags flags, + Handler handler) + : handler_base_from_member(handler), + socket_(socket), + io_service_(io_service), + work_(io_service), + buffers_(buffers), + flags_(flags) + { + } + + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) + { + // Check whether the operation was successful. + if (ec) + { + bytes_transferred = 0; + return true; + } + + // Copy buffers into array. + socket_ops::buf bufs[max_buffers]; + typename ConstBufferSequence::const_iterator iter = buffers_.begin(); + typename ConstBufferSequence::const_iterator end = buffers_.end(); + size_t i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + socket_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + } + + // Send the data. + int bytes = socket_ops::send(socket_, bufs, i, flags_, ec); + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + bytes_transferred = (bytes < 0 ? 0 : bytes); + return true; + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + + private: + socket_type socket_; + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + ConstBufferSequence buffers_; + socket_base::message_flags flags_; + }; + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template + void async_send(implementation_type& impl, const ConstBufferSequence& buffers, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + if (impl.protocol_.type() == SOCK_STREAM) + { + // Determine total size of buffers. + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to receive 0 bytes on a stream socket is a no-op. + if (total_buffer_size == 0) + { + this->get_io_service().post(bind_handler(handler, + boost::system::error_code(), 0)); + return; + } + } + + // Make socket non-blocking. + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + boost::system::error_code ec; + if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) + { + this->get_io_service().post(bind_handler(handler, ec, 0)); + return; + } + impl.flags_ |= implementation_type::internal_non_blocking; + } + + reactor_.start_write_op(impl.socket_, impl.reactor_data_, + send_operation( + impl.socket_, this->get_io_service(), buffers, flags, handler)); + } + } + + template + class null_buffers_operation : + public handler_base_from_member + { + public: + null_buffers_operation(boost::asio::io_service& io_service, Handler handler) + : handler_base_from_member(handler), + work_(io_service) + { + } + + bool perform(boost::system::error_code&, + std::size_t& bytes_transferred) + { + bytes_transferred = 0; + return true; + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + work_.get_io_service().post(bind_handler( + this->handler_, ec, bytes_transferred)); + } + + private: + boost::asio::io_service::work work_; + }; + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send(implementation_type& impl, const null_buffers&, + socket_base::message_flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + reactor_.start_write_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + + // Send a datagram to the specified endpoint. Returns the number of bytes + // sent. + template + size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Copy buffers into array. + socket_ops::buf bufs[max_buffers]; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + socket_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + } + + // Make socket non-blocking if user wants non-blocking. + if (impl.flags_ & implementation_type::user_set_non_blocking) + { + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) + return 0; + impl.flags_ |= implementation_type::internal_non_blocking; + } + } + + // Send the data. + for (;;) + { + // Try to complete the operation without blocking. + int bytes_sent = socket_ops::sendto(impl.socket_, bufs, i, flags, + destination.data(), destination.size(), ec); + + // Check if operation succeeded. + if (bytes_sent >= 0) + return bytes_sent; + + // Operation failed. + if ((impl.flags_ & implementation_type::user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_write(impl.socket_, ec) < 0) + return 0; + } + } + + // Wait until data can be sent without blocking. + size_t send_to(implementation_type& impl, const null_buffers&, + socket_base::message_flags, const endpoint_type&, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, ec); + + return 0; + } + + template + class send_to_operation : + public handler_base_from_member + { + public: + send_to_operation(socket_type socket, boost::asio::io_service& io_service, + const ConstBufferSequence& buffers, const endpoint_type& endpoint, + socket_base::message_flags flags, Handler handler) + : handler_base_from_member(handler), + socket_(socket), + io_service_(io_service), + work_(io_service), + buffers_(buffers), + destination_(endpoint), + flags_(flags) + { + } + + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) + { + // Check whether the operation was successful. + if (ec) + { + bytes_transferred = 0; + return true; + } + + // Copy buffers into array. + socket_ops::buf bufs[max_buffers]; + typename ConstBufferSequence::const_iterator iter = buffers_.begin(); + typename ConstBufferSequence::const_iterator end = buffers_.end(); + size_t i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + socket_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + } + + // Send the data. + int bytes = socket_ops::sendto(socket_, bufs, i, flags_, + destination_.data(), destination_.size(), ec); + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + bytes_transferred = (bytes < 0 ? 0 : bytes); + return true; + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + + private: + socket_type socket_; + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + ConstBufferSequence buffers_; + endpoint_type destination_; + socket_base::message_flags flags_; + }; + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template + void async_send_to(implementation_type& impl, + const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + // Make socket non-blocking. + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + boost::system::error_code ec; + if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) + { + this->get_io_service().post(bind_handler(handler, ec, 0)); + return; + } + impl.flags_ |= implementation_type::internal_non_blocking; + } + + reactor_.start_write_op(impl.socket_, impl.reactor_data_, + send_to_operation( + impl.socket_, this->get_io_service(), buffers, + destination, flags, handler)); + } + } + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send_to(implementation_type& impl, const null_buffers&, + socket_base::message_flags, const endpoint_type&, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + reactor_.start_write_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + + // Receive some data from the peer. Returns the number of bytes received. + template + size_t receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Copy buffers into array. + socket_ops::buf bufs[max_buffers]; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + socket_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to receive 0 bytes on a stream socket is a no-op. + if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) + { + ec = boost::system::error_code(); + return 0; + } + + // Make socket non-blocking if user wants non-blocking. + if (impl.flags_ & implementation_type::user_set_non_blocking) + { + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) + return 0; + impl.flags_ |= implementation_type::internal_non_blocking; + } + } + + // Receive some data. + for (;;) + { + // Try to complete the operation without blocking. + int bytes_recvd = socket_ops::recv(impl.socket_, bufs, i, flags, ec); + + // Check if operation succeeded. + if (bytes_recvd > 0) + return bytes_recvd; + + // Check for EOF. + if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM) + { + ec = boost::asio::error::eof; + return 0; + } + + // Operation failed. + if ((impl.flags_ & implementation_type::user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_read(impl.socket_, ec) < 0) + return 0; + } + } + + // Wait until data can be received without blocking. + size_t receive(implementation_type& impl, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, ec); + + return 0; + } + + template + class receive_operation : + public handler_base_from_member + { + public: + receive_operation(socket_type socket, int protocol_type, + boost::asio::io_service& io_service, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, Handler handler) + : handler_base_from_member(handler), + socket_(socket), + protocol_type_(protocol_type), + io_service_(io_service), + work_(io_service), + buffers_(buffers), + flags_(flags) + { + } + + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) + { + // Check whether the operation was successful. + if (ec) + { + bytes_transferred = 0; + return true; + } + + // Copy buffers into array. + socket_ops::buf bufs[max_buffers]; + typename MutableBufferSequence::const_iterator iter = buffers_.begin(); + typename MutableBufferSequence::const_iterator end = buffers_.end(); + size_t i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + socket_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + } + + // Receive some data. + int bytes = socket_ops::recv(socket_, bufs, i, flags_, ec); + if (bytes == 0 && protocol_type_ == SOCK_STREAM) + ec = boost::asio::error::eof; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + bytes_transferred = (bytes < 0 ? 0 : bytes); + return true; + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + + private: + socket_type socket_; + int protocol_type_; + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + MutableBufferSequence buffers_; + socket_base::message_flags flags_; + }; + + // Start an asynchronous receive. The buffer for the data being received + // must be valid for the lifetime of the asynchronous operation. + template + void async_receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + if (impl.protocol_.type() == SOCK_STREAM) + { + // Determine total size of buffers. + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to receive 0 bytes on a stream socket is a no-op. + if (total_buffer_size == 0) + { + this->get_io_service().post(bind_handler(handler, + boost::system::error_code(), 0)); + return; + } + } + + // Make socket non-blocking. + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + boost::system::error_code ec; + if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) + { + this->get_io_service().post(bind_handler(handler, ec, 0)); + return; + } + impl.flags_ |= implementation_type::internal_non_blocking; + } + + if (flags & socket_base::message_out_of_band) + { + reactor_.start_except_op(impl.socket_, impl.reactor_data_, + receive_operation( + impl.socket_, impl.protocol_.type(), + this->get_io_service(), buffers, flags, handler)); + } + else + { + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + receive_operation( + impl.socket_, impl.protocol_.type(), + this->get_io_service(), buffers, flags, handler)); + } + } + } + + // Wait until data can be received without blocking. + template + void async_receive(implementation_type& impl, const null_buffers&, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else if (flags & socket_base::message_out_of_band) + { + reactor_.start_except_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler)); + } + else + { + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + + // Receive a datagram with the endpoint of the sender. Returns the number of + // bytes received. + template + size_t receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Copy buffers into array. + socket_ops::buf bufs[max_buffers]; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + size_t i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + socket_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + } + + // Make socket non-blocking if user wants non-blocking. + if (impl.flags_ & implementation_type::user_set_non_blocking) + { + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) + return 0; + impl.flags_ |= implementation_type::internal_non_blocking; + } + } + + // Receive some data. + for (;;) + { + // Try to complete the operation without blocking. + std::size_t addr_len = sender_endpoint.capacity(); + int bytes_recvd = socket_ops::recvfrom(impl.socket_, bufs, i, flags, + sender_endpoint.data(), &addr_len, ec); + + // Check if operation succeeded. + if (bytes_recvd > 0) + { + sender_endpoint.resize(addr_len); + return bytes_recvd; + } + + // Check for EOF. + if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM) + { + ec = boost::asio::error::eof; + return 0; + } + + // Operation failed. + if ((impl.flags_ & implementation_type::user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_read(impl.socket_, ec) < 0) + return 0; + } + } + + // Wait until data can be received without blocking. + size_t receive_from(implementation_type& impl, const null_buffers&, + endpoint_type& sender_endpoint, socket_base::message_flags, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, ec); + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + return 0; + } + + template + class receive_from_operation : + public handler_base_from_member + { + public: + receive_from_operation(socket_type socket, int protocol_type, + boost::asio::io_service& io_service, + const MutableBufferSequence& buffers, endpoint_type& endpoint, + socket_base::message_flags flags, Handler handler) + : handler_base_from_member(handler), + socket_(socket), + protocol_type_(protocol_type), + io_service_(io_service), + work_(io_service), + buffers_(buffers), + sender_endpoint_(endpoint), + flags_(flags) + { + } + + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) + { + // Check whether the operation was successful. + if (ec) + { + bytes_transferred = 0; + return true; + } + + // Copy buffers into array. + socket_ops::buf bufs[max_buffers]; + typename MutableBufferSequence::const_iterator iter = buffers_.begin(); + typename MutableBufferSequence::const_iterator end = buffers_.end(); + size_t i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + socket_ops::init_buf(bufs[i], + boost::asio::buffer_cast(buffer), + boost::asio::buffer_size(buffer)); + } + + // Receive some data. + std::size_t addr_len = sender_endpoint_.capacity(); + int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_, + sender_endpoint_.data(), &addr_len, ec); + if (bytes == 0 && protocol_type_ == SOCK_STREAM) + ec = boost::asio::error::eof; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + sender_endpoint_.resize(addr_len); + bytes_transferred = (bytes < 0 ? 0 : bytes); + return true; + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + io_service_.post(bind_handler(this->handler_, ec, bytes_transferred)); + } + + private: + socket_type socket_; + int protocol_type_; + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + MutableBufferSequence buffers_; + endpoint_type& sender_endpoint_; + socket_base::message_flags flags_; + }; + + // Start an asynchronous receive. The buffer for the data being received and + // the sender_endpoint object must both be valid for the lifetime of the + // asynchronous operation. + template + void async_receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + // Make socket non-blocking. + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + boost::system::error_code ec; + if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) + { + this->get_io_service().post(bind_handler(handler, ec, 0)); + return; + } + impl.flags_ |= implementation_type::internal_non_blocking; + } + + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + receive_from_operation( + impl.socket_, impl.protocol_.type(), this->get_io_service(), + buffers, sender_endpoint, flags, handler)); + } + } + + // Wait until data can be received without blocking. + template + void async_receive_from(implementation_type& impl, + const null_buffers&, endpoint_type& sender_endpoint, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + if (flags & socket_base::message_out_of_band) + { + reactor_.start_except_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler)); + } + else + { + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + } + + // Accept a new connection. + template + boost::system::error_code accept(implementation_type& impl, + Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + // We cannot accept a socket that is already open. + if (peer.is_open()) + { + ec = boost::asio::error::already_open; + return ec; + } + + // Make socket non-blocking if user wants non-blocking. + if (impl.flags_ & implementation_type::user_set_non_blocking) + { + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) + return ec; + impl.flags_ |= implementation_type::internal_non_blocking; + } + } + + // Accept a socket. + for (;;) + { + // Try to complete the operation without blocking. + boost::system::error_code ec; + socket_holder new_socket; + std::size_t addr_len = 0; + if (peer_endpoint) + { + addr_len = peer_endpoint->capacity(); + new_socket.reset(socket_ops::accept(impl.socket_, + peer_endpoint->data(), &addr_len, ec)); + } + else + { + new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec)); + } + + // Check if operation succeeded. + if (new_socket.get() >= 0) + { + if (peer_endpoint) + peer_endpoint->resize(addr_len); + peer.assign(impl.protocol_, new_socket.get(), ec); + if (!ec) + new_socket.release(); + return ec; + } + + // Operation failed. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + { + if (impl.flags_ & implementation_type::user_set_non_blocking) + return ec; + // Fall through to retry operation. + } + else if (ec == boost::asio::error::connection_aborted) + { + if (impl.flags_ & implementation_type::enable_connection_aborted) + return ec; + // Fall through to retry operation. + } +#if defined(EPROTO) + else if (ec.value() == EPROTO) + { + if (impl.flags_ & implementation_type::enable_connection_aborted) + return ec; + // Fall through to retry operation. + } +#endif // defined(EPROTO) + else + return ec; + + // Wait for socket to become ready. + if (socket_ops::poll_read(impl.socket_, ec) < 0) + return ec; + } + } + + template + class accept_operation : + public handler_base_from_member + { + public: + accept_operation(socket_type socket, boost::asio::io_service& io_service, + Socket& peer, const protocol_type& protocol, + endpoint_type* peer_endpoint, bool enable_connection_aborted, + Handler handler) + : handler_base_from_member(handler), + socket_(socket), + io_service_(io_service), + work_(io_service), + peer_(peer), + protocol_(protocol), + peer_endpoint_(peer_endpoint), + enable_connection_aborted_(enable_connection_aborted) + { + } + + bool perform(boost::system::error_code& ec, std::size_t&) + { + // Check whether the operation was successful. + if (ec) + return true; + + // Accept the waiting connection. + socket_holder new_socket; + std::size_t addr_len = 0; + if (peer_endpoint_) + { + addr_len = peer_endpoint_->capacity(); + new_socket.reset(socket_ops::accept(socket_, + peer_endpoint_->data(), &addr_len, ec)); + } + else + { + new_socket.reset(socket_ops::accept(socket_, 0, 0, ec)); + } + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + if (ec == boost::asio::error::connection_aborted + && !enable_connection_aborted_) + return false; +#if defined(EPROTO) + if (ec.value() == EPROTO && !enable_connection_aborted_) + return false; +#endif // defined(EPROTO) + + // Transfer ownership of the new socket to the peer object. + if (!ec) + { + if (peer_endpoint_) + peer_endpoint_->resize(addr_len); + peer_.assign(protocol_, new_socket.get(), ec); + if (!ec) + new_socket.release(); + } + + return true; + } + + void complete(const boost::system::error_code& ec, std::size_t) + { + io_service_.post(bind_handler(this->handler_, ec)); + } + + private: + socket_type socket_; + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + Socket& peer_; + protocol_type protocol_; + endpoint_type* peer_endpoint_; + bool enable_connection_aborted_; + }; + + // Start an asynchronous accept. The peer and peer_endpoint objects + // must be valid until the accept's handler is invoked. + template + void async_accept(implementation_type& impl, Socket& peer, + endpoint_type* peer_endpoint, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor)); + } + else if (peer.is_open()) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::already_open)); + } + else + { + // Make socket non-blocking. + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + boost::system::error_code ec; + if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) + { + this->get_io_service().post(bind_handler(handler, ec)); + return; + } + impl.flags_ |= implementation_type::internal_non_blocking; + } + + reactor_.start_read_op(impl.socket_, impl.reactor_data_, + accept_operation( + impl.socket_, this->get_io_service(), + peer, impl.protocol_, peer_endpoint, + (impl.flags_ & implementation_type::enable_connection_aborted) != 0, + handler)); + } + } + + // Connect the socket to the specified endpoint. + boost::system::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + if (impl.flags_ & implementation_type::internal_non_blocking) + { + // Mark the socket as blocking while we perform the connect. + ioctl_arg_type non_blocking = 0; + if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) + return ec; + impl.flags_ &= ~implementation_type::internal_non_blocking; + } + + // Perform the connect operation. + socket_ops::connect(impl.socket_, + peer_endpoint.data(), peer_endpoint.size(), ec); + return ec; + } + + template + class connect_operation : + public handler_base_from_member + { + public: + connect_operation(socket_type socket, + boost::asio::io_service& io_service, Handler handler) + : handler_base_from_member(handler), + socket_(socket), + io_service_(io_service), + work_(io_service) + { + } + + bool perform(boost::system::error_code& ec, std::size_t&) + { + // Check whether the operation was successful. + if (ec) + return true; + + // Get the error code from the connect operation. + int connect_error = 0; + size_t connect_error_len = sizeof(connect_error); + if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR, + &connect_error, &connect_error_len, ec) == socket_error_retval) + return true; + + // The connection failed so the handler will be posted with an error code. + if (connect_error) + { + ec = boost::system::error_code(connect_error, + boost::asio::error::get_system_category()); + return true; + } + + return true; + } + + void complete(const boost::system::error_code& ec, std::size_t) + { + io_service_.post(bind_handler(this->handler_, ec)); + } + + private: + socket_type socket_; + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + }; + + // Start an asynchronous connect. + template + void async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor)); + return; + } + + // Make socket non-blocking. + if (!(impl.flags_ & implementation_type::internal_non_blocking)) + { + ioctl_arg_type non_blocking = 1; + boost::system::error_code ec; + if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) + { + this->get_io_service().post(bind_handler(handler, ec)); + return; + } + impl.flags_ |= implementation_type::internal_non_blocking; + } + + // Start the connect operation. The socket is already marked as non-blocking + // so the connection will take place asynchronously. + boost::system::error_code ec; + if (socket_ops::connect(impl.socket_, peer_endpoint.data(), + peer_endpoint.size(), ec) == 0) + { + // The connect operation has finished successfully so we need to post the + // handler immediately. + this->get_io_service().post(bind_handler(handler, + boost::system::error_code())); + } + else if (ec == boost::asio::error::in_progress + || ec == boost::asio::error::would_block) + { + // The connection is happening in the background, and we need to wait + // until the socket becomes writeable. + reactor_.start_connect_op(impl.socket_, impl.reactor_data_, + connect_operation(impl.socket_, + this->get_io_service(), handler)); + } + else + { + // The connect operation has failed, so post the handler immediately. + this->get_io_service().post(bind_handler(handler, ec)); + } + } + +private: + // The selector that performs event demultiplexing for the service. + Reactor& reactor_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP diff --git a/win32/include/boost/asio/detail/reactor_op_queue.hpp b/win32/include/boost/asio/detail/reactor_op_queue.hpp new file mode 100755 index 000000000..9c970c5dd --- /dev/null +++ b/win32/include/boost/asio/detail/reactor_op_queue.hpp @@ -0,0 +1,456 @@ +// +// reactor_op_queue.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP +#define BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class reactor_op_queue + : private noncopyable +{ +public: + // Constructor. + reactor_op_queue() + : operations_(), + cancelled_operations_(0), + complete_operations_(0) + { + } + + // Add a new operation to the queue. Returns true if this is the only + // operation for the given descriptor, in which case the reactor's event + // demultiplexing function call may need to be interrupted and restarted. + template + bool enqueue_operation(Descriptor descriptor, Operation operation) + { + // Allocate and construct an object to wrap the handler. + typedef handler_alloc_traits > alloc_traits; + raw_handler_ptr raw_ptr(operation); + handler_ptr ptr(raw_ptr, descriptor, operation); + + typedef typename operation_map::iterator iterator; + typedef typename operation_map::value_type value_type; + std::pair entry = + operations_.insert(value_type(descriptor, ptr.get())); + if (entry.second) + { + ptr.release(); + return true; + } + + op_base* current_op = entry.first->second; + while (current_op->next_) + current_op = current_op->next_; + current_op->next_ = ptr.release(); + + return false; + } + + // Cancel all operations associated with the descriptor. Any operations + // pending for the descriptor will be notified that they have been cancelled + // next time perform_cancellations is called. Returns true if any operations + // were cancelled, in which case the reactor's event demultiplexing function + // may need to be interrupted and restarted. + bool cancel_operations(Descriptor descriptor) + { + typename operation_map::iterator i = operations_.find(descriptor); + if (i != operations_.end()) + { + op_base* last_op = i->second; + while (last_op->next_) + last_op = last_op->next_; + last_op->next_ = cancelled_operations_; + cancelled_operations_ = i->second; + operations_.erase(i); + return true; + } + + return false; + } + + // Whether there are no operations in the queue. + bool empty() const + { + return operations_.empty(); + } + + // Determine whether there are any operations associated with the descriptor. + bool has_operation(Descriptor descriptor) const + { + return operations_.find(descriptor) != operations_.end(); + } + + // Perform the first operation corresponding to the descriptor. Returns true + // if there are more operations queued for the descriptor. + bool perform_operation(Descriptor descriptor, + const boost::system::error_code& result) + { + typename operation_map::iterator i = operations_.find(descriptor); + if (i != operations_.end()) + { + op_base* this_op = i->second; + i->second = this_op->next_; + this_op->next_ = complete_operations_; + complete_operations_ = this_op; + bool done = this_op->perform(result); + if (done) + { + // Operation has finished. + if (i->second) + { + return true; + } + else + { + operations_.erase(i); + return false; + } + } + else + { + // Operation wants to be called again. Leave it at the front of the + // queue for this descriptor, and remove from the completed list. + complete_operations_ = this_op->next_; + this_op->next_ = i->second; + i->second = this_op; + return true; + } + } + return false; + } + + // Perform all operations corresponding to the descriptor. + void perform_all_operations(Descriptor descriptor, + const boost::system::error_code& result) + { + typename operation_map::iterator i = operations_.find(descriptor); + if (i != operations_.end()) + { + while (i->second) + { + op_base* this_op = i->second; + i->second = this_op->next_; + this_op->next_ = complete_operations_; + complete_operations_ = this_op; + bool done = this_op->perform(result); + if (!done) + { + // Operation has not finished yet, so leave at front of queue, and + // remove from the completed list. + complete_operations_ = this_op->next_; + this_op->next_ = i->second; + i->second = this_op; + return; + } + } + operations_.erase(i); + } + } + + // Fill a descriptor set with the descriptors corresponding to each active + // operation. + template + void get_descriptors(Descriptor_Set& descriptors) + { + typename operation_map::iterator i = operations_.begin(); + while (i != operations_.end()) + { + Descriptor descriptor = i->first; + ++i; + if (!descriptors.set(descriptor)) + { + boost::system::error_code ec(error::fd_set_failure); + perform_all_operations(descriptor, ec); + } + } + } + + // Perform the operations corresponding to the ready file descriptors + // contained in the given descriptor set. + template + void perform_operations_for_descriptors(const Descriptor_Set& descriptors, + const boost::system::error_code& result) + { + typename operation_map::iterator i = operations_.begin(); + while (i != operations_.end()) + { + typename operation_map::iterator op_iter = i++; + if (descriptors.is_set(op_iter->first)) + { + op_base* this_op = op_iter->second; + op_iter->second = this_op->next_; + this_op->next_ = complete_operations_; + complete_operations_ = this_op; + bool done = this_op->perform(result); + if (done) + { + if (!op_iter->second) + operations_.erase(op_iter); + } + else + { + // Operation has not finished yet, so leave at front of queue, and + // remove from the completed list. + complete_operations_ = this_op->next_; + this_op->next_ = op_iter->second; + op_iter->second = this_op; + } + } + } + } + + // Perform any pending cancels for operations. + void perform_cancellations() + { + while (cancelled_operations_) + { + op_base* this_op = cancelled_operations_; + cancelled_operations_ = this_op->next_; + this_op->next_ = complete_operations_; + complete_operations_ = this_op; + this_op->perform(boost::asio::error::operation_aborted); + } + } + + // Complete all operations that are waiting to be completed. + void complete_operations() + { + while (complete_operations_) + { + op_base* next_op = complete_operations_->next_; + complete_operations_->next_ = 0; + complete_operations_->complete(); + complete_operations_ = next_op; + } + } + + // Destroy all operations owned by the queue. + void destroy_operations() + { + while (cancelled_operations_) + { + op_base* next_op = cancelled_operations_->next_; + cancelled_operations_->next_ = 0; + cancelled_operations_->destroy(); + cancelled_operations_ = next_op; + } + + while (complete_operations_) + { + op_base* next_op = complete_operations_->next_; + complete_operations_->next_ = 0; + complete_operations_->destroy(); + complete_operations_ = next_op; + } + + typename operation_map::iterator i = operations_.begin(); + while (i != operations_.end()) + { + typename operation_map::iterator op_iter = i++; + op_base* curr_op = op_iter->second; + operations_.erase(op_iter); + while (curr_op) + { + op_base* next_op = curr_op->next_; + curr_op->next_ = 0; + curr_op->destroy(); + curr_op = next_op; + } + } + } + +private: + // Base class for reactor operations. A function pointer is used instead of + // virtual functions to avoid the associated overhead. + class op_base + { + public: + // Get the descriptor associated with the operation. + Descriptor descriptor() const + { + return descriptor_; + } + + // Perform the operation. + bool perform(const boost::system::error_code& result) + { + result_ = result; + return perform_func_(this, result_, bytes_transferred_); + } + + // Destroy the operation and post the handler. + void complete() + { + complete_func_(this, result_, bytes_transferred_); + } + + // Destroy the operation. + void destroy() + { + destroy_func_(this); + } + + protected: + typedef bool (*perform_func_type)(op_base*, + boost::system::error_code&, std::size_t&); + typedef void (*complete_func_type)(op_base*, + const boost::system::error_code&, std::size_t); + typedef void (*destroy_func_type)(op_base*); + + // Construct an operation for the given descriptor. + op_base(perform_func_type perform_func, complete_func_type complete_func, + destroy_func_type destroy_func, Descriptor descriptor) + : perform_func_(perform_func), + complete_func_(complete_func), + destroy_func_(destroy_func), + descriptor_(descriptor), + result_(), + bytes_transferred_(0), + next_(0) + { + } + + // Prevent deletion through this type. + ~op_base() + { + } + + private: + friend class reactor_op_queue; + + // The function to be called to perform the operation. + perform_func_type perform_func_; + + // The function to be called to delete the operation and post the handler. + complete_func_type complete_func_; + + // The function to be called to delete the operation. + destroy_func_type destroy_func_; + + // The descriptor associated with the operation. + Descriptor descriptor_; + + // The result of the operation. + boost::system::error_code result_; + + // The number of bytes transferred in the operation. + std::size_t bytes_transferred_; + + // The next operation for the same file descriptor. + op_base* next_; + }; + + // Adaptor class template for operations. + template + class op + : public op_base + { + public: + // Constructor. + op(Descriptor descriptor, Operation operation) + : op_base(&op::do_perform, &op::do_complete, + &op::do_destroy, descriptor), + operation_(operation) + { + } + + // Perform the operation. + static bool do_perform(op_base* base, + boost::system::error_code& result, std::size_t& bytes_transferred) + { + return static_cast*>(base)->operation_.perform( + result, bytes_transferred); + } + + // Destroy the operation and post the handler. + static void do_complete(op_base* base, + const boost::system::error_code& result, std::size_t bytes_transferred) + { + // Take ownership of the operation object. + typedef op this_type; + this_type* this_op(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(this_op->operation_, this_op); + + // Make a copy of the error_code and the operation so that the memory can + // be deallocated before the upcall is made. + boost::system::error_code ec(result); + Operation operation(this_op->operation_); + + // Free the memory associated with the operation. + ptr.reset(); + + // Make the upcall. + operation.complete(ec, bytes_transferred); + } + + // Destroy the operation. + static void do_destroy(op_base* base) + { + // Take ownership of the operation object. + typedef op this_type; + this_type* this_op(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(this_op->operation_, this_op); + + // A sub-object of the operation may be the true owner of the memory + // associated with the operation. Consequently, a local copy of the + // operation is required to ensure that any owning sub-object remains + // valid until after we have deallocated the memory here. + Operation operation(this_op->operation_); + (void)operation; + + // Free the memory associated with the operation. + ptr.reset(); + } + + private: + Operation operation_; + }; + + // The type for a map of operations. + typedef hash_map operation_map; + + // The operations that are currently executing asynchronously. + operation_map operations_; + + // The list of operations that have been cancelled. + op_base* cancelled_operations_; + + // The list of operations waiting to be completed. + op_base* complete_operations_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP diff --git a/win32/include/boost/asio/detail/resolver_service.hpp b/win32/include/boost/asio/detail/resolver_service.hpp new file mode 100755 index 000000000..5b5f9f7f9 --- /dev/null +++ b/win32/include/boost/asio/detail/resolver_service.hpp @@ -0,0 +1,359 @@ +// +// resolver_service.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_RESOLVER_SERVICE_HPP +#define BOOST_ASIO_DETAIL_RESOLVER_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class resolver_service + : public boost::asio::detail::service_base > +{ +private: + // Helper class to perform exception-safe cleanup of addrinfo objects. + class auto_addrinfo + : private boost::asio::detail::noncopyable + { + public: + explicit auto_addrinfo(boost::asio::detail::addrinfo_type* ai) + : ai_(ai) + { + } + + ~auto_addrinfo() + { + if (ai_) + socket_ops::freeaddrinfo(ai_); + } + + operator boost::asio::detail::addrinfo_type*() + { + return ai_; + } + + private: + boost::asio::detail::addrinfo_type* ai_; + }; + +public: + // The implementation type of the resolver. The shared pointer is used as a + // cancellation token to indicate to the background thread that the operation + // has been cancelled. + typedef boost::shared_ptr implementation_type; + struct noop_deleter { void operator()(void*) {} }; + + // The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + // The query type. + typedef typename Protocol::resolver_query query_type; + + // The iterator type. + typedef typename Protocol::resolver_iterator iterator_type; + + // Constructor. + resolver_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + resolver_service >(io_service), + mutex_(), + work_io_service_(new boost::asio::io_service), + work_(new boost::asio::io_service::work(*work_io_service_)), + work_thread_(0) + { + } + + // Destructor. + ~resolver_service() + { + shutdown_service(); + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + work_.reset(); + if (work_io_service_) + { + work_io_service_->stop(); + if (work_thread_) + { + work_thread_->join(); + work_thread_.reset(); + } + work_io_service_.reset(); + } + } + + // Construct a new resolver implementation. + void construct(implementation_type& impl) + { + impl.reset(static_cast(0), noop_deleter()); + } + + // Destroy a resolver implementation. + void destroy(implementation_type&) + { + } + + // Cancel pending asynchronous operations. + void cancel(implementation_type& impl) + { + impl.reset(static_cast(0), noop_deleter()); + } + + // Resolve a query to a list of entries. + iterator_type resolve(implementation_type&, const query_type& query, + boost::system::error_code& ec) + { + boost::asio::detail::addrinfo_type* address_info = 0; + std::string host_name = query.host_name(); + std::string service_name = query.service_name(); + boost::asio::detail::addrinfo_type hints = query.hints(); + + socket_ops::getaddrinfo(host_name.length() ? host_name.c_str() : 0, + service_name.c_str(), &hints, &address_info, ec); + auto_addrinfo auto_address_info(address_info); + + if (ec) + return iterator_type(); + + return iterator_type::create(address_info, host_name, service_name); + } + + template + class resolve_query_handler + { + public: + resolve_query_handler(implementation_type impl, const query_type& query, + boost::asio::io_service& io_service, Handler handler) + : impl_(impl), + query_(query), + io_service_(io_service), + work_(io_service), + handler_(handler) + { + } + + void operator()() + { + // Check if the operation has been cancelled. + if (impl_.expired()) + { + iterator_type iterator; + io_service_.post(boost::asio::detail::bind_handler(handler_, + boost::asio::error::operation_aborted, iterator)); + return; + } + + // Perform the blocking host resolution operation. + boost::asio::detail::addrinfo_type* address_info = 0; + std::string host_name = query_.host_name(); + std::string service_name = query_.service_name(); + boost::asio::detail::addrinfo_type hints = query_.hints(); + boost::system::error_code ec; + socket_ops::getaddrinfo(host_name.length() ? host_name.c_str() : 0, + service_name.c_str(), &hints, &address_info, ec); + auto_addrinfo auto_address_info(address_info); + + // Invoke the handler and pass the result. + iterator_type iterator; + if (!ec) + iterator = iterator_type::create(address_info, host_name, service_name); + io_service_.post(boost::asio::detail::bind_handler( + handler_, ec, iterator)); + } + + private: + boost::weak_ptr impl_; + query_type query_; + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + Handler handler_; + }; + + // Asynchronously resolve a query to a list of entries. + template + void async_resolve(implementation_type& impl, const query_type& query, + Handler handler) + { + if (work_io_service_) + { + start_work_thread(); + work_io_service_->post( + resolve_query_handler( + impl, query, this->get_io_service(), handler)); + } + } + + // Resolve an endpoint to a list of entries. + iterator_type resolve(implementation_type&, + const endpoint_type& endpoint, boost::system::error_code& ec) + { + // First try resolving with the service name. If that fails try resolving + // but allow the service to be returned as a number. + char host_name[NI_MAXHOST]; + char service_name[NI_MAXSERV]; + int flags = endpoint.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0; + socket_ops::getnameinfo(endpoint.data(), endpoint.size(), + host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec); + if (ec) + { + flags |= NI_NUMERICSERV; + socket_ops::getnameinfo(endpoint.data(), endpoint.size(), + host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec); + } + + if (ec) + return iterator_type(); + + return iterator_type::create(endpoint, host_name, service_name); + } + + template + class resolve_endpoint_handler + { + public: + resolve_endpoint_handler(implementation_type impl, + const endpoint_type& endpoint, boost::asio::io_service& io_service, + Handler handler) + : impl_(impl), + endpoint_(endpoint), + io_service_(io_service), + work_(io_service), + handler_(handler) + { + } + + void operator()() + { + // Check if the operation has been cancelled. + if (impl_.expired()) + { + iterator_type iterator; + io_service_.post(boost::asio::detail::bind_handler(handler_, + boost::asio::error::operation_aborted, iterator)); + return; + } + + + // First try resolving with the service name. If that fails try resolving + // but allow the service to be returned as a number. + char host_name[NI_MAXHOST]; + char service_name[NI_MAXSERV]; + int flags = endpoint_.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0; + boost::system::error_code ec; + socket_ops::getnameinfo(endpoint_.data(), endpoint_.size(), + host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec); + if (ec) + { + flags |= NI_NUMERICSERV; + socket_ops::getnameinfo(endpoint_.data(), endpoint_.size(), + host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec); + } + + // Invoke the handler and pass the result. + iterator_type iterator; + if (!ec) + iterator = iterator_type::create(endpoint_, host_name, service_name); + io_service_.post(boost::asio::detail::bind_handler( + handler_, ec, iterator)); + } + + private: + boost::weak_ptr impl_; + endpoint_type endpoint_; + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + Handler handler_; + }; + + // Asynchronously resolve an endpoint to a list of entries. + template + void async_resolve(implementation_type& impl, const endpoint_type& endpoint, + Handler handler) + { + if (work_io_service_) + { + start_work_thread(); + work_io_service_->post( + resolve_endpoint_handler( + impl, endpoint, this->get_io_service(), handler)); + } + } + +private: + // Helper class to run the work io_service in a thread. + class work_io_service_runner + { + public: + work_io_service_runner(boost::asio::io_service& io_service) + : io_service_(io_service) {} + void operator()() { io_service_.run(); } + private: + boost::asio::io_service& io_service_; + }; + + // Start the work thread if it's not already running. + void start_work_thread() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (work_thread_ == 0) + { + work_thread_.reset(new boost::asio::detail::thread( + work_io_service_runner(*work_io_service_))); + } + } + + // Mutex to protect access to internal data. + boost::asio::detail::mutex mutex_; + + // Private io_service used for performing asynchronous host resolution. + boost::scoped_ptr work_io_service_; + + // Work for the private io_service to perform. + boost::scoped_ptr work_; + + // Thread used for running the work io_service's run loop. + boost::scoped_ptr work_thread_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_RESOLVER_SERVICE_HPP diff --git a/win32/include/boost/asio/detail/scoped_lock.hpp b/win32/include/boost/asio/detail/scoped_lock.hpp new file mode 100755 index 000000000..5dfb4fd29 --- /dev/null +++ b/win32/include/boost/asio/detail/scoped_lock.hpp @@ -0,0 +1,93 @@ +// +// scoped_lock.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SCOPED_LOCK_HPP +#define BOOST_ASIO_DETAIL_SCOPED_LOCK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +// Helper class to lock and unlock a mutex automatically. +template +class scoped_lock + : private noncopyable +{ +public: + // Constructor acquires the lock. + scoped_lock(Mutex& m) + : mutex_(m) + { + mutex_.lock(); + locked_ = true; + } + + // Destructor releases the lock. + ~scoped_lock() + { + if (locked_) + mutex_.unlock(); + } + + // Explicitly acquire the lock. + void lock() + { + if (!locked_) + { + mutex_.lock(); + locked_ = true; + } + } + + // Explicitly release the lock. + void unlock() + { + if (locked_) + { + mutex_.unlock(); + locked_ = false; + } + } + + // Test whether the lock is held. + bool locked() const + { + return locked_; + } + + // Get the underlying mutex. + Mutex& mutex() + { + return mutex_; + } + +private: + // The underlying mutex. + Mutex& mutex_; + + // Whether the mutex is currently locked or unlocked. + bool locked_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SCOPED_LOCK_HPP diff --git a/win32/include/boost/asio/detail/select_interrupter.hpp b/win32/include/boost/asio/detail/select_interrupter.hpp new file mode 100755 index 000000000..d6586bcb8 --- /dev/null +++ b/win32/include/boost/asio/detail/select_interrupter.hpp @@ -0,0 +1,43 @@ +// +// select_interrupter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SELECT_INTERRUPTER_HPP +#define BOOST_ASIO_DETAIL_SELECT_INTERRUPTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +typedef socket_select_interrupter select_interrupter; +#else +typedef pipe_select_interrupter select_interrupter; +#endif + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SELECT_INTERRUPTER_HPP diff --git a/win32/include/boost/asio/detail/select_reactor.hpp b/win32/include/boost/asio/detail/select_reactor.hpp new file mode 100755 index 000000000..08ac2cbc9 --- /dev/null +++ b/win32/include/boost/asio/detail/select_reactor.hpp @@ -0,0 +1,536 @@ +// +// select_reactor.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SELECT_REACTOR_HPP +#define BOOST_ASIO_DETAIL_SELECT_REACTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include // Must come before posix_time. + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class select_reactor + : public boost::asio::detail::service_base > +{ +public: + // Per-descriptor data. + struct per_descriptor_data + { + }; + + // Constructor. + select_reactor(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + select_reactor >(io_service), + mutex_(), + select_in_progress_(false), + interrupter_(), + read_op_queue_(), + write_op_queue_(), + except_op_queue_(), + pending_cancellations_(), + stop_thread_(false), + thread_(0), + shutdown_(false) + { + if (Own_Thread) + { + boost::asio::detail::signal_blocker sb; + thread_ = new boost::asio::detail::thread( + bind_handler(&select_reactor::call_run_thread, this)); + } + } + + // Destructor. + ~select_reactor() + { + shutdown_service(); + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + shutdown_ = true; + stop_thread_ = true; + lock.unlock(); + + if (thread_) + { + interrupter_.interrupt(); + thread_->join(); + delete thread_; + thread_ = 0; + } + + read_op_queue_.destroy_operations(); + write_op_queue_.destroy_operations(); + except_op_queue_.destroy_operations(); + + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + timer_queues_[i]->destroy_timers(); + timer_queues_.clear(); + } + + // Register a socket with the reactor. Returns 0 on success, system error + // code on failure. + int register_descriptor(socket_type, per_descriptor_data&) + { + return 0; + } + + // Start a new read operation. The handler object will be invoked when the + // given descriptor is ready to be read, or an error has occurred. + template + void start_read_op(socket_type descriptor, per_descriptor_data&, + Handler handler, bool /*allow_speculative_read*/ = true) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (!shutdown_) + if (read_op_queue_.enqueue_operation(descriptor, handler)) + interrupter_.interrupt(); + } + + // Start a new write operation. The handler object will be invoked when the + // given descriptor is ready to be written, or an error has occurred. + template + void start_write_op(socket_type descriptor, per_descriptor_data&, + Handler handler, bool /*allow_speculative_write*/ = true) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (!shutdown_) + if (write_op_queue_.enqueue_operation(descriptor, handler)) + interrupter_.interrupt(); + } + + // Start a new exception operation. The handler object will be invoked when + // the given descriptor has exception information, or an error has occurred. + template + void start_except_op(socket_type descriptor, + per_descriptor_data&, Handler handler) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (!shutdown_) + if (except_op_queue_.enqueue_operation(descriptor, handler)) + interrupter_.interrupt(); + } + + // Wrapper for connect handlers to enable the handler object to be placed + // in both the write and the except operation queues, but ensure that only + // one of the handlers is called. + template + class connect_handler_wrapper + { + public: + connect_handler_wrapper(socket_type descriptor, + boost::shared_ptr completed, + select_reactor& reactor, Handler handler) + : descriptor_(descriptor), + completed_(completed), + reactor_(reactor), + handler_(handler) + { + } + + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) + { + // Check whether one of the handlers has already been called. If it has, + // then we don't want to do anything in this handler. + if (*completed_) + { + completed_.reset(); // Indicate that this handler should not complete. + return true; + } + + // Cancel the other reactor operation for the connection. + *completed_ = true; + reactor_.enqueue_cancel_ops_unlocked(descriptor_); + + // Call the contained handler. + return handler_.perform(ec, bytes_transferred); + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + if (completed_.get()) + handler_.complete(ec, bytes_transferred); + } + + private: + socket_type descriptor_; + boost::shared_ptr completed_; + select_reactor& reactor_; + Handler handler_; + }; + + // Start new write and exception operations. The handler object will be + // invoked when the given descriptor is ready for writing or has exception + // information available, or an error has occurred. The handler will be called + // only once. + template + void start_connect_op(socket_type descriptor, + per_descriptor_data&, Handler handler) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (!shutdown_) + { + boost::shared_ptr completed(new bool(false)); + connect_handler_wrapper wrapped_handler( + descriptor, completed, *this, handler); + bool interrupt = write_op_queue_.enqueue_operation( + descriptor, wrapped_handler); + interrupt = except_op_queue_.enqueue_operation( + descriptor, wrapped_handler) || interrupt; + if (interrupt) + interrupter_.interrupt(); + } + } + + // Cancel all operations associated with the given descriptor. The + // handlers associated with the descriptor will be invoked with the + // operation_aborted error. + void cancel_ops(socket_type descriptor, per_descriptor_data&) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + cancel_ops_unlocked(descriptor); + } + + // Enqueue cancellation of all operations associated with the given + // descriptor. The handlers associated with the descriptor will be invoked + // with the operation_aborted error. This function does not acquire the + // select_reactor's mutex, and so should only be used when the reactor lock is + // already held. + void enqueue_cancel_ops_unlocked(socket_type descriptor) + { + pending_cancellations_.push_back(descriptor); + } + + // Cancel any operations that are running against the descriptor and remove + // its registration from the reactor. + void close_descriptor(socket_type descriptor, per_descriptor_data&) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + cancel_ops_unlocked(descriptor); + } + + // Add a new timer queue to the reactor. + template + void add_timer_queue(timer_queue& timer_queue) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + timer_queues_.push_back(&timer_queue); + } + + // Remove a timer queue from the reactor. + template + void remove_timer_queue(timer_queue& timer_queue) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + { + if (timer_queues_[i] == &timer_queue) + { + timer_queues_.erase(timer_queues_.begin() + i); + return; + } + } + } + + // Schedule a timer in the given timer queue to expire at the specified + // absolute time. The handler object will be invoked when the timer expires. + template + void schedule_timer(timer_queue& timer_queue, + const typename Time_Traits::time_type& time, Handler handler, void* token) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (!shutdown_) + if (timer_queue.enqueue_timer(time, handler, token)) + interrupter_.interrupt(); + } + + // Cancel the timer associated with the given token. Returns the number of + // handlers that have been posted or dispatched. + template + std::size_t cancel_timer(timer_queue& timer_queue, void* token) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + std::size_t n = timer_queue.cancel_timer(token); + if (n > 0) + interrupter_.interrupt(); + return n; + } + +private: + friend class task_io_service >; + + // Run select once until interrupted or events are ready to be dispatched. + void run(bool block) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // Dispatch any operation cancellations that were made while the select + // loop was not running. + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + except_op_queue_.perform_cancellations(); + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + timer_queues_[i]->dispatch_cancellations(); + + // Check if the thread is supposed to stop. + if (stop_thread_) + { + complete_operations_and_timers(lock); + return; + } + + // We can return immediately if there's no work to do and the reactor is + // not supposed to block. + if (!block && read_op_queue_.empty() && write_op_queue_.empty() + && except_op_queue_.empty() && all_timer_queues_are_empty()) + { + complete_operations_and_timers(lock); + return; + } + + // Set up the descriptor sets. + fd_set_adapter read_fds; + read_fds.set(interrupter_.read_descriptor()); + read_op_queue_.get_descriptors(read_fds); + fd_set_adapter write_fds; + write_op_queue_.get_descriptors(write_fds); + fd_set_adapter except_fds; + except_op_queue_.get_descriptors(except_fds); + socket_type max_fd = read_fds.max_descriptor(); + if (write_fds.max_descriptor() > max_fd) + max_fd = write_fds.max_descriptor(); + if (except_fds.max_descriptor() > max_fd) + max_fd = except_fds.max_descriptor(); + + // Block on the select call without holding the lock so that new + // operations can be started while the call is executing. + timeval tv_buf = { 0, 0 }; + timeval* tv = block ? get_timeout(tv_buf) : &tv_buf; + select_in_progress_ = true; + lock.unlock(); + boost::system::error_code ec; + int retval = socket_ops::select(static_cast(max_fd + 1), + read_fds, write_fds, except_fds, tv, ec); + lock.lock(); + select_in_progress_ = false; + + // Block signals while dispatching operations. + boost::asio::detail::signal_blocker sb; + + // Reset the interrupter. + if (retval > 0 && read_fds.is_set(interrupter_.read_descriptor())) + interrupter_.reset(); + + // Dispatch all ready operations. + if (retval > 0) + { + // Exception operations must be processed first to ensure that any + // out-of-band data is read before normal data. + except_op_queue_.perform_operations_for_descriptors( + except_fds, boost::system::error_code()); + read_op_queue_.perform_operations_for_descriptors( + read_fds, boost::system::error_code()); + write_op_queue_.perform_operations_for_descriptors( + write_fds, boost::system::error_code()); + except_op_queue_.perform_cancellations(); + read_op_queue_.perform_cancellations(); + write_op_queue_.perform_cancellations(); + } + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + { + timer_queues_[i]->dispatch_timers(); + timer_queues_[i]->dispatch_cancellations(); + } + + // Issue any pending cancellations. + for (size_t i = 0; i < pending_cancellations_.size(); ++i) + cancel_ops_unlocked(pending_cancellations_[i]); + pending_cancellations_.clear(); + + complete_operations_and_timers(lock); + } + + // Run the select loop in the thread. + void run_thread() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + while (!stop_thread_) + { + lock.unlock(); + run(true); + lock.lock(); + } + } + + // Entry point for the select loop thread. + static void call_run_thread(select_reactor* reactor) + { + reactor->run_thread(); + } + + // Interrupt the select loop. + void interrupt() + { + interrupter_.interrupt(); + } + + // Check if all timer queues are empty. + bool all_timer_queues_are_empty() const + { + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + if (!timer_queues_[i]->empty()) + return false; + return true; + } + + // Get the timeout value for the select call. + timeval* get_timeout(timeval& tv) + { + if (all_timer_queues_are_empty()) + return 0; + + // By default we will wait no longer than 5 minutes. This will ensure that + // any changes to the system clock are detected after no longer than this. + boost::posix_time::time_duration minimum_wait_duration + = boost::posix_time::minutes(5); + + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + { + boost::posix_time::time_duration wait_duration + = timer_queues_[i]->wait_duration(); + if (wait_duration < minimum_wait_duration) + minimum_wait_duration = wait_duration; + } + + if (minimum_wait_duration > boost::posix_time::time_duration()) + { + tv.tv_sec = minimum_wait_duration.total_seconds(); + tv.tv_usec = minimum_wait_duration.total_microseconds() % 1000000; + } + else + { + tv.tv_sec = 0; + tv.tv_usec = 0; + } + + return &tv; + } + + // Cancel all operations associated with the given descriptor. The do_cancel + // function of the handler objects will be invoked. This function does not + // acquire the select_reactor's mutex. + void cancel_ops_unlocked(socket_type descriptor) + { + bool interrupt = read_op_queue_.cancel_operations(descriptor); + interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt; + interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt; + if (interrupt) + interrupter_.interrupt(); + } + + // Clean up operations and timers. We must not hold the lock since the + // destructors may make calls back into this reactor. We make a copy of the + // vector of timer queues since the original may be modified while the lock + // is not held. + void complete_operations_and_timers( + boost::asio::detail::mutex::scoped_lock& lock) + { + timer_queues_for_cleanup_ = timer_queues_; + lock.unlock(); + read_op_queue_.complete_operations(); + write_op_queue_.complete_operations(); + except_op_queue_.complete_operations(); + for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i) + timer_queues_for_cleanup_[i]->complete_timers(); + } + + // Mutex to protect access to internal data. + boost::asio::detail::mutex mutex_; + + // Whether the select loop is currently running or not. + bool select_in_progress_; + + // The interrupter is used to break a blocking select call. + select_interrupter interrupter_; + + // The queue of read operations. + reactor_op_queue read_op_queue_; + + // The queue of write operations. + reactor_op_queue write_op_queue_; + + // The queue of exception operations. + reactor_op_queue except_op_queue_; + + // The timer queues. + std::vector timer_queues_; + + // A copy of the timer queues, used when cleaning up timers. The copy is + // stored as a class data member to avoid unnecessary memory allocation. + std::vector timer_queues_for_cleanup_; + + // The descriptors that are pending cancellation. + std::vector pending_cancellations_; + + // Does the reactor loop thread need to stop. + bool stop_thread_; + + // The thread that is running the reactor loop. + boost::asio::detail::thread* thread_; + + // Whether the service has been shut down. + bool shutdown_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SELECT_REACTOR_HPP diff --git a/win32/include/boost/asio/detail/select_reactor_fwd.hpp b/win32/include/boost/asio/detail/select_reactor_fwd.hpp new file mode 100755 index 000000000..44b6b592e --- /dev/null +++ b/win32/include/boost/asio/detail/select_reactor_fwd.hpp @@ -0,0 +1,33 @@ +// +// select_reactor_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SELECT_REACTOR_FWD_HPP +#define BOOST_ASIO_DETAIL_SELECT_REACTOR_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class select_reactor; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SELECT_REACTOR_FWD_HPP diff --git a/win32/include/boost/asio/detail/service_base.hpp b/win32/include/boost/asio/detail/service_base.hpp new file mode 100755 index 000000000..cdcba2ed3 --- /dev/null +++ b/win32/include/boost/asio/detail/service_base.hpp @@ -0,0 +1,51 @@ +// +// service_base.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SERVICE_BASE_HPP +#define BOOST_ASIO_DETAIL_SERVICE_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +// Special service base class to keep classes header-file only. +template +class service_base + : public boost::asio::io_service::service +{ +public: + static boost::asio::detail::service_id id; + + // Constructor. + service_base(boost::asio::io_service& io_service) + : boost::asio::io_service::service(io_service) + { + } +}; + +template +boost::asio::detail::service_id service_base::id; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SERVICE_BASE_HPP diff --git a/win32/include/boost/asio/detail/service_id.hpp b/win32/include/boost/asio/detail/service_id.hpp new file mode 100755 index 000000000..ea9046833 --- /dev/null +++ b/win32/include/boost/asio/detail/service_id.hpp @@ -0,0 +1,39 @@ +// +// service_id.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SERVICE_ID_HPP +#define BOOST_ASIO_DETAIL_SERVICE_ID_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +// Special derived service id type to keep classes header-file only. +template +class service_id + : public boost::asio::io_service::id +{ +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SERVICE_ID_HPP diff --git a/win32/include/boost/asio/detail/service_registry.hpp b/win32/include/boost/asio/detail/service_registry.hpp new file mode 100755 index 000000000..5a610c7e5 --- /dev/null +++ b/win32/include/boost/asio/detail/service_registry.hpp @@ -0,0 +1,212 @@ +// +// service_registry.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SERVICE_REGISTRY_HPP +#define BOOST_ASIO_DETAIL_SERVICE_REGISTRY_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(BOOST_NO_TYPEID) +# if !defined(BOOST_ASIO_NO_TYPEID) +# define BOOST_ASIO_NO_TYPEID +# endif // !defined(BOOST_ASIO_NO_TYPEID) +#endif // defined(BOOST_NO_TYPEID) + +namespace boost { +namespace asio { +namespace detail { + +class service_registry + : private noncopyable +{ +public: + // Constructor. + service_registry(boost::asio::io_service& o) + : owner_(o), + first_service_(0) + { + } + + // Destructor. + ~service_registry() + { + // Shutdown all services. This must be done in a separate loop before the + // services are destroyed since the destructors of user-defined handler + // objects may try to access other service objects. + boost::asio::io_service::service* service = first_service_; + while (service) + { + service->shutdown_service(); + service = service->next_; + } + + // Destroy all services. + while (first_service_) + { + boost::asio::io_service::service* next_service = first_service_->next_; + delete first_service_; + first_service_ = next_service; + } + } + + // Get the service object corresponding to the specified service type. Will + // create a new service object automatically if no such object already + // exists. Ownership of the service object is not transferred to the caller. + template + Service& use_service() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // First see if there is an existing service object for the given type. + boost::asio::io_service::service* service = first_service_; + while (service) + { + if (service_id_matches(*service, Service::id)) + return *static_cast(service); + service = service->next_; + } + + // Create a new service object. The service registry's mutex is not locked + // at this time to allow for nested calls into this function from the new + // service's constructor. + lock.unlock(); + std::auto_ptr new_service(new Service(owner_)); + init_service_id(*new_service, Service::id); + Service& new_service_ref = *new_service; + lock.lock(); + + // Check that nobody else created another service object of the same type + // while the lock was released. + service = first_service_; + while (service) + { + if (service_id_matches(*service, Service::id)) + return *static_cast(service); + service = service->next_; + } + + // Service was successfully initialised, pass ownership to registry. + new_service->next_ = first_service_; + first_service_ = new_service.release(); + + return new_service_ref; + } + + // Add a service object. Returns false on error, in which case ownership of + // the object is retained by the caller. + template + bool add_service(Service* new_service) + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // Check if there is an existing service object for the given type. + boost::asio::io_service::service* service = first_service_; + while (service) + { + if (service_id_matches(*service, Service::id)) + return false; + service = service->next_; + } + + // Take ownership of the service object. + init_service_id(*new_service, Service::id); + new_service->next_ = first_service_; + first_service_ = new_service; + + return true; + } + + // Check whether a service object of the specified type already exists. + template + bool has_service() const + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + boost::asio::io_service::service* service = first_service_; + while (service) + { + if (service_id_matches(*service, Service::id)) + return true; + service = service->next_; + } + + return false; + } + +private: + // Set a service's id. + void init_service_id(boost::asio::io_service::service& service, + const boost::asio::io_service::id& id) + { + service.type_info_ = 0; + service.id_ = &id; + } + +#if !defined(BOOST_ASIO_NO_TYPEID) + // Set a service's id. + template + void init_service_id(boost::asio::io_service::service& service, + const boost::asio::detail::service_id& /*id*/) + { + service.type_info_ = &typeid(Service); + service.id_ = 0; + } +#endif // !defined(BOOST_ASIO_NO_TYPEID) + + // Check if a service matches the given id. + static bool service_id_matches( + const boost::asio::io_service::service& service, + const boost::asio::io_service::id& id) + { + return service.id_ == &id; + } + +#if !defined(BOOST_ASIO_NO_TYPEID) + // Check if a service matches the given id. + template + static bool service_id_matches( + const boost::asio::io_service::service& service, + const boost::asio::detail::service_id& /*id*/) + { + return service.type_info_ != 0 && *service.type_info_ == typeid(Service); + } +#endif // !defined(BOOST_ASIO_NO_TYPEID) + + // Mutex to protect access to internal data. + mutable boost::asio::detail::mutex mutex_; + + // The owner of this service registry and the services it contains. + boost::asio::io_service& owner_; + + // The first service in the list of contained services. + boost::asio::io_service::service* first_service_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SERVICE_REGISTRY_HPP diff --git a/win32/include/boost/asio/detail/service_registry_fwd.hpp b/win32/include/boost/asio/detail/service_registry_fwd.hpp new file mode 100755 index 000000000..5e1bc2981 --- /dev/null +++ b/win32/include/boost/asio/detail/service_registry_fwd.hpp @@ -0,0 +1,32 @@ +// +// service_registry_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP +#define BOOST_ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +namespace boost { +namespace asio { +namespace detail { + +class service_registry; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP diff --git a/win32/include/boost/asio/detail/signal_blocker.hpp b/win32/include/boost/asio/detail/signal_blocker.hpp new file mode 100755 index 000000000..09f11b3a6 --- /dev/null +++ b/win32/include/boost/asio/detail/signal_blocker.hpp @@ -0,0 +1,52 @@ +// +// signal_blocker.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SIGNAL_BLOCKER_HPP +#define BOOST_ASIO_DETAIL_SIGNAL_BLOCKER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if !defined(BOOST_HAS_THREADS) +# include +#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) +# include +#elif defined(BOOST_HAS_PTHREADS) +# include +#else +# error Only Windows and POSIX are supported! +#endif + +namespace boost { +namespace asio { +namespace detail { + +#if !defined(BOOST_HAS_THREADS) +typedef null_signal_blocker signal_blocker; +#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) +typedef win_signal_blocker signal_blocker; +#elif defined(BOOST_HAS_PTHREADS) +typedef posix_signal_blocker signal_blocker; +#endif + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SIGNAL_BLOCKER_HPP diff --git a/win32/include/boost/asio/detail/signal_init.hpp b/win32/include/boost/asio/detail/signal_init.hpp new file mode 100755 index 000000000..e295b0ab4 --- /dev/null +++ b/win32/include/boost/asio/detail/signal_init.hpp @@ -0,0 +1,53 @@ +// +// signal_init.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SIGNAL_INIT_HPP +#define BOOST_ASIO_DETAIL_SIGNAL_INIT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class signal_init +{ +public: + // Constructor. + signal_init() + { + std::signal(Signal, SIG_IGN); + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +#include + +#endif // BOOST_ASIO_DETAIL_SIGNAL_INIT_HPP diff --git a/win32/include/boost/asio/detail/socket_holder.hpp b/win32/include/boost/asio/detail/socket_holder.hpp new file mode 100755 index 000000000..a2136357f --- /dev/null +++ b/win32/include/boost/asio/detail/socket_holder.hpp @@ -0,0 +1,97 @@ +// +// socket_holder.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SOCKET_HOLDER_HPP +#define BOOST_ASIO_DETAIL_SOCKET_HOLDER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +// Implement the resource acquisition is initialisation idiom for sockets. +class socket_holder + : private noncopyable +{ +public: + // Construct as an uninitialised socket. + socket_holder() + : socket_(invalid_socket) + { + } + + // Construct to take ownership of the specified socket. + explicit socket_holder(socket_type s) + : socket_(s) + { + } + + // Destructor. + ~socket_holder() + { + if (socket_ != invalid_socket) + { + boost::system::error_code ec; + socket_ops::close(socket_, ec); + } + } + + // Get the underlying socket. + socket_type get() const + { + return socket_; + } + + // Reset to an uninitialised socket. + void reset() + { + if (socket_ != invalid_socket) + { + boost::system::error_code ec; + socket_ops::close(socket_, ec); + socket_ = invalid_socket; + } + } + + // Reset to take ownership of the specified socket. + void reset(socket_type s) + { + reset(); + socket_ = s; + } + + // Release ownership of the socket. + socket_type release() + { + socket_type tmp = socket_; + socket_ = invalid_socket; + return tmp; + } + +private: + // The underlying socket. + socket_type socket_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SOCKET_HOLDER_HPP diff --git a/win32/include/boost/asio/detail/socket_ops.hpp b/win32/include/boost/asio/detail/socket_ops.hpp new file mode 100755 index 000000000..4aec943e3 --- /dev/null +++ b/win32/include/boost/asio/detail/socket_ops.hpp @@ -0,0 +1,1895 @@ +// +// socket_ops.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_HPP +#define BOOST_ASIO_DETAIL_SOCKET_OPS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { +namespace detail { +namespace socket_ops { + +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +struct msghdr { int msg_namelen; }; +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + +#if defined(__hpux) +// HP-UX doesn't declare these functions extern "C", so they are declared again +// here to avoid linker errors about undefined symbols. +extern "C" char* if_indextoname(unsigned int, char*); +extern "C" unsigned int if_nametoindex(const char*); +#endif // defined(__hpux) + +inline void clear_error(boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + WSASetLastError(0); +#else + errno = 0; +#endif + ec = boost::system::error_code(); +} + +template +inline ReturnType error_wrapper(ReturnType return_value, + boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + ec = boost::system::error_code(WSAGetLastError(), + boost::asio::error::get_system_category()); +#else + ec = boost::system::error_code(errno, + boost::asio::error::get_system_category()); +#endif + return return_value; +} + +template +inline socket_type call_accept(SockLenType msghdr::*, + socket_type s, socket_addr_type* addr, std::size_t* addrlen) +{ + SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0; + socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0); + if (addrlen) + *addrlen = (std::size_t)tmp_addrlen; + return result; +} + +inline socket_type accept(socket_type s, socket_addr_type* addr, + std::size_t* addrlen, boost::system::error_code& ec) +{ + clear_error(ec); + + socket_type new_s = error_wrapper(call_accept( + &msghdr::msg_namelen, s, addr, addrlen), ec); + if (new_s == invalid_socket) + return new_s; + +#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__) + int optval = 1; + int result = error_wrapper(::setsockopt(new_s, + SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec); + if (result != 0) + { + ::close(new_s); + return invalid_socket; + } +#endif + +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + clear_error(ec); +#endif + + return new_s; +} + +template +inline int call_bind(SockLenType msghdr::*, + socket_type s, const socket_addr_type* addr, std::size_t addrlen) +{ + return ::bind(s, addr, (SockLenType)addrlen); +} + +inline int bind(socket_type s, const socket_addr_type* addr, + std::size_t addrlen, boost::system::error_code& ec) +{ + clear_error(ec); + int result = error_wrapper(call_bind( + &msghdr::msg_namelen, s, addr, addrlen), ec); +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +#endif + return result; +} + +inline int close(socket_type s, boost::system::error_code& ec) +{ + clear_error(ec); +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + int result = error_wrapper(::closesocket(s), ec); +# if defined(UNDER_CE) + if (result == 0) + clear_error(ec); +# endif + return result; +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + return error_wrapper(::close(s), ec); +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +} + +inline int shutdown(socket_type s, int what, boost::system::error_code& ec) +{ + clear_error(ec); + int result = error_wrapper(::shutdown(s, what), ec); +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +#endif + return result; +} + +template +inline int call_connect(SockLenType msghdr::*, + socket_type s, const socket_addr_type* addr, std::size_t addrlen) +{ + return ::connect(s, addr, (SockLenType)addrlen); +} + +inline int connect(socket_type s, const socket_addr_type* addr, + std::size_t addrlen, boost::system::error_code& ec) +{ + clear_error(ec); + int result = error_wrapper(call_connect( + &msghdr::msg_namelen, s, addr, addrlen), ec); +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +#endif + return result; +} + +inline int socketpair(int af, int type, int protocol, + socket_type sv[2], boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + (void)(af); + (void)(type); + (void)(protocol); + (void)(sv); + ec = boost::asio::error::operation_not_supported; + return -1; +#else + clear_error(ec); + return error_wrapper(::socketpair(af, type, protocol, sv), ec); +#endif +} + +inline int listen(socket_type s, int backlog, boost::system::error_code& ec) +{ + clear_error(ec); + int result = error_wrapper(::listen(s, backlog), ec); +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +#endif + return result; +} + +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +typedef WSABUF buf; +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +typedef iovec buf; +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + +inline void init_buf(buf& b, void* data, size_t size) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + b.buf = static_cast(data); + b.len = static_cast(size); +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + b.iov_base = data; + b.iov_len = size; +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +} + +inline void init_buf(buf& b, const void* data, size_t size) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + b.buf = static_cast(const_cast(data)); + b.len = static_cast(size); +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + b.iov_base = const_cast(data); + b.iov_len = size; +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +} + +inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr) +{ + name = addr; +} + +inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr) +{ + name = const_cast(addr); +} + +template +inline void init_msghdr_msg_name(T& name, socket_addr_type* addr) +{ + name = reinterpret_cast(addr); +} + +template +inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr) +{ + name = reinterpret_cast(const_cast(addr)); +} + +inline int recv(socket_type s, buf* bufs, size_t count, int flags, + boost::system::error_code& ec) +{ + clear_error(ec); +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + // Receive some data. + DWORD recv_buf_count = static_cast(count); + DWORD bytes_transferred = 0; + DWORD recv_flags = flags; + int result = error_wrapper(::WSARecv(s, bufs, + recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec); + if (result != 0) + return -1; +# if defined(UNDER_CE) + clear_error(ec); +# endif + return bytes_transferred; +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + msghdr msg = msghdr(); + msg.msg_iov = bufs; + msg.msg_iovlen = count; + return error_wrapper(::recvmsg(s, &msg, flags), ec); +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +} + +inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags, + socket_addr_type* addr, std::size_t* addrlen, + boost::system::error_code& ec) +{ + clear_error(ec); +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + // Receive some data. + DWORD recv_buf_count = static_cast(count); + DWORD bytes_transferred = 0; + DWORD recv_flags = flags; + int tmp_addrlen = (int)*addrlen; + int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count, + &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec); + *addrlen = (std::size_t)tmp_addrlen; + if (result != 0) + return -1; +# if defined(UNDER_CE) + clear_error(ec); +# endif + return bytes_transferred; +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + msghdr msg = msghdr(); + init_msghdr_msg_name(msg.msg_name, addr); + msg.msg_namelen = *addrlen; + msg.msg_iov = bufs; + msg.msg_iovlen = count; + int result = error_wrapper(::recvmsg(s, &msg, flags), ec); + *addrlen = msg.msg_namelen; + return result; +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +} + +inline int send(socket_type s, const buf* bufs, size_t count, int flags, + boost::system::error_code& ec) +{ + clear_error(ec); +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + // Send the data. + DWORD send_buf_count = static_cast(count); + DWORD bytes_transferred = 0; + DWORD send_flags = flags; + int result = error_wrapper(::WSASend(s, const_cast(bufs), + send_buf_count, &bytes_transferred, send_flags, 0, 0), ec); + if (result != 0) + return -1; +# if defined(UNDER_CE) + clear_error(ec); +# endif + return bytes_transferred; +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + msghdr msg = msghdr(); + msg.msg_iov = const_cast(bufs); + msg.msg_iovlen = count; +#if defined(__linux__) + flags |= MSG_NOSIGNAL; +#endif // defined(__linux__) + return error_wrapper(::sendmsg(s, &msg, flags), ec); +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +} + +inline int sendto(socket_type s, const buf* bufs, size_t count, int flags, + const socket_addr_type* addr, std::size_t addrlen, + boost::system::error_code& ec) +{ + clear_error(ec); +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + // Send the data. + DWORD send_buf_count = static_cast(count); + DWORD bytes_transferred = 0; + int result = error_wrapper(::WSASendTo(s, const_cast(bufs), + send_buf_count, &bytes_transferred, flags, addr, + static_cast(addrlen), 0, 0), ec); + if (result != 0) + return -1; +# if defined(UNDER_CE) + clear_error(ec); +# endif + return bytes_transferred; +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + msghdr msg = msghdr(); + init_msghdr_msg_name(msg.msg_name, addr); + msg.msg_namelen = addrlen; + msg.msg_iov = const_cast(bufs); + msg.msg_iovlen = count; +#if defined(__linux__) + flags |= MSG_NOSIGNAL; +#endif // defined(__linux__) + return error_wrapper(::sendmsg(s, &msg, flags), ec); +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +} + +inline socket_type socket(int af, int type, int protocol, + boost::system::error_code& ec) +{ + clear_error(ec); +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + socket_type s = error_wrapper(::WSASocket(af, type, protocol, 0, 0, + WSA_FLAG_OVERLAPPED), ec); + if (s == invalid_socket) + return s; + + if (af == AF_INET6) + { + // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to + // false. This will only succeed on Windows Vista and later versions of + // Windows, where a dual-stack IPv4/v6 implementation is available. + DWORD optval = 0; + ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, + reinterpret_cast(&optval), sizeof(optval)); + } + +# if defined(UNDER_CE) + clear_error(ec); +# endif + + return s; +#elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__) + socket_type s = error_wrapper(::socket(af, type, protocol), ec); + if (s == invalid_socket) + return s; + + int optval = 1; + int result = error_wrapper(::setsockopt(s, + SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec); + if (result != 0) + { + ::close(s); + return invalid_socket; + } + + return s; +#else + return error_wrapper(::socket(af, type, protocol), ec); +#endif +} + +template +inline int call_setsockopt(SockLenType msghdr::*, + socket_type s, int level, int optname, + const void* optval, std::size_t optlen) +{ + return ::setsockopt(s, level, optname, + (const char*)optval, (SockLenType)optlen); +} + +inline int setsockopt(socket_type s, int level, int optname, + const void* optval, std::size_t optlen, boost::system::error_code& ec) +{ + if (level == custom_socket_option_level && optname == always_fail_option) + { + ec = boost::asio::error::invalid_argument; + return -1; + } + +#if defined(__BORLANDC__) + // Mysteriously, using the getsockopt and setsockopt functions directly with + // Borland C++ results in incorrect values being set and read. The bug can be + // worked around by using function addresses resolved with GetProcAddress. + if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) + { + typedef int (WSAAPI *sso_t)(SOCKET, int, int, const char*, int); + if (sso_t sso = (sso_t)::GetProcAddress(winsock_module, "setsockopt")) + { + clear_error(ec); + return error_wrapper(sso(s, level, optname, + reinterpret_cast(optval), + static_cast(optlen)), ec); + } + } + ec = boost::asio::error::fault; + return -1; +#else // defined(__BORLANDC__) + clear_error(ec); + int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen, + s, level, optname, optval, optlen), ec); +# if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +# endif + return result; +#endif // defined(__BORLANDC__) +} + +template +inline int call_getsockopt(SockLenType msghdr::*, + socket_type s, int level, int optname, + void* optval, std::size_t* optlen) +{ + SockLenType tmp_optlen = (SockLenType)*optlen; + int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen); + *optlen = (std::size_t)tmp_optlen; + return result; +} + +inline int getsockopt(socket_type s, int level, int optname, void* optval, + size_t* optlen, boost::system::error_code& ec) +{ + if (level == custom_socket_option_level && optname == always_fail_option) + { + ec = boost::asio::error::invalid_argument; + return -1; + } + +#if defined(__BORLANDC__) + // Mysteriously, using the getsockopt and setsockopt functions directly with + // Borland C++ results in incorrect values being set and read. The bug can be + // worked around by using function addresses resolved with GetProcAddress. + if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) + { + typedef int (WSAAPI *gso_t)(SOCKET, int, int, char*, int*); + if (gso_t gso = (gso_t)::GetProcAddress(winsock_module, "getsockopt")) + { + clear_error(ec); + int tmp_optlen = static_cast(*optlen); + int result = error_wrapper(gso(s, level, optname, + reinterpret_cast(optval), &tmp_optlen), ec); + *optlen = static_cast(tmp_optlen); + if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY + && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD)) + { + // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are + // only supported on Windows Vista and later. To simplify program logic + // we will fake success of getting this option and specify that the + // value is non-zero (i.e. true). This corresponds to the behavior of + // IPv6 sockets on Windows platforms pre-Vista. + *static_cast(optval) = 1; + clear_error(ec); + } + return result; + } + } + ec = boost::asio::error::fault; + return -1; +#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) + clear_error(ec); + int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen, + s, level, optname, optval, optlen), ec); + if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY + && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD)) + { + // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only + // supported on Windows Vista and later. To simplify program logic we will + // fake success of getting this option and specify that the value is + // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets + // on Windows platforms pre-Vista. + *static_cast(optval) = 1; + clear_error(ec); + } +# if defined(UNDER_CE) + if (result == 0) + clear_error(ec); +# endif + return result; +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + clear_error(ec); + int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen, + s, level, optname, optval, optlen), ec); +#if defined(__linux__) + if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int) + && (optname == SO_SNDBUF || optname == SO_RCVBUF)) + { + // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel + // to set the buffer size to N*2. Linux puts additional stuff into the + // buffers so that only about half is actually available to the application. + // The retrieved value is divided by 2 here to make it appear as though the + // correct value has been set. + *static_cast(optval) /= 2; + } +#endif // defined(__linux__) + return result; +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +} + +template +inline int call_getpeername(SockLenType msghdr::*, + socket_type s, socket_addr_type* addr, std::size_t* addrlen) +{ + SockLenType tmp_addrlen = (SockLenType)*addrlen; + int result = ::getpeername(s, addr, &tmp_addrlen); + *addrlen = (std::size_t)tmp_addrlen; + return result; +} + +inline int getpeername(socket_type s, socket_addr_type* addr, + std::size_t* addrlen, boost::system::error_code& ec) +{ + clear_error(ec); + int result = error_wrapper(call_getpeername( + &msghdr::msg_namelen, s, addr, addrlen), ec); +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +#endif + return result; +} + +template +inline int call_getsockname(SockLenType msghdr::*, + socket_type s, socket_addr_type* addr, std::size_t* addrlen) +{ + SockLenType tmp_addrlen = (SockLenType)*addrlen; + int result = ::getsockname(s, addr, &tmp_addrlen); + *addrlen = (std::size_t)tmp_addrlen; + return result; +} + +inline int getsockname(socket_type s, socket_addr_type* addr, + std::size_t* addrlen, boost::system::error_code& ec) +{ + clear_error(ec); + int result = error_wrapper(call_getsockname( + &msghdr::msg_namelen, s, addr, addrlen), ec); +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +#endif + return result; +} + +inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg, + boost::system::error_code& ec) +{ + clear_error(ec); +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec); +# if defined(UNDER_CE) + if (result == 0) + clear_error(ec); +# endif + return result; +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + return error_wrapper(::ioctl(s, cmd, arg), ec); +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +} + +inline int select(int nfds, fd_set* readfds, fd_set* writefds, + fd_set* exceptfds, timeval* timeout, boost::system::error_code& ec) +{ + clear_error(ec); +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + if (!readfds && !writefds && !exceptfds && timeout) + { + DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; + if (milliseconds == 0) + milliseconds = 1; // Force context switch. + ::Sleep(milliseconds); + ec = boost::system::error_code(); + return 0; + } + + // The select() call allows timeout values measured in microseconds, but the + // system clock (as wrapped by boost::posix_time::microsec_clock) typically + // has a resolution of 10 milliseconds. This can lead to a spinning select + // reactor, meaning increased CPU usage, when waiting for the earliest + // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight + // spin we'll use a minimum timeout of 1 millisecond. + if (timeout && timeout->tv_sec == 0 + && timeout->tv_usec > 0 && timeout->tv_usec < 1000) + timeout->tv_usec = 1000; +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + +#if defined(__hpux) && defined(__HP_aCC) + timespec ts; + ts.tv_sec = timeout ? timeout->tv_sec : 0; + ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0; + return error_wrapper(::pselect(nfds, readfds, + writefds, exceptfds, timeout ? &ts : 0, 0), ec); +#else + int result = error_wrapper(::select(nfds, readfds, + writefds, exceptfds, timeout), ec); +# if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result >= 0) + clear_error(ec); +# endif + return result; +#endif +} + +inline int poll_read(socket_type s, boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + FD_SET fds; + FD_ZERO(&fds); + FD_SET(s, &fds); + clear_error(ec); + int result = error_wrapper(::select(s, &fds, 0, 0, 0), ec); +# if defined(UNDER_CE) + if (result >= 0) + clear_error(ec); +# endif + return result; +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + pollfd fds; + fds.fd = s; + fds.events = POLLIN; + fds.revents = 0; + clear_error(ec); + return error_wrapper(::poll(&fds, 1, -1), ec); +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +} + +inline int poll_write(socket_type s, boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + FD_SET fds; + FD_ZERO(&fds); + FD_SET(s, &fds); + clear_error(ec); + int result = error_wrapper(::select(s, 0, &fds, 0, 0), ec); +# if defined(UNDER_CE) + if (result >= 0) + clear_error(ec); +# endif + return result; +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + pollfd fds; + fds.fd = s; + fds.events = POLLOUT; + fds.revents = 0; + clear_error(ec); + return error_wrapper(::poll(&fds, 1, -1), ec); +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +} + +inline const char* inet_ntop(int af, const void* src, char* dest, size_t length, + unsigned long scope_id, boost::system::error_code& ec) +{ + clear_error(ec); +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + using namespace std; // For memcpy. + + if (af != AF_INET && af != AF_INET6) + { + ec = boost::asio::error::address_family_not_supported; + return 0; + } + + union + { + socket_addr_type base; + sockaddr_storage_type storage; + sockaddr_in4_type v4; + sockaddr_in6_type v6; + } address; + DWORD address_length; + if (af == AF_INET) + { + address_length = sizeof(sockaddr_in4_type); + address.v4.sin_family = AF_INET; + address.v4.sin_port = 0; + memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type)); + } + else // AF_INET6 + { + address_length = sizeof(sockaddr_in6_type); + address.v6.sin6_family = AF_INET6; + address.v6.sin6_port = 0; + address.v6.sin6_flowinfo = 0; + address.v6.sin6_scope_id = scope_id; + memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type)); + } + + DWORD string_length = static_cast(length); +#if defined(BOOST_NO_ANSI_APIS) + LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR)); + int result = error_wrapper(::WSAAddressToStringW(&address.base, + address_length, 0, string_buffer, &string_length), ec); + ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0); +#else + int result = error_wrapper(::WSAAddressToStringA( + &address.base, address_length, 0, dest, &string_length), ec); +#endif + + // Windows may set error code on success. + if (result != socket_error_retval) + clear_error(ec); + + // Windows may not set an error code on failure. + else if (result == socket_error_retval && !ec) + ec = boost::asio::error::invalid_argument; + + return result == socket_error_retval ? 0 : dest; +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + const char* result = error_wrapper(::inet_ntop(af, src, dest, length), ec); + if (result == 0 && !ec) + ec = boost::asio::error::invalid_argument; + if (result != 0 && af == AF_INET6 && scope_id != 0) + { + using namespace std; // For strcat and sprintf. + char if_name[IF_NAMESIZE + 1] = "%"; + const in6_addr_type* ipv6_address = static_cast(src); + bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address); + if (!is_link_local || if_indextoname(scope_id, if_name + 1) == 0) + sprintf(if_name + 1, "%lu", scope_id); + strcat(dest, if_name); + } + return result; +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +} + +inline int inet_pton(int af, const char* src, void* dest, + unsigned long* scope_id, boost::system::error_code& ec) +{ + clear_error(ec); +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + using namespace std; // For memcpy and strcmp. + + if (af != AF_INET && af != AF_INET6) + { + ec = boost::asio::error::address_family_not_supported; + return -1; + } + + union + { + socket_addr_type base; + sockaddr_storage_type storage; + sockaddr_in4_type v4; + sockaddr_in6_type v6; + } address; + int address_length = sizeof(sockaddr_storage_type); +#if defined(BOOST_NO_ANSI_APIS) + int num_wide_chars = strlen(src) + 1; + LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR)); + ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars); + int result = error_wrapper(::WSAStringToAddressW( + wide_buffer, af, 0, &address.base, &address_length), ec); +#else + int result = error_wrapper(::WSAStringToAddressA( + const_cast(src), af, 0, &address.base, &address_length), ec); +#endif + + if (af == AF_INET) + { + if (result != socket_error_retval) + { + memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type)); + clear_error(ec); + } + else if (strcmp(src, "255.255.255.255") == 0) + { + static_cast(dest)->s_addr = INADDR_NONE; + clear_error(ec); + } + } + else // AF_INET6 + { + if (result != socket_error_retval) + { + memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type)); + if (scope_id) + *scope_id = address.v6.sin6_scope_id; + clear_error(ec); + } + } + + // Windows may not set an error code on failure. + if (result == socket_error_retval && !ec) + ec = boost::asio::error::invalid_argument; + +#if defined(UNDER_CE) + if (result != socket_error_retval) + clear_error(ec); +#endif + + return result == socket_error_retval ? -1 : 1; +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + int result = error_wrapper(::inet_pton(af, src, dest), ec); + if (result <= 0 && !ec) + ec = boost::asio::error::invalid_argument; + if (result > 0 && af == AF_INET6 && scope_id) + { + using namespace std; // For strchr and atoi. + *scope_id = 0; + if (const char* if_name = strchr(src, '%')) + { + in6_addr_type* ipv6_address = static_cast(dest); + bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address); + if (is_link_local) + *scope_id = if_nametoindex(if_name + 1); + if (*scope_id == 0) + *scope_id = atoi(if_name + 1); + } + } + return result; +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +} + +inline int gethostname(char* name, int namelen, boost::system::error_code& ec) +{ + clear_error(ec); + int result = error_wrapper(::gethostname(name, namelen), ec); +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + if (result == 0) + clear_error(ec); +#endif + return result; +} + +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \ + || defined(__MACH__) && defined(__APPLE__) + +// The following functions are only needed for emulation of getaddrinfo and +// getnameinfo. + +inline boost::system::error_code translate_netdb_error(int error) +{ + switch (error) + { + case 0: + return boost::system::error_code(); + case HOST_NOT_FOUND: + return boost::asio::error::host_not_found; + case TRY_AGAIN: + return boost::asio::error::host_not_found_try_again; + case NO_RECOVERY: + return boost::asio::error::no_recovery; + case NO_DATA: + return boost::asio::error::no_data; + default: + BOOST_ASSERT(false); + return boost::asio::error::invalid_argument; + } +} + +inline hostent* gethostbyaddr(const char* addr, int length, int af, + hostent* result, char* buffer, int buflength, boost::system::error_code& ec) +{ + clear_error(ec); +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + (void)(buffer); + (void)(buflength); + hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec); + if (!retval) + return 0; +# if defined(UNDER_CE) + clear_error(ec); +# endif + *result = *retval; + return retval; +#elif defined(__sun) || defined(__QNX__) + int error = 0; + hostent* retval = error_wrapper(::gethostbyaddr_r(addr, length, af, result, + buffer, buflength, &error), ec); + if (error) + ec = translate_netdb_error(error); + return retval; +#elif defined(__MACH__) && defined(__APPLE__) + (void)(buffer); + (void)(buflength); + int error = 0; + hostent* retval = error_wrapper(::getipnodebyaddr( + addr, length, af, &error), ec); + if (error) + ec = translate_netdb_error(error); + if (!retval) + return 0; + *result = *retval; + return retval; +#else + hostent* retval = 0; + int error = 0; + error_wrapper(::gethostbyaddr_r(addr, length, af, result, buffer, + buflength, &retval, &error), ec); + if (error) + ec = translate_netdb_error(error); + return retval; +#endif +} + +inline hostent* gethostbyname(const char* name, int af, struct hostent* result, + char* buffer, int buflength, int ai_flags, boost::system::error_code& ec) +{ + clear_error(ec); +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + (void)(buffer); + (void)(buflength); + (void)(ai_flags); + if (af != AF_INET) + { + ec = boost::asio::error::address_family_not_supported; + return 0; + } + hostent* retval = error_wrapper(::gethostbyname(name), ec); + if (!retval) + return 0; +# if defined(UNDER_CE) + clear_error(ec); +# endif + *result = *retval; + return result; +#elif defined(__sun) || defined(__QNX__) + (void)(ai_flags); + if (af != AF_INET) + { + ec = boost::asio::error::address_family_not_supported; + return 0; + } + int error = 0; + hostent* retval = error_wrapper(::gethostbyname_r(name, result, buffer, + buflength, &error), ec); + if (error) + ec = translate_netdb_error(error); + return retval; +#elif defined(__MACH__) && defined(__APPLE__) + (void)(buffer); + (void)(buflength); + int error = 0; + hostent* retval = error_wrapper(::getipnodebyname( + name, af, ai_flags, &error), ec); + if (error) + ec = translate_netdb_error(error); + if (!retval) + return 0; + *result = *retval; + return retval; +#else + (void)(ai_flags); + if (af != AF_INET) + { + ec = boost::asio::error::address_family_not_supported; + return 0; + } + hostent* retval = 0; + int error = 0; + error_wrapper(::gethostbyname_r(name, result, + buffer, buflength, &retval, &error), ec); + if (error) + ec = translate_netdb_error(error); + return retval; +#endif +} + +inline void freehostent(hostent* h) +{ +#if defined(__MACH__) && defined(__APPLE__) + if (h) + ::freehostent(h); +#else + (void)(h); +#endif +} + +// Emulation of getaddrinfo based on implementation in: +// Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998. + +struct gai_search +{ + const char* host; + int family; +}; + +inline int gai_nsearch(const char* host, + const addrinfo_type* hints, gai_search (&search)[2]) +{ + int search_count = 0; + if (host == 0 || host[0] == '\0') + { + if (hints->ai_flags & AI_PASSIVE) + { + // No host and AI_PASSIVE implies wildcard bind. + switch (hints->ai_family) + { + case AF_INET: + search[search_count].host = "0.0.0.0"; + search[search_count].family = AF_INET; + ++search_count; + break; + case AF_INET6: + search[search_count].host = "0::0"; + search[search_count].family = AF_INET6; + ++search_count; + break; + case AF_UNSPEC: + search[search_count].host = "0::0"; + search[search_count].family = AF_INET6; + ++search_count; + search[search_count].host = "0.0.0.0"; + search[search_count].family = AF_INET; + ++search_count; + break; + default: + break; + } + } + else + { + // No host and not AI_PASSIVE means connect to local host. + switch (hints->ai_family) + { + case AF_INET: + search[search_count].host = "localhost"; + search[search_count].family = AF_INET; + ++search_count; + break; + case AF_INET6: + search[search_count].host = "localhost"; + search[search_count].family = AF_INET6; + ++search_count; + break; + case AF_UNSPEC: + search[search_count].host = "localhost"; + search[search_count].family = AF_INET6; + ++search_count; + search[search_count].host = "localhost"; + search[search_count].family = AF_INET; + ++search_count; + break; + default: + break; + } + } + } + else + { + // Host is specified. + switch (hints->ai_family) + { + case AF_INET: + search[search_count].host = host; + search[search_count].family = AF_INET; + ++search_count; + break; + case AF_INET6: + search[search_count].host = host; + search[search_count].family = AF_INET6; + ++search_count; + break; + case AF_UNSPEC: + search[search_count].host = host; + search[search_count].family = AF_INET6; + ++search_count; + search[search_count].host = host; + search[search_count].family = AF_INET; + ++search_count; + break; + default: + break; + } + } + return search_count; +} + +template +inline T* gai_alloc(std::size_t size = sizeof(T)) +{ + using namespace std; + T* p = static_cast(::operator new(size, std::nothrow)); + if (p) + memset(p, 0, size); + return p; +} + +inline void gai_free(void* p) +{ + ::operator delete(p); +} + +inline void gai_strcpy(char* target, const char* source, std::size_t max_size) +{ + using namespace std; +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE) + strcpy_s(target, max_size, source); +#else + *target = 0; + strncat(target, source, max_size); +#endif +} + +enum { gai_clone_flag = 1 << 30 }; + +inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints, + const void* addr, int family) +{ + using namespace std; + + addrinfo_type* ai = gai_alloc(); + if (ai == 0) + return EAI_MEMORY; + + ai->ai_next = 0; + **next = ai; + *next = &ai->ai_next; + + ai->ai_canonname = 0; + ai->ai_socktype = hints->ai_socktype; + if (ai->ai_socktype == 0) + ai->ai_flags |= gai_clone_flag; + ai->ai_protocol = hints->ai_protocol; + ai->ai_family = family; + + switch (ai->ai_family) + { + case AF_INET: + { + sockaddr_in4_type* sinptr = gai_alloc(); + if (sinptr == 0) + return EAI_MEMORY; + sinptr->sin_family = AF_INET; + memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type)); + ai->ai_addr = reinterpret_cast(sinptr); + ai->ai_addrlen = sizeof(sockaddr_in4_type); + break; + } + case AF_INET6: + { + sockaddr_in6_type* sin6ptr = gai_alloc(); + if (sin6ptr == 0) + return EAI_MEMORY; + sin6ptr->sin6_family = AF_INET6; + memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type)); + ai->ai_addr = reinterpret_cast(sin6ptr); + ai->ai_addrlen = sizeof(sockaddr_in6_type); + break; + } + default: + break; + } + + return 0; +} + +inline addrinfo_type* gai_clone(addrinfo_type* ai) +{ + using namespace std; + + addrinfo_type* new_ai = gai_alloc(); + if (new_ai == 0) + return new_ai; + + new_ai->ai_next = ai->ai_next; + ai->ai_next = new_ai; + + new_ai->ai_flags = 0; + new_ai->ai_family = ai->ai_family; + new_ai->ai_socktype = ai->ai_socktype; + new_ai->ai_protocol = ai->ai_protocol; + new_ai->ai_canonname = 0; + new_ai->ai_addrlen = ai->ai_addrlen; + new_ai->ai_addr = gai_alloc(ai->ai_addrlen); + memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen); + + return new_ai; +} + +inline int gai_port(addrinfo_type* aihead, int port, int socktype) +{ + int num_found = 0; + + for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next) + { + if (ai->ai_flags & gai_clone_flag) + { + if (ai->ai_socktype != 0) + { + ai = gai_clone(ai); + if (ai == 0) + return -1; + // ai now points to newly cloned entry. + } + } + else if (ai->ai_socktype != socktype) + { + // Ignore if mismatch on socket type. + continue; + } + + ai->ai_socktype = socktype; + + switch (ai->ai_family) + { + case AF_INET: + { + sockaddr_in4_type* sinptr = + reinterpret_cast(ai->ai_addr); + sinptr->sin_port = port; + ++num_found; + break; + } + case AF_INET6: + { + sockaddr_in6_type* sin6ptr = + reinterpret_cast(ai->ai_addr); + sin6ptr->sin6_port = port; + ++num_found; + break; + } + default: + break; + } + } + + return num_found; +} + +inline int gai_serv(addrinfo_type* aihead, + const addrinfo_type* hints, const char* serv) +{ + using namespace std; + + int num_found = 0; + + if ( +#if defined(AI_NUMERICSERV) + (hints->ai_flags & AI_NUMERICSERV) || +#endif + isdigit(serv[0])) + { + int port = htons(atoi(serv)); + if (hints->ai_socktype) + { + // Caller specifies socket type. + int rc = gai_port(aihead, port, hints->ai_socktype); + if (rc < 0) + return EAI_MEMORY; + num_found += rc; + } + else + { + // Caller does not specify socket type. + int rc = gai_port(aihead, port, SOCK_STREAM); + if (rc < 0) + return EAI_MEMORY; + num_found += rc; + rc = gai_port(aihead, port, SOCK_DGRAM); + if (rc < 0) + return EAI_MEMORY; + num_found += rc; + } + } + else + { + // Try service name with TCP first, then UDP. + if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM) + { + servent* sptr = getservbyname(serv, "tcp"); + if (sptr != 0) + { + int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM); + if (rc < 0) + return EAI_MEMORY; + num_found += rc; + } + } + if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM) + { + servent* sptr = getservbyname(serv, "udp"); + if (sptr != 0) + { + int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM); + if (rc < 0) + return EAI_MEMORY; + num_found += rc; + } + } + } + + if (num_found == 0) + { + if (hints->ai_socktype == 0) + { + // All calls to getservbyname() failed. + return EAI_NONAME; + } + else + { + // Service not supported for socket type. + return EAI_SERVICE; + } + } + + return 0; +} + +inline int gai_echeck(const char* host, const char* service, + int flags, int family, int socktype, int protocol) +{ + (void)(flags); + (void)(protocol); + + // Host or service must be specified. + if (host == 0 || host[0] == '\0') + if (service == 0 || service[0] == '\0') + return EAI_NONAME; + + // Check combination of family and socket type. + switch (family) + { + case AF_UNSPEC: + break; + case AF_INET: + case AF_INET6: + if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM) + return EAI_SOCKTYPE; + break; + default: + return EAI_FAMILY; + } + + return 0; +} + +inline void freeaddrinfo_emulation(addrinfo_type* aihead) +{ + addrinfo_type* ai = aihead; + while (ai) + { + gai_free(ai->ai_addr); + gai_free(ai->ai_canonname); + addrinfo_type* ainext = ai->ai_next; + gai_free(ai); + ai = ainext; + } +} + +inline int getaddrinfo_emulation(const char* host, const char* service, + const addrinfo_type* hintsp, addrinfo_type** result) +{ + // Set up linked list of addrinfo structures. + addrinfo_type* aihead = 0; + addrinfo_type** ainext = &aihead; + char* canon = 0; + + // Supply default hints if not specified by caller. + addrinfo_type hints = addrinfo_type(); + hints.ai_family = AF_UNSPEC; + if (hintsp) + hints = *hintsp; + + // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED + // and AI_ALL flags. +#if defined(AI_V4MAPPED) + if (hints.ai_family != AF_INET6) + hints.ai_flags &= ~AI_V4MAPPED; +#endif +#if defined(AI_ALL) + if (hints.ai_family != AF_INET6) + hints.ai_flags &= ~AI_ALL; +#endif + + // Basic error checking. + int rc = gai_echeck(host, service, hints.ai_flags, hints.ai_family, + hints.ai_socktype, hints.ai_protocol); + if (rc != 0) + { + freeaddrinfo_emulation(aihead); + return rc; + } + + gai_search search[2]; + int search_count = gai_nsearch(host, &hints, search); + for (gai_search* sptr = search; sptr < search + search_count; ++sptr) + { + // Check for IPv4 dotted decimal string. + in4_addr_type inaddr; + boost::system::error_code ec; + if (socket_ops::inet_pton(AF_INET, sptr->host, &inaddr, 0, ec) == 1) + { + if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET) + { + freeaddrinfo_emulation(aihead); + gai_free(canon); + return EAI_FAMILY; + } + if (sptr->family == AF_INET) + { + rc = gai_aistruct(&ainext, &hints, &inaddr, AF_INET); + if (rc != 0) + { + freeaddrinfo_emulation(aihead); + gai_free(canon); + return rc; + } + } + continue; + } + + // Check for IPv6 hex string. + in6_addr_type in6addr; + if (socket_ops::inet_pton(AF_INET6, sptr->host, &in6addr, 0, ec) == 1) + { + if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET6) + { + freeaddrinfo_emulation(aihead); + gai_free(canon); + return EAI_FAMILY; + } + if (sptr->family == AF_INET6) + { + rc = gai_aistruct(&ainext, &hints, &in6addr, AF_INET6); + if (rc != 0) + { + freeaddrinfo_emulation(aihead); + gai_free(canon); + return rc; + } + } + continue; + } + + // Look up hostname. + hostent hent; + char hbuf[8192] = ""; + hostent* hptr = socket_ops::gethostbyname(sptr->host, + sptr->family, &hent, hbuf, sizeof(hbuf), hints.ai_flags, ec); + if (hptr == 0) + { + if (search_count == 2) + { + // Failure is OK if there are multiple searches. + continue; + } + freeaddrinfo_emulation(aihead); + gai_free(canon); + if (ec == boost::asio::error::host_not_found) + return EAI_NONAME; + if (ec == boost::asio::error::host_not_found_try_again) + return EAI_AGAIN; + if (ec == boost::asio::error::no_recovery) + return EAI_FAIL; + if (ec == boost::asio::error::no_data) + return EAI_NONAME; + return EAI_NONAME; + } + + // Check for address family mismatch if one was specified. + if (hints.ai_family != AF_UNSPEC && hints.ai_family != hptr->h_addrtype) + { + freeaddrinfo_emulation(aihead); + gai_free(canon); + socket_ops::freehostent(hptr); + return EAI_FAMILY; + } + + // Save canonical name first time. + if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0] + && (hints.ai_flags & AI_CANONNAME) && canon == 0) + { + std::size_t canon_len = strlen(hptr->h_name) + 1; + canon = gai_alloc(canon_len); + if (canon == 0) + { + freeaddrinfo_emulation(aihead); + socket_ops::freehostent(hptr); + return EAI_MEMORY; + } + gai_strcpy(canon, hptr->h_name, canon_len); + } + + // Create an addrinfo structure for each returned address. + for (char** ap = hptr->h_addr_list; *ap; ++ap) + { + rc = gai_aistruct(&ainext, &hints, *ap, hptr->h_addrtype); + if (rc != 0) + { + freeaddrinfo_emulation(aihead); + gai_free(canon); + socket_ops::freehostent(hptr); + return EAI_FAMILY; + } + } + + socket_ops::freehostent(hptr); + } + + // Check if we found anything. + if (aihead == 0) + { + gai_free(canon); + return EAI_NONAME; + } + + // Return canonical name in first entry. + if (host != 0 && host[0] != '\0' && (hints.ai_flags & AI_CANONNAME)) + { + if (canon) + { + aihead->ai_canonname = canon; + canon = 0; + } + else + { + std::size_t canonname_len = strlen(search[0].host) + 1; + aihead->ai_canonname = gai_alloc(canonname_len); + if (aihead->ai_canonname == 0) + { + freeaddrinfo_emulation(aihead); + return EAI_MEMORY; + } + gai_strcpy(aihead->ai_canonname, search[0].host, canonname_len); + } + } + gai_free(canon); + + // Process the service name. + if (service != 0 && service[0] != '\0') + { + rc = gai_serv(aihead, &hints, service); + if (rc != 0) + { + freeaddrinfo_emulation(aihead); + return rc; + } + } + + // Return result to caller. + *result = aihead; + return 0; +} + +inline boost::system::error_code getnameinfo_emulation( + const socket_addr_type* sa, std::size_t salen, char* host, + std::size_t hostlen, char* serv, std::size_t servlen, int flags, + boost::system::error_code& ec) +{ + using namespace std; + + const char* addr; + size_t addr_len; + unsigned short port; + switch (sa->sa_family) + { + case AF_INET: + if (salen != sizeof(sockaddr_in4_type)) + { + return ec = boost::asio::error::invalid_argument; + } + addr = reinterpret_cast( + &reinterpret_cast(sa)->sin_addr); + addr_len = sizeof(in4_addr_type); + port = reinterpret_cast(sa)->sin_port; + break; + case AF_INET6: + if (salen != sizeof(sockaddr_in6_type)) + { + return ec = boost::asio::error::invalid_argument; + } + addr = reinterpret_cast( + &reinterpret_cast(sa)->sin6_addr); + addr_len = sizeof(in6_addr_type); + port = reinterpret_cast(sa)->sin6_port; + break; + default: + return ec = boost::asio::error::address_family_not_supported; + } + + if (host && hostlen > 0) + { + if (flags & NI_NUMERICHOST) + { + if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0) + { + return ec; + } + } + else + { + hostent hent; + char hbuf[8192] = ""; + hostent* hptr = socket_ops::gethostbyaddr(addr, + static_cast(addr_len), sa->sa_family, + &hent, hbuf, sizeof(hbuf), ec); + if (hptr && hptr->h_name && hptr->h_name[0] != '\0') + { + if (flags & NI_NOFQDN) + { + char* dot = strchr(hptr->h_name, '.'); + if (dot) + { + *dot = 0; + } + } + gai_strcpy(host, hptr->h_name, hostlen); + socket_ops::freehostent(hptr); + } + else + { + socket_ops::freehostent(hptr); + if (flags & NI_NAMEREQD) + { + return ec = boost::asio::error::host_not_found; + } + if (socket_ops::inet_ntop(sa->sa_family, + addr, host, hostlen, 0, ec) == 0) + { + return ec; + } + } + } + } + + if (serv && servlen > 0) + { + if (flags & NI_NUMERICSERV) + { + if (servlen < 6) + { + return ec = boost::asio::error::no_buffer_space; + } +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE) + sprintf_s(serv, servlen, "%u", ntohs(port)); +#else + sprintf(serv, "%u", ntohs(port)); +#endif + } + else + { +#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) + static ::pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + ::pthread_mutex_lock(&mutex); +#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) + servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0); + if (sptr && sptr->s_name && sptr->s_name[0] != '\0') + { + gai_strcpy(serv, sptr->s_name, servlen); + } + else + { + if (servlen < 6) + { + return ec = boost::asio::error::no_buffer_space; + } +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE) + sprintf_s(serv, servlen, "%u", ntohs(port)); +#else + sprintf(serv, "%u", ntohs(port)); +#endif + } +#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) + ::pthread_mutex_unlock(&mutex); +#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) + } + } + + clear_error(ec); + return ec; +} + +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + // || defined(__MACH__) && defined(__APPLE__) + +inline boost::system::error_code translate_addrinfo_error(int error) +{ + switch (error) + { + case 0: + return boost::system::error_code(); + case EAI_AGAIN: + return boost::asio::error::host_not_found_try_again; + case EAI_BADFLAGS: + return boost::asio::error::invalid_argument; + case EAI_FAIL: + return boost::asio::error::no_recovery; + case EAI_FAMILY: + return boost::asio::error::address_family_not_supported; + case EAI_MEMORY: + return boost::asio::error::no_memory; + case EAI_NONAME: +#if defined(EAI_ADDRFAMILY) + case EAI_ADDRFAMILY: +#endif +#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) + case EAI_NODATA: +#endif + return boost::asio::error::host_not_found; + case EAI_SERVICE: + return boost::asio::error::service_not_found; + case EAI_SOCKTYPE: + return boost::asio::error::socket_type_not_supported; + default: // Possibly the non-portable EAI_SYSTEM. +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + return boost::system::error_code( + WSAGetLastError(), boost::asio::error::get_system_category()); +#else + return boost::system::error_code( + errno, boost::asio::error::get_system_category()); +#endif + } +} + +inline boost::system::error_code getaddrinfo(const char* host, + const char* service, const addrinfo_type* hints, addrinfo_type** result, + boost::system::error_code& ec) +{ + clear_error(ec); +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE) + // Building for Windows XP, Windows Server 2003, or later. + int error = ::getaddrinfo(host, service, hints, result); + return ec = translate_addrinfo_error(error); +# else + // Building for Windows 2000 or earlier. + typedef int (WSAAPI *gai_t)(const char*, + const char*, const addrinfo_type*, addrinfo_type**); + if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) + { + if (gai_t gai = (gai_t)::GetProcAddress(winsock_module, "getaddrinfo")) + { + int error = gai(host, service, hints, result); + return ec = translate_addrinfo_error(error); + } + } + int error = getaddrinfo_emulation(host, service, hints, result); + return ec = translate_addrinfo_error(error); +# endif +#elif defined(__MACH__) && defined(__APPLE__) + int error = getaddrinfo_emulation(host, service, hints, result); + return ec = translate_addrinfo_error(error); +#else + int error = ::getaddrinfo(host, service, hints, result); + return ec = translate_addrinfo_error(error); +#endif +} + +inline void freeaddrinfo(addrinfo_type* ai) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE) + // Building for Windows XP, Windows Server 2003, or later. + ::freeaddrinfo(ai); +# else + // Building for Windows 2000 or earlier. + typedef int (WSAAPI *fai_t)(addrinfo_type*); + if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) + { + if (fai_t fai = (fai_t)::GetProcAddress(winsock_module, "freeaddrinfo")) + { + fai(ai); + return; + } + } + freeaddrinfo_emulation(ai); +# endif +#elif defined(__MACH__) && defined(__APPLE__) + freeaddrinfo_emulation(ai); +#else + ::freeaddrinfo(ai); +#endif +} + +inline boost::system::error_code getnameinfo(const socket_addr_type* addr, + std::size_t addrlen, char* host, std::size_t hostlen, + char* serv, std::size_t servlen, int flags, boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE) + // Building for Windows XP, Windows Server 2003, or later. + clear_error(ec); + int error = ::getnameinfo(addr, static_cast(addrlen), + host, static_cast(hostlen), + serv, static_cast(servlen), flags); + return ec = translate_addrinfo_error(error); +# else + // Building for Windows 2000 or earlier. + typedef int (WSAAPI *gni_t)(const socket_addr_type*, + int, char*, DWORD, char*, DWORD, int); + if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) + { + if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo")) + { + clear_error(ec); + int error = gni(addr, static_cast(addrlen), + host, static_cast(hostlen), + serv, static_cast(servlen), flags); + return ec = translate_addrinfo_error(error); + } + } + clear_error(ec); + return getnameinfo_emulation(addr, addrlen, + host, hostlen, serv, servlen, flags, ec); +# endif +#elif defined(__MACH__) && defined(__APPLE__) + using namespace std; // For memcpy. + sockaddr_storage_type tmp_addr; + memcpy(&tmp_addr, addr, addrlen); + tmp_addr.ss_len = addrlen; + addr = reinterpret_cast(&tmp_addr); + clear_error(ec); + return getnameinfo_emulation(addr, addrlen, + host, hostlen, serv, servlen, flags, ec); +#else + clear_error(ec); + int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags); + return ec = translate_addrinfo_error(error); +#endif +} + +inline u_long_type network_to_host_long(u_long_type value) +{ + return ntohl(value); +} + +inline u_long_type host_to_network_long(u_long_type value) +{ + return htonl(value); +} + +inline u_short_type network_to_host_short(u_short_type value) +{ + return ntohs(value); +} + +inline u_short_type host_to_network_short(u_short_type value) +{ + return htons(value); +} + +} // namespace socket_ops +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_HPP diff --git a/win32/include/boost/asio/detail/socket_option.hpp b/win32/include/boost/asio/detail/socket_option.hpp new file mode 100755 index 000000000..64bfeca08 --- /dev/null +++ b/win32/include/boost/asio/detail/socket_option.hpp @@ -0,0 +1,311 @@ +// +// socket_option.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SOCKET_OPTION_HPP +#define BOOST_ASIO_DETAIL_SOCKET_OPTION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { +namespace socket_option { + +// Helper template for implementing boolean-based options. +template +class boolean +{ +public: + // Default constructor. + boolean() + : value_(0) + { + } + + // Construct with a specific option value. + explicit boolean(bool v) + : value_(v ? 1 : 0) + { + } + + // Set the current value of the boolean. + boolean& operator=(bool v) + { + value_ = v ? 1 : 0; + return *this; + } + + // Get the current value of the boolean. + bool value() const + { + return !!value_; + } + + // Convert to bool. + operator bool() const + { + return !!value_; + } + + // Test for false. + bool operator!() const + { + return !value_; + } + + // Get the level of the socket option. + template + int level(const Protocol&) const + { + return Level; + } + + // Get the name of the socket option. + template + int name(const Protocol&) const + { + return Name; + } + + // Get the address of the boolean data. + template + int* data(const Protocol&) + { + return &value_; + } + + // Get the address of the boolean data. + template + const int* data(const Protocol&) const + { + return &value_; + } + + // Get the size of the boolean data. + template + std::size_t size(const Protocol&) const + { + return sizeof(value_); + } + + // Set the size of the boolean data. + template + void resize(const Protocol&, std::size_t s) + { + // On some platforms (e.g. Windows Vista), the getsockopt function will + // return the size of a boolean socket option as one byte, even though a + // four byte integer was passed in. + switch (s) + { + case sizeof(char): + value_ = *reinterpret_cast(&value_) ? 1 : 0; + break; + case sizeof(value_): + break; + default: + throw std::length_error("boolean socket option resize"); + } + } + +private: + int value_; +}; + +// Helper template for implementing integer options. +template +class integer +{ +public: + // Default constructor. + integer() + : value_(0) + { + } + + // Construct with a specific option value. + explicit integer(int v) + : value_(v) + { + } + + // Set the value of the int option. + integer& operator=(int v) + { + value_ = v; + return *this; + } + + // Get the current value of the int option. + int value() const + { + return value_; + } + + // Get the level of the socket option. + template + int level(const Protocol&) const + { + return Level; + } + + // Get the name of the socket option. + template + int name(const Protocol&) const + { + return Name; + } + + // Get the address of the int data. + template + int* data(const Protocol&) + { + return &value_; + } + + // Get the address of the int data. + template + const int* data(const Protocol&) const + { + return &value_; + } + + // Get the size of the int data. + template + std::size_t size(const Protocol&) const + { + return sizeof(value_); + } + + // Set the size of the int data. + template + void resize(const Protocol&, std::size_t s) + { + if (s != sizeof(value_)) + throw std::length_error("integer socket option resize"); + } + +private: + int value_; +}; + +// Helper template for implementing linger options. +template +class linger +{ +public: + // Default constructor. + linger() + { + value_.l_onoff = 0; + value_.l_linger = 0; + } + + // Construct with specific option values. + linger(bool e, int t) + { + enabled(e); + timeout(t); + } + + // Set the value for whether linger is enabled. + void enabled(bool value) + { + value_.l_onoff = value ? 1 : 0; + } + + // Get the value for whether linger is enabled. + bool enabled() const + { + return value_.l_onoff != 0; + } + + // Set the value for the linger timeout. + void timeout(int value) + { +#if defined(WIN32) + value_.l_linger = static_cast(value); +#else + value_.l_linger = value; +#endif + } + + // Get the value for the linger timeout. + int timeout() const + { + return static_cast(value_.l_linger); + } + + // Get the level of the socket option. + template + int level(const Protocol&) const + { + return Level; + } + + // Get the name of the socket option. + template + int name(const Protocol&) const + { + return Name; + } + + // Get the address of the linger data. + template + ::linger* data(const Protocol&) + { + return &value_; + } + + // Get the address of the linger data. + template + const ::linger* data(const Protocol&) const + { + return &value_; + } + + // Get the size of the linger data. + template + std::size_t size(const Protocol&) const + { + return sizeof(value_); + } + + // Set the size of the int data. + template + void resize(const Protocol&, std::size_t s) + { + if (s != sizeof(value_)) + throw std::length_error("linger socket option resize"); + } + +private: + ::linger value_; +}; + +} // namespace socket_option +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SOCKET_OPTION_HPP diff --git a/win32/include/boost/asio/detail/socket_select_interrupter.hpp b/win32/include/boost/asio/detail/socket_select_interrupter.hpp new file mode 100755 index 000000000..4a7b22592 --- /dev/null +++ b/win32/include/boost/asio/detail/socket_select_interrupter.hpp @@ -0,0 +1,189 @@ +// +// socket_select_interrupter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP +#define BOOST_ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +class socket_select_interrupter +{ +public: + // Constructor. + socket_select_interrupter() + { + boost::system::error_code ec; + socket_holder acceptor(socket_ops::socket( + AF_INET, SOCK_STREAM, IPPROTO_TCP, ec)); + if (acceptor.get() == invalid_socket) + { + boost::system::system_error e(ec, "socket_select_interrupter"); + boost::throw_exception(e); + } + + int opt = 1; + socket_ops::setsockopt(acceptor.get(), + SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt), ec); + + using namespace std; // For memset. + sockaddr_in4_type addr; + std::size_t addr_len = sizeof(addr); + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + addr.sin_port = 0; + if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr, + addr_len, ec) == socket_error_retval) + { + boost::system::system_error e(ec, "socket_select_interrupter"); + boost::throw_exception(e); + } + + if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr, + &addr_len, ec) == socket_error_retval) + { + boost::system::system_error e(ec, "socket_select_interrupter"); + boost::throw_exception(e); + } + + if (socket_ops::listen(acceptor.get(), + SOMAXCONN, ec) == socket_error_retval) + { + boost::system::system_error e(ec, "socket_select_interrupter"); + boost::throw_exception(e); + } + + socket_holder client(socket_ops::socket( + AF_INET, SOCK_STREAM, IPPROTO_TCP, ec)); + if (client.get() == invalid_socket) + { + boost::system::system_error e(ec, "socket_select_interrupter"); + boost::throw_exception(e); + } + + if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr, + addr_len, ec) == socket_error_retval) + { + boost::system::system_error e(ec, "socket_select_interrupter"); + boost::throw_exception(e); + } + + socket_holder server(socket_ops::accept(acceptor.get(), 0, 0, ec)); + if (server.get() == invalid_socket) + { + boost::system::system_error e(ec, "socket_select_interrupter"); + boost::throw_exception(e); + } + + ioctl_arg_type non_blocking = 1; + if (socket_ops::ioctl(client.get(), FIONBIO, &non_blocking, ec)) + { + boost::system::system_error e(ec, "socket_select_interrupter"); + boost::throw_exception(e); + } + + opt = 1; + socket_ops::setsockopt(client.get(), + IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec); + + non_blocking = 1; + if (socket_ops::ioctl(server.get(), FIONBIO, &non_blocking, ec)) + { + boost::system::system_error e(ec, "socket_select_interrupter"); + boost::throw_exception(e); + } + + opt = 1; + socket_ops::setsockopt(server.get(), + IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec); + + read_descriptor_ = server.release(); + write_descriptor_ = client.release(); + } + + // Destructor. + ~socket_select_interrupter() + { + boost::system::error_code ec; + if (read_descriptor_ != invalid_socket) + socket_ops::close(read_descriptor_, ec); + if (write_descriptor_ != invalid_socket) + socket_ops::close(write_descriptor_, ec); + } + + // Interrupt the select call. + void interrupt() + { + char byte = 0; + socket_ops::buf b; + socket_ops::init_buf(b, &byte, 1); + boost::system::error_code ec; + socket_ops::send(write_descriptor_, &b, 1, 0, ec); + } + + // Reset the select interrupt. Returns true if the call was interrupted. + bool reset() + { + char data[1024]; + socket_ops::buf b; + socket_ops::init_buf(b, data, sizeof(data)); + boost::system::error_code ec; + int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec); + bool was_interrupted = (bytes_read > 0); + while (bytes_read == sizeof(data)) + bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec); + return was_interrupted; + } + + // Get the read descriptor to be passed to select. + socket_type read_descriptor() const + { + return read_descriptor_; + } + +private: + // The read end of a connection used to interrupt the select call. This file + // descriptor is passed to select such that when it is time to stop, a single + // byte will be written on the other end of the connection and this + // descriptor will become readable. + socket_type read_descriptor_; + + // The write end of a connection used to interrupt the select call. A single + // byte may be written to this to wake up the select which is waiting for the + // other end to become readable. + socket_type write_descriptor_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP diff --git a/win32/include/boost/asio/detail/socket_types.hpp b/win32/include/boost/asio/detail/socket_types.hpp new file mode 100755 index 000000000..3562d9d8c --- /dev/null +++ b/win32/include/boost/asio/detail/socket_types.hpp @@ -0,0 +1,208 @@ +// +// socket_types.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SOCKET_TYPES_HPP +#define BOOST_ASIO_DETAIL_SOCKET_TYPES_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +# if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_) +# error WinSock.h has already been included +# endif // defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_) +# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) +# if defined(_MSC_VER) || defined(__BORLANDC__) +# pragma message("Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately") +# pragma message("Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target)") +# else // defined(_MSC_VER) || defined(__BORLANDC__) +# warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately +# warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target) +# endif // defined(_MSC_VER) || defined(__BORLANDC__) +# define _WIN32_WINNT 0x0501 +# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) +# if defined(_MSC_VER) +# if defined(_WIN32) && !defined(WIN32) +# if !defined(_WINSOCK2API_) +# define WIN32 // Needed for correct types in winsock2.h +# else // !defined(_WINSOCK2API_) +# error Please define the macro WIN32 in your compiler options +# endif // !defined(_WINSOCK2API_) +# endif // defined(_WIN32) && !defined(WIN32) +# endif // defined(_MSC_VER) +# if defined(__BORLANDC__) +# include // Needed for __errno +# if defined(__WIN32__) && !defined(WIN32) +# if !defined(_WINSOCK2API_) +# define WIN32 // Needed for correct types in winsock2.h +# else // !defined(_WINSOCK2API_) +# error Please define the macro WIN32 in your compiler options +# endif // !defined(_WINSOCK2API_) +# endif // defined(__WIN32__) && !defined(WIN32) +# if !defined(_WSPIAPI_H_) +# define _WSPIAPI_H_ +# define BOOST_ASIO_WSPIAPI_H_DEFINED +# endif // !defined(_WSPIAPI_H_) +# endif // defined(__BORLANDC__) +# if !defined(BOOST_ASIO_NO_WIN32_LEAN_AND_MEAN) +# if !defined(WIN32_LEAN_AND_MEAN) +# define WIN32_LEAN_AND_MEAN +# endif // !defined(WIN32_LEAN_AND_MEAN) +# endif // !defined(BOOST_ASIO_NO_WIN32_LEAN_AND_MEAN) +# if defined(__CYGWIN__) +# if !defined(__USE_W32_SOCKETS) +# error You must add -D__USE_W32_SOCKETS to your compiler options. +# endif // !defined(__USE_W32_SOCKETS) +# if !defined(NOMINMAX) +# define NOMINMAX 1 +# endif // !defined(NOMINMAX) +# endif // defined(__CYGWIN__) +# include +# include +# include +# if defined(BOOST_ASIO_WSPIAPI_H_DEFINED) +# undef _WSPIAPI_H_ +# undef BOOST_ASIO_WSPIAPI_H_DEFINED +# endif // defined(BOOST_ASIO_WSPIAPI_H_DEFINED) +# if !defined(BOOST_ASIO_NO_DEFAULT_LINKED_LIBS) +# if defined(UNDER_CE) +# pragma comment(lib, "ws2.lib") +# elif defined(_MSC_VER) || defined(__BORLANDC__) +# pragma comment(lib, "ws2_32.lib") +# pragma comment(lib, "mswsock.lib") +# endif // defined(_MSC_VER) || defined(__BORLANDC__) +# endif // !defined(BOOST_ASIO_NO_DEFAULT_LINKED_LIBS) +# include +#else +# include +# include +# include +# if defined(__hpux) && !defined(__HP_aCC) +# include +# else +# include +# endif +# include +# include +# include +# include +# include +# include +# include +# include +# include +# if defined(__sun) +# include +# include +# endif +#endif +#include + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +typedef SOCKET socket_type; +const SOCKET invalid_socket = INVALID_SOCKET; +const int socket_error_retval = SOCKET_ERROR; +const int max_addr_v4_str_len = 256; +const int max_addr_v6_str_len = 256; +typedef sockaddr socket_addr_type; +typedef in_addr in4_addr_type; +typedef ip_mreq in4_mreq_type; +typedef sockaddr_in sockaddr_in4_type; +# if defined(BOOST_ASIO_HAS_OLD_WIN_SDK) +typedef in6_addr_emulation in6_addr_type; +typedef ipv6_mreq_emulation in6_mreq_type; +typedef sockaddr_in6_emulation sockaddr_in6_type; +typedef sockaddr_storage_emulation sockaddr_storage_type; +typedef addrinfo_emulation addrinfo_type; +# else +typedef in6_addr in6_addr_type; +typedef ipv6_mreq in6_mreq_type; +typedef sockaddr_in6 sockaddr_in6_type; +typedef sockaddr_storage sockaddr_storage_type; +typedef addrinfo addrinfo_type; +# endif +typedef unsigned long ioctl_arg_type; +typedef u_long u_long_type; +typedef u_short u_short_type; +const int shutdown_receive = SD_RECEIVE; +const int shutdown_send = SD_SEND; +const int shutdown_both = SD_BOTH; +const int message_peek = MSG_PEEK; +const int message_out_of_band = MSG_OOB; +const int message_do_not_route = MSG_DONTROUTE; +# if defined (_WIN32_WINNT) +const int max_iov_len = 64; +# else +const int max_iov_len = 16; +# endif +#else +typedef int socket_type; +const int invalid_socket = -1; +const int socket_error_retval = -1; +const int max_addr_v4_str_len = INET_ADDRSTRLEN; +const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; +typedef sockaddr socket_addr_type; +typedef in_addr in4_addr_type; +# if defined(__hpux) +// HP-UX doesn't provide ip_mreq when _XOPEN_SOURCE_EXTENDED is defined. +struct in4_mreq_type +{ + struct in_addr imr_multiaddr; + struct in_addr imr_interface; +}; +# else +typedef ip_mreq in4_mreq_type; +# endif +typedef sockaddr_in sockaddr_in4_type; +typedef in6_addr in6_addr_type; +typedef ipv6_mreq in6_mreq_type; +typedef sockaddr_in6 sockaddr_in6_type; +typedef sockaddr_storage sockaddr_storage_type; +typedef sockaddr_un sockaddr_un_type; +typedef addrinfo addrinfo_type; +typedef int ioctl_arg_type; +typedef uint32_t u_long_type; +typedef uint16_t u_short_type; +const int shutdown_receive = SHUT_RD; +const int shutdown_send = SHUT_WR; +const int shutdown_both = SHUT_RDWR; +const int message_peek = MSG_PEEK; +const int message_out_of_band = MSG_OOB; +const int message_do_not_route = MSG_DONTROUTE; +# if defined(IOV_MAX) +const int max_iov_len = IOV_MAX; +# else +// POSIX platforms are not required to define IOV_MAX. +const int max_iov_len = 16; +# endif +#endif +const int custom_socket_option_level = 0xA5100000; +const int enable_connection_aborted_option = 1; +const int always_fail_option = 2; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_SOCKET_TYPES_HPP diff --git a/win32/include/boost/asio/detail/strand_service.hpp b/win32/include/boost/asio/detail/strand_service.hpp new file mode 100755 index 000000000..2c6614fec --- /dev/null +++ b/win32/include/boost/asio/detail/strand_service.hpp @@ -0,0 +1,532 @@ +// +// strand_service.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_STRAND_SERVICE_HPP +#define BOOST_ASIO_DETAIL_STRAND_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +// Default service implementation for a strand. +class strand_service + : public boost::asio::detail::service_base +{ +public: + class handler_base; + class invoke_current_handler; + class post_next_waiter_on_exit; + + // The underlying implementation of a strand. + class strand_impl + { +#if defined (__BORLANDC__) + public: +#else + private: +#endif + void add_ref() + { + ++ref_count_; + } + + void release() + { + if (--ref_count_ == 0) + delete this; + } + + private: + // Only this service will have access to the internal values. + friend class strand_service; + friend class post_next_waiter_on_exit; + friend class invoke_current_handler; + + strand_impl(strand_service& owner) + : owner_(owner), + current_handler_(0), + first_waiter_(0), + last_waiter_(0), + ref_count_(0) + { + // Insert implementation into linked list of all implementations. + boost::asio::detail::mutex::scoped_lock lock(owner_.mutex_); + next_ = owner_.impl_list_; + prev_ = 0; + if (owner_.impl_list_) + owner_.impl_list_->prev_ = this; + owner_.impl_list_ = this; + } + + ~strand_impl() + { + // Remove implementation from linked list of all implementations. + boost::asio::detail::mutex::scoped_lock lock(owner_.mutex_); + if (owner_.impl_list_ == this) + owner_.impl_list_ = next_; + if (prev_) + prev_->next_ = next_; + if (next_) + next_->prev_= prev_; + next_ = 0; + prev_ = 0; + lock.unlock(); + + if (current_handler_) + { + current_handler_->destroy(); + } + + while (first_waiter_) + { + handler_base* next = first_waiter_->next_; + first_waiter_->destroy(); + first_waiter_ = next; + } + } + + // Mutex to protect access to internal data. + boost::asio::detail::mutex mutex_; + + // The service that owns this implementation. + strand_service& owner_; + + // The handler that is ready to execute. If this pointer is non-null then it + // indicates that a handler holds the lock. + handler_base* current_handler_; + + // The start of the list of waiting handlers for the strand. + handler_base* first_waiter_; + + // The end of the list of waiting handlers for the strand. + handler_base* last_waiter_; + + // Storage for posted handlers. + typedef boost::aligned_storage<128> handler_storage_type; +#if defined(__BORLANDC__) + boost::aligned_storage<128> handler_storage_; +#else + handler_storage_type handler_storage_; +#endif + + // Pointers to adjacent socket implementations in linked list. + strand_impl* next_; + strand_impl* prev_; + + // The reference count on the strand implementation. + boost::detail::atomic_count ref_count_; + +#if !defined(__BORLANDC__) + friend void intrusive_ptr_add_ref(strand_impl* p) + { + p->add_ref(); + } + + friend void intrusive_ptr_release(strand_impl* p) + { + p->release(); + } +#endif + }; + + friend class strand_impl; + + typedef boost::intrusive_ptr implementation_type; + + // Base class for all handler types. + class handler_base + { + public: + typedef void (*invoke_func_type)(handler_base*, + strand_service&, implementation_type&); + typedef void (*destroy_func_type)(handler_base*); + + handler_base(invoke_func_type invoke_func, destroy_func_type destroy_func) + : next_(0), + invoke_func_(invoke_func), + destroy_func_(destroy_func) + { + } + + void invoke(strand_service& service_impl, implementation_type& impl) + { + invoke_func_(this, service_impl, impl); + } + + void destroy() + { + destroy_func_(this); + } + + protected: + ~handler_base() + { + } + + private: + friend class strand_service; + friend class strand_impl; + friend class post_next_waiter_on_exit; + handler_base* next_; + invoke_func_type invoke_func_; + destroy_func_type destroy_func_; + }; + + // Helper class to allow handlers to be dispatched. + class invoke_current_handler + { + public: + invoke_current_handler(strand_service& service_impl, + const implementation_type& impl) + : service_impl_(service_impl), + impl_(impl) + { + } + + void operator()() + { + impl_->current_handler_->invoke(service_impl_, impl_); + } + + friend void* asio_handler_allocate(std::size_t size, + invoke_current_handler* this_handler) + { + return this_handler->do_handler_allocate(size); + } + + friend void asio_handler_deallocate(void*, std::size_t, + invoke_current_handler*) + { + } + + void* do_handler_allocate(std::size_t size) + { +#if defined(__BORLANDC__) + BOOST_ASSERT(size <= boost::aligned_storage<128>::size); +#else + BOOST_ASSERT(size <= strand_impl::handler_storage_type::size); +#endif + (void)size; + return impl_->handler_storage_.address(); + } + + // The asio_handler_invoke hook is not defined here since the default one + // provides the correct behaviour, and including it here breaks MSVC 7.1 + // in some situations. + + private: + strand_service& service_impl_; + implementation_type impl_; + }; + + // Helper class to automatically enqueue next waiter on block exit. + class post_next_waiter_on_exit + { + public: + post_next_waiter_on_exit(strand_service& service_impl, + implementation_type& impl) + : service_impl_(service_impl), + impl_(impl), + cancelled_(false) + { + } + + ~post_next_waiter_on_exit() + { + if (!cancelled_) + { + boost::asio::detail::mutex::scoped_lock lock(impl_->mutex_); + impl_->current_handler_ = impl_->first_waiter_; + if (impl_->current_handler_) + { + impl_->first_waiter_ = impl_->first_waiter_->next_; + if (impl_->first_waiter_ == 0) + impl_->last_waiter_ = 0; + lock.unlock(); + service_impl_.get_io_service().post( + invoke_current_handler(service_impl_, impl_)); + } + } + } + + void cancel() + { + cancelled_ = true; + } + + private: + strand_service& service_impl_; + implementation_type& impl_; + bool cancelled_; + }; + + // Class template for a waiter. + template + class handler_wrapper + : public handler_base + { + public: + handler_wrapper(Handler handler) + : handler_base(&handler_wrapper::do_invoke, + &handler_wrapper::do_destroy), + handler_(handler) + { + } + + static void do_invoke(handler_base* base, + strand_service& service_impl, implementation_type& impl) + { + // Take ownership of the handler object. + typedef handler_wrapper this_type; + this_type* h(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(h->handler_, h); + + post_next_waiter_on_exit p1(service_impl, impl); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(h->handler_); + + // A handler object must still be valid when the next waiter is posted + // since destroying the last handler might cause the strand object to be + // destroyed. Therefore we create a second post_next_waiter_on_exit object + // that will be destroyed before the handler object. + p1.cancel(); + post_next_waiter_on_exit p2(service_impl, impl); + + // Free the memory associated with the handler. + ptr.reset(); + + // Indicate that this strand is executing on the current thread. + call_stack::context ctx(impl.get()); + + // Make the upcall. + boost_asio_handler_invoke_helpers::invoke(handler, &handler); + } + + static void do_destroy(handler_base* base) + { + // Take ownership of the handler object. + typedef handler_wrapper this_type; + this_type* h(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(h->handler_, h); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(h->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + private: + Handler handler_; + }; + + // Construct a new strand service for the specified io_service. + explicit strand_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + mutex_(), + impl_list_(0) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + // Construct a list of all handlers to be destroyed. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + strand_impl* impl = impl_list_; + handler_base* first_handler = 0; + while (impl) + { + if (impl->current_handler_) + { + impl->current_handler_->next_ = first_handler; + first_handler = impl->current_handler_; + impl->current_handler_ = 0; + } + if (impl->first_waiter_) + { + impl->last_waiter_->next_ = first_handler; + first_handler = impl->first_waiter_; + impl->first_waiter_ = 0; + impl->last_waiter_ = 0; + } + impl = impl->next_; + } + + // Destroy all handlers without holding the lock. + lock.unlock(); + while (first_handler) + { + handler_base* next = first_handler->next_; + first_handler->destroy(); + first_handler = next; + } + } + + // Construct a new strand implementation. + void construct(implementation_type& impl) + { + impl = implementation_type(new strand_impl(*this)); + } + + // Destroy a strand implementation. + void destroy(implementation_type& impl) + { + implementation_type().swap(impl); + } + + // Request the io_service to invoke the given handler. + template + void dispatch(implementation_type& impl, Handler handler) + { + if (call_stack::contains(impl.get())) + { + boost_asio_handler_invoke_helpers::invoke(handler, &handler); + } + else + { + // Allocate and construct an object to wrap the handler. + typedef handler_wrapper value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + handler_ptr ptr(raw_ptr, handler); + + boost::asio::detail::mutex::scoped_lock lock(impl->mutex_); + + if (impl->current_handler_ == 0) + { + // This handler now has the lock, so can be dispatched immediately. + impl->current_handler_ = ptr.release(); + lock.unlock(); + this->get_io_service().dispatch(invoke_current_handler(*this, impl)); + } + else + { + // Another handler already holds the lock, so this handler must join + // the list of waiters. The handler will be posted automatically when + // its turn comes. + if (impl->last_waiter_) + { + impl->last_waiter_->next_ = ptr.get(); + impl->last_waiter_ = impl->last_waiter_->next_; + } + else + { + impl->first_waiter_ = ptr.get(); + impl->last_waiter_ = ptr.get(); + } + ptr.release(); + } + } + } + + // Request the io_service to invoke the given handler and return immediately. + template + void post(implementation_type& impl, Handler handler) + { + // Allocate and construct an object to wrap the handler. + typedef handler_wrapper value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + handler_ptr ptr(raw_ptr, handler); + + boost::asio::detail::mutex::scoped_lock lock(impl->mutex_); + + if (impl->current_handler_ == 0) + { + // This handler now has the lock, so can be dispatched immediately. + impl->current_handler_ = ptr.release(); + lock.unlock(); + this->get_io_service().post(invoke_current_handler(*this, impl)); + } + else + { + // Another handler already holds the lock, so this handler must join the + // list of waiters. The handler will be posted automatically when its turn + // comes. + if (impl->last_waiter_) + { + impl->last_waiter_->next_ = ptr.get(); + impl->last_waiter_ = impl->last_waiter_->next_; + } + else + { + impl->first_waiter_ = ptr.get(); + impl->last_waiter_ = ptr.get(); + } + ptr.release(); + } + } + +private: + // Mutex to protect access to the linked list of implementations. + boost::asio::detail::mutex mutex_; + + // The head of a linked list of all implementations. + strand_impl* impl_list_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#if defined(__BORLANDC__) + +namespace boost { + +inline void intrusive_ptr_add_ref( + boost::asio::detail::strand_service::strand_impl* p) +{ + p->add_ref(); +} + +inline void intrusive_ptr_release( + boost::asio::detail::strand_service::strand_impl* p) +{ + p->release(); +} + +} // namespace boost + +#endif // defined(__BORLANDC__) + +#include + +#endif // BOOST_ASIO_DETAIL_STRAND_SERVICE_HPP diff --git a/win32/include/boost/asio/detail/task_io_service.hpp b/win32/include/boost/asio/detail/task_io_service.hpp new file mode 100755 index 000000000..e16ab04c2 --- /dev/null +++ b/win32/include/boost/asio/detail/task_io_service.hpp @@ -0,0 +1,427 @@ +// +// task_io_service.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_TASK_IO_SERVICE_HPP +#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#if defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE) +#include +#else // defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class task_io_service + : public boost::asio::detail::service_base > +{ +public: + // Constructor. + task_io_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base >(io_service), + mutex_(), + task_(use_service(io_service)), + task_interrupted_(true), + outstanding_work_(0), + stopped_(false), + shutdown_(false), + first_idle_thread_(0) + { + handler_queue_.push(&task_handler_); + } + + void init(size_t /*concurrency_hint*/) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + shutdown_ = true; + lock.unlock(); + + // Destroy handler objects. + while (!handler_queue_.empty()) + { + handler_queue::handler* h = handler_queue_.front(); + handler_queue_.pop(); + if (h != &task_handler_) + h->destroy(); + } + + // Reset handler queue to initial state. + handler_queue_.push(&task_handler_); + } + + // Run the event loop until interrupted or no more work. + size_t run(boost::system::error_code& ec) + { + typename call_stack::context ctx(this); + + idle_thread_info this_idle_thread; + this_idle_thread.next = 0; + + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + size_t n = 0; + while (do_one(lock, &this_idle_thread, ec)) + if (n != (std::numeric_limits::max)()) + ++n; + return n; + } + + // Run until interrupted or one operation is performed. + size_t run_one(boost::system::error_code& ec) + { + typename call_stack::context ctx(this); + + idle_thread_info this_idle_thread; + this_idle_thread.next = 0; + + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + return do_one(lock, &this_idle_thread, ec); + } + + // Poll for operations without blocking. + size_t poll(boost::system::error_code& ec) + { + typename call_stack::context ctx(this); + + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + size_t n = 0; + while (do_one(lock, 0, ec)) + if (n != (std::numeric_limits::max)()) + ++n; + return n; + } + + // Poll for one operation without blocking. + size_t poll_one(boost::system::error_code& ec) + { + typename call_stack::context ctx(this); + + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + return do_one(lock, 0, ec); + } + + // Interrupt the event processing loop. + void stop() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + stop_all_threads(lock); + } + + // Reset in preparation for a subsequent run invocation. + void reset() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + stopped_ = false; + } + + // Notify that some work has started. + void work_started() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + ++outstanding_work_; + } + + // Notify that some work has finished. + void work_finished() + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (--outstanding_work_ == 0) + stop_all_threads(lock); + } + + // Request invocation of the given handler. + template + void dispatch(Handler handler) + { + if (call_stack::contains(this)) + boost_asio_handler_invoke_helpers::invoke(handler, &handler); + else + post(handler); + } + + // Request invocation of the given handler and return immediately. + template + void post(Handler handler) + { + // Allocate and construct an operation to wrap the handler. + handler_queue::scoped_ptr ptr(handler_queue::wrap(handler)); + + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // If the service has been shut down we silently discard the handler. + if (shutdown_) + return; + + // Add the handler to the end of the queue. + handler_queue_.push(ptr.get()); + ptr.release(); + + // An undelivered handler is treated as unfinished work. + ++outstanding_work_; + + // Wake up a thread to execute the handler. + if (!interrupt_one_idle_thread(lock)) + { + if (!task_interrupted_) + { + task_interrupted_ = true; + task_.interrupt(); + } + } + } + +private: + struct idle_thread_info; + + size_t do_one(boost::asio::detail::mutex::scoped_lock& lock, + idle_thread_info* this_idle_thread, boost::system::error_code& ec) + { + if (outstanding_work_ == 0 && !stopped_) + { + stop_all_threads(lock); + ec = boost::system::error_code(); + return 0; + } + + bool polling = !this_idle_thread; + bool task_has_run = false; + while (!stopped_) + { + if (!handler_queue_.empty()) + { + // Prepare to execute first handler from queue. + handler_queue::handler* h = handler_queue_.front(); + handler_queue_.pop(); + + if (h == &task_handler_) + { + bool more_handlers = (!handler_queue_.empty()); + task_interrupted_ = more_handlers || polling; + + // If the task has already run and we're polling then we're done. + if (task_has_run && polling) + { + task_interrupted_ = true; + handler_queue_.push(&task_handler_); + ec = boost::system::error_code(); + return 0; + } + task_has_run = true; + + lock.unlock(); + task_cleanup c(lock, *this); + + // Run the task. May throw an exception. Only block if the handler + // queue is empty and we have an idle_thread_info object, otherwise + // we want to return as soon as possible. + task_.run(!more_handlers && !polling); + } + else + { + lock.unlock(); + handler_cleanup c(lock, *this); + + // Invoke the handler. May throw an exception. + h->invoke(); // invoke() deletes the handler object + + ec = boost::system::error_code(); + return 1; + } + } + else if (this_idle_thread) + { + // Nothing to run right now, so just wait for work to do. + this_idle_thread->next = first_idle_thread_; + first_idle_thread_ = this_idle_thread; + this_idle_thread->wakeup_event.clear(lock); + this_idle_thread->wakeup_event.wait(lock); + } + else + { + ec = boost::system::error_code(); + return 0; + } + } + + ec = boost::system::error_code(); + return 0; + } + + // Stop the task and all idle threads. + void stop_all_threads( + boost::asio::detail::mutex::scoped_lock& lock) + { + stopped_ = true; + interrupt_all_idle_threads(lock); + if (!task_interrupted_) + { + task_interrupted_ = true; + task_.interrupt(); + } + } + + // Interrupt a single idle thread. Returns true if a thread was interrupted, + // false if no running thread could be found to interrupt. + bool interrupt_one_idle_thread( + boost::asio::detail::mutex::scoped_lock& lock) + { + if (first_idle_thread_) + { + idle_thread_info* idle_thread = first_idle_thread_; + first_idle_thread_ = idle_thread->next; + idle_thread->next = 0; + idle_thread->wakeup_event.signal(lock); + return true; + } + return false; + } + + // Interrupt all idle threads. + void interrupt_all_idle_threads( + boost::asio::detail::mutex::scoped_lock& lock) + { + while (first_idle_thread_) + { + idle_thread_info* idle_thread = first_idle_thread_; + first_idle_thread_ = idle_thread->next; + idle_thread->next = 0; + idle_thread->wakeup_event.signal(lock); + } + } + + // Helper class to perform task-related operations on block exit. + class task_cleanup; + friend class task_cleanup; + class task_cleanup + { + public: + task_cleanup(boost::asio::detail::mutex::scoped_lock& lock, + task_io_service& task_io_svc) + : lock_(lock), + task_io_service_(task_io_svc) + { + } + + ~task_cleanup() + { + // Reinsert the task at the end of the handler queue. + lock_.lock(); + task_io_service_.task_interrupted_ = true; + task_io_service_.handler_queue_.push(&task_io_service_.task_handler_); + } + + private: + boost::asio::detail::mutex::scoped_lock& lock_; + task_io_service& task_io_service_; + }; + + // Helper class to perform handler-related operations on block exit. + class handler_cleanup; + friend class handler_cleanup; + class handler_cleanup + { + public: + handler_cleanup(boost::asio::detail::mutex::scoped_lock& lock, + task_io_service& task_io_svc) + : lock_(lock), + task_io_service_(task_io_svc) + { + } + + ~handler_cleanup() + { + lock_.lock(); + if (--task_io_service_.outstanding_work_ == 0) + task_io_service_.stop_all_threads(lock_); + } + + private: + boost::asio::detail::mutex::scoped_lock& lock_; + task_io_service& task_io_service_; + }; + + // Mutex to protect access to internal data. + boost::asio::detail::mutex mutex_; + + // The task to be run by this service. + Task& task_; + + // Handler object to represent the position of the task in the queue. + class task_handler + : public handler_queue::handler + { + public: + task_handler() + : handler_queue::handler(0, 0) + { + } + } task_handler_; + + // Whether the task has been interrupted. + bool task_interrupted_; + + // The count of unfinished work. + int outstanding_work_; + + // The queue of handlers that are ready to be delivered. + handler_queue handler_queue_; + + // Flag to indicate that the dispatcher has been stopped. + bool stopped_; + + // Flag to indicate that the dispatcher has been shut down. + bool shutdown_; + + // Structure containing information about an idle thread. + struct idle_thread_info + { + event wakeup_event; + idle_thread_info* next; + }; + + // The number of threads that are currently idle. + idle_thread_info* first_idle_thread_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include +#include + +#endif // defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE) + +#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_HPP diff --git a/win32/include/boost/asio/detail/task_io_service_2lock.hpp b/win32/include/boost/asio/detail/task_io_service_2lock.hpp new file mode 100755 index 000000000..d30126577 --- /dev/null +++ b/win32/include/boost/asio/detail/task_io_service_2lock.hpp @@ -0,0 +1,464 @@ +// +// task_io_service_2lock.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP +#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +// An alternative task_io_service implementation based on a two-lock queue. + +template +class task_io_service + : public boost::asio::detail::service_base > +{ +public: + typedef indirect_handler_queue handler_queue; + + // Constructor. + task_io_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base >(io_service), + front_mutex_(), + back_mutex_(), + task_(use_service(io_service)), + outstanding_work_(0), + front_stopped_(false), + back_stopped_(false), + back_shutdown_(false), + back_first_idle_thread_(0), + back_task_thread_(0) + { + handler_queue_.push(&task_handler_); + } + + void init(size_t /*concurrency_hint*/) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); + back_shutdown_ = true; + back_lock.unlock(); + + // Destroy handler objects. + while (handler_queue::handler* h = handler_queue_.pop()) + if (h != &task_handler_) + h->destroy(); + + // Reset handler queue to initial state. + handler_queue_.push(&task_handler_); + } + + // Run the event loop until interrupted or no more work. + size_t run(boost::system::error_code& ec) + { + if (outstanding_work_ == 0) + { + stop(); + ec = boost::system::error_code(); + return 0; + } + + typename call_stack::context ctx(this); + + idle_thread_info this_idle_thread; + this_idle_thread.next = 0; + + size_t n = 0; + while (do_one(&this_idle_thread, ec)) + if (n != (std::numeric_limits::max)()) + ++n; + return n; + } + + // Run until interrupted or one operation is performed. + size_t run_one(boost::system::error_code& ec) + { + if (outstanding_work_ == 0) + { + stop(); + ec = boost::system::error_code(); + return 0; + } + + typename call_stack::context ctx(this); + + idle_thread_info this_idle_thread; + this_idle_thread.next = 0; + + return do_one(&this_idle_thread, ec); + } + + // Poll for operations without blocking. + size_t poll(boost::system::error_code& ec) + { + if (outstanding_work_ == 0) + { + stop(); + ec = boost::system::error_code(); + return 0; + } + + typename call_stack::context ctx(this); + + size_t n = 0; + while (do_one(0, ec)) + if (n != (std::numeric_limits::max)()) + ++n; + return n; + } + + // Poll for one operation without blocking. + size_t poll_one(boost::system::error_code& ec) + { + if (outstanding_work_ == 0) + { + stop(); + ec = boost::system::error_code(); + return 0; + } + + typename call_stack::context ctx(this); + + return do_one(0, ec); + } + + // Interrupt the event processing loop. + void stop() + { + boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_); + front_stopped_ = true; + front_lock.unlock(); + + boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); + back_stopped_ = true; + interrupt_all_idle_threads(back_lock); + } + + // Reset in preparation for a subsequent run invocation. + void reset() + { + boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_); + front_stopped_ = false; + front_lock.unlock(); + + boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); + back_stopped_ = false; + } + + // Notify that some work has started. + void work_started() + { + ++outstanding_work_; + } + + // Notify that some work has finished. + void work_finished() + { + if (--outstanding_work_ == 0) + stop(); + } + + // Request invocation of the given handler. + template + void dispatch(Handler handler) + { + if (call_stack::contains(this)) + boost_asio_handler_invoke_helpers::invoke(handler, &handler); + else + post(handler); + } + + // Request invocation of the given handler and return immediately. + template + void post(Handler handler) + { + // Allocate and construct an operation to wrap the handler. + handler_queue::scoped_ptr ptr(handler_queue::wrap(handler)); + + boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); + + // If the service has been shut down we silently discard the handler. + if (back_shutdown_) + return; + + // Add the handler to the end of the queue. + handler_queue_.push(ptr.get()); + ptr.release(); + + // An undelivered handler is treated as unfinished work. + ++outstanding_work_; + + // Wake up a thread to execute the handler. + interrupt_one_idle_thread(back_lock); + } + +private: + struct idle_thread_info; + + size_t do_one(idle_thread_info* this_idle_thread, + boost::system::error_code& ec) + { + bool task_has_run = false; + for (;;) + { + // The front lock must be held before we can pop items from the queue. + boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_); + if (front_stopped_) + { + ec = boost::system::error_code(); + return 0; + } + + if (handler_queue::handler* h = handler_queue_.pop()) + { + if (h == &task_handler_) + { + bool more_handlers = handler_queue_.poppable(); + unsigned long front_version = handler_queue_.front_version(); + front_lock.unlock(); + + // The task is always added to the back of the queue when we exit + // this block. + task_cleanup c(*this); + + // If we're polling and the task has already run then we're done. + bool polling = !this_idle_thread; + if (task_has_run && polling) + { + ec = boost::system::error_code(); + return 0; + } + + // If we're considering going idle we need to check whether the queue + // is still empty. If it is, add the thread to the list of idle + // threads. + if (!more_handlers && !polling) + { + boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); + if (back_stopped_) + { + ec = boost::system::error_code(); + return 0; + } + else if (front_version == handler_queue_.back_version()) + { + back_task_thread_ = this_idle_thread; + } + else + { + more_handlers = true; + } + } + + // Run the task. May throw an exception. Only block if the handler + // queue is empty and we're not polling, otherwise we want to return + // as soon as possible. + task_has_run = true; + task_.run(!more_handlers && !polling); + } + else + { + front_lock.unlock(); + handler_cleanup c(*this); + + // Invoke the handler. May throw an exception. + h->invoke(); // invoke() deletes the handler object + + ec = boost::system::error_code(); + return 1; + } + } + else if (this_idle_thread) + { + unsigned long front_version = handler_queue_.front_version(); + front_lock.unlock(); + + // If we're considering going idle we need to check whether the queue + // is still empty. If it is, add the thread to the list of idle + // threads. + boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_); + if (back_stopped_) + { + ec = boost::system::error_code(); + return 0; + } + else if (front_version == handler_queue_.back_version()) + { + this_idle_thread->next = back_first_idle_thread_; + back_first_idle_thread_ = this_idle_thread; + this_idle_thread->wakeup_event.clear(back_lock); + this_idle_thread->wakeup_event.wait(back_lock); + } + } + else + { + ec = boost::system::error_code(); + return 0; + } + } + } + + // Interrupt a single idle thread. + void interrupt_one_idle_thread( + boost::asio::detail::mutex::scoped_lock& back_lock) + { + if (back_first_idle_thread_) + { + idle_thread_info* idle_thread = back_first_idle_thread_; + back_first_idle_thread_ = idle_thread->next; + idle_thread->next = 0; + idle_thread->wakeup_event.signal(back_lock); + } + else if (back_task_thread_) + { + back_task_thread_ = 0; + task_.interrupt(); + } + } + + // Interrupt all idle threads. + void interrupt_all_idle_threads( + boost::asio::detail::mutex::scoped_lock& back_lock) + { + while (back_first_idle_thread_) + { + idle_thread_info* idle_thread = back_first_idle_thread_; + back_first_idle_thread_ = idle_thread->next; + idle_thread->next = 0; + idle_thread->wakeup_event.signal(back_lock); + } + + if (back_task_thread_) + { + back_task_thread_ = 0; + task_.interrupt(); + } + } + + // Helper class to perform task-related operations on block exit. + class task_cleanup; + friend class task_cleanup; + class task_cleanup + { + public: + task_cleanup(task_io_service& task_io_svc) + : task_io_service_(task_io_svc) + { + } + + ~task_cleanup() + { + // Reinsert the task at the end of the handler queue. + boost::asio::detail::mutex::scoped_lock back_lock( + task_io_service_.back_mutex_); + task_io_service_.back_task_thread_ = 0; + task_io_service_.handler_queue_.push(&task_io_service_.task_handler_); + } + + private: + task_io_service& task_io_service_; + }; + + // Helper class to perform handler-related operations on block exit. + class handler_cleanup + { + public: + handler_cleanup(task_io_service& task_io_svc) + : task_io_service_(task_io_svc) + { + } + + ~handler_cleanup() + { + task_io_service_.work_finished(); + } + + private: + task_io_service& task_io_service_; + }; + + // Mutexes to protect access to internal data. + boost::asio::detail::mutex front_mutex_; + boost::asio::detail::mutex back_mutex_; + + // The task to be run by this service. + Task& task_; + + // Handler object to represent the position of the task in the queue. + class task_handler + : public handler_queue::handler + { + public: + task_handler() + : handler_queue::handler(0, 0) + { + } + } task_handler_; + + // The count of unfinished work. + boost::detail::atomic_count outstanding_work_; + + // The queue of handlers that are ready to be delivered. + handler_queue handler_queue_; + + // Flag to indicate that the dispatcher has been stopped. + bool front_stopped_; + bool back_stopped_; + + // Flag to indicate that the dispatcher has been shut down. + bool back_shutdown_; + + // Structure containing information about an idle thread. + struct idle_thread_info + { + event wakeup_event; + idle_thread_info* next; + }; + + // The number of threads that are currently idle. + idle_thread_info* back_first_idle_thread_; + + // The thread that is currently blocked on the task. + idle_thread_info* back_task_thread_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP diff --git a/win32/include/boost/asio/detail/task_io_service_fwd.hpp b/win32/include/boost/asio/detail/task_io_service_fwd.hpp new file mode 100755 index 000000000..ea5ac2dc9 --- /dev/null +++ b/win32/include/boost/asio/detail/task_io_service_fwd.hpp @@ -0,0 +1,33 @@ +// +// task_io_service_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP +#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class task_io_service; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP diff --git a/win32/include/boost/asio/detail/thread.hpp b/win32/include/boost/asio/detail/thread.hpp new file mode 100755 index 000000000..008aeb703 --- /dev/null +++ b/win32/include/boost/asio/detail/thread.hpp @@ -0,0 +1,60 @@ +// +// thread.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_THREAD_HPP +#define BOOST_ASIO_DETAIL_THREAD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if !defined(BOOST_HAS_THREADS) +# include +#elif defined(BOOST_WINDOWS) +# if defined(UNDER_CE) +# include +# else +# include +# endif +#elif defined(BOOST_HAS_PTHREADS) +# include +#else +# error Only Windows and POSIX are supported! +#endif + +namespace boost { +namespace asio { +namespace detail { + +#if !defined(BOOST_HAS_THREADS) +typedef null_thread thread; +#elif defined(BOOST_WINDOWS) +# if defined(UNDER_CE) +typedef wince_thread thread; +# else +typedef win_thread thread; +# endif +#elif defined(BOOST_HAS_PTHREADS) +typedef posix_thread thread; +#endif + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_THREAD_HPP diff --git a/win32/include/boost/asio/detail/throw_error.hpp b/win32/include/boost/asio/detail/throw_error.hpp new file mode 100755 index 000000000..b93f3d70f --- /dev/null +++ b/win32/include/boost/asio/detail/throw_error.hpp @@ -0,0 +1,46 @@ +// +// throw_error.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_THROW_ERROR_HPP +#define BOOST_ASIO_DETAIL_THROW_ERROR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + + +namespace boost { +namespace asio { +namespace detail { + +inline void throw_error(const boost::system::error_code& err) +{ + if (err) + { + boost::system::system_error e(err); + boost::throw_exception(e); + } +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_THROW_ERROR_HPP diff --git a/win32/include/boost/asio/detail/timer_queue.hpp b/win32/include/boost/asio/detail/timer_queue.hpp new file mode 100755 index 000000000..fb772f847 --- /dev/null +++ b/win32/include/boost/asio/detail/timer_queue.hpp @@ -0,0 +1,438 @@ +// +// timer_queue.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_TIMER_QUEUE_HPP +#define BOOST_ASIO_DETAIL_TIMER_QUEUE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class timer_queue + : public timer_queue_base +{ +public: + // The time type. + typedef typename Time_Traits::time_type time_type; + + // The duration type. + typedef typename Time_Traits::duration_type duration_type; + + // Constructor. + timer_queue() + : timers_(), + heap_(), + cancelled_timers_(0), + complete_timers_(0) + { + } + + // Add a new timer to the queue. Returns true if this is the timer that is + // earliest in the queue, in which case the reactor's event demultiplexing + // function call may need to be interrupted and restarted. + template + bool enqueue_timer(const time_type& time, Handler handler, void* token) + { + // Ensure that there is space for the timer in the heap. We reserve here so + // that the push_back below will not throw due to a reallocation failure. + heap_.reserve(heap_.size() + 1); + + // Create a new timer object. + std::auto_ptr > new_timer( + new timer(time, handler, token)); + + // Insert the new timer into the hash. + typedef typename hash_map::iterator iterator; + typedef typename hash_map::value_type value_type; + std::pair result = + timers_.insert(value_type(token, new_timer.get())); + if (!result.second) + { + result.first->second->prev_ = new_timer.get(); + new_timer->next_ = result.first->second; + result.first->second = new_timer.get(); + } + + // Put the timer at the correct position in the heap. + new_timer->heap_index_ = heap_.size(); + heap_.push_back(new_timer.get()); + up_heap(heap_.size() - 1); + bool is_first = (heap_[0] == new_timer.get()); + + // Ownership of the timer is transferred to the timer queue. + new_timer.release(); + + return is_first; + } + + // Whether there are no timers in the queue. + virtual bool empty() const + { + return heap_.empty(); + } + + // Get the time for the timer that is earliest in the queue. + virtual boost::posix_time::time_duration wait_duration() const + { + if (heap_.empty()) + return boost::posix_time::pos_infin; + return Time_Traits::to_posix_duration( + Time_Traits::subtract(heap_[0]->time_, Time_Traits::now())); + } + + // Dispatch the timers that are earlier than the specified time. + virtual void dispatch_timers() + { + const time_type now = Time_Traits::now(); + while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0]->time_)) + { + timer_base* t = heap_[0]; + remove_timer(t); + t->result_ = boost::system::error_code(); + t->prev_ = 0; + t->next_ = complete_timers_; + complete_timers_ = t; + } + } + + // Cancel the timers with the given token. Any timers pending for the token + // will be notified that they have been cancelled next time + // dispatch_cancellations is called. Returns the number of timers that were + // cancelled. + std::size_t cancel_timer(void* timer_token) + { + std::size_t num_cancelled = 0; + typedef typename hash_map::iterator iterator; + iterator it = timers_.find(timer_token); + if (it != timers_.end()) + { + timer_base* t = it->second; + while (t) + { + timer_base* next = t->next_; + remove_timer(t); + t->prev_ = 0; + t->next_ = cancelled_timers_; + cancelled_timers_ = t; + t = next; + ++num_cancelled; + } + } + return num_cancelled; + } + + // Dispatch any pending cancels for timers. + virtual void dispatch_cancellations() + { + while (cancelled_timers_) + { + timer_base* this_timer = cancelled_timers_; + this_timer->result_ = boost::asio::error::operation_aborted; + cancelled_timers_ = this_timer->next_; + this_timer->next_ = complete_timers_; + complete_timers_ = this_timer; + } + } + + // Complete any timers that are waiting to be completed. + virtual void complete_timers() + { + while (complete_timers_) + { + timer_base* this_timer = complete_timers_; + complete_timers_ = this_timer->next_; + this_timer->next_ = 0; + this_timer->complete(); + } + } + + // Destroy all timers. + virtual void destroy_timers() + { + typename hash_map::iterator i = timers_.begin(); + typename hash_map::iterator end = timers_.end(); + while (i != end) + { + timer_base* t = i->second; + typename hash_map::iterator old_i = i++; + timers_.erase(old_i); + destroy_timer_list(t); + } + heap_.clear(); + timers_.clear(); + destroy_timer_list(cancelled_timers_); + destroy_timer_list(complete_timers_); + } + +private: + // Base class for timer operations. Function pointers are used instead of + // virtual functions to avoid the associated overhead. + class timer_base + { + public: + // Delete the timer and post the handler. + void complete() + { + complete_func_(this, result_); + } + + // Delete the timer. + void destroy() + { + destroy_func_(this); + } + + protected: + typedef void (*complete_func_type)(timer_base*, + const boost::system::error_code&); + typedef void (*destroy_func_type)(timer_base*); + + // Constructor. + timer_base(complete_func_type complete_func, destroy_func_type destroy_func, + const time_type& time, void* token) + : complete_func_(complete_func), + destroy_func_(destroy_func), + time_(time), + token_(token), + next_(0), + prev_(0), + heap_index_( + std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()) + { + } + + // Prevent deletion through this type. + ~timer_base() + { + } + + private: + friend class timer_queue; + + // The function to be called to delete the timer and post the handler. + complete_func_type complete_func_; + + // The function to be called to delete the timer. + destroy_func_type destroy_func_; + + // The result of the timer operation. + boost::system::error_code result_; + + // The time when the timer should fire. + time_type time_; + + // The token associated with the timer. + void* token_; + + // The next timer known to the queue. + timer_base* next_; + + // The previous timer known to the queue. + timer_base* prev_; + + // The index of the timer in the heap. + size_t heap_index_; + }; + + // Adaptor class template for using handlers in timers. + template + class timer + : public timer_base + { + public: + // Constructor. + timer(const time_type& time, Handler handler, void* token) + : timer_base(&timer::complete_handler, + &timer::destroy_handler, time, token), + handler_(handler) + { + } + + // Delete the timer and post the handler. + static void complete_handler(timer_base* base, + const boost::system::error_code& result) + { + // Take ownership of the timer object. + typedef timer this_type; + this_type* this_timer(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(this_timer->handler_, this_timer); + + // Make a copy of the error_code and the handler so that the memory can + // be deallocated before the upcall is made. + boost::system::error_code ec(result); + Handler handler(this_timer->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Make the upcall. + handler(ec); + } + + // Delete the timer. + static void destroy_handler(timer_base* base) + { + // Take ownership of the timer object. + typedef timer this_type; + this_type* this_timer(static_cast(base)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(this_timer->handler_, this_timer); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(this_timer->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + private: + Handler handler_; + }; + + // Move the item at the given index up the heap to its correct position. + void up_heap(size_t index) + { + size_t parent = (index - 1) / 2; + while (index > 0 + && Time_Traits::less_than(heap_[index]->time_, heap_[parent]->time_)) + { + swap_heap(index, parent); + index = parent; + parent = (index - 1) / 2; + } + } + + // Move the item at the given index down the heap to its correct position. + void down_heap(size_t index) + { + size_t child = index * 2 + 1; + while (child < heap_.size()) + { + size_t min_child = (child + 1 == heap_.size() + || Time_Traits::less_than( + heap_[child]->time_, heap_[child + 1]->time_)) + ? child : child + 1; + if (Time_Traits::less_than(heap_[index]->time_, heap_[min_child]->time_)) + break; + swap_heap(index, min_child); + index = min_child; + child = index * 2 + 1; + } + } + + // Swap two entries in the heap. + void swap_heap(size_t index1, size_t index2) + { + timer_base* tmp = heap_[index1]; + heap_[index1] = heap_[index2]; + heap_[index2] = tmp; + heap_[index1]->heap_index_ = index1; + heap_[index2]->heap_index_ = index2; + } + + // Remove a timer from the heap and list of timers. + void remove_timer(timer_base* t) + { + // Remove the timer from the heap. + size_t index = t->heap_index_; + if (!heap_.empty() && index < heap_.size()) + { + if (index == heap_.size() - 1) + { + heap_.pop_back(); + } + else + { + swap_heap(index, heap_.size() - 1); + heap_.pop_back(); + size_t parent = (index - 1) / 2; + if (index > 0 && Time_Traits::less_than( + heap_[index]->time_, heap_[parent]->time_)) + up_heap(index); + else + down_heap(index); + } + } + + // Remove the timer from the hash. + typedef typename hash_map::iterator iterator; + iterator it = timers_.find(t->token_); + if (it != timers_.end()) + { + if (it->second == t) + it->second = t->next_; + if (t->prev_) + t->prev_->next_ = t->next_; + if (t->next_) + t->next_->prev_ = t->prev_; + if (it->second == 0) + timers_.erase(it); + } + } + + // Destroy all timers in a linked list. + void destroy_timer_list(timer_base*& t) + { + while (t) + { + timer_base* next = t->next_; + t->next_ = 0; + t->destroy(); + t = next; + } + } + + // A hash of timer token to linked lists of timers. + hash_map timers_; + + // The heap of timers, with the earliest timer at the front. + std::vector heap_; + + // The list of timers to be cancelled. + timer_base* cancelled_timers_; + + // The list of timers waiting to be completed. + timer_base* complete_timers_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_TIMER_QUEUE_HPP diff --git a/win32/include/boost/asio/detail/timer_queue_base.hpp b/win32/include/boost/asio/detail/timer_queue_base.hpp new file mode 100755 index 000000000..e761e99ab --- /dev/null +++ b/win32/include/boost/asio/detail/timer_queue_base.hpp @@ -0,0 +1,64 @@ +// +// timer_queue_base.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_TIMER_QUEUE_BASE_HPP +#define BOOST_ASIO_DETAIL_TIMER_QUEUE_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include // Must come before posix_time. + +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +class timer_queue_base + : private noncopyable +{ +public: + // Destructor. + virtual ~timer_queue_base() {} + + // Whether there are no timers in the queue. + virtual bool empty() const = 0; + + // Get the time to wait until the next timer. + virtual boost::posix_time::time_duration wait_duration() const = 0; + + // Dispatch all ready timers. + virtual void dispatch_timers() = 0; + + // Dispatch any pending cancels for timers. + virtual void dispatch_cancellations() = 0; + + // Complete all timers that are waiting to be completed. + virtual void complete_timers() = 0; + + // Destroy all timers. + virtual void destroy_timers() = 0; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_TIMER_QUEUE_BASE_HPP diff --git a/win32/include/boost/asio/detail/tss_ptr.hpp b/win32/include/boost/asio/detail/tss_ptr.hpp new file mode 100755 index 000000000..2871e8dba --- /dev/null +++ b/win32/include/boost/asio/detail/tss_ptr.hpp @@ -0,0 +1,67 @@ +// +// tss_ptr.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_TSS_PTR_HPP +#define BOOST_ASIO_DETAIL_TSS_PTR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if !defined(BOOST_HAS_THREADS) +# include +#elif defined(BOOST_WINDOWS) +# include +#elif defined(BOOST_HAS_PTHREADS) +# include +#else +# error Only Windows and POSIX are supported! +#endif + +namespace boost { +namespace asio { +namespace detail { + +template +class tss_ptr +#if !defined(BOOST_HAS_THREADS) + : public null_tss_ptr +#elif defined(BOOST_WINDOWS) + : public win_tss_ptr +#elif defined(BOOST_HAS_PTHREADS) + : public posix_tss_ptr +#endif +{ +public: + void operator=(T* value) + { +#if !defined(BOOST_HAS_THREADS) + null_tss_ptr::operator=(value); +#elif defined(BOOST_WINDOWS) + win_tss_ptr::operator=(value); +#elif defined(BOOST_HAS_PTHREADS) + posix_tss_ptr::operator=(value); +#endif + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_TSS_PTR_HPP diff --git a/win32/include/boost/asio/detail/win_event.hpp b/win32/include/boost/asio/detail/win_event.hpp new file mode 100755 index 000000000..289d37890 --- /dev/null +++ b/win32/include/boost/asio/detail/win_event.hpp @@ -0,0 +1,105 @@ +// +// win_event.hpp +// ~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_EVENT_HPP +#define BOOST_ASIO_DETAIL_WIN_EVENT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#if defined(BOOST_WINDOWS) + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +class win_event + : private noncopyable +{ +public: + // Constructor. + win_event() + : event_(::CreateEvent(0, true, false, 0)) + { + if (!event_) + { + DWORD last_error = ::GetLastError(); + boost::system::system_error e( + boost::system::error_code(last_error, + boost::asio::error::get_system_category()), + "event"); + boost::throw_exception(e); + } + } + + // Destructor. + ~win_event() + { + ::CloseHandle(event_); + } + + // Signal the event. + template + void signal(Lock& lock) + { + BOOST_ASSERT(lock.locked()); + (void)lock; + ::SetEvent(event_); + } + + // Reset the event. + template + void clear(Lock& lock) + { + BOOST_ASSERT(lock.locked()); + (void)lock; + ::ResetEvent(event_); + } + + // Wait for the event to become signalled. + template + void wait(Lock& lock) + { + BOOST_ASSERT(lock.locked()); + lock.unlock(); + ::WaitForSingleObject(event_, INFINITE); + lock.lock(); + } + +private: + HANDLE event_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_WINDOWS) + +#include + +#endif // BOOST_ASIO_DETAIL_WIN_EVENT_HPP diff --git a/win32/include/boost/asio/detail/win_fd_set_adapter.hpp b/win32/include/boost/asio/detail/win_fd_set_adapter.hpp new file mode 100755 index 000000000..b055a8908 --- /dev/null +++ b/win32/include/boost/asio/detail/win_fd_set_adapter.hpp @@ -0,0 +1,90 @@ +// +// win_fd_set_adapter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP +#define BOOST_ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + +namespace boost { +namespace asio { +namespace detail { + +// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements. +class win_fd_set_adapter +{ +public: + enum { win_fd_set_size = 1024 }; + + win_fd_set_adapter() + : max_descriptor_(invalid_socket) + { + fd_set_.fd_count = 0; + } + + bool set(socket_type descriptor) + { + for (u_int i = 0; i < fd_set_.fd_count; ++i) + if (fd_set_.fd_array[i] == descriptor) + return true; + if (fd_set_.fd_count < win_fd_set_size) + { + fd_set_.fd_array[fd_set_.fd_count++] = descriptor; + return true; + } + return false; + } + + bool is_set(socket_type descriptor) const + { + return !!__WSAFDIsSet(descriptor, + const_cast(reinterpret_cast(&fd_set_))); + } + + operator fd_set*() + { + return reinterpret_cast(&fd_set_); + } + + socket_type max_descriptor() const + { + return max_descriptor_; + } + +private: + // This structure is defined to be compatible with the Windows API fd_set + // structure, but without being dependent on the value of FD_SETSIZE. + struct win_fd_set + { + u_int fd_count; + SOCKET fd_array[win_fd_set_size]; + }; + + win_fd_set fd_set_; + socket_type max_descriptor_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + +#include + +#endif // BOOST_ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP diff --git a/win32/include/boost/asio/detail/win_iocp_handle_service.hpp b/win32/include/boost/asio/detail/win_iocp_handle_service.hpp new file mode 100755 index 000000000..8b0593b79 --- /dev/null +++ b/win32/include/boost/asio/detail/win_iocp_handle_service.hpp @@ -0,0 +1,834 @@ +// +// win_iocp_handle_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP +#define BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_IOCP) + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +class win_iocp_handle_service + : public boost::asio::detail::service_base +{ +public: + // Base class for all operations. + typedef win_iocp_io_service::operation operation; + + // The native type of a stream handle. + typedef HANDLE native_type; + + // The implementation type of the stream handle. + class implementation_type + { + public: + // Default constructor. + implementation_type() + : handle_(INVALID_HANDLE_VALUE), + safe_cancellation_thread_id_(0), + next_(0), + prev_(0) + { + } + + private: + // Only this service will have access to the internal values. + friend class win_iocp_handle_service; + + // The native stream handle representation. + native_type handle_; + + // The ID of the thread from which it is safe to cancel asynchronous + // operations. 0 means no asynchronous operations have been started yet. + // ~0 means asynchronous operations have been started from more than one + // thread, and cancellation is not supported for the handle. + DWORD safe_cancellation_thread_id_; + + // Pointers to adjacent handle implementations in linked list. + implementation_type* next_; + implementation_type* prev_; + }; + + win_iocp_handle_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + iocp_service_(boost::asio::use_service(io_service)), + mutex_(), + impl_list_(0) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + // Close all implementations, causing all operations to complete. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + implementation_type* impl = impl_list_; + while (impl) + { + close_for_destruction(*impl); + impl = impl->next_; + } + } + + // Construct a new handle implementation. + void construct(implementation_type& impl) + { + impl.handle_ = INVALID_HANDLE_VALUE; + impl.safe_cancellation_thread_id_ = 0; + + // Insert implementation into linked list of all implementations. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + impl.next_ = impl_list_; + impl.prev_ = 0; + if (impl_list_) + impl_list_->prev_ = &impl; + impl_list_ = &impl; + } + + // Destroy a handle implementation. + void destroy(implementation_type& impl) + { + close_for_destruction(impl); + + // Remove implementation from linked list of all implementations. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (impl_list_ == &impl) + impl_list_ = impl.next_; + if (impl.prev_) + impl.prev_->next_ = impl.next_; + if (impl.next_) + impl.next_->prev_= impl.prev_; + impl.next_ = 0; + impl.prev_ = 0; + } + + // Assign a native handle to a handle implementation. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_handle, boost::system::error_code& ec) + { + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + if (iocp_service_.register_handle(native_handle, ec)) + return ec; + + impl.handle_ = native_handle; + ec = boost::system::error_code(); + return ec; + } + + // Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return impl.handle_ != INVALID_HANDLE_VALUE; + } + + // Destroy a handle implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + if (is_open(impl)) + { + if (!::CloseHandle(impl.handle_)) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + impl.handle_ = INVALID_HANDLE_VALUE; + impl.safe_cancellation_thread_id_ = 0; + } + + ec = boost::system::error_code(); + return ec; + } + + // Get the native handle representation. + native_type native(const implementation_type& impl) const + { + return impl.handle_; + } + + // Cancel all operations associated with the handle. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + } + else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress( + ::GetModuleHandleA("KERNEL32"), "CancelIoEx")) + { + // The version of Windows supports cancellation from any thread. + typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED); + cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr; + if (!cancel_io_ex(impl.handle_, 0)) + { + DWORD last_error = ::GetLastError(); + if (last_error == ERROR_NOT_FOUND) + { + // ERROR_NOT_FOUND means that there were no operations to be + // cancelled. We swallow this error to match the behaviour on other + // platforms. + ec = boost::system::error_code(); + } + else + { + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + } + else + { + ec = boost::system::error_code(); + } + } + else if (impl.safe_cancellation_thread_id_ == 0) + { + // No operations have been started, so there's nothing to cancel. + ec = boost::system::error_code(); + } + else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId()) + { + // Asynchronous operations have been started from the current thread only, + // so it is safe to try to cancel them using CancelIo. + if (!::CancelIo(impl.handle_)) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + else + { + ec = boost::system::error_code(); + } + } + else + { + // Asynchronous operations have been started from more than one thread, + // so cancellation is not safe. + ec = boost::asio::error::operation_not_supported; + } + + return ec; + } + + class overlapped_wrapper + : public OVERLAPPED + { + public: + explicit overlapped_wrapper(boost::system::error_code& ec) + { + Internal = 0; + InternalHigh = 0; + Offset = 0; + OffsetHigh = 0; + + // Create a non-signalled manual-reset event, for GetOverlappedResult. + hEvent = ::CreateEvent(0, TRUE, FALSE, 0); + if (hEvent) + { + // As documented in GetQueuedCompletionStatus, setting the low order + // bit of this event prevents our synchronous writes from being treated + // as completion port events. + *reinterpret_cast(&hEvent) |= 1; + } + else + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + } + + ~overlapped_wrapper() + { + if (hEvent) + { + ::CloseHandle(hEvent); + } + } + }; + + // Write the given data. Returns the number of bytes written. + template + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return write_some_at(impl, 0, buffers, ec); + } + + // Write the given data at the specified offset. Returns the number of bytes + // written. + template + size_t write_some_at(implementation_type& impl, boost::uint64_t offset, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Find first buffer of non-zero length. + boost::asio::const_buffer buffer; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + for (DWORD i = 0; iter != end; ++iter, ++i) + { + buffer = boost::asio::const_buffer(*iter); + if (boost::asio::buffer_size(buffer) != 0) + break; + } + + // A request to write 0 bytes on a handle is a no-op. + if (boost::asio::buffer_size(buffer) == 0) + { + ec = boost::system::error_code(); + return 0; + } + + overlapped_wrapper overlapped(ec); + if (ec) + { + return 0; + } + + // Write the data. + overlapped.Offset = offset & 0xFFFFFFFF; + overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF; + BOOL ok = ::WriteFile(impl.handle_, + boost::asio::buffer_cast(buffer), + static_cast(boost::asio::buffer_size(buffer)), 0, &overlapped); + if (!ok) + { + DWORD last_error = ::GetLastError(); + if (last_error != ERROR_IO_PENDING) + { + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return 0; + } + } + + // Wait for the operation to complete. + DWORD bytes_transferred = 0; + ok = ::GetOverlappedResult(impl.handle_, + &overlapped, &bytes_transferred, TRUE); + if (!ok) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + + ec = boost::system::error_code(); + return bytes_transferred; + } + + template + class write_operation + : public operation + { + public: + write_operation(win_iocp_io_service& io_service, + const ConstBufferSequence& buffers, Handler handler) + : operation(io_service, + &write_operation::do_completion_impl, + &write_operation::destroy_impl), + work_(io_service.get_io_service()), + buffers_(buffers), + handler_(handler) + { + } + + private: + static void do_completion_impl(operation* op, + DWORD last_error, size_t bytes_transferred) + { + // Take ownership of the operation object. + typedef write_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + // Check whether buffers are still valid. + typename ConstBufferSequence::const_iterator iter + = handler_op->buffers_.begin(); + typename ConstBufferSequence::const_iterator end + = handler_op->buffers_.end(); + while (iter != end) + { + boost::asio::const_buffer buffer(*iter); + boost::asio::buffer_cast(buffer); + ++iter; + } +#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(handler_op->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Call the handler. + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + boost_asio_handler_invoke_helpers::invoke( + bind_handler(handler, ec, bytes_transferred), &handler); + } + + static void destroy_impl(operation* op) + { + // Take ownership of the operation object. + typedef write_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + boost::asio::io_service::work work_; + ConstBufferSequence buffers_; + Handler handler_; + }; + + // Start an asynchronous write. The data being written must be valid for the + // lifetime of the asynchronous operation. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, Handler handler) + { + async_write_some_at(impl, 0, buffers, handler); + } + + // Start an asynchronous write at a specified offset. The data being written + // must be valid for the lifetime of the asynchronous operation. + template + void async_write_some_at(implementation_type& impl, boost::uint64_t offset, + const ConstBufferSequence& buffers, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + return; + } + + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); + + // Allocate and construct an operation to wrap the handler. + typedef write_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + handler_ptr ptr(raw_ptr, iocp_service_, buffers, handler); + + // Find first buffer of non-zero length. + boost::asio::const_buffer buffer; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + for (DWORD i = 0; iter != end; ++iter, ++i) + { + buffer = boost::asio::const_buffer(*iter); + if (boost::asio::buffer_size(buffer) != 0) + break; + } + + // A request to write 0 bytes on a handle is a no-op. + if (boost::asio::buffer_size(buffer) == 0) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code error; + iocp_service_.post(bind_handler(handler, error, 0)); + return; + } + + // Write the data. + DWORD bytes_transferred = 0; + ptr.get()->Offset = offset & 0xFFFFFFFF; + ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF; + BOOL ok = ::WriteFile(impl.handle_, + boost::asio::buffer_cast(buffer), + static_cast(boost::asio::buffer_size(buffer)), + &bytes_transferred, ptr.get()); + DWORD last_error = ::GetLastError(); + + // Check if the operation completed immediately. + if (!ok && last_error != ERROR_IO_PENDING) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); + } + else + { + ptr.release(); + } + } + + // Read some data. Returns the number of bytes received. + template + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return read_some_at(impl, 0, buffers, ec); + } + + // Read some data at a specified offset. Returns the number of bytes received. + template + size_t read_some_at(implementation_type& impl, boost::uint64_t offset, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Find first buffer of non-zero length. + boost::asio::mutable_buffer buffer; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + for (DWORD i = 0; iter != end; ++iter, ++i) + { + buffer = boost::asio::mutable_buffer(*iter); + if (boost::asio::buffer_size(buffer) != 0) + break; + } + + // A request to read 0 bytes on a stream handle is a no-op. + if (boost::asio::buffer_size(buffer) == 0) + { + ec = boost::system::error_code(); + return 0; + } + + overlapped_wrapper overlapped(ec); + if (ec) + { + return 0; + } + + // Read some data. + overlapped.Offset = offset & 0xFFFFFFFF; + overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF; + BOOL ok = ::ReadFile(impl.handle_, + boost::asio::buffer_cast(buffer), + static_cast(boost::asio::buffer_size(buffer)), 0, &overlapped); + if (!ok) + { + DWORD last_error = ::GetLastError(); + if (last_error != ERROR_IO_PENDING) + { + if (last_error == ERROR_HANDLE_EOF) + { + ec = boost::asio::error::eof; + } + else + { + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + return 0; + } + } + + // Wait for the operation to complete. + DWORD bytes_transferred = 0; + ok = ::GetOverlappedResult(impl.handle_, + &overlapped, &bytes_transferred, TRUE); + if (!ok) + { + DWORD last_error = ::GetLastError(); + if (last_error == ERROR_HANDLE_EOF) + { + ec = boost::asio::error::eof; + } + else + { + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + } + + ec = boost::system::error_code(); + return bytes_transferred; + } + + template + class read_operation + : public operation + { + public: + read_operation(win_iocp_io_service& io_service, + const MutableBufferSequence& buffers, Handler handler) + : operation(io_service, + &read_operation< + MutableBufferSequence, Handler>::do_completion_impl, + &read_operation< + MutableBufferSequence, Handler>::destroy_impl), + work_(io_service.get_io_service()), + buffers_(buffers), + handler_(handler) + { + } + + private: + static void do_completion_impl(operation* op, + DWORD last_error, size_t bytes_transferred) + { + // Take ownership of the operation object. + typedef read_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + // Check whether buffers are still valid. + typename MutableBufferSequence::const_iterator iter + = handler_op->buffers_.begin(); + typename MutableBufferSequence::const_iterator end + = handler_op->buffers_.end(); + while (iter != end) + { + boost::asio::mutable_buffer buffer(*iter); + boost::asio::buffer_cast(buffer); + ++iter; + } +#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + + // Check for the end-of-file condition. + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + if (!ec && bytes_transferred == 0 || last_error == ERROR_HANDLE_EOF) + { + ec = boost::asio::error::eof; + } + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(handler_op->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Call the handler. + boost_asio_handler_invoke_helpers::invoke( + bind_handler(handler, ec, bytes_transferred), &handler); + } + + static void destroy_impl(operation* op) + { + // Take ownership of the operation object. + typedef read_operation op_type; + op_type* handler_op(static_cast(op)); + typedef boost::asio::detail::handler_alloc_traits< + Handler, op_type> alloc_traits; + boost::asio::detail::handler_ptr ptr( + handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + boost::asio::io_service::work work_; + MutableBufferSequence buffers_; + Handler handler_; + }; + + // Start an asynchronous read. The buffer for the data being received must be + // valid for the lifetime of the asynchronous operation. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, Handler handler) + { + async_read_some_at(impl, 0, buffers, handler); + } + + // Start an asynchronous read at a specified offset. The buffer for the data + // being received must be valid for the lifetime of the asynchronous + // operation. + template + void async_read_some_at(implementation_type& impl, boost::uint64_t offset, + const MutableBufferSequence& buffers, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + return; + } + + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); + + // Allocate and construct an operation to wrap the handler. + typedef read_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + handler_ptr ptr(raw_ptr, iocp_service_, buffers, handler); + + // Find first buffer of non-zero length. + boost::asio::mutable_buffer buffer; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + for (DWORD i = 0; iter != end; ++iter, ++i) + { + buffer = boost::asio::mutable_buffer(*iter); + if (boost::asio::buffer_size(buffer) != 0) + break; + } + + // A request to receive 0 bytes on a stream handle is a no-op. + if (boost::asio::buffer_size(buffer) == 0) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code error; + iocp_service_.post(bind_handler(handler, error, 0)); + return; + } + + // Read some data. + DWORD bytes_transferred = 0; + ptr.get()->Offset = offset & 0xFFFFFFFF; + ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF; + BOOL ok = ::ReadFile(impl.handle_, + boost::asio::buffer_cast(buffer), + static_cast(boost::asio::buffer_size(buffer)), + &bytes_transferred, ptr.get()); + DWORD last_error = ::GetLastError(); + if (!ok && last_error != ERROR_IO_PENDING) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); + } + else + { + ptr.release(); + } + } + +private: + // Prevent the use of the null_buffers type with this service. + size_t write_some(implementation_type& impl, + const null_buffers& buffers, boost::system::error_code& ec); + size_t write_some_at(implementation_type& impl, boost::uint64_t offset, + const null_buffers& buffers, boost::system::error_code& ec); + template + void async_write_some(implementation_type& impl, + const null_buffers& buffers, Handler handler); + template + void async_write_some_at(implementation_type& impl, boost::uint64_t offset, + const null_buffers& buffers, Handler handler); + size_t read_some(implementation_type& impl, + const null_buffers& buffers, boost::system::error_code& ec); + size_t read_some_at(implementation_type& impl, boost::uint64_t offset, + const null_buffers& buffers, boost::system::error_code& ec); + template + void async_read_some(implementation_type& impl, + const null_buffers& buffers, Handler handler); + template + void async_read_some_at(implementation_type& impl, boost::uint64_t offset, + const null_buffers& buffers, Handler handler); + + // Helper function to close a handle when the associated object is being + // destroyed. + void close_for_destruction(implementation_type& impl) + { + if (is_open(impl)) + { + ::CloseHandle(impl.handle_); + impl.handle_ = INVALID_HANDLE_VALUE; + impl.safe_cancellation_thread_id_ = 0; + } + } + + // The IOCP service used for running asynchronous operations and dispatching + // handlers. + win_iocp_io_service& iocp_service_; + + // Mutex to protect access to the linked list of implementations. + boost::asio::detail::mutex mutex_; + + // The head of a linked list of all implementations. + implementation_type* impl_list_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +#include + +#endif // BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP diff --git a/win32/include/boost/asio/detail/win_iocp_io_service.hpp b/win32/include/boost/asio/detail/win_iocp_io_service.hpp new file mode 100755 index 000000000..4e2cf6c20 --- /dev/null +++ b/win32/include/boost/asio/detail/win_iocp_io_service.hpp @@ -0,0 +1,730 @@ +// +// win_iocp_io_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP +#define BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_IOCP) + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +class win_iocp_io_service + : public boost::asio::detail::service_base +{ +public: + // Base class for all operations. A function pointer is used instead of + // virtual functions to avoid the associated overhead. + // + // This class inherits from OVERLAPPED so that we can downcast to get back to + // the operation pointer from the LPOVERLAPPED out parameter of + // GetQueuedCompletionStatus. + class operation + : public OVERLAPPED + { + public: + typedef void (*invoke_func_type)(operation*, DWORD, size_t); + typedef void (*destroy_func_type)(operation*); + + operation(win_iocp_io_service& iocp_service, + invoke_func_type invoke_func, destroy_func_type destroy_func) + : outstanding_operations_(&iocp_service.outstanding_operations_), + invoke_func_(invoke_func), + destroy_func_(destroy_func) + { + Internal = 0; + InternalHigh = 0; + Offset = 0; + OffsetHigh = 0; + hEvent = 0; + + ::InterlockedIncrement(outstanding_operations_); + } + + void do_completion(DWORD last_error, size_t bytes_transferred) + { + invoke_func_(this, last_error, bytes_transferred); + } + + void destroy() + { + destroy_func_(this); + } + + protected: + // Prevent deletion through this type. + ~operation() + { + ::InterlockedDecrement(outstanding_operations_); + } + + private: + long* outstanding_operations_; + invoke_func_type invoke_func_; + destroy_func_type destroy_func_; + }; + + + // Constructor. + win_iocp_io_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + iocp_(), + outstanding_work_(0), + outstanding_operations_(0), + stopped_(0), + shutdown_(0), + timer_thread_(0), + timer_interrupt_issued_(false) + { + } + + void init(size_t concurrency_hint) + { + iocp_.handle = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, + static_cast((std::min)(concurrency_hint, DWORD(~0)))); + if (!iocp_.handle) + { + DWORD last_error = ::GetLastError(); + boost::system::system_error e( + boost::system::error_code(last_error, + boost::asio::error::get_system_category()), + "iocp"); + boost::throw_exception(e); + } + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + ::InterlockedExchange(&shutdown_, 1); + + while (::InterlockedExchangeAdd(&outstanding_operations_, 0) > 0) + { + DWORD bytes_transferred = 0; +#if (WINVER < 0x0500) + DWORD completion_key = 0; +#else + DWORD_PTR completion_key = 0; +#endif + LPOVERLAPPED overlapped = 0; + ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred, + &completion_key, &overlapped, INFINITE); + if (overlapped) + static_cast(overlapped)->destroy(); + } + + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + timer_queues_[i]->destroy_timers(); + timer_queues_.clear(); + } + + // Register a handle with the IO completion port. + boost::system::error_code register_handle( + HANDLE handle, boost::system::error_code& ec) + { + if (::CreateIoCompletionPort(handle, iocp_.handle, 0, 0) == 0) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + else + { + ec = boost::system::error_code(); + } + return ec; + } + + // Run the event loop until stopped or no more work. + size_t run(boost::system::error_code& ec) + { + if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) + { + ec = boost::system::error_code(); + return 0; + } + + call_stack::context ctx(this); + + size_t n = 0; + while (do_one(true, ec)) + if (n != (std::numeric_limits::max)()) + ++n; + return n; + } + + // Run until stopped or one operation is performed. + size_t run_one(boost::system::error_code& ec) + { + if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) + { + ec = boost::system::error_code(); + return 0; + } + + call_stack::context ctx(this); + + return do_one(true, ec); + } + + // Poll for operations without blocking. + size_t poll(boost::system::error_code& ec) + { + if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) + { + ec = boost::system::error_code(); + return 0; + } + + call_stack::context ctx(this); + + size_t n = 0; + while (do_one(false, ec)) + if (n != (std::numeric_limits::max)()) + ++n; + return n; + } + + // Poll for one operation without blocking. + size_t poll_one(boost::system::error_code& ec) + { + if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) + { + ec = boost::system::error_code(); + return 0; + } + + call_stack::context ctx(this); + + return do_one(false, ec); + } + + // Stop the event processing loop. + void stop() + { + if (::InterlockedExchange(&stopped_, 1) == 0) + { + if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0)) + { + DWORD last_error = ::GetLastError(); + boost::system::system_error e( + boost::system::error_code(last_error, + boost::asio::error::get_system_category()), + "pqcs"); + boost::throw_exception(e); + } + } + } + + // Reset in preparation for a subsequent run invocation. + void reset() + { + ::InterlockedExchange(&stopped_, 0); + } + + // Notify that some work has started. + void work_started() + { + ::InterlockedIncrement(&outstanding_work_); + } + + // Notify that some work has finished. + void work_finished() + { + if (::InterlockedDecrement(&outstanding_work_) == 0) + stop(); + } + + // Request invocation of the given handler. + template + void dispatch(Handler handler) + { + if (call_stack::contains(this)) + boost_asio_handler_invoke_helpers::invoke(handler, &handler); + else + post(handler); + } + + // Request invocation of the given handler and return immediately. + template + void post(Handler handler) + { + // If the service has been shut down we silently discard the handler. + if (::InterlockedExchangeAdd(&shutdown_, 0) != 0) + return; + + // Allocate and construct an operation to wrap the handler. + typedef handler_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + handler_ptr ptr(raw_ptr, *this, handler); + + // Enqueue the operation on the I/O completion port. + if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, ptr.get())) + { + DWORD last_error = ::GetLastError(); + boost::system::system_error e( + boost::system::error_code(last_error, + boost::asio::error::get_system_category()), + "pqcs"); + boost::throw_exception(e); + } + + // Operation has been successfully posted. + ptr.release(); + } + + // Request invocation of the given OVERLAPPED-derived operation. + void post_completion(operation* op, DWORD op_last_error, + DWORD bytes_transferred) + { + // Enqueue the operation on the I/O completion port. + if (!::PostQueuedCompletionStatus(iocp_.handle, + bytes_transferred, op_last_error, op)) + { + DWORD last_error = ::GetLastError(); + boost::system::system_error e( + boost::system::error_code(last_error, + boost::asio::error::get_system_category()), + "pqcs"); + boost::throw_exception(e); + } + } + + // Add a new timer queue to the service. + template + void add_timer_queue(timer_queue& timer_queue) + { + boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); + timer_queues_.push_back(&timer_queue); + } + + // Remove a timer queue from the service. + template + void remove_timer_queue(timer_queue& timer_queue) + { + boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + { + if (timer_queues_[i] == &timer_queue) + { + timer_queues_.erase(timer_queues_.begin() + i); + return; + } + } + } + + // Schedule a timer in the given timer queue to expire at the specified + // absolute time. The handler object will be invoked when the timer expires. + template + void schedule_timer(timer_queue& timer_queue, + const typename Time_Traits::time_type& time, Handler handler, void* token) + { + // If the service has been shut down we silently discard the timer. + if (::InterlockedExchangeAdd(&shutdown_, 0) != 0) + return; + + boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); + if (timer_queue.enqueue_timer(time, handler, token)) + { + if (!timer_interrupt_issued_) + { + timer_interrupt_issued_ = true; + lock.unlock(); + ::PostQueuedCompletionStatus(iocp_.handle, + 0, steal_timer_dispatching, 0); + } + } + } + + // Cancel the timer associated with the given token. Returns the number of + // handlers that have been posted or dispatched. + template + std::size_t cancel_timer(timer_queue& timer_queue, void* token) + { + // If the service has been shut down we silently ignore the cancellation. + if (::InterlockedExchangeAdd(&shutdown_, 0) != 0) + return 0; + + boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); + std::size_t n = timer_queue.cancel_timer(token); + if (n > 0 && !timer_interrupt_issued_) + { + timer_interrupt_issued_ = true; + lock.unlock(); + ::PostQueuedCompletionStatus(iocp_.handle, + 0, steal_timer_dispatching, 0); + } + return n; + } + +private: + // Dequeues at most one operation from the I/O completion port, and then + // executes it. Returns the number of operations that were dequeued (i.e. + // either 0 or 1). + size_t do_one(bool block, boost::system::error_code& ec) + { + long this_thread_id = static_cast(::GetCurrentThreadId()); + + for (;;) + { + // Try to acquire responsibility for dispatching timers. + bool dispatching_timers = (::InterlockedCompareExchange( + &timer_thread_, this_thread_id, 0) == 0); + + // Calculate timeout for GetQueuedCompletionStatus call. + DWORD timeout = max_timeout; + if (dispatching_timers) + { + boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); + timer_interrupt_issued_ = false; + timeout = get_timeout(); + } + + // Get the next operation from the queue. + DWORD bytes_transferred = 0; +#if (WINVER < 0x0500) + DWORD completion_key = 0; +#else + DWORD_PTR completion_key = 0; +#endif + LPOVERLAPPED overlapped = 0; + ::SetLastError(0); + BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred, + &completion_key, &overlapped, block ? timeout : 0); + DWORD last_error = ::GetLastError(); + + // Dispatch any pending timers. + if (dispatching_timers) + { + try + { + boost::asio::detail::mutex::scoped_lock lock(timer_mutex_); + timer_queues_copy_ = timer_queues_; + for (std::size_t i = 0; i < timer_queues_copy_.size(); ++i) + { + timer_queues_copy_[i]->dispatch_timers(); + timer_queues_copy_[i]->dispatch_cancellations(); + timer_queues_copy_[i]->complete_timers(); + } + } + catch (...) + { + // Transfer responsibility for dispatching timers to another thread. + if (::InterlockedCompareExchange(&timer_thread_, + 0, this_thread_id) == this_thread_id) + { + ::PostQueuedCompletionStatus(iocp_.handle, + 0, transfer_timer_dispatching, 0); + } + + throw; + } + } + + if (!ok && overlapped == 0) + { + if (block && last_error == WAIT_TIMEOUT) + { + // Relinquish responsibility for dispatching timers. + if (dispatching_timers) + { + ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id); + } + + continue; + } + + // Transfer responsibility for dispatching timers to another thread. + if (dispatching_timers && ::InterlockedCompareExchange( + &timer_thread_, 0, this_thread_id) == this_thread_id) + { + ::PostQueuedCompletionStatus(iocp_.handle, + 0, transfer_timer_dispatching, 0); + } + + ec = boost::system::error_code(); + return 0; + } + else if (overlapped) + { + // We may have been passed a last_error value in the completion_key. + if (last_error == 0) + { + last_error = completion_key; + } + + // Transfer responsibility for dispatching timers to another thread. + if (dispatching_timers && ::InterlockedCompareExchange( + &timer_thread_, 0, this_thread_id) == this_thread_id) + { + ::PostQueuedCompletionStatus(iocp_.handle, + 0, transfer_timer_dispatching, 0); + } + + // Ensure that the io_service does not exit due to running out of work + // while we make the upcall. + auto_work work(*this); + + // Dispatch the operation. + operation* op = static_cast(overlapped); + op->do_completion(last_error, bytes_transferred); + + ec = boost::system::error_code(); + return 1; + } + else if (completion_key == transfer_timer_dispatching) + { + // Woken up to try to acquire responsibility for dispatching timers. + ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id); + } + else if (completion_key == steal_timer_dispatching) + { + // Woken up to steal responsibility for dispatching timers. + ::InterlockedExchange(&timer_thread_, 0); + } + else + { + // Relinquish responsibility for dispatching timers. If the io_service + // is not being stopped then the thread will get an opportunity to + // reacquire timer responsibility on the next loop iteration. + if (dispatching_timers) + { + ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id); + } + + // The stopped_ flag is always checked to ensure that any leftover + // interrupts from a previous run invocation are ignored. + if (::InterlockedExchangeAdd(&stopped_, 0) != 0) + { + // Wake up next thread that is blocked on GetQueuedCompletionStatus. + if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0)) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return 0; + } + + ec = boost::system::error_code(); + return 0; + } + } + } + } + + // Check if all timer queues are empty. + bool all_timer_queues_are_empty() const + { + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + if (!timer_queues_[i]->empty()) + return false; + return true; + } + + // Get the timeout value for the GetQueuedCompletionStatus call. The timeout + // value is returned as a number of milliseconds. We will wait no longer than + // 1000 milliseconds. + DWORD get_timeout() + { + if (all_timer_queues_are_empty()) + return max_timeout; + + boost::posix_time::time_duration minimum_wait_duration + = boost::posix_time::milliseconds(max_timeout); + + for (std::size_t i = 0; i < timer_queues_.size(); ++i) + { + boost::posix_time::time_duration wait_duration + = timer_queues_[i]->wait_duration(); + if (wait_duration < minimum_wait_duration) + minimum_wait_duration = wait_duration; + } + + if (minimum_wait_duration > boost::posix_time::time_duration()) + { + int milliseconds = minimum_wait_duration.total_milliseconds(); + return static_cast(milliseconds > 0 ? milliseconds : 1); + } + else + { + return 0; + } + } + + struct auto_work + { + auto_work(win_iocp_io_service& io_service) + : io_service_(io_service) + { + io_service_.work_started(); + } + + ~auto_work() + { + io_service_.work_finished(); + } + + private: + win_iocp_io_service& io_service_; + }; + + template + struct handler_operation + : public operation + { + handler_operation(win_iocp_io_service& io_service, + Handler handler) + : operation(io_service, &handler_operation::do_completion_impl, + &handler_operation::destroy_impl), + io_service_(io_service), + handler_(handler) + { + io_service_.work_started(); + } + + ~handler_operation() + { + io_service_.work_finished(); + } + + private: + // Prevent copying and assignment. + handler_operation(const handler_operation&); + void operator=(const handler_operation&); + + static void do_completion_impl(operation* op, DWORD, size_t) + { + // Take ownership of the operation object. + typedef handler_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(handler_op->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Make the upcall. + boost_asio_handler_invoke_helpers::invoke(handler, &handler); + } + + static void destroy_impl(operation* op) + { + // Take ownership of the operation object. + typedef handler_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + win_iocp_io_service& io_service_; + Handler handler_; + }; + + // The IO completion port used for queueing operations. + struct iocp_holder + { + HANDLE handle; + iocp_holder() : handle(0) {} + ~iocp_holder() { if (handle) ::CloseHandle(handle); } + } iocp_; + + // The count of unfinished work. + long outstanding_work_; + + // The count of unfinished operations. + long outstanding_operations_; + friend class operation; + + // Flag to indicate whether the event loop has been stopped. + long stopped_; + + // Flag to indicate whether the service has been shut down. + long shutdown_; + + enum + { + // Maximum GetQueuedCompletionStatus timeout, in milliseconds. + max_timeout = 500, + + // Completion key value to indicate that responsibility for dispatching + // timers is being cooperatively transferred from one thread to another. + transfer_timer_dispatching = 1, + + // Completion key value to indicate that responsibility for dispatching + // timers should be stolen from another thread. + steal_timer_dispatching = 2 + }; + + // The thread that's currently in charge of dispatching timers. + long timer_thread_; + + // Mutex for protecting access to the timer queues. + mutex timer_mutex_; + + // Whether a thread has been interrupted to process a new timeout. + bool timer_interrupt_issued_; + + // The timer queues. + std::vector timer_queues_; + + // A copy of the timer queues, used when dispatching, cancelling and cleaning + // up timers. The copy is stored as a class data member to avoid unnecessary + // memory allocation. + std::vector timer_queues_copy_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +#include + +#endif // BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP diff --git a/win32/include/boost/asio/detail/win_iocp_io_service_fwd.hpp b/win32/include/boost/asio/detail/win_iocp_io_service_fwd.hpp new file mode 100755 index 000000000..04f4d6c81 --- /dev/null +++ b/win32/include/boost/asio/detail/win_iocp_io_service_fwd.hpp @@ -0,0 +1,52 @@ +// +// win_iocp_io_service_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP +#define BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include + +// This service is only supported on Win32 (NT4 and later). +#if !defined(BOOST_ASIO_DISABLE_IOCP) +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) +#if !defined(UNDER_CE) + +// Define this to indicate that IOCP is supported on the target platform. +#define BOOST_ASIO_HAS_IOCP 1 + +namespace boost { +namespace asio { +namespace detail { + +class win_iocp_io_service; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(UNDER_CE) +#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_DISABLE_IOCP) + +#include + +#endif // BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP diff --git a/win32/include/boost/asio/detail/win_iocp_serial_port_service.hpp b/win32/include/boost/asio/detail/win_iocp_serial_port_service.hpp new file mode 100755 index 000000000..c543f28ad --- /dev/null +++ b/win32/include/boost/asio/detail/win_iocp_serial_port_service.hpp @@ -0,0 +1,294 @@ +// +// win_iocp_serial_port_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP +#define BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include + +#if defined(BOOST_ASIO_HAS_IOCP) + +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +// Extend win_iocp_handle_service to provide serial port support. +class win_iocp_serial_port_service + : public boost::asio::detail::service_base +{ +public: + // The native type of a stream handle. + typedef win_iocp_handle_service::native_type native_type; + + // The implementation type of the stream handle. + typedef win_iocp_handle_service::implementation_type implementation_type; + + win_iocp_serial_port_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + win_iocp_serial_port_service>(io_service), + handle_service_( + boost::asio::use_service(io_service)) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Construct a new handle implementation. + void construct(implementation_type& impl) + { + handle_service_.construct(impl); + } + + // Destroy a handle implementation. + void destroy(implementation_type& impl) + { + handle_service_.destroy(impl); + } + + // Open the serial port using the specified device name. + boost::system::error_code open(implementation_type& impl, + const std::string& device, boost::system::error_code& ec) + { + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + // For convenience, add a leading \\.\ sequence if not already present. + std::string name = (device[0] == '\\') ? device : "\\\\.\\" + device; + + // Open a handle to the serial port. + ::HANDLE handle = ::CreateFileA(name.c_str(), + GENERIC_READ | GENERIC_WRITE, 0, 0, + OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + if (handle == INVALID_HANDLE_VALUE) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + // Determine the initial serial port parameters. + using namespace std; // For memcpy. + ::DCB dcb; + memset(&dcb, 0, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + if (!::GetCommState(handle, &dcb)) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(handle); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + // Set some default serial port parameters. This implementation does not + // support changing these, so they might as well be in a known state. + dcb.fBinary = TRUE; // Win32 only supports binary mode. + dcb.fDsrSensitivity = FALSE; + dcb.fNull = FALSE; // Do not ignore NULL characters. + dcb.fAbortOnError = FALSE; // Ignore serial framing errors. + if (!::SetCommState(handle, &dcb)) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(handle); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + // Set up timeouts so that the serial port will behave similarly to a + // network socket. Reads wait for at least one byte, then return with + // whatever they have. Writes return once everything is out the door. + ::COMMTIMEOUTS timeouts; + timeouts.ReadIntervalTimeout = 1; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + if (!::SetCommTimeouts(handle, &timeouts)) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(handle); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + // We're done. Take ownership of the serial port handle. + if (handle_service_.assign(impl, handle, ec)) + ::CloseHandle(handle); + return ec; + } + + // Assign a native handle to a handle implementation. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_handle, boost::system::error_code& ec) + { + return handle_service_.assign(impl, native_handle, ec); + } + + // Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return handle_service_.is_open(impl); + } + + // Destroy a handle implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return handle_service_.close(impl, ec); + } + + // Get the native handle representation. + native_type native(implementation_type& impl) + { + return handle_service_.native(impl); + } + + // Cancel all operations associated with the handle. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return handle_service_.cancel(impl, ec); + } + + // Set an option on the serial port. + template + boost::system::error_code set_option(implementation_type& impl, + const SettableSerialPortOption& option, boost::system::error_code& ec) + { + using namespace std; // For memcpy. + + ::DCB dcb; + memset(&dcb, 0, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + if (!::GetCommState(handle_service_.native(impl), &dcb)) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + if (option.store(dcb, ec)) + return ec; + + if (!::SetCommState(handle_service_.native(impl), &dcb)) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Get an option from the serial port. + template + boost::system::error_code get_option(const implementation_type& impl, + GettableSerialPortOption& option, boost::system::error_code& ec) const + { + using namespace std; // For memcpy. + + ::DCB dcb; + memset(&dcb, 0, sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + if (!::GetCommState(handle_service_.native(impl), &dcb)) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return ec; + } + + return option.load(dcb, ec); + } + + // Send a break sequence to the serial port. + boost::system::error_code send_break(implementation_type& impl, + boost::system::error_code& ec) + { + ec = boost::asio::error::operation_not_supported; + return ec; + } + + // Write the given data. Returns the number of bytes sent. + template + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return handle_service_.write_some(impl, buffers, ec); + } + + // Start an asynchronous write. The data being written must be valid for the + // lifetime of the asynchronous operation. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, Handler handler) + { + handle_service_.async_write_some(impl, buffers, handler); + } + + // Read some data. Returns the number of bytes received. + template + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return handle_service_.read_some(impl, buffers, ec); + } + + // Start an asynchronous read. The buffer for the data being received must be + // valid for the lifetime of the asynchronous operation. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, Handler handler) + { + handle_service_.async_read_some(impl, buffers, handler); + } + +private: + // The handle service used for initiating asynchronous operations. + win_iocp_handle_service& handle_service_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +#include + +#endif // BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP diff --git a/win32/include/boost/asio/detail/win_iocp_socket_service.hpp b/win32/include/boost/asio/detail/win_iocp_socket_service.hpp new file mode 100755 index 000000000..380727fbd --- /dev/null +++ b/win32/include/boost/asio/detail/win_iocp_socket_service.hpp @@ -0,0 +1,2415 @@ +// +// win_iocp_socket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP +#define BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_IOCP) + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class win_iocp_socket_service + : public boost::asio::detail::service_base > +{ +public: + // The protocol type. + typedef Protocol protocol_type; + + // The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + // Base class for all operations. + typedef win_iocp_io_service::operation operation; + + struct noop_deleter { void operator()(void*) {} }; + typedef boost::shared_ptr shared_cancel_token_type; + typedef boost::weak_ptr weak_cancel_token_type; + + // The native type of a socket. + class native_type + { + public: + native_type(socket_type s) + : socket_(s), + have_remote_endpoint_(false) + { + } + + native_type(socket_type s, const endpoint_type& ep) + : socket_(s), + have_remote_endpoint_(true), + remote_endpoint_(ep) + { + } + + void operator=(socket_type s) + { + socket_ = s; + have_remote_endpoint_ = false; + remote_endpoint_ = endpoint_type(); + } + + operator socket_type() const + { + return socket_; + } + + HANDLE as_handle() const + { + return reinterpret_cast(socket_); + } + + bool have_remote_endpoint() const + { + return have_remote_endpoint_; + } + + endpoint_type remote_endpoint() const + { + return remote_endpoint_; + } + + private: + socket_type socket_; + bool have_remote_endpoint_; + endpoint_type remote_endpoint_; + }; + + // The type of the reactor used for connect operations. + typedef detail::select_reactor reactor_type; + + // The implementation type of the socket. + class implementation_type + { + public: + // Default constructor. + implementation_type() + : socket_(invalid_socket), + flags_(0), + cancel_token_(), + protocol_(endpoint_type().protocol()), + next_(0), + prev_(0) + { + } + + private: + // Only this service will have access to the internal values. + friend class win_iocp_socket_service; + + // The native socket representation. + native_type socket_; + + enum + { + enable_connection_aborted = 1, // User wants connection_aborted errors. + close_might_block = 2, // User set linger option for blocking close. + user_set_non_blocking = 4 // The user wants a non-blocking socket. + }; + + // Flags indicating the current state of the socket. + unsigned char flags_; + + // We use a shared pointer as a cancellation token here to work around the + // broken Windows support for cancellation. MSDN says that when you call + // closesocket any outstanding WSARecv or WSASend operations will complete + // with the error ERROR_OPERATION_ABORTED. In practice they complete with + // ERROR_NETNAME_DELETED, which means you can't tell the difference between + // a local cancellation and the socket being hard-closed by the peer. + shared_cancel_token_type cancel_token_; + + // The protocol associated with the socket. + protocol_type protocol_; + + // Per-descriptor data used by the reactor. + reactor_type::per_descriptor_data reactor_data_; + +#if defined(BOOST_ASIO_ENABLE_CANCELIO) + // The ID of the thread from which it is safe to cancel asynchronous + // operations. 0 means no asynchronous operations have been started yet. + // ~0 means asynchronous operations have been started from more than one + // thread, and cancellation is not supported for the socket. + DWORD safe_cancellation_thread_id_; +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) + + // Pointers to adjacent socket implementations in linked list. + implementation_type* next_; + implementation_type* prev_; + }; + + // The maximum number of buffers to support in a single operation. + enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; + + // Constructor. + win_iocp_socket_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + win_iocp_socket_service >(io_service), + iocp_service_(boost::asio::use_service(io_service)), + reactor_(0), + mutex_(), + impl_list_(0) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + // Close all implementations, causing all operations to complete. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + implementation_type* impl = impl_list_; + while (impl) + { + boost::system::error_code ignored_ec; + close_for_destruction(*impl); + impl = impl->next_; + } + } + + // Construct a new socket implementation. + void construct(implementation_type& impl) + { + impl.socket_ = invalid_socket; + impl.flags_ = 0; + impl.cancel_token_.reset(); +#if defined(BOOST_ASIO_ENABLE_CANCELIO) + impl.safe_cancellation_thread_id_ = 0; +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) + + // Insert implementation into linked list of all implementations. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + impl.next_ = impl_list_; + impl.prev_ = 0; + if (impl_list_) + impl_list_->prev_ = &impl; + impl_list_ = &impl; + } + + // Destroy a socket implementation. + void destroy(implementation_type& impl) + { + close_for_destruction(impl); + + // Remove implementation from linked list of all implementations. + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (impl_list_ == &impl) + impl_list_ = impl.next_; + if (impl.prev_) + impl.prev_->next_ = impl.next_; + if (impl.next_) + impl.next_->prev_= impl.prev_; + impl.next_ = 0; + impl.prev_ = 0; + } + + // Open a new socket implementation. + boost::system::error_code open(implementation_type& impl, + const protocol_type& protocol, boost::system::error_code& ec) + { + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + socket_holder sock(socket_ops::socket(protocol.family(), protocol.type(), + protocol.protocol(), ec)); + if (sock.get() == invalid_socket) + return ec; + + HANDLE sock_as_handle = reinterpret_cast(sock.get()); + if (iocp_service_.register_handle(sock_as_handle, ec)) + return ec; + + impl.socket_ = sock.release(); + impl.flags_ = 0; + impl.cancel_token_.reset(static_cast(0), noop_deleter()); + impl.protocol_ = protocol; + ec = boost::system::error_code(); + return ec; + } + + // Assign a native socket to a socket implementation. + boost::system::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_type& native_socket, + boost::system::error_code& ec) + { + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + if (iocp_service_.register_handle(native_socket.as_handle(), ec)) + return ec; + + impl.socket_ = native_socket; + impl.flags_ = 0; + impl.cancel_token_.reset(static_cast(0), noop_deleter()); + impl.protocol_ = protocol; + ec = boost::system::error_code(); + return ec; + } + + // Determine whether the socket is open. + bool is_open(const implementation_type& impl) const + { + return impl.socket_ != invalid_socket; + } + + // Destroy a socket implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + if (is_open(impl)) + { + // Check if the reactor was created, in which case we need to close the + // socket on the reactor as well to cancel any operations that might be + // running there. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (reactor) + reactor->close_descriptor(impl.socket_, impl.reactor_data_); + + if (socket_ops::close(impl.socket_, ec) == socket_error_retval) + return ec; + + impl.socket_ = invalid_socket; + impl.flags_ = 0; + impl.cancel_token_.reset(); +#if defined(BOOST_ASIO_ENABLE_CANCELIO) + impl.safe_cancellation_thread_id_ = 0; +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) + } + + ec = boost::system::error_code(); + return ec; + } + + // Get the native socket representation. + native_type native(implementation_type& impl) + { + return impl.socket_; + } + + // Cancel all operations associated with the socket. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress( + ::GetModuleHandleA("KERNEL32"), "CancelIoEx")) + { + // The version of Windows supports cancellation from any thread. + typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED); + cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr; + socket_type sock = impl.socket_; + HANDLE sock_as_handle = reinterpret_cast(sock); + if (!cancel_io_ex(sock_as_handle, 0)) + { + DWORD last_error = ::GetLastError(); + if (last_error == ERROR_NOT_FOUND) + { + // ERROR_NOT_FOUND means that there were no operations to be + // cancelled. We swallow this error to match the behaviour on other + // platforms. + ec = boost::system::error_code(); + } + else + { + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + } + else + { + ec = boost::system::error_code(); + } + } +#if defined(BOOST_ASIO_ENABLE_CANCELIO) + else if (impl.safe_cancellation_thread_id_ == 0) + { + // No operations have been started, so there's nothing to cancel. + ec = boost::system::error_code(); + } + else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId()) + { + // Asynchronous operations have been started from the current thread only, + // so it is safe to try to cancel them using CancelIo. + socket_type sock = impl.socket_; + HANDLE sock_as_handle = reinterpret_cast(sock); + if (!::CancelIo(sock_as_handle)) + { + DWORD last_error = ::GetLastError(); + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + } + else + { + ec = boost::system::error_code(); + } + } + else + { + // Asynchronous operations have been started from more than one thread, + // so cancellation is not safe. + ec = boost::asio::error::operation_not_supported; + } +#else // defined(BOOST_ASIO_ENABLE_CANCELIO) + else + { + // Cancellation is not supported as CancelIo may not be used. + ec = boost::asio::error::operation_not_supported; + } +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) + + return ec; + } + + // Determine whether the socket is at the out-of-band data mark. + bool at_mark(const implementation_type& impl, + boost::system::error_code& ec) const + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return false; + } + + boost::asio::detail::ioctl_arg_type value = 0; + socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec); + return ec ? false : value != 0; + } + + // Determine the number of bytes available for reading. + std::size_t available(const implementation_type& impl, + boost::system::error_code& ec) const + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + boost::asio::detail::ioctl_arg_type value = 0; + socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec); + return ec ? static_cast(0) : static_cast(value); + } + + // Bind the socket to the specified local endpoint. + boost::system::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); + return ec; + } + + // Place the socket into the state where it will listen for new connections. + boost::system::error_code listen(implementation_type& impl, int backlog, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + socket_ops::listen(impl.socket_, backlog, ec); + return ec; + } + + // Set a socket option. + template + boost::system::error_code set_option(implementation_type& impl, + const Option& option, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + if (option.level(impl.protocol_) == custom_socket_option_level + && option.name(impl.protocol_) == enable_connection_aborted_option) + { + if (option.size(impl.protocol_) != sizeof(int)) + { + ec = boost::asio::error::invalid_argument; + } + else + { + if (*reinterpret_cast(option.data(impl.protocol_))) + impl.flags_ |= implementation_type::enable_connection_aborted; + else + impl.flags_ &= ~implementation_type::enable_connection_aborted; + ec = boost::system::error_code(); + } + return ec; + } + else + { + if (option.level(impl.protocol_) == SOL_SOCKET + && option.name(impl.protocol_) == SO_LINGER) + { + const ::linger* linger_option = + reinterpret_cast(option.data(impl.protocol_)); + if (linger_option->l_onoff != 0 && linger_option->l_linger != 0) + impl.flags_ |= implementation_type::close_might_block; + else + impl.flags_ &= ~implementation_type::close_might_block; + } + + socket_ops::setsockopt(impl.socket_, + option.level(impl.protocol_), option.name(impl.protocol_), + option.data(impl.protocol_), option.size(impl.protocol_), ec); + return ec; + } + } + + // Set a socket option. + template + boost::system::error_code get_option(const implementation_type& impl, + Option& option, boost::system::error_code& ec) const + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + if (option.level(impl.protocol_) == custom_socket_option_level + && option.name(impl.protocol_) == enable_connection_aborted_option) + { + if (option.size(impl.protocol_) != sizeof(int)) + { + ec = boost::asio::error::invalid_argument; + } + else + { + int* target = reinterpret_cast(option.data(impl.protocol_)); + if (impl.flags_ & implementation_type::enable_connection_aborted) + *target = 1; + else + *target = 0; + option.resize(impl.protocol_, sizeof(int)); + ec = boost::system::error_code(); + } + return ec; + } + else + { + size_t size = option.size(impl.protocol_); + socket_ops::getsockopt(impl.socket_, + option.level(impl.protocol_), option.name(impl.protocol_), + option.data(impl.protocol_), &size, ec); + if (!ec) + option.resize(impl.protocol_, size); + return ec; + } + } + + // Perform an IO control command on the socket. + template + boost::system::error_code io_control(implementation_type& impl, + IO_Control_Command& command, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + socket_ops::ioctl(impl.socket_, command.name(), + static_cast(command.data()), ec); + + if (!ec && command.name() == static_cast(FIONBIO)) + { + if (command.get()) + impl.flags_ |= implementation_type::user_set_non_blocking; + else + impl.flags_ &= ~implementation_type::user_set_non_blocking; + } + + return ec; + } + + // Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return endpoint_type(); + } + + endpoint_type endpoint; + std::size_t addr_len = endpoint.capacity(); + if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) + return endpoint_type(); + endpoint.resize(addr_len); + return endpoint; + } + + // Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return endpoint_type(); + } + + if (impl.socket_.have_remote_endpoint()) + { + // Check if socket is still connected. + DWORD connect_time = 0; + size_t connect_time_len = sizeof(connect_time); + if (socket_ops::getsockopt(impl.socket_, SOL_SOCKET, SO_CONNECT_TIME, + &connect_time, &connect_time_len, ec) == socket_error_retval) + { + return endpoint_type(); + } + if (connect_time == 0xFFFFFFFF) + { + ec = boost::asio::error::not_connected; + return endpoint_type(); + } + + ec = boost::system::error_code(); + return impl.socket_.remote_endpoint(); + } + else + { + endpoint_type endpoint; + std::size_t addr_len = endpoint.capacity(); + if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec)) + return endpoint_type(); + endpoint.resize(addr_len); + return endpoint; + } + } + + /// Disable sends or receives on the socket. + boost::system::error_code shutdown(implementation_type& impl, + socket_base::shutdown_type what, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + socket_ops::shutdown(impl.socket_, what, ec); + return ec; + } + + // Send the given data to the peer. Returns the number of bytes sent. + template + size_t send(implementation_type& impl, const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Copy buffers into WSABUF array. + ::WSABUF bufs[max_buffers]; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + DWORD i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + bufs[i].len = static_cast(boost::asio::buffer_size(buffer)); + bufs[i].buf = const_cast( + boost::asio::buffer_cast(buffer)); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to receive 0 bytes on a stream socket is a no-op. + if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) + { + ec = boost::system::error_code(); + return 0; + } + + // Send the data. + DWORD bytes_transferred = 0; + int result = ::WSASend(impl.socket_, bufs, + i, &bytes_transferred, flags, 0, 0); + if (result != 0) + { + DWORD last_error = ::WSAGetLastError(); + if (last_error == ERROR_NETNAME_DELETED) + last_error = WSAECONNRESET; + else if (last_error == ERROR_PORT_UNREACHABLE) + last_error = WSAECONNREFUSED; + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return 0; + } + + ec = boost::system::error_code(); + return bytes_transferred; + } + + // Wait until data can be sent without blocking. + size_t send(implementation_type& impl, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, ec); + + return 0; + } + + template + class send_operation + : public operation + { + public: + send_operation(win_iocp_io_service& io_service, + weak_cancel_token_type cancel_token, + const ConstBufferSequence& buffers, Handler handler) + : operation(io_service, + &send_operation::do_completion_impl, + &send_operation::destroy_impl), + work_(io_service.get_io_service()), + cancel_token_(cancel_token), + buffers_(buffers), + handler_(handler) + { + } + + private: + static void do_completion_impl(operation* op, + DWORD last_error, size_t bytes_transferred) + { + // Take ownership of the operation object. + typedef send_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + // Check whether buffers are still valid. + typename ConstBufferSequence::const_iterator iter + = handler_op->buffers_.begin(); + typename ConstBufferSequence::const_iterator end + = handler_op->buffers_.end(); + while (iter != end) + { + boost::asio::const_buffer buffer(*iter); + boost::asio::buffer_cast(buffer); + ++iter; + } +#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + + // Map non-portable errors to their portable counterparts. + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + if (ec.value() == ERROR_NETNAME_DELETED) + { + if (handler_op->cancel_token_.expired()) + ec = boost::asio::error::operation_aborted; + else + ec = boost::asio::error::connection_reset; + } + else if (ec.value() == ERROR_PORT_UNREACHABLE) + { + ec = boost::asio::error::connection_refused; + } + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(handler_op->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Call the handler. + boost_asio_handler_invoke_helpers::invoke( + detail::bind_handler(handler, ec, bytes_transferred), &handler); + } + + static void destroy_impl(operation* op) + { + // Take ownership of the operation object. + typedef send_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + boost::asio::io_service::work work_; + weak_cancel_token_type cancel_token_; + ConstBufferSequence buffers_; + Handler handler_; + }; + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template + void async_send(implementation_type& impl, const ConstBufferSequence& buffers, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + return; + } + +#if defined(BOOST_ASIO_ENABLE_CANCELIO) + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) + + // Allocate and construct an operation to wrap the handler. + typedef send_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + handler_ptr ptr(raw_ptr, iocp_service_, + impl.cancel_token_, buffers, handler); + + // Copy buffers into WSABUF array. + ::WSABUF bufs[max_buffers]; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + DWORD i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + bufs[i].len = static_cast(boost::asio::buffer_size(buffer)); + bufs[i].buf = const_cast( + boost::asio::buffer_cast(buffer)); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to receive 0 bytes on a stream socket is a no-op. + if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code error; + iocp_service_.post(bind_handler(handler, error, 0)); + return; + } + + // Send the data. + DWORD bytes_transferred = 0; + int result = ::WSASend(impl.socket_, bufs, i, + &bytes_transferred, flags, ptr.get(), 0); + DWORD last_error = ::WSAGetLastError(); + + // Check if the operation completed immediately. + if (result != 0 && last_error != WSA_IO_PENDING) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); + } + else + { + ptr.release(); + } + } + + template + class null_buffers_operation + { + public: + null_buffers_operation(boost::asio::io_service& io_service, Handler handler) + : work_(io_service), + handler_(handler) + { + } + + bool perform(boost::system::error_code&, + std::size_t& bytes_transferred) + { + bytes_transferred = 0; + return true; + } + + void complete(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + work_.get_io_service().post(bind_handler( + handler_, ec, bytes_transferred)); + } + + private: + boost::asio::io_service::work work_; + Handler handler_; + }; + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send(implementation_type& impl, const null_buffers&, + socket_base::message_flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + // Check if the reactor was already obtained from the io_service. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (!reactor) + { + reactor = &(boost::asio::use_service( + this->get_io_service())); + interlocked_exchange_pointer( + reinterpret_cast(&reactor_), reactor); + } + + reactor->start_write_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + + // Send a datagram to the specified endpoint. Returns the number of bytes + // sent. + template + size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Copy buffers into WSABUF array. + ::WSABUF bufs[max_buffers]; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + DWORD i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + bufs[i].len = static_cast(boost::asio::buffer_size(buffer)); + bufs[i].buf = const_cast( + boost::asio::buffer_cast(buffer)); + } + + // Send the data. + DWORD bytes_transferred = 0; + int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred, + flags, destination.data(), static_cast(destination.size()), 0, 0); + if (result != 0) + { + DWORD last_error = ::WSAGetLastError(); + if (last_error == ERROR_PORT_UNREACHABLE) + last_error = WSAECONNREFUSED; + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return 0; + } + + ec = boost::system::error_code(); + return bytes_transferred; + } + + // Wait until data can be sent without blocking. + size_t send_to(implementation_type& impl, const null_buffers&, + socket_base::message_flags, const endpoint_type&, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, ec); + + return 0; + } + + template + class send_to_operation + : public operation + { + public: + send_to_operation(win_iocp_io_service& io_service, + const ConstBufferSequence& buffers, Handler handler) + : operation(io_service, + &send_to_operation::do_completion_impl, + &send_to_operation::destroy_impl), + work_(io_service.get_io_service()), + buffers_(buffers), + handler_(handler) + { + } + + private: + static void do_completion_impl(operation* op, + DWORD last_error, size_t bytes_transferred) + { + // Take ownership of the operation object. + typedef send_to_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + // Check whether buffers are still valid. + typename ConstBufferSequence::const_iterator iter + = handler_op->buffers_.begin(); + typename ConstBufferSequence::const_iterator end + = handler_op->buffers_.end(); + while (iter != end) + { + boost::asio::const_buffer buffer(*iter); + boost::asio::buffer_cast(buffer); + ++iter; + } +#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + + // Map non-portable errors to their portable counterparts. + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + if (ec.value() == ERROR_PORT_UNREACHABLE) + { + ec = boost::asio::error::connection_refused; + } + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(handler_op->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Call the handler. + boost_asio_handler_invoke_helpers::invoke( + detail::bind_handler(handler, ec, bytes_transferred), &handler); + } + + static void destroy_impl(operation* op) + { + // Take ownership of the operation object. + typedef send_to_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + boost::asio::io_service::work work_; + ConstBufferSequence buffers_; + Handler handler_; + }; + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template + void async_send_to(implementation_type& impl, + const ConstBufferSequence& buffers, const endpoint_type& destination, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + return; + } + +#if defined(BOOST_ASIO_ENABLE_CANCELIO) + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) + + // Allocate and construct an operation to wrap the handler. + typedef send_to_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + handler_ptr ptr(raw_ptr, iocp_service_, buffers, handler); + + // Copy buffers into WSABUF array. + ::WSABUF bufs[max_buffers]; + typename ConstBufferSequence::const_iterator iter = buffers.begin(); + typename ConstBufferSequence::const_iterator end = buffers.end(); + DWORD i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::const_buffer buffer(*iter); + bufs[i].len = static_cast(boost::asio::buffer_size(buffer)); + bufs[i].buf = const_cast( + boost::asio::buffer_cast(buffer)); + } + + // Send the data. + DWORD bytes_transferred = 0; + int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred, flags, + destination.data(), static_cast(destination.size()), ptr.get(), 0); + DWORD last_error = ::WSAGetLastError(); + + // Check if the operation completed immediately. + if (result != 0 && last_error != WSA_IO_PENDING) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); + } + else + { + ptr.release(); + } + } + + // Start an asynchronous wait until data can be sent without blocking. + template + void async_send_to(implementation_type& impl, const null_buffers&, + socket_base::message_flags, const endpoint_type&, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + // Check if the reactor was already obtained from the io_service. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (!reactor) + { + reactor = &(boost::asio::use_service( + this->get_io_service())); + interlocked_exchange_pointer( + reinterpret_cast(&reactor_), reactor); + } + + reactor->start_write_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + + // Receive some data from the peer. Returns the number of bytes received. + template + size_t receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Copy buffers into WSABUF array. + ::WSABUF bufs[max_buffers]; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + DWORD i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + bufs[i].len = static_cast(boost::asio::buffer_size(buffer)); + bufs[i].buf = boost::asio::buffer_cast(buffer); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to receive 0 bytes on a stream socket is a no-op. + if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) + { + ec = boost::system::error_code(); + return 0; + } + + // Receive some data. + DWORD bytes_transferred = 0; + DWORD recv_flags = flags; + int result = ::WSARecv(impl.socket_, bufs, i, + &bytes_transferred, &recv_flags, 0, 0); + if (result != 0) + { + DWORD last_error = ::WSAGetLastError(); + if (last_error == ERROR_NETNAME_DELETED) + last_error = WSAECONNRESET; + else if (last_error == ERROR_PORT_UNREACHABLE) + last_error = WSAECONNREFUSED; + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return 0; + } + if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM) + { + ec = boost::asio::error::eof; + return 0; + } + + ec = boost::system::error_code(); + return bytes_transferred; + } + + // Wait until data can be received without blocking. + size_t receive(implementation_type& impl, const null_buffers&, + socket_base::message_flags, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, ec); + + return 0; + } + + template + class receive_operation + : public operation + { + public: + receive_operation(int protocol_type, win_iocp_io_service& io_service, + weak_cancel_token_type cancel_token, + const MutableBufferSequence& buffers, Handler handler) + : operation(io_service, + &receive_operation< + MutableBufferSequence, Handler>::do_completion_impl, + &receive_operation< + MutableBufferSequence, Handler>::destroy_impl), + protocol_type_(protocol_type), + work_(io_service.get_io_service()), + cancel_token_(cancel_token), + buffers_(buffers), + handler_(handler) + { + } + + private: + static void do_completion_impl(operation* op, + DWORD last_error, size_t bytes_transferred) + { + // Take ownership of the operation object. + typedef receive_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + // Check whether buffers are still valid. + typename MutableBufferSequence::const_iterator iter + = handler_op->buffers_.begin(); + typename MutableBufferSequence::const_iterator end + = handler_op->buffers_.end(); + while (iter != end) + { + boost::asio::mutable_buffer buffer(*iter); + boost::asio::buffer_cast(buffer); + ++iter; + } +#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + + // Map non-portable errors to their portable counterparts. + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + if (ec.value() == ERROR_NETNAME_DELETED) + { + if (handler_op->cancel_token_.expired()) + ec = boost::asio::error::operation_aborted; + else + ec = boost::asio::error::connection_reset; + } + else if (ec.value() == ERROR_PORT_UNREACHABLE) + { + ec = boost::asio::error::connection_refused; + } + + // Check for connection closed. + else if (!ec && bytes_transferred == 0 + && handler_op->protocol_type_ == SOCK_STREAM + && !boost::is_same::value) + { + ec = boost::asio::error::eof; + } + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(handler_op->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Call the handler. + boost_asio_handler_invoke_helpers::invoke( + detail::bind_handler(handler, ec, bytes_transferred), &handler); + } + + static void destroy_impl(operation* op) + { + // Take ownership of the operation object. + typedef receive_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + int protocol_type_; + boost::asio::io_service::work work_; + weak_cancel_token_type cancel_token_; + MutableBufferSequence buffers_; + Handler handler_; + }; + + // Start an asynchronous receive. The buffer for the data being received + // must be valid for the lifetime of the asynchronous operation. + template + void async_receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + return; + } + +#if defined(BOOST_ASIO_ENABLE_CANCELIO) + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) + + // Allocate and construct an operation to wrap the handler. + typedef receive_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + int protocol_type = impl.protocol_.type(); + handler_ptr ptr(raw_ptr, protocol_type, + iocp_service_, impl.cancel_token_, buffers, handler); + + // Copy buffers into WSABUF array. + ::WSABUF bufs[max_buffers]; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + DWORD i = 0; + size_t total_buffer_size = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + bufs[i].len = static_cast(boost::asio::buffer_size(buffer)); + bufs[i].buf = boost::asio::buffer_cast(buffer); + total_buffer_size += boost::asio::buffer_size(buffer); + } + + // A request to receive 0 bytes on a stream socket is a no-op. + if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code error; + iocp_service_.post(bind_handler(handler, error, 0)); + return; + } + + // Receive some data. + DWORD bytes_transferred = 0; + DWORD recv_flags = flags; + int result = ::WSARecv(impl.socket_, bufs, i, + &bytes_transferred, &recv_flags, ptr.get(), 0); + DWORD last_error = ::WSAGetLastError(); + if (result != 0 && last_error != WSA_IO_PENDING) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); + } + else + { + ptr.release(); + } + } + + // Wait until data can be received without blocking. + template + void async_receive(implementation_type& impl, const null_buffers& buffers, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else if (impl.protocol_.type() == SOCK_STREAM) + { + // For stream sockets on Windows, we may issue a 0-byte overlapped + // WSARecv to wait until there is data available on the socket. + +#if defined(BOOST_ASIO_ENABLE_CANCELIO) + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) + + // Allocate and construct an operation to wrap the handler. + typedef receive_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + int protocol_type = impl.protocol_.type(); + handler_ptr ptr(raw_ptr, protocol_type, + iocp_service_, impl.cancel_token_, buffers, handler); + + // Issue a receive operation with an empty buffer. + ::WSABUF buf = { 0, 0 }; + DWORD bytes_transferred = 0; + DWORD recv_flags = flags; + int result = ::WSARecv(impl.socket_, &buf, 1, + &bytes_transferred, &recv_flags, ptr.get(), 0); + DWORD last_error = ::WSAGetLastError(); + if (result != 0 && last_error != WSA_IO_PENDING) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); + } + else + { + ptr.release(); + } + } + else + { + // Check if the reactor was already obtained from the io_service. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (!reactor) + { + reactor = &(boost::asio::use_service( + this->get_io_service())); + interlocked_exchange_pointer( + reinterpret_cast(&reactor_), reactor); + } + + if (flags & socket_base::message_out_of_band) + { + reactor->start_except_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler)); + } + else + { + reactor->start_read_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + } + + // Receive a datagram with the endpoint of the sender. Returns the number of + // bytes received. + template + size_t receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Copy buffers into WSABUF array. + ::WSABUF bufs[max_buffers]; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + DWORD i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + bufs[i].len = static_cast(boost::asio::buffer_size(buffer)); + bufs[i].buf = boost::asio::buffer_cast(buffer); + } + + // Receive some data. + DWORD bytes_transferred = 0; + DWORD recv_flags = flags; + int endpoint_size = static_cast(sender_endpoint.capacity()); + int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred, + &recv_flags, sender_endpoint.data(), &endpoint_size, 0, 0); + if (result != 0) + { + DWORD last_error = ::WSAGetLastError(); + if (last_error == ERROR_PORT_UNREACHABLE) + last_error = WSAECONNREFUSED; + ec = boost::system::error_code(last_error, + boost::asio::error::get_system_category()); + return 0; + } + if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM) + { + ec = boost::asio::error::eof; + return 0; + } + + sender_endpoint.resize(static_cast(endpoint_size)); + + ec = boost::system::error_code(); + return bytes_transferred; + } + + // Wait until data can be received without blocking. + size_t receive_from(implementation_type& impl, + const null_buffers&, endpoint_type& sender_endpoint, + socket_base::message_flags, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, ec); + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + return 0; + } + + template + class receive_from_operation + : public operation + { + public: + receive_from_operation(int protocol_type, win_iocp_io_service& io_service, + endpoint_type& endpoint, const MutableBufferSequence& buffers, + Handler handler) + : operation(io_service, + &receive_from_operation< + MutableBufferSequence, Handler>::do_completion_impl, + &receive_from_operation< + MutableBufferSequence, Handler>::destroy_impl), + protocol_type_(protocol_type), + endpoint_(endpoint), + endpoint_size_(static_cast(endpoint.capacity())), + work_(io_service.get_io_service()), + buffers_(buffers), + handler_(handler) + { + } + + int& endpoint_size() + { + return endpoint_size_; + } + + private: + static void do_completion_impl(operation* op, + DWORD last_error, size_t bytes_transferred) + { + // Take ownership of the operation object. + typedef receive_from_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + // Check whether buffers are still valid. + typename MutableBufferSequence::const_iterator iter + = handler_op->buffers_.begin(); + typename MutableBufferSequence::const_iterator end + = handler_op->buffers_.end(); + while (iter != end) + { + boost::asio::mutable_buffer buffer(*iter); + boost::asio::buffer_cast(buffer); + ++iter; + } +#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + + // Map non-portable errors to their portable counterparts. + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + if (ec.value() == ERROR_PORT_UNREACHABLE) + { + ec = boost::asio::error::connection_refused; + } + + // Check for connection closed. + if (!ec && bytes_transferred == 0 + && handler_op->protocol_type_ == SOCK_STREAM) + { + ec = boost::asio::error::eof; + } + + // Record the size of the endpoint returned by the operation. + handler_op->endpoint_.resize(handler_op->endpoint_size_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(handler_op->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Call the handler. + boost_asio_handler_invoke_helpers::invoke( + detail::bind_handler(handler, ec, bytes_transferred), &handler); + } + + static void destroy_impl(operation* op) + { + // Take ownership of the operation object. + typedef receive_from_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + int protocol_type_; + endpoint_type& endpoint_; + int endpoint_size_; + boost::asio::io_service::work work_; + MutableBufferSequence buffers_; + Handler handler_; + }; + + // Start an asynchronous receive. The buffer for the data being received and + // the sender_endpoint object must both be valid for the lifetime of the + // asynchronous operation. + template + void async_receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endp, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + return; + } + +#if defined(BOOST_ASIO_ENABLE_CANCELIO) + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) + + // Allocate and construct an operation to wrap the handler. + typedef receive_from_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + int protocol_type = impl.protocol_.type(); + handler_ptr ptr(raw_ptr, protocol_type, + iocp_service_, sender_endp, buffers, handler); + + // Copy buffers into WSABUF array. + ::WSABUF bufs[max_buffers]; + typename MutableBufferSequence::const_iterator iter = buffers.begin(); + typename MutableBufferSequence::const_iterator end = buffers.end(); + DWORD i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + { + boost::asio::mutable_buffer buffer(*iter); + bufs[i].len = static_cast(boost::asio::buffer_size(buffer)); + bufs[i].buf = boost::asio::buffer_cast(buffer); + } + + // Receive some data. + DWORD bytes_transferred = 0; + DWORD recv_flags = flags; + int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred, + &recv_flags, sender_endp.data(), &ptr.get()->endpoint_size(), + ptr.get(), 0); + DWORD last_error = ::WSAGetLastError(); + if (result != 0 && last_error != WSA_IO_PENDING) + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); + } + else + { + ptr.release(); + } + } + + // Wait until data can be received without blocking. + template + void async_receive_from(implementation_type& impl, + const null_buffers&, endpoint_type& sender_endpoint, + socket_base::message_flags flags, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor, 0)); + } + else + { + // Check if the reactor was already obtained from the io_service. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (!reactor) + { + reactor = &(boost::asio::use_service( + this->get_io_service())); + interlocked_exchange_pointer( + reinterpret_cast(&reactor_), reactor); + } + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + if (flags & socket_base::message_out_of_band) + { + reactor->start_except_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler)); + } + else + { + reactor->start_read_op(impl.socket_, impl.reactor_data_, + null_buffers_operation(this->get_io_service(), handler), + false); + } + } + } + + // Accept a new connection. + template + boost::system::error_code accept(implementation_type& impl, Socket& peer, + endpoint_type* peer_endpoint, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + // We cannot accept a socket that is already open. + if (peer.is_open()) + { + ec = boost::asio::error::already_open; + return ec; + } + + for (;;) + { + socket_holder new_socket; + std::size_t addr_len = 0; + if (peer_endpoint) + { + addr_len = peer_endpoint->capacity(); + new_socket.reset(socket_ops::accept(impl.socket_, + peer_endpoint->data(), &addr_len, ec)); + } + else + { + new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec)); + } + + if (ec) + { + if (ec == boost::asio::error::connection_aborted + && !(impl.flags_ & implementation_type::enable_connection_aborted)) + { + // Retry accept operation. + continue; + } + else + { + return ec; + } + } + + if (peer_endpoint) + peer_endpoint->resize(addr_len); + + peer.assign(impl.protocol_, new_socket.get(), ec); + if (!ec) + new_socket.release(); + return ec; + } + } + + template + class accept_operation + : public operation + { + public: + accept_operation(win_iocp_io_service& io_service, + socket_type socket, socket_type new_socket, Socket& peer, + const protocol_type& protocol, endpoint_type* peer_endpoint, + bool enable_connection_aborted, Handler handler) + : operation(io_service, + &accept_operation::do_completion_impl, + &accept_operation::destroy_impl), + io_service_(io_service), + socket_(socket), + new_socket_(new_socket), + peer_(peer), + protocol_(protocol), + peer_endpoint_(peer_endpoint), + work_(io_service.get_io_service()), + enable_connection_aborted_(enable_connection_aborted), + handler_(handler) + { + } + + socket_type new_socket() + { + return new_socket_.get(); + } + + void* output_buffer() + { + return output_buffer_; + } + + DWORD address_length() + { + return sizeof(sockaddr_storage_type) + 16; + } + + private: + static void do_completion_impl(operation* op, DWORD last_error, size_t) + { + // Take ownership of the operation object. + typedef accept_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + + // Map Windows error ERROR_NETNAME_DELETED to connection_aborted. + if (last_error == ERROR_NETNAME_DELETED) + { + last_error = WSAECONNABORTED; + } + + // Restart the accept operation if we got the connection_aborted error + // and the enable_connection_aborted socket option is not set. + if (last_error == WSAECONNABORTED + && !ptr.get()->enable_connection_aborted_) + { + // Reset OVERLAPPED structure. + ptr.get()->Internal = 0; + ptr.get()->InternalHigh = 0; + ptr.get()->Offset = 0; + ptr.get()->OffsetHigh = 0; + ptr.get()->hEvent = 0; + + // Create a new socket for the next connection, since the AcceptEx call + // fails with WSAEINVAL if we try to reuse the same socket. + boost::system::error_code ec; + ptr.get()->new_socket_.reset(); + ptr.get()->new_socket_.reset(socket_ops::socket( + ptr.get()->protocol_.family(), ptr.get()->protocol_.type(), + ptr.get()->protocol_.protocol(), ec)); + if (ptr.get()->new_socket() != invalid_socket) + { + // Accept a connection. + DWORD bytes_read = 0; + BOOL result = ::AcceptEx(ptr.get()->socket_, ptr.get()->new_socket(), + ptr.get()->output_buffer(), 0, ptr.get()->address_length(), + ptr.get()->address_length(), &bytes_read, ptr.get()); + last_error = ::WSAGetLastError(); + + // Check if the operation completed immediately. + if (!result && last_error != WSA_IO_PENDING) + { + if (last_error == ERROR_NETNAME_DELETED + || last_error == WSAECONNABORTED) + { + // Post this handler so that operation will be restarted again. + ptr.get()->io_service_.post_completion(ptr.get(), last_error, 0); + ptr.release(); + return; + } + else + { + // Operation already complete. Continue with rest of this handler. + } + } + else + { + // Asynchronous operation has been successfully restarted. + ptr.release(); + return; + } + } + } + + // Get the address of the peer. + endpoint_type peer_endpoint; + if (last_error == 0) + { + LPSOCKADDR local_addr = 0; + int local_addr_length = 0; + LPSOCKADDR remote_addr = 0; + int remote_addr_length = 0; + GetAcceptExSockaddrs(handler_op->output_buffer(), 0, + handler_op->address_length(), handler_op->address_length(), + &local_addr, &local_addr_length, &remote_addr, &remote_addr_length); + if (static_cast(remote_addr_length) + > peer_endpoint.capacity()) + { + last_error = WSAEINVAL; + } + else + { + using namespace std; // For memcpy. + memcpy(peer_endpoint.data(), remote_addr, remote_addr_length); + peer_endpoint.resize(static_cast(remote_addr_length)); + } + } + + // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname + // and getpeername will work on the accepted socket. + if (last_error == 0) + { + SOCKET update_ctx_param = handler_op->socket_; + boost::system::error_code ec; + if (socket_ops::setsockopt(handler_op->new_socket_.get(), + SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, + &update_ctx_param, sizeof(SOCKET), ec) != 0) + { + last_error = ec.value(); + } + } + + // If the socket was successfully accepted, transfer ownership of the + // socket to the peer object. + if (last_error == 0) + { + boost::system::error_code ec; + handler_op->peer_.assign(handler_op->protocol_, + native_type(handler_op->new_socket_.get(), peer_endpoint), ec); + if (ec) + last_error = ec.value(); + else + handler_op->new_socket_.release(); + } + + // Pass endpoint back to caller. + if (handler_op->peer_endpoint_) + *handler_op->peer_endpoint_ = peer_endpoint; + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. + Handler handler(handler_op->handler_); + + // Free the memory associated with the handler. + ptr.reset(); + + // Call the handler. + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + boost_asio_handler_invoke_helpers::invoke( + detail::bind_handler(handler, ec), &handler); + } + + static void destroy_impl(operation* op) + { + // Take ownership of the operation object. + typedef accept_operation op_type; + op_type* handler_op(static_cast(op)); + typedef handler_alloc_traits alloc_traits; + handler_ptr ptr(handler_op->handler_, handler_op); + + // A sub-object of the handler may be the true owner of the memory + // associated with the handler. Consequently, a local copy of the handler + // is required to ensure that any owning sub-object remains valid until + // after we have deallocated the memory here. + Handler handler(handler_op->handler_); + (void)handler; + + // Free the memory associated with the handler. + ptr.reset(); + } + + win_iocp_io_service& io_service_; + socket_type socket_; + socket_holder new_socket_; + Socket& peer_; + protocol_type protocol_; + endpoint_type* peer_endpoint_; + boost::asio::io_service::work work_; + unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2]; + bool enable_connection_aborted_; + Handler handler_; + }; + + // Start an asynchronous accept. The peer and peer_endpoint objects + // must be valid until the accept's handler is invoked. + template + void async_accept(implementation_type& impl, Socket& peer, + endpoint_type* peer_endpoint, Handler handler) + { + // Check whether acceptor has been initialised. + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor)); + return; + } + + // Check that peer socket has not already been opened. + if (peer.is_open()) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::already_open)); + return; + } + +#if defined(BOOST_ASIO_ENABLE_CANCELIO) + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) + + // Create a new socket for the connection. + boost::system::error_code ec; + socket_holder sock(socket_ops::socket(impl.protocol_.family(), + impl.protocol_.type(), impl.protocol_.protocol(), ec)); + if (sock.get() == invalid_socket) + { + this->get_io_service().post(bind_handler(handler, ec)); + return; + } + + // Allocate and construct an operation to wrap the handler. + typedef accept_operation value_type; + typedef handler_alloc_traits alloc_traits; + raw_handler_ptr raw_ptr(handler); + socket_type new_socket = sock.get(); + bool enable_connection_aborted = + (impl.flags_ & implementation_type::enable_connection_aborted); + handler_ptr ptr(raw_ptr, + iocp_service_, impl.socket_, new_socket, peer, impl.protocol_, + peer_endpoint, enable_connection_aborted, handler); + sock.release(); + + // Accept a connection. + DWORD bytes_read = 0; + BOOL result = ::AcceptEx(impl.socket_, ptr.get()->new_socket(), + ptr.get()->output_buffer(), 0, ptr.get()->address_length(), + ptr.get()->address_length(), &bytes_read, ptr.get()); + DWORD last_error = ::WSAGetLastError(); + + // Check if the operation completed immediately. + if (!result && last_error != WSA_IO_PENDING) + { + if (!enable_connection_aborted + && (last_error == ERROR_NETNAME_DELETED + || last_error == WSAECONNABORTED)) + { + // Post handler so that operation will be restarted again. We do not + // perform the AcceptEx again here to avoid the possibility of starving + // other handlers. + iocp_service_.post_completion(ptr.get(), last_error, 0); + ptr.release(); + } + else + { + boost::asio::io_service::work work(this->get_io_service()); + ptr.reset(); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + iocp_service_.post(bind_handler(handler, ec)); + } + } + else + { + ptr.release(); + } + } + + // Connect the socket to the specified endpoint. + boost::system::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + // Perform the connect operation. + socket_ops::connect(impl.socket_, + peer_endpoint.data(), peer_endpoint.size(), ec); + return ec; + } + + template + class connect_operation + { + public: + connect_operation(socket_type socket, bool user_set_non_blocking, + boost::asio::io_service& io_service, Handler handler) + : socket_(socket), + user_set_non_blocking_(user_set_non_blocking), + io_service_(io_service), + work_(io_service), + handler_(handler) + { + } + + bool perform(boost::system::error_code& ec, + std::size_t& bytes_transferred) + { + // Check whether the operation was successful. + if (ec) + return true; + + // Get the error code from the connect operation. + int connect_error = 0; + size_t connect_error_len = sizeof(connect_error); + if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR, + &connect_error, &connect_error_len, ec) == socket_error_retval) + return true; + + // If connection failed then post the handler with the error code. + if (connect_error) + { + ec = boost::system::error_code(connect_error, + boost::asio::error::get_system_category()); + return true; + } + + // Revert socket to blocking mode unless the user requested otherwise. + if (!user_set_non_blocking_) + { + ioctl_arg_type non_blocking = 0; + if (socket_ops::ioctl(socket_, FIONBIO, &non_blocking, ec)) + return true; + } + + // Post the result of the successful connection operation. + ec = boost::system::error_code(); + return true; + } + + void complete(const boost::system::error_code& ec, std::size_t) + { + io_service_.post(bind_handler(handler_, ec)); + } + + private: + socket_type socket_; + bool user_set_non_blocking_; + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + Handler handler_; + }; + + // Start an asynchronous connect. + template + void async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, Handler handler) + { + if (!is_open(impl)) + { + this->get_io_service().post(bind_handler(handler, + boost::asio::error::bad_descriptor)); + return; + } + +#if defined(BOOST_ASIO_ENABLE_CANCELIO) + // Update the ID of the thread from which cancellation is safe. + if (impl.safe_cancellation_thread_id_ == 0) + impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); + else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) + impl.safe_cancellation_thread_id_ = ~DWORD(0); +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) + + // Check if the reactor was already obtained from the io_service. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (!reactor) + { + reactor = &(boost::asio::use_service( + this->get_io_service())); + interlocked_exchange_pointer( + reinterpret_cast(&reactor_), reactor); + } + + // Mark the socket as non-blocking so that the connection will take place + // asynchronously. + ioctl_arg_type non_blocking = 1; + boost::system::error_code ec; + if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) + { + this->get_io_service().post(bind_handler(handler, ec)); + return; + } + + // Start the connect operation. + if (socket_ops::connect(impl.socket_, peer_endpoint.data(), + peer_endpoint.size(), ec) == 0) + { + // Revert socket to blocking mode unless the user requested otherwise. + if (!(impl.flags_ & implementation_type::user_set_non_blocking)) + { + non_blocking = 0; + socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec); + } + + // The connect operation has finished successfully so we need to post the + // handler immediately. + this->get_io_service().post(bind_handler(handler, ec)); + } + else if (ec == boost::asio::error::in_progress + || ec == boost::asio::error::would_block) + { + // The connection is happening in the background, and we need to wait + // until the socket becomes writeable. + boost::shared_ptr completed(new bool(false)); + reactor->start_connect_op(impl.socket_, impl.reactor_data_, + connect_operation( + impl.socket_, + (impl.flags_ & implementation_type::user_set_non_blocking) != 0, + this->get_io_service(), handler)); + } + else + { + // Revert socket to blocking mode unless the user requested otherwise. + if (!(impl.flags_ & implementation_type::user_set_non_blocking)) + { + non_blocking = 0; + boost::system::error_code ignored_ec; + socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec); + } + + // The connect operation has failed, so post the handler immediately. + this->get_io_service().post(bind_handler(handler, ec)); + } + } + +private: + // Helper function to close a socket when the associated object is being + // destroyed. + void close_for_destruction(implementation_type& impl) + { + if (is_open(impl)) + { + // Check if the reactor was created, in which case we need to close the + // socket on the reactor as well to cancel any operations that might be + // running there. + reactor_type* reactor = static_cast( + interlocked_compare_exchange_pointer( + reinterpret_cast(&reactor_), 0, 0)); + if (reactor) + reactor->close_descriptor(impl.socket_, impl.reactor_data_); + + // The socket destructor must not block. If the user has changed the + // linger option to block in the foreground, we will change it back to the + // default so that the closure is performed in the background. + if (impl.flags_ & implementation_type::close_might_block) + { + ::linger opt; + opt.l_onoff = 0; + opt.l_linger = 0; + boost::system::error_code ignored_ec; + socket_ops::setsockopt(impl.socket_, + SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec); + } + + boost::system::error_code ignored_ec; + socket_ops::close(impl.socket_, ignored_ec); + impl.socket_ = invalid_socket; + impl.flags_ = 0; + impl.cancel_token_.reset(); +#if defined(BOOST_ASIO_ENABLE_CANCELIO) + impl.safe_cancellation_thread_id_ = 0; +#endif // defined(BOOST_ASIO_ENABLE_CANCELIO) + } + } + + // Helper function to emulate InterlockedCompareExchangePointer functionality + // for: + // - very old Platform SDKs; and + // - platform SDKs where MSVC's /Wp64 option causes spurious warnings. + void* interlocked_compare_exchange_pointer(void** dest, void* exch, void* cmp) + { +#if defined(_M_IX86) + return reinterpret_cast(InterlockedCompareExchange( + reinterpret_cast(dest), reinterpret_cast(exch), + reinterpret_cast(cmp))); +#else + return InterlockedCompareExchangePointer(dest, exch, cmp); +#endif + } + + // Helper function to emulate InterlockedExchangePointer functionality for: + // - very old Platform SDKs; and + // - platform SDKs where MSVC's /Wp64 option causes spurious warnings. + void* interlocked_exchange_pointer(void** dest, void* val) + { +#if defined(_M_IX86) + return reinterpret_cast(InterlockedExchange( + reinterpret_cast(dest), reinterpret_cast(val))); +#else + return InterlockedExchangePointer(dest, val); +#endif + } + + // The IOCP service used for running asynchronous operations and dispatching + // handlers. + win_iocp_io_service& iocp_service_; + + // The reactor used for performing connect operations. This object is created + // only if needed. + reactor_type* reactor_; + + // Mutex to protect access to the linked list of implementations. + boost::asio::detail::mutex mutex_; + + // The head of a linked list of all implementations. + implementation_type* impl_list_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +#include + +#endif // BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP diff --git a/win32/include/boost/asio/detail/win_mutex.hpp b/win32/include/boost/asio/detail/win_mutex.hpp new file mode 100755 index 000000000..4c83a4c90 --- /dev/null +++ b/win32/include/boost/asio/detail/win_mutex.hpp @@ -0,0 +1,151 @@ +// +// win_mutex.hpp +// ~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_MUTEX_HPP +#define BOOST_ASIO_DETAIL_WIN_MUTEX_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#if defined(BOOST_WINDOWS) + +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +class win_mutex + : private noncopyable +{ +public: + typedef boost::asio::detail::scoped_lock scoped_lock; + + // Constructor. + win_mutex() + { + int error = do_init(); + if (error != 0) + { + boost::system::system_error e( + boost::system::error_code(error, + boost::asio::error::get_system_category()), + "mutex"); + boost::throw_exception(e); + } + } + + // Destructor. + ~win_mutex() + { + ::DeleteCriticalSection(&crit_section_); + } + + // Lock the mutex. + void lock() + { + int error = do_lock(); + if (error != 0) + { + boost::system::system_error e( + boost::system::error_code(error, + boost::asio::error::get_system_category()), + "mutex"); + boost::throw_exception(e); + } + } + + // Unlock the mutex. + void unlock() + { + ::LeaveCriticalSection(&crit_section_); + } + +private: + // Initialisation must be performed in a separate function to the constructor + // since the compiler does not support the use of structured exceptions and + // C++ exceptions in the same function. + int do_init() + { +#if defined(__MINGW32__) + // Not sure if MinGW supports structured exception handling, so for now + // we'll just call the Windows API and hope. + ::InitializeCriticalSection(&crit_section_); + return 0; +#else + __try + { + ::InitializeCriticalSection(&crit_section_); + } + __except(GetExceptionCode() == STATUS_NO_MEMORY + ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) + { + return ERROR_OUTOFMEMORY; + } + + return 0; +#endif + } + + // Locking must be performed in a separate function to lock() since the + // compiler does not support the use of structured exceptions and C++ + // exceptions in the same function. + int do_lock() + { +#if defined(__MINGW32__) + // Not sure if MinGW supports structured exception handling, so for now + // we'll just call the Windows API and hope. + ::EnterCriticalSection(&crit_section_); + return 0; +#else + __try + { + ::EnterCriticalSection(&crit_section_); + } + __except(GetExceptionCode() == STATUS_INVALID_HANDLE + || GetExceptionCode() == STATUS_NO_MEMORY + ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) + { + if (GetExceptionCode() == STATUS_NO_MEMORY) + return ERROR_OUTOFMEMORY; + return ERROR_INVALID_HANDLE; + } + + return 0; +#endif + } + + ::CRITICAL_SECTION crit_section_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_WINDOWS) + +#include + +#endif // BOOST_ASIO_DETAIL_WIN_MUTEX_HPP diff --git a/win32/include/boost/asio/detail/win_signal_blocker.hpp b/win32/include/boost/asio/detail/win_signal_blocker.hpp new file mode 100755 index 000000000..78206084e --- /dev/null +++ b/win32/include/boost/asio/detail/win_signal_blocker.hpp @@ -0,0 +1,69 @@ +// +// win_signal_blocker.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_SIGNAL_BLOCKER_HPP +#define BOOST_ASIO_DETAIL_WIN_SIGNAL_BLOCKER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + +#include + +namespace boost { +namespace asio { +namespace detail { + +class win_signal_blocker + : private noncopyable +{ +public: + // Constructor blocks all signals for the calling thread. + win_signal_blocker() + { + // No-op. + } + + // Destructor restores the previous signal mask. + ~win_signal_blocker() + { + // No-op. + } + + // Block all signals for the calling thread. + void block() + { + // No-op. + } + + // Restore the previous signal mask. + void unblock() + { + // No-op. + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + +#include + +#endif // BOOST_ASIO_DETAIL_WIN_SIGNAL_BLOCKER_HPP diff --git a/win32/include/boost/asio/detail/win_thread.hpp b/win32/include/boost/asio/detail/win_thread.hpp new file mode 100755 index 000000000..a8d5b7af7 --- /dev/null +++ b/win32/include/boost/asio/detail/win_thread.hpp @@ -0,0 +1,196 @@ +// +// win_thread.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_THREAD_HPP +#define BOOST_ASIO_DETAIL_WIN_THREAD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#if defined(BOOST_WINDOWS) && !defined(UNDER_CE) + +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +unsigned int __stdcall win_thread_function(void* arg); + +class win_thread + : private noncopyable +{ +public: + // The purpose of the thread. + enum purpose { internal, external }; + + // Constructor. + template + win_thread(Function f, purpose p = internal) + : exit_event_(0) + { + std::auto_ptr arg(new func(f)); + + ::HANDLE entry_event = 0; + if (p == internal) + { + arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0); + if (!entry_event) + { + DWORD last_error = ::GetLastError(); + boost::system::system_error e( + boost::system::error_code(last_error, + boost::asio::error::get_system_category()), + "thread.entry_event"); + boost::throw_exception(e); + } + + arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0); + if (!exit_event_) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(entry_event); + boost::system::system_error e( + boost::system::error_code(last_error, + boost::asio::error::get_system_category()), + "thread.exit_event"); + boost::throw_exception(e); + } + } + + unsigned int thread_id = 0; + thread_ = reinterpret_cast(::_beginthreadex(0, 0, + win_thread_function, arg.get(), 0, &thread_id)); + if (!thread_) + { + DWORD last_error = ::GetLastError(); + if (entry_event) + ::CloseHandle(entry_event); + if (exit_event_) + ::CloseHandle(exit_event_); + boost::system::system_error e( + boost::system::error_code(last_error, + boost::asio::error::get_system_category()), + "thread"); + boost::throw_exception(e); + } + arg.release(); + + if (entry_event) + { + ::WaitForSingleObject(entry_event, INFINITE); + ::CloseHandle(entry_event); + } + } + + // Destructor. + ~win_thread() + { + ::CloseHandle(thread_); + + // The exit_event_ handle is deliberately allowed to leak here since it + // is an error for the owner of an internal thread not to join() it. + } + + // Wait for the thread to exit. + void join() + { + if (exit_event_) + { + ::WaitForSingleObject(exit_event_, INFINITE); + ::CloseHandle(exit_event_); + ::TerminateThread(thread_, 0); + } + else + { + ::WaitForSingleObject(thread_, INFINITE); + } + } + +private: + friend unsigned int __stdcall win_thread_function(void* arg); + + class func_base + { + public: + virtual ~func_base() {} + virtual void run() = 0; + ::HANDLE entry_event_; + ::HANDLE exit_event_; + }; + + template + class func + : public func_base + { + public: + func(Function f) + : f_(f) + { + } + + virtual void run() + { + f_(); + } + + private: + Function f_; + }; + + ::HANDLE thread_; + ::HANDLE exit_event_; +}; + +inline unsigned int __stdcall win_thread_function(void* arg) +{ + std::auto_ptr func( + static_cast(arg)); + + if (func->entry_event_) + ::SetEvent(func->entry_event_); + + func->run(); + + if (HANDLE exit_event = func->exit_event_) + { + func.reset(); + ::SetEvent(exit_event); + ::Sleep(INFINITE); + } + + return 0; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE) + +#include + +#endif // BOOST_ASIO_DETAIL_WIN_THREAD_HPP diff --git a/win32/include/boost/asio/detail/win_tss_ptr.hpp b/win32/include/boost/asio/detail/win_tss_ptr.hpp new file mode 100755 index 000000000..981069381 --- /dev/null +++ b/win32/include/boost/asio/detail/win_tss_ptr.hpp @@ -0,0 +1,97 @@ +// +// win_tss_ptr.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WIN_TSS_PTR_HPP +#define BOOST_ASIO_DETAIL_WIN_TSS_PTR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#if defined(BOOST_WINDOWS) + +#include +#include +#include + +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class win_tss_ptr + : private noncopyable +{ +public: +#if defined(UNDER_CE) + enum { out_of_indexes = 0xFFFFFFFF }; +#else + enum { out_of_indexes = TLS_OUT_OF_INDEXES }; +#endif + + // Constructor. + win_tss_ptr() + { + tss_key_ = ::TlsAlloc(); + if (tss_key_ == out_of_indexes) + { + DWORD last_error = ::GetLastError(); + boost::system::system_error e( + boost::system::error_code(last_error, + boost::asio::error::get_system_category()), + "tss"); + boost::throw_exception(e); + } + } + + // Destructor. + ~win_tss_ptr() + { + ::TlsFree(tss_key_); + } + + // Get the value. + operator T*() const + { + return static_cast(::TlsGetValue(tss_key_)); + } + + // Set the value. + void operator=(T* value) + { + ::TlsSetValue(tss_key_, value); + } + +private: + // Thread-specific storage to allow unlocked access to determine whether a + // thread is a member of the pool. + DWORD tss_key_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_WINDOWS) + +#include + +#endif // BOOST_ASIO_DETAIL_WIN_TSS_PTR_HPP diff --git a/win32/include/boost/asio/detail/wince_thread.hpp b/win32/include/boost/asio/detail/wince_thread.hpp new file mode 100755 index 000000000..c1c6589db --- /dev/null +++ b/win32/include/boost/asio/detail/wince_thread.hpp @@ -0,0 +1,129 @@ +// +// wince_thread.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WINCE_THREAD_HPP +#define BOOST_ASIO_DETAIL_WINCE_THREAD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +DWORD WINAPI wince_thread_function(LPVOID arg); + +class wince_thread + : private noncopyable +{ +public: + // The purpose of the thread. + enum purpose { internal, external }; + + // Constructor. + template + wince_thread(Function f, purpose = internal) + { + std::auto_ptr arg(new func(f)); + DWORD thread_id = 0; + thread_ = ::CreateThread(0, 0, wince_thread_function, + arg.get(), 0, &thread_id); + if (!thread_) + { + DWORD last_error = ::GetLastError(); + boost::system::system_error e( + boost::system::error_code(last_error, + boost::asio::error::get_system_category()), + "thread"); + boost::throw_exception(e); + } + arg.release(); + } + + // Destructor. + ~wince_thread() + { + ::CloseHandle(thread_); + } + + // Wait for the thread to exit. + void join() + { + ::WaitForSingleObject(thread_, INFINITE); + } + +private: + friend DWORD WINAPI wince_thread_function(LPVOID arg); + + class func_base + { + public: + virtual ~func_base() {} + virtual void run() = 0; + }; + + template + class func + : public func_base + { + public: + func(Function f) + : f_(f) + { + } + + virtual void run() + { + f_(); + } + + private: + Function f_; + }; + + ::HANDLE thread_; +}; + +inline DWORD WINAPI wince_thread_function(LPVOID arg) +{ + std::auto_ptr func( + static_cast(arg)); + func->run(); + return 0; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE) + +#include + +#endif // BOOST_ASIO_DETAIL_WINCE_THREAD_HPP diff --git a/win32/include/boost/asio/detail/winsock_init.hpp b/win32/include/boost/asio/detail/winsock_init.hpp new file mode 100755 index 000000000..5e56d03c2 --- /dev/null +++ b/win32/include/boost/asio/detail/winsock_init.hpp @@ -0,0 +1,122 @@ +// +// winsock_init.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WINSOCK_INIT_HPP +#define BOOST_ASIO_DETAIL_WINSOCK_INIT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class winsock_init + : private noncopyable +{ +private: + // Structure to perform the actual initialisation. + struct do_init + { + do_init() + { + WSADATA wsa_data; + result_ = ::WSAStartup(MAKEWORD(Major, Minor), &wsa_data); + } + + ~do_init() + { + ::WSACleanup(); + } + + int result() const + { + return result_; + } + + // Helper function to manage a do_init singleton. The static instance of the + // winsock_init object ensures that this function is always called before + // main, and therefore before any other threads can get started. The do_init + // instance must be static in this function to ensure that it gets + // initialised before any other global objects try to use it. + static boost::shared_ptr instance() + { + static boost::shared_ptr init(new do_init); + return init; + } + + private: + int result_; + }; + +public: + // Constructor. + winsock_init() + : ref_(do_init::instance()) + { + // Check whether winsock was successfully initialised. This check is not + // performed for the global instance since there will be nobody around to + // catch the exception. + if (this != &instance_ && ref_->result() != 0) + { + boost::system::system_error e( + boost::system::error_code(ref_->result(), + boost::asio::error::get_system_category()), + "winsock"); + boost::throw_exception(e); + } + } + + // Destructor. + ~winsock_init() + { + } + +private: + // Instance to force initialisation of winsock at global scope. + static winsock_init instance_; + + // Reference to singleton do_init object to ensure that winsock does not get + // cleaned up until the last user has finished with it. + boost::shared_ptr ref_; +}; + +template +winsock_init winsock_init::instance_; + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + +#include + +#endif // BOOST_ASIO_DETAIL_WINSOCK_INIT_HPP diff --git a/win32/include/boost/asio/detail/wrapped_handler.hpp b/win32/include/boost/asio/detail/wrapped_handler.hpp new file mode 100755 index 000000000..4fd275806 --- /dev/null +++ b/win32/include/boost/asio/detail/wrapped_handler.hpp @@ -0,0 +1,211 @@ +// +// wrapped_handler.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_WRAPPED_HANDLER_HPP +#define BOOST_ASIO_DETAIL_WRAPPED_HANDLER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include +#include + +namespace boost { +namespace asio { +namespace detail { + +template +class wrapped_handler +{ +public: + typedef void result_type; + + wrapped_handler( + typename boost::add_reference::type dispatcher, + Handler handler) + : dispatcher_(dispatcher), + handler_(handler) + { + } + + void operator()() + { + dispatcher_.dispatch(handler_); + } + + void operator()() const + { + dispatcher_.dispatch(handler_); + } + + template + void operator()(const Arg1& arg1) + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1)); + } + + template + void operator()(const Arg1& arg1) const + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1)); + } + + template + void operator()(const Arg1& arg1, const Arg2& arg2) + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2)); + } + + template + void operator()(const Arg1& arg1, const Arg2& arg2) const + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2)); + } + + template + void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3)); + } + + template + void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) const + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3)); + } + + template + void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, + const Arg4& arg4) + { + dispatcher_.dispatch( + detail::bind_handler(handler_, arg1, arg2, arg3, arg4)); + } + + template + void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, + const Arg4& arg4) const + { + dispatcher_.dispatch( + detail::bind_handler(handler_, arg1, arg2, arg3, arg4)); + } + + template + void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, + const Arg4& arg4, const Arg5& arg5) + { + dispatcher_.dispatch( + detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5)); + } + + template + void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, + const Arg4& arg4, const Arg5& arg5) const + { + dispatcher_.dispatch( + detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5)); + } + +//private: + Dispatcher dispatcher_; + Handler handler_; +}; + +template +class rewrapped_handler +{ +public: + explicit rewrapped_handler(const Handler& handler, const Context& context) + : handler_(handler), + context_(context) + { + } + + void operator()() + { + handler_(); + } + + void operator()() const + { + handler_(); + } + +//private: + Handler handler_; + Context context_; +}; + +template +inline void* asio_handler_allocate(std::size_t size, + wrapped_handler* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); +} + +template +inline void asio_handler_deallocate(void* pointer, std::size_t size, + wrapped_handler* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); +} + +template +inline void asio_handler_invoke(const Function& function, + wrapped_handler* this_handler) +{ + this_handler->dispatcher_.dispatch( + rewrapped_handler( + function, this_handler->handler_)); +} + +template +inline void* asio_handler_allocate(std::size_t size, + rewrapped_handler* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->context_); +} + +template +inline void asio_handler_deallocate(void* pointer, std::size_t size, + rewrapped_handler* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->context_); +} + +template +inline void asio_handler_invoke(const Function& function, + rewrapped_handler* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->context_); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_DETAIL_WRAPPED_HANDLER_HPP diff --git a/win32/include/boost/asio/error.hpp b/win32/include/boost/asio/error.hpp new file mode 100755 index 000000000..5e3a190da --- /dev/null +++ b/win32/include/boost/asio/error.hpp @@ -0,0 +1,442 @@ +// +// error.hpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_ERROR_HPP +#define BOOST_ASIO_ERROR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include + +#if defined(GENERATING_DOCUMENTATION) +/// INTERNAL ONLY. +# define BOOST_ASIO_NATIVE_ERROR(e) implementation_defined +/// INTERNAL ONLY. +# define BOOST_ASIO_SOCKET_ERROR(e) implementation_defined +/// INTERNAL ONLY. +# define BOOST_ASIO_NETDB_ERROR(e) implementation_defined +/// INTERNAL ONLY. +# define BOOST_ASIO_GETADDRINFO_ERROR(e) implementation_defined +/// INTERNAL ONLY. +# define BOOST_ASIO_WIN_OR_POSIX(e_win, e_posix) implementation_defined +#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) +# define BOOST_ASIO_NATIVE_ERROR(e) e +# define BOOST_ASIO_SOCKET_ERROR(e) WSA ## e +# define BOOST_ASIO_NETDB_ERROR(e) WSA ## e +# define BOOST_ASIO_GETADDRINFO_ERROR(e) WSA ## e +# define BOOST_ASIO_WIN_OR_POSIX(e_win, e_posix) e_win +#else +# define BOOST_ASIO_NATIVE_ERROR(e) e +# define BOOST_ASIO_SOCKET_ERROR(e) e +# define BOOST_ASIO_NETDB_ERROR(e) e +# define BOOST_ASIO_GETADDRINFO_ERROR(e) e +# define BOOST_ASIO_WIN_OR_POSIX(e_win, e_posix) e_posix +#endif + +namespace boost { +namespace asio { +namespace error { + +enum basic_errors +{ + /// Permission denied. + access_denied = BOOST_ASIO_SOCKET_ERROR(EACCES), + + /// Address family not supported by protocol. + address_family_not_supported = BOOST_ASIO_SOCKET_ERROR(EAFNOSUPPORT), + + /// Address already in use. + address_in_use = BOOST_ASIO_SOCKET_ERROR(EADDRINUSE), + + /// Transport endpoint is already connected. + already_connected = BOOST_ASIO_SOCKET_ERROR(EISCONN), + + /// Operation already in progress. + already_started = BOOST_ASIO_SOCKET_ERROR(EALREADY), + + /// Broken pipe. + broken_pipe = BOOST_ASIO_WIN_OR_POSIX( + BOOST_ASIO_NATIVE_ERROR(ERROR_BROKEN_PIPE), + BOOST_ASIO_NATIVE_ERROR(EPIPE)), + + /// A connection has been aborted. + connection_aborted = BOOST_ASIO_SOCKET_ERROR(ECONNABORTED), + + /// Connection refused. + connection_refused = BOOST_ASIO_SOCKET_ERROR(ECONNREFUSED), + + /// Connection reset by peer. + connection_reset = BOOST_ASIO_SOCKET_ERROR(ECONNRESET), + + /// Bad file descriptor. + bad_descriptor = BOOST_ASIO_SOCKET_ERROR(EBADF), + + /// Bad address. + fault = BOOST_ASIO_SOCKET_ERROR(EFAULT), + + /// No route to host. + host_unreachable = BOOST_ASIO_SOCKET_ERROR(EHOSTUNREACH), + + /// Operation now in progress. + in_progress = BOOST_ASIO_SOCKET_ERROR(EINPROGRESS), + + /// Interrupted system call. + interrupted = BOOST_ASIO_SOCKET_ERROR(EINTR), + + /// Invalid argument. + invalid_argument = BOOST_ASIO_SOCKET_ERROR(EINVAL), + + /// Message too long. + message_size = BOOST_ASIO_SOCKET_ERROR(EMSGSIZE), + + /// The name was too long. + name_too_long = BOOST_ASIO_SOCKET_ERROR(ENAMETOOLONG), + + /// Network is down. + network_down = BOOST_ASIO_SOCKET_ERROR(ENETDOWN), + + /// Network dropped connection on reset. + network_reset = BOOST_ASIO_SOCKET_ERROR(ENETRESET), + + /// Network is unreachable. + network_unreachable = BOOST_ASIO_SOCKET_ERROR(ENETUNREACH), + + /// Too many open files. + no_descriptors = BOOST_ASIO_SOCKET_ERROR(EMFILE), + + /// No buffer space available. + no_buffer_space = BOOST_ASIO_SOCKET_ERROR(ENOBUFS), + + /// Cannot allocate memory. + no_memory = BOOST_ASIO_WIN_OR_POSIX( + BOOST_ASIO_NATIVE_ERROR(ERROR_OUTOFMEMORY), + BOOST_ASIO_NATIVE_ERROR(ENOMEM)), + + /// Operation not permitted. + no_permission = BOOST_ASIO_WIN_OR_POSIX( + BOOST_ASIO_NATIVE_ERROR(ERROR_ACCESS_DENIED), + BOOST_ASIO_NATIVE_ERROR(EPERM)), + + /// Protocol not available. + no_protocol_option = BOOST_ASIO_SOCKET_ERROR(ENOPROTOOPT), + + /// Transport endpoint is not connected. + not_connected = BOOST_ASIO_SOCKET_ERROR(ENOTCONN), + + /// Socket operation on non-socket. + not_socket = BOOST_ASIO_SOCKET_ERROR(ENOTSOCK), + + /// Operation cancelled. + operation_aborted = BOOST_ASIO_WIN_OR_POSIX( + BOOST_ASIO_NATIVE_ERROR(ERROR_OPERATION_ABORTED), + BOOST_ASIO_NATIVE_ERROR(ECANCELED)), + + /// Operation not supported. + operation_not_supported = BOOST_ASIO_SOCKET_ERROR(EOPNOTSUPP), + + /// Cannot send after transport endpoint shutdown. + shut_down = BOOST_ASIO_SOCKET_ERROR(ESHUTDOWN), + + /// Connection timed out. + timed_out = BOOST_ASIO_SOCKET_ERROR(ETIMEDOUT), + + /// Resource temporarily unavailable. + try_again = BOOST_ASIO_WIN_OR_POSIX( + BOOST_ASIO_NATIVE_ERROR(ERROR_RETRY), + BOOST_ASIO_NATIVE_ERROR(EAGAIN)), + + /// The socket is marked non-blocking and the requested operation would block. + would_block = BOOST_ASIO_SOCKET_ERROR(EWOULDBLOCK) +}; + +enum netdb_errors +{ + /// Host not found (authoritative). + host_not_found = BOOST_ASIO_NETDB_ERROR(HOST_NOT_FOUND), + + /// Host not found (non-authoritative). + host_not_found_try_again = BOOST_ASIO_NETDB_ERROR(TRY_AGAIN), + + /// The query is valid but does not have associated address data. + no_data = BOOST_ASIO_NETDB_ERROR(NO_DATA), + + /// A non-recoverable error occurred. + no_recovery = BOOST_ASIO_NETDB_ERROR(NO_RECOVERY) +}; + +enum addrinfo_errors +{ + /// The service is not supported for the given socket type. + service_not_found = BOOST_ASIO_WIN_OR_POSIX( + BOOST_ASIO_NATIVE_ERROR(WSATYPE_NOT_FOUND), + BOOST_ASIO_GETADDRINFO_ERROR(EAI_SERVICE)), + + /// The socket type is not supported. + socket_type_not_supported = BOOST_ASIO_WIN_OR_POSIX( + BOOST_ASIO_NATIVE_ERROR(WSAESOCKTNOSUPPORT), + BOOST_ASIO_GETADDRINFO_ERROR(EAI_SOCKTYPE)) +}; + +enum misc_errors +{ + /// Already open. + already_open = 1, + + /// End of file or stream. + eof, + + /// Element not found. + not_found, + + /// The descriptor cannot fit into the select system call's fd_set. + fd_set_failure +}; + +enum ssl_errors +{ +}; + +inline const boost::system::error_category& get_system_category() +{ + return boost::system::get_system_category(); +} + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +namespace detail { + +class netdb_category : public boost::system::error_category +{ +public: + const char* name() const + { + return "asio.netdb"; + } + + std::string message(int value) const + { + if (value == error::host_not_found) + return "Host not found (authoritative)"; + if (value == error::host_not_found_try_again) + return "Host not found (non-authoritative), try again later"; + if (value == error::no_data) + return "The query is valid, but it does not have associated data"; + if (value == error::no_recovery) + return "A non-recoverable error occurred during database lookup"; + return "asio.netdb error"; + } +}; + +} // namespace detail + +inline const boost::system::error_category& get_netdb_category() +{ + static detail::netdb_category instance; + return instance; +} + +namespace detail { + +class addrinfo_category : public boost::system::error_category +{ +public: + const char* name() const + { + return "asio.addrinfo"; + } + + std::string message(int value) const + { + if (value == error::service_not_found) + return "Service not found"; + if (value == error::socket_type_not_supported) + return "Socket type not supported"; + return "asio.addrinfo error"; + } +}; + +} // namespace detail + +inline const boost::system::error_category& get_addrinfo_category() +{ + static detail::addrinfo_category instance; + return instance; +} + +#else // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +inline const boost::system::error_category& get_netdb_category() +{ + return get_system_category(); +} + +inline const boost::system::error_category& get_addrinfo_category() +{ + return get_system_category(); +} + +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +namespace detail { + +class misc_category : public boost::system::error_category +{ +public: + const char* name() const + { + return "asio.misc"; + } + + std::string message(int value) const + { + if (value == error::already_open) + return "Already open"; + if (value == error::eof) + return "End of file"; + if (value == error::not_found) + return "Element not found"; + if (value == error::fd_set_failure) + return "The descriptor does not fit into the select call's fd_set"; + return "asio.misc error"; + } +}; + +} // namespace detail + +inline const boost::system::error_category& get_misc_category() +{ + static detail::misc_category instance; + return instance; +} + +namespace detail { + +class ssl_category : public boost::system::error_category +{ +public: + const char* name() const + { + return "asio.ssl"; + } + + std::string message(int) const + { + return "asio.ssl error"; + } +}; + +} // namespace detail + +inline const boost::system::error_category& get_ssl_category() +{ + static detail::ssl_category instance; + return instance; +} + +static const boost::system::error_category& system_category + = boost::asio::error::get_system_category(); +static const boost::system::error_category& netdb_category + = boost::asio::error::get_netdb_category(); +static const boost::system::error_category& addrinfo_category + = boost::asio::error::get_addrinfo_category(); +static const boost::system::error_category& misc_category + = boost::asio::error::get_misc_category(); +static const boost::system::error_category& ssl_category + = boost::asio::error::get_ssl_category(); + +} // namespace error +} // namespace asio + +namespace system { + +template<> struct is_error_code_enum +{ + static const bool value = true; +}; + +template<> struct is_error_code_enum +{ + static const bool value = true; +}; + +template<> struct is_error_code_enum +{ + static const bool value = true; +}; + +template<> struct is_error_code_enum +{ + static const bool value = true; +}; + +template<> struct is_error_code_enum +{ + static const bool value = true; +}; + +} // namespace system + +namespace asio { +namespace error { + +inline boost::system::error_code make_error_code(basic_errors e) +{ + return boost::system::error_code( + static_cast(e), get_system_category()); +} + +inline boost::system::error_code make_error_code(netdb_errors e) +{ + return boost::system::error_code( + static_cast(e), get_netdb_category()); +} + +inline boost::system::error_code make_error_code(addrinfo_errors e) +{ + return boost::system::error_code( + static_cast(e), get_addrinfo_category()); +} + +inline boost::system::error_code make_error_code(misc_errors e) +{ + return boost::system::error_code( + static_cast(e), get_misc_category()); +} + +inline boost::system::error_code make_error_code(ssl_errors e) +{ + return boost::system::error_code( + static_cast(e), get_ssl_category()); +} + +} // namespace error +} // namespace asio +} // namespace boost + +#undef BOOST_ASIO_NATIVE_ERROR +#undef BOOST_ASIO_SOCKET_ERROR +#undef BOOST_ASIO_NETDB_ERROR +#undef BOOST_ASIO_GETADDRINFO_ERROR +#undef BOOST_ASIO_WIN_OR_POSIX + + +#include + +#endif // BOOST_ASIO_ERROR_HPP diff --git a/win32/include/boost/asio/handler_alloc_hook.hpp b/win32/include/boost/asio/handler_alloc_hook.hpp new file mode 100755 index 000000000..8c9ff764e --- /dev/null +++ b/win32/include/boost/asio/handler_alloc_hook.hpp @@ -0,0 +1,90 @@ +// +// handler_alloc_hook.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_HANDLER_ALLOC_HOOK_HPP +#define BOOST_ASIO_HANDLER_ALLOC_HOOK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Default allocation function for handlers. +/** + * Asynchronous operations may need to allocate temporary objects. Since + * asynchronous operations have a handler function object, these temporary + * objects can be said to be associated with the handler. + * + * Implement asio_handler_allocate and asio_handler_deallocate for your own + * handlers to provide custom allocation for these temporary objects. + * + * This default implementation is simply: + * @code + * return ::operator new(size); + * @endcode + * + * @note All temporary objects associated with a handler will be deallocated + * before the upcall to the handler is performed. This allows the same memory to + * be reused for a subsequent asynchronous operation initiated by the handler. + * + * @par Example + * @code + * class my_handler; + * + * void* asio_handler_allocate(std::size_t size, my_handler* context) + * { + * return ::operator new(size); + * } + * + * void asio_handler_deallocate(void* pointer, std::size_t size, + * my_handler* context) + * { + * ::operator delete(pointer); + * } + * @endcode + */ +inline void* asio_handler_allocate(std::size_t size, ...) +{ + return ::operator new(size); +} + +/// Default deallocation function for handlers. +/** + * Implement asio_handler_allocate and asio_handler_deallocate for your own + * handlers to provide custom allocation for the associated temporary objects. + * + * This default implementation is simply: + * @code + * ::operator delete(pointer); + * @endcode + * + * @sa asio_handler_allocate. + */ +inline void asio_handler_deallocate(void* pointer, std::size_t size, ...) +{ + (void)(size); + ::operator delete(pointer); +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_HANDLER_ALLOC_HOOK_HPP diff --git a/win32/include/boost/asio/handler_invoke_hook.hpp b/win32/include/boost/asio/handler_invoke_hook.hpp new file mode 100755 index 000000000..039b44d49 --- /dev/null +++ b/win32/include/boost/asio/handler_invoke_hook.hpp @@ -0,0 +1,71 @@ +// +// handler_invoke_hook.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_HANDLER_INVOKE_HOOK_HPP +#define BOOST_ASIO_HANDLER_INVOKE_HOOK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +namespace boost { +namespace asio { + +/// Default invoke function for handlers. +/** + * Completion handlers for asynchronous operations are invoked by the + * io_service associated with the corresponding object (e.g. a socket or + * deadline_timer). Certain guarantees are made on when the handler may be + * invoked, in particular that a handler can only be invoked from a thread that + * is currently calling boost::asio::io_service::run() on the corresponding + * io_service object. Handlers may subsequently be invoked through other + * objects (such as boost::asio::strand objects) that provide additional + * guarantees. + * + * When asynchronous operations are composed from other asynchronous + * operations, all intermediate handlers should be invoked using the same + * method as the final handler. This is required to ensure that user-defined + * objects are not accessed in a way that may violate the guarantees. This + * hooking function ensures that the invoked method used for the final handler + * is accessible at each intermediate step. + * + * Implement asio_handler_invoke for your own handlers to specify a custom + * invocation strategy. + * + * This default implementation is simply: + * @code + * function(); + * @endcode + * + * @par Example + * @code + * class my_handler; + * + * template + * void asio_handler_invoke(Function function, my_handler* context) + * { + * context->strand_.dispatch(function); + * } + * @endcode + */ +template +inline void asio_handler_invoke(Function function, ...) +{ + function(); +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_HANDLER_INVOKE_HOOK_HPP diff --git a/win32/include/boost/asio/impl/io_service.ipp b/win32/include/boost/asio/impl/io_service.ipp new file mode 100755 index 000000000..a794ff0e9 --- /dev/null +++ b/win32/include/boost/asio/impl/io_service.ipp @@ -0,0 +1,226 @@ +// +// io_service.ipp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IO_SERVICE_IPP +#define BOOST_ASIO_IO_SERVICE_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +inline io_service::io_service() + : service_registry_(new boost::asio::detail::service_registry(*this)), + impl_(service_registry_->use_service()) +{ + impl_.init((std::numeric_limits::max)()); +} + +inline io_service::io_service(std::size_t concurrency_hint) + : service_registry_(new boost::asio::detail::service_registry(*this)), + impl_(service_registry_->use_service()) +{ + impl_.init(concurrency_hint); +} + +inline io_service::~io_service() +{ + delete service_registry_; +} + +inline std::size_t io_service::run() +{ + boost::system::error_code ec; + std::size_t s = impl_.run(ec); + boost::asio::detail::throw_error(ec); + return s; +} + +inline std::size_t io_service::run(boost::system::error_code& ec) +{ + return impl_.run(ec); +} + +inline std::size_t io_service::run_one() +{ + boost::system::error_code ec; + std::size_t s = impl_.run_one(ec); + boost::asio::detail::throw_error(ec); + return s; +} + +inline std::size_t io_service::run_one(boost::system::error_code& ec) +{ + return impl_.run_one(ec); +} + +inline std::size_t io_service::poll() +{ + boost::system::error_code ec; + std::size_t s = impl_.poll(ec); + boost::asio::detail::throw_error(ec); + return s; +} + +inline std::size_t io_service::poll(boost::system::error_code& ec) +{ + return impl_.poll(ec); +} + +inline std::size_t io_service::poll_one() +{ + boost::system::error_code ec; + std::size_t s = impl_.poll_one(ec); + boost::asio::detail::throw_error(ec); + return s; +} + +inline std::size_t io_service::poll_one(boost::system::error_code& ec) +{ + return impl_.poll_one(ec); +} + +inline void io_service::stop() +{ + impl_.stop(); +} + +inline void io_service::reset() +{ + impl_.reset(); +} + +template +inline void io_service::dispatch(Handler handler) +{ + impl_.dispatch(handler); +} + +template +inline void io_service::post(Handler handler) +{ + impl_.post(handler); +} + +template +#if defined(GENERATING_DOCUMENTATION) +unspecified +#else +inline detail::wrapped_handler +#endif +io_service::wrap(Handler handler) +{ + return detail::wrapped_handler(*this, handler); +} + +inline io_service::work::work(boost::asio::io_service& io_service) + : io_service_(io_service) +{ + io_service_.impl_.work_started(); +} + +inline io_service::work::work(const work& other) + : io_service_(other.io_service_) +{ + io_service_.impl_.work_started(); +} + +inline io_service::work::~work() +{ + io_service_.impl_.work_finished(); +} + +inline boost::asio::io_service& io_service::work::io_service() +{ + return io_service_; +} + +inline boost::asio::io_service& io_service::work::get_io_service() +{ + return io_service_; +} + +inline io_service::service::service(boost::asio::io_service& owner) + : owner_(owner), + type_info_(0), + next_(0) +{ +} + +inline io_service::service::~service() +{ +} + +inline boost::asio::io_service& io_service::service::io_service() +{ + return owner_; +} + +inline boost::asio::io_service& io_service::service::get_io_service() +{ + return owner_; +} + +template +inline Service& use_service(io_service& ios) +{ + // Check that Service meets the necessary type requirements. + (void)static_cast(static_cast(0)); + (void)static_cast(&Service::id); + + return ios.service_registry_->template use_service(); +} + +template +void add_service(io_service& ios, Service* svc) +{ + // Check that Service meets the necessary type requirements. + (void)static_cast(static_cast(0)); + (void)static_cast(&Service::id); + + if (&ios != &svc->io_service()) + boost::throw_exception(invalid_service_owner()); + if (!ios.service_registry_->template add_service(svc)) + boost::throw_exception(service_already_exists()); +} + +template +bool has_service(io_service& ios) +{ + // Check that Service meets the necessary type requirements. + (void)static_cast(static_cast(0)); + (void)static_cast(&Service::id); + + return ios.service_registry_->template has_service(); +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IO_SERVICE_IPP diff --git a/win32/include/boost/asio/impl/read.ipp b/win32/include/boost/asio/impl/read.ipp new file mode 100755 index 000000000..b2ca26690 --- /dev/null +++ b/win32/include/boost/asio/impl/read.ipp @@ -0,0 +1,316 @@ +// +// read.ipp +// ~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_READ_IPP +#define BOOST_ASIO_READ_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +template +std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, boost::system::error_code& ec) +{ + boost::asio::detail::consuming_buffers< + mutable_buffer, MutableBufferSequence> tmp(buffers); + std::size_t total_transferred = 0; + while (tmp.begin() != tmp.end()) + { + std::size_t bytes_transferred = s.read_some(tmp, ec); + tmp.consume(bytes_transferred); + total_transferred += bytes_transferred; + if (completion_condition(ec, total_transferred)) + return total_transferred; + } + ec = boost::system::error_code(); + return total_transferred; +} + +template +inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, + CompletionCondition completion_condition) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read(s, buffers, completion_condition, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +std::size_t read(SyncReadStream& s, + boost::asio::basic_streambuf& b, + CompletionCondition completion_condition, boost::system::error_code& ec) +{ + std::size_t total_transferred = 0; + for (;;) + { + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec); + b.commit(bytes_transferred); + total_transferred += bytes_transferred; + if (b.size() == b.max_size() + || completion_condition(ec, total_transferred)) + return total_transferred; + } +} + +template +inline std::size_t read(SyncReadStream& s, + boost::asio::basic_streambuf& b) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read(s, b, transfer_all(), ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t read(SyncReadStream& s, + boost::asio::basic_streambuf& b, + CompletionCondition completion_condition) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read(s, b, completion_condition, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +namespace detail +{ + template + class read_handler + { + public: + typedef boost::asio::detail::consuming_buffers< + mutable_buffer, MutableBufferSequence> buffers_type; + + read_handler(AsyncReadStream& stream, const buffers_type& buffers, + CompletionCondition completion_condition, ReadHandler handler) + : stream_(stream), + buffers_(buffers), + total_transferred_(0), + completion_condition_(completion_condition), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + total_transferred_ += bytes_transferred; + buffers_.consume(bytes_transferred); + if (completion_condition_(ec, total_transferred_) + || buffers_.begin() == buffers_.end()) + { + handler_(ec, total_transferred_); + } + else + { + stream_.async_read_some(buffers_, *this); + } + } + + //private: + AsyncReadStream& stream_; + buffers_type buffers_; + std::size_t total_transferred_; + CompletionCondition completion_condition_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + read_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + read_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, ReadHandler handler) +{ + boost::asio::detail::consuming_buffers< + mutable_buffer, MutableBufferSequence> tmp(buffers); + s.async_read_some(tmp, + detail::read_handler( + s, tmp, completion_condition, handler)); +} + +template +inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, + ReadHandler handler) +{ + async_read(s, buffers, transfer_all(), handler); +} + +namespace detail +{ + template + class read_streambuf_handler + { + public: + read_streambuf_handler(AsyncReadStream& stream, + basic_streambuf& streambuf, + CompletionCondition completion_condition, ReadHandler handler) + : stream_(stream), + streambuf_(streambuf), + total_transferred_(0), + completion_condition_(completion_condition), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + total_transferred_ += bytes_transferred; + streambuf_.commit(bytes_transferred); + if (streambuf_.size() == streambuf_.max_size() + || completion_condition_(ec, total_transferred_)) + { + handler_(ec, total_transferred_); + } + else + { + std::size_t bytes_available = + std::min(512, streambuf_.max_size() - streambuf_.size()); + stream_.async_read_some(streambuf_.prepare(bytes_available), *this); + } + } + + //private: + AsyncReadStream& stream_; + boost::asio::basic_streambuf& streambuf_; + std::size_t total_transferred_; + CompletionCondition completion_condition_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + read_streambuf_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_streambuf_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + read_streambuf_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_read(AsyncReadStream& s, + boost::asio::basic_streambuf& b, + CompletionCondition completion_condition, ReadHandler handler) +{ + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + s.async_read_some(b.prepare(bytes_available), + detail::read_streambuf_handler( + s, b, completion_condition, handler)); +} + +template +inline void async_read(AsyncReadStream& s, + boost::asio::basic_streambuf& b, ReadHandler handler) +{ + async_read(s, b, transfer_all(), handler); +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_READ_IPP diff --git a/win32/include/boost/asio/impl/read_at.ipp b/win32/include/boost/asio/impl/read_at.ipp new file mode 100755 index 000000000..8a4c624c2 --- /dev/null +++ b/win32/include/boost/asio/impl/read_at.ipp @@ -0,0 +1,339 @@ +// +// read_at.ipp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_READ_AT_IPP +#define BOOST_ASIO_READ_AT_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, boost::system::error_code& ec) +{ + boost::asio::detail::consuming_buffers< + mutable_buffer, MutableBufferSequence> tmp(buffers); + std::size_t total_transferred = 0; + while (tmp.begin() != tmp.end()) + { + std::size_t bytes_transferred = d.read_some_at( + offset + total_transferred, tmp, ec); + tmp.consume(bytes_transferred); + total_transferred += bytes_transferred; + if (completion_condition(ec, total_transferred)) + return total_transferred; + } + ec = boost::system::error_code(); + return total_transferred; +} + +template +inline std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_at( + d, offset, buffers, transfer_all(), ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_at( + d, offset, buffers, completion_condition, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + CompletionCondition completion_condition, boost::system::error_code& ec) +{ + std::size_t total_transferred = 0; + for (;;) + { + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + std::size_t bytes_transferred = d.read_some_at( + offset + total_transferred, b.prepare(bytes_available), ec); + b.commit(bytes_transferred); + total_transferred += bytes_transferred; + if (b.size() == b.max_size() + || completion_condition(ec, total_transferred)) + return total_transferred; + } +} + +template +inline std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_at( + d, offset, b, transfer_all(), ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + CompletionCondition completion_condition) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_at( + d, offset, b, completion_condition, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +namespace detail +{ + template + class read_at_handler + { + public: + typedef boost::asio::detail::consuming_buffers< + mutable_buffer, MutableBufferSequence> buffers_type; + + read_at_handler(AsyncRandomAccessReadDevice& stream, + boost::uint64_t offset, const buffers_type& buffers, + CompletionCondition completion_condition, ReadHandler handler) + : stream_(stream), + offset_(offset), + buffers_(buffers), + total_transferred_(0), + completion_condition_(completion_condition), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + total_transferred_ += bytes_transferred; + buffers_.consume(bytes_transferred); + if (completion_condition_(ec, total_transferred_) + || buffers_.begin() == buffers_.end()) + { + handler_(ec, total_transferred_); + } + else + { + stream_.async_read_some_at( + offset_ + total_transferred_, buffers_, *this); + } + } + + //private: + AsyncRandomAccessReadDevice& stream_; + boost::uint64_t offset_; + buffers_type buffers_; + std::size_t total_transferred_; + CompletionCondition completion_condition_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + read_at_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_at_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + read_at_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, ReadHandler handler) +{ + boost::asio::detail::consuming_buffers< + mutable_buffer, MutableBufferSequence> tmp(buffers); + d.async_read_some_at(offset, tmp, + detail::read_at_handler( + d, offset, tmp, completion_condition, handler)); +} + +template +inline void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + ReadHandler handler) +{ + async_read_at(d, offset, buffers, transfer_all(), handler); +} + +namespace detail +{ + template + class read_at_streambuf_handler + { + public: + read_at_streambuf_handler(AsyncRandomAccessReadDevice& stream, + boost::uint64_t offset, basic_streambuf& streambuf, + CompletionCondition completion_condition, ReadHandler handler) + : stream_(stream), + offset_(offset), + streambuf_(streambuf), + total_transferred_(0), + completion_condition_(completion_condition), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + total_transferred_ += bytes_transferred; + streambuf_.commit(bytes_transferred); + if (streambuf_.size() == streambuf_.max_size() + || completion_condition_(ec, total_transferred_)) + { + handler_(ec, total_transferred_); + } + else + { + std::size_t bytes_available = + std::min(512, streambuf_.max_size() - streambuf_.size()); + stream_.async_read_some_at(offset_ + total_transferred_, + streambuf_.prepare(bytes_available), *this); + } + } + + //private: + AsyncRandomAccessReadDevice& stream_; + boost::uint64_t offset_; + boost::asio::basic_streambuf& streambuf_; + std::size_t total_transferred_; + CompletionCondition completion_condition_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + read_at_streambuf_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_at_streambuf_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + read_at_streambuf_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + CompletionCondition completion_condition, ReadHandler handler) +{ + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + d.async_read_some_at(offset, b.prepare(bytes_available), + detail::read_at_streambuf_handler( + d, offset, b, completion_condition, handler)); +} + +template +inline void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + ReadHandler handler) +{ + async_read_at(d, offset, b, transfer_all(), handler); +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_READ_AT_IPP diff --git a/win32/include/boost/asio/impl/read_until.ipp b/win32/include/boost/asio/impl/read_until.ipp new file mode 100755 index 000000000..ce5c5a766 --- /dev/null +++ b/win32/include/boost/asio/impl/read_until.ipp @@ -0,0 +1,998 @@ +// +// read_until.ipp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_READ_UNTIL_IPP +#define BOOST_ASIO_READ_UNTIL_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +template +inline std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, char delim) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_until(s, b, delim, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, char delim, + boost::system::error_code& ec) +{ + std::size_t next_search_start = 0; + for (;;) + { + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = b.data(); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start; + iterator end = iterator::end(buffers); + + // Look for a match. + iterator iter = std::find(start, end, delim); + if (iter != end) + { + // Found a match. We're done. + ec = boost::system::error_code(); + return iter - begin + 1; + } + else + { + // No match. Next search can start with the new data. + next_search_start = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + ec = error::not_found; + return 0; + } + + // Need more data. + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + b.commit(s.read_some(b.prepare(bytes_available), ec)); + if (ec) + return 0; + } +} + +template +inline std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, const std::string& delim) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_until(s, b, delim, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +namespace detail +{ + // Algorithm that finds a subsequence of equal values in a sequence. Returns + // (iterator,true) if a full match was found, in which case the iterator + // points to the beginning of the match. Returns (iterator,false) if a + // partial match was found at the end of the first sequence, in which case + // the iterator points to the beginning of the partial match. Returns + // (last1,false) if no full or partial match was found. + template + std::pair partial_search( + Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2) + { + for (Iterator1 iter1 = first1; iter1 != last1; ++iter1) + { + Iterator1 test_iter1 = iter1; + Iterator2 test_iter2 = first2; + for (;; ++test_iter1, ++test_iter2) + { + if (test_iter2 == last2) + return std::make_pair(iter1, true); + if (test_iter1 == last1) + { + if (test_iter2 != first2) + return std::make_pair(iter1, false); + else + break; + } + if (*test_iter1 != *test_iter2) + break; + } + } + return std::make_pair(last1, false); + } +} // namespace detail + +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, const std::string& delim, + boost::system::error_code& ec) +{ + std::size_t next_search_start = 0; + for (;;) + { + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = b.data(); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start; + iterator end = iterator::end(buffers); + + // Look for a match. + std::pair result = boost::asio::detail::partial_search( + start, end, delim.begin(), delim.end()); + if (result.first != end) + { + if (result.second) + { + // Full match. We're done. + ec = boost::system::error_code(); + return result.first - begin + delim.length(); + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start = result.first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + ec = error::not_found; + return 0; + } + + // Need more data. + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + b.commit(s.read_some(b.prepare(bytes_available), ec)); + if (ec) + return 0; + } +} + +template +inline std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, const boost::regex& expr) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_until(s, b, expr, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, const boost::regex& expr, + boost::system::error_code& ec) +{ + std::size_t next_search_start = 0; + for (;;) + { + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = b.data(); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start; + iterator end = iterator::end(buffers); + + // Look for a match. + boost::match_results match_results; + if (boost::regex_search(start, end, match_results, expr, + boost::match_default | boost::match_partial)) + { + if (match_results[0].matched) + { + // Full match. We're done. + ec = boost::system::error_code(); + return match_results[0].second - begin; + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start = match_results[0].first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + ec = error::not_found; + return 0; + } + + // Need more data. + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + b.commit(s.read_some(b.prepare(bytes_available), ec)); + if (ec) + return 0; + } +} + +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, + MatchCondition match_condition, boost::system::error_code& ec, + typename boost::enable_if >::type*) +{ + std::size_t next_search_start = 0; + for (;;) + { + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = b.data(); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start; + iterator end = iterator::end(buffers); + + // Look for a match. + std::pair result = match_condition(start, end); + if (result.first != end) + { + if (result.second) + { + // Full match. We're done. + ec = boost::system::error_code(); + return result.first - begin; + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start = result.first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + ec = error::not_found; + return 0; + } + + // Need more data. + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + b.commit(s.read_some(b.prepare(bytes_available), ec)); + if (ec) + return 0; + } +} + +template +inline std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, MatchCondition match_condition, + typename boost::enable_if >::type*) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = read_until(s, b, match_condition, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +namespace detail +{ + template + class read_until_delim_handler + { + public: + read_until_delim_handler(AsyncReadStream& stream, + boost::asio::basic_streambuf& streambuf, char delim, + std::size_t next_search_start, ReadHandler handler) + : stream_(stream), + streambuf_(streambuf), + delim_(delim), + next_search_start_(next_search_start), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + // Check for errors. + if (ec) + { + std::size_t bytes = 0; + handler_(ec, bytes); + return; + } + + // Commit received data to streambuf's get area. + streambuf_.commit(bytes_transferred); + + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = streambuf_.data(); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start_; + iterator end = iterator::end(buffers); + + // Look for a match. + iterator iter = std::find(start, end, delim_); + if (iter != end) + { + // Found a match. We're done. + std::size_t bytes = iter - begin + 1; + handler_(ec, bytes); + return; + } + + // No match. Check if buffer is full. + if (streambuf_.size() == streambuf_.max_size()) + { + std::size_t bytes = 0; + boost::system::error_code ec(error::not_found); + handler_(ec, bytes); + return; + } + + // Next search can start with the new data. + next_search_start_ = end - begin; + + // Start a new asynchronous read operation to obtain more data. + std::size_t bytes_available = + std::min(512, streambuf_.max_size() - streambuf_.size()); + stream_.async_read_some(streambuf_.prepare(bytes_available), *this); + } + + //private: + AsyncReadStream& stream_; + boost::asio::basic_streambuf& streambuf_; + char delim_; + std::size_t next_search_start_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + read_until_delim_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_until_delim_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + read_until_delim_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +void async_read_until(AsyncReadStream& s, + boost::asio::basic_streambuf& b, char delim, ReadHandler handler) +{ + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = b.data(); + iterator begin = iterator::begin(buffers); + iterator end = iterator::end(buffers); + + // Look for a match. + iterator iter = std::find(begin, end, delim); + if (iter != end) + { + // Found a match. We're done. + boost::system::error_code ec; + std::size_t bytes = iter - begin + 1; + s.io_service().post(detail::bind_handler(handler, ec, bytes)); + return; + } + + // No match. Check if buffer is full. + if (b.size() == b.max_size()) + { + boost::system::error_code ec(error::not_found); + s.io_service().post(detail::bind_handler(handler, ec, 0)); + return; + } + + // Start a new asynchronous read operation to obtain more data. + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + s.async_read_some(b.prepare(bytes_available), + detail::read_until_delim_handler( + s, b, delim, end - begin, handler)); +} + +namespace detail +{ + template + class read_until_delim_string_handler + { + public: + read_until_delim_string_handler(AsyncReadStream& stream, + boost::asio::basic_streambuf& streambuf, + const std::string& delim, std::size_t next_search_start, + ReadHandler handler) + : stream_(stream), + streambuf_(streambuf), + delim_(delim), + next_search_start_(next_search_start), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + // Check for errors. + if (ec) + { + std::size_t bytes = 0; + handler_(ec, bytes); + return; + } + + // Commit received data to streambuf's get area. + streambuf_.commit(bytes_transferred); + + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = streambuf_.data(); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start_; + iterator end = iterator::end(buffers); + + // Look for a match. + std::pair result = boost::asio::detail::partial_search( + start, end, delim_.begin(), delim_.end()); + if (result.first != end) + { + if (result.second) + { + // Full match. We're done. + std::size_t bytes = result.first - begin + delim_.length(); + handler_(ec, bytes); + return; + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start_ = result.first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start_ = end - begin; + } + + // Check if buffer is full. + if (streambuf_.size() == streambuf_.max_size()) + { + std::size_t bytes = 0; + boost::system::error_code ec(error::not_found); + handler_(ec, bytes); + return; + } + + // Start a new asynchronous read operation to obtain more data. + std::size_t bytes_available = + std::min(512, streambuf_.max_size() - streambuf_.size()); + stream_.async_read_some(streambuf_.prepare(bytes_available), *this); + } + + //private: + AsyncReadStream& stream_; + boost::asio::basic_streambuf& streambuf_; + std::string delim_; + std::size_t next_search_start_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + read_until_delim_string_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_until_delim_string_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + read_until_delim_string_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +void async_read_until(AsyncReadStream& s, + boost::asio::basic_streambuf& b, const std::string& delim, + ReadHandler handler) +{ + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = b.data(); + iterator begin = iterator::begin(buffers); + iterator end = iterator::end(buffers); + + // Look for a match. + std::size_t next_search_start; + std::pair result = boost::asio::detail::partial_search( + begin, end, delim.begin(), delim.end()); + if (result.first != end) + { + if (result.second) + { + // Full match. We're done. + boost::system::error_code ec; + std::size_t bytes = result.first - begin + delim.length(); + s.io_service().post(detail::bind_handler(handler, ec, bytes)); + return; + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start = result.first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + boost::system::error_code ec(error::not_found); + s.io_service().post(detail::bind_handler(handler, ec, 0)); + return; + } + + // Start a new asynchronous read operation to obtain more data. + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + s.async_read_some(b.prepare(bytes_available), + detail::read_until_delim_string_handler< + AsyncReadStream, Allocator, ReadHandler>( + s, b, delim, next_search_start, handler)); +} + +namespace detail +{ + template + class read_until_expr_handler + { + public: + read_until_expr_handler(AsyncReadStream& stream, + boost::asio::basic_streambuf& streambuf, + const boost::regex& expr, std::size_t next_search_start, + ReadHandler handler) + : stream_(stream), + streambuf_(streambuf), + expr_(expr), + next_search_start_(next_search_start), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + // Check for errors. + if (ec) + { + std::size_t bytes = 0; + handler_(ec, bytes); + return; + } + + // Commit received data to streambuf's get area. + streambuf_.commit(bytes_transferred); + + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = streambuf_.data(); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start_; + iterator end = iterator::end(buffers); + + // Look for a match. + boost::match_results match_results; + if (boost::regex_search(start, end, match_results, expr_, + boost::match_default | boost::match_partial)) + { + if (match_results[0].matched) + { + // Full match. We're done. + std::size_t bytes = match_results[0].second - begin; + handler_(ec, bytes); + return; + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start_ = match_results[0].first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start_ = end - begin; + } + + // Check if buffer is full. + if (streambuf_.size() == streambuf_.max_size()) + { + std::size_t bytes = 0; + boost::system::error_code ec(error::not_found); + handler_(ec, bytes); + return; + } + + // Start a new asynchronous read operation to obtain more data. + std::size_t bytes_available = + std::min(512, streambuf_.max_size() - streambuf_.size()); + stream_.async_read_some(streambuf_.prepare(bytes_available), *this); + } + + //private: + AsyncReadStream& stream_; + boost::asio::basic_streambuf& streambuf_; + boost::regex expr_; + std::size_t next_search_start_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + read_until_expr_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_until_expr_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + read_until_expr_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +void async_read_until(AsyncReadStream& s, + boost::asio::basic_streambuf& b, const boost::regex& expr, + ReadHandler handler) +{ + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = b.data(); + iterator begin = iterator::begin(buffers); + iterator end = iterator::end(buffers); + + // Look for a match. + std::size_t next_search_start; + boost::match_results match_results; + if (boost::regex_search(begin, end, match_results, expr, + boost::match_default | boost::match_partial)) + { + if (match_results[0].matched) + { + // Full match. We're done. + boost::system::error_code ec; + std::size_t bytes = match_results[0].second - begin; + s.io_service().post(detail::bind_handler(handler, ec, bytes)); + return; + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start = match_results[0].first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + boost::system::error_code ec(error::not_found); + s.io_service().post(detail::bind_handler(handler, ec, 0)); + return; + } + + // Start a new asynchronous read operation to obtain more data. + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + s.async_read_some(b.prepare(bytes_available), + detail::read_until_expr_handler( + s, b, expr, next_search_start, handler)); +} + +namespace detail +{ + template + class read_until_match_handler + { + public: + read_until_match_handler(AsyncReadStream& stream, + boost::asio::basic_streambuf& streambuf, + MatchCondition match_condition, std::size_t next_search_start, + ReadHandler handler) + : stream_(stream), + streambuf_(streambuf), + match_condition_(match_condition), + next_search_start_(next_search_start), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + // Check for errors. + if (ec) + { + std::size_t bytes = 0; + handler_(ec, bytes); + return; + } + + // Commit received data to streambuf's get area. + streambuf_.commit(bytes_transferred); + + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = streambuf_.data(); + iterator begin = iterator::begin(buffers); + iterator start = begin + next_search_start_; + iterator end = iterator::end(buffers); + + // Look for a match. + std::pair result = match_condition_(start, end); + if (result.first != end) + { + if (result.second) + { + // Full match. We're done. + std::size_t bytes = result.first - begin; + handler_(ec, bytes); + return; + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start_ = result.first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start_ = end - begin; + } + + // Check if buffer is full. + if (streambuf_.size() == streambuf_.max_size()) + { + std::size_t bytes = 0; + boost::system::error_code ec(error::not_found); + handler_(ec, bytes); + return; + } + + // Start a new asynchronous read operation to obtain more data. + std::size_t bytes_available = + std::min(512, streambuf_.max_size() - streambuf_.size()); + stream_.async_read_some(streambuf_.prepare(bytes_available), *this); + } + + //private: + AsyncReadStream& stream_; + boost::asio::basic_streambuf& streambuf_; + MatchCondition match_condition_; + std::size_t next_search_start_; + ReadHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + read_until_match_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + read_until_match_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + read_until_match_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +void async_read_until(AsyncReadStream& s, + boost::asio::basic_streambuf& b, + MatchCondition match_condition, ReadHandler handler, + typename boost::enable_if >::type*) +{ + // Determine the range of the data to be searched. + typedef typename boost::asio::basic_streambuf< + Allocator>::const_buffers_type const_buffers_type; + typedef boost::asio::buffers_iterator iterator; + const_buffers_type buffers = b.data(); + iterator begin = iterator::begin(buffers); + iterator end = iterator::end(buffers); + + // Look for a match. + std::size_t next_search_start; + std::pair result = match_condition(begin, end); + if (result.first != end) + { + if (result.second) + { + // Full match. We're done. + boost::system::error_code ec; + std::size_t bytes = result.first - begin; + s.io_service().post(detail::bind_handler(handler, ec, bytes)); + return; + } + else + { + // Partial match. Next search needs to start from beginning of match. + next_search_start = result.first - begin; + } + } + else + { + // No match. Next search can start with the new data. + next_search_start = end - begin; + } + + // Check if buffer is full. + if (b.size() == b.max_size()) + { + boost::system::error_code ec(error::not_found); + s.io_service().post(detail::bind_handler(handler, ec, 0)); + return; + } + + // Start a new asynchronous read operation to obtain more data. + std::size_t bytes_available = + std::min(512, b.max_size() - b.size()); + s.async_read_some(b.prepare(bytes_available), + detail::read_until_match_handler< + AsyncReadStream, Allocator, MatchCondition, ReadHandler>( + s, b, match_condition, next_search_start, handler)); +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_READ_UNTIL_IPP diff --git a/win32/include/boost/asio/impl/serial_port_base.ipp b/win32/include/boost/asio/impl/serial_port_base.ipp new file mode 100755 index 000000000..3ed298d8d --- /dev/null +++ b/win32/include/boost/asio/impl/serial_port_base.ipp @@ -0,0 +1,543 @@ +// +// serial_port_base.ipp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SERIAL_PORT_BASE_IPP +#define BOOST_ASIO_SERIAL_PORT_BASE_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +namespace boost { +namespace asio { + +inline serial_port_base::baud_rate::baud_rate(unsigned int rate) + : value_(rate) +{ +} + +inline unsigned int serial_port_base::baud_rate::value() const +{ + return value_; +} + +inline boost::system::error_code serial_port_base::baud_rate::store( + BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + storage.BaudRate = value_; +#else + speed_t baud; + switch (value_) + { + // Do POSIX-specified rates first. + case 0: baud = B0; break; + case 50: baud = B50; break; + case 75: baud = B75; break; + case 110: baud = B110; break; + case 134: baud = B134; break; + case 150: baud = B150; break; + case 200: baud = B200; break; + case 300: baud = B300; break; + case 600: baud = B600; break; + case 1200: baud = B1200; break; + case 1800: baud = B1800; break; + case 2400: baud = B2400; break; + case 4800: baud = B4800; break; + case 9600: baud = B9600; break; + case 19200: baud = B19200; break; + case 38400: baud = B38400; break; + // And now the extended ones conditionally. +# ifdef B7200 + case 7200: baud = B7200; break; +# endif +# ifdef B14400 + case 14400: baud = B14400; break; +# endif +# ifdef B57600 + case 57600: baud = B57600; break; +# endif +# ifdef B115200 + case 115200: baud = B115200; break; +# endif +# ifdef B230400 + case 230400: baud = B230400; break; +# endif +# ifdef B460800 + case 460800: baud = B460800; break; +# endif +# ifdef B500000 + case 500000: baud = B500000; break; +# endif +# ifdef B576000 + case 576000: baud = B576000; break; +# endif +# ifdef B921600 + case 921600: baud = B921600; break; +# endif +# ifdef B1000000 + case 1000000: baud = B1000000; break; +# endif +# ifdef B1152000 + case 1152000: baud = B1152000; break; +# endif +# ifdef B2000000 + case 2000000: baud = B2000000; break; +# endif +# ifdef B3000000 + case 3000000: baud = B3000000; break; +# endif +# ifdef B3500000 + case 3500000: baud = B3500000; break; +# endif +# ifdef B4000000 + case 4000000: baud = B4000000; break; +# endif + default: + baud = B0; + ec = boost::asio::error::invalid_argument; + return ec; + } +# if defined(_BSD_SOURCE) + ::cfsetspeed(&storage, baud); +# else + ::cfsetispeed(&storage, baud); + ::cfsetospeed(&storage, baud); +# endif +#endif + ec = boost::system::error_code(); + return ec; +} + +inline boost::system::error_code serial_port_base::baud_rate::load( + const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + value_ = storage.BaudRate; +#else + speed_t baud = ::cfgetospeed(&storage); + switch (baud) + { + // First do those specified by POSIX. + case B0: value_ = 0; break; + case B50: value_ = 50; break; + case B75: value_ = 75; break; + case B110: value_ = 110; break; + case B134: value_ = 134; break; + case B150: value_ = 150; break; + case B200: value_ = 200; break; + case B300: value_ = 300; break; + case B600: value_ = 600; break; + case B1200: value_ = 1200; break; + case B1800: value_ = 1800; break; + case B2400: value_ = 2400; break; + case B4800: value_ = 4800; break; + case B9600: value_ = 9600; break; + case B19200: value_ = 19200; break; + case B38400: value_ = 38400; break; + // Now conditionally handle a bunch of extended rates. +# ifdef B7200 + case B7200: value_ = 7200; break; +# endif +# ifdef B14400 + case B14400: value_ = 14400; break; +# endif +# ifdef B57600 + case B57600: value_ = 57600; break; +# endif +# ifdef B115200 + case B115200: value_ = 115200; break; +# endif +# ifdef B230400 + case B230400: value_ = 230400; break; +# endif +# ifdef B460800 + case B460800: value_ = 460800; break; +# endif +# ifdef B500000 + case B500000: value_ = 500000; break; +# endif +# ifdef B576000 + case B576000: value_ = 576000; break; +# endif +# ifdef B921600 + case B921600: value_ = 921600; break; +# endif +# ifdef B1000000 + case B1000000: value_ = 1000000; break; +# endif +# ifdef B1152000 + case B1152000: value_ = 1152000; break; +# endif +# ifdef B2000000 + case B2000000: value_ = 2000000; break; +# endif +# ifdef B3000000 + case B3000000: value_ = 3000000; break; +# endif +# ifdef B3500000 + case B3500000: value_ = 3500000; break; +# endif +# ifdef B4000000 + case B4000000: value_ = 4000000; break; +# endif + default: + value_ = 0; + ec = boost::asio::error::invalid_argument; + return ec; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +inline serial_port_base::flow_control::flow_control( + serial_port_base::flow_control::type t) + : value_(t) +{ + if (t != none && t != software && t != hardware) + throw std::out_of_range("invalid flow_control value"); +} + +inline serial_port_base::flow_control::type +serial_port_base::flow_control::value() const +{ + return value_; +} + +inline boost::system::error_code serial_port_base::flow_control::store( + BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + storage.fOutxCtsFlow = FALSE; + storage.fOutxDsrFlow = FALSE; + storage.fTXContinueOnXoff = TRUE; + storage.fDtrControl = DTR_CONTROL_ENABLE; + storage.fDsrSensitivity = FALSE; + storage.fOutX = FALSE; + storage.fInX = FALSE; + storage.fRtsControl = RTS_CONTROL_ENABLE; + switch (value_) + { + case none: + break; + case software: + storage.fOutX = TRUE; + storage.fInX = TRUE; + break; + case hardware: + storage.fOutxCtsFlow = TRUE; + storage.fRtsControl = RTS_CONTROL_HANDSHAKE; + break; + default: + break; + } +#else + switch (value_) + { + case none: + storage.c_iflag &= ~(IXOFF | IXON); +# if defined(_BSD_SOURCE) + storage.c_cflag &= ~CRTSCTS; +# endif + break; + case software: + storage.c_iflag |= IXOFF | IXON; +# if defined(_BSD_SOURCE) + storage.c_cflag &= ~CRTSCTS; +# endif + break; + case hardware: +# if defined(_BSD_SOURCE) + storage.c_iflag &= ~(IXOFF | IXON); + storage.c_cflag |= CRTSCTS; + break; +# else + ec = boost::asio::error::operation_not_supported; + return ec; +# endif + default: + break; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +inline boost::system::error_code serial_port_base::flow_control::load( + const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + if (storage.fOutX && storage.fInX) + { + value_ = software; + } + else if (storage.fOutxCtsFlow && storage.fRtsControl == RTS_CONTROL_HANDSHAKE) + { + value_ = hardware; + } + else + { + value_ = none; + } +#else + if (storage.c_iflag & (IXOFF | IXON)) + { + value_ = software; + } +# if defined(_BSD_SOURCE) + else if (storage.c_cflag & CRTSCTS) + { + value_ = hardware; + } +# endif + else + { + value_ = none; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +inline serial_port_base::parity::parity(serial_port_base::parity::type t) + : value_(t) +{ + if (t != none && t != odd && t != even) + throw std::out_of_range("invalid parity value"); +} + +inline serial_port_base::parity::type serial_port_base::parity::value() const +{ + return value_; +} + +inline boost::system::error_code serial_port_base::parity::store( + BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + switch (value_) + { + case none: + storage.fParity = FALSE; + storage.Parity = NOPARITY; + break; + case odd: + storage.fParity = TRUE; + storage.Parity = ODDPARITY; + break; + case even: + storage.fParity = TRUE; + storage.Parity = EVENPARITY; + break; + default: + break; + } +#else + switch (value_) + { + case none: + storage.c_iflag |= IGNPAR; + storage.c_cflag &= ~(PARENB | PARODD); + break; + case even: + storage.c_iflag &= ~(IGNPAR | PARMRK); + storage.c_iflag |= INPCK; + storage.c_cflag |= PARENB; + storage.c_cflag &= ~PARODD; + break; + case odd: + storage.c_iflag &= ~(IGNPAR | PARMRK); + storage.c_iflag |= INPCK; + storage.c_cflag |= (PARENB | PARODD); + break; + default: + break; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +inline boost::system::error_code serial_port_base::parity::load( + const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + if (storage.Parity == EVENPARITY) + { + value_ = even; + } + else if (storage.Parity == ODDPARITY) + { + value_ = odd; + } + else + { + value_ = none; + } +#else + if (storage.c_cflag & PARENB) + { + if (storage.c_cflag & PARODD) + { + value_ = odd; + } + else + { + value_ = even; + } + } + else + { + value_ = none; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +inline serial_port_base::stop_bits::stop_bits( + serial_port_base::stop_bits::type t) + : value_(t) +{ + if (t != one && t != onepointfive && t != two) + throw std::out_of_range("invalid stop_bits value"); +} + +inline serial_port_base::stop_bits::type +serial_port_base::stop_bits::value() const +{ + return value_; +} + +inline boost::system::error_code serial_port_base::stop_bits::store( + BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + switch (value_) + { + case one: + storage.StopBits = ONESTOPBIT; + break; + case onepointfive: + storage.StopBits = ONE5STOPBITS; + break; + case two: + storage.StopBits = TWOSTOPBITS; + break; + default: + break; + } +#else + switch (value_) + { + case one: + storage.c_cflag &= ~CSTOPB; + break; + case two: + storage.c_cflag |= CSTOPB; + break; + default: + ec = boost::asio::error::operation_not_supported; + return ec; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +inline boost::system::error_code serial_port_base::stop_bits::load( + const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + if (storage.StopBits == ONESTOPBIT) + { + value_ = one; + } + else if (storage.StopBits == ONE5STOPBITS) + { + value_ = onepointfive; + } + else if (storage.StopBits == TWOSTOPBITS) + { + value_ = two; + } + else + { + value_ = one; + } +#else + value_ = (storage.c_cflag & CSTOPB) ? two : one; +#endif + ec = boost::system::error_code(); + return ec; +} + +inline serial_port_base::character_size::character_size(unsigned int t) + : value_(t) +{ + if (t < 5 || t > 8) + throw std::out_of_range("invalid character_size value"); +} + +inline unsigned int serial_port_base::character_size::value() const +{ + return value_; +} + +inline boost::system::error_code serial_port_base::character_size::store( + BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + storage.ByteSize = value_; +#else + storage.c_cflag &= ~CSIZE; + switch (value_) + { + case 5: storage.c_cflag |= CS5; break; + case 6: storage.c_cflag |= CS6; break; + case 7: storage.c_cflag |= CS7; break; + case 8: storage.c_cflag |= CS8; break; + default: break; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +inline boost::system::error_code serial_port_base::character_size::load( + const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) +{ +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + value_ = storage.ByteSize; +#else + if ((storage.c_cflag & CSIZE) == CS5) { value_ = 5; } + else if ((storage.c_cflag & CSIZE) == CS6) { value_ = 6; } + else if ((storage.c_cflag & CSIZE) == CS7) { value_ = 7; } + else if ((storage.c_cflag & CSIZE) == CS8) { value_ = 8; } + else + { + // Hmmm, use 8 for now. + value_ = 8; + } +#endif + ec = boost::system::error_code(); + return ec; +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SERIAL_PORT_BASE_IPP diff --git a/win32/include/boost/asio/impl/write.ipp b/win32/include/boost/asio/impl/write.ipp new file mode 100755 index 000000000..1a53c269c --- /dev/null +++ b/win32/include/boost/asio/impl/write.ipp @@ -0,0 +1,281 @@ +// +// write.ipp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WRITE_IPP +#define BOOST_ASIO_WRITE_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +template +std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, boost::system::error_code& ec) +{ + boost::asio::detail::consuming_buffers< + const_buffer, ConstBufferSequence> tmp(buffers); + std::size_t total_transferred = 0; + while (tmp.begin() != tmp.end()) + { + std::size_t bytes_transferred = s.write_some(tmp, ec); + tmp.consume(bytes_transferred); + total_transferred += bytes_transferred; + if (completion_condition(ec, total_transferred)) + return total_transferred; + } + ec = boost::system::error_code(); + return total_transferred; +} + +template +inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, + CompletionCondition completion_condition) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = write(s, buffers, completion_condition, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +std::size_t write(SyncWriteStream& s, + boost::asio::basic_streambuf& b, + CompletionCondition completion_condition, boost::system::error_code& ec) +{ + std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec); + b.consume(bytes_transferred); + return bytes_transferred; +} + +template +inline std::size_t write(SyncWriteStream& s, + boost::asio::basic_streambuf& b) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = write(s, b, transfer_all(), ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t write(SyncWriteStream& s, + boost::asio::basic_streambuf& b, + CompletionCondition completion_condition) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = write(s, b, completion_condition, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +namespace detail +{ + template + class write_handler + { + public: + typedef boost::asio::detail::consuming_buffers< + const_buffer, ConstBufferSequence> buffers_type; + + write_handler(AsyncWriteStream& stream, const buffers_type& buffers, + CompletionCondition completion_condition, WriteHandler handler) + : stream_(stream), + buffers_(buffers), + total_transferred_(0), + completion_condition_(completion_condition), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + total_transferred_ += bytes_transferred; + buffers_.consume(bytes_transferred); + if (completion_condition_(ec, total_transferred_) + || buffers_.begin() == buffers_.end()) + { + handler_(ec, total_transferred_); + } + else + { + stream_.async_write_some(buffers_, *this); + } + } + + //private: + AsyncWriteStream& stream_; + buffers_type buffers_; + std::size_t total_transferred_; + CompletionCondition completion_condition_; + WriteHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + write_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + write_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + write_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, WriteHandler handler) +{ + boost::asio::detail::consuming_buffers< + const_buffer, ConstBufferSequence> tmp(buffers); + s.async_write_some(tmp, + detail::write_handler( + s, tmp, completion_condition, handler)); +} + +template +inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, + WriteHandler handler) +{ + async_write(s, buffers, transfer_all(), handler); +} + +namespace detail +{ + template + class write_streambuf_handler + { + public: + write_streambuf_handler(boost::asio::basic_streambuf& streambuf, + WriteHandler handler) + : streambuf_(streambuf), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + streambuf_.consume(bytes_transferred); + handler_(ec, bytes_transferred); + } + + //private: + boost::asio::basic_streambuf& streambuf_; + WriteHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + write_streambuf_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + write_streambuf_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + write_streambuf_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_write(AsyncWriteStream& s, + boost::asio::basic_streambuf& b, + CompletionCondition completion_condition, WriteHandler handler) +{ + async_write(s, b.data(), completion_condition, + detail::write_streambuf_handler< + AsyncWriteStream, Allocator, WriteHandler>(b, handler)); +} + +template +inline void async_write(AsyncWriteStream& s, + boost::asio::basic_streambuf& b, WriteHandler handler) +{ + async_write(s, b, transfer_all(), handler); +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_WRITE_IPP diff --git a/win32/include/boost/asio/impl/write_at.ipp b/win32/include/boost/asio/impl/write_at.ipp new file mode 100755 index 000000000..1e1ee21af --- /dev/null +++ b/win32/include/boost/asio/impl/write_at.ipp @@ -0,0 +1,298 @@ +// +// write_at.ipp +// ~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WRITE_AT_IPP +#define BOOST_ASIO_WRITE_AT_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, boost::system::error_code& ec) +{ + boost::asio::detail::consuming_buffers< + const_buffer, ConstBufferSequence> tmp(buffers); + std::size_t total_transferred = 0; + while (tmp.begin() != tmp.end()) + { + std::size_t bytes_transferred = d.write_some_at( + offset + total_transferred, tmp, ec); + tmp.consume(bytes_transferred); + total_transferred += bytes_transferred; + if (completion_condition(ec, total_transferred)) + return total_transferred; + } + ec = boost::system::error_code(); + return total_transferred; +} + +template +inline std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = write_at( + d, offset, buffers, transfer_all(), ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = write_at( + d, offset, buffers, completion_condition, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + CompletionCondition completion_condition, boost::system::error_code& ec) +{ + std::size_t bytes_transferred = write_at( + d, offset, b.data(), completion_condition, ec); + b.consume(bytes_transferred); + return bytes_transferred; +} + +template +inline std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +template +inline std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + CompletionCondition completion_condition) +{ + boost::system::error_code ec; + std::size_t bytes_transferred = write_at( + d, offset, b, completion_condition, ec); + boost::asio::detail::throw_error(ec); + return bytes_transferred; +} + +namespace detail +{ + template + class write_at_handler + { + public: + typedef boost::asio::detail::consuming_buffers< + const_buffer, ConstBufferSequence> buffers_type; + + write_at_handler(AsyncRandomAccessWriteDevice& stream, + boost::uint64_t offset, const buffers_type& buffers, + CompletionCondition completion_condition, WriteHandler handler) + : stream_(stream), + buffers_(buffers), + offset_(offset), + total_transferred_(0), + completion_condition_(completion_condition), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + total_transferred_ += bytes_transferred; + buffers_.consume(bytes_transferred); + if (completion_condition_(ec, total_transferred_) + || buffers_.begin() == buffers_.end()) + { + handler_(ec, total_transferred_); + } + else + { + stream_.async_write_some_at( + offset_ + total_transferred_, buffers_, *this); + } + } + + //private: + AsyncRandomAccessWriteDevice& stream_; + buffers_type buffers_; + boost::uint64_t offset_; + std::size_t total_transferred_; + CompletionCondition completion_condition_; + WriteHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + write_at_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + write_at_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + write_at_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, WriteHandler handler) +{ + boost::asio::detail::consuming_buffers< + const_buffer, ConstBufferSequence> tmp(buffers); + d.async_write_some_at(offset, tmp, + detail::write_at_handler( + d, offset, tmp, completion_condition, handler)); +} + +template +inline void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + WriteHandler handler) +{ + async_write_at(d, offset, buffers, transfer_all(), handler); +} + +namespace detail +{ + template + class write_at_streambuf_handler + { + public: + write_at_streambuf_handler( + boost::asio::basic_streambuf& streambuf, + WriteHandler handler) + : streambuf_(streambuf), + handler_(handler) + { + } + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred) + { + streambuf_.consume(bytes_transferred); + handler_(ec, bytes_transferred); + } + + //private: + boost::asio::basic_streambuf& streambuf_; + WriteHandler handler_; + }; + + template + inline void* asio_handler_allocate(std::size_t size, + write_at_streambuf_handler* this_handler) + { + return boost_asio_handler_alloc_helpers::allocate( + size, &this_handler->handler_); + } + + template + inline void asio_handler_deallocate(void* pointer, std::size_t size, + write_at_streambuf_handler* this_handler) + { + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, &this_handler->handler_); + } + + template + inline void asio_handler_invoke(const Function& function, + write_at_streambuf_handler* this_handler) + { + boost_asio_handler_invoke_helpers::invoke( + function, &this_handler->handler_); + } +} // namespace detail + +template +inline void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + CompletionCondition completion_condition, WriteHandler handler) +{ + async_write_at(d, offset, b.data(), completion_condition, + detail::write_at_streambuf_handler< + AsyncRandomAccessWriteDevice, Allocator, WriteHandler>(b, handler)); +} + +template +inline void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, boost::asio::basic_streambuf& b, + WriteHandler handler) +{ + async_write_at(d, offset, b, transfer_all(), handler); +} + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_WRITE_AT_IPP diff --git a/win32/include/boost/asio/io_service.hpp b/win32/include/boost/asio/io_service.hpp new file mode 100755 index 000000000..a0a09ae1d --- /dev/null +++ b/win32/include/boost/asio/io_service.hpp @@ -0,0 +1,553 @@ +// +// io_service.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IO_SERVICE_HPP +#define BOOST_ASIO_IO_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +class io_service; +template Service& use_service(io_service& ios); +template void add_service(io_service& ios, Service* svc); +template bool has_service(io_service& ios); + +/// Provides core I/O functionality. +/** + * The io_service class provides the core I/O functionality for users of the + * asynchronous I/O objects, including: + * + * @li boost::asio::ip::tcp::socket + * @li boost::asio::ip::tcp::acceptor + * @li boost::asio::ip::udp::socket + * @li boost::asio::deadline_timer. + * + * The io_service class also includes facilities intended for developers of + * custom asynchronous services. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe, with the exception that calling reset() + * while there are unfinished run() calls results in undefined behaviour. + * + * @par Concepts: + * Dispatcher. + * + * @par Effect of exceptions thrown from handlers + * + * If an exception is thrown from a handler, the exception is allowed to + * propagate through the throwing thread's invocation of + * boost::asio::io_service::run(), boost::asio::io_service::run_one(), + * boost::asio::io_service::poll() or boost::asio::io_service::poll_one(). + * No other threads that are calling any of these functions are affected. It is + * then the responsibility of the application to catch the exception. + * + * After the exception has been caught, the + * boost::asio::io_service::run(), boost::asio::io_service::run_one(), + * boost::asio::io_service::poll() or boost::asio::io_service::poll_one() + * call may be restarted @em without the need for an intervening call to + * boost::asio::io_service::reset(). This allows the thread to rejoin the + * io_service's thread pool without impacting any other threads in the pool. + * + * For example: + * + * @code + * boost::asio::io_service io_service; + * ... + * for (;;) + * { + * try + * { + * io_service.run(); + * break; // run() exited normally + * } + * catch (my_exception& e) + * { + * // Deal with exception as appropriate. + * } + * } + * @endcode + * + * @par Stopping the io_service from running out of work + * + * Some applications may need to prevent an io_service's run() call from + * returning when there is no more work to do. For example, the io_service may + * be being run in a background thread that is launched prior to the + * application's asynchronous operations. The run() call may be kept running by + * creating an object of type boost::asio::io_service::work: + * + * @code boost::asio::io_service io_service; + * boost::asio::io_service::work work(io_service); + * ... @endcode + * + * To effect a shutdown, the application will then need to call the io_service's + * stop() member function. This will cause the io_service run() call to return + * as soon as possible, abandoning unfinished operations and without permitting + * ready handlers to be dispatched. + * + * Alternatively, if the application requires that all operations and handlers + * be allowed to finish normally, the work object may be explicitly destroyed. + * + * @code boost::asio::io_service io_service; + * auto_ptr work( + * new boost::asio::io_service::work(io_service)); + * ... + * work.reset(); // Allow run() to exit. @endcode + */ +class io_service + : private noncopyable +{ +private: + // The type of the platform-specific implementation. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef detail::win_iocp_io_service impl_type; +#elif defined(BOOST_ASIO_HAS_EPOLL) + typedef detail::task_io_service > impl_type; +#elif defined(BOOST_ASIO_HAS_KQUEUE) + typedef detail::task_io_service > impl_type; +#elif defined(BOOST_ASIO_HAS_DEV_POLL) + typedef detail::task_io_service > impl_type; +#else + typedef detail::task_io_service > impl_type; +#endif + +public: + class work; + friend class work; + + class id; + + class service; + + class strand; + + /// Constructor. + io_service(); + + /// Constructor. + /** + * Construct with a hint about the required level of concurrency. + * + * @param concurrency_hint A suggestion to the implementation on how many + * threads it should allow to run simultaneously. + */ + explicit io_service(std::size_t concurrency_hint); + + /// Destructor. + ~io_service(); + + /// Run the io_service's event processing loop. + /** + * The run() function blocks until all work has finished and there are no + * more handlers to be dispatched, or until the io_service has been stopped. + * + * Multiple threads may call the run() function to set up a pool of threads + * from which the io_service may execute handlers. All threads that are + * waiting in the pool are equivalent and the io_service may choose any one + * of them to invoke a handler. + * + * The run() function may be safely called again once it has completed only + * after a call to reset(). + * + * @return The number of handlers that were executed. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The poll() function may also be used to dispatch ready handlers, + * but without blocking. + */ + std::size_t run(); + + /// Run the io_service's event processing loop. + /** + * The run() function blocks until all work has finished and there are no + * more handlers to be dispatched, or until the io_service has been stopped. + * + * Multiple threads may call the run() function to set up a pool of threads + * from which the io_service may execute handlers. All threads that are + * waiting in the pool are equivalent and the io_service may choose any one + * of them to invoke a handler. + * + * The run() function may be safely called again once it has completed only + * after a call to reset(). + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of handlers that were executed. + * + * @note The poll() function may also be used to dispatch ready handlers, + * but without blocking. + */ + std::size_t run(boost::system::error_code& ec); + + /// Run the io_service's event processing loop to execute at most one handler. + /** + * The run_one() function blocks until one handler has been dispatched, or + * until the io_service has been stopped. + * + * @return The number of handlers that were executed. + * + * @throws boost::system::system_error Thrown on failure. + */ + std::size_t run_one(); + + /// Run the io_service's event processing loop to execute at most one handler. + /** + * The run_one() function blocks until one handler has been dispatched, or + * until the io_service has been stopped. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of handlers that were executed. + */ + std::size_t run_one(boost::system::error_code& ec); + + /// Run the io_service's event processing loop to execute ready handlers. + /** + * The poll() function runs handlers that are ready to run, without blocking, + * until the io_service has been stopped or there are no more ready handlers. + * + * @return The number of handlers that were executed. + * + * @throws boost::system::system_error Thrown on failure. + */ + std::size_t poll(); + + /// Run the io_service's event processing loop to execute ready handlers. + /** + * The poll() function runs handlers that are ready to run, without blocking, + * until the io_service has been stopped or there are no more ready handlers. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of handlers that were executed. + */ + std::size_t poll(boost::system::error_code& ec); + + /// Run the io_service's event processing loop to execute one ready handler. + /** + * The poll_one() function runs at most one handler that is ready to run, + * without blocking. + * + * @return The number of handlers that were executed. + * + * @throws boost::system::system_error Thrown on failure. + */ + std::size_t poll_one(); + + /// Run the io_service's event processing loop to execute one ready handler. + /** + * The poll_one() function runs at most one handler that is ready to run, + * without blocking. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of handlers that were executed. + */ + std::size_t poll_one(boost::system::error_code& ec); + + /// Stop the io_service's event processing loop. + /** + * This function does not block, but instead simply signals the io_service to + * stop. All invocations of its run() or run_one() member functions should + * return as soon as possible. Subsequent calls to run(), run_one(), poll() + * or poll_one() will return immediately until reset() is called. + */ + void stop(); + + /// Reset the io_service in preparation for a subsequent run() invocation. + /** + * This function must be called prior to any second or later set of + * invocations of the run(), run_one(), poll() or poll_one() functions when a + * previous invocation of these functions returned due to the io_service + * being stopped or running out of work. This function allows the io_service + * to reset any internal state, such as a "stopped" flag. + * + * This function must not be called while there are any unfinished calls to + * the run(), run_one(), poll() or poll_one() functions. + */ + void reset(); + + /// Request the io_service to invoke the given handler. + /** + * This function is used to ask the io_service to execute the given handler. + * + * The io_service guarantees that the handler will only be called in a thread + * in which the run(), run_one(), poll() or poll_one() member functions is + * currently being invoked. The handler may be executed inside this function + * if the guarantee can be met. + * + * @param handler The handler to be called. The io_service will make + * a copy of the handler object as required. The function signature of the + * handler must be: @code void handler(); @endcode + */ + template + void dispatch(CompletionHandler handler); + + /// Request the io_service to invoke the given handler and return immediately. + /** + * This function is used to ask the io_service to execute the given handler, + * but without allowing the io_service to call the handler from inside this + * function. + * + * The io_service guarantees that the handler will only be called in a thread + * in which the run(), run_one(), poll() or poll_one() member functions is + * currently being invoked. + * + * @param handler The handler to be called. The io_service will make + * a copy of the handler object as required. The function signature of the + * handler must be: @code void handler(); @endcode + */ + template + void post(CompletionHandler handler); + + /// Create a new handler that automatically dispatches the wrapped handler + /// on the io_service. + /** + * This function is used to create a new handler function object that, when + * invoked, will automatically pass the wrapped handler to the io_service's + * dispatch function. + * + * @param handler The handler to be wrapped. The io_service will make a copy + * of the handler object as required. The function signature of the handler + * must be: @code void handler(A1 a1, ... An an); @endcode + * + * @return A function object that, when invoked, passes the wrapped handler to + * the io_service's dispatch function. Given a function object with the + * signature: + * @code R f(A1 a1, ... An an); @endcode + * If this function object is passed to the wrap function like so: + * @code io_service.wrap(f); @endcode + * then the return value is a function object with the signature + * @code void g(A1 a1, ... An an); @endcode + * that, when invoked, executes code equivalent to: + * @code io_service.dispatch(boost::bind(f, a1, ... an)); @endcode + */ + template +#if defined(GENERATING_DOCUMENTATION) + unspecified +#else + detail::wrapped_handler +#endif + wrap(Handler handler); + + /// Obtain the service object corresponding to the given type. + /** + * This function is used to locate a service object that corresponds to + * the given service type. If there is no existing implementation of the + * service, then the io_service will create a new instance of the service. + * + * @param ios The io_service object that owns the service. + * + * @return The service interface implementing the specified service type. + * Ownership of the service interface is not transferred to the caller. + */ + template + friend Service& use_service(io_service& ios); + + /// Add a service object to the io_service. + /** + * This function is used to add a service to the io_service. + * + * @param ios The io_service object that owns the service. + * + * @param svc The service object. On success, ownership of the service object + * is transferred to the io_service. When the io_service object is destroyed, + * it will destroy the service object by performing: + * @code delete static_cast(svc) @endcode + * + * @throws boost::asio::service_already_exists Thrown if a service of the + * given type is already present in the io_service. + * + * @throws boost::asio::invalid_service_owner Thrown if the service's owning + * io_service is not the io_service object specified by the ios parameter. + */ + template + friend void add_service(io_service& ios, Service* svc); + + /// Determine if an io_service contains a specified service type. + /** + * This function is used to determine whether the io_service contains a + * service object corresponding to the given service type. + * + * @param ios The io_service object that owns the service. + * + * @return A boolean indicating whether the io_service contains the service. + */ + template + friend bool has_service(io_service& ios); + +private: +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + detail::winsock_init<> init_; +#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \ + || defined(__osf__) + detail::signal_init<> init_; +#endif + + // The service registry. + boost::asio::detail::service_registry* service_registry_; + + // The implementation. + impl_type& impl_; +}; + +/// Class to inform the io_service when it has work to do. +/** + * The work class is used to inform the io_service when work starts and + * finishes. This ensures that the io_service's run() function will not exit + * while work is underway, and that it does exit when there is no unfinished + * work remaining. + * + * The work class is copy-constructible so that it may be used as a data member + * in a handler class. It is not assignable. + */ +class io_service::work +{ +public: + /// Constructor notifies the io_service that work is starting. + /** + * The constructor is used to inform the io_service that some work has begun. + * This ensures that the io_service's run() function will not exit while the + * work is underway. + */ + explicit work(boost::asio::io_service& io_service); + + /// Copy constructor notifies the io_service that work is starting. + /** + * The constructor is used to inform the io_service that some work has begun. + * This ensures that the io_service's run() function will not exit while the + * work is underway. + */ + work(const work& other); + + /// Destructor notifies the io_service that the work is complete. + /** + * The destructor is used to inform the io_service that some work has + * finished. Once the count of unfinished work reaches zero, the io_service's + * run() function is permitted to exit. + */ + ~work(); + + /// (Deprecated: use get_io_service().) Get the io_service associated with the + /// work. + boost::asio::io_service& io_service(); + + /// Get the io_service associated with the work. + boost::asio::io_service& get_io_service(); + +private: + // Prevent assignment. + void operator=(const work& other); + + // The io_service. + boost::asio::io_service& io_service_; +}; + +/// Class used to uniquely identify a service. +class io_service::id + : private noncopyable +{ +public: + /// Constructor. + id() {} +}; + +/// Base class for all io_service services. +class io_service::service + : private noncopyable +{ +public: + /// (Deprecated: use get_io_service().) Get the io_service object that owns + /// the service. + boost::asio::io_service& io_service(); + + /// Get the io_service object that owns the service. + boost::asio::io_service& get_io_service(); + +protected: + /// Constructor. + /** + * @param owner The io_service object that owns the service. + */ + service(boost::asio::io_service& owner); + + /// Destructor. + virtual ~service(); + +private: + /// Destroy all user-defined handler objects owned by the service. + virtual void shutdown_service() = 0; + + friend class boost::asio::detail::service_registry; + boost::asio::io_service& owner_; + const std::type_info* type_info_; + const boost::asio::io_service::id* id_; + service* next_; +}; + +/// Exception thrown when trying to add a duplicate service to an io_service. +class service_already_exists + : public std::logic_error +{ +public: + service_already_exists() + : std::logic_error("Service already exists.") + { + } +}; + +/// Exception thrown when trying to add a service object to an io_service where +/// the service has a different owner. +class invalid_service_owner + : public std::logic_error +{ +public: + invalid_service_owner() + : std::logic_error("Invalid service owner.") + { + } +}; + +} // namespace asio +} // namespace boost + +#include + +#include + +#endif // BOOST_ASIO_IO_SERVICE_HPP diff --git a/win32/include/boost/asio/ip/address.hpp b/win32/include/boost/asio/ip/address.hpp new file mode 100755 index 000000000..dd11b70de --- /dev/null +++ b/win32/include/boost/asio/ip/address.hpp @@ -0,0 +1,279 @@ +// +// address.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_ADDRESS_HPP +#define BOOST_ASIO_IP_ADDRESS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ip { + +/// Implements version-independent IP addresses. +/** + * The boost::asio::ip::address class provides the ability to use either IP + * version 4 or version 6 addresses. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +class address +{ +public: + /// Default constructor. + address() + : type_(ipv4), + ipv4_address_(), + ipv6_address_() + { + } + + /// Construct an address from an IPv4 address. + address(const boost::asio::ip::address_v4& ipv4_address) + : type_(ipv4), + ipv4_address_(ipv4_address), + ipv6_address_() + { + } + + /// Construct an address from an IPv6 address. + address(const boost::asio::ip::address_v6& ipv6_address) + : type_(ipv6), + ipv4_address_(), + ipv6_address_(ipv6_address) + { + } + + /// Copy constructor. + address(const address& other) + : type_(other.type_), + ipv4_address_(other.ipv4_address_), + ipv6_address_(other.ipv6_address_) + { + } + + /// Assign from another address. + address& operator=(const address& other) + { + type_ = other.type_; + ipv4_address_ = other.ipv4_address_; + ipv6_address_ = other.ipv6_address_; + return *this; + } + + /// Assign from an IPv4 address. + address& operator=(const boost::asio::ip::address_v4& ipv4_address) + { + type_ = ipv4; + ipv4_address_ = ipv4_address; + ipv6_address_ = boost::asio::ip::address_v6(); + return *this; + } + + /// Assign from an IPv6 address. + address& operator=(const boost::asio::ip::address_v6& ipv6_address) + { + type_ = ipv6; + ipv4_address_ = boost::asio::ip::address_v4(); + ipv6_address_ = ipv6_address; + return *this; + } + + /// Get whether the address is an IP version 4 address. + bool is_v4() const + { + return type_ == ipv4; + } + + /// Get whether the address is an IP version 6 address. + bool is_v6() const + { + return type_ == ipv6; + } + + /// Get the address as an IP version 4 address. + boost::asio::ip::address_v4 to_v4() const + { + if (type_ != ipv4) + { + boost::system::system_error e( + boost::asio::error::address_family_not_supported); + boost::throw_exception(e); + } + return ipv4_address_; + } + + /// Get the address as an IP version 6 address. + boost::asio::ip::address_v6 to_v6() const + { + if (type_ != ipv6) + { + boost::system::system_error e( + boost::asio::error::address_family_not_supported); + boost::throw_exception(e); + } + return ipv6_address_; + } + + /// Get the address as a string in dotted decimal format. + std::string to_string() const + { + if (type_ == ipv6) + return ipv6_address_.to_string(); + return ipv4_address_.to_string(); + } + + /// Get the address as a string in dotted decimal format. + std::string to_string(boost::system::error_code& ec) const + { + if (type_ == ipv6) + return ipv6_address_.to_string(ec); + return ipv4_address_.to_string(ec); + } + + /// Create an address from an IPv4 address string in dotted decimal form, + /// or from an IPv6 address in hexadecimal notation. + static address from_string(const char* str) + { + boost::system::error_code ec; + address addr = from_string(str, ec); + boost::asio::detail::throw_error(ec); + return addr; + } + + /// Create an address from an IPv4 address string in dotted decimal form, + /// or from an IPv6 address in hexadecimal notation. + static address from_string(const char* str, boost::system::error_code& ec) + { + boost::asio::ip::address_v6 ipv6_address = + boost::asio::ip::address_v6::from_string(str, ec); + if (!ec) + { + address tmp; + tmp.type_ = ipv6; + tmp.ipv6_address_ = ipv6_address; + return tmp; + } + + boost::asio::ip::address_v4 ipv4_address = + boost::asio::ip::address_v4::from_string(str, ec); + if (!ec) + { + address tmp; + tmp.type_ = ipv4; + tmp.ipv4_address_ = ipv4_address; + return tmp; + } + + return address(); + } + + /// Create an address from an IPv4 address string in dotted decimal form, + /// or from an IPv6 address in hexadecimal notation. + static address from_string(const std::string& str) + { + return from_string(str.c_str()); + } + + /// Create an address from an IPv4 address string in dotted decimal form, + /// or from an IPv6 address in hexadecimal notation. + static address from_string(const std::string& str, + boost::system::error_code& ec) + { + return from_string(str.c_str(), ec); + } + + /// Compare two addresses for equality. + friend bool operator==(const address& a1, const address& a2) + { + if (a1.type_ != a2.type_) + return false; + if (a1.type_ == ipv6) + return a1.ipv6_address_ == a2.ipv6_address_; + return a1.ipv4_address_ == a2.ipv4_address_; + } + + /// Compare two addresses for inequality. + friend bool operator!=(const address& a1, const address& a2) + { + if (a1.type_ != a2.type_) + return true; + if (a1.type_ == ipv6) + return a1.ipv6_address_ != a2.ipv6_address_; + return a1.ipv4_address_ != a2.ipv4_address_; + } + + /// Compare addresses for ordering. + friend bool operator<(const address& a1, const address& a2) + { + if (a1.type_ < a2.type_) + return true; + if (a1.type_ > a2.type_) + return false; + if (a1.type_ == ipv6) + return a1.ipv6_address_ < a2.ipv6_address_; + return a1.ipv4_address_ < a2.ipv4_address_; + } + +private: + // The type of the address. + enum { ipv4, ipv6 } type_; + + // The underlying IPv4 address. + boost::asio::ip::address_v4 ipv4_address_; + + // The underlying IPv6 address. + boost::asio::ip::address_v6 ipv6_address_; +}; + +/// Output an address as a string. +/** + * Used to output a human-readable string for a specified address. + * + * @param os The output stream to which the string will be written. + * + * @param addr The address to be written. + * + * @return The output stream. + * + * @relates boost::asio::ip::address + */ +template +std::basic_ostream& operator<<( + std::basic_ostream& os, const address& addr) +{ + os << addr.to_string(); + return os; +} + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_ADDRESS_HPP diff --git a/win32/include/boost/asio/ip/address_v4.hpp b/win32/include/boost/asio/ip/address_v4.hpp new file mode 100755 index 000000000..451b238a8 --- /dev/null +++ b/win32/include/boost/asio/ip/address_v4.hpp @@ -0,0 +1,290 @@ +// +// address_v4.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_ADDRESS_V4_HPP +#define BOOST_ASIO_IP_ADDRESS_V4_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ip { + +/// Implements IP version 4 style addresses. +/** + * The boost::asio::ip::address_v4 class provides the ability to use and + * manipulate IP version 4 addresses. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +class address_v4 +{ +public: + /// The type used to represent an address as an array of bytes. + typedef boost::array bytes_type; + + /// Default constructor. + address_v4() + { + addr_.s_addr = 0; + } + + /// Construct an address from raw bytes. + explicit address_v4(const bytes_type& bytes) + { + using namespace std; // For memcpy. + memcpy(&addr_.s_addr, bytes.elems, 4); + } + + /// Construct an address from a unsigned long in host byte order. + explicit address_v4(unsigned long addr) + { + addr_.s_addr = boost::asio::detail::socket_ops::host_to_network_long(addr); + } + + /// Copy constructor. + address_v4(const address_v4& other) + : addr_(other.addr_) + { + } + + /// Assign from another address. + address_v4& operator=(const address_v4& other) + { + addr_ = other.addr_; + return *this; + } + + /// Get the address in bytes. + bytes_type to_bytes() const + { + using namespace std; // For memcpy. + bytes_type bytes; + memcpy(bytes.elems, &addr_.s_addr, 4); + return bytes; + } + + /// Get the address as an unsigned long in host byte order + unsigned long to_ulong() const + { + return boost::asio::detail::socket_ops::network_to_host_long(addr_.s_addr); + } + + /// Get the address as a string in dotted decimal format. + std::string to_string() const + { + boost::system::error_code ec; + std::string addr = to_string(ec); + boost::asio::detail::throw_error(ec); + return addr; + } + + /// Get the address as a string in dotted decimal format. + std::string to_string(boost::system::error_code& ec) const + { + char addr_str[boost::asio::detail::max_addr_v4_str_len]; + const char* addr = + boost::asio::detail::socket_ops::inet_ntop(AF_INET, &addr_, addr_str, + boost::asio::detail::max_addr_v4_str_len, 0, ec); + if (addr == 0) + return std::string(); + return addr; + } + + /// Create an address from an IP address string in dotted decimal form. + static address_v4 from_string(const char* str) + { + boost::system::error_code ec; + address_v4 addr = from_string(str, ec); + boost::asio::detail::throw_error(ec); + return addr; + } + + /// Create an address from an IP address string in dotted decimal form. + static address_v4 from_string(const char* str, boost::system::error_code& ec) + { + address_v4 tmp; + if (boost::asio::detail::socket_ops::inet_pton( + AF_INET, str, &tmp.addr_, 0, ec) <= 0) + return address_v4(); + return tmp; + } + + /// Create an address from an IP address string in dotted decimal form. + static address_v4 from_string(const std::string& str) + { + return from_string(str.c_str()); + } + + /// Create an address from an IP address string in dotted decimal form. + static address_v4 from_string(const std::string& str, + boost::system::error_code& ec) + { + return from_string(str.c_str(), ec); + } + + /// Determine whether the address is a class A address. + bool is_class_a() const + { + return IN_CLASSA(to_ulong()); + } + + /// Determine whether the address is a class B address. + bool is_class_b() const + { + return IN_CLASSB(to_ulong()); + } + + /// Determine whether the address is a class C address. + bool is_class_c() const + { + return IN_CLASSC(to_ulong()); + } + + /// Determine whether the address is a multicast address. + bool is_multicast() const + { + return IN_MULTICAST(to_ulong()); + } + + /// Compare two addresses for equality. + friend bool operator==(const address_v4& a1, const address_v4& a2) + { + return a1.addr_.s_addr == a2.addr_.s_addr; + } + + /// Compare two addresses for inequality. + friend bool operator!=(const address_v4& a1, const address_v4& a2) + { + return a1.addr_.s_addr != a2.addr_.s_addr; + } + + /// Compare addresses for ordering. + friend bool operator<(const address_v4& a1, const address_v4& a2) + { + return a1.to_ulong() < a2.to_ulong(); + } + + /// Compare addresses for ordering. + friend bool operator>(const address_v4& a1, const address_v4& a2) + { + return a1.to_ulong() > a2.to_ulong(); + } + + /// Compare addresses for ordering. + friend bool operator<=(const address_v4& a1, const address_v4& a2) + { + return a1.to_ulong() <= a2.to_ulong(); + } + + /// Compare addresses for ordering. + friend bool operator>=(const address_v4& a1, const address_v4& a2) + { + return a1.to_ulong() >= a2.to_ulong(); + } + + /// Obtain an address object that represents any address. + static address_v4 any() + { + return address_v4(static_cast(INADDR_ANY)); + } + + /// Obtain an address object that represents the loopback address. + static address_v4 loopback() + { + return address_v4(static_cast(INADDR_LOOPBACK)); + } + + /// Obtain an address object that represents the broadcast address. + static address_v4 broadcast() + { + return address_v4(static_cast(INADDR_BROADCAST)); + } + + /// Obtain an address object that represents the broadcast address that + /// corresponds to the specified address and netmask. + static address_v4 broadcast(const address_v4& addr, const address_v4& mask) + { + return address_v4(addr.to_ulong() | ~mask.to_ulong()); + } + + /// Obtain the netmask that corresponds to the address, based on its address + /// class. + static address_v4 netmask(const address_v4& addr) + { + if (addr.is_class_a()) + return address_v4(0xFF000000); + if (addr.is_class_b()) + return address_v4(0xFFFF0000); + if (addr.is_class_c()) + return address_v4(0xFFFFFF00); + return address_v4(0xFFFFFFFF); + } + +private: + // The underlying IPv4 address. + boost::asio::detail::in4_addr_type addr_; +}; + +/// Output an address as a string. +/** + * Used to output a human-readable string for a specified address. + * + * @param os The output stream to which the string will be written. + * + * @param addr The address to be written. + * + * @return The output stream. + * + * @relates boost::asio::ip::address_v4 + */ +template +std::basic_ostream& operator<<( + std::basic_ostream& os, const address_v4& addr) +{ + boost::system::error_code ec; + std::string s = addr.to_string(ec); + if (ec) + { + if (os.exceptions() & std::ios::failbit) + boost::asio::detail::throw_error(ec); + else + os.setstate(std::ios_base::failbit); + } + else + for (std::string::iterator i = s.begin(); i != s.end(); ++i) + os << os.widen(*i); + return os; +} + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_ADDRESS_V4_HPP diff --git a/win32/include/boost/asio/ip/address_v6.hpp b/win32/include/boost/asio/ip/address_v6.hpp new file mode 100755 index 000000000..1326dd118 --- /dev/null +++ b/win32/include/boost/asio/ip/address_v6.hpp @@ -0,0 +1,408 @@ +// +// address_v6.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_ADDRESS_V6_HPP +#define BOOST_ASIO_IP_ADDRESS_V6_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ip { + +/// Implements IP version 6 style addresses. +/** + * The boost::asio::ip::address_v6 class provides the ability to use and + * manipulate IP version 6 addresses. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +class address_v6 +{ +public: + /// The type used to represent an address as an array of bytes. + typedef boost::array bytes_type; + + /// Default constructor. + address_v6() + : scope_id_(0) + { + boost::asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; + addr_ = tmp_addr; + } + + /// Construct an address from raw bytes and scope ID. + explicit address_v6(const bytes_type& bytes, unsigned long scope_id = 0) + : scope_id_(scope_id) + { + using namespace std; // For memcpy. + memcpy(addr_.s6_addr, bytes.elems, 16); + } + + /// Copy constructor. + address_v6(const address_v6& other) + : addr_(other.addr_), + scope_id_(other.scope_id_) + { + } + + /// Assign from another address. + address_v6& operator=(const address_v6& other) + { + addr_ = other.addr_; + scope_id_ = other.scope_id_; + return *this; + } + + /// The scope ID of the address. + /** + * Returns the scope ID associated with the IPv6 address. + */ + unsigned long scope_id() const + { + return scope_id_; + } + + /// The scope ID of the address. + /** + * Modifies the scope ID associated with the IPv6 address. + */ + void scope_id(unsigned long id) + { + scope_id_ = id; + } + + /// Get the address in bytes. + bytes_type to_bytes() const + { + using namespace std; // For memcpy. + bytes_type bytes; + memcpy(bytes.elems, addr_.s6_addr, 16); + return bytes; + } + + /// Get the address as a string. + std::string to_string() const + { + boost::system::error_code ec; + std::string addr = to_string(ec); + boost::asio::detail::throw_error(ec); + return addr; + } + + /// Get the address as a string. + std::string to_string(boost::system::error_code& ec) const + { + char addr_str[boost::asio::detail::max_addr_v6_str_len]; + const char* addr = + boost::asio::detail::socket_ops::inet_ntop(AF_INET6, &addr_, addr_str, + boost::asio::detail::max_addr_v6_str_len, scope_id_, ec); + if (addr == 0) + return std::string(); + return addr; + } + + /// Create an address from an IP address string. + static address_v6 from_string(const char* str) + { + boost::system::error_code ec; + address_v6 addr = from_string(str, ec); + boost::asio::detail::throw_error(ec); + return addr; + } + + /// Create an address from an IP address string. + static address_v6 from_string(const char* str, boost::system::error_code& ec) + { + address_v6 tmp; + if (boost::asio::detail::socket_ops::inet_pton( + AF_INET6, str, &tmp.addr_, &tmp.scope_id_, ec) <= 0) + return address_v6(); + return tmp; + } + + /// Create an address from an IP address string. + static address_v6 from_string(const std::string& str) + { + return from_string(str.c_str()); + } + + /// Create an address from an IP address string. + static address_v6 from_string(const std::string& str, + boost::system::error_code& ec) + { + return from_string(str.c_str(), ec); + } + + /// Converts an IPv4-mapped or IPv4-compatible address to an IPv4 address. + address_v4 to_v4() const + { + if (!is_v4_mapped() && !is_v4_compatible()) + throw std::bad_cast(); + address_v4::bytes_type v4_bytes = { { addr_.s6_addr[12], + addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } }; + return address_v4(v4_bytes); + } + + /// Determine whether the address is a loopback address. + bool is_loopback() const + { +#if defined(__BORLANDC__) + return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) + && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) + && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0) + && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0) + && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0) + && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0) + && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0) + && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1)); +#else + using namespace boost::asio::detail; + return IN6_IS_ADDR_LOOPBACK(&addr_) != 0; +#endif + } + + /// Determine whether the address is unspecified. + bool is_unspecified() const + { +#if defined(__BORLANDC__) + return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) + && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) + && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0) + && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0) + && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0) + && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0) + && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0) + && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0)); +#else + using namespace boost::asio::detail; + return IN6_IS_ADDR_UNSPECIFIED(&addr_) != 0; +#endif + } + + /// Determine whether the address is link local. + bool is_link_local() const + { + using namespace boost::asio::detail; + return IN6_IS_ADDR_LINKLOCAL(&addr_) != 0; + } + + /// Determine whether the address is site local. + bool is_site_local() const + { + using namespace boost::asio::detail; + return IN6_IS_ADDR_SITELOCAL(&addr_) != 0; + } + + /// Determine whether the address is a mapped IPv4 address. + bool is_v4_mapped() const + { + using namespace boost::asio::detail; + return IN6_IS_ADDR_V4MAPPED(&addr_) != 0; + } + + /// Determine whether the address is an IPv4-compatible address. + bool is_v4_compatible() const + { + using namespace boost::asio::detail; + return IN6_IS_ADDR_V4COMPAT(&addr_) != 0; + } + + /// Determine whether the address is a multicast address. + bool is_multicast() const + { + using namespace boost::asio::detail; + return IN6_IS_ADDR_MULTICAST(&addr_) != 0; + } + + /// Determine whether the address is a global multicast address. + bool is_multicast_global() const + { + using namespace boost::asio::detail; + return IN6_IS_ADDR_MC_GLOBAL(&addr_) != 0; + } + + /// Determine whether the address is a link-local multicast address. + bool is_multicast_link_local() const + { + using namespace boost::asio::detail; + return IN6_IS_ADDR_MC_LINKLOCAL(&addr_) != 0; + } + + /// Determine whether the address is a node-local multicast address. + bool is_multicast_node_local() const + { + using namespace boost::asio::detail; + return IN6_IS_ADDR_MC_NODELOCAL(&addr_) != 0; + } + + /// Determine whether the address is a org-local multicast address. + bool is_multicast_org_local() const + { + using namespace boost::asio::detail; + return IN6_IS_ADDR_MC_ORGLOCAL(&addr_) != 0; + } + + /// Determine whether the address is a site-local multicast address. + bool is_multicast_site_local() const + { + using namespace boost::asio::detail; + return IN6_IS_ADDR_MC_SITELOCAL(&addr_) != 0; + } + + /// Compare two addresses for equality. + friend bool operator==(const address_v6& a1, const address_v6& a2) + { + using namespace std; // For memcmp. + return memcmp(&a1.addr_, &a2.addr_, + sizeof(boost::asio::detail::in6_addr_type)) == 0 + && a1.scope_id_ == a2.scope_id_; + } + + /// Compare two addresses for inequality. + friend bool operator!=(const address_v6& a1, const address_v6& a2) + { + using namespace std; // For memcmp. + return memcmp(&a1.addr_, &a2.addr_, + sizeof(boost::asio::detail::in6_addr_type)) != 0 + || a1.scope_id_ != a2.scope_id_; + } + + /// Compare addresses for ordering. + friend bool operator<(const address_v6& a1, const address_v6& a2) + { + using namespace std; // For memcmp. + int memcmp_result = memcmp(&a1.addr_, &a2.addr_, + sizeof(boost::asio::detail::in6_addr_type)); + if (memcmp_result < 0) + return true; + if (memcmp_result > 0) + return false; + return a1.scope_id_ < a2.scope_id_; + } + + /// Compare addresses for ordering. + friend bool operator>(const address_v6& a1, const address_v6& a2) + { + return a2 < a1; + } + + /// Compare addresses for ordering. + friend bool operator<=(const address_v6& a1, const address_v6& a2) + { + return !(a2 < a1); + } + + /// Compare addresses for ordering. + friend bool operator>=(const address_v6& a1, const address_v6& a2) + { + return !(a1 < a2); + } + + /// Obtain an address object that represents any address. + static address_v6 any() + { + return address_v6(); + } + + /// Obtain an address object that represents the loopback address. + static address_v6 loopback() + { + address_v6 tmp; + boost::asio::detail::in6_addr_type tmp_addr = IN6ADDR_LOOPBACK_INIT; + tmp.addr_ = tmp_addr; + return tmp; + } + + /// Create an IPv4-mapped IPv6 address. + static address_v6 v4_mapped(const address_v4& addr) + { + address_v4::bytes_type v4_bytes = addr.to_bytes(); + bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, + v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } }; + return address_v6(v6_bytes); + } + + /// Create an IPv4-compatible IPv6 address. + static address_v6 v4_compatible(const address_v4& addr) + { + address_v4::bytes_type v4_bytes = addr.to_bytes(); + bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } }; + return address_v6(v6_bytes); + } + +private: + // The underlying IPv6 address. + boost::asio::detail::in6_addr_type addr_; + + // The scope ID associated with the address. + unsigned long scope_id_; +}; + +/// Output an address as a string. +/** + * Used to output a human-readable string for a specified address. + * + * @param os The output stream to which the string will be written. + * + * @param addr The address to be written. + * + * @return The output stream. + * + * @relates boost::asio::ip::address_v6 + */ +template +std::basic_ostream& operator<<( + std::basic_ostream& os, const address_v6& addr) +{ + boost::system::error_code ec; + std::string s = addr.to_string(ec); + if (ec) + { + if (os.exceptions() & std::ios::failbit) + boost::asio::detail::throw_error(ec); + else + os.setstate(std::ios_base::failbit); + } + else + for (std::string::iterator i = s.begin(); i != s.end(); ++i) + os << os.widen(*i); + return os; +} + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_ADDRESS_V6_HPP diff --git a/win32/include/boost/asio/ip/basic_endpoint.hpp b/win32/include/boost/asio/ip/basic_endpoint.hpp new file mode 100755 index 000000000..543d4f35e --- /dev/null +++ b/win32/include/boost/asio/ip/basic_endpoint.hpp @@ -0,0 +1,370 @@ +// +// basic_endpoint.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_BASIC_ENDPOINT_HPP +#define BOOST_ASIO_IP_BASIC_ENDPOINT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +# include +#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ip { + +/// Describes an endpoint for a version-independent IP socket. +/** + * The boost::asio::ip::basic_endpoint class template describes an endpoint that + * may be associated with a particular socket. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * Endpoint. + */ +template +class basic_endpoint +{ +public: + /// The protocol type associated with the endpoint. + typedef InternetProtocol protocol_type; + + /// The type of the endpoint structure. This type is dependent on the + /// underlying implementation of the socket layer. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined data_type; +#else + typedef boost::asio::detail::socket_addr_type data_type; +#endif + + /// Default constructor. + basic_endpoint() + : data_() + { + data_.v4.sin_family = AF_INET; + data_.v4.sin_port = 0; + data_.v4.sin_addr.s_addr = INADDR_ANY; + } + + /// Construct an endpoint using a port number, specified in the host's byte + /// order. The IP address will be the any address (i.e. INADDR_ANY or + /// in6addr_any). This constructor would typically be used for accepting new + /// connections. + /** + * @par Examples + * To initialise an IPv4 TCP endpoint for port 1234, use: + * @code + * boost::asio::ip::tcp::endpoint ep(boost::asio::ip::tcp::v4(), 1234); + * @endcode + * + * To specify an IPv6 UDP endpoint for port 9876, use: + * @code + * boost::asio::ip::udp::endpoint ep(boost::asio::ip::udp::v6(), 9876); + * @endcode + */ + basic_endpoint(const InternetProtocol& protocol, unsigned short port_num) + : data_() + { + using namespace std; // For memcpy. + if (protocol.family() == PF_INET) + { + data_.v4.sin_family = AF_INET; + data_.v4.sin_port = + boost::asio::detail::socket_ops::host_to_network_short(port_num); + data_.v4.sin_addr.s_addr = INADDR_ANY; + } + else + { + data_.v6.sin6_family = AF_INET6; + data_.v6.sin6_port = + boost::asio::detail::socket_ops::host_to_network_short(port_num); + data_.v6.sin6_flowinfo = 0; + boost::asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; + data_.v6.sin6_addr = tmp_addr; + data_.v6.sin6_scope_id = 0; + } + } + + /// Construct an endpoint using a port number and an IP address. This + /// constructor may be used for accepting connections on a specific interface + /// or for making a connection to a remote endpoint. + basic_endpoint(const boost::asio::ip::address& addr, unsigned short port_num) + : data_() + { + using namespace std; // For memcpy. + if (addr.is_v4()) + { + data_.v4.sin_family = AF_INET; + data_.v4.sin_port = + boost::asio::detail::socket_ops::host_to_network_short(port_num); + data_.v4.sin_addr.s_addr = + boost::asio::detail::socket_ops::host_to_network_long( + addr.to_v4().to_ulong()); + } + else + { + data_.v6.sin6_family = AF_INET6; + data_.v6.sin6_port = + boost::asio::detail::socket_ops::host_to_network_short(port_num); + data_.v6.sin6_flowinfo = 0; + boost::asio::ip::address_v6 v6_addr = addr.to_v6(); + boost::asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes(); + memcpy(data_.v6.sin6_addr.s6_addr, bytes.elems, 16); + data_.v6.sin6_scope_id = v6_addr.scope_id(); + } + } + + /// Copy constructor. + basic_endpoint(const basic_endpoint& other) + : data_(other.data_) + { + } + + /// Assign from another endpoint. + basic_endpoint& operator=(const basic_endpoint& other) + { + data_ = other.data_; + return *this; + } + + /// The protocol associated with the endpoint. + protocol_type protocol() const + { + if (is_v4()) + return InternetProtocol::v4(); + return InternetProtocol::v6(); + } + + /// Get the underlying endpoint in the native type. + data_type* data() + { + return &data_.base; + } + + /// Get the underlying endpoint in the native type. + const data_type* data() const + { + return &data_.base; + } + + /// Get the underlying size of the endpoint in the native type. + std::size_t size() const + { + if (is_v4()) + return sizeof(boost::asio::detail::sockaddr_in4_type); + else + return sizeof(boost::asio::detail::sockaddr_in6_type); + } + + /// Set the underlying size of the endpoint in the native type. + void resize(std::size_t size) + { + if (size > sizeof(boost::asio::detail::sockaddr_storage_type)) + { + boost::system::system_error e(boost::asio::error::invalid_argument); + boost::throw_exception(e); + } + } + + /// Get the capacity of the endpoint in the native type. + std::size_t capacity() const + { + return sizeof(boost::asio::detail::sockaddr_storage_type); + } + + /// Get the port associated with the endpoint. The port number is always in + /// the host's byte order. + unsigned short port() const + { + if (is_v4()) + { + return boost::asio::detail::socket_ops::network_to_host_short( + data_.v4.sin_port); + } + else + { + return boost::asio::detail::socket_ops::network_to_host_short( + data_.v6.sin6_port); + } + } + + /// Set the port associated with the endpoint. The port number is always in + /// the host's byte order. + void port(unsigned short port_num) + { + if (is_v4()) + { + data_.v4.sin_port + = boost::asio::detail::socket_ops::host_to_network_short(port_num); + } + else + { + data_.v6.sin6_port + = boost::asio::detail::socket_ops::host_to_network_short(port_num); + } + } + + /// Get the IP address associated with the endpoint. + boost::asio::ip::address address() const + { + using namespace std; // For memcpy. + if (is_v4()) + { + return boost::asio::ip::address_v4( + boost::asio::detail::socket_ops::network_to_host_long( + data_.v4.sin_addr.s_addr)); + } + else + { + boost::asio::ip::address_v6::bytes_type bytes; + memcpy(bytes.elems, data_.v6.sin6_addr.s6_addr, 16); + return boost::asio::ip::address_v6(bytes, data_.v6.sin6_scope_id); + } + } + + /// Set the IP address associated with the endpoint. + void address(const boost::asio::ip::address& addr) + { + basic_endpoint tmp_endpoint(addr, port()); + data_ = tmp_endpoint.data_; + } + + /// Compare two endpoints for equality. + friend bool operator==(const basic_endpoint& e1, + const basic_endpoint& e2) + { + return e1.address() == e2.address() && e1.port() == e2.port(); + } + + /// Compare two endpoints for inequality. + friend bool operator!=(const basic_endpoint& e1, + const basic_endpoint& e2) + { + return e1.address() != e2.address() || e1.port() != e2.port(); + } + + /// Compare endpoints for ordering. + friend bool operator<(const basic_endpoint& e1, + const basic_endpoint& e2) + { + if (e1.address() < e2.address()) + return true; + if (e1.address() != e2.address()) + return false; + return e1.port() < e2.port(); + } + +private: + // Helper function to determine whether the endpoint is IPv4. + bool is_v4() const + { + return data_.base.sa_family == AF_INET; + } + + // The underlying IP socket address. + union data_union + { + boost::asio::detail::socket_addr_type base; + boost::asio::detail::sockaddr_storage_type storage; + boost::asio::detail::sockaddr_in4_type v4; + boost::asio::detail::sockaddr_in6_type v6; + } data_; +}; + +/// Output an endpoint as a string. +/** + * Used to output a human-readable string for a specified endpoint. + * + * @param os The output stream to which the string will be written. + * + * @param endpoint The endpoint to be written. + * + * @return The output stream. + * + * @relates boost::asio::ip::basic_endpoint + */ +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +template +std::ostream& operator<<(std::ostream& os, + const basic_endpoint& endpoint) +{ + const address& addr = endpoint.address(); + boost::system::error_code ec; + std::string a = addr.to_string(ec); + if (ec) + { + if (os.exceptions() & std::ios::failbit) + boost::asio::detail::throw_error(ec); + else + os.setstate(std::ios_base::failbit); + } + else + { + if (addr.is_v4()) + os << a; + else + os << '[' << a << ']'; + os << ':' << endpoint.port(); + } + return os; +} +#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +template +std::basic_ostream& operator<<( + std::basic_ostream& os, + const basic_endpoint& endpoint) +{ + const address& addr = endpoint.address(); + boost::system::error_code ec; + std::string a = addr.to_string(ec); + if (ec) + { + if (os.exceptions() & std::ios::failbit) + boost::asio::detail::throw_error(ec); + else + os.setstate(std::ios_base::failbit); + } + else + { + if (addr.is_v4()) + os << a; + else + os << '[' << a << ']'; + os << ':' << endpoint.port(); + } + return os; +} +#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_BASIC_ENDPOINT_HPP diff --git a/win32/include/boost/asio/ip/basic_resolver.hpp b/win32/include/boost/asio/ip/basic_resolver.hpp new file mode 100755 index 000000000..cdd885d31 --- /dev/null +++ b/win32/include/boost/asio/ip/basic_resolver.hpp @@ -0,0 +1,247 @@ +// +// basic_resolver.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_BASIC_RESOLVER_HPP +#define BOOST_ASIO_IP_BASIC_RESOLVER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ip { + +/// Provides endpoint resolution functionality. +/** + * The basic_resolver class template provides the ability to resolve a query + * to a list of endpoints. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template > +class basic_resolver + : public basic_io_object +{ +public: + /// The protocol type. + typedef InternetProtocol protocol_type; + + /// The endpoint type. + typedef typename InternetProtocol::endpoint endpoint_type; + + /// The query type. + typedef typename InternetProtocol::resolver_query query; + + /// The iterator type. + typedef typename InternetProtocol::resolver_iterator iterator; + + /// Constructor. + /** + * This constructor creates a basic_resolver. + * + * @param io_service The io_service object that the resolver will use to + * dispatch handlers for any asynchronous operations performed on the timer. + */ + explicit basic_resolver(boost::asio::io_service& io_service) + : basic_io_object(io_service) + { + } + + /// Cancel any asynchronous operations that are waiting on the resolver. + /** + * This function forces the completion of any pending asynchronous + * operations on the host resolver. The handler for each cancelled operation + * will be invoked with the boost::asio::error::operation_aborted error code. + */ + void cancel() + { + return this->service.cancel(this->implementation); + } + + /// Resolve a query to a list of entries. + /** + * This function is used to resolve a query into a list of endpoint entries. + * + * @param q A query object that determines what endpoints will be returned. + * + * @returns A forward-only iterator that can be used to traverse the list + * of endpoint entries. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note A default constructed iterator represents the end of the list. + * + * A successful call to this function is guaranteed to return at least one + * entry. + */ + iterator resolve(const query& q) + { + boost::system::error_code ec; + iterator i = this->service.resolve(this->implementation, q, ec); + boost::asio::detail::throw_error(ec); + return i; + } + + /// Resolve a query to a list of entries. + /** + * This function is used to resolve a query into a list of endpoint entries. + * + * @param q A query object that determines what endpoints will be returned. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns A forward-only iterator that can be used to traverse the list + * of endpoint entries. Returns a default constructed iterator if an error + * occurs. + * + * @note A default constructed iterator represents the end of the list. + * + * A successful call to this function is guaranteed to return at least one + * entry. + */ + iterator resolve(const query& q, boost::system::error_code& ec) + { + return this->service.resolve(this->implementation, q, ec); + } + + /// Asynchronously resolve a query to a list of entries. + /** + * This function is used to asynchronously resolve a query into a list of + * endpoint entries. + * + * @param q A query object that determines what endpoints will be returned. + * + * @param handler The handler to be called when the resolve operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * resolver::iterator iterator // Forward-only iterator that can + * // be used to traverse the list + * // of endpoint entries. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note A default constructed iterator represents the end of the list. + * + * A successful resolve operation is guaranteed to pass at least one entry to + * the handler. + */ + template + void async_resolve(const query& q, ResolveHandler handler) + { + return this->service.async_resolve(this->implementation, q, handler); + } + + /// Resolve an endpoint to a list of entries. + /** + * This function is used to resolve an endpoint into a list of endpoint + * entries. + * + * @param e An endpoint object that determines what endpoints will be + * returned. + * + * @returns A forward-only iterator that can be used to traverse the list + * of endpoint entries. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note A default constructed iterator represents the end of the list. + * + * A successful call to this function is guaranteed to return at least one + * entry. + */ + iterator resolve(const endpoint_type& e) + { + boost::system::error_code ec; + iterator i = this->service.resolve(this->implementation, e, ec); + boost::asio::detail::throw_error(ec); + return i; + } + + /// Resolve an endpoint to a list of entries. + /** + * This function is used to resolve an endpoint into a list of endpoint + * entries. + * + * @param e An endpoint object that determines what endpoints will be + * returned. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns A forward-only iterator that can be used to traverse the list + * of endpoint entries. Returns a default constructed iterator if an error + * occurs. + * + * @note A default constructed iterator represents the end of the list. + * + * A successful call to this function is guaranteed to return at least one + * entry. + */ + iterator resolve(const endpoint_type& e, boost::system::error_code& ec) + { + return this->service.resolve(this->implementation, e, ec); + } + + /// Asynchronously resolve an endpoint to a list of entries. + /** + * This function is used to asynchronously resolve an endpoint into a list of + * endpoint entries. + * + * @param e An endpoint object that determines what endpoints will be + * returned. + * + * @param handler The handler to be called when the resolve operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * resolver::iterator iterator // Forward-only iterator that can + * // be used to traverse the list + * // of endpoint entries. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note A default constructed iterator represents the end of the list. + * + * A successful resolve operation is guaranteed to pass at least one entry to + * the handler. + */ + template + void async_resolve(const endpoint_type& e, ResolveHandler handler) + { + return this->service.async_resolve(this->implementation, e, handler); + } +}; + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_BASIC_RESOLVER_HPP diff --git a/win32/include/boost/asio/ip/basic_resolver_entry.hpp b/win32/include/boost/asio/ip/basic_resolver_entry.hpp new file mode 100755 index 000000000..4bb41ae86 --- /dev/null +++ b/win32/include/boost/asio/ip/basic_resolver_entry.hpp @@ -0,0 +1,97 @@ +// +// basic_resolver_entry.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_BASIC_RESOLVER_ENTRY_HPP +#define BOOST_ASIO_IP_BASIC_RESOLVER_ENTRY_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +namespace boost { +namespace asio { +namespace ip { + +/// An entry produced by a resolver. +/** + * The boost::asio::ip::basic_resolver_entry class template describes an entry + * as returned by a resolver. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_resolver_entry +{ +public: + /// The protocol type associated with the endpoint entry. + typedef InternetProtocol protocol_type; + + /// The endpoint type associated with the endpoint entry. + typedef typename InternetProtocol::endpoint endpoint_type; + + /// Default constructor. + basic_resolver_entry() + { + } + + /// Construct with specified endpoint, host name and service name. + basic_resolver_entry(const endpoint_type& endpoint, + const std::string& host_name, const std::string& service_name) + : endpoint_(endpoint), + host_name_(host_name), + service_name_(service_name) + { + } + + /// Get the endpoint associated with the entry. + endpoint_type endpoint() const + { + return endpoint_; + } + + /// Convert to the endpoint associated with the entry. + operator endpoint_type() const + { + return endpoint_; + } + + /// Get the host name associated with the entry. + std::string host_name() const + { + return host_name_; + } + + /// Get the service name associated with the entry. + std::string service_name() const + { + return service_name_; + } + +private: + endpoint_type endpoint_; + std::string host_name_; + std::string service_name_; +}; + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_BASIC_RESOLVER_ENTRY_HPP diff --git a/win32/include/boost/asio/ip/basic_resolver_iterator.hpp b/win32/include/boost/asio/ip/basic_resolver_iterator.hpp new file mode 100755 index 000000000..fdaf273b8 --- /dev/null +++ b/win32/include/boost/asio/ip/basic_resolver_iterator.hpp @@ -0,0 +1,156 @@ +// +// basic_resolver_iterator.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP +#define BOOST_ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { +namespace asio { +namespace ip { + +/// An iterator over the entries produced by a resolver. +/** + * The boost::asio::ip::basic_resolver_iterator class template is used to define + * iterators over the results returned by a resolver. + * + * The iterator's value_type, obtained when the iterator is dereferenced, is: + * @code const basic_resolver_entry @endcode + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_resolver_iterator + : public boost::iterator_facade< + basic_resolver_iterator, + const basic_resolver_entry, + boost::forward_traversal_tag> +{ +public: + /// Default constructor creates an end iterator. + basic_resolver_iterator() + { + } + + /// Create an iterator from an addrinfo list returned by getaddrinfo. + static basic_resolver_iterator create( + boost::asio::detail::addrinfo_type* address_info, + const std::string& host_name, const std::string& service_name) + { + basic_resolver_iterator iter; + if (!address_info) + return iter; + + std::string actual_host_name = host_name; + if (address_info->ai_canonname) + actual_host_name = address_info->ai_canonname; + + iter.values_.reset(new values_type); + + while (address_info) + { + if (address_info->ai_family == PF_INET + || address_info->ai_family == PF_INET6) + { + using namespace std; // For memcpy. + typename InternetProtocol::endpoint endpoint; + endpoint.resize(static_cast(address_info->ai_addrlen)); + memcpy(endpoint.data(), address_info->ai_addr, + address_info->ai_addrlen); + iter.values_->push_back( + basic_resolver_entry(endpoint, + actual_host_name, service_name)); + } + address_info = address_info->ai_next; + } + + if (iter.values_->size()) + iter.iter_ = iter.values_->begin(); + else + iter.values_.reset(); + + return iter; + } + + /// Create an iterator from an endpoint, host name and service name. + static basic_resolver_iterator create( + const typename InternetProtocol::endpoint& endpoint, + const std::string& host_name, const std::string& service_name) + { + basic_resolver_iterator iter; + iter.values_.reset(new values_type); + iter.values_->push_back( + basic_resolver_entry( + endpoint, host_name, service_name)); + iter.iter_ = iter.values_->begin(); + return iter; + } + +private: + friend class boost::iterator_core_access; + + void increment() + { + if (++*iter_ == values_->end()) + { + // Reset state to match a default constructed end iterator. + values_.reset(); + typedef typename values_type::const_iterator values_iterator_type; + iter_.reset(); + } + } + + bool equal(const basic_resolver_iterator& other) const + { + if (!values_ && !other.values_) + return true; + if (values_ != other.values_) + return false; + return *iter_ == *other.iter_; + } + + const basic_resolver_entry& dereference() const + { + return **iter_; + } + + typedef std::vector > values_type; + typedef typename values_type::const_iterator values_iter_type; + boost::shared_ptr values_; + boost::optional iter_; +}; + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP diff --git a/win32/include/boost/asio/ip/basic_resolver_query.hpp b/win32/include/boost/asio/ip/basic_resolver_query.hpp new file mode 100755 index 000000000..9be32c48f --- /dev/null +++ b/win32/include/boost/asio/ip/basic_resolver_query.hpp @@ -0,0 +1,151 @@ +// +// basic_resolver_query.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_BASIC_RESOLVER_QUERY_HPP +#define BOOST_ASIO_IP_BASIC_RESOLVER_QUERY_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { +namespace ip { + +/// An query to be passed to a resolver. +/** + * The boost::asio::ip::basic_resolver_query class template describes a query + * that can be passed to a resolver. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_resolver_query + : public resolver_query_base +{ +public: + /// The protocol type associated with the endpoint query. + typedef InternetProtocol protocol_type; + + /// Construct with specified service name for any protocol. + basic_resolver_query(const std::string& service_name, + int flags = passive | address_configured) + : hints_(), + host_name_(), + service_name_(service_name) + { + typename InternetProtocol::endpoint endpoint; + hints_.ai_flags = flags; + hints_.ai_family = PF_UNSPEC; + hints_.ai_socktype = endpoint.protocol().type(); + hints_.ai_protocol = endpoint.protocol().protocol(); + hints_.ai_addrlen = 0; + hints_.ai_canonname = 0; + hints_.ai_addr = 0; + hints_.ai_next = 0; + } + + /// Construct with specified service name for a given protocol. + basic_resolver_query(const protocol_type& protocol, + const std::string& service_name, + int flags = passive | address_configured) + : hints_(), + host_name_(), + service_name_(service_name) + { + hints_.ai_flags = flags; + hints_.ai_family = protocol.family(); + hints_.ai_socktype = protocol.type(); + hints_.ai_protocol = protocol.protocol(); + hints_.ai_addrlen = 0; + hints_.ai_canonname = 0; + hints_.ai_addr = 0; + hints_.ai_next = 0; + } + + /// Construct with specified host name and service name for any protocol. + basic_resolver_query(const std::string& host_name, + const std::string& service_name, int flags = address_configured) + : hints_(), + host_name_(host_name), + service_name_(service_name) + { + typename InternetProtocol::endpoint endpoint; + hints_.ai_flags = flags; + hints_.ai_family = PF_UNSPEC; + hints_.ai_socktype = endpoint.protocol().type(); + hints_.ai_protocol = endpoint.protocol().protocol(); + hints_.ai_addrlen = 0; + hints_.ai_canonname = 0; + hints_.ai_addr = 0; + hints_.ai_next = 0; + } + + /// Construct with specified host name and service name for a given protocol. + basic_resolver_query(const protocol_type& protocol, + const std::string& host_name, const std::string& service_name, + int flags = address_configured) + : hints_(), + host_name_(host_name), + service_name_(service_name) + { + hints_.ai_flags = flags; + hints_.ai_family = protocol.family(); + hints_.ai_socktype = protocol.type(); + hints_.ai_protocol = protocol.protocol(); + hints_.ai_addrlen = 0; + hints_.ai_canonname = 0; + hints_.ai_addr = 0; + hints_.ai_next = 0; + } + + /// Get the hints associated with the query. + const boost::asio::detail::addrinfo_type& hints() const + { + return hints_; + } + + /// Get the host name associated with the query. + std::string host_name() const + { + return host_name_; + } + + /// Get the service name associated with the query. + std::string service_name() const + { + return service_name_; + } + +private: + boost::asio::detail::addrinfo_type hints_; + std::string host_name_; + std::string service_name_; +}; + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_BASIC_RESOLVER_QUERY_HPP diff --git a/win32/include/boost/asio/ip/detail/socket_option.hpp b/win32/include/boost/asio/ip/detail/socket_option.hpp new file mode 100755 index 000000000..f35ff8d69 --- /dev/null +++ b/win32/include/boost/asio/ip/detail/socket_option.hpp @@ -0,0 +1,580 @@ +// +// socket_option.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_DETAIL_SOCKET_OPTION_HPP +#define BOOST_ASIO_IP_DETAIL_SOCKET_OPTION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { +namespace asio { +namespace ip { +namespace detail { +namespace socket_option { + +// Helper template for implementing multicast enable loopback options. +template +class multicast_enable_loopback +{ +public: +#if defined(__sun) || defined(__osf__) + typedef unsigned char ipv4_value_type; + typedef unsigned char ipv6_value_type; +#elif defined(_AIX) || defined(__hpux) + typedef unsigned char ipv4_value_type; + typedef unsigned int ipv6_value_type; +#else + typedef int ipv4_value_type; + typedef int ipv6_value_type; +#endif + + // Default constructor. + multicast_enable_loopback() + : ipv4_value_(0), + ipv6_value_(0) + { + } + + // Construct with a specific option value. + explicit multicast_enable_loopback(bool v) + : ipv4_value_(v ? 1 : 0), + ipv6_value_(v ? 1 : 0) + { + } + + // Set the value of the boolean. + multicast_enable_loopback& operator=(bool v) + { + ipv4_value_ = v ? 1 : 0; + ipv6_value_ = v ? 1 : 0; + return *this; + } + + // Get the current value of the boolean. + bool value() const + { + return !!ipv4_value_; + } + + // Convert to bool. + operator bool() const + { + return !!ipv4_value_; + } + + // Test for false. + bool operator!() const + { + return !ipv4_value_; + } + + // Get the level of the socket option. + template + int level(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return IPv6_Level; + return IPv4_Level; + } + + // Get the name of the socket option. + template + int name(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return IPv6_Name; + return IPv4_Name; + } + + // Get the address of the boolean data. + template + void* data(const Protocol& protocol) + { + if (protocol.family() == PF_INET6) + return &ipv6_value_; + return &ipv4_value_; + } + + // Get the address of the boolean data. + template + const void* data(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return &ipv6_value_; + return &ipv4_value_; + } + + // Get the size of the boolean data. + template + std::size_t size(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return sizeof(ipv6_value_); + return sizeof(ipv4_value_); + } + + // Set the size of the boolean data. + template + void resize(const Protocol& protocol, std::size_t s) + { + if (protocol.family() == PF_INET6) + { + if (s != sizeof(ipv6_value_)) + { + throw std::length_error( + "multicast_enable_loopback socket option resize"); + } + ipv4_value_ = ipv6_value_ ? 1 : 0; + } + else + { + if (s != sizeof(ipv4_value_)) + { + throw std::length_error( + "multicast_enable_loopback socket option resize"); + } + ipv6_value_ = ipv4_value_ ? 1 : 0; + } + } + +private: + ipv4_value_type ipv4_value_; + ipv6_value_type ipv6_value_; +}; + +// Helper template for implementing unicast hops options. +template +class unicast_hops +{ +public: + // Default constructor. + unicast_hops() + : value_(0) + { + } + + // Construct with a specific option value. + explicit unicast_hops(int v) + : value_(v) + { + } + + // Set the value of the option. + unicast_hops& operator=(int v) + { + value_ = v; + return *this; + } + + // Get the current value of the option. + int value() const + { + return value_; + } + + // Get the level of the socket option. + template + int level(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return IPv6_Level; + return IPv4_Level; + } + + // Get the name of the socket option. + template + int name(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return IPv6_Name; + return IPv4_Name; + } + + // Get the address of the data. + template + int* data(const Protocol&) + { + return &value_; + } + + // Get the address of the data. + template + const int* data(const Protocol&) const + { + return &value_; + } + + // Get the size of the data. + template + std::size_t size(const Protocol&) const + { + return sizeof(value_); + } + + // Set the size of the data. + template + void resize(const Protocol&, std::size_t s) + { + if (s != sizeof(value_)) + throw std::length_error("unicast hops socket option resize"); +#if defined(__hpux) + if (value_ < 0) + value_ = value_ & 0xFF; +#endif + } + +private: + int value_; +}; + +// Helper template for implementing multicast hops options. +template +class multicast_hops +{ +public: +#if defined(BOOST_WINDOWS) && defined(UNDER_CE) + typedef int ipv4_value_type; +#else + typedef unsigned char ipv4_value_type; +#endif + typedef int ipv6_value_type; + + // Default constructor. + multicast_hops() + : ipv4_value_(0), + ipv6_value_(0) + { + } + + // Construct with a specific option value. + explicit multicast_hops(int v) + { + if (v < 0 || v > 255) + throw std::out_of_range("multicast hops value out of range"); + ipv4_value_ = (ipv4_value_type)v; + ipv6_value_ = v; + } + + // Set the value of the option. + multicast_hops& operator=(int v) + { + if (v < 0 || v > 255) + throw std::out_of_range("multicast hops value out of range"); + ipv4_value_ = (ipv4_value_type)v; + ipv6_value_ = v; + return *this; + } + + // Get the current value of the option. + int value() const + { + return ipv6_value_; + } + + // Get the level of the socket option. + template + int level(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return IPv6_Level; + return IPv4_Level; + } + + // Get the name of the socket option. + template + int name(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return IPv6_Name; + return IPv4_Name; + } + + // Get the address of the data. + template + void* data(const Protocol& protocol) + { + if (protocol.family() == PF_INET6) + return &ipv6_value_; + return &ipv4_value_; + } + + // Get the address of the data. + template + const void* data(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return &ipv6_value_; + return &ipv4_value_; + } + + // Get the size of the data. + template + std::size_t size(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return sizeof(ipv6_value_); + return sizeof(ipv4_value_); + } + + // Set the size of the data. + template + void resize(const Protocol& protocol, std::size_t s) + { + if (protocol.family() == PF_INET6) + { + if (s != sizeof(ipv6_value_)) + throw std::length_error("multicast hops socket option resize"); + if (ipv6_value_ < 0) + ipv4_value_ = 0; + else if (ipv6_value_ > 255) + ipv4_value_ = 255; + else + ipv4_value_ = (ipv4_value_type)ipv6_value_; + } + else + { + if (s != sizeof(ipv4_value_)) + throw std::length_error("multicast hops socket option resize"); + ipv6_value_ = ipv4_value_; + } + } + +private: + ipv4_value_type ipv4_value_; + ipv6_value_type ipv6_value_; +}; + +// Helper template for implementing ip_mreq-based options. +template +class multicast_request +{ +public: + // Default constructor. + multicast_request() + { + ipv4_value_.imr_multiaddr.s_addr = + boost::asio::detail::socket_ops::host_to_network_long( + boost::asio::ip::address_v4::any().to_ulong()); + ipv4_value_.imr_interface.s_addr = + boost::asio::detail::socket_ops::host_to_network_long( + boost::asio::ip::address_v4::any().to_ulong()); + + boost::asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; + ipv6_value_.ipv6mr_multiaddr = tmp_addr; + ipv6_value_.ipv6mr_interface = 0; + } + + // Construct with multicast address only. + explicit multicast_request(const boost::asio::ip::address& multicast_address) + { + if (multicast_address.is_v6()) + { + ipv4_value_.imr_multiaddr.s_addr = + boost::asio::detail::socket_ops::host_to_network_long( + boost::asio::ip::address_v4::any().to_ulong()); + ipv4_value_.imr_interface.s_addr = + boost::asio::detail::socket_ops::host_to_network_long( + boost::asio::ip::address_v4::any().to_ulong()); + + using namespace std; // For memcpy. + boost::asio::ip::address_v6 ipv6_address = multicast_address.to_v6(); + boost::asio::ip::address_v6::bytes_type bytes = ipv6_address.to_bytes(); + memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.elems, 16); + ipv6_value_.ipv6mr_interface = 0; + } + else + { + ipv4_value_.imr_multiaddr.s_addr = + boost::asio::detail::socket_ops::host_to_network_long( + multicast_address.to_v4().to_ulong()); + ipv4_value_.imr_interface.s_addr = + boost::asio::detail::socket_ops::host_to_network_long( + boost::asio::ip::address_v4::any().to_ulong()); + + boost::asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; + ipv6_value_.ipv6mr_multiaddr = tmp_addr; + ipv6_value_.ipv6mr_interface = 0; + } + } + + // Construct with multicast address and IPv4 address specifying an interface. + explicit multicast_request( + const boost::asio::ip::address_v4& multicast_address, + const boost::asio::ip::address_v4& network_interface + = boost::asio::ip::address_v4::any()) + { + ipv4_value_.imr_multiaddr.s_addr = + boost::asio::detail::socket_ops::host_to_network_long( + multicast_address.to_ulong()); + ipv4_value_.imr_interface.s_addr = + boost::asio::detail::socket_ops::host_to_network_long( + network_interface.to_ulong()); + + boost::asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; + ipv6_value_.ipv6mr_multiaddr = tmp_addr; + ipv6_value_.ipv6mr_interface = 0; + } + + // Construct with multicast address and IPv6 network interface index. + explicit multicast_request( + const boost::asio::ip::address_v6& multicast_address, + unsigned long network_interface = 0) + { + ipv4_value_.imr_multiaddr.s_addr = + boost::asio::detail::socket_ops::host_to_network_long( + boost::asio::ip::address_v4::any().to_ulong()); + ipv4_value_.imr_interface.s_addr = + boost::asio::detail::socket_ops::host_to_network_long( + boost::asio::ip::address_v4::any().to_ulong()); + + using namespace std; // For memcpy. + boost::asio::ip::address_v6::bytes_type bytes = + multicast_address.to_bytes(); + memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.elems, 16); + ipv6_value_.ipv6mr_interface = network_interface; + } + + // Get the level of the socket option. + template + int level(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return IPv6_Level; + return IPv4_Level; + } + + // Get the name of the socket option. + template + int name(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return IPv6_Name; + return IPv4_Name; + } + + // Get the address of the option data. + template + const void* data(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return &ipv6_value_; + return &ipv4_value_; + } + + // Get the size of the option data. + template + std::size_t size(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return sizeof(ipv6_value_); + return sizeof(ipv4_value_); + } + +private: + boost::asio::detail::in4_mreq_type ipv4_value_; + boost::asio::detail::in6_mreq_type ipv6_value_; +}; + +// Helper template for implementing options that specify a network interface. +template +class network_interface +{ +public: + // Default constructor. + network_interface() + { + ipv4_value_.s_addr = + boost::asio::detail::socket_ops::host_to_network_long( + boost::asio::ip::address_v4::any().to_ulong()); + ipv6_value_ = 0; + } + + // Construct with IPv4 interface. + explicit network_interface(const boost::asio::ip::address_v4& ipv4_interface) + { + ipv4_value_.s_addr = + boost::asio::detail::socket_ops::host_to_network_long( + ipv4_interface.to_ulong()); + ipv6_value_ = 0; + } + + // Construct with IPv6 interface. + explicit network_interface(unsigned int ipv6_interface) + { + ipv4_value_.s_addr = + boost::asio::detail::socket_ops::host_to_network_long( + boost::asio::ip::address_v4::any().to_ulong()); + ipv6_value_ = ipv6_interface; + } + + // Get the level of the socket option. + template + int level(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return IPv6_Level; + return IPv4_Level; + } + + // Get the name of the socket option. + template + int name(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return IPv6_Name; + return IPv4_Name; + } + + // Get the address of the option data. + template + const void* data(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return &ipv6_value_; + return &ipv4_value_; + } + + // Get the size of the option data. + template + std::size_t size(const Protocol& protocol) const + { + if (protocol.family() == PF_INET6) + return sizeof(ipv6_value_); + return sizeof(ipv4_value_); + } + +private: + boost::asio::detail::in4_addr_type ipv4_value_; + unsigned int ipv6_value_; +}; + +} // namespace socket_option +} // namespace detail +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_DETAIL_SOCKET_OPTION_HPP diff --git a/win32/include/boost/asio/ip/host_name.hpp b/win32/include/boost/asio/ip/host_name.hpp new file mode 100755 index 000000000..778e5256e --- /dev/null +++ b/win32/include/boost/asio/ip/host_name.hpp @@ -0,0 +1,64 @@ +// +// host_name.hpp +// ~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_HOST_NAME_HPP +#define BOOST_ASIO_IP_HOST_NAME_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include +#include + +namespace boost { +namespace asio { +namespace ip { + +/// Get the current host name. +std::string host_name(); + +/// Get the current host name. +std::string host_name(boost::system::error_code& ec); + +inline std::string host_name() +{ + char name[1024]; + boost::system::error_code ec; + if (boost::asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0) + { + boost::asio::detail::throw_error(ec); + return std::string(); + } + return std::string(name); +} + +inline std::string host_name(boost::system::error_code& ec) +{ + char name[1024]; + if (boost::asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0) + return std::string(); + return std::string(name); +} + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_HOST_NAME_HPP diff --git a/win32/include/boost/asio/ip/icmp.hpp b/win32/include/boost/asio/ip/icmp.hpp new file mode 100755 index 000000000..c8cd1b0d3 --- /dev/null +++ b/win32/include/boost/asio/ip/icmp.hpp @@ -0,0 +1,120 @@ +// +// icmp.hpp +// ~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_ICMP_HPP +#define BOOST_ASIO_IP_ICMP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ip { + +/// Encapsulates the flags needed for ICMP. +/** + * The boost::asio::ip::icmp class contains flags necessary for ICMP sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol, InternetProtocol. + */ +class icmp +{ +public: + /// The type of a ICMP endpoint. + typedef basic_endpoint endpoint; + + /// The type of a resolver query. + typedef basic_resolver_query resolver_query; + + /// The type of a resolver iterator. + typedef basic_resolver_iterator resolver_iterator; + + /// Construct to represent the IPv4 ICMP protocol. + static icmp v4() + { + return icmp(IPPROTO_ICMP, PF_INET); + } + + /// Construct to represent the IPv6 ICMP protocol. + static icmp v6() + { + return icmp(IPPROTO_ICMPV6, PF_INET6); + } + + /// Obtain an identifier for the type of the protocol. + int type() const + { + return SOCK_RAW; + } + + /// Obtain an identifier for the protocol. + int protocol() const + { + return protocol_; + } + + /// Obtain an identifier for the protocol family. + int family() const + { + return family_; + } + + /// The ICMP socket type. + typedef basic_raw_socket socket; + + /// The ICMP resolver type. + typedef basic_resolver resolver; + + /// Compare two protocols for equality. + friend bool operator==(const icmp& p1, const icmp& p2) + { + return p1.protocol_ == p2.protocol_ && p1.family_ == p2.family_; + } + + /// Compare two protocols for inequality. + friend bool operator!=(const icmp& p1, const icmp& p2) + { + return p1.protocol_ != p2.protocol_ || p1.family_ != p2.family_; + } + +private: + // Construct with a specific family. + explicit icmp(int protocol, int family) + : protocol_(protocol), + family_(family) + { + } + + int protocol_; + int family_; +}; + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_ICMP_HPP diff --git a/win32/include/boost/asio/ip/multicast.hpp b/win32/include/boost/asio/ip/multicast.hpp new file mode 100755 index 000000000..0888d0824 --- /dev/null +++ b/win32/include/boost/asio/ip/multicast.hpp @@ -0,0 +1,183 @@ +// +// multicast.hpp +// ~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_MULTICAST_HPP +#define BOOST_ASIO_IP_MULTICAST_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace ip { +namespace multicast { + +/// Socket option to join a multicast group on a specified interface. +/** + * Implements the IPPROTO_IP/IP_ADD_MEMBERSHIP socket option. + * + * @par Examples + * Setting the option to join a multicast group: + * @code + * boost::asio::ip::udp::socket socket(io_service); + * ... + * boost::asio::ip::address multicast_address = + * boost::asio::ip::address::from_string("225.0.0.1"); + * boost::asio::ip::multicast::join_group option(multicast_address); + * socket.set_option(option); + * @endcode + * + * @par Concepts: + * SettableSocketOption. + */ +#if defined(GENERATING_DOCUMENTATION) +typedef implementation_defined join_group; +#else +typedef boost::asio::ip::detail::socket_option::multicast_request< + IPPROTO_IP, IP_ADD_MEMBERSHIP, IPPROTO_IPV6, IPV6_JOIN_GROUP> join_group; +#endif + +/// Socket option to leave a multicast group on a specified interface. +/** + * Implements the IPPROTO_IP/IP_DROP_MEMBERSHIP socket option. + * + * @par Examples + * Setting the option to leave a multicast group: + * @code + * boost::asio::ip::udp::socket socket(io_service); + * ... + * boost::asio::ip::address multicast_address = + * boost::asio::ip::address::from_string("225.0.0.1"); + * boost::asio::ip::multicast::leave_group option(multicast_address); + * socket.set_option(option); + * @endcode + * + * @par Concepts: + * SettableSocketOption. + */ +#if defined(GENERATING_DOCUMENTATION) +typedef implementation_defined leave_group; +#else +typedef boost::asio::ip::detail::socket_option::multicast_request< + IPPROTO_IP, IP_DROP_MEMBERSHIP, IPPROTO_IPV6, IPV6_LEAVE_GROUP> leave_group; +#endif + +/// Socket option for local interface to use for outgoing multicast packets. +/** + * Implements the IPPROTO_IP/IP_MULTICAST_IF socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::udp::socket socket(io_service); + * ... + * boost::asio::ip::address_v4 local_interface = + * boost::asio::ip::address_v4::from_string("1.2.3.4"); + * boost::asio::ip::multicast::outbound_interface option(local_interface); + * socket.set_option(option); + * @endcode + * + * @par Concepts: + * SettableSocketOption. + */ +#if defined(GENERATING_DOCUMENTATION) +typedef implementation_defined outbound_interface; +#else +typedef boost::asio::ip::detail::socket_option::network_interface< + IPPROTO_IP, IP_MULTICAST_IF, IPPROTO_IPV6, IPV6_MULTICAST_IF> + outbound_interface; +#endif + +/// Socket option for time-to-live associated with outgoing multicast packets. +/** + * Implements the IPPROTO_IP/IP_MULTICAST_TTL socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::udp::socket socket(io_service); + * ... + * boost::asio::ip::multicast::hops option(4); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::udp::socket socket(io_service); + * ... + * boost::asio::ip::multicast::hops option; + * socket.get_option(option); + * int ttl = option.value(); + * @endcode + * + * @par Concepts: + * GettableSocketOption, SettableSocketOption. + */ +#if defined(GENERATING_DOCUMENTATION) +typedef implementation_defined hops; +#else +typedef boost::asio::ip::detail::socket_option::multicast_hops< + IPPROTO_IP, IP_MULTICAST_TTL, IPPROTO_IPV6, IPV6_MULTICAST_HOPS> hops; +#endif + +/// Socket option determining whether outgoing multicast packets will be +/// received on the same socket if it is a member of the multicast group. +/** + * Implements the IPPROTO_IP/IP_MULTICAST_LOOP socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::udp::socket socket(io_service); + * ... + * boost::asio::ip::multicast::enable_loopback option(true); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::udp::socket socket(io_service); + * ... + * boost::asio::ip::multicast::enable_loopback option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * GettableSocketOption, SettableSocketOption. + */ +#if defined(GENERATING_DOCUMENTATION) +typedef implementation_defined enable_loopback; +#else +typedef boost::asio::ip::detail::socket_option::multicast_enable_loopback< + IPPROTO_IP, IP_MULTICAST_LOOP, IPPROTO_IPV6, IPV6_MULTICAST_LOOP> + enable_loopback; +#endif + +} // namespace multicast +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_MULTICAST_HPP diff --git a/win32/include/boost/asio/ip/resolver_query_base.hpp b/win32/include/boost/asio/ip/resolver_query_base.hpp new file mode 100755 index 000000000..26cf6b60f --- /dev/null +++ b/win32/include/boost/asio/ip/resolver_query_base.hpp @@ -0,0 +1,111 @@ +// +// resolver_query_base.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_RESOLVER_QUERY_BASE_HPP +#define BOOST_ASIO_IP_RESOLVER_QUERY_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace ip { + +/// The resolver_query_base class is used as a base for the +/// basic_resolver_query class templates to provide a common place to define +/// the flag constants. +class resolver_query_base +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// Determine the canonical name of the host specified in the query. + static const int canonical_name = implementation_defined; + + /// Indicate that returned endpoint is intended for use as a locally bound + /// socket endpoint. + static const int passive = implementation_defined; + + /// Host name should be treated as a numeric string defining an IPv4 or IPv6 + /// address and no name resolution should be attempted. + static const int numeric_host = implementation_defined; + + /// Service name should be treated as a numeric string defining a port number + /// and no name resolution should be attempted. + static const int numeric_service = implementation_defined; + + /// If the query protocol family is specified as IPv6, return IPv4-mapped + /// IPv6 addresses on finding no IPv6 addresses. + static const int v4_mapped = implementation_defined; + + /// If used with v4_mapped, return all matching IPv6 and IPv4 addresses. + static const int all_matching = implementation_defined; + + /// Only return IPv4 addresses if a non-loopback IPv4 address is configured + /// for the system. Only return IPv6 addresses if a non-loopback IPv6 address + /// is configured for the system. + static const int address_configured = implementation_defined; +#else + BOOST_STATIC_CONSTANT(int, canonical_name = AI_CANONNAME); + BOOST_STATIC_CONSTANT(int, passive = AI_PASSIVE); + BOOST_STATIC_CONSTANT(int, numeric_host = AI_NUMERICHOST); +# if defined(AI_NUMERICSERV) + BOOST_STATIC_CONSTANT(int, numeric_service = AI_NUMERICSERV); +# else + BOOST_STATIC_CONSTANT(int, numeric_service = 0); +# endif + // Note: QNX Neutrino 6.3 defines AI_V4MAPPED, AI_ALL and AI_ADDRCONFIG but + // does not implement them. Therefore they are specifically excluded here. +# if defined(AI_V4MAPPED) && !defined(__QNXNTO__) + BOOST_STATIC_CONSTANT(int, v4_mapped = AI_V4MAPPED); +# else + BOOST_STATIC_CONSTANT(int, v4_mapped = 0); +# endif +# if defined(AI_ALL) && !defined(__QNXNTO__) + BOOST_STATIC_CONSTANT(int, all_matching = AI_ALL); +# else + BOOST_STATIC_CONSTANT(int, all_matching = 0); +# endif +# if defined(AI_ADDRCONFIG) && !defined(__QNXNTO__) + BOOST_STATIC_CONSTANT(int, address_configured = AI_ADDRCONFIG); +# else + BOOST_STATIC_CONSTANT(int, address_configured = 0); +# endif +#endif + +protected: + /// Protected destructor to prevent deletion through this type. + ~resolver_query_base() + { + } + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +private: + // Workaround to enable the empty base optimisation with Borland C++. + char dummy_; +#endif +}; + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_RESOLVER_QUERY_BASE_HPP diff --git a/win32/include/boost/asio/ip/resolver_service.hpp b/win32/include/boost/asio/ip/resolver_service.hpp new file mode 100755 index 000000000..0460f54d0 --- /dev/null +++ b/win32/include/boost/asio/ip/resolver_service.hpp @@ -0,0 +1,142 @@ +// +// resolver_service.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_RESOLVER_SERVICE_HPP +#define BOOST_ASIO_IP_RESOLVER_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ip { + +/// Default service implementation for a resolver. +template +class resolver_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base< + resolver_service > +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + + /// The protocol type. + typedef InternetProtocol protocol_type; + + /// The endpoint type. + typedef typename InternetProtocol::endpoint endpoint_type; + + /// The query type. + typedef typename InternetProtocol::resolver_query query_type; + + /// The iterator type. + typedef typename InternetProtocol::resolver_iterator iterator_type; + +private: + // The type of the platform-specific implementation. + typedef boost::asio::detail::resolver_service + service_impl_type; + +public: + /// The type of a resolver implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef typename service_impl_type::implementation_type implementation_type; +#endif + + /// Construct a new resolver service for the specified io_service. + explicit resolver_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + resolver_service >(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new resolver implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a resolver implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Cancel pending asynchronous operations. + void cancel(implementation_type& impl) + { + service_impl_.cancel(impl); + } + + /// Resolve a query to a list of entries. + iterator_type resolve(implementation_type& impl, const query_type& query, + boost::system::error_code& ec) + { + return service_impl_.resolve(impl, query, ec); + } + + /// Asynchronously resolve a query to a list of entries. + template + void async_resolve(implementation_type& impl, const query_type& query, + Handler handler) + { + service_impl_.async_resolve(impl, query, handler); + } + + /// Resolve an endpoint to a list of entries. + iterator_type resolve(implementation_type& impl, + const endpoint_type& endpoint, boost::system::error_code& ec) + { + return service_impl_.resolve(impl, endpoint, ec); + } + + /// Asynchronously resolve an endpoint to a list of entries. + template + void async_resolve(implementation_type& impl, const endpoint_type& endpoint, + ResolveHandler handler) + { + return service_impl_.async_resolve(impl, endpoint, handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_RESOLVER_SERVICE_HPP diff --git a/win32/include/boost/asio/ip/tcp.hpp b/win32/include/boost/asio/ip/tcp.hpp new file mode 100755 index 000000000..582e6f8d5 --- /dev/null +++ b/win32/include/boost/asio/ip/tcp.hpp @@ -0,0 +1,160 @@ +// +// tcp.hpp +// ~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_TCP_HPP +#define BOOST_ASIO_IP_TCP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ip { + +/// Encapsulates the flags needed for TCP. +/** + * The boost::asio::ip::tcp class contains flags necessary for TCP sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol, InternetProtocol. + */ +class tcp +{ +public: + /// The type of a TCP endpoint. + typedef basic_endpoint endpoint; + + /// The type of a resolver query. + typedef basic_resolver_query resolver_query; + + /// The type of a resolver iterator. + typedef basic_resolver_iterator resolver_iterator; + + /// Construct to represent the IPv4 TCP protocol. + static tcp v4() + { + return tcp(PF_INET); + } + + /// Construct to represent the IPv6 TCP protocol. + static tcp v6() + { + return tcp(PF_INET6); + } + + /// Obtain an identifier for the type of the protocol. + int type() const + { + return SOCK_STREAM; + } + + /// Obtain an identifier for the protocol. + int protocol() const + { + return IPPROTO_TCP; + } + + /// Obtain an identifier for the protocol family. + int family() const + { + return family_; + } + + /// The TCP socket type. + typedef basic_stream_socket socket; + + /// The TCP acceptor type. + typedef basic_socket_acceptor acceptor; + + /// The TCP resolver type. + typedef basic_resolver resolver; + + /// The TCP iostream type. + typedef basic_socket_iostream iostream; + + /// Socket option for disabling the Nagle algorithm. + /** + * Implements the IPPROTO_TCP/TCP_NODELAY socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::no_delay option(true); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::no_delay option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Boolean_Socket_Option. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined no_delay; +#else + typedef boost::asio::detail::socket_option::boolean< + IPPROTO_TCP, TCP_NODELAY> no_delay; +#endif + + /// Compare two protocols for equality. + friend bool operator==(const tcp& p1, const tcp& p2) + { + return p1.family_ == p2.family_; + } + + /// Compare two protocols for inequality. + friend bool operator!=(const tcp& p1, const tcp& p2) + { + return p1.family_ != p2.family_; + } + +private: + // Construct with a specific family. + explicit tcp(int family) + : family_(family) + { + } + + int family_; +}; + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_TCP_HPP diff --git a/win32/include/boost/asio/ip/udp.hpp b/win32/include/boost/asio/ip/udp.hpp new file mode 100755 index 000000000..458ab9e93 --- /dev/null +++ b/win32/include/boost/asio/ip/udp.hpp @@ -0,0 +1,118 @@ +// +// udp.hpp +// ~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_UDP_HPP +#define BOOST_ASIO_IP_UDP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ip { + +/// Encapsulates the flags needed for UDP. +/** + * The boost::asio::ip::udp class contains flags necessary for UDP sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol, InternetProtocol. + */ +class udp +{ +public: + /// The type of a UDP endpoint. + typedef basic_endpoint endpoint; + + /// The type of a resolver query. + typedef basic_resolver_query resolver_query; + + /// The type of a resolver iterator. + typedef basic_resolver_iterator resolver_iterator; + + /// Construct to represent the IPv4 UDP protocol. + static udp v4() + { + return udp(PF_INET); + } + + /// Construct to represent the IPv6 UDP protocol. + static udp v6() + { + return udp(PF_INET6); + } + + /// Obtain an identifier for the type of the protocol. + int type() const + { + return SOCK_DGRAM; + } + + /// Obtain an identifier for the protocol. + int protocol() const + { + return IPPROTO_UDP; + } + + /// Obtain an identifier for the protocol family. + int family() const + { + return family_; + } + + /// The UDP socket type. + typedef basic_datagram_socket socket; + + /// The UDP resolver type. + typedef basic_resolver resolver; + + /// Compare two protocols for equality. + friend bool operator==(const udp& p1, const udp& p2) + { + return p1.family_ == p2.family_; + } + + /// Compare two protocols for inequality. + friend bool operator!=(const udp& p1, const udp& p2) + { + return p1.family_ != p2.family_; + } + +private: + // Construct with a specific family. + explicit udp(int family) + : family_(family) + { + } + + int family_; +}; + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_UDP_HPP diff --git a/win32/include/boost/asio/ip/unicast.hpp b/win32/include/boost/asio/ip/unicast.hpp new file mode 100755 index 000000000..775934a4f --- /dev/null +++ b/win32/include/boost/asio/ip/unicast.hpp @@ -0,0 +1,72 @@ +// +// unicast.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_UNICAST_HPP +#define BOOST_ASIO_IP_UNICAST_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace ip { +namespace unicast { + +/// Socket option for time-to-live associated with outgoing unicast packets. +/** + * Implements the IPPROTO_IP/IP_UNICAST_TTL socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::udp::socket socket(io_service); + * ... + * boost::asio::ip::unicast::hops option(4); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::udp::socket socket(io_service); + * ... + * boost::asio::ip::unicast::hops option; + * socket.get_option(option); + * int ttl = option.value(); + * @endcode + * + * @par Concepts: + * GettableSocketOption, SettableSocketOption. + */ +#if defined(GENERATING_DOCUMENTATION) +typedef implementation_defined hops; +#else +typedef boost::asio::ip::detail::socket_option::unicast_hops< + IPPROTO_IP, IP_TTL, IPPROTO_IPV6, IPV6_UNICAST_HOPS> hops; +#endif + +} // namespace unicast +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_UNICAST_HPP diff --git a/win32/include/boost/asio/ip/v6_only.hpp b/win32/include/boost/asio/ip/v6_only.hpp new file mode 100755 index 000000000..7af5c31dc --- /dev/null +++ b/win32/include/boost/asio/ip/v6_only.hpp @@ -0,0 +1,70 @@ +// +// v6_only.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IP_V6_ONLY_HPP +#define BOOST_ASIO_IP_V6_ONLY_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +namespace boost { +namespace asio { +namespace ip { + +/// Socket option for determining whether an IPv6 socket supports IPv6 +/// communication only. +/** + * Implements the IPPROTO_IPV6/IP_V6ONLY socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::v6_only option(true); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::v6_only option; + * socket.get_option(option); + * bool v6_only = option.value(); + * @endcode + * + * @par Concepts: + * GettableSocketOption, SettableSocketOption. + */ +#if defined(GENERATING_DOCUMENTATION) +typedef implementation_defined v6_only; +#elif defined(IPV6_V6ONLY) +typedef boost::asio::detail::socket_option::boolean< + IPPROTO_IPV6, IPV6_V6ONLY> v6_only; +#else +typedef boost::asio::detail::socket_option::boolean< + boost::asio::detail::custom_socket_option_level, + boost::asio::detail::always_fail_option> v6_only; +#endif + +} // namespace ip +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IP_V6_ONLY_HPP diff --git a/win32/include/boost/asio/is_read_buffered.hpp b/win32/include/boost/asio/is_read_buffered.hpp new file mode 100755 index 000000000..4122870a9 --- /dev/null +++ b/win32/include/boost/asio/is_read_buffered.hpp @@ -0,0 +1,64 @@ +// +// is_read_buffered.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IS_READ_BUFFERED_HPP +#define BOOST_ASIO_IS_READ_BUFFERED_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { + +namespace detail { + +template +char is_read_buffered_helper(buffered_stream* s); + +template +char is_read_buffered_helper(buffered_read_stream* s); + +struct is_read_buffered_big_type { char data[10]; }; +is_read_buffered_big_type is_read_buffered_helper(...); + +} // namespace detail + +/// The is_read_buffered class is a traits class that may be used to determine +/// whether a stream type supports buffering of read data. +template +class is_read_buffered +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The value member is true only if the Stream type supports buffering of + /// read data. + static const bool value; +#else + BOOST_STATIC_CONSTANT(bool, + value = sizeof(detail::is_read_buffered_helper((Stream*)0)) == 1); +#endif +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IS_READ_BUFFERED_HPP diff --git a/win32/include/boost/asio/is_write_buffered.hpp b/win32/include/boost/asio/is_write_buffered.hpp new file mode 100755 index 000000000..0cf3259bd --- /dev/null +++ b/win32/include/boost/asio/is_write_buffered.hpp @@ -0,0 +1,64 @@ +// +// is_write_buffered.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_IS_WRITE_BUFFERED_HPP +#define BOOST_ASIO_IS_WRITE_BUFFERED_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { + +namespace detail { + +template +char is_write_buffered_helper(buffered_stream* s); + +template +char is_write_buffered_helper(buffered_write_stream* s); + +struct is_write_buffered_big_type { char data[10]; }; +is_write_buffered_big_type is_write_buffered_helper(...); + +} // namespace detail + +/// The is_write_buffered class is a traits class that may be used to determine +/// whether a stream type supports buffering of written data. +template +class is_write_buffered +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The value member is true only if the Stream type supports buffering of + /// written data. + static const bool value; +#else + BOOST_STATIC_CONSTANT(bool, + value = sizeof(detail::is_write_buffered_helper((Stream*)0)) == 1); +#endif +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_IS_WRITE_BUFFERED_HPP diff --git a/win32/include/boost/asio/local/basic_endpoint.hpp b/win32/include/boost/asio/local/basic_endpoint.hpp new file mode 100755 index 000000000..ab046d46f --- /dev/null +++ b/win32/include/boost/asio/local/basic_endpoint.hpp @@ -0,0 +1,267 @@ +// +// basic_endpoint.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Derived from a public domain implementation written by Daniel Casimiro. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_LOCAL_BASIC_ENDPOINT_HPP +#define BOOST_ASIO_LOCAL_BASIC_ENDPOINT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if !defined(BOOST_ASIO_DISABLE_LOCAL_SOCKETS) +# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +# define BOOST_ASIO_HAS_LOCAL_SOCKETS 1 +# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_DISABLE_LOCAL_SOCKETS) + +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \ + || defined(GENERATING_DOCUMENTATION) + + +namespace boost { +namespace asio { +namespace local { + +/// Describes an endpoint for a UNIX socket. +/** + * The boost::asio::local::basic_endpoint class template describes an endpoint + * that may be associated with a particular UNIX socket. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * Endpoint. + */ +template +class basic_endpoint +{ +public: + /// The protocol type associated with the endpoint. + typedef Protocol protocol_type; + + /// The type of the endpoint structure. This type is dependent on the + /// underlying implementation of the socket layer. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined data_type; +#else + typedef boost::asio::detail::socket_addr_type data_type; +#endif + + /// Default constructor. + basic_endpoint() + { + init("", 0); + } + + /// Construct an endpoint using the specified path name. + basic_endpoint(const char* path) + { + using namespace std; // For strlen. + init(path, strlen(path)); + } + + /// Construct an endpoint using the specified path name. + basic_endpoint(const std::string& path) + { + init(path.data(), path.length()); + } + + /// Copy constructor. + basic_endpoint(const basic_endpoint& other) + : data_(other.data_), + path_length_(other.path_length_) + { + } + + /// Assign from another endpoint. + basic_endpoint& operator=(const basic_endpoint& other) + { + data_ = other.data_; + path_length_ = other.path_length_; + return *this; + } + + /// The protocol associated with the endpoint. + protocol_type protocol() const + { + return protocol_type(); + } + + /// Get the underlying endpoint in the native type. + data_type* data() + { + return &data_.base; + } + + /// Get the underlying endpoint in the native type. + const data_type* data() const + { + return &data_.base; + } + + /// Get the underlying size of the endpoint in the native type. + std::size_t size() const + { + return path_length_ + + offsetof(boost::asio::detail::sockaddr_un_type, sun_path); + } + + /// Set the underlying size of the endpoint in the native type. + void resize(std::size_t size) + { + if (size > sizeof(boost::asio::detail::sockaddr_un_type)) + { + boost::system::system_error e(boost::asio::error::invalid_argument); + boost::throw_exception(e); + } + else if (size == 0) + { + path_length_ = 0; + } + else + { + path_length_ = size + - offsetof(boost::asio::detail::sockaddr_un_type, sun_path); + + // The path returned by the operating system may be NUL-terminated. + if (path_length_ > 0 && data_.local.sun_path[path_length_ - 1] == 0) + --path_length_; + } + } + + /// Get the capacity of the endpoint in the native type. + std::size_t capacity() const + { + return sizeof(boost::asio::detail::sockaddr_un_type); + } + + /// Get the path associated with the endpoint. + std::string path() const + { + return std::string(data_.local.sun_path, path_length_); + } + + /// Set the path associated with the endpoint. + void path(const char* p) + { + using namespace std; // For strlen. + init(p, strlen(p)); + } + + /// Set the path associated with the endpoint. + void path(const std::string& p) + { + init(p.data(), p.length()); + } + + /// Compare two endpoints for equality. + friend bool operator==(const basic_endpoint& e1, + const basic_endpoint& e2) + { + return e1.path() == e2.path(); + } + + /// Compare two endpoints for inequality. + friend bool operator!=(const basic_endpoint& e1, + const basic_endpoint& e2) + { + return e1.path() != e2.path(); + } + + /// Compare endpoints for ordering. + friend bool operator<(const basic_endpoint& e1, + const basic_endpoint& e2) + { + return e1.path() < e2.path(); + } + +private: + // The underlying UNIX socket address. + union data_union + { + boost::asio::detail::socket_addr_type base; + boost::asio::detail::sockaddr_un_type local; + } data_; + + // The length of the path associated with the endpoint. + std::size_t path_length_; + + // Initialise with a specified path. + void init(const char* path, std::size_t path_length) + { + if (path_length > sizeof(data_.local.sun_path) - 1) + { + // The buffer is not large enough to store this address. + boost::system::error_code ec(boost::asio::error::name_too_long); + boost::asio::detail::throw_error(ec); + } + + using namespace std; // For memcpy. + data_.local = boost::asio::detail::sockaddr_un_type(); + data_.local.sun_family = AF_UNIX; + memcpy(data_.local.sun_path, path, path_length); + path_length_ = path_length; + + // NUL-terminate normal path names. Names that start with a NUL are in the + // UNIX domain protocol's "abstract namespace" and are not NUL-terminated. + if (path_length > 0 && data_.local.sun_path[0] == 0) + data_.local.sun_path[path_length] = 0; + } +}; + +/// Output an endpoint as a string. +/** + * Used to output a human-readable string for a specified endpoint. + * + * @param os The output stream to which the string will be written. + * + * @param endpoint The endpoint to be written. + * + * @return The output stream. + * + * @relates boost::asio::local::basic_endpoint + */ +template +std::basic_ostream& operator<<( + std::basic_ostream& os, + const basic_endpoint& endpoint) +{ + os << endpoint.path(); + return os; +} + +} // namespace local +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_LOCAL_BASIC_ENDPOINT_HPP diff --git a/win32/include/boost/asio/local/connect_pair.hpp b/win32/include/boost/asio/local/connect_pair.hpp new file mode 100755 index 000000000..8327c2931 --- /dev/null +++ b/win32/include/boost/asio/local/connect_pair.hpp @@ -0,0 +1,102 @@ +// +// connect_pair.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_LOCAL_CONNECT_PAIR_HPP +#define BOOST_ASIO_LOCAL_CONNECT_PAIR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace local { + +/// Create a pair of connected sockets. +template +void connect_pair( + basic_socket& socket1, + basic_socket& socket2); + +/// Create a pair of connected sockets. +template +boost::system::error_code connect_pair( + basic_socket& socket1, + basic_socket& socket2, + boost::system::error_code& ec); + +template +inline void connect_pair( + basic_socket& socket1, + basic_socket& socket2) +{ + boost::system::error_code ec; + connect_pair(socket1, socket2, ec); + boost::asio::detail::throw_error(ec); +} + +template +inline boost::system::error_code connect_pair( + basic_socket& socket1, + basic_socket& socket2, + boost::system::error_code& ec) +{ + // Check that this function is only being used with a UNIX domain socket. + boost::asio::local::basic_endpoint* tmp + = static_cast(0); + (void)tmp; + + Protocol protocol; + boost::asio::detail::socket_type sv[2]; + if (boost::asio::detail::socket_ops::socketpair(protocol.family(), + protocol.type(), protocol.protocol(), sv, ec) + == boost::asio::detail::socket_error_retval) + return ec; + + if (socket1.assign(protocol, sv[0], ec)) + { + boost::system::error_code temp_ec; + boost::asio::detail::socket_ops::close(sv[0], temp_ec); + boost::asio::detail::socket_ops::close(sv[1], temp_ec); + return ec; + } + + if (socket2.assign(protocol, sv[1], ec)) + { + boost::system::error_code temp_ec; + socket1.close(temp_ec); + boost::asio::detail::socket_ops::close(sv[1], temp_ec); + return ec; + } + + return ec; +} + +} // namespace local +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_LOCAL_CONNECT_PAIR_HPP diff --git a/win32/include/boost/asio/local/datagram_protocol.hpp b/win32/include/boost/asio/local/datagram_protocol.hpp new file mode 100755 index 000000000..0d032ac42 --- /dev/null +++ b/win32/include/boost/asio/local/datagram_protocol.hpp @@ -0,0 +1,80 @@ +// +// datagram_protocol.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP +#define BOOST_ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace local { + +/// Encapsulates the flags needed for datagram-oriented UNIX sockets. +/** + * The boost::asio::local::datagram_protocol class contains flags necessary for + * datagram-oriented UNIX domain sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol. + */ +class datagram_protocol +{ +public: + /// Obtain an identifier for the type of the protocol. + int type() const + { + return SOCK_DGRAM; + } + + /// Obtain an identifier for the protocol. + int protocol() const + { + return 0; + } + + /// Obtain an identifier for the protocol family. + int family() const + { + return AF_UNIX; + } + + /// The type of a UNIX domain endpoint. + typedef basic_endpoint endpoint; + + /// The UNIX domain socket type. + typedef basic_datagram_socket socket; +}; + +} // namespace local +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP diff --git a/win32/include/boost/asio/local/stream_protocol.hpp b/win32/include/boost/asio/local/stream_protocol.hpp new file mode 100755 index 000000000..fe5771a2e --- /dev/null +++ b/win32/include/boost/asio/local/stream_protocol.hpp @@ -0,0 +1,88 @@ +// +// stream_protocol.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_LOCAL_STREAM_PROTOCOL_HPP +#define BOOST_ASIO_LOCAL_STREAM_PROTOCOL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace local { + +/// Encapsulates the flags needed for stream-oriented UNIX sockets. +/** + * The boost::asio::local::stream_protocol class contains flags necessary for + * stream-oriented UNIX domain sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol. + */ +class stream_protocol +{ +public: + /// Obtain an identifier for the type of the protocol. + int type() const + { + return SOCK_STREAM; + } + + /// Obtain an identifier for the protocol. + int protocol() const + { + return 0; + } + + /// Obtain an identifier for the protocol family. + int family() const + { + return AF_UNIX; + } + + /// The type of a UNIX domain endpoint. + typedef basic_endpoint endpoint; + + /// The UNIX domain socket type. + typedef basic_stream_socket socket; + + /// The UNIX domain acceptor type. + typedef basic_socket_acceptor acceptor; + + /// The UNIX domain iostream type. + typedef basic_socket_iostream iostream; +}; + +} // namespace local +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_LOCAL_STREAM_PROTOCOL_HPP diff --git a/win32/include/boost/asio/placeholders.hpp b/win32/include/boost/asio/placeholders.hpp new file mode 100755 index 000000000..bb152e336 --- /dev/null +++ b/win32/include/boost/asio/placeholders.hpp @@ -0,0 +1,109 @@ +// +// placeholders.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_PLACEHOLDERS_HPP +#define BOOST_ASIO_PLACEHOLDERS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace placeholders { + +#if defined(GENERATING_DOCUMENTATION) + +/// An argument placeholder, for use with boost::bind(), that corresponds to +/// the error argument of a handler for any of the asynchronous functions. +unspecified error; + +/// An argument placeholder, for use with boost::bind(), that corresponds to +/// the bytes_transferred argument of a handler for asynchronous functions such +/// as boost::asio::basic_stream_socket::async_write_some or +/// boost::asio::async_write. +unspecified bytes_transferred; + +/// An argument placeholder, for use with boost::bind(), that corresponds to +/// the iterator argument of a handler for asynchronous functions such as +/// boost::asio::basic_resolver::resolve. +unspecified iterator; + +#elif defined(__BORLANDC__) || defined(__GNUC__) + +inline boost::arg<1> error() +{ + return boost::arg<1>(); +} + +inline boost::arg<2> bytes_transferred() +{ + return boost::arg<2>(); +} + +inline boost::arg<2> iterator() +{ + return boost::arg<2>(); +} + +#else + +namespace detail +{ + template + struct placeholder + { + static boost::arg& get() + { + static boost::arg result; + return result; + } + }; +} + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1400) + +static boost::arg<1>& error + = boost::asio::placeholders::detail::placeholder<1>::get(); +static boost::arg<2>& bytes_transferred + = boost::asio::placeholders::detail::placeholder<2>::get(); +static boost::arg<2>& iterator + = boost::asio::placeholders::detail::placeholder<2>::get(); + +#else + +namespace +{ + boost::arg<1>& error + = boost::asio::placeholders::detail::placeholder<1>::get(); + boost::arg<2>& bytes_transferred + = boost::asio::placeholders::detail::placeholder<2>::get(); + boost::arg<2>& iterator + = boost::asio::placeholders::detail::placeholder<2>::get(); +} // namespace + +#endif + +#endif + +} // namespace placeholders +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_PLACEHOLDERS_HPP diff --git a/win32/include/boost/asio/posix/basic_descriptor.hpp b/win32/include/boost/asio/posix/basic_descriptor.hpp new file mode 100755 index 000000000..7fc7b77aa --- /dev/null +++ b/win32/include/boost/asio/posix/basic_descriptor.hpp @@ -0,0 +1,282 @@ +// +// basic_descriptor.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP +#define BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace posix { + +/// Provides POSIX descriptor functionality. +/** + * The posix::basic_descriptor class template provides the ability to wrap a + * POSIX descriptor. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_descriptor + : public basic_io_object, + public descriptor_base +{ +public: + /// The native representation of a descriptor. + typedef typename DescriptorService::native_type native_type; + + /// A basic_descriptor is always the lowest layer. + typedef basic_descriptor lowest_layer_type; + + /// Construct a basic_descriptor without opening it. + /** + * This constructor creates a descriptor without opening it. + * + * @param io_service The io_service object that the descriptor will use to + * dispatch handlers for any asynchronous operations performed on the + * descriptor. + */ + explicit basic_descriptor(boost::asio::io_service& io_service) + : basic_io_object(io_service) + { + } + + /// Construct a basic_descriptor on an existing native descriptor. + /** + * This constructor creates a descriptor object to hold an existing native + * descriptor. + * + * @param io_service The io_service object that the descriptor will use to + * dispatch handlers for any asynchronous operations performed on the + * descriptor. + * + * @param native_descriptor A native descriptor. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_descriptor(boost::asio::io_service& io_service, + const native_type& native_descriptor) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.assign(this->implementation, native_descriptor, ec); + boost::asio::detail::throw_error(ec); + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_descriptor cannot contain any further layers, it + * simply returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Assign an existing native descriptor to the descriptor. + /* + * This function opens the descriptor to hold an existing native descriptor. + * + * @param native_descriptor A native descriptor. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const native_type& native_descriptor) + { + boost::system::error_code ec; + this->service.assign(this->implementation, native_descriptor, ec); + boost::asio::detail::throw_error(ec); + } + + /// Assign an existing native descriptor to the descriptor. + /* + * This function opens the descriptor to hold an existing native descriptor. + * + * @param native_descriptor A native descriptor. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code assign(const native_type& native_descriptor, + boost::system::error_code& ec) + { + return this->service.assign(this->implementation, native_descriptor, ec); + } + + /// Determine whether the descriptor is open. + bool is_open() const + { + return this->service.is_open(this->implementation); + } + + /// Close the descriptor. + /** + * This function is used to close the descriptor. Any asynchronous read or + * write operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void close() + { + boost::system::error_code ec; + this->service.close(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Close the descriptor. + /** + * This function is used to close the descriptor. Any asynchronous read or + * write operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code close(boost::system::error_code& ec) + { + return this->service.close(this->implementation, ec); + } + + /// Get the native descriptor representation. + /** + * This function may be used to obtain the underlying representation of the + * descriptor. This is intended to allow access to native descriptor + * functionality that is not otherwise provided. + */ + native_type native() + { + return this->service.native(this->implementation); + } + + /// Cancel all asynchronous operations associated with the descriptor. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void cancel() + { + boost::system::error_code ec; + this->service.cancel(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Cancel all asynchronous operations associated with the descriptor. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code cancel(boost::system::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + + /// Perform an IO control command on the descriptor. + /** + * This function is used to execute an IO control command on the descriptor. + * + * @param command The IO control command to be performed on the descriptor. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa IoControlCommand @n + * boost::asio::posix::descriptor_base::bytes_readable @n + * boost::asio::posix::descriptor_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::posix::stream_descriptor descriptor(io_service); + * ... + * boost::asio::posix::stream_descriptor::bytes_readable command; + * descriptor.io_control(command); + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template + void io_control(IoControlCommand& command) + { + boost::system::error_code ec; + this->service.io_control(this->implementation, command, ec); + boost::asio::detail::throw_error(ec); + } + + /// Perform an IO control command on the descriptor. + /** + * This function is used to execute an IO control command on the descriptor. + * + * @param command The IO control command to be performed on the descriptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa IoControlCommand @n + * boost::asio::posix::descriptor_base::bytes_readable @n + * boost::asio::posix::descriptor_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::posix::stream_descriptor descriptor(io_service); + * ... + * boost::asio::posix::stream_descriptor::bytes_readable command; + * boost::system::error_code ec; + * descriptor.io_control(command, ec); + * if (ec) + * { + * // An error occurred. + * } + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template + boost::system::error_code io_control(IoControlCommand& command, + boost::system::error_code& ec) + { + return this->service.io_control(this->implementation, command, ec); + } + +protected: + /// Protected destructor to prevent deletion through this type. + ~basic_descriptor() + { + } +}; + +} // namespace posix +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP diff --git a/win32/include/boost/asio/posix/basic_stream_descriptor.hpp b/win32/include/boost/asio/posix/basic_stream_descriptor.hpp new file mode 100755 index 000000000..804a3343a --- /dev/null +++ b/win32/include/boost/asio/posix/basic_stream_descriptor.hpp @@ -0,0 +1,306 @@ +// +// basic_stream_descriptor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP +#define BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace posix { + +/// Provides stream-oriented descriptor functionality. +/** + * The posix::basic_stream_descriptor class template provides asynchronous and + * blocking stream-oriented descriptor functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template +class basic_stream_descriptor + : public basic_descriptor +{ +public: + /// The native representation of a descriptor. + typedef typename StreamDescriptorService::native_type native_type; + + /// Construct a basic_stream_descriptor without opening it. + /** + * This constructor creates a stream descriptor without opening it. The + * descriptor needs to be opened and then connected or accepted before data + * can be sent or received on it. + * + * @param io_service The io_service object that the stream descriptor will + * use to dispatch handlers for any asynchronous operations performed on the + * descriptor. + */ + explicit basic_stream_descriptor(boost::asio::io_service& io_service) + : basic_descriptor(io_service) + { + } + + /// Construct a basic_stream_descriptor on an existing native descriptor. + /** + * This constructor creates a stream descriptor object to hold an existing + * native descriptor. + * + * @param io_service The io_service object that the stream descriptor will + * use to dispatch handlers for any asynchronous operations performed on the + * descriptor. + * + * @param native_descriptor The new underlying descriptor implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_stream_descriptor(boost::asio::io_service& io_service, + const native_type& native_descriptor) + : basic_descriptor(io_service, native_descriptor) + { + } + + /// Write some data to the descriptor. + /** + * This function is used to write data to the stream descriptor. The function + * call will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the descriptor. + * + * @returns The number of bytes written. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * descriptor.write_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.write_some(this->implementation, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Write some data to the descriptor. + /** + * This function is used to write data to the stream descriptor. The function + * call will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the descriptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->service.write_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the stream + * descriptor. The function call always returns immediately. + * + * @param buffers One or more data buffers to be written to the descriptor. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * descriptor.async_write_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_write_some(const ConstBufferSequence& buffers, + WriteHandler handler) + { + this->service.async_write_some(this->implementation, buffers, handler); + } + + /// Read some data from the descriptor. + /** + * This function is used to read data from the stream descriptor. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * descriptor.read_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.read_some(this->implementation, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Read some data from the descriptor. + /** + * This function is used to read data from the stream descriptor. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->service.read_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the stream + * descriptor. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * descriptor.async_read_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_read_some(const MutableBufferSequence& buffers, + ReadHandler handler) + { + this->service.async_read_some(this->implementation, buffers, handler); + } +}; + +} // namespace posix +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP diff --git a/win32/include/boost/asio/posix/descriptor_base.hpp b/win32/include/boost/asio/posix/descriptor_base.hpp new file mode 100755 index 000000000..1333075f3 --- /dev/null +++ b/win32/include/boost/asio/posix/descriptor_base.hpp @@ -0,0 +1,95 @@ +// +// descriptor_base.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_POSIX_DESCRIPTOR_BASE_HPP +#define BOOST_ASIO_POSIX_DESCRIPTOR_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { +namespace posix { + +/// The descriptor_base class is used as a base for the basic_stream_descriptor +/// class template so that we have a common place to define the associated +/// IO control commands. +class descriptor_base +{ +public: + /// IO control command to set the blocking mode of the descriptor. + /** + * Implements the FIONBIO IO control command. + * + * @par Example + * @code + * boost::asio::posix::stream_descriptor descriptor(io_service); + * ... + * boost::asio::descriptor_base::non_blocking_io command(true); + * descriptor.io_control(command); + * @endcode + * + * @par Concepts: + * IoControlCommand. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined non_blocking_io; +#else + typedef boost::asio::detail::io_control::non_blocking_io non_blocking_io; +#endif + + /// IO control command to get the amount of data that can be read without + /// blocking. + /** + * Implements the FIONREAD IO control command. + * + * @par Example + * @code + * boost::asio::posix::stream_descriptor descriptor(io_service); + * ... + * boost::asio::descriptor_base::bytes_readable command(true); + * descriptor.io_control(command); + * std::size_t bytes_readable = command.get(); + * @endcode + * + * @par Concepts: + * IoControlCommand. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined bytes_readable; +#else + typedef boost::asio::detail::io_control::bytes_readable bytes_readable; +#endif + +protected: + /// Protected destructor to prevent deletion through this type. + ~descriptor_base() + { + } +}; + +} // namespace posix +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_POSIX_DESCRIPTOR_BASE_HPP diff --git a/win32/include/boost/asio/posix/stream_descriptor.hpp b/win32/include/boost/asio/posix/stream_descriptor.hpp new file mode 100755 index 000000000..643afaf2a --- /dev/null +++ b/win32/include/boost/asio/posix/stream_descriptor.hpp @@ -0,0 +1,41 @@ +// +// stream_descriptor.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_HPP +#define BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace posix { + +/// Typedef for the typical usage of a stream-oriented descriptor. +typedef basic_stream_descriptor<> stream_descriptor; + +} // namespace posix +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_HPP diff --git a/win32/include/boost/asio/posix/stream_descriptor_service.hpp b/win32/include/boost/asio/posix/stream_descriptor_service.hpp new file mode 100755 index 000000000..39d0761cc --- /dev/null +++ b/win32/include/boost/asio/posix/stream_descriptor_service.hpp @@ -0,0 +1,202 @@ +// +// stream_descriptor_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP +#define BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR) +# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +# define BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR 1 +# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR) + +#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace posix { + +/// Default service implementation for a stream descriptor. +class stream_descriptor_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + +private: + // The type of the platform-specific implementation. +#if defined(BOOST_ASIO_HAS_EPOLL) + typedef detail::reactive_descriptor_service< + detail::epoll_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_KQUEUE) + typedef detail::reactive_descriptor_service< + detail::kqueue_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_DEV_POLL) + typedef detail::reactive_descriptor_service< + detail::dev_poll_reactor > service_impl_type; +#else + typedef detail::reactive_descriptor_service< + detail::select_reactor > service_impl_type; +#endif + +public: + /// The type of a stream descriptor implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef service_impl_type::implementation_type implementation_type; +#endif + + /// The native descriptor type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef service_impl_type::native_type native_type; +#endif + + /// Construct a new stream descriptor service for the specified io_service. + explicit stream_descriptor_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined descriptorr objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new stream descriptor implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a stream descriptor implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Assign an existing native descriptor to a stream descriptor. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_descriptor, boost::system::error_code& ec) + { + return service_impl_.assign(impl, native_descriptor, ec); + } + + /// Determine whether the descriptor is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a stream descriptor implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native descriptor implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the descriptor. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Perform an IO control command on the descriptor. + template + boost::system::error_code io_control(implementation_type& impl, + IoControlCommand& command, boost::system::error_code& ec) + { + return service_impl_.io_control(impl, command, ec); + } + + /// Write the given data to the stream. + template + std::size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.write_some(impl, buffers, ec); + } + + /// Start an asynchronous write. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, WriteHandler descriptorr) + { + service_impl_.async_write_some(impl, buffers, descriptorr); + } + + /// Read some data from the stream. + template + std::size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.read_some(impl, buffers, ec); + } + + /// Start an asynchronous read. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, ReadHandler descriptorr) + { + service_impl_.async_read_some(impl, buffers, descriptorr); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace posix +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP diff --git a/win32/include/boost/asio/raw_socket_service.hpp b/win32/include/boost/asio/raw_socket_service.hpp new file mode 100755 index 000000000..2acf00104 --- /dev/null +++ b/win32/include/boost/asio/raw_socket_service.hpp @@ -0,0 +1,325 @@ +// +// raw_socket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_RAW_SOCKET_SERVICE_HPP +#define BOOST_ASIO_RAW_SOCKET_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Default service implementation for a raw socket. +template +class raw_socket_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base > +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + +private: + // The type of the platform-specific implementation. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef detail::win_iocp_socket_service service_impl_type; +#elif defined(BOOST_ASIO_HAS_EPOLL) + typedef detail::reactive_socket_service< + Protocol, detail::epoll_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_KQUEUE) + typedef detail::reactive_socket_service< + Protocol, detail::kqueue_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_DEV_POLL) + typedef detail::reactive_socket_service< + Protocol, detail::dev_poll_reactor > service_impl_type; +#else + typedef detail::reactive_socket_service< + Protocol, detail::select_reactor > service_impl_type; +#endif + +public: + /// The type of a raw socket. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef typename service_impl_type::implementation_type implementation_type; +#endif + + /// The native socket type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef typename service_impl_type::native_type native_type; +#endif + + /// Construct a new raw socket service for the specified io_service. + explicit raw_socket_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + raw_socket_service >(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new raw socket implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a raw socket implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + // Open a new raw socket implementation. + boost::system::error_code open(implementation_type& impl, + const protocol_type& protocol, boost::system::error_code& ec) + { + if (protocol.type() == SOCK_RAW) + service_impl_.open(impl, protocol, ec); + else + ec = boost::asio::error::invalid_argument; + return ec; + } + + /// Assign an existing native socket to a raw socket. + boost::system::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_type& native_socket, + boost::system::error_code& ec) + { + return service_impl_.assign(impl, protocol, native_socket, ec); + } + + /// Determine whether the socket is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a raw socket implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native socket implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the socket. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Determine whether the socket is at the out-of-band data mark. + bool at_mark(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.at_mark(impl, ec); + } + + /// Determine the number of bytes available for reading. + std::size_t available(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.available(impl, ec); + } + + // Bind the raw socket to the specified local endpoint. + boost::system::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, boost::system::error_code& ec) + { + return service_impl_.bind(impl, endpoint, ec); + } + + /// Connect the raw socket to the specified endpoint. + boost::system::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + return service_impl_.connect(impl, peer_endpoint, ec); + } + + /// Start an asynchronous connect. + template + void async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, ConnectHandler handler) + { + service_impl_.async_connect(impl, peer_endpoint, handler); + } + + /// Set a socket option. + template + boost::system::error_code set_option(implementation_type& impl, + const SettableSocketOption& option, boost::system::error_code& ec) + { + return service_impl_.set_option(impl, option, ec); + } + + /// Get a socket option. + template + boost::system::error_code get_option(const implementation_type& impl, + GettableSocketOption& option, boost::system::error_code& ec) const + { + return service_impl_.get_option(impl, option, ec); + } + + /// Perform an IO control command on the socket. + template + boost::system::error_code io_control(implementation_type& impl, + IoControlCommand& command, boost::system::error_code& ec) + { + return service_impl_.io_control(impl, command, ec); + } + + /// Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.local_endpoint(impl, ec); + } + + /// Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.remote_endpoint(impl, ec); + } + + /// Disable sends or receives on the socket. + boost::system::error_code shutdown(implementation_type& impl, + socket_base::shutdown_type what, boost::system::error_code& ec) + { + return service_impl_.shutdown(impl, what, ec); + } + + /// Send the given data to the peer. + template + std::size_t send(implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.send(impl, buffers, flags, ec); + } + + /// Start an asynchronous send. + template + void async_send(implementation_type& impl, const ConstBufferSequence& buffers, + socket_base::message_flags flags, WriteHandler handler) + { + service_impl_.async_send(impl, buffers, flags, handler); + } + + /// Send raw data to the specified endpoint. + template + std::size_t send_to(implementation_type& impl, + const ConstBufferSequence& buffers, const endpoint_type& destination, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.send_to(impl, buffers, destination, flags, ec); + } + + /// Start an asynchronous send. + template + void async_send_to(implementation_type& impl, + const ConstBufferSequence& buffers, const endpoint_type& destination, + socket_base::message_flags flags, WriteHandler handler) + { + service_impl_.async_send_to(impl, buffers, destination, flags, handler); + } + + /// Receive some data from the peer. + template + std::size_t receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.receive(impl, buffers, flags, ec); + } + + /// Start an asynchronous receive. + template + void async_receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, ReadHandler handler) + { + service_impl_.async_receive(impl, buffers, flags, handler); + } + + /// Receive raw data with the endpoint of the sender. + template + std::size_t receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.receive_from(impl, buffers, sender_endpoint, flags, + ec); + } + + /// Start an asynchronous receive that will get the endpoint of the sender. + template + void async_receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, ReadHandler handler) + { + service_impl_.async_receive_from(impl, buffers, sender_endpoint, flags, + handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_RAW_SOCKET_SERVICE_HPP diff --git a/win32/include/boost/asio/read.hpp b/win32/include/boost/asio/read.hpp new file mode 100755 index 000000000..be7192e99 --- /dev/null +++ b/win32/include/boost/asio/read.hpp @@ -0,0 +1,524 @@ +// +// read.hpp +// ~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_READ_HPP +#define BOOST_ASIO_READ_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { + +/** + * @defgroup read boost::asio::read + * + * @brief Attempt to read a certain amount of data from a stream before + * returning. + */ +/*@{*/ + +/// Attempt to read a certain amount of data from a stream before returning. +/** + * This function is used to read a certain number of bytes of data from a + * stream. The call will block until one of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the stream's + * read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * stream. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code boost::asio::read(s, boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code boost::asio::read( + * s, buffers, + * boost::asio::transfer_all()); @endcode + */ +template +std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers); + +/// Attempt to read a certain amount of data from a stream before returning. +/** + * This function is used to read a certain number of bytes of data from a + * stream. The call will block until one of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the stream's + * read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * stream. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const boost::system::error_code& error, // Result of latest read_some + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the stream's read_some function are required. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code boost::asio::read(s, boost::asio::buffer(data, size), + * boost::asio::transfer_at_least(32)); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, + CompletionCondition completion_condition); + +/// Attempt to read a certain amount of data from a stream before returning. +/** + * This function is used to read a certain number of bytes of data from a + * stream. The call will block until one of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the stream's + * read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * stream. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const boost::system::error_code& error, // Result of latest read_some + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the stream's read_some function are required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, boost::system::error_code& ec); + +/// Attempt to read a certain amount of data from a stream before returning. +/** + * This function is used to read a certain number of bytes of data from a + * stream. The call will block until one of the following conditions is true: + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the stream's + * read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b The basic_streambuf object into which the data will be read. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This overload is equivalent to calling: + * @code boost::asio::read( + * s, b, + * boost::asio::transfer_all()); @endcode + */ +template +std::size_t read(SyncReadStream& s, basic_streambuf& b); + +/// Attempt to read a certain amount of data from a stream before returning. +/** + * This function is used to read a certain number of bytes of data from a + * stream. The call will block until one of the following conditions is true: + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the stream's + * read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b The basic_streambuf object into which the data will be read. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const boost::system::error_code& error, // Result of latest read_some + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the stream's read_some function are required. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + */ +template +std::size_t read(SyncReadStream& s, basic_streambuf& b, + CompletionCondition completion_condition); + +/// Attempt to read a certain amount of data from a stream before returning. +/** + * This function is used to read a certain number of bytes of data from a + * stream. The call will block until one of the following conditions is true: + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the stream's + * read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b The basic_streambuf object into which the data will be read. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const boost::system::error_code& error, // Result of latest read_some + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the stream's read_some function are required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t read(SyncReadStream& s, basic_streambuf& b, + CompletionCondition completion_condition, boost::system::error_code& ec); + +/*@}*/ +/** + * @defgroup async_read boost::asio::async_read + * + * @brief Start an asynchronous operation to read a certain amount of data from + * a stream. + */ +/*@{*/ + +/// Start an asynchronous operation to read a certain amount of data from a +/// stream. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions is + * true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the stream's + * async_read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * stream. Although the buffers object may be copied as necessary, ownership of + * the underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes copied into the + * // buffers. If an error occurred, + * // this will be the number of + * // bytes successfully transferred + * // prior to the error. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::async_read(s, boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code boost::asio::async_read( + * s, buffers, + * boost::asio::transfer_all(), + * handler); @endcode + */ +template +void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, + ReadHandler handler); + +/// Start an asynchronous operation to read a certain amount of data from a +/// stream. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions is + * true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * stream. Although the buffers object may be copied as necessary, ownership of + * the underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const boost::system::error_code& error, // Result of latest read_some + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the stream's async_read_some function are + * required. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes copied into the + * // buffers. If an error occurred, + * // this will be the number of + * // bytes successfully transferred + * // prior to the error. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code boost::asio::async_read(s, + * boost::asio::buffer(data, size), + * boost::asio::transfer_at_least(32), + * handler); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, ReadHandler handler); + +/// Start an asynchronous operation to read a certain amount of data from a +/// stream. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions is + * true: + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the stream's + * async_read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param b A basic_streambuf object into which the data will be read. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes copied into the + * // buffers. If an error occurred, + * // this will be the number of + * // bytes successfully transferred + * // prior to the error. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note This overload is equivalent to calling: + * @code boost::asio::async_read( + * s, b, + * boost::asio::transfer_all(), + * handler); @endcode + */ +template +void async_read(AsyncReadStream& s, basic_streambuf& b, + ReadHandler handler); + +/// Start an asynchronous operation to read a certain amount of data from a +/// stream. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions is + * true: + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the stream's + * async_read_some function. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param b A basic_streambuf object into which the data will be read. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const boost::system::error_code& error, // Result of latest read_some + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the stream's async_read_some function are + * required. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes copied into the + * // buffers. If an error occurred, + * // this will be the number of + * // bytes successfully transferred + * // prior to the error. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ +template +void async_read(AsyncReadStream& s, basic_streambuf& b, + CompletionCondition completion_condition, ReadHandler handler); + +/*@}*/ + +} // namespace asio +} // namespace boost + +#include + +#include + +#endif // BOOST_ASIO_READ_HPP diff --git a/win32/include/boost/asio/read_at.hpp b/win32/include/boost/asio/read_at.hpp new file mode 100755 index 000000000..cacbe0d74 --- /dev/null +++ b/win32/include/boost/asio/read_at.hpp @@ -0,0 +1,570 @@ +// +// read_at.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_READ_AT_HPP +#define BOOST_ASIO_READ_AT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { + +/** + * @defgroup read_at boost::asio::read_at + * + * @brief Attempt to read a certain amount of data at the specified offset + * before returning. + */ +/*@{*/ + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code boost::asio::read_at(d, 42, boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code boost::asio::read_at( + * d, 42, buffers, + * boost::asio::transfer_all()); @endcode + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's read_some_at function are + * required. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code boost::asio::read_at(d, 42, boost::asio::buffer(data, size), + * boost::asio::transfer_at_least(32)); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const boost::system::error_code& error, // Result of latest read_some_at + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's read_some_at function are + * required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, boost::system::error_code& ec); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b The basic_streambuf object into which the data will be read. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This overload is equivalent to calling: + * @code boost::asio::read_at( + * d, 42, b, + * boost::asio::transfer_all()); @endcode + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, basic_streambuf& b); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b The basic_streambuf object into which the data will be read. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's read_some_at function are + * required. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, basic_streambuf& b, + CompletionCondition completion_condition); + +/// Attempt to read a certain amount of data at the specified offset before +/// returning. +/** + * This function is used to read a certain number of bytes of data from a + * random access device at the specified offset. The call will block until one + * of the following conditions is true: + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the SyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b The basic_streambuf object into which the data will be read. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's read_some_at function are + * required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t read_at(SyncRandomAccessReadDevice& d, + boost::uint64_t offset, basic_streambuf& b, + CompletionCondition completion_condition, boost::system::error_code& ec); + +/*@}*/ +/** + * @defgroup async_read_at boost::asio::async_read_at + * + * @brief Start an asynchronous operation to read a certain amount of data at + * the specified offset. + */ +/*@{*/ + +/// Start an asynchronous operation to read a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a random access device at the specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * async_read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the AsyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. Although the buffers object may be copied as necessary, ownership of + * the underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::async_read_at(d, 42, boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code boost::asio::async_read_at( + * d, 42, buffers, + * boost::asio::transfer_all(), + * handler); @endcode + */ +template +void async_read_at(AsyncRandomAccessReadDevice& d, boost::uint64_t offset, + const MutableBufferSequence& buffers, ReadHandler handler); + +/// Start an asynchronous operation to read a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a random access device at the specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li The supplied buffers are full. That is, the bytes transferred is equal to + * the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * @param d The device from which the data is to be read. The type must support + * the AsyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. The sum + * of the buffer sizes indicates the maximum number of bytes to read from the + * device. Although the buffers object may be copied as necessary, ownership of + * the underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's async_read_some_at function are + * required. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code boost::asio::async_read_at(d, 42, + * boost::asio::buffer(data, size), + * boost::asio::transfer_at_least(32), + * handler); @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, ReadHandler handler); + +/// Start an asynchronous operation to read a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a random access device at the specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * async_read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the AsyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b A basic_streambuf object into which the data will be read. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note This overload is equivalent to calling: + * @code boost::asio::async_read_at( + * d, 42, b, + * boost::asio::transfer_all(), + * handler); @endcode + */ +template +void async_read_at(AsyncRandomAccessReadDevice& d, boost::uint64_t offset, + basic_streambuf& b, ReadHandler handler); + +/// Start an asynchronous operation to read a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously read a certain number of bytes of + * data from a random access device at the specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * async_read_some_at function. + * + * @param d The device from which the data is to be read. The type must support + * the AsyncRandomAccessReadDevice concept. + * + * @param offset The offset at which the data will be read. + * + * @param b A basic_streambuf object into which the data will be read. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the read operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest read_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the read operation is complete. False + * indicates that further calls to the device's async_read_some_at function are + * required. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ +template +void async_read_at(AsyncRandomAccessReadDevice& d, + boost::uint64_t offset, basic_streambuf& b, + CompletionCondition completion_condition, ReadHandler handler); + +/*@}*/ + +} // namespace asio +} // namespace boost + +#include + +#include + +#endif // BOOST_ASIO_READ_AT_HPP diff --git a/win32/include/boost/asio/read_until.hpp b/win32/include/boost/asio/read_until.hpp new file mode 100755 index 000000000..bd7a36905 --- /dev/null +++ b/win32/include/boost/asio/read_until.hpp @@ -0,0 +1,825 @@ +// +// read_until.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_READ_UNTIL_HPP +#define BOOST_ASIO_READ_UNTIL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { + +namespace detail +{ + template + struct has_result_type + { + struct big { char a[100]; }; + template static big helper(U, ...); + template static char helper(U, typename U::result_type* = 0); + static const T& ref(); + enum { value = (sizeof((helper)((ref)())) == 1) }; + }; +} // namespace detail + +/// Type trait used to determine whether a type can be used as a match condition +/// function with read_until and async_read_until. +template +struct is_match_condition +{ +#if defined(GENERATING_DOCUMENTATION) + /// The value member is true if the type may be used as a match condition. + static const bool value; +#else + enum + { + value = boost::is_function::type>::value + || detail::has_result_type::value + }; +#endif +}; + +/** + * @defgroup read_until boost::asio::read_until + * + * @brief Read data into a streambuf until it contains a delimiter, matches a + * regular expression, or a function object indicates a match. + */ +/*@{*/ + +/// Read data into a streambuf until it contains a specified delimiter. +/** + * This function is used to read data into the specified streambuf until the + * streambuf's get area contains the specified delimiter. The call will block + * until one of the following conditions is true: + * + * @li The get area of the streambuf contains the specified delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the streambuf's get area already contains the + * delimiter, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param delim The delimiter character. + * + * @returns The number of bytes in the streambuf's get area up to and including + * the delimiter. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond the delimiter. An application will typically leave + * that data in the streambuf for a subsequent read_until operation to examine. + * + * @par Example + * To read data into a streambuf until a newline is encountered: + * @code boost::asio::streambuf b; + * boost::asio::read_until(s, b, '\n'); + * std::istream is(&b); + * std::string line; + * std::getline(is, line); @endcode + */ +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, char delim); + +/// Read data into a streambuf until it contains a specified delimiter. +/** + * This function is used to read data into the specified streambuf until the + * streambuf's get area contains the specified delimiter. The call will block + * until one of the following conditions is true: + * + * @li The get area of the streambuf contains the specified delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the streambuf's get area already contains the + * delimiter, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param delim The delimiter character. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes in the streambuf's get area up to and including + * the delimiter. Returns 0 if an error occurred. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond the delimiter. An application will typically leave + * that data in the streambuf for a subsequent read_until operation to examine. + */ +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, char delim, + boost::system::error_code& ec); + +/// Read data into a streambuf until it contains a specified delimiter. +/** + * This function is used to read data into the specified streambuf until the + * streambuf's get area contains the specified delimiter. The call will block + * until one of the following conditions is true: + * + * @li The get area of the streambuf contains the specified delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the streambuf's get area already contains the + * delimiter, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param delim The delimiter string. + * + * @returns The number of bytes in the streambuf's get area up to and including + * the delimiter. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond the delimiter. An application will typically leave + * that data in the streambuf for a subsequent read_until operation to examine. + * + * @par Example + * To read data into a streambuf until a newline is encountered: + * @code boost::asio::streambuf b; + * boost::asio::read_until(s, b, "\r\n"); + * std::istream is(&b); + * std::string line; + * std::getline(is, line); @endcode + */ +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, const std::string& delim); + +/// Read data into a streambuf until it contains a specified delimiter. +/** + * This function is used to read data into the specified streambuf until the + * streambuf's get area contains the specified delimiter. The call will block + * until one of the following conditions is true: + * + * @li The get area of the streambuf contains the specified delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the streambuf's get area already contains the + * delimiter, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param delim The delimiter string. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes in the streambuf's get area up to and including + * the delimiter. Returns 0 if an error occurred. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond the delimiter. An application will typically leave + * that data in the streambuf for a subsequent read_until operation to examine. + */ +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, const std::string& delim, + boost::system::error_code& ec); + +/// Read data into a streambuf until some part of the data it contains matches +/// a regular expression. +/** + * This function is used to read data into the specified streambuf until the + * streambuf's get area contains some data that matches a regular expression. + * The call will block until one of the following conditions is true: + * + * @li A substring of the streambuf's get area matches the regular expression. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the streambuf's get area already contains data that + * matches the regular expression, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param expr The regular expression. + * + * @returns The number of bytes in the streambuf's get area up to and including + * the substring that matches the regular expression. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond that which matched the regular expression. An + * application will typically leave that data in the streambuf for a subsequent + * read_until operation to examine. + * + * @par Example + * To read data into a streambuf until a CR-LF sequence is encountered: + * @code boost::asio::streambuf b; + * boost::asio::read_until(s, b, boost::regex("\r\n")); + * std::istream is(&b); + * std::string line; + * std::getline(is, line); @endcode + */ +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, const boost::regex& expr); + +/// Read data into a streambuf until some part of the data it contains matches +/// a regular expression. +/** + * This function is used to read data into the specified streambuf until the + * streambuf's get area contains some data that matches a regular expression. + * The call will block until one of the following conditions is true: + * + * @li A substring of the streambuf's get area matches the regular expression. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the streambuf's get area already contains data that + * matches the regular expression, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param expr The regular expression. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes in the streambuf's get area up to and including + * the substring that matches the regular expression. Returns 0 if an error + * occurred. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond that which matched the regular expression. An + * application will typically leave that data in the streambuf for a subsequent + * read_until operation to examine. + */ +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, const boost::regex& expr, + boost::system::error_code& ec); + +/// Read data into a streambuf until a function object indicates a match. +/** + * This function is used to read data into the specified streambuf until a + * user-defined match condition function object, when applied to the data + * contained in the streambuf, indicates a successful match. The call will + * block until one of the following conditions is true: + * + * @li The match condition function object returns a std::pair where the second + * element evaluates to true. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the match condition function object already indicates + * a match, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param match_condition The function object to be called to determine whether + * a match exists. The signature of the function object must be: + * @code pair match_condition(iterator begin, iterator end); + * @endcode + * where @c iterator represents the type: + * @code buffers_iterator::const_buffers_type> + * @endcode + * The iterator parameters @c begin and @c end define the range of bytes to be + * scanned to determine whether there is a match. The @c first member of the + * return value is an iterator marking one-past-the-end of the bytes that have + * been consumed by the match function. This iterator is used to calculate the + * @c begin parameter for any subsequent invocation of the match condition. The + * @c second member of the return value is true if a match has been found, false + * otherwise. + * + * @returns The number of bytes in the streambuf's get area that have been fully + * consumed by the match function. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond that which matched the function object. An application + * will typically leave that data in the streambuf for a subsequent + * + * @note The default implementation of the @c is_match_condition type trait + * evaluates to true for function pointers and function objects with a + * @c result_type typedef. It must be specialised for other user-defined + * function objects. + * + * @par Examples + * To read data into a streambuf until whitespace is encountered: + * @code typedef boost::asio::buffers_iterator< + * boost::asio::streambuf::const_buffers_type> iterator; + * + * std::pair + * match_whitespace(iterator begin, iterator end) + * { + * iterator i = begin; + * while (i != end) + * if (std::isspace(*i++)) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * ... + * boost::asio::streambuf b; + * boost::asio::read_until(s, b, match_whitespace); + * @endcode + * + * To read data into a streambuf until a matching character is found: + * @code class match_char + * { + * public: + * explicit match_char(char c) : c_(c) {} + * + * template + * std::pair operator()( + * Iterator begin, Iterator end) const + * { + * Iterator i = begin; + * while (i != end) + * if (c_ == *i++) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * + * private: + * char c_; + * }; + * + * namespace asio { + * template <> struct is_match_condition + * : public boost::true_type {}; + * } // namespace asio + * ... + * boost::asio::streambuf b; + * boost::asio::read_until(s, b, match_char('a')); + * @endcode + */ +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, MatchCondition match_condition, + typename boost::enable_if >::type* = 0); + +/// Read data into a streambuf until a function object indicates a match. +/** + * This function is used to read data into the specified streambuf until a + * user-defined match condition function object, when applied to the data + * contained in the streambuf, indicates a successful match. The call will + * block until one of the following conditions is true: + * + * @li The match condition function object returns a std::pair where the second + * element evaluates to true. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * read_some function. If the match condition function object already indicates + * a match, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the SyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param match_condition The function object to be called to determine whether + * a match exists. The signature of the function object must be: + * @code pair match_condition(iterator begin, iterator end); + * @endcode + * where @c iterator represents the type: + * @code buffers_iterator::const_buffers_type> + * @endcode + * The iterator parameters @c begin and @c end define the range of bytes to be + * scanned to determine whether there is a match. The @c first member of the + * return value is an iterator marking one-past-the-end of the bytes that have + * been consumed by the match function. This iterator is used to calculate the + * @c begin parameter for any subsequent invocation of the match condition. The + * @c second member of the return value is true if a match has been found, false + * otherwise. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes in the streambuf's get area that have been fully + * consumed by the match function. Returns 0 if an error occurred. + * + * @note After a successful read_until operation, the streambuf may contain + * additional data beyond that which matched the function object. An application + * will typically leave that data in the streambuf for a subsequent + * + * @note The default implementation of the @c is_match_condition type trait + * evaluates to true for function pointers and function objects with a + * @c result_type typedef. It must be specialised for other user-defined + * function objects. + */ +template +std::size_t read_until(SyncReadStream& s, + boost::asio::basic_streambuf& b, + MatchCondition match_condition, boost::system::error_code& ec, + typename boost::enable_if >::type* = 0); + +/*@}*/ +/** + * @defgroup async_read_until boost::asio::async_read_until + * + * @brief Start an asynchronous operation to read data into a streambuf until it + * contains a delimiter, matches a regular expression, or a function object + * indicates a match. + */ +/*@{*/ + +/// Start an asynchronous operation to read data into a streambuf until it +/// contains a specified delimiter. +/** + * This function is used to asynchronously read data into the specified + * streambuf until the streambuf's get area contains the specified delimiter. + * The function call always returns immediately. The asynchronous operation + * will continue until one of the following conditions is true: + * + * @li The get area of the streambuf contains the specified delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function. If the streambuf's get area already contains the + * delimiter, the asynchronous operation completes immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. Ownership of + * the streambuf is retained by the caller, which must guarantee that it remains + * valid until the handler is called. + * + * @param delim The delimiter character. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // The number of bytes in the streambuf's get + * // area up to and including the delimiter. + * // 0 if an error occurred. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note After a successful async_read_until operation, the streambuf may + * contain additional data beyond the delimiter. An application will typically + * leave that data in the streambuf for a subsequent async_read_until operation + * to examine. + * + * @par Example + * To asynchronously read data into a streambuf until a newline is encountered: + * @code boost::asio::streambuf b; + * ... + * void handler(const boost::system::error_code& e, std::size_t size) + * { + * if (!e) + * { + * std::istream is(&b); + * std::string line; + * std::getline(is, line); + * ... + * } + * } + * ... + * boost::asio::async_read_until(s, b, '\n', handler); @endcode + */ +template +void async_read_until(AsyncReadStream& s, + boost::asio::basic_streambuf& b, + char delim, ReadHandler handler); + +/// Start an asynchronous operation to read data into a streambuf until it +/// contains a specified delimiter. +/** + * This function is used to asynchronously read data into the specified + * streambuf until the streambuf's get area contains the specified delimiter. + * The function call always returns immediately. The asynchronous operation + * will continue until one of the following conditions is true: + * + * @li The get area of the streambuf contains the specified delimiter. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function. If the streambuf's get area already contains the + * delimiter, the asynchronous operation completes immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. Ownership of + * the streambuf is retained by the caller, which must guarantee that it remains + * valid until the handler is called. + * + * @param delim The delimiter string. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // The number of bytes in the streambuf's get + * // area up to and including the delimiter. + * // 0 if an error occurred. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note After a successful async_read_until operation, the streambuf may + * contain additional data beyond the delimiter. An application will typically + * leave that data in the streambuf for a subsequent async_read_until operation + * to examine. + * + * @par Example + * To asynchronously read data into a streambuf until a newline is encountered: + * @code boost::asio::streambuf b; + * ... + * void handler(const boost::system::error_code& e, std::size_t size) + * { + * if (!e) + * { + * std::istream is(&b); + * std::string line; + * std::getline(is, line); + * ... + * } + * } + * ... + * boost::asio::async_read_until(s, b, "\r\n", handler); @endcode + */ +template +void async_read_until(AsyncReadStream& s, + boost::asio::basic_streambuf& b, const std::string& delim, + ReadHandler handler); + +/// Start an asynchronous operation to read data into a streambuf until some +/// part of its data matches a regular expression. +/** + * This function is used to asynchronously read data into the specified + * streambuf until the streambuf's get area contains some data that matches a + * regular expression. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: + * + * @li A substring of the streambuf's get area matches the regular expression. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function. If the streambuf's get area already contains data + * that matches the regular expression, the function returns immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. Ownership of + * the streambuf is retained by the caller, which must guarantee that it remains + * valid until the handler is called. + * + * @param expr The regular expression. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // The number of bytes in the streambuf's get + * // area up to and including the substring + * // that matches the regular. expression. + * // 0 if an error occurred. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note After a successful async_read_until operation, the streambuf may + * contain additional data beyond that which matched the regular expression. An + * application will typically leave that data in the streambuf for a subsequent + * async_read_until operation to examine. + * + * @par Example + * To asynchronously read data into a streambuf until a CR-LF sequence is + * encountered: + * @code boost::asio::streambuf b; + * ... + * void handler(const boost::system::error_code& e, std::size_t size) + * { + * if (!e) + * { + * std::istream is(&b); + * std::string line; + * std::getline(is, line); + * ... + * } + * } + * ... + * boost::asio::async_read_until(s, b, boost::regex("\r\n"), handler); @endcode + */ +template +void async_read_until(AsyncReadStream& s, + boost::asio::basic_streambuf& b, const boost::regex& expr, + ReadHandler handler); + +/// Start an asynchronous operation to read data into a streambuf until a +/// function object indicates a match. +/** + * This function is used to asynchronously read data into the specified + * streambuf until a user-defined match condition function object, when applied + * to the data contained in the streambuf, indicates a successful match. The + * function call always returns immediately. The asynchronous operation will + * continue until one of the following conditions is true: + * + * @li The match condition function object returns a std::pair where the second + * element evaluates to true. + * + * @li An error occurred. + * + * This operation is implemented in terms of zero or more calls to the stream's + * async_read_some function. If the match condition function object already + * indicates a match, the operation completes immediately. + * + * @param s The stream from which the data is to be read. The type must support + * the AsyncReadStream concept. + * + * @param b A streambuf object into which the data will be read. + * + * @param match_condition The function object to be called to determine whether + * a match exists. The signature of the function object must be: + * @code pair match_condition(iterator begin, iterator end); + * @endcode + * where @c iterator represents the type: + * @code buffers_iterator::const_buffers_type> + * @endcode + * The iterator parameters @c begin and @c end define the range of bytes to be + * scanned to determine whether there is a match. The @c first member of the + * return value is an iterator marking one-past-the-end of the bytes that have + * been consumed by the match function. This iterator is used to calculate the + * @c begin parameter for any subsequent invocation of the match condition. The + * @c second member of the return value is true if a match has been found, false + * otherwise. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // The number of bytes in the streambuf's get + * // area that have been fully consumed by the + * // match function. O if an error occurred. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note After a successful async_read_until operation, the streambuf may + * contain additional data beyond that which matched the function object. An + * application will typically leave that data in the streambuf for a subsequent + * async_read_until operation to examine. + * + * @note The default implementation of the @c is_match_condition type trait + * evaluates to true for function pointers and function objects with a + * @c result_type typedef. It must be specialised for other user-defined + * function objects. + * + * @par Examples + * To asynchronously read data into a streambuf until whitespace is encountered: + * @code typedef boost::asio::buffers_iterator< + * boost::asio::streambuf::const_buffers_type> iterator; + * + * std::pair + * match_whitespace(iterator begin, iterator end) + * { + * iterator i = begin; + * while (i != end) + * if (std::isspace(*i++)) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * ... + * void handler(const boost::system::error_code& e, std::size_t size); + * ... + * boost::asio::streambuf b; + * boost::asio::async_read_until(s, b, match_whitespace, handler); + * @endcode + * + * To asynchronously read data into a streambuf until a matching character is + * found: + * @code class match_char + * { + * public: + * explicit match_char(char c) : c_(c) {} + * + * template + * std::pair operator()( + * Iterator begin, Iterator end) const + * { + * Iterator i = begin; + * while (i != end) + * if (c_ == *i++) + * return std::make_pair(i, true); + * return std::make_pair(i, false); + * } + * + * private: + * char c_; + * }; + * + * namespace asio { + * template <> struct is_match_condition + * : public boost::true_type {}; + * } // namespace asio + * ... + * void handler(const boost::system::error_code& e, std::size_t size); + * ... + * boost::asio::streambuf b; + * boost::asio::async_read_until(s, b, match_char('a'), handler); + * @endcode + */ +template +void async_read_until(AsyncReadStream& s, + boost::asio::basic_streambuf& b, + MatchCondition match_condition, ReadHandler handler, + typename boost::enable_if >::type* = 0); + +/*@}*/ + +} // namespace asio +} // namespace boost + +#include + +#include + +#endif // BOOST_ASIO_READ_UNTIL_HPP diff --git a/win32/include/boost/asio/serial_port.hpp b/win32/include/boost/asio/serial_port.hpp new file mode 100755 index 000000000..72a7ae8d2 --- /dev/null +++ b/win32/include/boost/asio/serial_port.hpp @@ -0,0 +1,40 @@ +// +// serial_port.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SERIAL_PORT_HPP +#define BOOST_ASIO_SERIAL_PORT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { + +/// Typedef for the typical usage of a serial port. +typedef basic_serial_port<> serial_port; + +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_SERIAL_PORT_HPP diff --git a/win32/include/boost/asio/serial_port_base.hpp b/win32/include/boost/asio/serial_port_base.hpp new file mode 100755 index 000000000..9dced7c8f --- /dev/null +++ b/win32/include/boost/asio/serial_port_base.hpp @@ -0,0 +1,159 @@ +// +// serial_port_base.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SERIAL_PORT_BASE_HPP +#define BOOST_ASIO_SERIAL_PORT_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +# include +#endif +#include +#include + +#include + +#if defined(GENERATING_DOCUMENTATION) +# define BOOST_ASIO_OPTION_STORAGE implementation_defined +#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) +# define BOOST_ASIO_OPTION_STORAGE DCB +#else +# define BOOST_ASIO_OPTION_STORAGE termios +#endif + +namespace boost { +namespace asio { + +/// The serial_port_base class is used as a base for the basic_serial_port class +/// template so that we have a common place to define the serial port options. +class serial_port_base +{ +public: + /// Serial port option to permit changing the baud rate. + /** + * Implements changing the baud rate for a given serial port. + */ + class baud_rate + { + public: + explicit baud_rate(unsigned int rate = 0); + unsigned int value() const; + boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec) const; + boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec); + private: + unsigned int value_; + }; + + /// Serial port option to permit changing the flow control. + /** + * Implements changing the flow control for a given serial port. + */ + class flow_control + { + public: + enum type { none, software, hardware }; + explicit flow_control(type t = none); + type value() const; + boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec) const; + boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec); + private: + type value_; + }; + + /// Serial port option to permit changing the parity. + /** + * Implements changing the parity for a given serial port. + */ + class parity + { + public: + enum type { none, odd, even }; + explicit parity(type t = none); + type value() const; + boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec) const; + boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec); + private: + type value_; + }; + + /// Serial port option to permit changing the number of stop bits. + /** + * Implements changing the number of stop bits for a given serial port. + */ + class stop_bits + { + public: + enum type { one, onepointfive, two }; + explicit stop_bits(type t = one); + type value() const; + boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec) const; + boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec); + private: + type value_; + }; + + /// Serial port option to permit changing the character size. + /** + * Implements changing the character size for a given serial port. + */ + class character_size + { + public: + explicit character_size(unsigned int t = 8); + unsigned int value() const; + boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec) const; + boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage, + boost::system::error_code& ec); + private: + unsigned int value_; + }; + +protected: + /// Protected destructor to prevent deletion through this type. + ~serial_port_base() + { + } + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +private: + // Workaround to enable the empty base optimisation with Borland C++. + char dummy_; +#endif +}; + +} // namespace asio +} // namespace boost + +#include + +#undef BOOST_ASIO_OPTION_STORAGE + +#include + +#endif // BOOST_ASIO_SERIAL_PORT_BASE_HPP diff --git a/win32/include/boost/asio/serial_port_service.hpp b/win32/include/boost/asio/serial_port_service.hpp new file mode 100755 index 000000000..3769741e5 --- /dev/null +++ b/win32/include/boost/asio/serial_port_service.hpp @@ -0,0 +1,224 @@ +// +// serial_port_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SERIAL_PORT_SERVICE_HPP +#define BOOST_ASIO_SERIAL_PORT_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#if !defined(BOOST_ASIO_DISABLE_SERIAL_PORT) +# if defined(BOOST_ASIO_HAS_IOCP) \ + || !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) +# define BOOST_ASIO_HAS_SERIAL_PORT 1 +# endif // defined(BOOST_ASIO_HAS_IOCP) +#endif // !defined(BOOST_ASIO_DISABLE_STREAM_HANDLE) + +#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { + +/// Default service implementation for a serial port. +class serial_port_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + +private: + // The type of the platform-specific implementation. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef detail::win_iocp_serial_port_service service_impl_type; +#elif defined(BOOST_ASIO_HAS_EPOLL) + typedef detail::reactive_serial_port_service< + detail::epoll_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_KQUEUE) + typedef detail::reactive_serial_port_service< + detail::kqueue_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_DEV_POLL) + typedef detail::reactive_serial_port_service< + detail::dev_poll_reactor > service_impl_type; +#else + typedef detail::reactive_serial_port_service< + detail::select_reactor > service_impl_type; +#endif + +public: + /// The type of a serial port implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef service_impl_type::implementation_type implementation_type; +#endif + + /// The native handle type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef service_impl_type::native_type native_type; +#endif + + /// Construct a new serial port service for the specified io_service. + explicit serial_port_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new serial port implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a serial port implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Open a serial port. + boost::system::error_code open(implementation_type& impl, + const std::string& device, boost::system::error_code& ec) + { + return service_impl_.open(impl, device, ec); + } + + /// Assign an existing native handle to a serial port. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_handle, boost::system::error_code& ec) + { + return service_impl_.assign(impl, native_handle, ec); + } + + /// Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a serial port implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native handle implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the handle. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Set a serial port option. + template + boost::system::error_code set_option(implementation_type& impl, + const SettableSerialPortOption& option, boost::system::error_code& ec) + { + return service_impl_.set_option(impl, option, ec); + } + + /// Get a serial port option. + template + boost::system::error_code get_option(const implementation_type& impl, + GettableSerialPortOption& option, boost::system::error_code& ec) const + { + return service_impl_.get_option(impl, option, ec); + } + + /// Send a break sequence to the serial port. + boost::system::error_code send_break(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.send_break(impl, ec); + } + + /// Write the given data to the stream. + template + std::size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.write_some(impl, buffers, ec); + } + + /// Start an asynchronous write. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, WriteHandler handler) + { + service_impl_.async_write_some(impl, buffers, handler); + } + + /// Read some data from the stream. + template + std::size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.read_some(impl, buffers, ec); + } + + /// Start an asynchronous read. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, ReadHandler handler) + { + service_impl_.async_read_some(impl, buffers, handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_SERIAL_PORT_SERVICE_HPP diff --git a/win32/include/boost/asio/socket_acceptor_service.hpp b/win32/include/boost/asio/socket_acceptor_service.hpp new file mode 100755 index 000000000..3b435b282 --- /dev/null +++ b/win32/include/boost/asio/socket_acceptor_service.hpp @@ -0,0 +1,227 @@ +// +// socket_acceptor_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SOCKET_ACCEPTOR_SERVICE_HPP +#define BOOST_ASIO_SOCKET_ACCEPTOR_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Default service implementation for a socket acceptor. +template +class socket_acceptor_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base > +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename protocol_type::endpoint endpoint_type; + +private: + // The type of the platform-specific implementation. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef detail::win_iocp_socket_service service_impl_type; +#elif defined(BOOST_ASIO_HAS_EPOLL) + typedef detail::reactive_socket_service< + Protocol, detail::epoll_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_KQUEUE) + typedef detail::reactive_socket_service< + Protocol, detail::kqueue_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_DEV_POLL) + typedef detail::reactive_socket_service< + Protocol, detail::dev_poll_reactor > service_impl_type; +#else + typedef detail::reactive_socket_service< + Protocol, detail::select_reactor > service_impl_type; +#endif + +public: + /// The native type of the socket acceptor. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef typename service_impl_type::implementation_type implementation_type; +#endif + + /// The native acceptor type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef typename service_impl_type::native_type native_type; +#endif + + /// Construct a new socket acceptor service for the specified io_service. + explicit socket_acceptor_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + socket_acceptor_service >(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new socket acceptor implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a socket acceptor implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Open a new socket acceptor implementation. + boost::system::error_code open(implementation_type& impl, + const protocol_type& protocol, boost::system::error_code& ec) + { + return service_impl_.open(impl, protocol, ec); + } + + /// Assign an existing native acceptor to a socket acceptor. + boost::system::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_type& native_acceptor, + boost::system::error_code& ec) + { + return service_impl_.assign(impl, protocol, native_acceptor, ec); + } + + /// Determine whether the acceptor is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Cancel all asynchronous operations associated with the acceptor. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Bind the socket acceptor to the specified local endpoint. + boost::system::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, boost::system::error_code& ec) + { + return service_impl_.bind(impl, endpoint, ec); + } + + /// Place the socket acceptor into the state where it will listen for new + /// connections. + boost::system::error_code listen(implementation_type& impl, int backlog, + boost::system::error_code& ec) + { + return service_impl_.listen(impl, backlog, ec); + } + + /// Close a socket acceptor implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native acceptor implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Set a socket option. + template + boost::system::error_code set_option(implementation_type& impl, + const SettableSocketOption& option, boost::system::error_code& ec) + { + return service_impl_.set_option(impl, option, ec); + } + + /// Get a socket option. + template + boost::system::error_code get_option(const implementation_type& impl, + GettableSocketOption& option, boost::system::error_code& ec) const + { + return service_impl_.get_option(impl, option, ec); + } + + /// Perform an IO control command on the socket. + template + boost::system::error_code io_control(implementation_type& impl, + IoControlCommand& command, boost::system::error_code& ec) + { + return service_impl_.io_control(impl, command, ec); + } + + /// Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.local_endpoint(impl, ec); + } + + /// Accept a new connection. + template + boost::system::error_code accept(implementation_type& impl, + basic_socket& peer, + endpoint_type* peer_endpoint, boost::system::error_code& ec) + { + return service_impl_.accept(impl, peer, peer_endpoint, ec); + } + + /// Start an asynchronous accept. + template + void async_accept(implementation_type& impl, + basic_socket& peer, + endpoint_type* peer_endpoint, AcceptHandler handler) + { + service_impl_.async_accept(impl, peer, peer_endpoint, handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SOCKET_ACCEPTOR_SERVICE_HPP diff --git a/win32/include/boost/asio/socket_base.hpp b/win32/include/boost/asio/socket_base.hpp new file mode 100755 index 000000000..fec77c852 --- /dev/null +++ b/win32/include/boost/asio/socket_base.hpp @@ -0,0 +1,517 @@ +// +// socket_base.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SOCKET_BASE_HPP +#define BOOST_ASIO_SOCKET_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { +namespace asio { + +/// The socket_base class is used as a base for the basic_stream_socket and +/// basic_datagram_socket class templates so that we have a common place to +/// define the shutdown_type and enum. +class socket_base +{ +public: + /// Different ways a socket may be shutdown. + enum shutdown_type + { +#if defined(GENERATING_DOCUMENTATION) + /// Shutdown the receive side of the socket. + shutdown_receive = implementation_defined, + + /// Shutdown the send side of the socket. + shutdown_send = implementation_defined, + + /// Shutdown both send and receive on the socket. + shutdown_both = implementation_defined +#else + shutdown_receive = boost::asio::detail::shutdown_receive, + shutdown_send = boost::asio::detail::shutdown_send, + shutdown_both = boost::asio::detail::shutdown_both +#endif + }; + + /// Bitmask type for flags that can be passed to send and receive operations. + typedef int message_flags; + +#if defined(GENERATING_DOCUMENTATION) + /// Peek at incoming data without removing it from the input queue. + static const int message_peek = implementation_defined; + + /// Process out-of-band data. + static const int message_out_of_band = implementation_defined; + + /// Specify that the data should not be subject to routing. + static const int message_do_not_route = implementation_defined; +#else + BOOST_STATIC_CONSTANT(int, + message_peek = boost::asio::detail::message_peek); + BOOST_STATIC_CONSTANT(int, + message_out_of_band = boost::asio::detail::message_out_of_band); + BOOST_STATIC_CONSTANT(int, + message_do_not_route = boost::asio::detail::message_do_not_route); +#endif + + /// Socket option to permit sending of broadcast messages. + /** + * Implements the SOL_SOCKET/SO_BROADCAST socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::udp::socket socket(io_service); + * ... + * boost::asio::socket_base::broadcast option(true); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::udp::socket socket(io_service); + * ... + * boost::asio::socket_base::broadcast option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Boolean_Socket_Option. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined broadcast; +#else + typedef boost::asio::detail::socket_option::boolean< + SOL_SOCKET, SO_BROADCAST> broadcast; +#endif + + /// Socket option to enable socket-level debugging. + /** + * Implements the SOL_SOCKET/SO_DEBUG socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::debug option(true); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::debug option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Boolean_Socket_Option. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined debug; +#else + typedef boost::asio::detail::socket_option::boolean< + SOL_SOCKET, SO_DEBUG> debug; +#endif + + /// Socket option to prevent routing, use local interfaces only. + /** + * Implements the SOL_SOCKET/SO_DONTROUTE socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::udp::socket socket(io_service); + * ... + * boost::asio::socket_base::do_not_route option(true); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::udp::socket socket(io_service); + * ... + * boost::asio::socket_base::do_not_route option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Boolean_Socket_Option. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined do_not_route; +#else + typedef boost::asio::detail::socket_option::boolean< + SOL_SOCKET, SO_DONTROUTE> do_not_route; +#endif + + /// Socket option to send keep-alives. + /** + * Implements the SOL_SOCKET/SO_KEEPALIVE socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::keep_alive option(true); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::keep_alive option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Boolean_Socket_Option. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined keep_alive; +#else + typedef boost::asio::detail::socket_option::boolean< + SOL_SOCKET, SO_KEEPALIVE> keep_alive; +#endif + + /// Socket option for the send buffer size of a socket. + /** + * Implements the SOL_SOCKET/SO_SNDBUF socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::send_buffer_size option(8192); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::send_buffer_size option; + * socket.get_option(option); + * int size = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Integer_Socket_Option. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined send_buffer_size; +#else + typedef boost::asio::detail::socket_option::integer< + SOL_SOCKET, SO_SNDBUF> send_buffer_size; +#endif + + /// Socket option for the send low watermark. + /** + * Implements the SOL_SOCKET/SO_SNDLOWAT socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::send_low_watermark option(1024); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::send_low_watermark option; + * socket.get_option(option); + * int size = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Integer_Socket_Option. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined send_low_watermark; +#else + typedef boost::asio::detail::socket_option::integer< + SOL_SOCKET, SO_SNDLOWAT> send_low_watermark; +#endif + + /// Socket option for the receive buffer size of a socket. + /** + * Implements the SOL_SOCKET/SO_RCVBUF socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::receive_buffer_size option(8192); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::receive_buffer_size option; + * socket.get_option(option); + * int size = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Integer_Socket_Option. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined receive_buffer_size; +#else + typedef boost::asio::detail::socket_option::integer< + SOL_SOCKET, SO_RCVBUF> receive_buffer_size; +#endif + + /// Socket option for the receive low watermark. + /** + * Implements the SOL_SOCKET/SO_RCVLOWAT socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::receive_low_watermark option(1024); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::receive_low_watermark option; + * socket.get_option(option); + * int size = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Integer_Socket_Option. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined receive_low_watermark; +#else + typedef boost::asio::detail::socket_option::integer< + SOL_SOCKET, SO_RCVLOWAT> receive_low_watermark; +#endif + + /// Socket option to allow the socket to be bound to an address that is + /// already in use. + /** + * Implements the SOL_SOCKET/SO_REUSEADDR socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::socket_base::reuse_address option(true); + * acceptor.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::socket_base::reuse_address option; + * acceptor.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Boolean_Socket_Option. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined reuse_address; +#else + typedef boost::asio::detail::socket_option::boolean< + SOL_SOCKET, SO_REUSEADDR> reuse_address; +#endif + + /// Socket option to specify whether the socket lingers on close if unsent + /// data is present. + /** + * Implements the SOL_SOCKET/SO_LINGER socket option. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::linger option(true, 30); + * socket.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::linger option; + * socket.get_option(option); + * bool is_set = option.enabled(); + * unsigned short timeout = option.timeout(); + * @endcode + * + * @par Concepts: + * Socket_Option, Linger_Socket_Option. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined linger; +#else + typedef boost::asio::detail::socket_option::linger< + SOL_SOCKET, SO_LINGER> linger; +#endif + + /// Socket option to report aborted connections on accept. + /** + * Implements a custom socket option that determines whether or not an accept + * operation is permitted to fail with boost::asio::error::connection_aborted. + * By default the option is false. + * + * @par Examples + * Setting the option: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::socket_base::enable_connection_aborted option(true); + * acceptor.set_option(option); + * @endcode + * + * @par + * Getting the current option value: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::socket_base::enable_connection_aborted option; + * acceptor.get_option(option); + * bool is_set = option.value(); + * @endcode + * + * @par Concepts: + * Socket_Option, Boolean_Socket_Option. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined enable_connection_aborted; +#else + typedef boost::asio::detail::socket_option::boolean< + boost::asio::detail::custom_socket_option_level, + boost::asio::detail::enable_connection_aborted_option> + enable_connection_aborted; +#endif + + /// IO control command to set the blocking mode of the socket. + /** + * Implements the FIONBIO IO control command. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::non_blocking_io command(true); + * socket.io_control(command); + * @endcode + * + * @par Concepts: + * IO_Control_Command, Boolean_IO_Control_Command. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined non_blocking_io; +#else + typedef boost::asio::detail::io_control::non_blocking_io non_blocking_io; +#endif + + /// IO control command to get the amount of data that can be read without + /// blocking. + /** + * Implements the FIONREAD IO control command. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::socket_base::bytes_readable command(true); + * socket.io_control(command); + * std::size_t bytes_readable = command.get(); + * @endcode + * + * @par Concepts: + * IO_Control_Command, Size_IO_Control_Command. + */ +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined bytes_readable; +#else + typedef boost::asio::detail::io_control::bytes_readable bytes_readable; +#endif + + /// The maximum length of the queue of pending incoming connections. +#if defined(GENERATING_DOCUMENTATION) + static const int max_connections = implementation_defined; +#else + BOOST_STATIC_CONSTANT(int, max_connections = SOMAXCONN); +#endif + +protected: + /// Protected destructor to prevent deletion through this type. + ~socket_base() + { + } + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +private: + // Workaround to enable the empty base optimisation with Borland C++. + char dummy_; +#endif +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SOCKET_BASE_HPP diff --git a/win32/include/boost/asio/ssl.hpp b/win32/include/boost/asio/ssl.hpp new file mode 100755 index 000000000..97c61c95d --- /dev/null +++ b/win32/include/boost/asio/ssl.hpp @@ -0,0 +1,26 @@ +// +// ssl.hpp +// ~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SSL_HPP +#define BOOST_ASIO_SSL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include +#include +#include +#include +#include +#include +#include + +#endif // BOOST_ASIO_SSL_HPP diff --git a/win32/include/boost/asio/ssl/basic_context.hpp b/win32/include/boost/asio/ssl/basic_context.hpp new file mode 100755 index 000000000..d452e24fb --- /dev/null +++ b/win32/include/boost/asio/ssl/basic_context.hpp @@ -0,0 +1,436 @@ +// +// basic_context.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com +// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SSL_BASIC_CONTEXT_HPP +#define BOOST_ASIO_SSL_BASIC_CONTEXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ssl { + +/// SSL context. +template +class basic_context + : public context_base, + private boost::noncopyable +{ +public: + /// The type of the service that will be used to provide context operations. + typedef Service service_type; + + /// The native implementation type of the locking dispatcher. + typedef typename service_type::impl_type impl_type; + + /// Constructor. + basic_context(boost::asio::io_service& io_service, method m) + : service_(boost::asio::use_service(io_service)), + impl_(service_.null()) + { + service_.create(impl_, m); + } + + /// Destructor. + ~basic_context() + { + service_.destroy(impl_); + } + + /// Get the underlying implementation in the native type. + /** + * This function may be used to obtain the underlying implementation of the + * context. This is intended to allow access to context functionality that is + * not otherwise provided. + */ + impl_type impl() + { + return impl_; + } + + /// Set options on the context. + /** + * This function may be used to configure the SSL options used by the context. + * + * @param o A bitmask of options. The available option values are defined in + * the context_base class. The options are bitwise-ored with any existing + * value for the options. + * + * @throws boost::system::system_error Thrown on failure. + */ + void set_options(options o) + { + boost::system::error_code ec; + service_.set_options(impl_, o, ec); + boost::asio::detail::throw_error(ec); + } + + /// Set options on the context. + /** + * This function may be used to configure the SSL options used by the context. + * + * @param o A bitmask of options. The available option values are defined in + * the context_base class. The options are bitwise-ored with any existing + * value for the options. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code set_options(options o, + boost::system::error_code& ec) + { + return service_.set_options(impl_, o, ec); + } + + /// Set the peer verification mode. + /** + * This function may be used to configure the peer verification mode used by + * the context. + * + * @param v A bitmask of peer verification modes. The available verify_mode + * values are defined in the context_base class. + * + * @throws boost::system::system_error Thrown on failure. + */ + void set_verify_mode(verify_mode v) + { + boost::system::error_code ec; + service_.set_verify_mode(impl_, v, ec); + boost::asio::detail::throw_error(ec); + } + + /// Set the peer verification mode. + /** + * This function may be used to configure the peer verification mode used by + * the context. + * + * @param v A bitmask of peer verification modes. The available verify_mode + * values are defined in the context_base class. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code set_verify_mode(verify_mode v, + boost::system::error_code& ec) + { + return service_.set_verify_mode(impl_, v, ec); + } + + /// Load a certification authority file for performing verification. + /** + * This function is used to load one or more trusted certification authorities + * from a file. + * + * @param filename The name of a file containing certification authority + * certificates in PEM format. + * + * @throws boost::system::system_error Thrown on failure. + */ + void load_verify_file(const std::string& filename) + { + boost::system::error_code ec; + service_.load_verify_file(impl_, filename, ec); + boost::asio::detail::throw_error(ec); + } + + /// Load a certification authority file for performing verification. + /** + * This function is used to load the certificates for one or more trusted + * certification authorities from a file. + * + * @param filename The name of a file containing certification authority + * certificates in PEM format. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code load_verify_file(const std::string& filename, + boost::system::error_code& ec) + { + return service_.load_verify_file(impl_, filename, ec); + } + + /// Add a directory containing certificate authority files to be used for + /// performing verification. + /** + * This function is used to specify the name of a directory containing + * certification authority certificates. Each file in the directory must + * contain a single certificate. The files must be named using the subject + * name's hash and an extension of ".0". + * + * @param path The name of a directory containing the certificates. + * + * @throws boost::system::system_error Thrown on failure. + */ + void add_verify_path(const std::string& path) + { + boost::system::error_code ec; + service_.add_verify_path(impl_, path, ec); + boost::asio::detail::throw_error(ec); + } + + /// Add a directory containing certificate authority files to be used for + /// performing verification. + /** + * This function is used to specify the name of a directory containing + * certification authority certificates. Each file in the directory must + * contain a single certificate. The files must be named using the subject + * name's hash and an extension of ".0". + * + * @param path The name of a directory containing the certificates. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code add_verify_path(const std::string& path, + boost::system::error_code& ec) + { + return service_.add_verify_path(impl_, path, ec); + } + + /// Use a certificate from a file. + /** + * This function is used to load a certificate into the context from a file. + * + * @param filename The name of the file containing the certificate. + * + * @param format The file format (ASN.1 or PEM). + * + * @throws boost::system::system_error Thrown on failure. + */ + void use_certificate_file(const std::string& filename, file_format format) + { + boost::system::error_code ec; + service_.use_certificate_file(impl_, filename, format, ec); + boost::asio::detail::throw_error(ec); + } + + /// Use a certificate from a file. + /** + * This function is used to load a certificate into the context from a file. + * + * @param filename The name of the file containing the certificate. + * + * @param format The file format (ASN.1 or PEM). + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code use_certificate_file(const std::string& filename, + file_format format, boost::system::error_code& ec) + { + return service_.use_certificate_file(impl_, filename, format, ec); + } + + /// Use a certificate chain from a file. + /** + * This function is used to load a certificate chain into the context from a + * file. + * + * @param filename The name of the file containing the certificate. The file + * must use the PEM format. + * + * @throws boost::system::system_error Thrown on failure. + */ + void use_certificate_chain_file(const std::string& filename) + { + boost::system::error_code ec; + service_.use_certificate_chain_file(impl_, filename, ec); + boost::asio::detail::throw_error(ec); + } + + /// Use a certificate chain from a file. + /** + * This function is used to load a certificate chain into the context from a + * file. + * + * @param filename The name of the file containing the certificate. The file + * must use the PEM format. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code use_certificate_chain_file( + const std::string& filename, boost::system::error_code& ec) + { + return service_.use_certificate_chain_file(impl_, filename, ec); + } + + /// Use a private key from a file. + /** + * This function is used to load a private key into the context from a file. + * + * @param filename The name of the file containing the private key. + * + * @param format The file format (ASN.1 or PEM). + * + * @throws boost::system::system_error Thrown on failure. + */ + void use_private_key_file(const std::string& filename, file_format format) + { + boost::system::error_code ec; + service_.use_private_key_file(impl_, filename, format, ec); + boost::asio::detail::throw_error(ec); + } + + /// Use a private key from a file. + /** + * This function is used to load a private key into the context from a file. + * + * @param filename The name of the file containing the private key. + * + * @param format The file format (ASN.1 or PEM). + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code use_private_key_file(const std::string& filename, + file_format format, boost::system::error_code& ec) + { + return service_.use_private_key_file(impl_, filename, format, ec); + } + + /// Use an RSA private key from a file. + /** + * This function is used to load an RSA private key into the context from a + * file. + * + * @param filename The name of the file containing the RSA private key. + * + * @param format The file format (ASN.1 or PEM). + * + * @throws boost::system::system_error Thrown on failure. + */ + void use_rsa_private_key_file(const std::string& filename, file_format format) + { + boost::system::error_code ec; + service_.use_rsa_private_key_file(impl_, filename, format, ec); + boost::asio::detail::throw_error(ec); + } + + /// Use an RSA private key from a file. + /** + * This function is used to load an RSA private key into the context from a + * file. + * + * @param filename The name of the file containing the RSA private key. + * + * @param format The file format (ASN.1 or PEM). + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code use_rsa_private_key_file( + const std::string& filename, file_format format, + boost::system::error_code& ec) + { + return service_.use_rsa_private_key_file(impl_, filename, format, ec); + } + + /// Use the specified file to obtain the temporary Diffie-Hellman parameters. + /** + * This function is used to load Diffie-Hellman parameters into the context + * from a file. + * + * @param filename The name of the file containing the Diffie-Hellman + * parameters. The file must use the PEM format. + * + * @throws boost::system::system_error Thrown on failure. + */ + void use_tmp_dh_file(const std::string& filename) + { + boost::system::error_code ec; + service_.use_tmp_dh_file(impl_, filename, ec); + boost::asio::detail::throw_error(ec); + } + + /// Use the specified file to obtain the temporary Diffie-Hellman parameters. + /** + * This function is used to load Diffie-Hellman parameters into the context + * from a file. + * + * @param filename The name of the file containing the Diffie-Hellman + * parameters. The file must use the PEM format. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code use_tmp_dh_file(const std::string& filename, + boost::system::error_code& ec) + { + return service_.use_tmp_dh_file(impl_, filename, ec); + } + + /// Set the password callback. + /** + * This function is used to specify a callback function to obtain password + * information about an encrypted key in PEM format. + * + * @param callback The function object to be used for obtaining the password. + * The function signature of the handler must be: + * @code std::string password_callback( + * std::size_t max_length, // The maximum size for a password. + * password_purpose purpose // Whether password is for reading or writing. + * ); @endcode + * The return value of the callback is a string containing the password. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + void set_password_callback(PasswordCallback callback) + { + boost::system::error_code ec; + service_.set_password_callback(impl_, callback, ec); + boost::asio::detail::throw_error(ec); + } + + /// Set the password callback. + /** + * This function is used to specify a callback function to obtain password + * information about an encrypted key in PEM format. + * + * @param callback The function object to be used for obtaining the password. + * The function signature of the handler must be: + * @code std::string password_callback( + * std::size_t max_length, // The maximum size for a password. + * password_purpose purpose // Whether password is for reading or writing. + * ); @endcode + * The return value of the callback is a string containing the password. + * + * @param ec Set to indicate what error occurred, if any. + */ + template + boost::system::error_code set_password_callback(PasswordCallback callback, + boost::system::error_code& ec) + { + return service_.set_password_callback(impl_, callback, ec); + } + +private: + /// The backend service implementation. + service_type& service_; + + /// The underlying native implementation. + impl_type impl_; +}; + +} // namespace ssl +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SSL_BASIC_CONTEXT_HPP diff --git a/win32/include/boost/asio/ssl/context.hpp b/win32/include/boost/asio/ssl/context.hpp new file mode 100755 index 000000000..361827750 --- /dev/null +++ b/win32/include/boost/asio/ssl/context.hpp @@ -0,0 +1,37 @@ +// +// context.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com +// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SSL_CONTEXT_HPP +#define BOOST_ASIO_SSL_CONTEXT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include + +namespace boost { +namespace asio { +namespace ssl { + +/// Typedef for the typical usage of context. +typedef basic_context context; + +} // namespace ssl +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SSL_CONTEXT_HPP diff --git a/win32/include/boost/asio/ssl/context_base.hpp b/win32/include/boost/asio/ssl/context_base.hpp new file mode 100755 index 000000000..b03e8fd82 --- /dev/null +++ b/win32/include/boost/asio/ssl/context_base.hpp @@ -0,0 +1,166 @@ +// +// context_base.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SSL_CONTEXT_BASE_HPP +#define BOOST_ASIO_SSL_CONTEXT_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace ssl { + +/// The context_base class is used as a base for the basic_context class +/// template so that we have a common place to define various enums. +class context_base +{ +public: + /// Different methods supported by a context. + enum method + { + /// Generic SSL version 2. + sslv2, + + /// SSL version 2 client. + sslv2_client, + + /// SSL version 2 server. + sslv2_server, + + /// Generic SSL version 3. + sslv3, + + /// SSL version 3 client. + sslv3_client, + + /// SSL version 3 server. + sslv3_server, + + /// Generic TLS version 1. + tlsv1, + + /// TLS version 1 client. + tlsv1_client, + + /// TLS version 1 server. + tlsv1_server, + + /// Generic SSL/TLS. + sslv23, + + /// SSL/TLS client. + sslv23_client, + + /// SSL/TLS server. + sslv23_server + }; + + /// Bitmask type for SSL options. + typedef int options; + +#if defined(GENERATING_DOCUMENTATION) + /// Implement various bug workarounds. + static const int default_workarounds = implementation_defined; + + /// Always create a new key when using tmp_dh parameters. + static const int single_dh_use = implementation_defined; + + /// Disable SSL v2. + static const int no_sslv2 = implementation_defined; + + /// Disable SSL v3. + static const int no_sslv3 = implementation_defined; + + /// Disable TLS v1. + static const int no_tlsv1 = implementation_defined; +#else + BOOST_STATIC_CONSTANT(int, default_workarounds = SSL_OP_ALL); + BOOST_STATIC_CONSTANT(int, single_dh_use = SSL_OP_SINGLE_DH_USE); + BOOST_STATIC_CONSTANT(int, no_sslv2 = SSL_OP_NO_SSLv2); + BOOST_STATIC_CONSTANT(int, no_sslv3 = SSL_OP_NO_SSLv3); + BOOST_STATIC_CONSTANT(int, no_tlsv1 = SSL_OP_NO_TLSv1); +#endif + + /// File format types. + enum file_format + { + /// ASN.1 file. + asn1, + + /// PEM file. + pem + }; + + /// Bitmask type for peer verification. + typedef int verify_mode; + +#if defined(GENERATING_DOCUMENTATION) + /// No verification. + static const int verify_none = implementation_defined; + + /// Verify the peer. + static const int verify_peer = implementation_defined; + + /// Fail verification if the peer has no certificate. Ignored unless + /// verify_peer is set. + static const int verify_fail_if_no_peer_cert = implementation_defined; + + /// Do not request client certificate on renegotiation. Ignored unless + /// verify_peer is set. + static const int verify_client_once = implementation_defined; +#else + BOOST_STATIC_CONSTANT(int, verify_none = SSL_VERIFY_NONE); + BOOST_STATIC_CONSTANT(int, verify_peer = SSL_VERIFY_PEER); + BOOST_STATIC_CONSTANT(int, + verify_fail_if_no_peer_cert = SSL_VERIFY_FAIL_IF_NO_PEER_CERT); + BOOST_STATIC_CONSTANT(int, verify_client_once = SSL_VERIFY_CLIENT_ONCE); +#endif + + /// Purpose of PEM password. + enum password_purpose + { + /// The password is needed for reading/decryption. + for_reading, + + /// The password is needed for writing/encryption. + for_writing + }; + +protected: + /// Protected destructor to prevent deletion through this type. + ~context_base() + { + } + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +private: + // Workaround to enable the empty base optimisation with Borland C++. + char dummy_; +#endif +}; + +} // namespace ssl +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SSL_CONTEXT_BASE_HPP diff --git a/win32/include/boost/asio/ssl/context_service.hpp b/win32/include/boost/asio/ssl/context_service.hpp new file mode 100755 index 000000000..4ef53c0e6 --- /dev/null +++ b/win32/include/boost/asio/ssl/context_service.hpp @@ -0,0 +1,177 @@ +// +// context_service.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com +// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SSL_CONTEXT_SERVICE_HPP +#define BOOST_ASIO_SSL_CONTEXT_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ssl { + +/// Default service implementation for a context. +class context_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base +#endif +{ +private: + // The type of the platform-specific implementation. + typedef detail::openssl_context_service service_impl_type; + +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + + /// The type of the context. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined impl_type; +#else + typedef service_impl_type::impl_type impl_type; +#endif + + /// Constructor. + explicit context_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Return a null context implementation. + impl_type null() const + { + return service_impl_.null(); + } + + /// Create a new context implementation. + void create(impl_type& impl, context_base::method m) + { + service_impl_.create(impl, m); + } + + /// Destroy a context implementation. + void destroy(impl_type& impl) + { + service_impl_.destroy(impl); + } + + /// Set options on the context. + boost::system::error_code set_options(impl_type& impl, + context_base::options o, boost::system::error_code& ec) + { + return service_impl_.set_options(impl, o, ec); + } + + /// Set peer verification mode. + boost::system::error_code set_verify_mode(impl_type& impl, + context_base::verify_mode v, boost::system::error_code& ec) + { + return service_impl_.set_verify_mode(impl, v, ec); + } + + /// Load a certification authority file for performing verification. + boost::system::error_code load_verify_file(impl_type& impl, + const std::string& filename, boost::system::error_code& ec) + { + return service_impl_.load_verify_file(impl, filename, ec); + } + + /// Add a directory containing certification authority files to be used for + /// performing verification. + boost::system::error_code add_verify_path(impl_type& impl, + const std::string& path, boost::system::error_code& ec) + { + return service_impl_.add_verify_path(impl, path, ec); + } + + /// Use a certificate from a file. + boost::system::error_code use_certificate_file(impl_type& impl, + const std::string& filename, context_base::file_format format, + boost::system::error_code& ec) + { + return service_impl_.use_certificate_file(impl, filename, format, ec); + } + + /// Use a certificate chain from a file. + boost::system::error_code use_certificate_chain_file(impl_type& impl, + const std::string& filename, boost::system::error_code& ec) + { + return service_impl_.use_certificate_chain_file(impl, filename, ec); + } + + /// Use a private key from a file. + boost::system::error_code use_private_key_file(impl_type& impl, + const std::string& filename, context_base::file_format format, + boost::system::error_code& ec) + { + return service_impl_.use_private_key_file(impl, filename, format, ec); + } + + /// Use an RSA private key from a file. + boost::system::error_code use_rsa_private_key_file(impl_type& impl, + const std::string& filename, context_base::file_format format, + boost::system::error_code& ec) + { + return service_impl_.use_rsa_private_key_file(impl, filename, format, ec); + } + + /// Use the specified file to obtain the temporary Diffie-Hellman parameters. + boost::system::error_code use_tmp_dh_file(impl_type& impl, + const std::string& filename, boost::system::error_code& ec) + { + return service_impl_.use_tmp_dh_file(impl, filename, ec); + } + + /// Set the password callback. + template + boost::system::error_code set_password_callback(impl_type& impl, + PasswordCallback callback, boost::system::error_code& ec) + { + return service_impl_.set_password_callback(impl, callback, ec); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace ssl +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SSL_CONTEXT_SERVICE_HPP diff --git a/win32/include/boost/asio/ssl/detail/openssl_context_service.hpp b/win32/include/boost/asio/ssl/detail/openssl_context_service.hpp new file mode 100755 index 000000000..142c2dad1 --- /dev/null +++ b/win32/include/boost/asio/ssl/detail/openssl_context_service.hpp @@ -0,0 +1,381 @@ +// +// openssl_context_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com +// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP +#define BOOST_ASIO_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +class openssl_context_service + : public boost::asio::detail::service_base +{ +public: + // The native type of the context. + typedef ::SSL_CTX* impl_type; + + // The type for the password callback function object. + typedef boost::function password_callback_type; + + // Constructor. + openssl_context_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Return a null context implementation. + static impl_type null() + { + return 0; + } + + // Create a new context implementation. + void create(impl_type& impl, context_base::method m) + { + ::SSL_METHOD* ssl_method = 0; + switch (m) + { + case context_base::sslv2: + ssl_method = ::SSLv2_method(); + break; + case context_base::sslv2_client: + ssl_method = ::SSLv2_client_method(); + break; + case context_base::sslv2_server: + ssl_method = ::SSLv2_server_method(); + break; + case context_base::sslv3: + ssl_method = ::SSLv3_method(); + break; + case context_base::sslv3_client: + ssl_method = ::SSLv3_client_method(); + break; + case context_base::sslv3_server: + ssl_method = ::SSLv3_server_method(); + break; + case context_base::tlsv1: + ssl_method = ::TLSv1_method(); + break; + case context_base::tlsv1_client: + ssl_method = ::TLSv1_client_method(); + break; + case context_base::tlsv1_server: + ssl_method = ::TLSv1_server_method(); + break; + case context_base::sslv23: + ssl_method = ::SSLv23_method(); + break; + case context_base::sslv23_client: + ssl_method = ::SSLv23_client_method(); + break; + case context_base::sslv23_server: + ssl_method = ::SSLv23_server_method(); + break; + default: + break; + } + impl = ::SSL_CTX_new(ssl_method); + } + + // Destroy a context implementation. + void destroy(impl_type& impl) + { + if (impl != null()) + { + if (impl->default_passwd_callback_userdata) + { + password_callback_type* callback = + static_cast( + impl->default_passwd_callback_userdata); + delete callback; + impl->default_passwd_callback_userdata = 0; + } + + ::SSL_CTX_free(impl); + impl = null(); + } + } + + // Set options on the context. + boost::system::error_code set_options(impl_type& impl, + context_base::options o, boost::system::error_code& ec) + { + ::SSL_CTX_set_options(impl, o); + + ec = boost::system::error_code(); + return ec; + } + + // Set peer verification mode. + boost::system::error_code set_verify_mode(impl_type& impl, + context_base::verify_mode v, boost::system::error_code& ec) + { + ::SSL_CTX_set_verify(impl, v, 0); + + ec = boost::system::error_code(); + return ec; + } + + // Load a certification authority file for performing verification. + boost::system::error_code load_verify_file(impl_type& impl, + const std::string& filename, boost::system::error_code& ec) + { + if (::SSL_CTX_load_verify_locations(impl, filename.c_str(), 0) != 1) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Add a directory containing certification authority files to be used for + // performing verification. + boost::system::error_code add_verify_path(impl_type& impl, + const std::string& path, boost::system::error_code& ec) + { + if (::SSL_CTX_load_verify_locations(impl, 0, path.c_str()) != 1) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Use a certificate from a file. + boost::system::error_code use_certificate_file(impl_type& impl, + const std::string& filename, context_base::file_format format, + boost::system::error_code& ec) + { + int file_type; + switch (format) + { + case context_base::asn1: + file_type = SSL_FILETYPE_ASN1; + break; + case context_base::pem: + file_type = SSL_FILETYPE_PEM; + break; + default: + { + ec = boost::asio::error::invalid_argument; + return ec; + } + } + + if (::SSL_CTX_use_certificate_file(impl, filename.c_str(), file_type) != 1) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Use a certificate chain from a file. + boost::system::error_code use_certificate_chain_file(impl_type& impl, + const std::string& filename, boost::system::error_code& ec) + { + if (::SSL_CTX_use_certificate_chain_file(impl, filename.c_str()) != 1) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Use a private key from a file. + boost::system::error_code use_private_key_file(impl_type& impl, + const std::string& filename, context_base::file_format format, + boost::system::error_code& ec) + { + int file_type; + switch (format) + { + case context_base::asn1: + file_type = SSL_FILETYPE_ASN1; + break; + case context_base::pem: + file_type = SSL_FILETYPE_PEM; + break; + default: + { + ec = boost::asio::error::invalid_argument; + return ec; + } + } + + if (::SSL_CTX_use_PrivateKey_file(impl, filename.c_str(), file_type) != 1) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Use an RSA private key from a file. + boost::system::error_code use_rsa_private_key_file(impl_type& impl, + const std::string& filename, context_base::file_format format, + boost::system::error_code& ec) + { + int file_type; + switch (format) + { + case context_base::asn1: + file_type = SSL_FILETYPE_ASN1; + break; + case context_base::pem: + file_type = SSL_FILETYPE_PEM; + break; + default: + { + ec = boost::asio::error::invalid_argument; + return ec; + } + } + + if (::SSL_CTX_use_RSAPrivateKey_file( + impl, filename.c_str(), file_type) != 1) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Use the specified file to obtain the temporary Diffie-Hellman parameters. + boost::system::error_code use_tmp_dh_file(impl_type& impl, + const std::string& filename, boost::system::error_code& ec) + { + ::BIO* bio = ::BIO_new_file(filename.c_str(), "r"); + if (!bio) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ::DH* dh = ::PEM_read_bio_DHparams(bio, 0, 0, 0); + if (!dh) + { + ::BIO_free(bio); + ec = boost::asio::error::invalid_argument; + return ec; + } + + ::BIO_free(bio); + int result = ::SSL_CTX_set_tmp_dh(impl, dh); + ::DH_free(dh); + if (result != 1) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + static int password_callback(char* buf, int size, int purpose, void* data) + { + using namespace std; // For strncat and strlen. + + if (data) + { + password_callback_type* callback = + static_cast(data); + std::string passwd = (*callback)(static_cast(size), + purpose ? context_base::for_writing : context_base::for_reading); + *buf = '\0'; + strncat(buf, passwd.c_str(), size); + return strlen(buf); + } + + return 0; + } + + // Set the password callback. + template + boost::system::error_code set_password_callback(impl_type& impl, + Password_Callback callback, boost::system::error_code& ec) + { + // Allocate callback function object if not already present. + if (impl->default_passwd_callback_userdata) + { + password_callback_type* callback_function = + static_cast( + impl->default_passwd_callback_userdata); + *callback_function = callback; + } + else + { + password_callback_type* callback_function = + new password_callback_type(callback); + impl->default_passwd_callback_userdata = callback_function; + } + + // Set the password callback. + SSL_CTX_set_default_passwd_cb(impl, + &openssl_context_service::password_callback); + + ec = boost::system::error_code(); + return ec; + } + +private: + // Ensure openssl is initialised. + openssl_init<> init_; +}; + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP diff --git a/win32/include/boost/asio/ssl/detail/openssl_init.hpp b/win32/include/boost/asio/ssl/detail/openssl_init.hpp new file mode 100755 index 000000000..f39bde1b7 --- /dev/null +++ b/win32/include/boost/asio/ssl/detail/openssl_init.hpp @@ -0,0 +1,152 @@ +// +// openssl_init.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com +// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SSL_DETAIL_OPENSSL_INIT_HPP +#define BOOST_ASIO_SSL_DETAIL_OPENSSL_INIT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +template +class openssl_init + : private boost::noncopyable +{ +private: + // Structure to perform the actual initialisation. + class do_init + { + public: + do_init() + { + if (Do_Init) + { + ::SSL_library_init(); + ::SSL_load_error_strings(); + ::OpenSSL_add_ssl_algorithms(); + + mutexes_.resize(::CRYPTO_num_locks()); + for (size_t i = 0; i < mutexes_.size(); ++i) + mutexes_[i].reset(new boost::asio::detail::mutex); + ::CRYPTO_set_locking_callback(&do_init::openssl_locking_func); + ::CRYPTO_set_id_callback(&do_init::openssl_id_func); + } + } + + ~do_init() + { + if (Do_Init) + { + ::CRYPTO_set_id_callback(0); + ::CRYPTO_set_locking_callback(0); + ::ERR_free_strings(); + ::ERR_remove_state(0); + ::EVP_cleanup(); + ::CRYPTO_cleanup_all_ex_data(); + ::CONF_modules_unload(1); + ::ENGINE_cleanup(); + } + } + + // Helper function to manage a do_init singleton. The static instance of the + // openssl_init object ensures that this function is always called before + // main, and therefore before any other threads can get started. The do_init + // instance must be static in this function to ensure that it gets + // initialised before any other global objects try to use it. + static boost::shared_ptr instance() + { + static boost::shared_ptr init(new do_init); + return init; + } + + private: + static unsigned long openssl_id_func() + { +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) + return ::GetCurrentThreadId(); +#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + void* id = instance()->thread_id_; + if (id == 0) + instance()->thread_id_ = id = &id; // Ugh. + BOOST_ASSERT(sizeof(unsigned long) >= sizeof(void*)); + return reinterpret_cast(id); +#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) + } + + static void openssl_locking_func(int mode, int n, + const char *file, int line) + { + if (mode & CRYPTO_LOCK) + instance()->mutexes_[n]->lock(); + else + instance()->mutexes_[n]->unlock(); + } + + // Mutexes to be used in locking callbacks. + std::vector > mutexes_; + +#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + // The thread identifiers to be used by openssl. + boost::asio::detail::tss_ptr thread_id_; +#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + }; + +public: + // Constructor. + openssl_init() + : ref_(do_init::instance()) + { + while (&instance_ == 0); // Ensure openssl_init::instance_ is linked in. + } + + // Destructor. + ~openssl_init() + { + } + +private: + // Instance to force initialisation of openssl at global scope. + static openssl_init instance_; + + // Reference to singleton do_init object to ensure that openssl does not get + // cleaned up until the last user has finished with it. + boost::shared_ptr ref_; +}; + +template +openssl_init openssl_init::instance_; + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SSL_DETAIL_OPENSSL_INIT_HPP diff --git a/win32/include/boost/asio/ssl/detail/openssl_operation.hpp b/win32/include/boost/asio/ssl/detail/openssl_operation.hpp new file mode 100755 index 000000000..9ccc0959e --- /dev/null +++ b/win32/include/boost/asio/ssl/detail/openssl_operation.hpp @@ -0,0 +1,518 @@ +// +// openssl_operation.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SSL_DETAIL_OPENSSL_OPERATION_HPP +#define BOOST_ASIO_SSL_DETAIL_OPENSSL_OPERATION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +typedef boost::function ssl_primitive_func; +typedef boost::function + user_handler_func; + +// Network send_/recv buffer implementation +// +// +class net_buffer +{ + static const int NET_BUF_SIZE = 16*1024 + 256; // SSL record size + spare + + unsigned char buf_[NET_BUF_SIZE]; + unsigned char* data_start_; + unsigned char* data_end_; + +public: + net_buffer() + { + data_start_ = data_end_ = buf_; + } + unsigned char* get_unused_start() { return data_end_; } + unsigned char* get_data_start() { return data_start_; } + size_t get_unused_len() { return (NET_BUF_SIZE - (data_end_ - buf_)); } + size_t get_data_len() { return (data_end_ - data_start_); } + void data_added(size_t count) + { + data_end_ += count; + data_end_ = data_end_ > (buf_ + NET_BUF_SIZE)? + (buf_ + NET_BUF_SIZE): + data_end_; + } + void data_removed(size_t count) + { + data_start_ += count; + if (data_start_ >= data_end_) reset(); + } + void reset() { data_start_ = buf_; data_end_ = buf_; } + bool has_data() { return (data_start_ < data_end_); } +}; // class net_buffer + +// +// Operation class +// +// +template +class openssl_operation +{ +public: + + // Constructor for asynchronous operations + openssl_operation(ssl_primitive_func primitive, + Stream& socket, + net_buffer& recv_buf, + SSL* session, + BIO* ssl_bio, + user_handler_func handler, + boost::asio::io_service::strand& strand + ) + : primitive_(primitive) + , user_handler_(handler) + , strand_(&strand) + , recv_buf_(recv_buf) + , socket_(socket) + , ssl_bio_(ssl_bio) + , session_(session) + { + write_ = boost::bind( + &openssl_operation::do_async_write, + this, boost::arg<1>(), boost::arg<2>() + ); + read_ = boost::bind( + &openssl_operation::do_async_read, + this + ); + handler_= boost::bind( + &openssl_operation::async_user_handler, + this, boost::arg<1>(), boost::arg<2>() + ); + } + + // Constructor for synchronous operations + openssl_operation(ssl_primitive_func primitive, + Stream& socket, + net_buffer& recv_buf, + SSL* session, + BIO* ssl_bio) + : primitive_(primitive) + , strand_(0) + , recv_buf_(recv_buf) + , socket_(socket) + , ssl_bio_(ssl_bio) + , session_(session) + { + write_ = boost::bind( + &openssl_operation::do_sync_write, + this, boost::arg<1>(), boost::arg<2>() + ); + read_ = boost::bind( + &openssl_operation::do_sync_read, + this + ); + handler_ = boost::bind( + &openssl_operation::sync_user_handler, + this, boost::arg<1>(), boost::arg<2>() + ); + } + + // Start operation + // In case of asynchronous it returns 0, in sync mode returns success code + // or throws an error... + int start() + { + int rc = primitive_( session_ ); + + bool is_operation_done = (rc > 0); + // For connect/accept/shutdown, the operation + // is done, when return code is 1 + // for write, it is done, when is retcode > 0 + // for read, is is done when retcode > 0 + + int error_code = !is_operation_done ? + ::SSL_get_error( session_, rc ) : + 0; + int sys_error_code = ERR_get_error(); + + bool is_read_needed = (error_code == SSL_ERROR_WANT_READ); + bool is_write_needed = (error_code == SSL_ERROR_WANT_WRITE || + ::BIO_ctrl_pending( ssl_bio_ )); + bool is_shut_down_received = + ((::SSL_get_shutdown( session_ ) & SSL_RECEIVED_SHUTDOWN) == + SSL_RECEIVED_SHUTDOWN); + bool is_shut_down_sent = + ((::SSL_get_shutdown( session_ ) & SSL_SENT_SHUTDOWN) == + SSL_SENT_SHUTDOWN); + + if (is_shut_down_sent && is_shut_down_received && is_operation_done && !is_write_needed) + // SSL connection is shut down cleanly + return handler_(boost::system::error_code(), 1); + + if (is_shut_down_received && !is_operation_done) + // Shutdown has been requested, while we were reading or writing... + // abort our action... + return handler_(boost::asio::error::shut_down, 0); + + if (!is_operation_done && !is_read_needed && !is_write_needed + && !is_shut_down_sent) + { + // The operation has failed... It is not completed and does + // not want network communication nor does want to send shutdown out... + if (error_code == SSL_ERROR_SYSCALL) + { + return handler_(boost::system::error_code( + sys_error_code, boost::asio::error::system_category), rc); + } + else + { + return handler_(boost::system::error_code( + error_code, boost::asio::error::get_ssl_category()), rc); + } + } + + if (!is_operation_done && !is_write_needed) + { + // We may have left over data that we can pass to SSL immediately + if (recv_buf_.get_data_len() > 0) + { + // Pass the buffered data to SSL + int written = ::BIO_write + ( + ssl_bio_, + recv_buf_.get_data_start(), + recv_buf_.get_data_len() + ); + + if (written > 0) + { + recv_buf_.data_removed(written); + } + else if (written < 0) + { + if (!BIO_should_retry(ssl_bio_)) + { + // Some serios error with BIO.... + return handler_(boost::asio::error::no_recovery, 0); + } + } + + return start(); + } + else if (is_read_needed || (is_shut_down_sent && !is_shut_down_received)) + { + return read_(); + } + } + + // Continue with operation, flush any SSL data out to network... + return write_(is_operation_done, rc); + } + +// Private implementation +private: + typedef boost::function + int_handler_func; + typedef boost::function write_func; + typedef boost::function read_func; + + ssl_primitive_func primitive_; + user_handler_func user_handler_; + boost::asio::io_service::strand* strand_; + write_func write_; + read_func read_; + int_handler_func handler_; + + net_buffer send_buf_; // buffers for network IO + + // The recv buffer is owned by the stream, not the operation, since there can + // be left over bytes after passing the data up to the application, and these + // bytes need to be kept around for the next read operation issued by the + // application. + net_buffer& recv_buf_; + + Stream& socket_; + BIO* ssl_bio_; + SSL* session_; + + // + int sync_user_handler(const boost::system::error_code& error, int rc) + { + if (!error) + return rc; + + throw boost::system::system_error(error); + } + + int async_user_handler(boost::system::error_code error, int rc) + { + if (rc < 0) + { + if (!error) + error = boost::asio::error::no_recovery; + rc = 0; + } + + user_handler_(error, rc); + return 0; + } + + // Writes bytes asynchronously from SSL to NET + int do_async_write(bool is_operation_done, int rc) + { + int len = ::BIO_ctrl_pending( ssl_bio_ ); + if ( len ) + { + // There is something to write into net, do it... + len = (int)send_buf_.get_unused_len() > len? + len: + send_buf_.get_unused_len(); + + if (len == 0) + { + // In case our send buffer is full, we have just to wait until + // previous send to complete... + return 0; + } + + // Read outgoing data from bio + len = ::BIO_read( ssl_bio_, send_buf_.get_unused_start(), len); + + if (len > 0) + { + unsigned char *data_start = send_buf_.get_unused_start(); + send_buf_.data_added(len); + + BOOST_ASSERT(strand_); + boost::asio::async_write + ( + socket_, + boost::asio::buffer(data_start, len), + strand_->wrap + ( + boost::bind + ( + &openssl_operation::async_write_handler, + this, + is_operation_done, + rc, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred + ) + ) + ); + + return 0; + } + else if (!BIO_should_retry(ssl_bio_)) + { + // Seems like fatal error + // reading from SSL BIO has failed... + handler_(boost::asio::error::no_recovery, 0); + return 0; + } + } + + if (is_operation_done) + { + // Finish the operation, with success + handler_(boost::system::error_code(), rc); + return 0; + } + + // OPeration is not done and writing to net has been made... + // start operation again + start(); + + return 0; + } + + void async_write_handler(bool is_operation_done, int rc, + const boost::system::error_code& error, size_t bytes_sent) + { + if (!error) + { + // Remove data from send buffer + send_buf_.data_removed(bytes_sent); + + if (is_operation_done) + handler_(boost::system::error_code(), rc); + else + // Since the operation was not completed, try it again... + start(); + } + else + handler_(error, rc); + } + + int do_async_read() + { + // Wait for new data + BOOST_ASSERT(strand_); + socket_.async_read_some + ( + boost::asio::buffer(recv_buf_.get_unused_start(), + recv_buf_.get_unused_len()), + strand_->wrap + ( + boost::bind + ( + &openssl_operation::async_read_handler, + this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred + ) + ) + ); + return 0; + } + + void async_read_handler(const boost::system::error_code& error, + size_t bytes_recvd) + { + if (!error) + { + recv_buf_.data_added(bytes_recvd); + + // Pass the received data to SSL + int written = ::BIO_write + ( + ssl_bio_, + recv_buf_.get_data_start(), + recv_buf_.get_data_len() + ); + + if (written > 0) + { + recv_buf_.data_removed(written); + } + else if (written < 0) + { + if (!BIO_should_retry(ssl_bio_)) + { + // Some serios error with BIO.... + handler_(boost::asio::error::no_recovery, 0); + return; + } + } + + // and try the SSL primitive again + start(); + } + else + { + // Error in network level... + // SSL can't continue either... + handler_(error, 0); + } + } + + // Syncronous functions... + int do_sync_write(bool is_operation_done, int rc) + { + int len = ::BIO_ctrl_pending( ssl_bio_ ); + if ( len ) + { + // There is something to write into net, do it... + len = (int)send_buf_.get_unused_len() > len? + len: + send_buf_.get_unused_len(); + + // Read outgoing data from bio + len = ::BIO_read( ssl_bio_, send_buf_.get_unused_start(), len); + + if (len > 0) + { + size_t sent_len = boost::asio::write( + socket_, + boost::asio::buffer(send_buf_.get_unused_start(), len) + ); + + send_buf_.data_added(len); + send_buf_.data_removed(sent_len); + } + else if (!BIO_should_retry(ssl_bio_)) + { + // Seems like fatal error + // reading from SSL BIO has failed... + throw boost::system::system_error(boost::asio::error::no_recovery); + } + } + + if (is_operation_done) + // Finish the operation, with success + return rc; + + // Operation is not finished, start again. + return start(); + } + + int do_sync_read() + { + size_t len = socket_.read_some + ( + boost::asio::buffer(recv_buf_.get_unused_start(), + recv_buf_.get_unused_len()) + ); + + // Write data to ssl + recv_buf_.data_added(len); + + // Pass the received data to SSL + int written = ::BIO_write + ( + ssl_bio_, + recv_buf_.get_data_start(), + recv_buf_.get_data_len() + ); + + if (written > 0) + { + recv_buf_.data_removed(written); + } + else if (written < 0) + { + if (!BIO_should_retry(ssl_bio_)) + { + // Some serios error with BIO.... + throw boost::system::system_error(boost::asio::error::no_recovery); + } + } + + // Try the operation again + return start(); + } +}; // class openssl_operation + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SSL_DETAIL_OPENSSL_OPERATION_HPP diff --git a/win32/include/boost/asio/ssl/detail/openssl_stream_service.hpp b/win32/include/boost/asio/ssl/detail/openssl_stream_service.hpp new file mode 100755 index 000000000..0471c35e1 --- /dev/null +++ b/win32/include/boost/asio/ssl/detail/openssl_stream_service.hpp @@ -0,0 +1,533 @@ +// +// stream_service.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com +// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SSL_DETAIL_OPENSSL_STREAM_SERVICE_HPP +#define BOOST_ASIO_SSL_DETAIL_OPENSSL_STREAM_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ssl { +namespace detail { + +class openssl_stream_service + : public boost::asio::detail::service_base +{ +private: + enum { max_buffer_size = INT_MAX }; + + //Base handler for asyncrhonous operations + template + class base_handler + { + public: + typedef boost::function< + void (const boost::system::error_code&, size_t)> func_t; + + base_handler(boost::asio::io_service& io_service) + : op_(NULL) + , io_service_(io_service) + , work_(io_service) + {} + + void do_func(const boost::system::error_code& error, size_t size) + { + func_(error, size); + } + + void set_operation(openssl_operation* op) { op_ = op; } + void set_func(func_t func) { func_ = func; } + + ~base_handler() + { + delete op_; + } + + private: + func_t func_; + openssl_operation* op_; + boost::asio::io_service& io_service_; + boost::asio::io_service::work work_; + }; // class base_handler + + // Handler for asynchronous IO (write/read) operations + template + class io_handler + : public base_handler + { + public: + io_handler(Handler handler, boost::asio::io_service& io_service) + : base_handler(io_service) + , handler_(handler) + { + set_func(boost::bind( + &io_handler::handler_impl, + this, boost::arg<1>(), boost::arg<2>() )); + } + + private: + Handler handler_; + void handler_impl(const boost::system::error_code& error, size_t size) + { + handler_(error, size); + delete this; + } + }; // class io_handler + + // Handler for asyncrhonous handshake (connect, accept) functions + template + class handshake_handler + : public base_handler + { + public: + handshake_handler(Handler handler, boost::asio::io_service& io_service) + : base_handler(io_service) + , handler_(handler) + { + set_func(boost::bind( + &handshake_handler::handler_impl, + this, boost::arg<1>(), boost::arg<2>() )); + } + + private: + Handler handler_; + void handler_impl(const boost::system::error_code& error, size_t) + { + handler_(error); + delete this; + } + + }; // class handshake_handler + + // Handler for asyncrhonous shutdown + template + class shutdown_handler + : public base_handler + { + public: + shutdown_handler(Handler handler, boost::asio::io_service& io_service) + : base_handler(io_service), + handler_(handler) + { + set_func(boost::bind( + &shutdown_handler::handler_impl, + this, boost::arg<1>(), boost::arg<2>() )); + } + + private: + Handler handler_; + void handler_impl(const boost::system::error_code& error, size_t) + { + handler_(error); + delete this; + } + }; // class shutdown_handler + +public: + // The implementation type. + typedef struct impl_struct + { + ::SSL* ssl; + ::BIO* ext_bio; + net_buffer recv_buf; + } * impl_type; + + // Construct a new stream socket service for the specified io_service. + explicit openssl_stream_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + strand_(io_service) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Return a null stream implementation. + impl_type null() const + { + return 0; + } + + // Create a new stream implementation. + template + void create(impl_type& impl, Stream& next_layer, + basic_context& context) + { + impl = new impl_struct; + impl->ssl = ::SSL_new(context.impl()); + ::SSL_set_mode(impl->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); + ::SSL_set_mode(impl->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + ::BIO* int_bio = 0; + impl->ext_bio = 0; + ::BIO_new_bio_pair(&int_bio, 8192, &impl->ext_bio, 8192); + ::SSL_set_bio(impl->ssl, int_bio, int_bio); + } + + // Destroy a stream implementation. + template + void destroy(impl_type& impl, Stream& next_layer) + { + if (impl != 0) + { + ::BIO_free(impl->ext_bio); + ::SSL_free(impl->ssl); + delete impl; + impl = 0; + } + } + + // Perform SSL handshaking. + template + boost::system::error_code handshake(impl_type& impl, Stream& next_layer, + stream_base::handshake_type type, boost::system::error_code& ec) + { + try + { + openssl_operation op( + type == stream_base::client ? + &ssl_wrap::SSL_connect: + &ssl_wrap::SSL_accept, + next_layer, + impl->recv_buf, + impl->ssl, + impl->ext_bio); + op.start(); + } + catch (boost::system::system_error& e) + { + ec = e.code(); + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Start an asynchronous SSL handshake. + template + void async_handshake(impl_type& impl, Stream& next_layer, + stream_base::handshake_type type, Handler handler) + { + typedef handshake_handler connect_handler; + + connect_handler* local_handler = + new connect_handler(handler, get_io_service()); + + openssl_operation* op = new openssl_operation + ( + type == stream_base::client ? + &ssl_wrap::SSL_connect: + &ssl_wrap::SSL_accept, + next_layer, + impl->recv_buf, + impl->ssl, + impl->ext_bio, + boost::bind + ( + &base_handler::do_func, + local_handler, + boost::arg<1>(), + boost::arg<2>() + ), + strand_ + ); + local_handler->set_operation(op); + + strand_.post(boost::bind(&openssl_operation::start, op)); + } + + // Shut down SSL on the stream. + template + boost::system::error_code shutdown(impl_type& impl, Stream& next_layer, + boost::system::error_code& ec) + { + try + { + openssl_operation op( + &ssl_wrap::SSL_shutdown, + next_layer, + impl->recv_buf, + impl->ssl, + impl->ext_bio); + op.start(); + } + catch (boost::system::system_error& e) + { + ec = e.code(); + return ec; + } + + ec = boost::system::error_code(); + return ec; + } + + // Asynchronously shut down SSL on the stream. + template + void async_shutdown(impl_type& impl, Stream& next_layer, Handler handler) + { + typedef shutdown_handler disconnect_handler; + + disconnect_handler* local_handler = + new disconnect_handler(handler, get_io_service()); + + openssl_operation* op = new openssl_operation + ( + &ssl_wrap::SSL_shutdown, + next_layer, + impl->recv_buf, + impl->ssl, + impl->ext_bio, + boost::bind + ( + &base_handler::do_func, + local_handler, + boost::arg<1>(), + boost::arg<2>() + ), + strand_ + ); + local_handler->set_operation(op); + + strand_.post(boost::bind(&openssl_operation::start, op)); + } + + // Write some data to the stream. + template + std::size_t write_some(impl_type& impl, Stream& next_layer, + const Const_Buffers& buffers, boost::system::error_code& ec) + { + size_t bytes_transferred = 0; + try + { + std::size_t buffer_size = boost::asio::buffer_size(*buffers.begin()); + if (buffer_size > max_buffer_size) + buffer_size = max_buffer_size; + + boost::function send_func = + boost::bind(&::SSL_write, boost::arg<1>(), + boost::asio::buffer_cast(*buffers.begin()), + static_cast(buffer_size)); + openssl_operation op( + send_func, + next_layer, + impl->recv_buf, + impl->ssl, + impl->ext_bio + ); + bytes_transferred = static_cast(op.start()); + } + catch (boost::system::system_error& e) + { + ec = e.code(); + return 0; + } + + ec = boost::system::error_code(); + return bytes_transferred; + } + + // Start an asynchronous write. + template + void async_write_some(impl_type& impl, Stream& next_layer, + const Const_Buffers& buffers, Handler handler) + { + typedef io_handler send_handler; + + send_handler* local_handler = new send_handler(handler, get_io_service()); + + std::size_t buffer_size = boost::asio::buffer_size(*buffers.begin()); + if (buffer_size > max_buffer_size) + buffer_size = max_buffer_size; + + boost::function send_func = + boost::bind(&::SSL_write, boost::arg<1>(), + boost::asio::buffer_cast(*buffers.begin()), + static_cast(buffer_size)); + + openssl_operation* op = new openssl_operation + ( + send_func, + next_layer, + impl->recv_buf, + impl->ssl, + impl->ext_bio, + boost::bind + ( + &base_handler::do_func, + local_handler, + boost::arg<1>(), + boost::arg<2>() + ), + strand_ + ); + local_handler->set_operation(op); + + strand_.post(boost::bind(&openssl_operation::start, op)); + } + + // Read some data from the stream. + template + std::size_t read_some(impl_type& impl, Stream& next_layer, + const Mutable_Buffers& buffers, boost::system::error_code& ec) + { + size_t bytes_transferred = 0; + try + { + std::size_t buffer_size = boost::asio::buffer_size(*buffers.begin()); + if (buffer_size > max_buffer_size) + buffer_size = max_buffer_size; + + boost::function recv_func = + boost::bind(&::SSL_read, boost::arg<1>(), + boost::asio::buffer_cast(*buffers.begin()), + static_cast(buffer_size)); + openssl_operation op(recv_func, + next_layer, + impl->recv_buf, + impl->ssl, + impl->ext_bio + ); + + bytes_transferred = static_cast(op.start()); + } + catch (boost::system::system_error& e) + { + ec = e.code(); + return 0; + } + + ec = boost::system::error_code(); + return bytes_transferred; + } + + // Start an asynchronous read. + template + void async_read_some(impl_type& impl, Stream& next_layer, + const Mutable_Buffers& buffers, Handler handler) + { + typedef io_handler recv_handler; + + recv_handler* local_handler = new recv_handler(handler, get_io_service()); + + std::size_t buffer_size = boost::asio::buffer_size(*buffers.begin()); + if (buffer_size > max_buffer_size) + buffer_size = max_buffer_size; + + boost::function recv_func = + boost::bind(&::SSL_read, boost::arg<1>(), + boost::asio::buffer_cast(*buffers.begin()), + static_cast(buffer_size)); + + openssl_operation* op = new openssl_operation + ( + recv_func, + next_layer, + impl->recv_buf, + impl->ssl, + impl->ext_bio, + boost::bind + ( + &base_handler::do_func, + local_handler, + boost::arg<1>(), + boost::arg<2>() + ), + strand_ + ); + local_handler->set_operation(op); + + strand_.post(boost::bind(&openssl_operation::start, op)); + } + + // Peek at the incoming data on the stream. + template + std::size_t peek(impl_type& impl, Stream& next_layer, + const Mutable_Buffers& buffers, boost::system::error_code& ec) + { + ec = boost::system::error_code(); + return 0; + } + + // Determine the amount of data that may be read without blocking. + template + std::size_t in_avail(impl_type& impl, Stream& next_layer, + boost::system::error_code& ec) + { + ec = boost::system::error_code(); + return 0; + } + +private: + boost::asio::io_service::strand strand_; + + typedef boost::asio::detail::mutex mutex_type; + + template + struct ssl_wrap + { + static Mutex ssl_mutex_; + + static int SSL_accept(SSL *ssl) + { + typename Mutex::scoped_lock lock(ssl_mutex_); + return ::SSL_accept(ssl); + } + + static int SSL_connect(SSL *ssl) + { + typename Mutex::scoped_lock lock(ssl_mutex_); + return ::SSL_connect(ssl); + } + + static int SSL_shutdown(SSL *ssl) + { + typename Mutex::scoped_lock lock(ssl_mutex_); + return ::SSL_shutdown(ssl); + } + }; +}; + +template +Mutex openssl_stream_service::ssl_wrap::ssl_mutex_; + +} // namespace detail +} // namespace ssl +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SSL_DETAIL_OPENSSL_STREAM_SERVICE_HPP diff --git a/win32/include/boost/asio/ssl/detail/openssl_types.hpp b/win32/include/boost/asio/ssl/detail/openssl_types.hpp new file mode 100755 index 000000000..f89b8017f --- /dev/null +++ b/win32/include/boost/asio/ssl/detail/openssl_types.hpp @@ -0,0 +1,31 @@ +// +// openssl_types.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP +#define BOOST_ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#endif // BOOST_ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP diff --git a/win32/include/boost/asio/ssl/stream.hpp b/win32/include/boost/asio/ssl/stream.hpp new file mode 100755 index 000000000..43a97920a --- /dev/null +++ b/win32/include/boost/asio/ssl/stream.hpp @@ -0,0 +1,505 @@ +// +// stream.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com +// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SSL_STREAM_HPP +#define BOOST_ASIO_SSL_STREAM_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ssl { + +/// Provides stream-oriented functionality using SSL. +/** + * The stream class template provides asynchronous and blocking stream-oriented + * functionality using SSL. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Example + * To use the SSL stream template with an ip::tcp::socket, you would write: + * @code + * boost::asio::io_service io_service; + * boost::asio::ssl::context context(io_service, boost::asio::ssl::context::sslv23); + * boost::asio::ssl::stream sock(io_service, context); + * @endcode + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncRead_Stream, SyncWriteStream. + */ +template +class stream + : public stream_base, + private boost::noncopyable +{ +public: + /// The type of the next layer. + typedef typename boost::remove_reference::type next_layer_type; + + /// The type of the lowest layer. + typedef typename next_layer_type::lowest_layer_type lowest_layer_type; + + /// The type of the service that will be used to provide stream operations. + typedef Service service_type; + + /// The native implementation type of the stream. + typedef typename service_type::impl_type impl_type; + + /// Construct a stream. + /** + * This constructor creates a stream and initialises the underlying stream + * object. + * + * @param arg The argument to be passed to initialise the underlying stream. + * + * @param context The SSL context to be used for the stream. + */ + template + explicit stream(Arg& arg, basic_context& context) + : next_layer_(arg), + service_(boost::asio::use_service(next_layer_.get_io_service())), + impl_(service_.null()) + { + service_.create(impl_, next_layer_, context); + } + + /// Destructor. + ~stream() + { + service_.destroy(impl_, next_layer_); + } + + /// (Deprecated: use get_io_service().) Get the io_service associated with + /// the object. + /** + * This function may be used to obtain the io_service object that the stream + * uses to dispatch handlers for asynchronous operations. + * + * @return A reference to the io_service object that stream will use to + * dispatch handlers. Ownership is not transferred to the caller. + */ + boost::asio::io_service& io_service() + { + return next_layer_.get_io_service(); + } + + /// Get the io_service associated with the object. + /** + * This function may be used to obtain the io_service object that the stream + * uses to dispatch handlers for asynchronous operations. + * + * @return A reference to the io_service object that stream will use to + * dispatch handlers. Ownership is not transferred to the caller. + */ + boost::asio::io_service& get_io_service() + { + return next_layer_.get_io_service(); + } + + /// Get a reference to the next layer. + /** + * This function returns a reference to the next layer in a stack of stream + * layers. + * + * @return A reference to the next layer in the stack of stream layers. + * Ownership is not transferred to the caller. + */ + next_layer_type& next_layer() + { + return next_layer_; + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * stream layers. + * + * @return A reference to the lowest layer in the stack of stream layers. + * Ownership is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return next_layer_.lowest_layer(); + } + + /// Get the underlying implementation in the native type. + /** + * This function may be used to obtain the underlying implementation of the + * context. This is intended to allow access to stream functionality that is + * not otherwise provided. + */ + impl_type impl() + { + return impl_; + } + + /// Perform SSL handshaking. + /** + * This function is used to perform SSL handshaking on the stream. The + * function call will block until handshaking is complete or an error occurs. + * + * @param type The type of handshaking to be performed, i.e. as a client or as + * a server. + * + * @throws boost::system::system_error Thrown on failure. + */ + void handshake(handshake_type type) + { + boost::system::error_code ec; + service_.handshake(impl_, next_layer_, type, ec); + boost::asio::detail::throw_error(ec); + } + + /// Perform SSL handshaking. + /** + * This function is used to perform SSL handshaking on the stream. The + * function call will block until handshaking is complete or an error occurs. + * + * @param type The type of handshaking to be performed, i.e. as a client or as + * a server. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code handshake(handshake_type type, + boost::system::error_code& ec) + { + return service_.handshake(impl_, next_layer_, type, ec); + } + + /// Start an asynchronous SSL handshake. + /** + * This function is used to asynchronously perform an SSL handshake on the + * stream. This function call always returns immediately. + * + * @param type The type of handshaking to be performed, i.e. as a client or as + * a server. + * + * @param handler The handler to be called when the handshake operation + * completes. Copies will be made of the handler as required. The equivalent + * function signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation. + * ); @endcode + */ + template + void async_handshake(handshake_type type, HandshakeHandler handler) + { + service_.async_handshake(impl_, next_layer_, type, handler); + } + + /// Shut down SSL on the stream. + /** + * This function is used to shut down SSL on the stream. The function call + * will block until SSL has been shut down or an error occurs. + * + * @throws boost::system::system_error Thrown on failure. + */ + void shutdown() + { + boost::system::error_code ec; + service_.shutdown(impl_, next_layer_, ec); + boost::asio::detail::throw_error(ec); + } + + /// Shut down SSL on the stream. + /** + * This function is used to shut down SSL on the stream. The function call + * will block until SSL has been shut down or an error occurs. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code shutdown(boost::system::error_code& ec) + { + return service_.shutdown(impl_, next_layer_, ec); + } + + /// Asynchronously shut down SSL on the stream. + /** + * This function is used to asynchronously shut down SSL on the stream. This + * function call always returns immediately. + * + * @param handler The handler to be called when the handshake operation + * completes. Copies will be made of the handler as required. The equivalent + * function signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation. + * ); @endcode + */ + template + void async_shutdown(ShutdownHandler handler) + { + service_.async_shutdown(impl_, next_layer_, handler); + } + + /// Write some data to the stream. + /** + * This function is used to write data on the stream. The function call will + * block until one or more bytes of data has been written successfully, or + * until an error occurs. + * + * @param buffers The data to be written. + * + * @returns The number of bytes written. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that all + * data is written before the blocking operation completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = service_.write_some(impl_, next_layer_, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Write some data to the stream. + /** + * This function is used to write data on the stream. The function call will + * block until one or more bytes of data has been written successfully, or + * until an error occurs. + * + * @param buffers The data to be written to the stream. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that all + * data is written before the blocking operation completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return service_.write_some(impl_, next_layer_, buffers, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write one or more bytes of data to + * the stream. The function call always returns immediately. + * + * @param buffers The data to be written to the stream. Although the buffers + * object may be copied as necessary, ownership of the underlying buffers is + * retained by the caller, which must guarantee that they remain valid until + * the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The equivalent function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * + * @note The async_write_some operation may not transmit all of the data to + * the peer. Consider using the @ref async_write function if you need to + * ensure that all data is written before the blocking operation completes. + */ + template + void async_write_some(const ConstBufferSequence& buffers, + WriteHandler handler) + { + service_.async_write_some(impl_, next_layer_, buffers, handler); + } + + /// Read some data from the stream. + /** + * This function is used to read data from the stream. The function call will + * block until one or more bytes of data has been read successfully, or until + * an error occurs. + * + * @param buffers The buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = service_.read_some(impl_, next_layer_, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Read some data from the stream. + /** + * This function is used to read data from the stream. The function call will + * block until one or more bytes of data has been read successfully, or until + * an error occurs. + * + * @param buffers The buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return service_.read_some(impl_, next_layer_, buffers, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read one or more bytes of data from + * the stream. The function call always returns immediately. + * + * @param buffers The buffers into which the data will be read. Although the + * buffers object may be copied as necessary, ownership of the underlying + * buffers is retained by the caller, which must guarantee that they remain + * valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The equivalent function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * + * @note The async_read_some operation may not read all of the requested + * number of bytes. Consider using the @ref async_read function if you need to + * ensure that the requested amount of data is read before the asynchronous + * operation completes. + */ + template + void async_read_some(const MutableBufferSequence& buffers, + ReadHandler handler) + { + service_.async_read_some(impl_, next_layer_, buffers, handler); + } + + /// Peek at the incoming data on the stream. + /** + * This function is used to peek at the incoming data on the stream, without + * removing it from the input queue. The function call will block until data + * has been read successfully or an error occurs. + * + * @param buffers The buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. + */ + template + std::size_t peek(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = service_.peek(impl_, next_layer_, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Peek at the incoming data on the stream. + /** + * This function is used to peek at the incoming data on the stream, withoutxi + * removing it from the input queue. The function call will block until data + * has been read successfully or an error occurs. + * + * @param buffers The buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + */ + template + std::size_t peek(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return service_.peek(impl_, next_layer_, buffers, ec); + } + + /// Determine the amount of data that may be read without blocking. + /** + * This function is used to determine the amount of data, in bytes, that may + * be read from the stream without blocking. + * + * @returns The number of bytes of data that can be read without blocking. + * + * @throws boost::system::system_error Thrown on failure. + */ + std::size_t in_avail() + { + boost::system::error_code ec; + std::size_t s = service_.in_avail(impl_, next_layer_, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Determine the amount of data that may be read without blocking. + /** + * This function is used to determine the amount of data, in bytes, that may + * be read from the stream without blocking. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes of data that can be read without blocking. + */ + std::size_t in_avail(boost::system::error_code& ec) + { + return service_.in_avail(impl_, next_layer_, ec); + } + +private: + /// The next layer. + Stream next_layer_; + + /// The backend service implementation. + service_type& service_; + + /// The underlying native implementation. + impl_type impl_; +}; + +} // namespace ssl +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SSL_STREAM_HPP diff --git a/win32/include/boost/asio/ssl/stream_base.hpp b/win32/include/boost/asio/ssl/stream_base.hpp new file mode 100755 index 000000000..df46c684e --- /dev/null +++ b/win32/include/boost/asio/ssl/stream_base.hpp @@ -0,0 +1,62 @@ +// +// stream_base.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SSL_STREAM_BASE_HPP +#define BOOST_ASIO_SSL_STREAM_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +namespace boost { +namespace asio { +namespace ssl { + +/// The stream_base class is used as a base for the boost::asio::ssl::stream +/// class template so that we have a common place to define various enums. +class stream_base +{ +public: + /// Different handshake types. + enum handshake_type + { + /// Perform handshaking as a client. + client, + + /// Perform handshaking as a server. + server + }; + +protected: + /// Protected destructor to prevent deletion through this type. + ~stream_base() + { + } + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +private: + // Workaround to enable the empty base optimisation with Borland C++. + char dummy_; +#endif +}; + +} // namespace ssl +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SSL_STREAM_BASE_HPP diff --git a/win32/include/boost/asio/ssl/stream_service.hpp b/win32/include/boost/asio/ssl/stream_service.hpp new file mode 100755 index 000000000..a8d76a262 --- /dev/null +++ b/win32/include/boost/asio/ssl/stream_service.hpp @@ -0,0 +1,188 @@ +// +// stream_service.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com +// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_SSL_STREAM_SERVICE_HPP +#define BOOST_ASIO_SSL_STREAM_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +namespace ssl { + +/// Default service implementation for an SSL stream. +class stream_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base +#endif +{ +private: + // The type of the platform-specific implementation. + typedef detail::openssl_stream_service service_impl_type; + +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + + /// The type of a stream implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined impl_type; +#else + typedef service_impl_type::impl_type impl_type; +#endif + + /// Construct a new stream service for the specified io_service. + explicit stream_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Return a null stream implementation. + impl_type null() const + { + return service_impl_.null(); + } + + /// Create a new stream implementation. + template + void create(impl_type& impl, Stream& next_layer, + basic_context& context) + { + service_impl_.create(impl, next_layer, context); + } + + /// Destroy a stream implementation. + template + void destroy(impl_type& impl, Stream& next_layer) + { + service_impl_.destroy(impl, next_layer); + } + + /// Perform SSL handshaking. + template + boost::system::error_code handshake(impl_type& impl, Stream& next_layer, + stream_base::handshake_type type, boost::system::error_code& ec) + { + return service_impl_.handshake(impl, next_layer, type, ec); + } + + /// Start an asynchronous SSL handshake. + template + void async_handshake(impl_type& impl, Stream& next_layer, + stream_base::handshake_type type, HandshakeHandler handler) + { + service_impl_.async_handshake(impl, next_layer, type, handler); + } + + /// Shut down SSL on the stream. + template + boost::system::error_code shutdown(impl_type& impl, Stream& next_layer, + boost::system::error_code& ec) + { + return service_impl_.shutdown(impl, next_layer, ec); + } + + /// Asynchronously shut down SSL on the stream. + template + void async_shutdown(impl_type& impl, Stream& next_layer, + ShutdownHandler handler) + { + service_impl_.async_shutdown(impl, next_layer, handler); + } + + /// Write some data to the stream. + template + std::size_t write_some(impl_type& impl, Stream& next_layer, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.write_some(impl, next_layer, buffers, ec); + } + + /// Start an asynchronous write. + template + void async_write_some(impl_type& impl, Stream& next_layer, + const ConstBufferSequence& buffers, WriteHandler handler) + { + service_impl_.async_write_some(impl, next_layer, buffers, handler); + } + + /// Read some data from the stream. + template + std::size_t read_some(impl_type& impl, Stream& next_layer, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.read_some(impl, next_layer, buffers, ec); + } + + /// Start an asynchronous read. + template + void async_read_some(impl_type& impl, Stream& next_layer, + const MutableBufferSequence& buffers, ReadHandler handler) + { + service_impl_.async_read_some(impl, next_layer, buffers, handler); + } + + /// Peek at the incoming data on the stream. + template + std::size_t peek(impl_type& impl, Stream& next_layer, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.peek(impl, next_layer, buffers, ec); + } + + /// Determine the amount of data that may be read without blocking. + template + std::size_t in_avail(impl_type& impl, Stream& next_layer, + boost::system::error_code& ec) + { + return service_impl_.in_avail(impl, next_layer, ec); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace ssl +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_SSL_STREAM_SERVICE_HPP diff --git a/win32/include/boost/asio/strand.hpp b/win32/include/boost/asio/strand.hpp new file mode 100755 index 000000000..a36425ced --- /dev/null +++ b/win32/include/boost/asio/strand.hpp @@ -0,0 +1,188 @@ +// +// strand.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_STRAND_HPP +#define BOOST_ASIO_STRAND_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +namespace boost { +namespace asio { + +/// Provides serialised handler execution. +/** + * The io_service::strand class provides the ability to post and dispatch + * handlers with the guarantee that none of those handlers will execute + * concurrently. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Dispatcher. + */ +class io_service::strand +{ +public: + /// Constructor. + /** + * Constructs the strand. + * + * @param io_service The io_service object that the strand will use to + * dispatch handlers that are ready to be run. + */ + explicit strand(boost::asio::io_service& io_service) + : service_(boost::asio::use_service< + boost::asio::detail::strand_service>(io_service)) + { + service_.construct(impl_); + } + + /// Destructor. + /** + * Destroys a strand. + * + * Handlers posted through the strand that have not yet been invoked will + * still be dispatched in a way that meets the guarantee of non-concurrency. + */ + ~strand() + { + service_.destroy(impl_); + } + + /// (Deprecated: use get_io_service().) Get the io_service associated with + /// the strand. + /** + * This function may be used to obtain the io_service object that the strand + * uses to dispatch handlers for asynchronous operations. + * + * @return A reference to the io_service object that the strand will use to + * dispatch handlers. Ownership is not transferred to the caller. + */ + boost::asio::io_service& io_service() + { + return service_.get_io_service(); + } + + /// Get the io_service associated with the strand. + /** + * This function may be used to obtain the io_service object that the strand + * uses to dispatch handlers for asynchronous operations. + * + * @return A reference to the io_service object that the strand will use to + * dispatch handlers. Ownership is not transferred to the caller. + */ + boost::asio::io_service& get_io_service() + { + return service_.get_io_service(); + } + + /// Request the strand to invoke the given handler. + /** + * This function is used to ask the strand to execute the given handler. + * + * The strand object guarantees that handlers posted or dispatched through + * the strand will not be executed concurrently. The handler may be executed + * inside this function if the guarantee can be met. If this function is + * called from within a handler that was posted or dispatched through the same + * strand, then the new handler will be executed immediately. + * + * The strand's guarantee is in addition to the guarantee provided by the + * underlying io_service. The io_service guarantees that the handler will only + * be called in a thread in which the io_service's run member function is + * currently being invoked. + * + * @param handler The handler to be called. The strand will make a copy of the + * handler object as required. The function signature of the handler must be: + * @code void handler(); @endcode + */ + template + void dispatch(Handler handler) + { + service_.dispatch(impl_, handler); + } + + /// Request the strand to invoke the given handler and return + /// immediately. + /** + * This function is used to ask the strand to execute the given handler, but + * without allowing the strand to call the handler from inside this function. + * + * The strand object guarantees that handlers posted or dispatched through + * the strand will not be executed concurrently. The strand's guarantee is in + * addition to the guarantee provided by the underlying io_service. The + * io_service guarantees that the handler will only be called in a thread in + * which the io_service's run member function is currently being invoked. + * + * @param handler The handler to be called. The strand will make a copy of the + * handler object as required. The function signature of the handler must be: + * @code void handler(); @endcode + */ + template + void post(Handler handler) + { + service_.post(impl_, handler); + } + + /// Create a new handler that automatically dispatches the wrapped handler + /// on the strand. + /** + * This function is used to create a new handler function object that, when + * invoked, will automatically pass the wrapped handler to the strand's + * dispatch function. + * + * @param handler The handler to be wrapped. The strand will make a copy of + * the handler object as required. The function signature of the handler must + * be: @code void handler(A1 a1, ... An an); @endcode + * + * @return A function object that, when invoked, passes the wrapped handler to + * the strand's dispatch function. Given a function object with the signature: + * @code R f(A1 a1, ... An an); @endcode + * If this function object is passed to the wrap function like so: + * @code strand.wrap(f); @endcode + * then the return value is a function object with the signature + * @code void g(A1 a1, ... An an); @endcode + * that, when invoked, executes code equivalent to: + * @code strand.dispatch(boost::bind(f, a1, ... an)); @endcode + */ + template +#if defined(GENERATING_DOCUMENTATION) + unspecified +#else + detail::wrapped_handler +#endif + wrap(Handler handler) + { + return detail::wrapped_handler(*this, handler); + } + +private: + boost::asio::detail::strand_service& service_; + boost::asio::detail::strand_service::implementation_type impl_; +}; + +/// Typedef for backwards compatibility. +typedef boost::asio::io_service::strand strand; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_STRAND_HPP diff --git a/win32/include/boost/asio/stream_socket_service.hpp b/win32/include/boost/asio/stream_socket_service.hpp new file mode 100755 index 000000000..83e6c20db --- /dev/null +++ b/win32/include/boost/asio/stream_socket_service.hpp @@ -0,0 +1,288 @@ +// +// stream_socket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_STREAM_SOCKET_SERVICE_HPP +#define BOOST_ASIO_STREAM_SOCKET_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { + +/// Default service implementation for a stream socket. +template +class stream_socket_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base > +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + +private: + // The type of the platform-specific implementation. +#if defined(BOOST_ASIO_HAS_IOCP) + typedef detail::win_iocp_socket_service service_impl_type; +#elif defined(BOOST_ASIO_HAS_EPOLL) + typedef detail::reactive_socket_service< + Protocol, detail::epoll_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_KQUEUE) + typedef detail::reactive_socket_service< + Protocol, detail::kqueue_reactor > service_impl_type; +#elif defined(BOOST_ASIO_HAS_DEV_POLL) + typedef detail::reactive_socket_service< + Protocol, detail::dev_poll_reactor > service_impl_type; +#else + typedef detail::reactive_socket_service< + Protocol, detail::select_reactor > service_impl_type; +#endif + +public: + /// The type of a stream socket implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef typename service_impl_type::implementation_type implementation_type; +#endif + + /// The native socket type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef typename service_impl_type::native_type native_type; +#endif + + /// Construct a new stream socket service for the specified io_service. + explicit stream_socket_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + stream_socket_service >(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new stream socket implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a stream socket implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Open a stream socket. + boost::system::error_code open(implementation_type& impl, + const protocol_type& protocol, boost::system::error_code& ec) + { + if (protocol.type() == SOCK_STREAM) + service_impl_.open(impl, protocol, ec); + else + ec = boost::asio::error::invalid_argument; + return ec; + } + + /// Assign an existing native socket to a stream socket. + boost::system::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_type& native_socket, + boost::system::error_code& ec) + { + return service_impl_.assign(impl, protocol, native_socket, ec); + } + + /// Determine whether the socket is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a stream socket implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native socket implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the socket. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Determine whether the socket is at the out-of-band data mark. + bool at_mark(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.at_mark(impl, ec); + } + + /// Determine the number of bytes available for reading. + std::size_t available(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.available(impl, ec); + } + + /// Bind the stream socket to the specified local endpoint. + boost::system::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, boost::system::error_code& ec) + { + return service_impl_.bind(impl, endpoint, ec); + } + + /// Connect the stream socket to the specified endpoint. + boost::system::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + return service_impl_.connect(impl, peer_endpoint, ec); + } + + /// Start an asynchronous connect. + template + void async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, ConnectHandler handler) + { + service_impl_.async_connect(impl, peer_endpoint, handler); + } + + /// Set a socket option. + template + boost::system::error_code set_option(implementation_type& impl, + const SettableSocketOption& option, boost::system::error_code& ec) + { + return service_impl_.set_option(impl, option, ec); + } + + /// Get a socket option. + template + boost::system::error_code get_option(const implementation_type& impl, + GettableSocketOption& option, boost::system::error_code& ec) const + { + return service_impl_.get_option(impl, option, ec); + } + + /// Perform an IO control command on the socket. + template + boost::system::error_code io_control(implementation_type& impl, + IoControlCommand& command, boost::system::error_code& ec) + { + return service_impl_.io_control(impl, command, ec); + } + + /// Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.local_endpoint(impl, ec); + } + + /// Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.remote_endpoint(impl, ec); + } + + /// Disable sends or receives on the socket. + boost::system::error_code shutdown(implementation_type& impl, + socket_base::shutdown_type what, boost::system::error_code& ec) + { + return service_impl_.shutdown(impl, what, ec); + } + + /// Send the given data to the peer. + template + std::size_t send(implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.send(impl, buffers, flags, ec); + } + + /// Start an asynchronous send. + template + void async_send(implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, WriteHandler handler) + { + service_impl_.async_send(impl, buffers, flags, handler); + } + + /// Receive some data from the peer. + template + std::size_t receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.receive(impl, buffers, flags, ec); + } + + /// Start an asynchronous receive. + template + void async_receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, ReadHandler handler) + { + service_impl_.async_receive(impl, buffers, flags, handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_STREAM_SOCKET_SERVICE_HPP diff --git a/win32/include/boost/asio/streambuf.hpp b/win32/include/boost/asio/streambuf.hpp new file mode 100755 index 000000000..8b3c7a4a9 --- /dev/null +++ b/win32/include/boost/asio/streambuf.hpp @@ -0,0 +1,33 @@ +// +// streambuf.hpp +// ~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_STREAMBUF_HPP +#define BOOST_ASIO_STREAMBUF_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +namespace boost { +namespace asio { + +/// Typedef for the typical usage of basic_streambuf. +typedef basic_streambuf<> streambuf; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_STREAMBUF_HPP diff --git a/win32/include/boost/asio/time_traits.hpp b/win32/include/boost/asio/time_traits.hpp new file mode 100755 index 000000000..c6f9c7155 --- /dev/null +++ b/win32/include/boost/asio/time_traits.hpp @@ -0,0 +1,80 @@ +// +// time_traits.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_TIME_TRAITS_HPP +#define BOOST_ASIO_TIME_TRAITS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include // Must come before posix_time. + +#include +#include +#include + +namespace boost { +namespace asio { + +/// Time traits suitable for use with the deadline timer. +template +struct time_traits; + +/// Time traits specialised for posix_time. +template <> +struct time_traits +{ + /// The time type. + typedef boost::posix_time::ptime time_type; + + /// The duration type. + typedef boost::posix_time::time_duration duration_type; + + /// Get the current time. + static time_type now() + { + return boost::posix_time::microsec_clock::universal_time(); + } + + /// Add a duration to a time. + static time_type add(const time_type& t, const duration_type& d) + { + return t + d; + } + + /// Subtract one time from another. + static duration_type subtract(const time_type& t1, const time_type& t2) + { + return t1 - t2; + } + + /// Test whether one time is less than another. + static bool less_than(const time_type& t1, const time_type& t2) + { + return t1 < t2; + } + + /// Convert to POSIX duration type. + static boost::posix_time::time_duration to_posix_duration( + const duration_type& d) + { + return d; + } +}; + +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_TIME_TRAITS_HPP diff --git a/win32/include/boost/asio/version.hpp b/win32/include/boost/asio/version.hpp new file mode 100755 index 000000000..7f0a53e04 --- /dev/null +++ b/win32/include/boost/asio/version.hpp @@ -0,0 +1,23 @@ +// +// version.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_VERSION_HPP +#define BOOST_ASIO_VERSION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +// BOOST_ASIO_VERSION % 100 is the sub-minor version +// BOOST_ASIO_VERSION / 100 % 1000 is the minor version +// BOOST_ASIO_VERSION / 100000 is the major version +#define BOOST_ASIO_VERSION 100200 // 1.2.0 + +#endif // BOOST_ASIO_VERSION_HPP diff --git a/win32/include/boost/asio/windows/basic_handle.hpp b/win32/include/boost/asio/windows/basic_handle.hpp new file mode 100755 index 000000000..7c446850b --- /dev/null +++ b/win32/include/boost/asio/windows/basic_handle.hpp @@ -0,0 +1,213 @@ +// +// basic_handle.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP +#define BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include + +#include +#include +#include + +namespace boost { +namespace asio { +namespace windows { + +/// Provides Windows handle functionality. +/** + * The windows::basic_handle class template provides the ability to wrap a + * Windows handle. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_handle + : public basic_io_object +{ +public: + /// The native representation of a handle. + typedef typename HandleService::native_type native_type; + + /// A basic_handle is always the lowest layer. + typedef basic_handle lowest_layer_type; + + /// Construct a basic_handle without opening it. + /** + * This constructor creates a handle without opening it. + * + * @param io_service The io_service object that the handle will use to + * dispatch handlers for any asynchronous operations performed on the handle. + */ + explicit basic_handle(boost::asio::io_service& io_service) + : basic_io_object(io_service) + { + } + + /// Construct a basic_handle on an existing native handle. + /** + * This constructor creates a handle object to hold an existing native handle. + * + * @param io_service The io_service object that the handle will use to + * dispatch handlers for any asynchronous operations performed on the handle. + * + * @param native_handle A native handle. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_handle(boost::asio::io_service& io_service, + const native_type& native_handle) + : basic_io_object(io_service) + { + boost::system::error_code ec; + this->service.assign(this->implementation, native_handle, ec); + boost::asio::detail::throw_error(ec); + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_handle cannot contain any further layers, it simply + * returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Assign an existing native handle to the handle. + /* + * This function opens the handle to hold an existing native handle. + * + * @param native_handle A native handle. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const native_type& native_handle) + { + boost::system::error_code ec; + this->service.assign(this->implementation, native_handle, ec); + boost::asio::detail::throw_error(ec); + } + + /// Assign an existing native handle to the handle. + /* + * This function opens the handle to hold an existing native handle. + * + * @param native_handle A native handle. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code assign(const native_type& native_handle, + boost::system::error_code& ec) + { + return this->service.assign(this->implementation, native_handle, ec); + } + + /// Determine whether the handle is open. + bool is_open() const + { + return this->service.is_open(this->implementation); + } + + /// Close the handle. + /** + * This function is used to close the handle. Any asynchronous read or write + * operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void close() + { + boost::system::error_code ec; + this->service.close(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Close the handle. + /** + * This function is used to close the handle. Any asynchronous read or write + * operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code close(boost::system::error_code& ec) + { + return this->service.close(this->implementation, ec); + } + + /// Get the native handle representation. + /** + * This function may be used to obtain the underlying representation of the + * handle. This is intended to allow access to native handle functionality + * that is not otherwise provided. + */ + native_type native() + { + return this->service.native(this->implementation); + } + + /// Cancel all asynchronous operations associated with the handle. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void cancel() + { + boost::system::error_code ec; + this->service.cancel(this->implementation, ec); + boost::asio::detail::throw_error(ec); + } + + /// Cancel all asynchronous operations associated with the handle. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code cancel(boost::system::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + +protected: + /// Protected destructor to prevent deletion through this type. + ~basic_handle() + { + } +}; + +} // namespace windows +} // namespace asio +} // namespace boost + +#include + +#endif // BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP diff --git a/win32/include/boost/asio/windows/basic_random_access_handle.hpp b/win32/include/boost/asio/windows/basic_random_access_handle.hpp new file mode 100755 index 000000000..50e3627fc --- /dev/null +++ b/win32/include/boost/asio/windows/basic_random_access_handle.hpp @@ -0,0 +1,322 @@ +// +// basic_random_access_handle.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP +#define BOOST_ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace windows { + +/// Provides random-access handle functionality. +/** + * The windows::basic_random_access_handle class template provides asynchronous + * and blocking random-access handle functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template +class basic_random_access_handle + : public basic_handle +{ +public: + /// The native representation of a handle. + typedef typename RandomAccessHandleService::native_type native_type; + + /// Construct a basic_random_access_handle without opening it. + /** + * This constructor creates a random-access handle without opening it. The + * handle needs to be opened before data can be written to or or read from it. + * + * @param io_service The io_service object that the random-access handle will + * use to dispatch handlers for any asynchronous operations performed on the + * handle. + */ + explicit basic_random_access_handle(boost::asio::io_service& io_service) + : basic_handle(io_service) + { + } + + /// Construct a basic_random_access_handle on an existing native handle. + /** + * This constructor creates a random-access handle object to hold an existing + * native handle. + * + * @param io_service The io_service object that the random-access handle will + * use to dispatch handlers for any asynchronous operations performed on the + * handle. + * + * @param native_handle The new underlying handle implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_random_access_handle(boost::asio::io_service& io_service, + const native_type& native_handle) + : basic_handle(io_service, native_handle) + { + } + + /// Write some data to the handle at the specified offset. + /** + * This function is used to write data to the random-access handle. The + * function call will block until one or more bytes of the data has been + * written successfully, or until an error occurs. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more data buffers to be written to the handle. + * + * @returns The number of bytes written. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some_at operation may not write all of the data. Consider + * using the @ref write_at function if you need to ensure that all data is + * written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * handle.write_some_at(42, boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t write_some_at(boost::uint64_t offset, + const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.write_some_at( + this->implementation, offset, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Write some data to the handle at the specified offset. + /** + * This function is used to write data to the random-access handle. The + * function call will block until one or more bytes of the data has been + * written successfully, or until an error occurs. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more data buffers to be written to the handle. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write_at function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template + std::size_t write_some_at(boost::uint64_t offset, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return this->service.write_some_at( + this->implementation, offset, buffers, ec); + } + + /// Start an asynchronous write at the specified offset. + /** + * This function is used to asynchronously write data to the random-access + * handle. The function call always returns immediately. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more data buffers to be written to the handle. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write_at function if you need to ensure that + * all data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * handle.async_write_some_at(42, boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_write_some_at(boost::uint64_t offset, + const ConstBufferSequence& buffers, WriteHandler handler) + { + this->service.async_write_some_at( + this->implementation, offset, buffers, handler); + } + + /// Read some data from the handle at the specified offset. + /** + * This function is used to read data from the random-access handle. The + * function call will block until one or more bytes of data has been read + * successfully, or until an error occurs. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read_at function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * handle.read_some_at(42, boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t read_some_at(boost::uint64_t offset, + const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.read_some_at( + this->implementation, offset, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Read some data from the handle at the specified offset. + /** + * This function is used to read data from the random-access handle. The + * function call will block until one or more bytes of data has been read + * successfully, or until an error occurs. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read_at function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template + std::size_t read_some_at(boost::uint64_t offset, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return this->service.read_some_at( + this->implementation, offset, buffers, ec); + } + + /// Start an asynchronous read at the specified offset. + /** + * This function is used to asynchronously read data from the random-access + * handle. The function call always returns immediately. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read_at function if you need to ensure that + * the requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * handle.async_read_some_at(42, boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_read_some_at(boost::uint64_t offset, + const MutableBufferSequence& buffers, ReadHandler handler) + { + this->service.async_read_some_at( + this->implementation, offset, buffers, handler); + } +}; + +} // namespace windows +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP diff --git a/win32/include/boost/asio/windows/basic_stream_handle.hpp b/win32/include/boost/asio/windows/basic_stream_handle.hpp new file mode 100755 index 000000000..5a5dc739f --- /dev/null +++ b/win32/include/boost/asio/windows/basic_stream_handle.hpp @@ -0,0 +1,304 @@ +// +// basic_stream_handle.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP +#define BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace windows { + +/// Provides stream-oriented handle functionality. +/** + * The windows::basic_stream_handle class template provides asynchronous and + * blocking stream-oriented handle functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template +class basic_stream_handle + : public basic_handle +{ +public: + /// The native representation of a handle. + typedef typename StreamHandleService::native_type native_type; + + /// Construct a basic_stream_handle without opening it. + /** + * This constructor creates a stream handle without opening it. The handle + * needs to be opened and then connected or accepted before data can be sent + * or received on it. + * + * @param io_service The io_service object that the stream handle will use to + * dispatch handlers for any asynchronous operations performed on the handle. + */ + explicit basic_stream_handle(boost::asio::io_service& io_service) + : basic_handle(io_service) + { + } + + /// Construct a basic_stream_handle on an existing native handle. + /** + * This constructor creates a stream handle object to hold an existing native + * handle. + * + * @param io_service The io_service object that the stream handle will use to + * dispatch handlers for any asynchronous operations performed on the handle. + * + * @param native_handle The new underlying handle implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_stream_handle(boost::asio::io_service& io_service, + const native_type& native_handle) + : basic_handle(io_service, native_handle) + { + } + + /// Write some data to the handle. + /** + * This function is used to write data to the stream handle. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the handle. + * + * @returns The number of bytes written. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * handle.write_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.write_some(this->implementation, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Write some data to the handle. + /** + * This function is used to write data to the stream handle. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the handle. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->service.write_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the stream handle. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be written to the handle. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * handle.async_write_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_write_some(const ConstBufferSequence& buffers, + WriteHandler handler) + { + this->service.async_write_some(this->implementation, buffers, handler); + } + + /// Read some data from the handle. + /** + * This function is used to read data from the stream handle. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * handle.read_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->service.read_some(this->implementation, buffers, ec); + boost::asio::detail::throw_error(ec); + return s; + } + + /// Read some data from the handle. + /** + * This function is used to read data from the stream handle. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->service.read_some(this->implementation, buffers, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the stream handle. + * The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * handle.async_read_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template + void async_read_some(const MutableBufferSequence& buffers, + ReadHandler handler) + { + this->service.async_read_some(this->implementation, buffers, handler); + } +}; + +} // namespace windows +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP diff --git a/win32/include/boost/asio/windows/random_access_handle.hpp b/win32/include/boost/asio/windows/random_access_handle.hpp new file mode 100755 index 000000000..1ea18fdb7 --- /dev/null +++ b/win32/include/boost/asio/windows/random_access_handle.hpp @@ -0,0 +1,41 @@ +// +// random_access_handle.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP +#define BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace windows { + +/// Typedef for the typical usage of a random-access handle. +typedef basic_random_access_handle<> random_access_handle; + +} // namespace windows +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP diff --git a/win32/include/boost/asio/windows/random_access_handle_service.hpp b/win32/include/boost/asio/windows/random_access_handle_service.hpp new file mode 100755 index 000000000..f1e273115 --- /dev/null +++ b/win32/include/boost/asio/windows/random_access_handle_service.hpp @@ -0,0 +1,181 @@ +// +// random_access_handle_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP +#define BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if !defined(BOOST_ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) +# if defined(BOOST_ASIO_HAS_IOCP) +# define BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE 1 +# endif // defined(BOOST_ASIO_HAS_IOCP) +#endif // !defined(BOOST_ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) + +#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace windows { + +/// Default service implementation for a random-access handle. +class random_access_handle_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + +private: + // The type of the platform-specific implementation. + typedef detail::win_iocp_handle_service service_impl_type; + +public: + /// The type of a random-access handle implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef service_impl_type::implementation_type implementation_type; +#endif + + /// The native handle type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef service_impl_type::native_type native_type; +#endif + + /// Construct a new random-access handle service for the specified io_service. + explicit random_access_handle_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + random_access_handle_service>(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new random-access handle implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a random-access handle implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Assign an existing native handle to a random-access handle. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_handle, boost::system::error_code& ec) + { + return service_impl_.assign(impl, native_handle, ec); + } + + /// Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a random-access handle implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native handle implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the handle. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Write the given data at the specified offset. + template + std::size_t write_some_at(implementation_type& impl, boost::uint64_t offset, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.write_some_at(impl, offset, buffers, ec); + } + + /// Start an asynchronous write at the specified offset. + template + void async_write_some_at(implementation_type& impl, boost::uint64_t offset, + const ConstBufferSequence& buffers, WriteHandler handler) + { + service_impl_.async_write_some_at(impl, offset, buffers, handler); + } + + /// Read some data from the specified offset. + template + std::size_t read_some_at(implementation_type& impl, boost::uint64_t offset, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.read_some_at(impl, offset, buffers, ec); + } + + /// Start an asynchronous read at the specified offset. + template + void async_read_some_at(implementation_type& impl, boost::uint64_t offset, + const MutableBufferSequence& buffers, ReadHandler handler) + { + service_impl_.async_read_some_at(impl, offset, buffers, handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace windows +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP diff --git a/win32/include/boost/asio/windows/stream_handle.hpp b/win32/include/boost/asio/windows/stream_handle.hpp new file mode 100755 index 000000000..420b242fe --- /dev/null +++ b/win32/include/boost/asio/windows/stream_handle.hpp @@ -0,0 +1,41 @@ +// +// stream_handle.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_STREAM_HANDLE_HPP +#define BOOST_ASIO_WINDOWS_STREAM_HANDLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include + +#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace windows { + +/// Typedef for the typical usage of a stream-oriented handle. +typedef basic_stream_handle<> stream_handle; + +} // namespace windows +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_WINDOWS_STREAM_HANDLE_HPP diff --git a/win32/include/boost/asio/windows/stream_handle_service.hpp b/win32/include/boost/asio/windows/stream_handle_service.hpp new file mode 100755 index 000000000..f4196af3c --- /dev/null +++ b/win32/include/boost/asio/windows/stream_handle_service.hpp @@ -0,0 +1,179 @@ +// +// stream_handle_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP +#define BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#if !defined(BOOST_ASIO_DISABLE_WINDOWS_STREAM_HANDLE) +# if defined(BOOST_ASIO_HAS_IOCP) +# define BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE 1 +# endif // defined(BOOST_ASIO_HAS_IOCP) +#endif // !defined(BOOST_ASIO_DISABLE_WINDOWS_STREAM_HANDLE) + +#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \ + || defined(GENERATING_DOCUMENTATION) + +namespace boost { +namespace asio { +namespace windows { + +/// Default service implementation for a stream handle. +class stream_handle_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + +private: + // The type of the platform-specific implementation. + typedef detail::win_iocp_handle_service service_impl_type; + +public: + /// The type of a stream handle implementation. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef service_impl_type::implementation_type implementation_type; +#endif + + /// The native handle type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef service_impl_type::native_type native_type; +#endif + + /// Construct a new stream handle service for the specified io_service. + explicit stream_handle_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base(io_service), + service_impl_(boost::asio::use_service(io_service)) + { + } + + /// Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + /// Construct a new stream handle implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a stream handle implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Assign an existing native handle to a stream handle. + boost::system::error_code assign(implementation_type& impl, + const native_type& native_handle, boost::system::error_code& ec) + { + return service_impl_.assign(impl, native_handle, ec); + } + + /// Determine whether the handle is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a stream handle implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// Get the native handle implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native(impl); + } + + /// Cancel all asynchronous operations associated with the handle. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Write the given data to the stream. + template + std::size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.write_some(impl, buffers, ec); + } + + /// Start an asynchronous write. + template + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, WriteHandler handler) + { + service_impl_.async_write_some(impl, buffers, handler); + } + + /// Read some data from the stream. + template + std::size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, boost::system::error_code& ec) + { + return service_impl_.read_some(impl, buffers, ec); + } + + /// Start an asynchronous read. + template + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, ReadHandler handler) + { + service_impl_.async_read_some(impl, buffers, handler); + } + +private: + // The service that provides the platform-specific implementation. + service_impl_type& service_impl_; +}; + +} // namespace windows +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) + // || defined(GENERATING_DOCUMENTATION) + +#include + +#endif // BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP diff --git a/win32/include/boost/asio/write.hpp b/win32/include/boost/asio/write.hpp new file mode 100755 index 000000000..af75618e4 --- /dev/null +++ b/win32/include/boost/asio/write.hpp @@ -0,0 +1,522 @@ +// +// write.hpp +// ~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WRITE_HPP +#define BOOST_ASIO_WRITE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { + +/** + * @defgroup write boost::asio::write + * + * @brief Write a certain amount of data to a stream before returning. + */ +/*@{*/ + +/// Write all of the supplied data to a stream before returning. +/** + * This function is used to write a certain number of bytes of data to a stream. + * The call will block until one of the following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the stream's + * write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the SyncWriteStream concept. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * stream. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code boost::asio::write(s, boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code boost::asio::write( + * s, buffers, + * boost::asio::transfer_all()); @endcode + */ +template +std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers); + +/// Write a certain amount of data to a stream before returning. +/** + * This function is used to write a certain number of bytes of data to a stream. + * The call will block until one of the following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the stream's + * write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the SyncWriteStream concept. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * stream. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const boost::system::error_code& error, // Result of latest write_some + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the stream's write_some function are + * required. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code boost::asio::write(s, boost::asio::buffer(data, size), + * boost::asio::transfer_at_least(32)); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, + CompletionCondition completion_condition); + +/// Write a certain amount of data to a stream before returning. +/** + * This function is used to write a certain number of bytes of data to a stream. + * The call will block until one of the following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the stream's + * write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the SyncWriteStream concept. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * stream. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const boost::system::error_code& error, // Result of latest write_some + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the stream's write_some function are + * required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, boost::system::error_code& ec); + +/// Write all of the supplied data to a stream before returning. +/** + * This function is used to write a certain number of bytes of data to a stream. + * The call will block until one of the following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the stream's + * write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the SyncWriteStream concept. + * + * @param b The basic_streambuf object from which data will be written. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This overload is equivalent to calling: + * @code boost::asio::write( + * s, b, + * boost::asio::transfer_all()); @endcode + */ +template +std::size_t write(SyncWriteStream& s, basic_streambuf& b); + +/// Write a certain amount of data to a stream before returning. +/** + * This function is used to write a certain number of bytes of data to a stream. + * The call will block until one of the following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the stream's + * write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the SyncWriteStream concept. + * + * @param b The basic_streambuf object from which data will be written. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const boost::system::error_code& error, // Result of latest write_some + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the stream's write_some function are + * required. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + */ +template +std::size_t write(SyncWriteStream& s, basic_streambuf& b, + CompletionCondition completion_condition); + +/// Write a certain amount of data to a stream before returning. +/** + * This function is used to write a certain number of bytes of data to a stream. + * The call will block until one of the following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the stream's + * write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the SyncWriteStream concept. + * + * @param b The basic_streambuf object from which data will be written. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const boost::system::error_code& error, // Result of latest write_some + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the stream's write_some function are + * required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t write(SyncWriteStream& s, basic_streambuf& b, + CompletionCondition completion_condition, boost::system::error_code& ec); + +/*@}*/ +/** + * @defgroup async_write boost::asio::async_write + * + * @brief Start an asynchronous operation to write a certain amount of data to a + * stream. + */ +/*@{*/ + +/// Start an asynchronous operation to write all of the supplied data to a +/// stream. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the stream's + * async_write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the AsyncWriteStream concept. + * + * @param buffers One or more buffers containing the data to be written. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes written from the + * // buffers. If an error occurred, + * // this will be less than the sum + * // of the buffer sizes. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::async_write(s, boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, + WriteHandler handler); + +/// Start an asynchronous operation to write a certain amount of data to a +/// stream. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the stream's + * async_write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the AsyncWriteStream concept. + * + * @param buffers One or more buffers containing the data to be written. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const boost::system::error_code& error, // Result of latest write_some + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the stream's async_write_some function are + * required. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes written from the + * // buffers. If an error occurred, + * // this will be less than the sum + * // of the buffer sizes. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code boost::asio::async_write(s, + * boost::asio::buffer(data, size), + * boost::asio::transfer_at_least(32), + * handler); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, WriteHandler handler); + +/// Start an asynchronous operation to write all of the supplied data to a +/// stream. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the stream's + * async_write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the AsyncWriteStream concept. + * + * @param b A basic_streambuf object from which data will be written. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes written from the + * // buffers. If an error occurred, + * // this will be less than the sum + * // of the buffer sizes. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ +template +void async_write(AsyncWriteStream& s, basic_streambuf& b, + WriteHandler handler); + +/// Start an asynchronous operation to write a certain amount of data to a +/// stream. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a stream. The function call always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the stream's + * async_write_some function. + * + * @param s The stream to which the data is to be written. The type must support + * the AsyncWriteStream concept. + * + * @param b A basic_streambuf object from which data will be written. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * const boost::system::error_code& error, // Result of latest write_some + * // operation. + * + * std::size_t bytes_transferred // Number of bytes transferred + * // so far. + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the stream's async_write_some function are + * required. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * + * std::size_t bytes_transferred // Number of bytes written from the + * // buffers. If an error occurred, + * // this will be less than the sum + * // of the buffer sizes. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ +template +void async_write(AsyncWriteStream& s, basic_streambuf& b, + CompletionCondition completion_condition, WriteHandler handler); + +/*@}*/ + +} // namespace asio +} // namespace boost + +#include + +#include + +#endif // BOOST_ASIO_WRITE_HPP diff --git a/win32/include/boost/asio/write_at.hpp b/win32/include/boost/asio/write_at.hpp new file mode 100755 index 000000000..0194675d6 --- /dev/null +++ b/win32/include/boost/asio/write_at.hpp @@ -0,0 +1,557 @@ +// +// write_at.hpp +// ~~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_WRITE_AT_HPP +#define BOOST_ASIO_WRITE_AT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace asio { + +/** + * @defgroup write_at boost::asio::write_at + * + * @brief Write a certain amount of data at a specified offset before returning. + */ +/*@{*/ + +/// Write all of the supplied data at the specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * device. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code boost::asio::write_at(d, 42, boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @note This overload is equivalent to calling: + * @code boost::asio::write_at( + * d, offset, buffers, + * boost::asio::transfer_all()); @endcode + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers); + +/// Write a certain amount of data at a specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * device. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's write_some_at function are + * required. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code boost::asio::write_at(d, 42, boost::asio::buffer(data, size), + * boost::asio::transfer_at_least(32)); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition); + +/// Write a certain amount of data at a specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. The sum + * of the buffer sizes indicates the maximum number of bytes to write to the + * device. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's write_some_at function are + * required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, boost::system::error_code& ec); + +/// Write all of the supplied data at the specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b The basic_streambuf object from which data will be written. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This overload is equivalent to calling: + * @code boost::asio::write_at( + * d, 42, b, + * boost::asio::transfer_all()); @endcode + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, + boost::uint64_t offset, basic_streambuf& b); + +/// Write a certain amount of data at a specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b The basic_streambuf object from which data will be written. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's write_some_at function are + * required. + * + * @returns The number of bytes transferred. + * + * @throws boost::system::system_error Thrown on failure. + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, boost::uint64_t offset, + basic_streambuf& b, CompletionCondition completion_condition); + +/// Write a certain amount of data at a specified offset before returning. +/** + * This function is used to write a certain number of bytes of data to a random + * access device at a specified offset. The call will block until one of the + * following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the SyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b The basic_streambuf object from which data will be written. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's write_some_at function are + * required. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. If an error occurs, returns the total + * number of bytes successfully transferred prior to the error. + */ +template +std::size_t write_at(SyncRandomAccessWriteDevice& d, boost::uint64_t offset, + basic_streambuf& b, CompletionCondition completion_condition, + boost::system::error_code& ec); + +/*@}*/ +/** + * @defgroup async_write_at boost::asio::async_write_at + * + * @brief Start an asynchronous operation to write a certain amount of data at + * the specified offset. + */ +/*@{*/ + +/// Start an asynchronous operation to write all of the supplied data at the +/// specified offset. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a random access device at a specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * async_write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the AsyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::async_write_at(d, 42, boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset, + const ConstBufferSequence& buffers, WriteHandler handler); + +/// Start an asynchronous operation to write a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a random access device at a specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li All of the data in the supplied buffers has been written. That is, the + * bytes transferred is equal to the sum of the buffer sizes. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * async_write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the AsyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more buffers containing the data to be written. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest write_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's async_write_some_at function are + * required. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code boost::asio::async_write_at(d, 42, + * boost::asio::buffer(data, size), + * boost::asio::transfer_at_least(32), + * handler); @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ +template +void async_write_at(AsyncRandomAccessWriteDevice& d, + boost::uint64_t offset, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, WriteHandler handler); + +/// Start an asynchronous operation to write all of the supplied data at the +/// specified offset. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a random access device at a specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li An error occurred. + * + * This operation is implemented in terms of one or more calls to the device's + * async_write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the AsyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b A basic_streambuf object from which data will be written. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ +template +void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset, + basic_streambuf& b, WriteHandler handler); + +/// Start an asynchronous operation to write a certain amount of data at the +/// specified offset. +/** + * This function is used to asynchronously write a certain number of bytes of + * data to a random access device at a specified offset. The function call + * always returns immediately. The asynchronous operation will continue until + * one of the following conditions is true: + * + * @li All of the data in the supplied basic_streambuf has been written. + * + * @li The completion_condition function object returns true. + * + * This operation is implemented in terms of one or more calls to the device's + * async_write_some_at function. + * + * @param d The device to which the data is to be written. The type must support + * the AsyncRandomAccessWriteDevice concept. + * + * @param offset The offset at which the data will be written. + * + * @param b A basic_streambuf object from which data will be written. Ownership + * of the streambuf is retained by the caller, which must guarantee that it + * remains valid until the handler is called. + * + * @param completion_condition The function object to be called to determine + * whether the write operation is complete. The signature of the function object + * must be: + * @code bool completion_condition( + * // Result of latest async_write_some_at operation. + * const boost::system::error_code& error, + * + * // Number of bytes transferred so far. + * std::size_t bytes_transferred + * ); @endcode + * A return value of true indicates that the write operation is complete. False + * indicates that further calls to the device's async_write_some_at function are + * required. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * // Result of operation. + * const boost::system::error_code& error, + * + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation of + * the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ +template +void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset, + basic_streambuf& b, CompletionCondition completion_condition, + WriteHandler handler); + +/*@}*/ + +} // namespace asio +} // namespace boost + +#include + +#include + +#endif // BOOST_ASIO_WRITE_AT_HPP diff --git a/win32/include/boost/assert.hpp b/win32/include/boost/assert.hpp new file mode 100755 index 000000000..281c46565 --- /dev/null +++ b/win32/include/boost/assert.hpp @@ -0,0 +1,50 @@ +// +// boost/assert.hpp - BOOST_ASSERT(expr) +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2007 Peter Dimov +// +// 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) +// +// Note: There are no include guards. This is intentional. +// +// See http://www.boost.org/libs/utility/assert.html for documentation. +// + +#undef BOOST_ASSERT + +#if defined(BOOST_DISABLE_ASSERTS) + +# define BOOST_ASSERT(expr) ((void)0) + +#elif defined(BOOST_ENABLE_ASSERT_HANDLER) + +#include + +namespace boost +{ + +void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined + +} // namespace boost + +#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__)) + +#else +# include // .h to support old libraries w/o - effect is the same +# define BOOST_ASSERT(expr) assert(expr) +#endif + +#undef BOOST_VERIFY + +#if defined(BOOST_DISABLE_ASSERTS) || ( !defined(BOOST_ENABLE_ASSERT_HANDLER) && defined(NDEBUG) ) + +# define BOOST_VERIFY(expr) ((void)(expr)) + +#else + +# define BOOST_VERIFY(expr) BOOST_ASSERT(expr) + +#endif diff --git a/win32/include/boost/assign.hpp b/win32/include/boost/assign.hpp new file mode 100755 index 000000000..6857f126e --- /dev/null +++ b/win32/include/boost/assign.hpp @@ -0,0 +1,24 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + + +#ifndef BOOST_ASSIGN_HPP +#define BOOST_ASSIGN_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/assign/assignment_exception.hpp b/win32/include/boost/assign/assignment_exception.hpp new file mode 100755 index 000000000..15d23c0ce --- /dev/null +++ b/win32/include/boost/assign/assignment_exception.hpp @@ -0,0 +1,43 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + + +#ifndef BOOST_ASSIGN_ASSIGNMENT_EXCEPTION_HPP +#define BOOST_ASSIGN_ASSIGNMENT_EXCEPTION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include + +namespace boost +{ + namespace assign + { + class assignment_exception : public std::exception + { + public: + assignment_exception( const char* what ) + : what_( what ) + { } + + virtual const char* what() const throw() + { + return what_; + } + + private: + const char* what_; + }; + } +} + +#endif diff --git a/win32/include/boost/assign/list_inserter.hpp b/win32/include/boost/assign/list_inserter.hpp new file mode 100755 index 000000000..ab5153032 --- /dev/null +++ b/win32/include/boost/assign/list_inserter.hpp @@ -0,0 +1,400 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + +#ifndef BOOST_ASSIGN_LIST_INSERTER_HPP +#define BOOST_ASSIGN_LIST_INSERTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace boost +{ +namespace assign_detail +{ + template< class T > + struct repeater + { + std::size_t sz; + T val; + + repeater( std::size_t sz, T r ) : sz( sz ), val( r ) + { } + }; + + template< class Fun > + struct fun_repeater + { + std::size_t sz; + Fun val; + + fun_repeater( std::size_t sz, Fun r ) : sz( sz ), val( r ) + { } + }; + + template< class C > + class call_push_back + { + C& c_; + public: + call_push_back( C& c ) : c_( c ) + { } + + template< class T > + void operator()( T r ) + { + c_.push_back( r ); + } + }; + + template< class C > + class call_push_front + { + C& c_; + public: + call_push_front( C& c ) : c_( c ) + { } + + template< class T > + void operator()( T r ) + { + c_.push_front( r ); + } + }; + + template< class C > + class call_push + { + C& c_; + public: + call_push( C& c ) : c_( c ) + { } + + template< class T > + void operator()( T r ) + { + c_.push( r ); + } + }; + + template< class C > + class call_insert + { + C& c_; + public: + call_insert( C& c ) : c_( c ) + { } + + template< class T > + void operator()( T r ) + { + c_.insert( r ); + } + }; + + template< class C > + class call_add_edge + { + C& c_; + public: + call_add_edge( C& c ) : c_(c) + { } + + template< class T > + void operator()( T l, T r ) + { + add_edge( l, r, c_ ); + } + + template< class T, class EP > + void operator()( T l, T r, const EP& ep ) + { + add_edge( l, r, ep, c_ ); + } + + }; + + struct forward_n_arguments {}; + +} // namespace 'assign_detail' + +namespace assign +{ + + template< class T > + inline assign_detail::repeater + repeat( std::size_t sz, T r ) + { + return assign_detail::repeater( sz, r ); + } + + template< class Function > + inline assign_detail::fun_repeater + repeat_fun( std::size_t sz, Function r ) + { + return assign_detail::fun_repeater( sz, r ); + } + + + template< class Function, class Argument = assign_detail::forward_n_arguments > + class list_inserter + { + struct single_arg_type {}; + struct n_arg_type {}; + + typedef BOOST_DEDUCED_TYPENAME mpl::if_c< is_same::value, + n_arg_type, + single_arg_type >::type arg_type; + + public: + + list_inserter( Function fun ) : insert_( fun ) + {} + + template< class Function2, class Arg > + list_inserter( const list_inserter& r ) + : insert_( r.fun_private() ) + {} + + list_inserter( const list_inserter& r ) : insert_( r.insert_ ) + {} + + list_inserter& operator()() + { + insert_( Argument() ); + return *this; + } + + template< class T > + list_inserter& operator=( const T& r ) + { + insert_( r ); + return *this; + } + + template< class T > + list_inserter& operator=( assign_detail::repeater r ) + { + return operator,( r ); + } + + template< class Nullary_function > + list_inserter& operator=( const assign_detail::fun_repeater& r ) + { + return operator,( r ); + } + + template< class T > + list_inserter& operator,( const T& r ) + { + insert_( r ); + return *this; + } + +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) + template< class T > + list_inserter& operator,( const assign_detail::repeater & r ) + { + return repeat( r.sz, r.val ); + } +#else + template< class T > + list_inserter& operator,( assign_detail::repeater r ) + { + return repeat( r.sz, r.val ); + } +#endif + + template< class Nullary_function > + list_inserter& operator,( const assign_detail::fun_repeater& r ) + { + return repeat_fun( r.sz, r.val ); + } + + template< class T > + list_inserter& repeat( std::size_t sz, T r ) + { + std::size_t i = 0; + while( i++ != sz ) + insert_( r ); + return *this; + } + + template< class Nullary_function > + list_inserter& repeat_fun( std::size_t sz, Nullary_function fun ) + { + std::size_t i = 0; + while( i++ != sz ) + insert_( fun() ); + return *this; + } + + template< class SinglePassIterator > + list_inserter& range( SinglePassIterator first, + SinglePassIterator last ) + { + for( ; first != last; ++first ) + insert_( *first ); + return *this; + } + + template< class SinglePassRange > + list_inserter& range( const SinglePassRange& r ) + { + return range( boost::begin(r), boost::end(r) ); + } + + template< class T > + list_inserter& operator()( const T& t ) + { + insert_( t ); + return *this; + } + +#ifndef BOOST_ASSIGN_MAX_PARAMS // use user's value +#define BOOST_ASSIGN_MAX_PARAMS 5 +#endif +#define BOOST_ASSIGN_MAX_PARAMETERS (BOOST_ASSIGN_MAX_PARAMS - 1) +#define BOOST_ASSIGN_PARAMS1(n) BOOST_PP_ENUM_PARAMS(n, class T) +#define BOOST_ASSIGN_PARAMS2(n) BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& t) +#define BOOST_ASSIGN_PARAMS3(n) BOOST_PP_ENUM_PARAMS(n, t) + +#define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS) +#define BOOST_PP_LOCAL_MACRO(n) \ + template< class T, BOOST_ASSIGN_PARAMS1(n) > \ + list_inserter& operator()(T t, BOOST_ASSIGN_PARAMS2(n) ) \ + { \ + BOOST_PP_CAT(insert, BOOST_PP_INC(n))(t, BOOST_ASSIGN_PARAMS3(n), arg_type()); \ + return *this; \ + } \ + /**/ + +#include BOOST_PP_LOCAL_ITERATE() + + +#define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS) +#define BOOST_PP_LOCAL_MACRO(n) \ + template< class T, BOOST_ASSIGN_PARAMS1(n) > \ + void BOOST_PP_CAT(insert, BOOST_PP_INC(n))(T const& t, BOOST_ASSIGN_PARAMS2(n), single_arg_type) \ + { \ + insert_( Argument(t, BOOST_ASSIGN_PARAMS3(n) )); \ + } \ + /**/ + +#include BOOST_PP_LOCAL_ITERATE() + +#define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS) +#define BOOST_PP_LOCAL_MACRO(n) \ + template< class T, BOOST_ASSIGN_PARAMS1(n) > \ + void BOOST_PP_CAT(insert, BOOST_PP_INC(n))(T const& t, BOOST_ASSIGN_PARAMS2(n), n_arg_type) \ + { \ + insert_(t, BOOST_ASSIGN_PARAMS3(n) ); \ + } \ + /**/ + +#include BOOST_PP_LOCAL_ITERATE() + + + Function fun_private() const + { + return insert_; + } + + private: + + list_inserter& operator=( const list_inserter& ); + Function insert_; + }; + + template< class Function > + inline list_inserter< Function > + make_list_inserter( Function fun ) + { + return list_inserter< Function >( fun ); + } + + template< class Function, class Argument > + inline list_inserter + make_list_inserter( Function fun, Argument* ) + { + return list_inserter( fun ); + } + + template< class C > + inline list_inserter< assign_detail::call_push_back, + BOOST_DEDUCED_TYPENAME C::value_type > + push_back( C& c ) + { + static BOOST_DEDUCED_TYPENAME C::value_type* p = 0; + return make_list_inserter( assign_detail::call_push_back( c ), + p ); + } + + template< class C > + inline list_inserter< assign_detail::call_push_front, + BOOST_DEDUCED_TYPENAME C::value_type > + push_front( C& c ) + { + static BOOST_DEDUCED_TYPENAME C::value_type* p = 0; + return make_list_inserter( assign_detail::call_push_front( c ), + p ); + } + + template< class C > + inline list_inserter< assign_detail::call_insert, + BOOST_DEDUCED_TYPENAME C::value_type > + insert( C& c ) + { + static BOOST_DEDUCED_TYPENAME C::value_type* p = 0; + return make_list_inserter( assign_detail::call_insert( c ), + p ); + } + + template< class C > + inline list_inserter< assign_detail::call_push, + BOOST_DEDUCED_TYPENAME C::value_type > + push( C& c ) + { + static BOOST_DEDUCED_TYPENAME C::value_type* p = 0; + return make_list_inserter( assign_detail::call_push( c ), + p ); + } + + template< class C > + inline list_inserter< assign_detail::call_add_edge > + add_edge( C& c ) + { + return make_list_inserter( assign_detail::call_add_edge( c ) ); + } + +} // namespace 'assign' +} // namespace 'boost' + +#undef BOOST_ASSIGN_PARAMS1 +#undef BOOST_ASSIGN_PARAMS2 +#undef BOOST_ASSIGN_PARAMS3 +#undef BOOST_ASSIGN_MAX_PARAMETERS + +#endif diff --git a/win32/include/boost/assign/list_of.hpp b/win32/include/boost/assign/list_of.hpp new file mode 100755 index 000000000..652384f87 --- /dev/null +++ b/win32/include/boost/assign/list_of.hpp @@ -0,0 +1,681 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + + +#ifndef BOOST_ASSIGN_LIST_OF_HPP +#define BOOST_ASSIGN_LIST_OF_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +// BCB requires full type definition for is_array<> to work correctly. +#include +#endif + +namespace boost +{ + +// this here is necessary to avoid compiler error in +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + template< class T, std::size_t sz > + class array; +#endif + +namespace assign_detail +{ + ///////////////////////////////////////////////////////////////////////// + // Part 0: common conversion code + ///////////////////////////////////////////////////////////////////////// + + template< class T > + struct assign_decay + { + // + // Add constness to array parameters + // to support string literals properly + // + typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< + ::boost::is_array, + ::boost::decay, + ::boost::decay >::type type; + }; + + template< class T, std::size_t sz > + type_traits::yes_type assign_is_array( const array* ); + type_traits::no_type assign_is_array( ... ); + template< class T, class U > + type_traits::yes_type assign_is_pair( const std::pair* ); + type_traits::no_type assign_is_pair( ... ); + + + + struct array_type_tag + { + #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + private: + char dummy_; // BCB would by default use 8 bytes + #endif + }; + struct adapter_type_tag + { + #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + private: + char dummy_; // BCB would by default use 8 bytes + #endif + }; + struct pair_type_tag + { + #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + private: + char dummy_; // BCB would by default use 8 bytes + #endif + }; + struct default_type_tag + { + #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + private: + char dummy_; // BCB would by default use 8 bytes + #endif + }; + + + + template< class DerivedTAssign, class Iterator > + class converter + { + public: // Range operations + typedef Iterator iterator; + typedef Iterator const_iterator; + + iterator begin() const + { + return static_cast(this)->begin(); + } + + iterator end() const + { + return static_cast(this)->end(); + } + + public: + + template< class Container > + Container convert_to_container() const + { + static Container* c = 0; + BOOST_STATIC_CONSTANT( bool, is_array_flag = sizeof( assign_detail::assign_is_array( c ) ) + == sizeof( type_traits::yes_type ) ); + + typedef BOOST_DEDUCED_TYPENAME mpl::if_c< is_array_flag, + array_type_tag, + default_type_tag >::type tag_type; + + return convert( c, tag_type() ); + } + + private: + + template< class Container > + Container convert( const Container*, default_type_tag ) const + { + +#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) +// old Dinkumware doesn't support iterator type as template + Container result; + iterator it = begin(), + e = end(); + while( it != e ) + { + result.insert( result.end(), *it ); + ++it; + } + return result; +#else + return Container( begin(), end() ); +#endif + } + + template< class Array > + Array convert( const Array*, array_type_tag ) const + { + typedef BOOST_DEDUCED_TYPENAME Array::value_type value_type; + +#if BOOST_WORKAROUND(BOOST_INTEL, <= 910 ) || BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580 ) + BOOST_DEDUCED_TYPENAME remove_const::type ar; +#else + Array ar; +#endif + const std::size_t sz = ar.size(); + if( sz < static_cast(this)->size() ) + throw assign::assignment_exception( "array initialized with too many elements" ); + std::size_t n = 0; + iterator i = begin(), + e = end(); + for( ; i != e; ++i, ++n ) + ar[n] = *i; + for( ; n < sz; ++n ) + ar[n] = value_type(); + return ar; + } + + template< class Adapter > + Adapter convert_to_adapter( const Adapter* = 0 ) const + { + Adapter a; + iterator i = begin(), + e = end(); + for( ; i != e; ++i ) + a.push( *i ); + return a; + } + + private: + struct adapter_converter; + friend struct adapter_converter; + + struct adapter_converter + { + const converter& gl; + adapter_converter( const converter& this_ ) : gl( this_ ) + {} + + adapter_converter( const adapter_converter& r ) + : gl( r.gl ) + { } + + template< class Adapter > + operator Adapter() const + { + return gl.convert_to_adapter(); + } + }; + + public: + template< class Container > + Container to_container( Container& c ) const + { + return convert( &c, default_type_tag() ); + } + + adapter_converter to_adapter() const + { + return adapter_converter( *this ); + } + + template< class Adapter > + Adapter to_adapter( Adapter& a ) const + { + return this->convert_to_adapter( &a ); + } + + template< class Array > + Array to_array( Array& a ) const + { + return convert( &a, array_type_tag() ); + } + }; + + template< class T, class I, class Range > + inline bool operator==( const converter& l, const Range& r ) + { + return ::boost::iterator_range_detail::equal( l, r ); + } + + template< class T, class I, class Range > + inline bool operator==( const Range& l, const converter& r ) + { + return r == l; + } + + template< class T, class I, class Range > + inline bool operator!=( const converter& l, const Range& r ) + { + return !( l == r ); + } + + template< class T, class I, class Range > + inline bool operator!=( const Range& l, const converter& r ) + { + return !( l == r ); + } + + template< class T, class I, class Range > + inline bool operator<( const converter& l, const Range& r ) + { + return ::boost::iterator_range_detail::less_than( l, r ); + } + + template< class T, class I, class Range > + inline bool operator<( const Range& l, const converter& r ) + { + return ::boost::iterator_range_detail::less_than( l, r ); + } + + template< class T, class I, class Range > + inline bool operator>( const converter& l, const Range& r ) + { + return r < l; + } + + template< class T, class I, class Range > + inline bool operator>( const Range& l, const converter& r ) + { + return r < l; + } + + template< class T, class I, class Range > + inline bool operator<=( const converter& l, const Range& r ) + { + return !( l > r ); + } + + template< class T, class I, class Range > + inline bool operator<=( const Range& l, const converter& r ) + { + return !( l > r ); + } + + template< class T, class I, class Range > + inline bool operator>=( const converter& l, const Range& r ) + { + return !( l < r ); + } + + template< class T, class I, class Range > + inline bool operator>=( const Range& l, const converter& r ) + { + return !( l < r ); + } + + template< class T, class I, class Elem, class Traits > + inline std::basic_ostream& + operator<<( std::basic_ostream& Os, + const converter& r ) + { + return Os << ::boost::make_iterator_range( r.begin(), r.end() ); + } + + ///////////////////////////////////////////////////////////////////////// + // Part 1: flexible, but inefficient interface + ///////////////////////////////////////////////////////////////////////// + + template< class T > + class generic_list : + public converter< generic_list< BOOST_DEDUCED_TYPENAME assign_decay::type >, + BOOST_DEDUCED_TYPENAME std::deque::type>::iterator > + { + typedef BOOST_DEDUCED_TYPENAME assign_decay::type Ty; + typedef std::deque impl_type; + mutable impl_type values_; + + public: + typedef BOOST_DEDUCED_TYPENAME impl_type::iterator iterator; + typedef iterator const_iterator; + typedef BOOST_DEDUCED_TYPENAME impl_type::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME impl_type::size_type size_type; + typedef BOOST_DEDUCED_TYPENAME impl_type::difference_type difference_type; + + public: + iterator begin() const { return values_.begin(); } + iterator end() const { return values_.end(); } + bool empty() const { return values_.empty(); } + size_type size() const { return values_.size(); } + + private: + void push_back( value_type r ) { values_.push_back( r ); } + + public: + generic_list& operator,( const Ty& u ) + { + this->push_back( u ); + return *this; + } + + generic_list& operator()() + { + this->push_back( Ty() ); + return *this; + } + + generic_list& operator()( const Ty& u ) + { + this->push_back( u ); + return *this; + } + + +#ifndef BOOST_ASSIGN_MAX_PARAMS // use user's value +#define BOOST_ASSIGN_MAX_PARAMS 5 +#endif +#define BOOST_ASSIGN_MAX_PARAMETERS (BOOST_ASSIGN_MAX_PARAMS - 1) +#define BOOST_ASSIGN_PARAMS1(n) BOOST_PP_ENUM_PARAMS(n, class U) +#define BOOST_ASSIGN_PARAMS2(n) BOOST_PP_ENUM_BINARY_PARAMS(n, U, const& u) +#define BOOST_ASSIGN_PARAMS3(n) BOOST_PP_ENUM_PARAMS(n, u) +#define BOOST_ASSIGN_PARAMS4(n) BOOST_PP_ENUM_PARAMS(n, U) +#define BOOST_ASSIGN_PARAMS2_NO_REF(n) BOOST_PP_ENUM_BINARY_PARAMS(n, U, u) + +#define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS) +#define BOOST_PP_LOCAL_MACRO(n) \ + template< class U, BOOST_ASSIGN_PARAMS1(n) > \ + generic_list& operator()(U const& u, BOOST_ASSIGN_PARAMS2(n) ) \ + { \ + this->push_back( Ty(u, BOOST_ASSIGN_PARAMS3(n))); \ + return *this; \ + } \ + /**/ + +#include BOOST_PP_LOCAL_ITERATE() + + + template< class U > + generic_list& repeat( std::size_t sz, U u ) + { + std::size_t i = 0; + while( i++ != sz ) + this->push_back( u ); + return *this; + } + + template< class Nullary_function > + generic_list& repeat_fun( std::size_t sz, Nullary_function fun ) + { + std::size_t i = 0; + while( i++ != sz ) + this->push_back( fun() ); + return *this; + } + + template< class SinglePassIterator > + generic_list& range( SinglePassIterator first, + SinglePassIterator last ) + { + for( ; first != last; ++first ) + this->push_back( *first ); + return *this; + } + + template< class SinglePassRange > + generic_list& range( const SinglePassRange& r ) + { + return range( boost::begin(r), boost::end(r) ); + } + + template< class Container > + operator Container() const + { + return this-> BOOST_NESTED_TEMPLATE convert_to_container(); + } + }; + + ///////////////////////////////////////////////////////////////////////// + // Part 2: efficient, but inconvenient interface + ///////////////////////////////////////////////////////////////////////// + + template< class T > + struct assign_reference + { + assign_reference() + { /* intentionally empty */ } + + assign_reference( T& r ) : ref_(&r) + { } + + void operator=( T& r ) + { + ref_ = &r; + } + + operator T&() const + { + return *ref_; + } + + void swap( assign_reference& r ) + { + std::swap( *ref_, *r.ref_ ); + } + + T& get_ref() const + { + return *ref_; + } + + private: + T* ref_; + + }; + + template< class T > + inline bool operator<( const assign_reference& l, + const assign_reference& r ) + { + return l.get_ref() < r.get_ref(); + } + + template< class T > + inline bool operator>( const assign_reference& l, + const assign_reference& r ) + { + return l.get_ref() > r.get_ref(); + } + + template< class T > + inline void swap( assign_reference& l, + assign_reference& r ) + { + l.swap( r ); + } + + + + template< class T, int N > + struct static_generic_list : + public converter< static_generic_list, assign_reference* > + { + private: + typedef T internal_value_type; + + public: + typedef assign_reference value_type; + typedef value_type* iterator; + typedef value_type* const_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + + static_generic_list( T& r ) : + current_(1) + { + refs_[0] = r; + } + + static_generic_list& operator()( T& r ) + { + insert( r ); + return *this; + } + + iterator begin() const + { + return &refs_[0]; + } + + iterator end() const + { + return &refs_[current_]; + } + + size_type size() const + { + return static_cast( current_ ); + } + + bool empty() const + { + return false; + } + + template< class ForwardIterator > + static_generic_list& range( ForwardIterator first, + ForwardIterator last ) + { + for( ; first != last; ++first ) + this->insert( *first ); + return *this; + } + + template< class ForwardRange > + static_generic_list& range( ForwardRange& r ) + { + return range( boost::begin(r), boost::end(r) ); + } + + template< class ForwardRange > + static_generic_list& range( const ForwardRange& r ) + { + return range( boost::begin(r), boost::end(r) ); + } + + template< class Container > + operator Container() const + { + return this-> BOOST_NESTED_TEMPLATE convert_to_container(); + } + + private: + void insert( T& r ) + { + refs_[current_] = r; + ++current_; + } + + static_generic_list(); + + mutable assign_reference refs_[N]; + int current_; + }; + +} // namespace 'assign_detail' + +namespace assign +{ + template< class T > + inline assign_detail::generic_list + list_of() + { + return assign_detail::generic_list()( T() ); + } + + template< class T > + inline assign_detail::generic_list + list_of( const T& t ) + { + return assign_detail::generic_list()( t ); + } + + template< int N, class T > + inline assign_detail::static_generic_list< BOOST_DEDUCED_TYPENAME assign_detail::assign_decay::type,N> + ref_list_of( T& t ) + { + return assign_detail::static_generic_list::type,N>( t ); + } + + template< int N, class T > + inline assign_detail::static_generic_list::type,N> + cref_list_of( const T& t ) + { + return assign_detail::static_generic_list::type,N>( t ); + } + +#define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS) +#define BOOST_PP_LOCAL_MACRO(n) \ + template< class T, class U, BOOST_ASSIGN_PARAMS1(n) > \ + inline assign_detail::generic_list \ + list_of(U const& u, BOOST_ASSIGN_PARAMS2(n) ) \ + { \ + return assign_detail::generic_list()(u, BOOST_ASSIGN_PARAMS3(n)); \ + } \ + /**/ + +#include BOOST_PP_LOCAL_ITERATE() + +#define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS) +#define BOOST_PP_LOCAL_MACRO(n) \ + template< class U, BOOST_ASSIGN_PARAMS1(n) > \ + inline assign_detail::generic_list< tuple > \ + tuple_list_of(U u, BOOST_ASSIGN_PARAMS2_NO_REF(n) ) \ + { \ + return assign_detail::generic_list< tuple >()( tuple( u, BOOST_ASSIGN_PARAMS3(n) )); \ + } \ + /**/ + +#include BOOST_PP_LOCAL_ITERATE() + + + template< class Key, class T > + inline assign_detail::generic_list< std::pair + < + BOOST_DEDUCED_TYPENAME assign_detail::assign_decay::type, + BOOST_DEDUCED_TYPENAME assign_detail::assign_decay::type + > > + map_list_of( const Key& k, const T& t ) + { + typedef BOOST_DEDUCED_TYPENAME assign_detail::assign_decay::type k_type; + typedef BOOST_DEDUCED_TYPENAME assign_detail::assign_decay::type t_type; + return assign_detail::generic_list< std::pair >()( k, t ); + } + + template< class F, class S > + inline assign_detail::generic_list< std::pair + < + BOOST_DEDUCED_TYPENAME assign_detail::assign_decay::type, + BOOST_DEDUCED_TYPENAME assign_detail::assign_decay::type + > > + pair_list_of( const F& f, const S& s ) + { + return map_list_of( f, s ); + } + + +} // namespace 'assign' +} // namespace 'boost' + + +#undef BOOST_ASSIGN_PARAMS1 +#undef BOOST_ASSIGN_PARAMS2 +#undef BOOST_ASSIGN_PARAMS3 +#undef BOOST_ASSIGN_PARAMS4 +#undef BOOST_ASSIGN_PARAMS2_NO_REF +#undef BOOST_ASSIGN_MAX_PARAMETERS + +#endif diff --git a/win32/include/boost/assign/ptr_list_inserter.hpp b/win32/include/boost/assign/ptr_list_inserter.hpp new file mode 100755 index 000000000..aa8302c5b --- /dev/null +++ b/win32/include/boost/assign/ptr_list_inserter.hpp @@ -0,0 +1,164 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2005. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + +#ifndef BOOST_ASSIGN_PTR_LIST_INSERTER_HPP +#define BOOST_ASSIGN_PTR_LIST_INSERTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ + +namespace assign +{ + template< class Function, class Obj > + class ptr_list_inserter + { + typedef BOOST_DEDUCED_TYPENAME + remove_pointer< BOOST_DEDUCED_TYPENAME + remove_reference::type >::type + obj_type; + public: + + ptr_list_inserter( Function fun ) : insert_( fun ) + {} + + template< class Function2, class Obj2 > + ptr_list_inserter( const ptr_list_inserter& r ) + : insert_( r.fun_private() ) + {} + + ptr_list_inserter( const ptr_list_inserter& r ) : insert_( r.insert_ ) + {} + + ptr_list_inserter& operator()() + { + insert_( new obj_type() ); + return *this; + } + + template< class T > + ptr_list_inserter& operator()( const T& t ) + { + insert_( new obj_type(t) ); + return *this; + } + +#ifndef BOOST_ASSIGN_MAX_PARAMS // use user's value +#define BOOST_ASSIGN_MAX_PARAMS 5 +#endif +#define BOOST_ASSIGN_MAX_PARAMETERS (BOOST_ASSIGN_MAX_PARAMS - 1) +#define BOOST_ASSIGN_PARAMS1(n) BOOST_PP_ENUM_PARAMS(n, class T) +#define BOOST_ASSIGN_PARAMS2(n) BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& t) +#define BOOST_ASSIGN_PARAMS3(n) BOOST_PP_ENUM_PARAMS(n, t) + +#define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS) +#define BOOST_PP_LOCAL_MACRO(n) \ + template< class T, BOOST_ASSIGN_PARAMS1(n) > \ + ptr_list_inserter& operator()( const T& t, BOOST_ASSIGN_PARAMS2(n) ) \ + { \ + insert_( new obj_type(t, BOOST_ASSIGN_PARAMS3(n) )); \ + return *this; \ + } \ + /**/ + +#include BOOST_PP_LOCAL_ITERATE() + + private: + + ptr_list_inserter& operator=( const ptr_list_inserter& ); + Function insert_; + }; + + template< class Obj, class Function > + inline ptr_list_inserter< Function, Obj > + make_ptr_list_inserter( Function fun ) + { + return ptr_list_inserter< Function, Obj >( fun ); + } + + template< class C > + inline ptr_list_inserter< assign_detail::call_push_back, + BOOST_DEDUCED_TYPENAME C::reference > + ptr_push_back( C& c ) + { + return make_ptr_list_inserter + ( assign_detail::call_push_back( c ) ); + } + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + + template< class T, class C > + inline ptr_list_inserter< assign_detail::call_push_back, T > + ptr_push_back( C& c ) + { + return make_ptr_list_inserter( + assign_detail::call_push_back( c ) ); + } + +#endif + + template< class C > + inline ptr_list_inserter< assign_detail::call_push_front, + BOOST_DEDUCED_TYPENAME C::reference > + ptr_push_front( C& c ) + { + return make_ptr_list_inserter + ( assign_detail::call_push_front( c ) ); + } + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + + template< class T, class C > + inline ptr_list_inserter< assign_detail::call_push_front, T > + ptr_push_front( C& c ) + { + return make_ptr_list_inserter( + assign_detail::call_push_front( c ) ); + } + +#endif + + template< class C > + inline ptr_list_inserter< assign_detail::call_insert, + BOOST_DEDUCED_TYPENAME C::reference> + ptr_insert( C& c ) + { + return make_ptr_list_inserter + ( assign_detail::call_insert( c ) ); + } + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + + template< class T, class C > + inline ptr_list_inserter< assign_detail::call_insert, T > + ptr_insert( C& c ) + { + return make_ptr_list_inserter( assign_detail::call_insert( c ) ); + } + +#endif + + +} // namespace 'assign' +} // namespace 'boost' + +#undef BOOST_ASSIGN_PARAMS1 +#undef BOOST_ASSIGN_PARAMS2 +#undef BOOST_ASSIGN_PARAMS3 +#undef BOOST_ASSIGN_MAX_PARAMETERS + +#endif diff --git a/win32/include/boost/assign/ptr_list_of.hpp b/win32/include/boost/assign/ptr_list_of.hpp new file mode 100755 index 000000000..3f314e6a0 --- /dev/null +++ b/win32/include/boost/assign/ptr_list_of.hpp @@ -0,0 +1,191 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2005. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + + +#ifndef BOOST_ASSIGN_PTR_LIST_OF_HPP +#define BOOST_ASSIGN_PTR_LIST_OF_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace boost +{ + +namespace assign_detail +{ + ///////////////////////////////////////////////////////////////////////// + // Part 1: flexible and efficient interface + ///////////////////////////////////////////////////////////////////////// + + template< class T > + class generic_ptr_list : + public converter< generic_ptr_list, + BOOST_DEDUCED_TYPENAME boost::ptr_vector::iterator > + { + protected: + typedef boost::ptr_vector impl_type; + typedef std::auto_ptr release_type; + mutable impl_type values_; + + public: + typedef BOOST_DEDUCED_TYPENAME impl_type::iterator iterator; + typedef iterator const_iterator; + typedef BOOST_DEDUCED_TYPENAME impl_type::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME impl_type::size_type size_type; + typedef BOOST_DEDUCED_TYPENAME impl_type::difference_type difference_type; + public: + generic_ptr_list() : values_( 32u ) + { } + + generic_ptr_list( release_type r ) : values_(r) + { } + + release_type release() + { + return values_.release(); + } + + public: + iterator begin() const { return values_.begin(); } + iterator end() const { return values_.end(); } + bool empty() const { return values_.empty(); } + size_type size() const { return values_.size(); } + + public: + + operator impl_type() const + { + return values_; + } + + template< template class Seq, class U, + class CA, class A > + operator Seq() const + { + Seq result; + result.transfer( result.end(), values_ ); + BOOST_ASSERT( empty() ); + return result; + } + + template< class PtrContainer > + std::auto_ptr convert( const PtrContainer* c ) const + { + std::auto_ptr res( new PtrContainer() ); + while( !empty() ) + res->insert( res->end(), + values_.pop_back().release() ); + return res; + } + + template< class PtrContainer > + std::auto_ptr to_container( const PtrContainer& c ) const + { + return convert( &c ); + } + + protected: + void push_back( T* r ) { values_.push_back( r ); } + + public: + generic_ptr_list& operator()() + { + this->push_back( new T() ); + return *this; + } + + template< class U > + generic_ptr_list& operator()( const U& u ) + { + this->push_back( new T(u) ); + return *this; + } + + +#ifndef BOOST_ASSIGN_MAX_PARAMS // use user's value +#define BOOST_ASSIGN_MAX_PARAMS 5 +#endif +#define BOOST_ASSIGN_MAX_PARAMETERS (BOOST_ASSIGN_MAX_PARAMS - 1) +#define BOOST_ASSIGN_PARAMS1(n) BOOST_PP_ENUM_PARAMS(n, class U) +#define BOOST_ASSIGN_PARAMS2(n) BOOST_PP_ENUM_BINARY_PARAMS(n, U, const& u) +#define BOOST_ASSIGN_PARAMS3(n) BOOST_PP_ENUM_PARAMS(n, u) + +#define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS) +#define BOOST_PP_LOCAL_MACRO(n) \ + template< class U, BOOST_ASSIGN_PARAMS1(n) > \ + generic_ptr_list& operator()(U const& u, BOOST_ASSIGN_PARAMS2(n) ) \ + { \ + this->push_back( new T(u, BOOST_ASSIGN_PARAMS3(n))); \ + return *this; \ + } \ + /**/ + +#include BOOST_PP_LOCAL_ITERATE() + + }; // class 'generic_ptr_list' + +} // namespace 'assign_detail' + +namespace assign +{ + template< class T > + inline assign_detail::generic_ptr_list + ptr_list_of() + { + return assign_detail::generic_ptr_list()(); + } + + template< class T, class U > + inline assign_detail::generic_ptr_list + ptr_list_of( const U& t ) + { + return assign_detail::generic_ptr_list()( t ); + } + + +#define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS) +#define BOOST_PP_LOCAL_MACRO(n) \ + template< class T, class U, BOOST_ASSIGN_PARAMS1(n) > \ + inline assign_detail::generic_ptr_list \ + ptr_list_of(U const& u, BOOST_ASSIGN_PARAMS2(n) ) \ + { \ + return assign_detail::generic_ptr_list()(u, BOOST_ASSIGN_PARAMS3(n)); \ + } \ + /**/ + +#include BOOST_PP_LOCAL_ITERATE() + + +} // namespace 'assign' +} // namespace 'boost' + + +#undef BOOST_ASSIGN_PARAMS1 +#undef BOOST_ASSIGN_PARAMS2 +#undef BOOST_ASSIGN_PARAMS3 +#undef BOOST_ASSIGN_MAX_PARAMETERS + +#endif diff --git a/win32/include/boost/assign/ptr_map_inserter.hpp b/win32/include/boost/assign/ptr_map_inserter.hpp new file mode 100755 index 000000000..69de771aa --- /dev/null +++ b/win32/include/boost/assign/ptr_map_inserter.hpp @@ -0,0 +1,103 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2006. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + +#ifndef BOOST_ASSIGN_PTR_CONTAINER_PTR_MAP_INSERTER_HPP +#define BOOST_ASSIGN_PTR_CONTAINER_PTR_MAP_INSERTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ + +namespace assign +{ + template< class PtrMap, class Obj > + class ptr_map_inserter + { + typedef BOOST_DEDUCED_TYPENAME + remove_pointer< BOOST_DEDUCED_TYPENAME + remove_reference::type >::type + obj_type; + typedef BOOST_DEDUCED_TYPENAME PtrMap::key_type + key_type; + + public: + + ptr_map_inserter( PtrMap& m ) : m_( m ) + {} + + template< class Key > + ptr_map_inserter& operator()( const Key& t ) + { + key_type k(t); + m_.insert( k, new obj_type ); + return *this; + } + +#ifndef BOOST_ASSIGN_MAX_PARAMS // use user's value +#define BOOST_ASSIGN_MAX_PARAMS 6 +#endif +#define BOOST_ASSIGN_MAX_PARAMETERS (BOOST_ASSIGN_MAX_PARAMS - 1) +#define BOOST_ASSIGN_PARAMS1(n) BOOST_PP_ENUM_PARAMS(n, class T) +#define BOOST_ASSIGN_PARAMS2(n) BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& t) +#define BOOST_ASSIGN_PARAMS3(n) BOOST_PP_ENUM_PARAMS(n, t) + +#define BOOST_PP_LOCAL_LIMITS (1, BOOST_ASSIGN_MAX_PARAMETERS) +#define BOOST_PP_LOCAL_MACRO(n) \ + template< class T, BOOST_ASSIGN_PARAMS1(n) > \ + ptr_map_inserter& operator()( const T& t, BOOST_ASSIGN_PARAMS2(n) ) \ + { \ + key_type k(t); \ + m_.insert( k, new obj_type( BOOST_ASSIGN_PARAMS3(n) ) ); \ + return *this; \ + } \ + /**/ + +#include BOOST_PP_LOCAL_ITERATE() + + private: + + ptr_map_inserter& operator=( const ptr_map_inserter& ); + PtrMap& m_; + }; + + template< class PtrMap > + inline ptr_map_inserter< PtrMap, typename PtrMap::mapped_reference > + ptr_map_insert( PtrMap& m ) + { + return ptr_map_inserter< PtrMap, typename PtrMap::mapped_reference >( m ); + } + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + + template< class T, class PtrMap > + inline ptr_map_inserter< PtrMap, T > + ptr_map_insert( PtrMap& m ) + { + return ptr_map_inserter< PtrMap, T >( m ); + } + +#endif + +} // namespace 'assign' +} // namespace 'boost' + +#undef BOOST_ASSIGN_PARAMS1 +#undef BOOST_ASSIGN_PARAMS2 +#undef BOOST_ASSIGN_PARAMS3 +#undef BOOST_ASSIGN_MAX_PARAMETERS + +#endif diff --git a/win32/include/boost/assign/std.hpp b/win32/include/boost/assign/std.hpp new file mode 100755 index 000000000..68c8a67c5 --- /dev/null +++ b/win32/include/boost/assign/std.hpp @@ -0,0 +1,27 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + +#ifndef BOOST_ASSIGN_STD_HPP +#define BOOST_ASSIGN_STD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/assign/std/deque.hpp b/win32/include/boost/assign/std/deque.hpp new file mode 100755 index 000000000..97484e590 --- /dev/null +++ b/win32/include/boost/assign/std/deque.hpp @@ -0,0 +1,38 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + + +#ifndef BOOST_ASSIGN_STD_DEQUE_HPP +#define BOOST_ASSIGN_STD_DEQUE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ +namespace assign +{ + + template< class V, class A, class V2 > + inline list_inserter< assign_detail::call_push_back< std::deque >, V > + operator+=( std::deque& c, V2 v ) + { + return push_back( c )( v ); + } + +} +} + +#endif diff --git a/win32/include/boost/assign/std/list.hpp b/win32/include/boost/assign/std/list.hpp new file mode 100755 index 000000000..10b1a9b2d --- /dev/null +++ b/win32/include/boost/assign/std/list.hpp @@ -0,0 +1,38 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + + +#ifndef BOOST_ASSIGN_STD_LIST_HPP +#define BOOST_ASSIGN_STD_LIST_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ +namespace assign +{ + + template< class V, class A, class V2 > + inline list_inserter< assign_detail::call_push_back< std::list >, V > + operator+=( std::list& c, V2 v ) + { + return push_back( c )( v ); + } + +} +} + +#endif diff --git a/win32/include/boost/assign/std/map.hpp b/win32/include/boost/assign/std/map.hpp new file mode 100755 index 000000000..9ecbedda1 --- /dev/null +++ b/win32/include/boost/assign/std/map.hpp @@ -0,0 +1,45 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + + +#ifndef BOOST_ASSIGN_STD_MAP_HPP +#define BOOST_ASSIGN_STD_MAP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ +namespace assign +{ + + template< class K, class V, class C, class A, class P > + inline list_inserter< assign_detail::call_insert< std::map >, P > + operator+=( std::map& m, const P& p ) + { + return insert( m )( p ); + } + + template< class K, class V, class C, class A, class P > + inline list_inserter< assign_detail::call_insert< std::multimap >, P > + operator+=( std::multimap& m, const P& p ) + { + return insert( m )( p ); + } + +} +} + +#endif diff --git a/win32/include/boost/assign/std/queue.hpp b/win32/include/boost/assign/std/queue.hpp new file mode 100755 index 000000000..e654511bc --- /dev/null +++ b/win32/include/boost/assign/std/queue.hpp @@ -0,0 +1,45 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + + +#ifndef BOOST_ASSIGN_STD_QUEUE_HPP +#define BOOST_ASSIGN_STD_QUEUE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ +namespace assign +{ + + template< class V, class C, class V2 > + inline list_inserter< assign_detail::call_push< std::queue >, V > + operator+=( std::queue& c, V2 v ) + { + return push( c )( v ); + } + + template< class V, class C, class V2 > + inline list_inserter< assign_detail::call_push< std::priority_queue >, V > + operator+=( std::priority_queue& c, V2 v ) + { + return push( c )( v ); + } + +} +} + +#endif diff --git a/win32/include/boost/assign/std/set.hpp b/win32/include/boost/assign/std/set.hpp new file mode 100755 index 000000000..3ca0316fb --- /dev/null +++ b/win32/include/boost/assign/std/set.hpp @@ -0,0 +1,44 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + + +#ifndef BOOST_ASSIGN_STD_SET_HPP +#define BOOST_ASSIGN_STD_SET_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ +namespace assign +{ + template< class K, class C, class A, class K2 > + inline list_inserter< assign_detail::call_insert< std::set >, K > + operator+=( std::set& c, K2 k ) + { + return insert( c )( k ); + } + + template< class K, class C, class A, class K2 > + inline list_inserter< assign_detail::call_insert< std::multiset >, K > + operator+=( std::multiset& c, K2 k ) + { + return insert( c )( k ); + } + +} +} + +#endif diff --git a/win32/include/boost/assign/std/slist.hpp b/win32/include/boost/assign/std/slist.hpp new file mode 100755 index 000000000..c357335c8 --- /dev/null +++ b/win32/include/boost/assign/std/slist.hpp @@ -0,0 +1,45 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + +#ifndef BOOST_ASSIGN_STD_SLIST_HPP +#define BOOST_ASSIGN_STD_SLIST_HPP + +#include +#ifdef BOOST_HAS_SLIST + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#ifdef BOOST_SLIST_HEADER +# include BOOST_SLIST_HEADER +#else +# include +#endif + +namespace boost +{ +namespace assign +{ + + template< class V, class A, class V2 > + inline list_inserter< assign_detail::call_push_back< BOOST_STD_EXTENSION_NAMESPACE::slist >, V > + operator+=( BOOST_STD_EXTENSION_NAMESPACE::slist& c, V2 v ) + { + return push_back( c )( v ); + } + +} +} + +#endif // BOOST_HAS_SLIST + +#endif diff --git a/win32/include/boost/assign/std/stack.hpp b/win32/include/boost/assign/std/stack.hpp new file mode 100755 index 000000000..003a8d6f1 --- /dev/null +++ b/win32/include/boost/assign/std/stack.hpp @@ -0,0 +1,37 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + +#ifndef BOOST_ASSIGN_STD_STACK_HPP +#define BOOST_ASSIGN_STD_STACK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ +namespace assign +{ + + template< class V, class C, class V2 > + inline list_inserter< assign_detail::call_push< std::stack >, V > + operator+=( std::stack& c, V2 v ) + { + return push( c )( v ); + } + +} +} + +#endif diff --git a/win32/include/boost/assign/std/vector.hpp b/win32/include/boost/assign/std/vector.hpp new file mode 100755 index 000000000..f955ea2c1 --- /dev/null +++ b/win32/include/boost/assign/std/vector.hpp @@ -0,0 +1,37 @@ +// Boost.Assign library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/assign/ +// + +#ifndef BOOST_ASSIGN_STD_VECTOR_HPP +#define BOOST_ASSIGN_STD_VECTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ +namespace assign +{ + + template< class V, class A, class V2 > + inline list_inserter< assign_detail::call_push_back< std::vector >, V > + operator+=( std::vector& c, V2 v ) + { + return push_back( c )( v ); + } + +} +} + +#endif diff --git a/win32/include/boost/bimap.hpp b/win32/include/boost/bimap.hpp new file mode 100755 index 000000000..015097acf --- /dev/null +++ b/win32/include/boost/bimap.hpp @@ -0,0 +1,19 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +// See www.boost.org/libs/bimap for documentation. + +// Convenience header + +#include + +namespace boost +{ + using ::boost::bimaps::bimap; +} + diff --git a/win32/include/boost/bimap/bimap.hpp b/win32/include/boost/bimap/bimap.hpp new file mode 100755 index 000000000..9135ad9cd --- /dev/null +++ b/win32/include/boost/bimap/bimap.hpp @@ -0,0 +1,430 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file bimap.hpp +/// \brief Includes the basic bimap container + +/** \mainpage notitle +\n +\image html http://matias.capeletto.googlepages.com/boost.bimap.reference.logo.png + +\section Introduction + +This is the complete reference of Boost.Bimap. + +After getting a good understanding of the library from a user perspective +the next step will be: + + - Understand the tagged idiom. (boost::bimaps::tags) + - Understand the internals of the relation class (boost::bimaps::relation) + - Read the container_adaptor toolbox docs (boost::bimaps::container_adaptor) + - Understand the internals of the bimap class. (boost::bimaps, boost::bimaps::views + and boost::bimaps::detail) + + + **/ + +/** \defgroup mutant_group mutant idiom +\brief A safe wrapper around reinterpret_cast + **/ + +/** \defgroup relation_group relation +\brief The relation + **/ + +/** \defgroup tags_group tagged idiom +\brief The tagged idiom + **/ + + +#ifndef BOOST_BIMAP_BIMAP_HPP +#define BOOST_BIMAP_BIMAP_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include +#include +#include + +#ifndef BOOST_BIMAP_DISABLE_SERIALIZATION + #include +#endif // BOOST_BIMAP_DISABLE_SERIALIZATION + +// Boost.Bimap +#include +#include +#include +#include +#include + +#include +#include +#include + +/// \brief The namespace where all the boost libraries lives. + +namespace boost { + +/// \brief Boost.Bimap library namespace +/** +All the entities in the library are defined in this namespace. + **/ +namespace bimaps { + +/// \brief The bimap class is the entry point to the library. +/** +This class manages the instantiation of the desired bimap type. +As there are several types of bidirectional maps that can be +created using it. the main job of it is to find the desired +type. This is done using metaprogramming to obtain the relation +type that will be stored, the map_view type of each side and +the set_view type of the general relationship. The instantiation +is kept simple using an extended standard set theory, where a +bidirectional map type is defined by the set types it relates. +For example, a bidirectional map that has multimap semantics +viewed from both sides is defined by specifying that the two +keys sets are of \c multiset_of type. +This allows the bimap class to support seamingless N-N, 1-N, +ordered/unordered and even vector-list types of mapping. +The three last parameters are used to specify the set type of +the relation, an inplace hooked data class and the allocator +type. As a help to the bimap user, these parameters support +default types but use a special idiom that allow them to be +specified without interleaving the usual use_default keyword. +The possible bimap instantiation are enumerated here: +\c {Side}KeyType can be directly a type, this is default to +\c set_of<{Side}KeyType>, or can be a \c {SetType}_of +specification. Additionally this two parameters can be tagged +to specify others tags instead of the usual \c member_at::{Side} +ones. + + +\code + + typedef bimap + < + LeftCollectionType, RightCollectionType + + [ , SetTypeOfRelation ] // Default to left_based + [ , info_hook< Info > ] // Default to no info + [ , Allocator ] // Default to std::allocator<> + + > bm; + +\endcode + + **/ + + +template +< + class KeyTypeA, class KeyTypeB, + class AP1 = ::boost::mpl::na, + class AP2 = ::boost::mpl::na, + class AP3 = ::boost::mpl::na +> +class bimap +: + // Bimap Core, use mpl magic to find the desired bimap type + + public ::boost::bimaps::detail::bimap_core, + + // You can use bimap as a collection of relations + + public ::boost::bimaps::detail::bimap_core + ::relation_set, + + // Include extra typedefs (i.e. left_local_iterator for unordered_map) + + public ::boost::bimaps::detail:: left_map_view_extra_typedefs< + BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail::left_map_view_type< + ::boost::bimaps::detail::bimap_core + >::type + >, + public ::boost::bimaps::detail::right_map_view_extra_typedefs< + BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail::right_map_view_type< + ::boost::bimaps::detail::bimap_core + >::type + > +{ + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail:: + bimap_core base_; + + BOOST_DEDUCED_TYPENAME base_::core_type core; + + public: + + // metadata -------------------------------------------------------- + + /* + // The rest is computed in the core, because it is quite difficult to + // expose a nice interface with so many metaprogramming stuff. + // Here it is the complete metadat list. + + // Map by {side} metadata + + typedef -unspecified- {side}_tag; + typedef -unspecified- {side}_data_type; + typedef -unspecified- {side}_value_type; + typedef -unspecified- {side}_key_type; + typedef -unspecified- {side}_iterator; + typedef -unspecified- {side}_const_iterator; + + ------------------------------------------------------------------*/ + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail:: + left_map_view_type::type left_map; + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail:: + right_map_view_type::type right_map; + + typedef BOOST_DEDUCED_TYPENAME + left_map::reference left_reference; + typedef BOOST_DEDUCED_TYPENAME + left_map::const_reference left_const_reference; + + typedef BOOST_DEDUCED_TYPENAME + right_map::reference right_reference; + typedef BOOST_DEDUCED_TYPENAME + right_map::const_reference right_const_reference; + + typedef BOOST_DEDUCED_TYPENAME base_::relation::info_type info_type; + + /// Left map view + left_map left; + + /// Right map view + right_map right; + + bimap() : + + base_::relation_set( + ::boost::multi_index::get< + BOOST_DEDUCED_TYPENAME base_::logic_relation_set_tag + >(core) + ), + left ( + ::boost::multi_index::get< + BOOST_DEDUCED_TYPENAME base_::logic_left_tag + >(core) + ), + right ( + ::boost::multi_index::get< + BOOST_DEDUCED_TYPENAME base_::logic_right_tag + >(core) + ) + + {} + + template< class InputIterator > + bimap(InputIterator first,InputIterator last) : + + base_::relation_set( + ::boost::multi_index::get< + BOOST_DEDUCED_TYPENAME base_::logic_relation_set_tag + >(core) + ), + + core(first,last), + + left ( + ::boost::multi_index::get< + BOOST_DEDUCED_TYPENAME base_::logic_left_tag + >(core) + ), + right ( + ::boost::multi_index::get< + BOOST_DEDUCED_TYPENAME base_::logic_right_tag + >(core) + ) + + {} + + bimap(const bimap& x) : + + base_::relation_set( + ::boost::multi_index::get< + BOOST_DEDUCED_TYPENAME base_::logic_relation_set_tag + >(core) + ), + + core(x.core), + + left ( + ::boost::multi_index::get< + BOOST_DEDUCED_TYPENAME base_::logic_left_tag + >(core) + ), + right ( + ::boost::multi_index::get< + BOOST_DEDUCED_TYPENAME base_::logic_right_tag + >(core) + ) + + {} + + bimap& operator=(const bimap& x) + { + core = x.core; + return *this; + } + + // Projection of iterators + + template< class IteratorType > + BOOST_DEDUCED_TYPENAME base_::left_iterator + project_left(IteratorType iter) + { + return core.template project< + BOOST_DEDUCED_TYPENAME base_::logic_left_tag>(iter.base()); + } + + template< class IteratorType > + BOOST_DEDUCED_TYPENAME base_::left_const_iterator + project_left(IteratorType iter) const + { + return core.template project< + BOOST_DEDUCED_TYPENAME base_::logic_left_tag>(iter.base()); + } + + template< class IteratorType > + BOOST_DEDUCED_TYPENAME base_::right_iterator + project_right(IteratorType iter) + { + return core.template project< + BOOST_DEDUCED_TYPENAME base_::logic_right_tag>(iter.base()); + } + + template< class IteratorType > + BOOST_DEDUCED_TYPENAME base_::right_const_iterator + project_right(IteratorType iter) const + { + return core.template project< + BOOST_DEDUCED_TYPENAME base_::logic_right_tag>(iter.base()); + } + + template< class IteratorType > + BOOST_DEDUCED_TYPENAME base_::relation_set::iterator + project_up(IteratorType iter) + { + return core.template project< + BOOST_DEDUCED_TYPENAME base_::logic_relation_set_tag>(iter.base()); + } + + template< class IteratorType > + BOOST_DEDUCED_TYPENAME base_::relation_set::const_iterator + project_up(IteratorType iter) const + { + return core.template project< + BOOST_DEDUCED_TYPENAME base_::logic_relation_set_tag>(iter.base()); + } + + // Support for tags + + template< class Tag, class IteratorType > + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + iterator_type_by::type + project(IteratorType iter + BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag)) + { + return core.template project(iter.base()); + } + + template< class Tag, class IteratorType > + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + const_iterator_type_by::type + project(IteratorType iter + BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Tag)) const + { + return core.template project(iter.base()); + } + + template< class Tag > + struct map_by : + public ::boost::bimaps::support::map_type_by::type + { + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + map_type_by::type type; + + private: map_by() {} + }; + + template< class Tag > + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + map_type_by::type & + by(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) + { + return ::boost::bimaps::support::map_by(*this); + } + + template< class Tag > + const BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + map_type_by::type & + by(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) const + { + return ::boost::bimaps::support::map_by(*this); + } + + + #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION + + // Serialization support + + private: + + friend class boost::serialization::access; + + template + void serialize(Archive & ar, const unsigned int version) + { + ar & serialization::make_nvp("mi_core",core); + } + + #endif // BOOST_BIMAP_DISABLE_SERIALIZATION +}; + +} // namespace bimaps +} // namespace boost + + +/** \namespace boost::bimaps::support +\brief Metafunctions to help working with bimaps. + **/ + +/** \namespace boost::bimaps::views +\brief Bimap views. + **/ + +/** \namespace boost::bimaps::views::detail +\brief Bimap views details. + **/ + + + +// Include basic tools for user commodity + +#include +#include +#include + +// Bring the most used namespaces directly to the user main namespace +namespace boost { +namespace bimaps { + +using ::boost::bimaps::tags::tagged; + +namespace member_at = ::boost::bimaps::relation::member_at; + +using ::boost::multi_index::unbounded; + +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_BIMAP_HPP diff --git a/win32/include/boost/bimap/container_adaptor/associative_container_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/associative_container_adaptor.hpp new file mode 100755 index 000000000..0c6f4c119 --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/associative_container_adaptor.hpp @@ -0,0 +1,287 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/associative_container_adaptor.hpp +/// \brief Container adaptor to build a type that is compliant to the concept of an associative container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template +< + class Base, class Iterator, class ConstIterator, class KeyType, + class IteratorToBaseConverter, class IteratorFromBaseConverter, + class ValueToBaseConverter, class ValueFromBaseConverter, class KeyToBaseConverter, + class FunctorsFromDerivedClasses +> +struct associative_container_adaptor_base +{ + typedef container_adaptor + < + Base, + + Iterator, ConstIterator, + + IteratorToBaseConverter, IteratorFromBaseConverter, + ValueToBaseConverter , ValueFromBaseConverter, + + BOOST_DEDUCED_TYPENAME mpl::push_front< + + FunctorsFromDerivedClasses, + + BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na, + // { + detail::key_to_base_identity + < + BOOST_DEDUCED_TYPENAME Base::key_type, KeyType + >, + // } + // else + // { + KeyToBaseConverter + // } + + >::type + + >::type + + > type; +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + + +/// \brief Container adaptor to build a type that is compliant to the concept of an associative container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + + class KeyType, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + class KeyToBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class associative_container_adaptor : + + public associative_container_adaptor_base + < + Base, Iterator, ConstIterator, KeyType, + IteratorToBaseConverter, IteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, KeyToBaseConverter, + FunctorsFromDerivedClasses + + >::type +{ + + // MetaData ------------------------------------------------------------- + + typedef typename associative_container_adaptor_base + < + Base, Iterator, ConstIterator, KeyType, + IteratorToBaseConverter, IteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, KeyToBaseConverter, + FunctorsFromDerivedClasses + + >::type base_; + + public: + + typedef KeyType key_type; + + protected: + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na, + // { + detail::key_to_base_identity + < + BOOST_DEDUCED_TYPENAME Base::key_type, KeyType + >, + // } + // else + // { + KeyToBaseConverter + // } + + >::type key_to_base; + + public: + + explicit associative_container_adaptor(Base & c) + : base_(c) {} + + protected: + + + typedef associative_container_adaptor associative_container_adaptor_; + + // Interface -------------------------------------------------------------- + + public: + + template< class CompatibleKey > + BOOST_DEDUCED_TYPENAME base_::size_type erase(const CompatibleKey & k) + { + return this->base().erase + ( + this->template functor()(k) + ); + } + + // As we redefine erase, the other overloads need to be manually routed + + BOOST_DEDUCED_TYPENAME base_::iterator erase( + BOOST_DEDUCED_TYPENAME base_::iterator pos) + { + return base_::container_adaptor_::erase(pos); + } + + BOOST_DEDUCED_TYPENAME base_::iterator erase( + BOOST_DEDUCED_TYPENAME base_::iterator first, + BOOST_DEDUCED_TYPENAME base_::iterator last) + { + return base_::container_adaptor_::erase(first,last); + } + + template< class CompatibleKey > + BOOST_DEDUCED_TYPENAME base_::size_type count(const CompatibleKey & k) + { + return this->base().count( + this->template functor()(k) + ); + } + + template< class CompatibleKey > + BOOST_DEDUCED_TYPENAME base_::iterator find(const CompatibleKey & k) + { + return this->template functor() + ( + this->base().find( + this->template functor()(k) + ) + ); + } + + template< class CompatibleKey > + BOOST_DEDUCED_TYPENAME base_::const_iterator + find(const CompatibleKey & k) const + { + return this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_from_base>() + ( + this->base().find( + this->template functor()(k) + ) + ); + } + + template< class CompatibleKey > + std::pair + < + BOOST_DEDUCED_TYPENAME base_::iterator, + BOOST_DEDUCED_TYPENAME base_::iterator + > + equal_range(const CompatibleKey & k) + { + std::pair< + + BOOST_DEDUCED_TYPENAME Base::iterator, + BOOST_DEDUCED_TYPENAME Base::iterator + + > r( this->base().equal_range( + this->template functor()(k) + ) + ); + + return std::pair + < + BOOST_DEDUCED_TYPENAME base_::iterator, + BOOST_DEDUCED_TYPENAME base_::iterator + >( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_from_base + >() ( r.first ), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_from_base + >() ( r.second ) + ); + } + + template< class CompatibleKey > + std::pair + < + BOOST_DEDUCED_TYPENAME base_::const_iterator, + BOOST_DEDUCED_TYPENAME base_::const_iterator + > + equal_range(const CompatibleKey & k) const + { + std::pair< + + BOOST_DEDUCED_TYPENAME Base::const_iterator, + BOOST_DEDUCED_TYPENAME Base::const_iterator + + > r( this->base().equal_range( + this->template functor()(k) + ) + ); + + return std::pair + < + BOOST_DEDUCED_TYPENAME base_::const_iterator, + BOOST_DEDUCED_TYPENAME base_::const_iterator + >( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_from_base + >() ( r.first ), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_from_base + >() ( r.second ) + ); + } + +}; + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP + + + diff --git a/win32/include/boost/bimap/container_adaptor/container_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/container_adaptor.hpp new file mode 100755 index 000000000..e69209cfe --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/container_adaptor.hpp @@ -0,0 +1,291 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/container_adaptor.hpp +/// \brief Container adaptor to build a type that is compliant to the concept of a container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_CONTAINER_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_CONTAINER_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + + +namespace boost { +namespace bimaps { + +/// \brief Container Adaptor toolbox, easy way to build new containers from existing ones. + +namespace container_adaptor { + +/// \brief Container adaptor to build a type that is compliant to the concept of a container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class container_adaptor +{ + // MetaData ------------------------------------------------------------- + + public: + + typedef Iterator iterator; + typedef ConstIterator const_iterator; + + typedef BOOST_DEDUCED_TYPENAME iterator_value < iterator >::type value_type; + typedef BOOST_DEDUCED_TYPENAME iterator_pointer < iterator >::type pointer; + typedef BOOST_DEDUCED_TYPENAME iterator_reference< iterator >::type reference; + typedef BOOST_DEDUCED_TYPENAME iterator_reference< const_iterator >::type const_reference; + + typedef BOOST_DEDUCED_TYPENAME Base::size_type size_type; + typedef BOOST_DEDUCED_TYPENAME Base::difference_type difference_type; + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na, + // { + ::boost::bimaps::container_adaptor::detail:: + iterator_to_base_identity + < + BOOST_DEDUCED_TYPENAME Base::iterator , iterator, + BOOST_DEDUCED_TYPENAME Base::const_iterator , const_iterator + >, + // } + // else + // { + IteratorToBaseConverter + // } + + >::type iterator_to_base; + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na, + // { + ::boost::bimaps::container_adaptor::detail:: + iterator_from_base_identity + < + BOOST_DEDUCED_TYPENAME Base::iterator , iterator, + BOOST_DEDUCED_TYPENAME Base::const_iterator , const_iterator + >, + // } + // else + // { + IteratorFromBaseConverter + // } + + >::type iterator_from_base; + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na, + // { + ::boost::bimaps::container_adaptor::detail:: + value_to_base_identity + < + BOOST_DEDUCED_TYPENAME Base::value_type, + value_type + >, + // } + // else + // { + ValueToBaseConverter + // } + + >::type value_to_base; + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na, + // { + ::boost::bimaps::container_adaptor::detail:: + value_from_base_identity + < + BOOST_DEDUCED_TYPENAME Base::value_type, + value_type + >, + // } + // else + // { + ValueFromBaseConverter + // } + + >::type value_from_base; + + // ACCESS ----------------------------------------------------------------- + + public: + + explicit container_adaptor(Base & c) : dwfb(c) {} + + protected: + + typedef Base base_type; + + typedef container_adaptor container_adaptor_; + + const Base & base() const { return dwfb.data; } + Base & base() { return dwfb.data; } + + // Interface -------------------------------------------------------------- + + public: + + size_type size() const { return base().size(); } + size_type max_size() const { return base().max_size(); } + bool empty() const { return base().empty(); } + + iterator begin() + { + return this->template functor()( base().begin() ); + } + + iterator end() + { + return this->template functor()( base().end() ); + } + + const_iterator begin() const + { + return this->template functor()( base().begin() ); + } + + const_iterator end() const + { + return this->template functor()( base().end() ); + } + + + iterator erase(iterator pos) + { + return this->template functor()( + base().erase(this->template functor()(pos)) + ); + } + + iterator erase(iterator first, iterator last) + { + return this->template functor()( + base().erase( + this->template functor()(first), + this->template functor()(last) + ) + ); + } + + void clear() + { + base().clear(); + } + + template< class InputIterator > + void insert(InputIterator iterBegin, InputIterator iterEnd) + { + for( ; iterBegin != iterEnd ; ++iterBegin ) + { + base().insert( this->template + functor()( *iterBegin ) + ); + } + } + + std::pair insert( + BOOST_DEDUCED_TYPENAME ::boost::call_traits< value_type >::param_type x) + { + std::pair< BOOST_DEDUCED_TYPENAME Base::iterator, bool > r( + base().insert( this->template functor()(x) ) + ); + + return std::pair( this->template + functor()(r.first),r.second + ); + } + + iterator insert(iterator pos, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< value_type >::param_type x) + { + return this->template functor()( + base().insert( + this->template functor()(pos), + this->template functor()(x)) + ); + } + + void swap( container_adaptor & c ) + { + base().swap( c.base() ); + } + + // Access to functors ---------------------------------------------------- + + protected: + + template< class Functor > + Functor & functor() + { + return dwfb.template functor(); + } + + template< class Functor > + Functor const & functor() const + { + return dwfb.template functor(); + } + + // Data ------------------------------------------------------------------ + + private: + + ::boost::bimaps::container_adaptor::detail::data_with_functor_bag + < + Base &, + + BOOST_DEDUCED_TYPENAME mpl::copy + < + mpl::vector + < + iterator_to_base, + iterator_from_base, + value_to_base, + value_from_base + >, + + mpl::front_inserter< FunctorsFromDerivedClasses > + + >::type + + > dwfb; +}; + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_CONTAINER_ADAPTOR_HPP diff --git a/win32/include/boost/bimap/container_adaptor/detail/comparison_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/detail/comparison_adaptor.hpp new file mode 100755 index 000000000..bc142c2ab --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/detail/comparison_adaptor.hpp @@ -0,0 +1,101 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/detail/comparison_adaptor.hpp +/// \brief Comparison adaptor. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_COMPARISON_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_COMPARISON_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { +namespace detail { + +/// \brief Comparison adaptor +/** + +A simple comparison adaptor. + **/ + +template < class Compare, class NewType, class Converter > +struct comparison_adaptor : std::binary_function +{ + comparison_adaptor( const Compare & comp, const Converter & conv) + : compare(comp), converter(conv) {} + + bool operator()( BOOST_DEDUCED_TYPENAME call_traits::param_type x, + BOOST_DEDUCED_TYPENAME call_traits::param_type y) const + { + return compare( converter(x), converter(y) ); + } + + private: + Compare compare; + Converter converter; +}; + +template < class Compare, class NewType, class Converter > +struct compatible_comparison_adaptor : std::binary_function +{ + compatible_comparison_adaptor( const Compare & comp, const Converter & conv) + : compare(comp), converter(conv) {} + + template< class CompatibleTypeLeft, class CompatibleTypeRight > + bool operator()( const CompatibleTypeLeft & x, + const CompatibleTypeRight & y) const + { + return compare( converter(x), converter(y) ); + } + + private: + Compare compare; + Converter converter; +}; + + +/// \brief Unary Check adaptor +/** + +A simple unary check adaptor. + **/ + +template < class Compare, class NewType, class Converter > +struct unary_check_adaptor : std::unary_function +{ + unary_check_adaptor( const Compare & comp, const Converter & conv ) : + compare(comp), converter(conv) {} + + bool operator()( BOOST_DEDUCED_TYPENAME call_traits::param_type x) const + { + return compare( converter(x) ); + } + + private: + Compare compare; + Converter converter; +}; + +} // namespace detail +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_COMPARISON_ADAPTOR_HPP + + diff --git a/win32/include/boost/bimap/container_adaptor/detail/functor_bag.hpp b/win32/include/boost/bimap/container_adaptor/detail/functor_bag.hpp new file mode 100755 index 000000000..d62250723 --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/detail/functor_bag.hpp @@ -0,0 +1,100 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/detail/functor_bag.hpp +/// \brief Defines a EBO optimizacion helper for functors. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_FUNCTOR_BAG_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_FUNCTOR_BAG_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#if defined(BOOST_MSVC) +// This bogus warning will appear when add_const is applied to a +// const volatile reference because we can't detect const volatile +// references with MSVC6. +# pragma warning(push) +# pragma warning(disable:4181) +// warning C4181: qualifier applied to reference type ignored +#endif + +#include + +#include +#include + +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { +namespace detail { + +/// \brief EBO optimizacion helper for functors +/** + +This class is a generalization of a helper class explained in an article by +Nathan C. Myers.\n +See it at \link http://www.cantrip.org/emptyopt.html + **/ + +template < class Data, class FunctorList > +struct data_with_functor_bag : + + public mpl::inherit_linearly< + + FunctorList, + mpl::if_< is_base_of< mpl::_2, mpl::_1 >, + // { + mpl::_1, + // } + // else + // { + mpl::inherit< mpl::_1, mpl::_2 > + // } + > + + >::type +{ + Data data; + + data_with_functor_bag() {} + + data_with_functor_bag(BOOST_DEDUCED_TYPENAME add_reference::type d) + : data(d) {} + + template< class Functor > + Functor& functor() + { + return *(static_cast(this)); + } + + template< class Functor > + const Functor& functor() const + { + return *(static_cast(this)); + } +}; + +} // namespace detail +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_FUNCTOR_BAG_HPP + + diff --git a/win32/include/boost/bimap/container_adaptor/detail/identity_converters.hpp b/win32/include/boost/bimap/container_adaptor/detail/identity_converters.hpp new file mode 100755 index 000000000..b7b910179 --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/detail/identity_converters.hpp @@ -0,0 +1,191 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/detail/identity_converters.hpp +/// \brief Value and iterators identity converters. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_IDENTITY_CONVERTERS_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_IDENTITY_CONVERTERS_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +/// \brief Details of the container adaptor toolbox + +namespace detail { + +/// \brief Iterator identity converter used by default in container adaptors. +/** +If Iterator and ConstIterator are of the same type one of the convert function is not +included. + **/ + +template +< + class BaseIterator , class Iterator, + class BaseConstIterator , class ConstIterator +> +struct iterator_to_base_identity +{ + BaseIterator operator()(Iterator iter) const + { + return BaseIterator(iter); + } + + BaseConstIterator operator()(ConstIterator iter) const + { + return BaseConstIterator(iter); + } +}; + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class BaseIterator, class Iterator > +struct iterator_to_base_identity +{ + BaseIterator operator()(Iterator iter) const + { + return BaseIterator(iter); + } +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +/// \brief Iterator from base identity converter used by default in container adaptors. +/** +If Iterator and ConstIterator are of the same type one of the convert function is not +included. + **/ + +template +< + class BaseIterator , class Iterator, + class BaseConstIterator , class ConstIterator +> +struct iterator_from_base_identity +{ + Iterator operator()(BaseIterator iter) const + { + return Iterator(iter); + } + ConstIterator operator()(BaseConstIterator iter) const + { + return ConstIterator(iter); + } +}; + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class BaseIterator, class Iterator, class ConstIterator > +struct iterator_from_base_identity +{ + Iterator operator()(BaseIterator iter) const + { + return Iterator(iter); + } +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +/// \brief Value to base identity converter used by default in container adaptors. + +template< class BaseValue, class Value > +struct value_to_base_identity +{ + BaseValue operator()(const Value & val) const + { + return BaseValue(val); + } +}; + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class Value > +struct value_to_base_identity< Value, Value > +{ + const Value & operator()(const Value & val) const + { + return val; + } +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +/// \brief Value from base identity converter used by default in container adaptors. + +template< class BaseValue, class Value > +struct value_from_base_identity +{ + Value operator()(const BaseValue & val) const + { + return Value(val); + } +}; + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class Value > +struct value_from_base_identity +{ + Value & operator()(Value & val) const + { + return val; + } + + const Value & operator()(const Value & val) const + { + return val; + } +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +/// \brief Key to base identity converter used by default in container adaptors. + +template< class BaseKey, class Key > +struct key_to_base_identity +{ + BaseKey operator()(const Key & k) const + { + return BaseKey(k); + } +}; + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class Key > +struct key_to_base_identity< Key, Key > +{ + // As default accept any type as key in order to allow container + // adaptors to work with compatible key types + + template< class CompatibleKey > + const CompatibleKey & operator()(const CompatibleKey & k) const + { + return k; + } +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +} // namespace detail +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_IDENTITY_CONVERTERS_HPP + + diff --git a/win32/include/boost/bimap/container_adaptor/detail/key_extractor.hpp b/win32/include/boost/bimap/container_adaptor/detail/key_extractor.hpp new file mode 100755 index 000000000..a8ff92ad1 --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/detail/key_extractor.hpp @@ -0,0 +1,45 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/detail/key_extractor.hpp +/// \brief Key extractor for a pair. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_KEY_EXTRACTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_KEY_EXTRACTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { +namespace detail { + +/// \brief Key Extractor + +template < class T > +struct key_from_pair_extractor + : std::unary_function< T, BOOST_DEDUCED_TYPENAME T::first_type > +{ + bool operator()( const T & p ) { return p.first; } +}; + +} // namespace detail +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_KEY_EXTRACTOR_HPP + + diff --git a/win32/include/boost/bimap/container_adaptor/detail/non_unique_container_helper.hpp b/win32/include/boost/bimap/container_adaptor/detail/non_unique_container_helper.hpp new file mode 100755 index 000000000..0481db3a6 --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/detail/non_unique_container_helper.hpp @@ -0,0 +1,62 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/detail/non_unique_container_helper.hpp +/// \brief Details for non unique containers + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_NON_UNIQUE_CONTAINER_HELPER_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_NON_UNIQUE_CONTAINER_HELPER_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +/*****************************************************************************/ +#define BOOST_BIMAP_NON_UNIQUE_CONTAINER_ADAPTOR_INSERT_FUNCTIONS \ + \ +template \ +void insert(InputIterator iterBegin, InputIterator iterEnd) \ +{ \ + for( ; iterBegin != iterEnd ; ++iterBegin ) \ + { \ + this->base().insert( \ + this->template functor< \ + BOOST_DEDUCED_TYPENAME base_::value_to_base>()( \ + BOOST_DEDUCED_TYPENAME base_::value_type(*iterBegin)) ); \ + } \ +} \ + \ +BOOST_DEDUCED_TYPENAME base_::iterator insert( \ + BOOST_DEDUCED_TYPENAME ::boost::call_traits< \ + BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x) \ +{ \ + return this->base().insert( this->template functor< \ + BOOST_DEDUCED_TYPENAME base_:: \ + value_to_base>()(x) ); \ +} \ + \ +BOOST_DEDUCED_TYPENAME base_::iterator \ + insert(BOOST_DEDUCED_TYPENAME base_::iterator pos, \ + BOOST_DEDUCED_TYPENAME ::boost::call_traits< \ + BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x) \ +{ \ + return this->template functor< \ + BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()( \ + this->base().insert(this->template functor< \ + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(pos), \ + this->template functor< \ + BOOST_DEDUCED_TYPENAME base_::value_to_base>()(x)) \ + ); \ +} +/*****************************************************************************/ + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_NON_UNIQUE_CONTAINER_HELPER_HPP + + diff --git a/win32/include/boost/bimap/container_adaptor/list_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/list_adaptor.hpp new file mode 100755 index 000000000..11f3c8d55 --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/list_adaptor.hpp @@ -0,0 +1,249 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/list_adaptor.hpp +/// \brief Container adaptor to easily build a std::list signature compatible container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_LIST_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_LIST_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +/// \brief Container adaptor to easily build a std::list signature compatible container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + class ReverseIterator, + class ConstReverseIterator, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class ReverseIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class list_adaptor : + + public ::boost::bimaps::container_adaptor::sequence_container_adaptor + < + Base, Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + FunctorsFromDerivedClasses + > +{ + typedef ::boost::bimaps::container_adaptor::sequence_container_adaptor + < + Base, Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + FunctorsFromDerivedClasses + + > base_; + + // Access ----------------------------------------------------------------- + + public: + + explicit list_adaptor(Base & c) : + base_(c) {} + + protected: + + typedef list_adaptor list_adaptor_; + + // Interface ------------------------------------------------------------- + + public: + + void splice(Iterator position, list_adaptor & x) + { + this->base().splice( + this->template functor() + (position), + x.base() + ); + } + + void splice(Iterator position, list_adaptor & x, Iterator i) + { + this->base().splice( + this->template functor() + (position), + x.base(), + this->template functor()(i) + ); + } + + void splice(Iterator position, list_adaptor & x, + Iterator first, Iterator last) + { + this->base().splice( + this->template functor() + (position), + x.base(), + this->template functor()(first), + this->template functor()(last) + ); + } + + void remove( + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::value_type + >::param_type value + ) + { + this->base().remove( + this->template functor()(value) + ); + } + + template< class Predicate > + void remove_if(Predicate pred) + { + this->base().remove_if( + ::boost::bimaps::container_adaptor::detail::unary_check_adaptor + < + Predicate, + BOOST_DEDUCED_TYPENAME Base::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( pred, this->template functor() ) + ); + } + + void unique() + { + this->base().unique( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::equal_to, + BOOST_DEDUCED_TYPENAME Base::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( + std::equal_to(), + this->template functor() + ) + ); + } + + template< class BinaryPredicate > + void unique(BinaryPredicate binary_pred) + { + this->base().unique( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + BinaryPredicate, + BOOST_DEDUCED_TYPENAME Base::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( binary_pred, + this->template functor() ) + ); + } + + void merge(list_adaptor & x) + { + this->base().merge(x.base(), + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::less, + BOOST_DEDUCED_TYPENAME Base::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( + std::less(), + this->template functor() + ) + ); + } + + template< class Compare > + void merge(list_adaptor & x, Compare comp) + { + this->base().merge(x.base(), + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + Compare, + BOOST_DEDUCED_TYPENAME Base::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( comp, this->template functor() ) + ); + } + + void sort() + { + this->base().sort( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::less, + BOOST_DEDUCED_TYPENAME Base::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( + std::less(), + this->template functor() + ) + ); + } + + template< class Compare > + void sort(Compare comp) + { + this->base().sort( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + Compare, + BOOST_DEDUCED_TYPENAME Base::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( comp, this->template functor() ) + ); + } + + void reverse() + { + this->base().reverse(); + } + +}; + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_SET_ADAPTOR_HPP + + diff --git a/win32/include/boost/bimap/container_adaptor/list_map_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/list_map_adaptor.hpp new file mode 100755 index 000000000..bd1d52be2 --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/list_map_adaptor.hpp @@ -0,0 +1,282 @@ + // Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/list_map_adaptor.hpp +/// \brief Container adaptor. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_LIST_MAP_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_LIST_MAP_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template +< + class Base, class Iterator, class ConstIterator, + class ReverseIterator, class ConstReverseIterator, + class IteratorToBaseConverter, class IteratorFromBaseConverter, + class ReverseIteratorFromBaseConverter, + class ValueToBaseConverter, class ValueFromBaseConverter, + class KeyFromBaseValueConverter, + class FunctorsFromDerivedClasses +> +struct list_map_adaptor_base +{ + typedef list_adaptor + < + Base, + + Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + + IteratorToBaseConverter, IteratorFromBaseConverter, + + ReverseIteratorFromBaseConverter, + + ValueToBaseConverter, ValueFromBaseConverter, + + BOOST_DEDUCED_TYPENAME mpl::push_front< + + FunctorsFromDerivedClasses, + + BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na, + // { + detail::key_from_pair_extractor + < + BOOST_DEDUCED_TYPENAME Iterator::value_type + >, + // } + // else + // { + KeyFromBaseValueConverter + // } + + >::type + + >::type + + > type; +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +/// \brief Container adaptor to easily build a list map container + +template +< + class Base, + + class Iterator, + class ConstIterator, + class ReverseIterator, + class ConstReverseIterator, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class ReverseIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + class KeyFromBaseValueConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class list_map_adaptor : + + public list_map_adaptor_base + < + Base, Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyFromBaseValueConverter, + FunctorsFromDerivedClasses + + >::type +{ + typedef BOOST_DEDUCED_TYPENAME list_map_adaptor_base + < + Base, Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyFromBaseValueConverter, + FunctorsFromDerivedClasses + + >::type base_; + + // MetaData ------------------------------------------------------------- + + public: + + typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type key_type; + typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::second_type data_type; + + protected: + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< ::boost::mpl::is_na, + // { + detail::key_from_pair_extractor< BOOST_DEDUCED_TYPENAME Iterator::value_type >, + // } + // else + // { + KeyFromBaseValueConverter + // } + + >::type key_from_base_value; + + // Access ----------------------------------------------------------------- + + public: + + explicit list_map_adaptor(Base & c) : + base_(c) {} + + protected: + + typedef list_map_adaptor list_map_adaptor_; + + // Functions ------------------------------------------------------------- + + public: + + // The following functions are overwritten in order to work + // with key_type instead of value_type + + template< class Predicate > + void remove_if(Predicate pred) + { + this->base().remove_if( + ::boost::bimaps::container_adaptor::detail::unary_check_adaptor + < + Predicate, + BOOST_DEDUCED_TYPENAME Base::value_type, + key_from_base_value + + >( pred, this->template functor() ) + ); + } + + void unique() + { + this->base().unique( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::equal_to, + BOOST_DEDUCED_TYPENAME Base::value_type, + key_from_base_value + + >( + std::equal_to(), + this->template functor() + ) + ); + } + + template< class BinaryPredicate > + void unique(BinaryPredicate binary_pred) + { + this->base().unique( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + BinaryPredicate, + BOOST_DEDUCED_TYPENAME Base::value_type, + key_from_base_value + + >( binary_pred, this->template functor() ) + ); + } + + void merge(list_map_adaptor & x) + { + this->base().merge(x.base(), + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::less, + BOOST_DEDUCED_TYPENAME Base::value_type, + key_from_base_value + + >( + std::less(), + this->template functor() + ) + ); + } + + template< class Compare > + void merge(list_map_adaptor & x, Compare comp) + { + this->base().merge(x.base(), + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + Compare, + BOOST_DEDUCED_TYPENAME Base::value_type, + key_from_base_value + + >( comp, this->template functor() ) + ); + } + + void sort() + { + this->base().sort( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::less, + BOOST_DEDUCED_TYPENAME Base::value_type, + key_from_base_value + + >( + std::less(), + this->template functor() + ) + ); + } + + template< class Compare > + void sort(Compare comp) + { + this->base().sort( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + Compare, + BOOST_DEDUCED_TYPENAME Base::value_type, + key_from_base_value + + >( comp, this->template functor() ) + ); + } + +}; + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_LIST_MAP_ADAPTOR_HPP + diff --git a/win32/include/boost/bimap/container_adaptor/map_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/map_adaptor.hpp new file mode 100755 index 000000000..b922529e6 --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/map_adaptor.hpp @@ -0,0 +1,131 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/map_adaptor.hpp +/// \brief Container adaptor to easily build a std::map signature compatible container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_MAP_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_MAP_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +/// \brief Container adaptor to easily build a std::map signature compatible container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + class ReverseIterator, + class ConstReverseIterator, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class ReverseIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + class KeyToBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class map_adaptor : + + public ::boost::bimaps::container_adaptor:: + ordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + > +{ + + typedef ::boost::bimaps::container_adaptor:: + ordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + + > base_; + + // MetaData ------------------------------------------------------------- + + public: + + typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::second_type data_type; + + // Access ----------------------------------------------------------------- + + public: + + explicit map_adaptor(Base & c) : + base_(c) {} + + protected: + + typedef map_adaptor map_adaptor_; + + // Interface -------------------------------------------------------------- + + public: + + template< class CompatibleKey > + data_type& operator[](const CompatibleKey & k) + { + return this->base() + [this->template functor()(k)]; + } + + template< class CompatibleKey > + data_type& at(const CompatibleKey & k) + { + return this->base(). + at(this->template functor()(k)); + } + + template< class CompatibleKey > + const data_type& at(const CompatibleKey & k) const + { + return this->base(). + at(this->template functor()(k)); + } + +}; + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_MAP_ADAPTOR_HPP + diff --git a/win32/include/boost/bimap/container_adaptor/multimap_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/multimap_adaptor.hpp new file mode 100755 index 000000000..468d083cb --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/multimap_adaptor.hpp @@ -0,0 +1,109 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/multimap_adaptor.hpp +/// \brief Container adaptor to easily build a std::multimap signature compatible container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_MULTIMAP_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_MULTIMAP_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +/// \brief Container adaptor to easily build a std::multimap signature compatible container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + class ReverseIterator, + class ConstReverseIterator, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class ReverseIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + class KeyToBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class multimap_adaptor : + + public ::boost::bimaps::container_adaptor:: + ordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + > +{ + typedef ::boost::bimaps::container_adaptor:: + ordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + + > base_; + + // MetaData ------------------------------------------------------------- + + public: + + typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::second_type data_type; + + // Access ----------------------------------------------------------------- + + public: + + explicit multimap_adaptor(Base & c) : + base_(c) {} + + protected: + + typedef multimap_adaptor multimap_adaptor_; + + public: + + BOOST_BIMAP_NON_UNIQUE_CONTAINER_ADAPTOR_INSERT_FUNCTIONS +}; + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_MULTIMAP_ADAPTOR_HPP + + diff --git a/win32/include/boost/bimap/container_adaptor/multiset_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/multiset_adaptor.hpp new file mode 100755 index 000000000..caab6435e --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/multiset_adaptor.hpp @@ -0,0 +1,103 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/multiset_adaptor.hpp +/// \brief Container adaptor to easily build a std::multiset signature compatible container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_MULTISET_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_MULTISET_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +/// \brief Container adaptor to easily build a std::multiset signature compatible container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + class ReverseIterator, + class ConstReverseIterator, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class ReverseIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + class KeyToBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class multiset_adaptor : + + public ::boost::bimaps::container_adaptor:: + ordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + > +{ + + typedef ::boost::bimaps::container_adaptor:: + ordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + + > base_; + + // Access ----------------------------------------------------------------- + + public: + + explicit multiset_adaptor(Base & c) : + base_(c) {} + + protected: + + typedef multiset_adaptor multiset_adaptor_; + + public: + + BOOST_BIMAP_NON_UNIQUE_CONTAINER_ADAPTOR_INSERT_FUNCTIONS +}; + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_MULTISET_ADAPTOR_HPP + diff --git a/win32/include/boost/bimap/container_adaptor/ordered_associative_container_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/ordered_associative_container_adaptor.hpp new file mode 100755 index 000000000..5fed3638f --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/ordered_associative_container_adaptor.hpp @@ -0,0 +1,312 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/ordered_associative_container_adaptor.hpp +/// \brief Container adaptor to build a type that is compliant to the concept of an ordered associative container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_ORDERED_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_ORDERED_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template +< + class Base, class Iterator, class ConstIterator, + class ReverseIterator, class ConstReverseIterator, class KeyType, + class IteratorToBaseConverter, class IteratorFromBaseConverter, + class ReverseIteratorFromBaseConverter, + class ValueToBaseConverter, class ValueFromBaseConverter, + class KeyToBaseConverter, + class FunctorsFromDerivedClasses +> +struct ordered_associative_container_adaptor_base +{ + typedef associative_container_adaptor< + Base, Iterator, ConstIterator, KeyType, + IteratorToBaseConverter, IteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, KeyToBaseConverter, + + BOOST_DEDUCED_TYPENAME mpl::push_front< + + FunctorsFromDerivedClasses, + + BOOST_DEDUCED_TYPENAME mpl::if_< + ::boost::mpl::is_na, + // { + detail::iterator_from_base_identity + < + BOOST_DEDUCED_TYPENAME Base::reverse_iterator, + ReverseIterator, + BOOST_DEDUCED_TYPENAME Base::const_reverse_iterator, + ConstReverseIterator + >, + // } + // else + // { + ReverseIteratorFromBaseConverter + // } + + >::type + + >::type + + > type; +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +/// \brief Container adaptor to build a type that is compliant to the concept of an ordered associative container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + class ReverseIterator, + class ConstReverseIterator, + + class KeyType, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class ReverseIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + class KeyToBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class ordered_associative_container_adaptor : + + public ordered_associative_container_adaptor_base + < + Base, Iterator, ConstIterator, + ReverseIterator, ConstReverseIterator, KeyType, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, KeyToBaseConverter, + FunctorsFromDerivedClasses + + >::type, + + ::boost::totally_ordered + < + ordered_associative_container_adaptor + < + Base, Iterator, ConstIterator, + ReverseIterator, ConstReverseIterator, + KeyType, IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, FunctorsFromDerivedClasses + > + > +{ + // MetaData ------------------------------------------------------------- + + typedef BOOST_DEDUCED_TYPENAME ordered_associative_container_adaptor_base + < + Base, Iterator, ConstIterator, + ReverseIterator, ConstReverseIterator, KeyType, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, KeyToBaseConverter, + FunctorsFromDerivedClasses + + >::type base_; + + public: + + typedef detail::compatible_comparison_adaptor + < + BOOST_DEDUCED_TYPENAME Base::key_compare, + BOOST_DEDUCED_TYPENAME base_::key_type, + BOOST_DEDUCED_TYPENAME base_::key_to_base + + > key_compare; + + typedef detail::comparison_adaptor + < + BOOST_DEDUCED_TYPENAME Base::value_compare, + BOOST_DEDUCED_TYPENAME base_::value_type, + BOOST_DEDUCED_TYPENAME base_::value_to_base + + > value_compare; + + typedef ReverseIterator reverse_iterator; + typedef ConstReverseIterator const_reverse_iterator; + + protected: + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< + ::boost::mpl::is_na, + // { + detail::iterator_from_base_identity + < + BOOST_DEDUCED_TYPENAME Base::reverse_iterator, + reverse_iterator, + BOOST_DEDUCED_TYPENAME Base::const_reverse_iterator, + const_reverse_iterator + >, + // } + // else + // { + ReverseIteratorFromBaseConverter + // } + + >::type reverse_iterator_from_base; + + // Access ----------------------------------------------------------------- + + public: + + explicit ordered_associative_container_adaptor(Base & c) + : base_(c) {} + + protected: + + typedef ordered_associative_container_adaptor + ordered_associative_container_adaptor_; + + // Interface -------------------------------------------------------------- + + public: + + reverse_iterator rbegin() + { + return this->template functor< + reverse_iterator_from_base + >() ( this->base().rbegin() ); + + } + + reverse_iterator rend() + { + return this->template functor< + reverse_iterator_from_base + >() ( this->base().rend() ); + } + + const_reverse_iterator rbegin() const + { + return this->template functor< + reverse_iterator_from_base + >() ( this->base().rbegin() ); + } + + const_reverse_iterator rend() const + { + return this->template functor< + reverse_iterator_from_base + >() ( this->base().rend() ); + } + + key_compare key_comp() const + { + typedef BOOST_DEDUCED_TYPENAME base_::key_to_base key_to_base_; + + return key_compare( + this->base().key_comp(), + this->template functor() + ); + } + + value_compare value_comp() const + { + typedef BOOST_DEDUCED_TYPENAME base_::value_to_base value_to_base_; + + return value_compare( + this->base().value_comp(), + this->template functor() + ); + } + + template< class CompatibleKey > + BOOST_DEDUCED_TYPENAME base_::iterator lower_bound(const CompatibleKey & k) + { + return this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()( + this->base().lower_bound( + this->template functor()(k) + ) + ); + } + + template< class CompatibleKey > + BOOST_DEDUCED_TYPENAME base_::const_iterator lower_bound(const CompatibleKey & k) const + { + return this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()( + this->base().lower_bound( + this->template functor()(k) + ) + ); + } + + template< class CompatibleKey > + BOOST_DEDUCED_TYPENAME base_::iterator upper_bound(const CompatibleKey & k) + { + return this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()( + this->base().upper_bound( + this->template functor()(k) + ) + ); + } + + template< class CompatibleKey > + BOOST_DEDUCED_TYPENAME base_::const_iterator upper_bound(const CompatibleKey & k) const + { + return this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()( + this->base().upper_bound( + this->template functor()(k) + ) + ); + } + + // Totally ordered implementation + + bool operator==(const ordered_associative_container_adaptor & c) const + { + return ( this->base() == c.base() ); + } + + bool operator<(const ordered_associative_container_adaptor & c) const + { + return ( this->base() < c.base() ); + } +}; + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_ORDERED_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP diff --git a/win32/include/boost/bimap/container_adaptor/sequence_container_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/sequence_container_adaptor.hpp new file mode 100755 index 000000000..942431265 --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/sequence_container_adaptor.hpp @@ -0,0 +1,355 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/sequence_container_adaptor.hpp +/// \brief Container adaptor to build a type that is compliant to the concept of a weak associative container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_SEQUENCE_CONTAINER_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_SEQUENCE_CONTAINER_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template +< + class Base, class Iterator, class ConstIterator, + class ReverseIterator, class ConstReverseIterator, + class IteratorToBaseConverter, class IteratorFromBaseConverter, + class ReverseIteratorFromBaseConverter, + class ValueToBaseConverter, class ValueFromBaseConverter, + class FunctorsFromDerivedClasses +> +struct sequence_container_adaptor_base +{ + typedef container_adaptor + < + Base, Iterator, ConstIterator, + IteratorToBaseConverter, IteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + + BOOST_DEDUCED_TYPENAME mpl::push_front< + + FunctorsFromDerivedClasses, + + BOOST_DEDUCED_TYPENAME mpl::if_< + ::boost::mpl::is_na, + // { + detail::iterator_from_base_identity + < + BOOST_DEDUCED_TYPENAME Base::reverse_iterator, + ReverseIterator, + BOOST_DEDUCED_TYPENAME Base::const_reverse_iterator, + ConstReverseIterator + >, + // } + // else + // { + ReverseIteratorFromBaseConverter + // } + + >::type + + >::type + + > type; +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +/// \brief Container adaptor to build a type that is compliant to the concept of a sequence container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + + class ReverseIterator, + class ConstReverseIterator, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class ReverseIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class sequence_container_adaptor : + + public sequence_container_adaptor_base + < + Base, Iterator, ConstIterator, + ReverseIterator, ConstReverseIterator, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + FunctorsFromDerivedClasses + + >::type, + + ::boost::totally_ordered + < + sequence_container_adaptor + < + Base, Iterator, ConstIterator, + ReverseIterator, ConstReverseIterator, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + FunctorsFromDerivedClasses + > + > +{ + typedef BOOST_DEDUCED_TYPENAME sequence_container_adaptor_base + < + Base, Iterator, ConstIterator, + ReverseIterator, ConstReverseIterator, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + FunctorsFromDerivedClasses + + >::type base_; + + // MetaData ------------------------------------------------------------- + + public: + + typedef ReverseIterator reverse_iterator; + typedef ConstReverseIterator const_reverse_iterator; + + protected: + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< + ::boost::mpl::is_na, + // { + detail::iterator_from_base_identity + < + BOOST_DEDUCED_TYPENAME Base::reverse_iterator, + reverse_iterator, + BOOST_DEDUCED_TYPENAME Base::const_reverse_iterator, + const_reverse_iterator + >, + // } + // else + // { + ReverseIteratorFromBaseConverter + // } + + >::type reverse_iterator_from_base; + + + // Access ----------------------------------------------------------------- + + public: + + explicit sequence_container_adaptor(Base & c) + : base_(c) {} + + protected: + + + typedef sequence_container_adaptor sequence_container_adaptor_; + + // Interface -------------------------------------------------------------- + + public: + + reverse_iterator rbegin() + { + return this->template functor< + reverse_iterator_from_base + >() ( this->base().rbegin() ); + + } + + reverse_iterator rend() + { + return this->template functor< + reverse_iterator_from_base + >() ( this->base().rend() ); + } + + const_reverse_iterator rbegin() const + { + return this->template functor< + reverse_iterator_from_base + >() ( this->base().rbegin() ); + } + + const_reverse_iterator rend() const + { + return this->template functor< + reverse_iterator_from_base + >() ( this->base().rend() ); + } + + void resize(BOOST_DEDUCED_TYPENAME base_::size_type n, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x = + BOOST_DEDUCED_TYPENAME base_::value_type()) + { + this->base().resize(n, + this->template functor()(x) + ); + } + + BOOST_DEDUCED_TYPENAME base_::reference front() + { + return this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() + ( + this->base().front() + ); + } + + BOOST_DEDUCED_TYPENAME base_::reference back() + { + return this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() + ( + this->base().back() + ); + } + + BOOST_DEDUCED_TYPENAME base_::const_reference front() const + { + return this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() + ( + this->base().front() + ); + } + + BOOST_DEDUCED_TYPENAME base_::const_reference back() const + { + return this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() + ( + this->base().back() + ); + } + + void push_front( + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x) + { + this->base().push_front( + this->template functor()(x)); + } + + void pop_front() + { + this->base().pop_front(); + } + + void push_back( + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x) + { + this->base().push_back( + this->template functor()(x)); + } + + void pop_back() + { + this->base().pop_back(); + } + + std::pair + insert(BOOST_DEDUCED_TYPENAME base_::iterator position, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x) + { + std::pair< BOOST_DEDUCED_TYPENAME Base::iterator, bool > r( + this->base().insert( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_to_base >()(x) + ) + ); + + return std::pair( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()(r.first), + r.second + ); + } + + void insert(BOOST_DEDUCED_TYPENAME base_::iterator position, + BOOST_DEDUCED_TYPENAME base_::size_type m, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x) + { + this->base().insert( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + m, + this->template functor()(x) + ); + } + + template< class InputIterator > + void insert(BOOST_DEDUCED_TYPENAME base_::iterator position, + InputIterator first, InputIterator last) + { + // This is the same problem found in the insert function + // of container_adaptor + // For now, do the simple thing. This can be optimized + + for( ; first != last ; ++first ) + { + this->base().insert( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()( position ), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_to_base >()( *first ) + ); + } + } + + // Totally ordered implementation + + bool operator==(const sequence_container_adaptor & c) const + { + return ( this->base() == c.base() ); + } + + bool operator<(const sequence_container_adaptor & c) const + { + return ( this->base() < c.base() ); + } +}; + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_SEQUENCE_CONTAINER_ADAPTOR_HPP diff --git a/win32/include/boost/bimap/container_adaptor/set_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/set_adaptor.hpp new file mode 100755 index 000000000..bcff9338e --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/set_adaptor.hpp @@ -0,0 +1,100 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/set_adaptor.hpp +/// \brief Container adaptor to easily build a std::set signature compatible container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_SET_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_SET_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +/// \brief Container adaptor to easily build a std::set signature compatible container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + class ReverseIterator, + class ConstReverseIterator, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class ReverseIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + class KeyToBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class set_adaptor : + + public ::boost::bimaps::container_adaptor:: + ordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + > +{ + + typedef ::boost::bimaps::container_adaptor:: + ordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + + > base_; + + // Access ----------------------------------------------------------------- + + public: + + explicit set_adaptor(Base & c) : + base_(c) {} + + protected: + + typedef set_adaptor set_adaptor_; + +}; + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_SET_ADAPTOR_HPP + + diff --git a/win32/include/boost/bimap/container_adaptor/support/iterator_facade_converters.hpp b/win32/include/boost/bimap/container_adaptor/support/iterator_facade_converters.hpp new file mode 100755 index 000000000..36b857941 --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/support/iterator_facade_converters.hpp @@ -0,0 +1,77 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/support/iterator_facade_converters.hpp +/// \brief Converter for Boost.Iterators based iterators. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_ITERATOR_FACADE_CONVERTERS_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_ITERATOR_FACADE_CONVERTERS_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +/// \brief Utilities to help in the construction of a container adaptor + +namespace support { + +/// \brief Converter for Boost.Iterators based iterators. +/** +Container adaptor is dessigned to play well with Boost.Iterators. This +converter can be used if this library is used to adapt the iterators. + **/ +template +< + class Iterator, + class ConstIterator +> +struct iterator_facade_to_base +{ + BOOST_DEDUCED_TYPENAME Iterator::base_type operator()(Iterator iter) const + { + return iter.base(); + } + + BOOST_DEDUCED_TYPENAME ConstIterator::base_type operator()(ConstIterator iter) const + { + return iter.base(); + } +}; + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template +< + class Iterator +> +struct iterator_facade_to_base +{ + BOOST_DEDUCED_TYPENAME Iterator::base_type operator()(Iterator iter) const + { + return iter.base(); + } +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#undef BOOST_BIMAP_CONTAINER_ADAPTOR_IMPLEMENT_CONVERT_FACADE_FUNCTION + + +} // namespace support +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_DETAIL_ITERATOR_FACADE_CONVERTERS_HPP diff --git a/win32/include/boost/bimap/container_adaptor/unordered_associative_container_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/unordered_associative_container_adaptor.hpp new file mode 100755 index 000000000..e64bc6ab4 --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/unordered_associative_container_adaptor.hpp @@ -0,0 +1,293 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/unordered_associative_container_adaptor.hpp +/// \brief Container adaptor to build a type that is compliant to the concept of an unordered associative container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template +< + class Base, class Iterator, class ConstIterator, + class LocalIterator, class ConstLocalIterator, + class KeyType, + class IteratorToBaseConverter, class IteratorFromBaseConverter, + class LocalIteratorFromBaseConverter, + class ValueToBaseConverter, class ValueFromBaseConverter, + class KeyToBaseConverter, + class FunctorsFromDerivedClasses +> +struct unordered_associative_container_adaptor_base +{ + + typedef associative_container_adaptor + < + Base, Iterator, ConstIterator, KeyType, + IteratorToBaseConverter, IteratorFromBaseConverter, + ValueToBaseConverter , ValueFromBaseConverter, + KeyToBaseConverter, + + BOOST_DEDUCED_TYPENAME mpl::push_front< + + FunctorsFromDerivedClasses, + + BOOST_DEDUCED_TYPENAME mpl::if_< + ::boost::mpl::is_na, + // { + detail::iterator_from_base_identity + < + BOOST_DEDUCED_TYPENAME Base::local_iterator, + LocalIterator, + BOOST_DEDUCED_TYPENAME Base::const_local_iterator, + ConstLocalIterator + >, + // } + // else + // { + LocalIteratorFromBaseConverter + // } + + >::type + + >::type + + > type; +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + + +/// \brief Container adaptor to build a type that is compliant to the concept of an unordered associative container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + + class LocalIterator, + class ConstLocalIterator, + + class KeyType, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class LocalIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + class KeyToBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> + +> +class unordered_associative_container_adaptor : + + public unordered_associative_container_adaptor_base + < + Base, Iterator, ConstIterator, + LocalIterator, ConstLocalIterator, + KeyType, + IteratorToBaseConverter, IteratorFromBaseConverter, + LocalIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + + >::type +{ + typedef BOOST_DEDUCED_TYPENAME unordered_associative_container_adaptor_base + < + Base, Iterator, ConstIterator, + LocalIterator, ConstLocalIterator, + KeyType, + IteratorToBaseConverter, IteratorFromBaseConverter, + LocalIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + + >::type base_; + + // Metadata --------------------------------------------------------------- + + public: + + typedef BOOST_DEDUCED_TYPENAME Base::key_equal key_equal; + typedef BOOST_DEDUCED_TYPENAME Base::hasher hasher; + + typedef LocalIterator local_iterator; + typedef ConstLocalIterator const_local_iterator; + + protected: + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< + ::boost::mpl::is_na, + // { + detail::iterator_from_base_identity + < + BOOST_DEDUCED_TYPENAME Base::local_iterator, + local_iterator, + BOOST_DEDUCED_TYPENAME Base::const_local_iterator, + const_local_iterator + >, + // } + // else + // { + LocalIteratorFromBaseConverter + // } + + >::type local_iterator_from_base; + + // Access ----------------------------------------------------------------- + + public: + + explicit unordered_associative_container_adaptor(Base & c) + : base_(c) {} + + protected: + + + typedef unordered_associative_container_adaptor + unordered_associative_container_adaptor_; + + // Interface -------------------------------------------------------------- + + public: + + // bucket interface: + + BOOST_DEDUCED_TYPENAME base_::size_type bucket_count() const + { + return this->base().bucket_count(); + } + + BOOST_DEDUCED_TYPENAME base_::size_type max_bucket_count() const + { + return this->base().max_bucket_count(); + } + + BOOST_DEDUCED_TYPENAME base_::size_type bucket_size( + BOOST_DEDUCED_TYPENAME base_::size_type n) const + { + return this->base().bucket_size(n); + } + + template< class CompatibleKey > + BOOST_DEDUCED_TYPENAME base_::size_type bucket( + const CompatibleKey & k) const + { + typedef BOOST_DEDUCED_TYPENAME base_::key_to_base key_to_base; + return this->base().bucket( + this->template functor()(k) + ); + } + + local_iterator begin(BOOST_DEDUCED_TYPENAME base_::size_type n) + { + return this->template functor< + local_iterator_from_base + >() ( this->base().begin(n) ); + } + + const_local_iterator begin(BOOST_DEDUCED_TYPENAME base_::size_type n) const + { + return this->template functor< + local_iterator_from_base + >() ( this->base().begin(n) ); + } + + local_iterator end(BOOST_DEDUCED_TYPENAME base_::size_type n) + { + return this->template functor< + local_iterator_from_base + >() ( this->base().end(n) ); + } + + const_local_iterator end(BOOST_DEDUCED_TYPENAME base_::size_type n) const + { + return this->template functor< + local_iterator_from_base + >() ( this->base().end(n) ); + } + + // hash policy + + float load_factor() const + { + return this->base().load_factor(); + } + + float max_load_factor() const + { + return this->base().max_load_factor(); + } + + void max_load_factor(float z) + { + return this->base().max_load_factor(z); + } + + void rehash(BOOST_DEDUCED_TYPENAME base_::size_type n) + { + return this->base().rehash(n); + } + + // We have redefined end and begin so we have to manually route the old ones + + BOOST_DEDUCED_TYPENAME base_::iterator begin() + { + return base_::container_adaptor_::begin(); + } + + BOOST_DEDUCED_TYPENAME base_::iterator end() + { + return base_::container_adaptor_::end(); + } + + BOOST_DEDUCED_TYPENAME base_::const_iterator begin() const + { + return base_::container_adaptor_::begin(); + } + + BOOST_DEDUCED_TYPENAME base_::const_iterator end() const + { + return base_::container_adaptor_::end(); + } + +}; + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_ASSOCIATIVE_CONTAINER_ADAPTOR_HPP diff --git a/win32/include/boost/bimap/container_adaptor/unordered_map_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/unordered_map_adaptor.hpp new file mode 100755 index 000000000..1e093868b --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/unordered_map_adaptor.hpp @@ -0,0 +1,132 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/unordered_map_adaptor.hpp +/// \brief Container adaptor to easily build a std::unordered_map signature compatible container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MAP_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MAP_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +/// \brief Container adaptor to easily build a std::unordered_map signature compatible container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + class LocalIterator, + class ConstLocalIterator, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class LocalIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + class KeyToBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class unordered_map_adaptor : + + public ::boost::bimaps::container_adaptor:: + unordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, LocalIterator, ConstLocalIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + LocalIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + > +{ + + typedef ::boost::bimaps::container_adaptor:: + unordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, LocalIterator, ConstLocalIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + LocalIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + + > base_; + + // MetaData ------------------------------------------------------------- + + public: + + typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::second_type data_type; + + // Access ----------------------------------------------------------------- + + public: + + explicit unordered_map_adaptor(Base & c) : + base_(c) {} + + protected: + + typedef unordered_map_adaptor unordered_map_adaptor_; + + // Interface -------------------------------------------------------------- + + public: + + template< class CompatibleKey > + data_type& operator[](const CompatibleKey & k) + { + return this->base() + [this->template functor()(k)]; + } + + template< class CompatibleKey > + data_type& at(const CompatibleKey & k) + { + return this->base(). + at(this->template functor()(k)); + } + + template< class CompatibleKey > + const data_type& at(const CompatibleKey & k) const + { + return this->base(). + at(this->template functor()(k)); + } + +}; + + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MAP_ADAPTOR_HPP + diff --git a/win32/include/boost/bimap/container_adaptor/unordered_multimap_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/unordered_multimap_adaptor.hpp new file mode 100755 index 000000000..b3cbae1c7 --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/unordered_multimap_adaptor.hpp @@ -0,0 +1,110 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/unordered_multimap_adaptor.hpp +/// \brief Container adaptor to easily build a std::unordered_multimap signature compatible container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MULTIMAP_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MULTIMAP_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +/// \brief Container adaptor to easily build a std::unordered_multimap signature compatible container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + class LocalIterator, + class ConstLocalIterator, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class LocalIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + class KeyToBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class unordered_multimap_adaptor : + + public ::boost::bimaps::container_adaptor:: + unordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, LocalIterator, ConstLocalIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + LocalIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + > +{ + typedef ::boost::bimaps::container_adaptor:: + unordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, LocalIterator, ConstLocalIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + LocalIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + + > base_; + + // MetaData ------------------------------------------------------------- + + public: + + typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::second_type data_type; + + // Access ----------------------------------------------------------------- + + public: + + explicit unordered_multimap_adaptor(Base & c) : + base_(c) {} + + protected: + + typedef unordered_multimap_adaptor unordered_multimap_adaptor_; + + public: + + BOOST_BIMAP_NON_UNIQUE_CONTAINER_ADAPTOR_INSERT_FUNCTIONS +}; + + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MULTIMAP_ADAPTOR_HPP + + diff --git a/win32/include/boost/bimap/container_adaptor/unordered_multiset_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/unordered_multiset_adaptor.hpp new file mode 100755 index 000000000..d611a42b7 --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/unordered_multiset_adaptor.hpp @@ -0,0 +1,102 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/unordered_multiset_adaptor.hpp +/// \brief Container adaptor to easily build a std::unordered_multiset signature compatible container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MULTISET_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MULTISET_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +/// \brief Container adaptor to easily build a std::unordered_multiset signature compatible container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + class LocalIterator, + class ConstLocalIterator, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class LocalIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + class KeyToBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class unordered_multiset_adaptor : + + public ::boost::bimaps::container_adaptor:: + unordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, LocalIterator, ConstLocalIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + LocalIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + > +{ + typedef ::boost::bimaps::container_adaptor:: + unordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, LocalIterator, ConstLocalIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + LocalIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + + > base_; + + // Access ----------------------------------------------------------------- + + public: + + explicit unordered_multiset_adaptor(Base & c) : + base_(c) {} + + protected: + + typedef unordered_multiset_adaptor unordered_multiset_adaptor_; + + public: + + BOOST_BIMAP_NON_UNIQUE_CONTAINER_ADAPTOR_INSERT_FUNCTIONS +}; + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_MULTISET_ADAPTOR_HPP + diff --git a/win32/include/boost/bimap/container_adaptor/unordered_set_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/unordered_set_adaptor.hpp new file mode 100755 index 000000000..3b3d3bdaa --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/unordered_set_adaptor.hpp @@ -0,0 +1,98 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/unordered_set_adaptor.hpp +/// \brief Container adaptor to easily build a std::unordered_set signature compatible container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_SET_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_SET_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +/// \brief Container adaptor to easily build a std::unordered_set signature compatible container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + class LocalIterator, + class ConstLocalIterator, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class LocalIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + class KeyToBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class unordered_set_adaptor : + + public ::boost::bimaps::container_adaptor:: + unordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, LocalIterator, ConstLocalIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + LocalIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + > +{ + typedef ::boost::bimaps::container_adaptor:: + unordered_associative_container_adaptor + < + Base, + Iterator, ConstIterator, LocalIterator, ConstLocalIterator, + BOOST_DEDUCED_TYPENAME Iterator::value_type, + IteratorToBaseConverter, IteratorFromBaseConverter, + LocalIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + KeyToBaseConverter, + FunctorsFromDerivedClasses + + > base_; + + // Access ----------------------------------------------------------------- + + public: + + explicit unordered_set_adaptor(Base & c) : + base_(c) {} + + protected: + + typedef unordered_set_adaptor unordered_set_adaptor_; + +}; + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_UNORDERED_SET_ADAPTOR_HPP + diff --git a/win32/include/boost/bimap/container_adaptor/vector_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/vector_adaptor.hpp new file mode 100755 index 000000000..d0ce022ac --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/vector_adaptor.hpp @@ -0,0 +1,142 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/vector_adaptor.hpp +/// \brief Container adaptor to easily build a std::vector signature compatible container. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_VECTOR_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_VECTOR_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +/// \brief Container adaptor to easily build a std::vector signature compatible container. + +template +< + class Base, + + class Iterator, + class ConstIterator, + class ReverseIterator, + class ConstReverseIterator, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class ReverseIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class vector_adaptor : + + public ::boost::bimaps::container_adaptor::sequence_container_adaptor + < + Base, + Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + FunctorsFromDerivedClasses + > +{ + + typedef ::boost::bimaps::container_adaptor::sequence_container_adaptor + < + Base, + Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + FunctorsFromDerivedClasses + + > base_; + + // Access ----------------------------------------------------------------- + + public: + + vector_adaptor() {} + + explicit vector_adaptor(Base & c) : + base_(c) {} + + protected: + + typedef vector_adaptor vector_adaptor_; + + // Interface -------------------------------------------------------------- + + public: + + BOOST_DEDUCED_TYPENAME base_::size_type capacity() const + { + return this->base().capacity(); + } + + void reserve(BOOST_DEDUCED_TYPENAME base_::size_type m) + { + this->base().resize(m); + } + + void resize(BOOST_DEDUCED_TYPENAME base_::size_type n, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x = + BOOST_DEDUCED_TYPENAME base_::value_type()) + { + this->base().resize(n, + this->template functor()(x) + ); + } + + BOOST_DEDUCED_TYPENAME base_::const_reference + operator[](BOOST_DEDUCED_TYPENAME base_::size_type n) const + { + return this->base().operator[](n); + } + + BOOST_DEDUCED_TYPENAME base_::const_reference + at(BOOST_DEDUCED_TYPENAME base_::size_type n) const + { + return this->base().at(n); + } + + BOOST_DEDUCED_TYPENAME base_::reference + operator[](BOOST_DEDUCED_TYPENAME base_::size_type n) + { + return this->base().operator[](n); + } + + BOOST_DEDUCED_TYPENAME base_::reference + at(BOOST_DEDUCED_TYPENAME base_::size_type n) + { + return this->base().at(n); + } +}; + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_VECTOR_ADAPTOR_HPP + + diff --git a/win32/include/boost/bimap/container_adaptor/vector_map_adaptor.hpp b/win32/include/boost/bimap/container_adaptor/vector_map_adaptor.hpp new file mode 100755 index 000000000..c099c3c26 --- /dev/null +++ b/win32/include/boost/bimap/container_adaptor/vector_map_adaptor.hpp @@ -0,0 +1,103 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file container_adaptor/vector_map_adaptor.hpp +/// \brief Container adaptor. + +#ifndef BOOST_BIMAP_CONTAINER_ADAPTOR_VECTOR_MAP_ADAPTOR_HPP +#define BOOST_BIMAP_CONTAINER_ADAPTOR_VECTOR_MAP_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace container_adaptor { + +/// \brief Container adaptor. + +template +< + class Base, + + class Iterator, + class ConstIterator, + class ReverseIterator, + class ConstReverseIterator, + + class IteratorToBaseConverter = ::boost::mpl::na, + class IteratorFromBaseConverter = ::boost::mpl::na, + class ReverseIteratorFromBaseConverter = ::boost::mpl::na, + class ValueToBaseConverter = ::boost::mpl::na, + class ValueFromBaseConverter = ::boost::mpl::na, + + class FunctorsFromDerivedClasses = mpl::vector<> +> +class vector_map_adaptor : + + public vector_adaptor + < + Base, + Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + FunctorsFromDerivedClasses + > +{ + typedef vector_adaptor + < + Base, + Iterator, ConstIterator, ReverseIterator, ConstReverseIterator, + IteratorToBaseConverter, IteratorFromBaseConverter, + ReverseIteratorFromBaseConverter, + ValueToBaseConverter, ValueFromBaseConverter, + FunctorsFromDerivedClasses + + > base_; + + // MetaData ------------------------------------------------------------- + + public: + + typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::first_type key_type; + typedef BOOST_DEDUCED_TYPENAME Iterator::value_type::second_type data_type; + + // Access ----------------------------------------------------------------- + + public: + + vector_map_adaptor() {} + + explicit vector_map_adaptor(Base & c) : + base_(c) {} + + protected: + + typedef vector_map_adaptor vector_map_adaptor_; + +}; + + +} // namespace container_adaptor +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_CONTAINER_ADAPTOR_VECTOR_MAP_ADAPTOR_HPP + diff --git a/win32/include/boost/bimap/detail/bimap_core.hpp b/win32/include/boost/bimap/detail/bimap_core.hpp new file mode 100755 index 000000000..b51504979 --- /dev/null +++ b/win32/include/boost/bimap/detail/bimap_core.hpp @@ -0,0 +1,520 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/bimap_core.hpp +/// \brief Bimap base definition. + +#ifndef BOOST_BIMAP_DETAIL_BIMAP_CORE_HPP +#define BOOST_BIMAP_DETAIL_BIMAP_CORE_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +// Boost.MultiIndex +#include +#include + +// Boost.Bimap +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace bimaps { + +/// \brief Library details + +namespace detail { + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class Type > +struct get_value_type +{ + typedef BOOST_DEDUCED_TYPENAME Type::value_type type; +}; + +struct independent_index_tag {}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + + +/// \brief Base for the bimap class. +/** + + +See also bimap. + **/ + + +template< class LeftSetType, class RightSetType, class AP1, class AP2, class AP3 > +class bimap_core +{ + // Manage bimap key instantiation + // -------------------------------------------------------------------- + public: + + typedef BOOST_DEDUCED_TYPENAME manage_bimap_key + < + LeftSetType + + >::type left_set_type; + + typedef BOOST_DEDUCED_TYPENAME manage_bimap_key + < + RightSetType + + >::type right_set_type; + + + private: + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::default_tagged + < + BOOST_DEDUCED_TYPENAME left_set_type::user_type, + ::boost::bimaps::relation::member_at::left + + >::type left_tagged_type; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support::default_tagged + < + BOOST_DEDUCED_TYPENAME right_set_type::user_type, + ::boost::bimaps::relation::member_at::right + + >::type right_tagged_type; + + public: + + //@{ + + typedef BOOST_DEDUCED_TYPENAME left_tagged_type::tag left_tag; + typedef BOOST_DEDUCED_TYPENAME right_tagged_type::tag right_tag; + + //@} + + //@{ + + typedef BOOST_DEDUCED_TYPENAME left_set_type::value_type left_key_type; + typedef BOOST_DEDUCED_TYPENAME right_set_type::value_type right_key_type; + + //@} + + //@{ + + typedef right_key_type left_data_type; + typedef left_key_type right_data_type; + + //@} + + // Manage the additional parameters + // -------------------------------------------------------------------- + private: + + typedef BOOST_DEDUCED_TYPENAME manage_additional_parameters::type parameters; + + /// \brief Relation type stored by the bimap. + // -------------------------------------------------------------------- + public: + + typedef ::boost::bimaps::relation::mutant_relation + < + + ::boost::bimaps::tags::tagged< + BOOST_DEDUCED_TYPENAME mpl::if_< + mpl::and_ + < + BOOST_DEDUCED_TYPENAME left_set_type::mutable_key, + BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation::left_mutable_key + >, + // { + left_key_type, + // } + // else + // { + BOOST_DEDUCED_TYPENAME ::boost::add_const< left_key_type >::type + // } + + >::type, + left_tag + >, + + ::boost::bimaps::tags::tagged< + BOOST_DEDUCED_TYPENAME mpl::if_< + mpl::and_ + < + BOOST_DEDUCED_TYPENAME right_set_type::mutable_key, + BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation::right_mutable_key + >, + // { + right_key_type, + // } + // else + // { + BOOST_DEDUCED_TYPENAME ::boost::add_const< right_key_type >::type + // } + + >::type, + right_tag + >, + + // It is ::boost::mpl::na if no info_hook was included + BOOST_DEDUCED_TYPENAME parameters::additional_info, + + // Force mutable keys + true + + > relation; + + //@{ + + typedef BOOST_DEDUCED_TYPENAME relation::left_pair left_value_type; + typedef BOOST_DEDUCED_TYPENAME relation::right_pair right_value_type; + + //@} + + // Bind the member of the relation, so multi_index can manage them + // -------------------------------------------------------------------- + private: + + typedef BOOST_DEDUCED_TYPENAME relation::storage_base relation_storage_base; + + typedef BOOST_MULTI_INDEX_MEMBER(relation_storage_base, left_key_type, left) + left_member_extractor; + + typedef BOOST_MULTI_INDEX_MEMBER(relation_storage_base,right_key_type,right) + right_member_extractor; + + // The core indices are somewhat complicated to calculate, because they + // can be zero, one, two or three indices, depending on the use of + // {side}_based set type of relations and unconstrained_set_of and + // unconstrained_set_of_relation specifications. + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< + ::boost::bimaps::detail::is_unconstrained_set_of< left_set_type >, + // { + mpl::vector<>, + // } + // else + // { + mpl::vector + < + BOOST_DEDUCED_TYPENAME left_set_type:: + BOOST_NESTED_TEMPLATE index_bind + < + left_member_extractor, + left_tag + + >::type + > + // } + >::type left_core_indices; + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< + ::boost::bimaps::detail::is_unconstrained_set_of< right_set_type >, + // { + left_core_indices, + // } + // else + // { + BOOST_DEDUCED_TYPENAME mpl::push_front + < + left_core_indices, + + BOOST_DEDUCED_TYPENAME right_set_type:: + BOOST_NESTED_TEMPLATE index_bind + < + right_member_extractor, + right_tag + + >::type + + >::type + // } + >::type basic_core_indices; + + // If it is based either on the left or on the right, then only the side + // indices are needed. But the set type of the relation can be completely + // diferent from the one used for the sides in wich case we have to add yet + // another index to the core. + + // TODO + // If all the set types are unsconstrained there must be readable compile + // time error. + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< + + is_same< BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation, left_based >, + // { + ::boost::bimaps::tags::tagged< left_set_type, left_tag >, + // } + /* else */ BOOST_DEDUCED_TYPENAME mpl::if_< + is_same< BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation, right_based >, + // { + ::boost::bimaps::tags::tagged< right_set_type, right_tag >, + // } + // else + // { + tags::tagged + < + BOOST_DEDUCED_TYPENAME parameters:: + set_type_of_relation::BOOST_NESTED_TEMPLATE bind_to + < + relation + + >::type, + independent_index_tag + > + // } + >::type + >::type tagged_set_of_relation_type; + + protected: + + typedef BOOST_DEDUCED_TYPENAME tagged_set_of_relation_type::tag + relation_set_tag; + + typedef BOOST_DEDUCED_TYPENAME tagged_set_of_relation_type::value_type + relation_set_type_of; + + // Logic tags + // This is a necesary extra level of indirection to allow unconstrained + // sets to be plug in the design. The bimap constructors use this logic + // tags. + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< + ::boost::bimaps::detail::is_unconstrained_set_of< left_set_type >, + + BOOST_DEDUCED_TYPENAME mpl::if_< + ::boost::bimaps::detail::is_unconstrained_set_of< right_set_type >, + + independent_index_tag, + right_tag + + >::type, + + left_tag + + >::type logic_left_tag; + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< + ::boost::bimaps::detail::is_unconstrained_set_of< right_set_type >, + + BOOST_DEDUCED_TYPENAME mpl::if_< + ::boost::bimaps::detail::is_unconstrained_set_of< left_set_type >, + + independent_index_tag, + left_tag + + >::type, + + right_tag + + >::type logic_right_tag; + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< + is_same< relation_set_tag, independent_index_tag >, + + BOOST_DEDUCED_TYPENAME mpl::if_< + ::boost::bimaps::detail:: + is_unconstrained_set_of< relation_set_type_of >, + + logic_left_tag, + independent_index_tag + + >::type, + + BOOST_DEDUCED_TYPENAME mpl::if_< + is_same< BOOST_DEDUCED_TYPENAME parameters::set_type_of_relation, left_based >, + + logic_left_tag, + logic_right_tag + + >::type + + >::type logic_relation_set_tag; + + private: + + typedef BOOST_DEDUCED_TYPENAME mpl::if_< + mpl::and_< is_same< relation_set_tag, independent_index_tag >, + mpl::not_< + ::boost::bimaps::detail:: + is_unconstrained_set_of< relation_set_type_of > + > + >, + // { + BOOST_DEDUCED_TYPENAME mpl::push_front + < + basic_core_indices, + + BOOST_DEDUCED_TYPENAME relation_set_type_of:: + BOOST_NESTED_TEMPLATE index_bind + < + ::boost::bimaps::relation::support::both_keys_extractor, + independent_index_tag + + >::type + + >::type, + // } + // else + // { + basic_core_indices + // } + + >::type complete_core_indices; + + struct core_indices : public complete_core_indices {}; + + // Define the core using compute_index_type to translate the + // set type to an multi-index specification + // -------------------------------------------------------------------- + public: + + typedef multi_index::multi_index_container + < + relation, + core_indices, + BOOST_DEDUCED_TYPENAME parameters::allocator:: + BOOST_NESTED_TEMPLATE rebind::other + + > core_type; + + // Core metadata + // -------------------------------------------------------------------- + public: + + typedef BOOST_DEDUCED_TYPENAME ::boost::multi_index:: + index::type left_index; + + typedef BOOST_DEDUCED_TYPENAME ::boost::multi_index:: + index::type right_index; + + typedef BOOST_DEDUCED_TYPENAME left_index::iterator left_core_iterator; + typedef BOOST_DEDUCED_TYPENAME left_index::const_iterator left_core_const_iterator; + + typedef BOOST_DEDUCED_TYPENAME right_index::iterator right_core_iterator; + typedef BOOST_DEDUCED_TYPENAME right_index::const_iterator right_core_const_iterator; + + // Map by {side} iterator metadata + // -------------------------------------------------------------------- + public: + + //@{ + + typedef ::boost::bimaps::detail::map_view_iterator + < + left_tag, + relation, + left_core_iterator + + > left_iterator; + + typedef ::boost::bimaps::detail::map_view_iterator + < + right_tag, + relation, + right_core_iterator + + > right_iterator; + + //@} + + //@{ + + typedef ::boost::bimaps::detail::const_map_view_iterator + < + left_tag, + relation, + left_core_const_iterator + + > left_const_iterator; + + typedef ::boost::bimaps::detail::const_map_view_iterator + < + right_tag, + relation, + right_core_const_iterator + + > right_const_iterator; + + //@} + + // Relation set view + + typedef BOOST_DEDUCED_TYPENAME ::boost::multi_index::index + < + core_type, logic_relation_set_tag + + >::type relation_set_core_index; + + typedef BOOST_DEDUCED_TYPENAME relation_set_type_of:: + BOOST_NESTED_TEMPLATE set_view_bind + < + relation_set_core_index + + >::type relation_set; + + public: + + typedef bimap_core bimap_core_; +}; + +// Two auxiliar metafunctions to compute the map view types +// The map view type can not be computed inside the bimap core because a +// they need the bimap core to be parsed first. + +template< class BimapBaseType > +struct left_map_view_type +{ + typedef BOOST_DEDUCED_TYPENAME BimapBaseType::left_set_type left_set_type; + typedef BOOST_DEDUCED_TYPENAME + left_set_type::BOOST_NESTED_TEMPLATE map_view_bind< + BOOST_DEDUCED_TYPENAME BimapBaseType::left_tag, BimapBaseType + >::type type; +}; + +template< class BimapBaseType > +struct right_map_view_type +{ + typedef BOOST_DEDUCED_TYPENAME BimapBaseType::right_set_type right_set_type; + typedef BOOST_DEDUCED_TYPENAME + right_set_type::BOOST_NESTED_TEMPLATE map_view_bind< + BOOST_DEDUCED_TYPENAME BimapBaseType::right_tag, BimapBaseType + >::type type; +}; + +} // namespace detail +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DETAIL_BIMAP_CORE_HPP diff --git a/win32/include/boost/bimap/detail/concept_tags.hpp b/win32/include/boost/bimap/detail/concept_tags.hpp new file mode 100755 index 000000000..cd20e15fc --- /dev/null +++ b/win32/include/boost/bimap/detail/concept_tags.hpp @@ -0,0 +1,97 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/concept_tags.hpp +/// \brief Bimap tags and concepts + +#ifndef BOOST_BIMAP_DETAIL_CONCEPT_TAGS_HPP +#define BOOST_BIMAP_DETAIL_CONCEPT_TAGS_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace detail { + +/// \brief Tag of {SetType}_of definition classes +/** +The {SetType}_of classes are derived from this class so it is easy to construct +metafunctions. For example now is easy to create a is_set_type_of metafunction. + **/ + +struct set_type_of_tag {}; + +/// \brief Tag of {SetType}_of_relation defition classes + +struct set_type_of_relation_tag {}; + +/// \brief Tag of {Side}_based identifiers + +struct side_based_tag : set_type_of_relation_tag {}; + +} // namespace detail + + +/** \struct boost::bimaps::left_based + \brief Tag to indicate that the main view will be based on the left side. + +This is convenient because the multi-index core will be more efficient. +If possible use this options or the right based one. + +See also right_based. + **/ + +/** \struct boost::bimaps::right_based + \brief Tag to indicate that the main view will be based on the right side. + +This is convenient because the multi-index core will be more efficient. +If possible use this options or the right based one. + +See also left_based. + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +struct left_based : ::boost::bimaps::detail::side_based_tag +{ + // I run into troubles if I do not define bind for side based tags. + // Maybe a more coherent way of binding the relation can be developped. + template< class Relation > struct bind_to { typedef void type; }; + + typedef mpl::bool_ left_mutable_key; + typedef mpl::bool_ right_mutable_key; +}; + +struct right_based : ::boost::bimaps::detail::side_based_tag +{ + // I run into troubles if I do not define bind for side based tags. + // Maybe a more coherent way of binding the relation can be developped. + template< class Relation > struct bind_to { typedef void type; }; + + typedef mpl::bool_ left_mutable_key; + typedef mpl::bool_ right_mutable_key; +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +typedef mpl::_ _relation; + +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_DETAIL_CONCEPT_TAGS_HPP + diff --git a/win32/include/boost/bimap/detail/debug/static_error.hpp b/win32/include/boost/bimap/detail/debug/static_error.hpp new file mode 100755 index 000000000..59a75afdf --- /dev/null +++ b/win32/include/boost/bimap/detail/debug/static_error.hpp @@ -0,0 +1,36 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/debug/static_error.hpp +/// \brief Formatted compile time error + +#ifndef BOOST_BIMAP_DETAIL_DEBUG_STATIC_ERROR_HPP +#define BOOST_BIMAP_DETAIL_DEBUG_STATIC_ERROR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +// Easier way to call BOOST_MPL_ASSERT_MSG in class scope to generate +// a static error. +/*===========================================================================*/ +#define BOOST_BIMAP_STATIC_ERROR(MESSAGE,VARIABLES) \ + struct BOOST_PP_CAT(BIMAP_STATIC_ERROR__,MESSAGE) {}; \ + BOOST_MPL_ASSERT_MSG(false, \ + BOOST_PP_CAT(BIMAP_STATIC_ERROR__,MESSAGE), \ + VARIABLES) +/*===========================================================================*/ + + + +#endif // BOOST_BIMAP_DETAIL_DEBUG_STATIC_ERROR_HPP diff --git a/win32/include/boost/bimap/detail/generate_index_binder.hpp b/win32/include/boost/bimap/detail/generate_index_binder.hpp new file mode 100755 index 000000000..1ac5b594d --- /dev/null +++ b/win32/include/boost/bimap/detail/generate_index_binder.hpp @@ -0,0 +1,125 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/generate_index_binder.hpp +/// \brief Define macros to help building the set type of definitions + + +#ifndef BOOST_BIMAP_DETAIL_GENERATE_INDEX_BINDER_HPP +#define BOOST_BIMAP_DETAIL_GENERATE_INDEX_BINDER_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + + +/*===========================================================================*/ +#define BOOST_BIMAP_GENERATE_INDEX_BINDER_0CP( \ + \ + MULTI_INDEX_TYPE \ + \ +) \ + \ +template< class KeyExtractor, class Tag > \ +struct index_bind \ +{ \ + typedef MULTI_INDEX_TYPE \ + < \ + multi_index::tag< Tag >, \ + KeyExtractor \ + \ + > type; \ +}; +/*===========================================================================*/ + + + +/*===========================================================================*/ +#define BOOST_BIMAP_GENERATE_INDEX_BINDER_1CP( \ + \ + MULTI_INDEX_TYPE, \ + CONFIG_PARAMETER \ + \ +) \ + \ +template< class KeyExtractor, class Tag > \ +struct index_bind \ +{ \ + typedef MULTI_INDEX_TYPE \ + < \ + multi_index::tag< Tag >, \ + KeyExtractor, \ + CONFIG_PARAMETER \ + \ + > type; \ +}; +/*===========================================================================*/ + + + + +/*===========================================================================*/ +#define BOOST_BIMAP_GENERATE_INDEX_BINDER_2CP( \ + \ + MULTI_INDEX_TYPE, \ + CONFIG_PARAMETER_1, \ + CONFIG_PARAMETER_2 \ +) \ + \ +template< class KeyExtractor, class Tag > \ +struct index_bind \ +{ \ + typedef MULTI_INDEX_TYPE \ + < \ + multi_index::tag< Tag >, \ + KeyExtractor, \ + CONFIG_PARAMETER_1, \ + CONFIG_PARAMETER_2 \ + \ + > type; \ + \ +}; +/*===========================================================================*/ + + +// This is a special registration to allow sequenced and random access indices +// to play along smoothly with the other index types. + +/*===========================================================================*/ +#define BOOST_BIMAP_GENERATE_INDEX_BINDER_0CP_NO_EXTRACTOR( \ + \ + MULTI_INDEX_TYPE \ + \ +) \ + \ +template< class KeyExtractor, class Tag > \ +struct index_bind \ +{ \ + typedef MULTI_INDEX_TYPE< multi_index::tag< Tag > > type; \ +}; +/*===========================================================================*/ + + +// This is yet another special registration to allow unconstrained sets +// to play along smoothly with the other index types. + +/*===========================================================================*/ +#define BOOST_BIMAP_GENERATE_INDEX_BINDER_FAKE \ + \ +template< class KeyExtractor, class Tag > \ +struct index_bind \ +{ \ + typedef void type; \ +}; \ +/*===========================================================================*/ + +#endif // BOOST_BIMAP_DETAIL_GENERATE_INDEX_BINDER_HPP diff --git a/win32/include/boost/bimap/detail/generate_relation_binder.hpp b/win32/include/boost/bimap/detail/generate_relation_binder.hpp new file mode 100755 index 000000000..f3add9e71 --- /dev/null +++ b/win32/include/boost/bimap/detail/generate_relation_binder.hpp @@ -0,0 +1,88 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/generate_relation_binder.hpp +/// \brief Define macros to help building the set type of definitions + +#ifndef BOOST_BIMAP_DETAIL_GENERATE_RELATION_BINDER_HPP +#define BOOST_BIMAP_DETAIL_GENERATE_RELATION_BINDER_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +/*===========================================================================*/ +#define BOOST_BIMAP_GENERATE_RELATION_BINDER_0CP( \ + \ + SET_TYPE_OF \ + ) \ + \ + template< class Relation > \ + struct bind_to \ + { \ + typedef SET_TYPE_OF type; \ + \ + }; +/*===========================================================================*/ + + + +/*===========================================================================*/ +#define BOOST_BIMAP_GENERATE_RELATION_BINDER_1CP( \ + \ + SET_TYPE_OF, \ + CP1 \ + ) \ + \ + template< class Relation > \ + struct bind_to \ + { \ + typedef SET_TYPE_OF \ + < \ + Relation, \ + BOOST_DEDUCED_TYPENAME mpl::apply::type \ + \ + > type; \ + \ + }; +/*===========================================================================*/ + + + +/*===========================================================================*/ +#define BOOST_BIMAP_GENERATE_RELATION_BINDER_2CP( \ + \ + SET_TYPE_OF, \ + CP1, \ + CP2 \ + ) \ + \ + template< class Relation > \ + struct bind_to \ + { \ + typedef SET_TYPE_OF \ + < \ + Relation, \ + BOOST_DEDUCED_TYPENAME mpl::apply::type, \ + BOOST_DEDUCED_TYPENAME mpl::apply::type \ + \ + > type; \ + \ + }; +/*===========================================================================*/ + + + +#endif // BOOST_BIMAP_DETAIL_GENERATE_RELATION_BINDER_HPP diff --git a/win32/include/boost/bimap/detail/generate_view_binder.hpp b/win32/include/boost/bimap/detail/generate_view_binder.hpp new file mode 100755 index 000000000..1442e5f45 --- /dev/null +++ b/win32/include/boost/bimap/detail/generate_view_binder.hpp @@ -0,0 +1,58 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/generate_view_binder.hpp +/// \brief Define macros to help building the set type of definitions + +#ifndef BOOST_BIMAP_DETAIL_GENERATE_VIEW_BINDER_HPP +#define BOOST_BIMAP_DETAIL_GENERATE_VIEW_BINDER_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +/*===========================================================================*/ +#define BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER( \ + \ + MAP_VIEW_TYPE \ + \ +) \ + \ +template< class Tag, class BimapType > \ +struct map_view_bind \ +{ \ + typedef MAP_VIEW_TYPE \ + < \ + Tag, \ + BimapType \ + \ + > type; \ +}; +/*===========================================================================*/ + + +/*===========================================================================*/ +#define BOOST_BIMAP_GENERATE_SET_VIEW_BINDER( \ + \ + SET_VIEW_TYPE \ + \ +) \ + \ +template< class IndexType > \ +struct set_view_bind \ +{ \ + typedef SET_VIEW_TYPE type; \ +}; +/*===========================================================================*/ + + +#endif // BOOST_BIMAP_DETAIL_GENERATE_VIEW_BINDER_HPP diff --git a/win32/include/boost/bimap/detail/is_set_type_of.hpp b/win32/include/boost/bimap/detail/is_set_type_of.hpp new file mode 100755 index 000000000..109733c11 --- /dev/null +++ b/win32/include/boost/bimap/detail/is_set_type_of.hpp @@ -0,0 +1,66 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/is_set_type_of.hpp +/// \brief Is set type of and is set type of relation metafunctions. + +#ifndef BOOST_BIMAP_DETAIL_IS_SET_TYPE_OF_HPP +#define BOOST_BIMAP_DETAIL_IS_SET_TYPE_OF_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +/** \struct boost::bimaps::detail::is_set_type_of + +\brief Type trait to check if a class is a set_type_of specification + +\code +template< class Type > +struct is_set_type_of : {true_|false_} {}; +\endcode + **/ + +/** \struct boost::bimaps::detail::is_set_type_of_relation + +\brief Type trait to check if a class is a set_type_of_relation specification + +\code +template< class Type > +struct is_set_type_of_relation : {true_|false_} {}; +\endcode + + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace detail { + +template< class Type > +struct is_set_type_of : + is_base_of< set_type_of_tag, Type > {}; + +template< class Type > +struct is_set_type_of_relation : + is_base_of< set_type_of_relation_tag, Type > {}; + +} // namespace detail +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_DETAIL_IS_SET_TYPE_OF_HPP + diff --git a/win32/include/boost/bimap/detail/manage_additional_parameters.hpp b/win32/include/boost/bimap/detail/manage_additional_parameters.hpp new file mode 100755 index 000000000..7947f7662 --- /dev/null +++ b/win32/include/boost/bimap/detail/manage_additional_parameters.hpp @@ -0,0 +1,243 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/manage_additional_parameters.hpp +/// \brief Utility class to extract the additional parameters from the template parameters. + +#ifndef BOOST_BIMAP_DETAIL_MANAGE_ADDITIONAL_PARAMETERS_HPP +#define BOOST_BIMAP_DETAIL_MANAGE_ADDITIONAL_PARAMETERS_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +// Boost.MPL +#include +#include +#include +#include + +#include + +namespace boost { +namespace bimaps { + +template< class Type > +struct with_info +{ + typedef Type value_type; +}; + +namespace detail { + +/// \brief Metafunction to check if a given type is a data_hook specification. + +template< class Type > +struct is_with_info : ::boost::mpl::false_ {}; + +template< class ValueType > +struct is_with_info< with_info > : ::boost::mpl::true_ {}; + +/** \struct boost::bimaps::detail::manage_additional_parameters +\brief Utility class to extract the additional parameters from the template parameters. + +\code +template< class AP1, class AP2, class AP3 > +struct manage_additional_parameters +{ + struct parameters + { + typedef -unspecified- set_type_of_relation; + typedef -unspecified- data_hook; + typedef -unspecified- allocator; + }; + + typedef parameters type; +}; +\endcode + +See also bimap, bimap_core. + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class AP1, class AP2, class AP3 > +struct manage_additional_parameters +{ + // (1) manage_additional_parameters< + // not_specified,not_specified,not_specified> + // + // set_type_of_relation: based on the left key type + // info_hook: no additional info + // allocator: default allocator + + struct case_NNN + { + typedef left_based set_type_of_relation; + typedef std::allocator allocator; + typedef ::boost::mpl::na additional_info; + }; + + // (2) manage_additional_parameters + // + // set_type_of_relation: based on the left key type + // info_hook: no additional info + // allocator: Allocator + + struct case_ANN + { + typedef left_based set_type_of_relation; + typedef AP1 allocator; + typedef ::boost::mpl::na additional_info; + }; + + // (3) manage_additional_parameters< + // SetOfRelationType,not_specified,not_specified> + // + // set_type_of_relation: SetTypeOfRelation + // info_hook: no additional info + // allocator: default allocator + + struct case_SNN + { + typedef AP1 set_type_of_relation; + typedef std::allocator allocator; + typedef ::boost::mpl::na additional_info; + }; + + // (4) manage_additional_parameters< + // SetTypeOfRelation,Allocator,not_specified> + // + // set_type_of_relation: SetTypeOfRelation + // info_hook: no additional info + // allocator: Allocator + + struct case_SAN + { + typedef AP1 set_type_of_relation; + typedef AP2 allocator; + typedef ::boost::mpl::na additional_info; + }; + + // (5) manage_additional_parameters + // + // set_type_of_relation: based on the left key type + // info_hook: InfoToHook + // allocator: default allocator + + struct case_HNN + { + typedef left_based set_type_of_relation; + typedef std::allocator allocator; + typedef BOOST_DEDUCED_TYPENAME AP1::value_type additional_info; + }; + + // (6) manage_additional_parameters< + // SetTypeOfRelation,InfoToHook,not_specified> + // + // set_type_of_relation: SetTypeOfRelation + // info_hook: InfoToHook + // allocator: default allocator + + struct case_SHN + { + typedef AP1 set_type_of_relation; + typedef std::allocator allocator; + typedef BOOST_DEDUCED_TYPENAME AP2::value_type additional_info; + }; + + // (7) manage_additional_parameters< + // DataToHook,Allocator,not_specified> + // + // set_type_of_relation: SetTypeOfRelation + // info_hook: InfoToHook + // allocator: default allocator + + struct case_HAN + { + typedef left_based set_type_of_relation; + typedef AP2 allocator; + typedef BOOST_DEDUCED_TYPENAME AP1::value_type additional_info; + }; + + // (8) manage_additional_parameters< + // SetTypeOfRelation,DataToHook,Allocator> + // + // set_type_of_relation: SetTypeOfRelation + // info_hook: InfoToHook + // allocator: Allocator + + struct case_SHA + { + typedef AP1 set_type_of_relation; + typedef AP2 allocator; + typedef BOOST_DEDUCED_TYPENAME AP2::value_type additional_info; + }; + + // Some annidated mpl::if_ and we are done! + + typedef BOOST_DEDUCED_TYPENAME mpl::if_ + < + ::boost::mpl::is_na, + case_NNN, // (1) + BOOST_DEDUCED_TYPENAME mpl::if_ + < + ::boost::mpl::is_na, + BOOST_DEDUCED_TYPENAME mpl::if_ + < + is_set_type_of_relation, + case_SNN, // (3) + BOOST_DEDUCED_TYPENAME mpl::if_ + < + is_with_info, + case_HNN, // (5) + case_ANN // (2) + + >::type + + >::type, + BOOST_DEDUCED_TYPENAME mpl::if_ + < + ::boost::mpl::is_na, + BOOST_DEDUCED_TYPENAME mpl::if_ + < + is_with_info, + case_HAN, // (7) + BOOST_DEDUCED_TYPENAME mpl::if_ + < + is_with_info, + case_SHN, // (6) + case_SAN // (4) + + >::type + + >::type, + + case_SHA // (8) + + >::type + + >::type + + >::type type; + +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +} // namespace detail +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_DETAIL_MANAGE_ADDITIONAL_PARAMETERS_HPP + diff --git a/win32/include/boost/bimap/detail/manage_bimap_key.hpp b/win32/include/boost/bimap/detail/manage_bimap_key.hpp new file mode 100755 index 000000000..95bcdd71e --- /dev/null +++ b/win32/include/boost/bimap/detail/manage_bimap_key.hpp @@ -0,0 +1,84 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/manage_bimap_key.hpp +/// \brief Utility class to manage the set types of a bimap. + +#ifndef BOOST_BIMAP_DETAIL_MANAGE_BIMAP_KEY_HPP +#define BOOST_BIMAP_DETAIL_MANAGE_BIMAP_KEY_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +#include + +#include + +namespace boost { +namespace bimaps { +namespace detail { + +/** \struct boost::bimaps::detail::manage_bimap_key +\brief Metafunction to manage the set types of a bimap. + +\code +template< class Type > +struct manage_bimap_key +{ + typedef -SetType- type; +} +\endcode + +See also bimap, bimap_core. + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class Type > +struct manage_bimap_key +{ + +typedef BOOST_DEDUCED_TYPENAME + + mpl::eval_if< BOOST_DEDUCED_TYPENAME is_set_type_of< Type >::type, + // { + mpl::identity< Type >, + // } + // else + // { + // Default it to a set + mpl::identity< set_of< Type > > + // } + + >::type set_type; + + // Returns set_type and evaluate the concept_checked_type + + typedef BOOST_DEDUCED_TYPENAME mpl::if_c< true, set_type, + BOOST_DEDUCED_TYPENAME set_type::lazy_concept_checked::type + >::type type; +}; + + + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +} // namespace detail +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_DETAIL_MANAGE_BIMAP_KEY_HPP + + diff --git a/win32/include/boost/bimap/detail/map_view_base.hpp b/win32/include/boost/bimap/detail/map_view_base.hpp new file mode 100755 index 000000000..ee709317d --- /dev/null +++ b/win32/include/boost/bimap/detail/map_view_base.hpp @@ -0,0 +1,552 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/map_view_base.hpp +/// \brief Helper base for the construction of the bimap views types. + +#ifndef BOOST_BIMAP_DETAIL_MAP_VIEW_BASE_HPP +#define BOOST_BIMAP_DETAIL_MAP_VIEW_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace bimaps { + +namespace detail { + + +// The next macro can be converted in a metafunctor to gain code robustness. +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR( \ + CONTAINER_ADAPTOR, TAG,BIMAP, OTHER_ITER, CONST_OTHER_ITER \ +) \ +::boost::bimaps::container_adaptor::CONTAINER_ADAPTOR \ +< \ + BOOST_DEDUCED_TYPENAME BIMAP::core_type:: \ + BOOST_NESTED_TEMPLATE index::type, \ + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ + iterator_type_by::type, \ + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ + const_iterator_type_by::type, \ + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ + OTHER_ITER::type, \ + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ + CONST_OTHER_ITER::type, \ + ::boost::bimaps::container_adaptor::support::iterator_facade_to_base \ + < \ + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ + iterator_type_by::type, \ + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: \ + const_iterator_type_by::type \ + \ + >, \ + ::boost::mpl::na, \ + ::boost::mpl::na, \ + ::boost::bimaps::relation::detail:: \ + pair_to_relation_functor, \ + ::boost::bimaps::relation::support:: \ + get_pair_functor \ +> +/*===========================================================================*/ + + +#if defined(BOOST_MSVC) +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(TYPE,TAG,BIMAP) \ + typedef ::boost::bimaps::detail::map_view_base< \ + TYPE,TAG,BIMAP > friend_map_view_base; \ + friend class friend_map_view_base; +/*===========================================================================*/ +#else +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(TYPE,TAG,BIMAP) \ + friend class ::boost::bimaps::detail::map_view_base< \ + TYPE,TAG,BIMAP >; +/*===========================================================================*/ +#endif + + +/// \brief Common base for map views. + +template< class Derived, class Tag, class BimapType> +class map_view_base +{ + typedef ::boost::bimaps::container_adaptor::support:: + iterator_facade_to_base< + + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + iterator_type_by::type, + + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + const_iterator_type_by::type + + > iterator_to_base_; + + typedef ::boost::bimaps::relation::detail:: + pair_to_relation_functor value_to_base_; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + key_type_by::type key_type_; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + data_type_by::type data_type_; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + pair_type_by::type value_type_; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + iterator_type_by::type iterator_; + + public: + + bool replace(iterator_ position, const value_type_ & x) + { + return derived().base().replace( + derived().template functor()(position), + derived().template functor()(x) + ); + } + + template< class CompatibleKey > + bool replace_key(iterator_ position, const CompatibleKey & k) + { + return derived().base().replace( + derived().template functor()(position), + derived().template functor()( + value_type_(k,position->second) + ) + ); + } + + template< class CompatibleData > + bool replace_data(iterator_ position, const CompatibleData & d) + { + return derived().base().replace( + derived().template functor()(position), + derived().template functor()( + value_type_(position->first,d) + ) + ); + } + + /* This function may be provided in the future + + template< class Modifier > + bool modify(iterator_ position, Modifier mod) + { + return derived().base().modify( + + derived().template functor()(position), + + ::boost::bimaps::detail::relation_modifier_adaptor + < + Modifier, + BOOST_DEDUCED_TYPENAME BimapType::relation, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + data_extractor + < + Tag, BOOST_DEDUCED_TYPENAME BimapType::relation + + >::type, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + data_extractor + < + BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + opossite_tag::type, + BOOST_DEDUCED_TYPENAME BimapType::relation + + >::type + + >(mod) + ); + } + */ + + template< class Modifier > + bool modify_key(iterator_ position, Modifier mod) + { + return derived().base().modify_key( + derived().template functor()(position), mod + ); + } + + template< class Modifier > + bool modify_data(iterator_ position, Modifier mod) + { + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + data_extractor + < + BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + opossite_tag::type, + BOOST_DEDUCED_TYPENAME BimapType::relation + + >::type data_extractor_; + + return derived().base().modify( + + derived().template functor()(position), + + // this may be replaced later by + // ::boost::bind( mod, ::boost::bind(data_extractor_(),_1) ) + + ::boost::bimaps::detail::unary_modifier_adaptor + < + Modifier, + BOOST_DEDUCED_TYPENAME BimapType::relation, + data_extractor_ + + >(mod) + ); + } + + protected: + + typedef map_view_base map_view_base_; + + private: + + // Curiously Recurring Template interface. + + Derived& derived() + { + return *static_cast(this); + } + + Derived const& derived() const + { + return *static_cast(this); + } +}; + + + + +template< class Derived, class Tag, class BimapType> +class mutable_data_unique_map_view_access +{ + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + data_type_by::type data_type_; + + public: + + template< class CompatibleKey > + data_type_ & at(const CompatibleKey& k) + { + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + iterator_type_by::type iterator; + + iterator iter = derived().find(k); + if( iter == derived().end() ) + { + ::boost::throw_exception( + std::out_of_range("bimap<>: invalid key") + ); + } + return iter->second; + } + + template< class CompatibleKey > + const data_type_ & at(const CompatibleKey& k) const + { + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + const_iterator_type_by::type const_iterator; + + const_iterator iter = derived().find(k); + if( iter == derived().end() ) + { + ::boost::throw_exception( + std::out_of_range("bimap<>: invalid key") + ); + } + return iter->second; + } + + template< class CompatibleKey > + data_type_ & operator[](const CompatibleKey& k) + { + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + iterator_type_by::type iterator; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + value_type_by::type value_type; + + iterator iter = derived().find(k); + if( iter == derived().end() ) + { + iter = derived().insert( value_type(k,data_type_()) ).first; + } + return iter->second; + } + + protected: + + typedef mutable_data_unique_map_view_access + mutable_data_unique_map_view_access_; + + private: + + // Curiously Recurring Template interface. + + Derived& derived() + { + return *static_cast(this); + } + + Derived const& derived() const + { + return *static_cast(this); + } +}; + + +template< class Derived, class Tag, class BimapType> +class non_mutable_data_unique_map_view_access +{ + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + data_type_by::type data_type_; + + public: + + template< class CompatibleKey > + const data_type_ & at(const CompatibleKey& k) const + { + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + const_iterator_type_by::type const_iterator; + + const_iterator iter = derived().find(k); + if( iter == derived().end() ) + { + ::boost::throw_exception( + std::out_of_range("bimap<>: invalid key") + ); + } + return iter->second; + } + + template< class CompatibleKey > + data_type_ & operator[](const CompatibleKey& k) + { + BOOST_BIMAP_STATIC_ERROR( OPERATOR_BRACKET_IS_NOT_SUPPORTED, (Derived)); + } + + protected: + + typedef non_mutable_data_unique_map_view_access + non_mutable_data_unique_map_view_access_; + + private: + + // Curiously Recurring Template interface. + + Derived& derived() + { + return *static_cast(this); + } + + Derived const& derived() const + { + return *static_cast(this); + } +}; + + +template< class Derived, class Tag, class BimapType> +struct unique_map_view_access +{ + private: + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + value_type_by::type value_type; + + public: + typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_ + < + typename ::boost::is_const< + BOOST_DEDUCED_TYPENAME value_type::second_type >::type, + + non_mutable_data_unique_map_view_access, + mutable_data_unique_map_view_access + + >::type type; +}; + +// Map views specialize the following structs to provide to the bimap class +// the extra side typedefs (i.e. left_local_iterator for unordered_maps, +// right_range_type for maps) + +template< class MapView > +struct left_map_view_extra_typedefs {}; + +template< class MapView > +struct right_map_view_extra_typedefs {}; + +} // namespace detail + +// This function is already part of Boost.Lambda. +// They may be moved to Boost.Utility. + +template inline const T& make_const(const T& t) { return t; } + +} // namespace bimaps +} // namespace boost + + +// The following macros avoids code duplication in map views +// Maybe this can be changed in the future using a scheme similar to +// the one used with map_view_base. + +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_RANGE_IMPLEMENTATION(BASE) \ + \ +typedef std::pair< \ + BOOST_DEDUCED_TYPENAME base_::iterator, \ + BOOST_DEDUCED_TYPENAME base_::iterator> range_type; \ + \ +typedef std::pair< \ + BOOST_DEDUCED_TYPENAME base_::const_iterator, \ + BOOST_DEDUCED_TYPENAME base_::const_iterator> const_range_type; \ + \ + \ +template< class LowerBounder, class UpperBounder> \ +range_type range(LowerBounder lower,UpperBounder upper) \ +{ \ + std::pair< \ + \ + BOOST_DEDUCED_TYPENAME BASE::base_type::iterator, \ + BOOST_DEDUCED_TYPENAME BASE::base_type::iterator \ + \ + > r( this->base().range(lower,upper) ); \ + \ + return range_type( \ + this->template functor< \ + BOOST_DEDUCED_TYPENAME BASE::iterator_from_base \ + >() ( r.first ), \ + this->template functor< \ + BOOST_DEDUCED_TYPENAME BASE::iterator_from_base \ + >() ( r.second ) \ + ); \ +} \ + \ +template< class LowerBounder, class UpperBounder> \ +const_range_type range(LowerBounder lower,UpperBounder upper) const \ +{ \ + std::pair< \ + \ + BOOST_DEDUCED_TYPENAME BASE::base_type::const_iterator, \ + BOOST_DEDUCED_TYPENAME BASE::base_type::const_iterator \ + \ + > r( this->base().range(lower,upper) ); \ + \ + return const_range_type( \ + this->template functor< \ + BOOST_DEDUCED_TYPENAME BASE::iterator_from_base \ + >() ( r.first ), \ + this->template functor< \ + BOOST_DEDUCED_TYPENAME BASE::iterator_from_base \ + >() ( r.second ) \ + ); \ +} +/*===========================================================================*/ + + +/*===========================================================================*/ +#define BOOST_BIMAP_VIEW_ASSIGN_IMPLEMENTATION(BASE) \ + \ +template< class InputIterator > \ +void assign(InputIterator first,InputIterator last) \ +{ \ + this->clear(); \ + this->insert(this->end(),first,last); \ +} \ + \ +void assign(BOOST_DEDUCED_TYPENAME BASE::size_type n, \ + const BOOST_DEDUCED_TYPENAME BASE::value_type& v) \ +{ \ + this->clear(); \ + for(BOOST_DEDUCED_TYPENAME BASE::size_type i = 0 ; i < n ; ++n) \ + { \ + this->push_back(v); \ + } \ +} +/*===========================================================================*/ + + +/*===========================================================================*/ +#define BOOST_BIMAP_VIEW_FRONT_BACK_IMPLEMENTATION(BASE) \ + \ +BOOST_DEDUCED_TYPENAME BASE::reference front() \ +{ \ + return this->template functor< \ + BOOST_DEDUCED_TYPENAME base_::value_from_base>() \ + ( \ + const_cast \ + < \ + BOOST_DEDUCED_TYPENAME BASE::base_type::value_type & \ + \ + > ( this->base().front() ) \ + ); \ +} \ + \ +BOOST_DEDUCED_TYPENAME BASE::reference back() \ +{ \ + return this->template functor< \ + BOOST_DEDUCED_TYPENAME base_::value_from_base>() \ + ( \ + const_cast \ + < \ + BOOST_DEDUCED_TYPENAME BASE::base_type::value_type & \ + \ + >( this->base().back() ) \ + ); \ +} \ + \ +BOOST_DEDUCED_TYPENAME BASE::const_reference front() const \ +{ \ + return this->template functor< \ + BOOST_DEDUCED_TYPENAME BASE::value_from_base>() \ + ( \ + this->base().front() \ + ); \ +} \ + \ +BOOST_DEDUCED_TYPENAME BASE::const_reference back() const \ +{ \ + return this->template functor< \ + BOOST_DEDUCED_TYPENAME BASE::value_from_base>() \ + ( \ + this->base().back() \ + ); \ +} +/*===========================================================================*/ + + +#endif // BOOST_BIMAP_DETAIL_MAP_VIEW_BASE_HPP diff --git a/win32/include/boost/bimap/detail/map_view_iterator.hpp b/win32/include/boost/bimap/detail/map_view_iterator.hpp new file mode 100755 index 000000000..10b62ddf1 --- /dev/null +++ b/win32/include/boost/bimap/detail/map_view_iterator.hpp @@ -0,0 +1,200 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/map_view_iterator.hpp +/// \brief Iterator adaptors from multi-index to bimap. + +#ifndef BOOST_BIMAP_DETAIL_MAP_VIEW_ITERATOR_HPP +#define BOOST_BIMAP_DETAIL_MAP_VIEW_ITERATOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +// Boost +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace detail { + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class Tag, class Relation, class CoreIterator > struct map_view_iterator; + +template< class Tag, class Relation, class CoreIterator > +struct map_view_iterator_base +{ + typedef iterator_adaptor + < + map_view_iterator< Tag, Relation, CoreIterator >, + CoreIterator, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + pair_type_by::type + + > type; +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +/** \brief Map View Iterator adaptor from multi index to bimap. + +This is class is based on transform iterator from Boost.Iterator that is +modified to allow serialization. It has been specialized for this +library, and EBO optimization was applied to the functor. + + **/ + +template< class Tag, class Relation, class CoreIterator > +struct map_view_iterator : public map_view_iterator_base::type +{ + typedef BOOST_DEDUCED_TYPENAME + map_view_iterator_base::type base_; + + public: + + map_view_iterator() {} + + map_view_iterator(CoreIterator const& iter) + : base_(iter) {} + + map_view_iterator(map_view_iterator const & iter) + : base_(iter.base()) {} + + BOOST_DEDUCED_TYPENAME base_::reference dereference() const + { + return ::boost::bimaps::relation::support::pair_by( + *const_cast( + &(*this->base()) + ) + ); + } + + private: + + friend class iterator_core_access; + + #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION + + // Serialization support + + BOOST_SERIALIZATION_SPLIT_MEMBER() + + friend class ::boost::serialization::access; + + template< class Archive > + void save(Archive & ar, const unsigned int version) const + { + ar << ::boost::serialization::make_nvp("mi_iterator",this->base()); + } + + template< class Archive > + void load(Archive & ar, const unsigned int version) + { + CoreIterator iter; + ar >> ::boost::serialization::make_nvp("mi_iterator",iter); + this->base_reference() = iter; + } + + #endif // BOOST_BIMAP_DISABLE_SERIALIZATION +}; + + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class Tag, class Relation, class CoreIterator > struct const_map_view_iterator; + +template< class Tag, class Relation, class CoreIterator > +struct const_map_view_iterator_base +{ + typedef iterator_adaptor + < + const_map_view_iterator< Tag, Relation, CoreIterator >, + CoreIterator, + const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + pair_type_by::type + + > type; +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + + +/** \brief Const Map View Iterator adaptor from multi index to bimap. + +See also map_view_iterator. + **/ + +template< class Tag, class Relation, class CoreIterator > +struct const_map_view_iterator : + + public const_map_view_iterator_base::type +{ + typedef BOOST_DEDUCED_TYPENAME + const_map_view_iterator_base::type base_; + + public: + + const_map_view_iterator() {} + + const_map_view_iterator(CoreIterator const& iter) + : base_(iter) {} + + const_map_view_iterator(const_map_view_iterator const & iter) + : base_(iter.base()) {} + + const_map_view_iterator(map_view_iterator i) + : base_(i.base()) {} + + BOOST_DEDUCED_TYPENAME base_::reference dereference() const + { + return ::boost::bimaps::relation::support::pair_by(*this->base()); + } + + private: + + friend class iterator_core_access; + + #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION + + // Serialization support + + BOOST_SERIALIZATION_SPLIT_MEMBER() + + friend class ::boost::serialization::access; + + template< class Archive > + void save(Archive & ar, const unsigned int version) const + { + ar << ::boost::serialization::make_nvp("mi_iterator",this->base()); + } + + template< class Archive > + void load(Archive & ar, const unsigned int version) + { + CoreIterator iter; + ar >> ::boost::serialization::make_nvp("mi_iterator",iter); + this->base_reference() = iter; + } + + #endif // BOOST_BIMAP_DISABLE_SERIALIZATION +}; + + +} // namespace detail +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DETAIL_MAP_VIEW_ITERATOR_HPP + + diff --git a/win32/include/boost/bimap/detail/modifier_adaptor.hpp b/win32/include/boost/bimap/detail/modifier_adaptor.hpp new file mode 100755 index 000000000..43f2f4b04 --- /dev/null +++ b/win32/include/boost/bimap/detail/modifier_adaptor.hpp @@ -0,0 +1,89 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/modifier_adaptor.hpp +/// \brief A binary to unary functor relation modifier adaptor. + +#ifndef BOOST_BIMAP_DETAIL_MODIFIER_ADAPTOR_HPP +#define BOOST_BIMAP_DETAIL_MODIFIER_ADAPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +namespace boost { +namespace bimaps { +namespace detail { + +/// \brief A binary to unary functor relation modifier adaptor. + +template +< + class Modifier, + class NewArgument, + class FirstExtractor, + class SecondExtractor +> +struct relation_modifier_adaptor : + public std::unary_function, + Modifier, + FirstExtractor, + SecondExtractor +{ + relation_modifier_adaptor( const Modifier & m ) : Modifier(m) {} + relation_modifier_adaptor( const Modifier & m, + const FirstExtractor & fe, + const SecondExtractor & se ) : + Modifier(m), FirstExtractor(fe), SecondExtractor(se) {} + + void operator()( NewArgument & x ) const + { + Modifier::operator()( + FirstExtractor ::operator()( x ), + SecondExtractor::operator()( x ) + ); + } +}; + +/// \brief A simple unary modifier adaptor. +// This modifier is equivalent to bind( Modifier, bind( Extractor, _1 ) ) +// It may be a good idea to start using Boost.Bind instead of it. + +template +< + class Modifier, + class NewArgument, + class Extractor +> +struct unary_modifier_adaptor : + public std::unary_function, + Modifier, + Extractor +{ + unary_modifier_adaptor( const Modifier & m ) : Modifier(m) {} + unary_modifier_adaptor( const Modifier & m, + const Extractor & fe) : + Modifier(m), Extractor(fe) {} + + void operator()( NewArgument & x ) const + { + Modifier::operator()( Extractor::operator()( x ) ); + } +}; + + +} // namespace detail +} // namespace bimap +} // namespace boost + + +#endif // BOOST_BIMAP_DETAIL_MODIFIER_ADAPTOR_HPP diff --git a/win32/include/boost/bimap/detail/non_unique_views_helper.hpp b/win32/include/boost/bimap/detail/non_unique_views_helper.hpp new file mode 100755 index 000000000..6ea05c07f --- /dev/null +++ b/win32/include/boost/bimap/detail/non_unique_views_helper.hpp @@ -0,0 +1,71 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/non_unique_views_helper.hpp +/// \brief Details for non unique views + +#ifndef BOOST_BIMAP_DETAIL_NON_UNIQUE_VIEWS_HELPER_HPP +#define BOOST_BIMAP_DETAIL_NON_UNIQUE_VIEWS_HELPER_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +/*===========================================================================*/ +#define BOOST_BIMAP_NON_UNIQUE_VIEW_INSERT_FUNCTIONS \ + \ +template \ +void insert(InputIterator iterBegin, InputIterator iterEnd) \ +{ \ + for( ; iterBegin != iterEnd ; ++iterBegin ) \ + { \ + this->base().insert( \ + this->template functor< \ + BOOST_DEDUCED_TYPENAME base_::value_to_base>()( \ + BOOST_DEDUCED_TYPENAME base_::value_type(*iterBegin)) ); \ + } \ +} \ + \ +std::pair insert( \ + BOOST_DEDUCED_TYPENAME ::boost::call_traits< \ + BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x) \ +{ \ + typedef BOOST_DEDUCED_TYPENAME base_::base_type::iterator base_iterator; \ + \ + std::pair< base_iterator, bool > r( \ + this->base().insert( \ + this->template functor< \ + BOOST_DEDUCED_TYPENAME base_::value_to_base>()(x) ) \ + ); \ + \ + return std::pair( \ + this->template functor< \ + BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()(r.first), \ + r.second \ + ); \ +} \ + \ +BOOST_DEDUCED_TYPENAME base_::iterator insert( \ + BOOST_DEDUCED_TYPENAME base_::iterator pos, \ + BOOST_DEDUCED_TYPENAME ::boost::call_traits< \ + BOOST_DEDUCED_TYPENAME base_::value_type >::param_type x) \ +{ \ + return this->template functor< \ + BOOST_DEDUCED_TYPENAME base_::iterator_from_base>()( \ + this->base().insert( \ + this->template functor< \ + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(pos), \ + this->template functor< \ + BOOST_DEDUCED_TYPENAME base_::value_to_base>()(x)) \ + ); \ +} +/*===========================================================================*/ + +#endif // BOOST_BIMAP_DETAIL_NON_UNIQUE_VIEWS_HELPER_HPP diff --git a/win32/include/boost/bimap/detail/set_view_base.hpp b/win32/include/boost/bimap/detail/set_view_base.hpp new file mode 100755 index 000000000..3db43f738 --- /dev/null +++ b/win32/include/boost/bimap/detail/set_view_base.hpp @@ -0,0 +1,330 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/set_view_base.hpp +/// \brief Helper base for the construction of the bimap views types. + +#ifndef BOOST_BIMAP_DETAIL_SET_VIEW_BASE_HPP +#define BOOST_BIMAP_DETAIL_SET_VIEW_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace detail { + +template< class Key, class Value, class KeyToBase > +class set_view_key_to_base +{ + public: + const Key operator()( const Value & v ) const + { + return keyToBase( v ); + } + private: + KeyToBase keyToBase; +}; + +template< class MutantRelationStorage, class KeyToBase > +class set_view_key_to_base +{ + typedef BOOST_DEDUCED_TYPENAME MutantRelationStorage::non_mutable_storage non_mutable_storage; + public: + const MutantRelationStorage & operator()( const non_mutable_storage & k ) const + { + return ::boost::bimaps::relation::detail::mutate(k); + } + const MutantRelationStorage & operator()( const MutantRelationStorage & k ) const + { + return k; + } +}; + + +// The next macro can be converted in a metafunctor to gain code robustness. +/*===========================================================================*/ +#define BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR( \ + CONTAINER_ADAPTOR, CORE_INDEX, OTHER_ITER, CONST_OTHER_ITER \ +) \ +::boost::bimaps::container_adaptor::CONTAINER_ADAPTOR \ +< \ + CORE_INDEX, \ + ::boost::bimaps::detail:: \ + set_view_iterator< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::iterator >, \ + ::boost::bimaps::detail:: \ + const_set_view_iterator< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::const_iterator >, \ + ::boost::bimaps::detail:: \ + set_view_iterator< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::OTHER_ITER >, \ + ::boost::bimaps::detail:: \ + const_set_view_iterator< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::CONST_OTHER_ITER >, \ + ::boost::bimaps::container_adaptor::support::iterator_facade_to_base \ + < \ + ::boost::bimaps::detail:: set_view_iterator< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::iterator>, \ + ::boost::bimaps::detail::const_set_view_iterator< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::const_iterator> \ + \ + >, \ + ::boost::mpl::na, \ + ::boost::mpl::na, \ + ::boost::bimaps::relation::detail:: \ + get_mutable_relation_functor< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::value_type >, \ + ::boost::bimaps::relation::support:: \ + get_above_view_functor< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::value_type >, \ + ::boost::bimaps::detail::set_view_key_to_base< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::key_type, \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::value_type, \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::key_from_value \ + > \ +> +/*===========================================================================*/ + + +/*===========================================================================*/ +#define BOOST_BIMAP_SEQUENCED_SET_VIEW_CONTAINER_ADAPTOR( \ + CONTAINER_ADAPTOR, CORE_INDEX, OTHER_ITER, CONST_OTHER_ITER \ +) \ +::boost::bimaps::container_adaptor::CONTAINER_ADAPTOR \ +< \ + CORE_INDEX, \ + ::boost::bimaps::detail:: \ + set_view_iterator< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::iterator >, \ + ::boost::bimaps::detail:: \ + const_set_view_iterator< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::const_iterator >, \ + ::boost::bimaps::detail:: \ + set_view_iterator< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::OTHER_ITER >, \ + ::boost::bimaps::detail:: \ + const_set_view_iterator< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::CONST_OTHER_ITER >, \ + ::boost::bimaps::container_adaptor::support::iterator_facade_to_base \ + < \ + ::boost::bimaps::detail:: set_view_iterator< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::iterator>, \ + ::boost::bimaps::detail::const_set_view_iterator< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::const_iterator> \ + \ + >, \ + ::boost::mpl::na, \ + ::boost::mpl::na, \ + ::boost::bimaps::relation::detail:: \ + get_mutable_relation_functor< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::value_type >, \ + ::boost::bimaps::relation::support:: \ + get_above_view_functor< \ + BOOST_DEDUCED_TYPENAME CORE_INDEX::value_type > \ +> +/*===========================================================================*/ + + +#if defined(BOOST_MSVC) +/*===========================================================================*/ +#define BOOST_BIMAP_SET_VIEW_BASE_FRIEND(TYPE,INDEX_TYPE) \ + typedef ::boost::bimaps::detail::set_view_base< \ + TYPE< INDEX_TYPE >, INDEX_TYPE > template_class_friend; \ + friend class template_class_friend; +/*===========================================================================*/ +#else +/*===========================================================================*/ +#define BOOST_BIMAP_SET_VIEW_BASE_FRIEND(TYPE,INDEX_TYPE) \ + friend class ::boost::bimaps::detail::set_view_base< \ + TYPE< INDEX_TYPE >, INDEX_TYPE >; +/*===========================================================================*/ +#endif + + +/// \brief Common base for set views. + +template< class Derived, class Index > +class set_view_base +{ + typedef ::boost::bimaps::container_adaptor::support:: + iterator_facade_to_base + < + ::boost::bimaps::detail:: + set_view_iterator, + ::boost::bimaps::detail:: + const_set_view_iterator + + > iterator_to_base_; + + typedef BOOST_DEDUCED_TYPENAME Index::value_type::left_value_type left_type_; + + typedef BOOST_DEDUCED_TYPENAME Index::value_type::right_value_type right_type_; + + typedef BOOST_DEDUCED_TYPENAME Index::value_type value_type_; + + typedef ::boost::bimaps::detail:: + set_view_iterator iterator_; + + public: + + bool replace(iterator_ position, + const value_type_ & x) + { + return derived().base().replace( + derived().template functor()(position),x + ); + } + + template< class CompatibleLeftType > + bool replace_left(iterator_ position, + const CompatibleLeftType & l) + { + return derived().base().replace( + derived().template functor()(position), + value_type_(l,position->right) + ); + } + + template< class CompatibleRightType > + bool replace_right(iterator_ position, + const CompatibleRightType & r) + { + return derived().base().replace( + derived().template functor()(position), + value_type_(position->left,r) + ); + } + + /* This function may be provided in the future + + template< class Modifier > + bool modify(iterator_ position, + Modifier mod) + { + return derived().base().modify( + + derived().template functor()(position), + + ::boost::bimaps::detail::relation_modifier_adaptor + < + Modifier, + BOOST_DEDUCED_TYPENAME Index::value_type, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + data_extractor + < + ::boost::bimaps::relation::member_at::left, + BOOST_DEDUCED_TYPENAME Index::value_type + + >::type, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + data_extractor + < + ::boost::bimaps::relation::member_at::right, + BOOST_DEDUCED_TYPENAME Index::value_type + + >::type + + >(mod) + ); + } + */ + /* + template< class Modifier > + bool modify_left(iterator_ position, Modifier mod) + { + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + data_extractor + < + BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::member_at::right, + BOOST_DEDUCED_TYPENAME Index::value_type + + >::type left_data_extractor_; + + return derived().base().modify( + + derived().template functor()(position), + + // this may be replaced later by + // ::boost::bind( mod, ::boost::bind(data_extractor_(),_1) ) + + ::boost::bimaps::detail::unary_modifier_adaptor + < + Modifier, + BOOST_DEDUCED_TYPENAME Index::value_type, + left_data_extractor_ + + >(mod) + ); + } + + template< class Modifier > + bool modify_right(iterator_ position, Modifier mod) + { + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + data_extractor + < + BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::member_at::right, + BOOST_DEDUCED_TYPENAME Index::value_type + + >::type right_data_extractor_; + + return derived().base().modify( + + derived().template functor()(position), + + // this may be replaced later by + // ::boost::bind( mod, ::boost::bind(data_extractor_(),_1) ) + + ::boost::bimaps::detail::unary_modifier_adaptor + < + Modifier, + BOOST_DEDUCED_TYPENAME Index::value_type, + right_data_extractor_ + + >(mod) + ); + } + */ + protected: + + typedef set_view_base set_view_base_; + + private: + + // Curiously Recurring Template interface. + + Derived& derived() + { + return *static_cast(this); + } + + Derived const& derived() const + { + return *static_cast(this); + } +}; + + + +} // namespace detail +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DETAIL_SET_VIEW_BASE_HPP diff --git a/win32/include/boost/bimap/detail/set_view_iterator.hpp b/win32/include/boost/bimap/detail/set_view_iterator.hpp new file mode 100755 index 000000000..011e6cef0 --- /dev/null +++ b/win32/include/boost/bimap/detail/set_view_iterator.hpp @@ -0,0 +1,193 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/set_view_iterator.hpp +/// \brief Iterator adaptors from multi-index to bimap. + +#ifndef BOOST_BIMAP_DETAIL_SET_VIEW_ITERATOR_HPP +#define BOOST_BIMAP_DETAIL_SET_VIEW_ITERATOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +// Boost +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace detail { + + +/** \brief Set View Iterator adaptor from multi index to bimap. + +This is class is based on transform iterator from Boost.Iterator that is +modified to allow serialization. It has been specialized for this +library, and EBO optimization was applied to the functor. + + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class CoreIterator > struct set_view_iterator; + +template< class CoreIterator > +struct set_view_iterator_base +{ + typedef iterator_adaptor + < + set_view_iterator< CoreIterator >, + CoreIterator, + BOOST_DEDUCED_TYPENAME CoreIterator::value_type::above_view + + > type; +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class CoreIterator > +struct set_view_iterator : public set_view_iterator_base::type +{ + typedef BOOST_DEDUCED_TYPENAME set_view_iterator_base::type base_; + + public: + + set_view_iterator() {} + + set_view_iterator(CoreIterator const& iter) + : base_(iter) {} + + set_view_iterator(set_view_iterator const & iter) + : base_(iter.base()) {} + + typename base_::reference dereference() const + { + return const_cast< + BOOST_DEDUCED_TYPENAME base_::base_type::value_type*>( + &(*this->base()) + )->get_view(); + } + + private: + + friend class iterator_core_access; + + #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION + + // Serialization support + + BOOST_SERIALIZATION_SPLIT_MEMBER() + + friend class ::boost::serialization::access; + + template< class Archive > + void save(Archive & ar, const unsigned int version) const + { + ar << ::boost::serialization::make_nvp("mi_iterator",this->base()); + } + + template< class Archive > + void load(Archive & ar, const unsigned int version) + { + CoreIterator iter; + ar >> ::boost::serialization::make_nvp("mi_iterator",iter); + this->base_reference() = iter; + } + + #endif // BOOST_BIMAP_DISABLE_SERIALIZATION +}; + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class CoreIterator > struct const_set_view_iterator; + +template< class CoreIterator > +struct const_set_view_iterator_base +{ + typedef iterator_adaptor + < + const_set_view_iterator< CoreIterator >, + CoreIterator, + const BOOST_DEDUCED_TYPENAME CoreIterator::value_type::above_view + + > type; +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + + +/** \brief Const Set View Iterator adaptor from multi index to bimap. + +See also set_view_iterator. + **/ + +template< class CoreIterator > +struct const_set_view_iterator : public const_set_view_iterator_base::type +{ + typedef BOOST_DEDUCED_TYPENAME const_set_view_iterator_base::type base_; + + public: + + const_set_view_iterator() {} + + const_set_view_iterator(CoreIterator const& iter) + : base_(iter) {} + + const_set_view_iterator(const_set_view_iterator const & iter) + : base_(iter.base()) {} + + const_set_view_iterator(set_view_iterator i) + : base_(i.base()) {} + + BOOST_DEDUCED_TYPENAME base_::reference dereference() const + { + return this->base()->get_view(); + } + + private: + + friend class iterator_core_access; + + #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION + + // Serialization support + + BOOST_SERIALIZATION_SPLIT_MEMBER() + + friend class ::boost::serialization::access; + + template< class Archive > + void save(Archive & ar, const unsigned int version) const + { + ar << ::boost::serialization::make_nvp("mi_iterator",this->base()); + } + + template< class Archive > + void load(Archive & ar, const unsigned int version) + { + CoreIterator iter; + ar >> ::boost::serialization::make_nvp("mi_iterator",iter); + this->base_reference() = iter; + } + + #endif // BOOST_BIMAP_DISABLE_SERIALIZATION +}; + + +} // namespace detail +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DETAIL_MAP_VIEW_ITERATOR_HPP + + diff --git a/win32/include/boost/bimap/detail/test/check_metadata.hpp b/win32/include/boost/bimap/detail/test/check_metadata.hpp new file mode 100755 index 000000000..13ffa7eac --- /dev/null +++ b/win32/include/boost/bimap/detail/test/check_metadata.hpp @@ -0,0 +1,113 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_BIMAP_DETAIL_CHECK_METADATA_HPP +#define BOOST_BIMAP_DETAIL_CHECK_METADATA_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include + + +// Easier way to call BOOST_MPL_ASSERT_MSG in class scope +/*===========================================================================*/ +#define BOOST_BIMAP_MPL_ASSERT_MSG_ACS(p1,p2,p3) \ + \ + struct p2 {}; \ + BOOST_MPL_ASSERT_MSG(p1,p2,p3); \ +/*===========================================================================*/ + + +// Build a descriptive name. +/*===========================================================================*/ +#define BOOST_BIMAP_WRONG_METADATA_MESSAGE( \ + \ + P_CLASS, \ + P_NAME, \ + P_CORRECT_TYPE \ + \ + ) \ + \ + BOOST_PP_CAT \ + ( \ + WRONG_METADATA__, \ + BOOST_PP_CAT \ + ( \ + P_CLASS, \ + BOOST_PP_CAT \ + ( \ + __AT__, \ + BOOST_PP_CAT \ + ( \ + P_NAME, \ + BOOST_PP_CAT \ + ( \ + __IS_DIFERENT_TO__, \ + P_CORRECT_TYPE \ + ) \ + ) \ + ) \ + ) \ + ) +/*===========================================================================*/ + + +// Check if the metadata have the correct type, and if not inform +// it with a useful compile time message. +/*===========================================================================*/ +#define BOOST_BIMAP_CHECK_METADATA( \ + \ + P_CLASS, \ + P_NAME, \ + P_CORRECT_TYPE \ + \ + ) \ + \ + BOOST_BIMAP_MPL_ASSERT_MSG_ACS \ + ( \ + ( \ + ::boost::is_same \ + < \ + P_CLASS::P_NAME, \ + P_CORRECT_TYPE \ + \ + >::value \ + ), \ + BOOST_BIMAP_WRONG_METADATA_MESSAGE \ + ( \ + P_CLASS, \ + P_NAME, \ + P_CORRECT_TYPE \ + ), \ + (P_CLASS::P_NAME,P_CORRECT_TYPE) \ + ) +/*===========================================================================*/ + + +// Just for autodocumment the test code +/*===========================================================================*/ +#define BOOST_BIMAP_TEST_STATIC_FUNCTION(NAME) \ + namespace NAME +/*===========================================================================*/ + + +// Just for autodocument the test code +/*===========================================================================*/ +#define BOOST_BIMAP_CALL_TEST_STATIC_FUNCTION(NAME) +/*===========================================================================*/ + + + +#endif // BOOST_BIMAP_DETAIL_CHECK_METADATA_HPP + diff --git a/win32/include/boost/bimap/detail/user_interface_config.hpp b/win32/include/boost/bimap/detail/user_interface_config.hpp new file mode 100755 index 000000000..7c9887abd --- /dev/null +++ b/win32/include/boost/bimap/detail/user_interface_config.hpp @@ -0,0 +1,24 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file detail/user_interface_config.hpp +/// \brief General configuration directives + + +#ifndef BOOST_BIMAP_DETAIL_USER_INTERFACE_CONFIG_HPP +#define BOOST_BIMAP_DETAIL_USER_INTERFACE_CONFIG_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#ifdef BOOST_BIMAP_DISABLE_SERIALIZATION + #define BOOST_MULTI_INDEX_DISABLE_SERIALIZATION +#endif + +#endif // BOOST_BIMAP_DETAIL_USER_INTERFACE_CONFIG_HPP diff --git a/win32/include/boost/bimap/list_of.hpp b/win32/include/boost/bimap/list_of.hpp new file mode 100755 index 000000000..b665d830f --- /dev/null +++ b/win32/include/boost/bimap/list_of.hpp @@ -0,0 +1,181 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file list_of.hpp +/// \brief Include support for list constrains for the bimap container + +#ifndef BOOST_BIMAP_LIST_OF_HPP +#define BOOST_BIMAP_LIST_OF_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +#include + +#include + +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +namespace boost { +namespace bimaps { + + +/// \brief Set Type Specification +/** +This struct is used to specify a set specification. +It is not a container, it is just a metaprogramming facility to +express the type of a set. Generally, this specification will +be used in other place to create a container. +It has the same syntax that an std::list instantiation, except +that the allocator cannot be specified. The rationale behind +this difference is that the allocator is not part of the set +type specification, rather it is a container configuration +parameter. + +\code +using namespace support; + +BOOST_STATIC_ASSERT( is_set_type_of< list_of >::value ) + +BOOST_STATIC_ASSERT +( + is_same + < + list_of::index_bind + < + KeyExtractor, + Tag + + >::type, + + sequenced< tag, KeyExtractor > + + >::value +) + +typedef bimap +< + list_of, RightKeyType + +> bimap_with_left_type_as_list; + +BOOST_STATIC_ASSERT +( + is_same + < + list_of::map_view_bind + < + member_at::left, + bimap_with_left_type_as_list + + >::type, + list_map_view< member_at::left, bimap_with_left_type_as_list > + + >::value +) + +\endcode + +See also list_of_relation. + **/ + +template< class Type > +struct list_of : public ::boost::bimaps::detail::set_type_of_tag +{ + /// User type, can be tagged + typedef Type user_type; + + /// Type of the object that will be stored in the list + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support:: + value_type_of::type value_type; + + + struct lazy_concept_checked + { + BOOST_CLASS_REQUIRE ( value_type, + boost, AssignableConcept ); + + typedef list_of type; + }; + + BOOST_BIMAP_GENERATE_INDEX_BINDER_0CP_NO_EXTRACTOR( + + // binds to + multi_index::sequenced + ) + + BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER( + + // binds to + views::list_map_view + ) + + BOOST_BIMAP_GENERATE_SET_VIEW_BINDER( + + // binds to + views::list_set_view + ) + + typedef mpl::bool_ mutable_key; +}; + + +/// \brief List Of Relation Specification +/** +This struct is similar to list_of but it is bind logically to a +relation. It is used in the bimap instantiation to specify the +desired type of the main view. This struct implements internally +a metafunction named bind_to that manages the quite complicated +task of finding the right type of the set for the relation. + +\code +template +struct bind_to +{ + typedef -unspecified- type; +}; +\endcode + +See also list_of, is_set_type_of_relation. + **/ + +struct list_of_relation : public ::boost::bimaps::detail::set_type_of_relation_tag +{ + BOOST_BIMAP_GENERATE_RELATION_BINDER_0CP( + + // binds to + list_of + ) + + typedef mpl::bool_ left_mutable_key; + typedef mpl::bool_ right_mutable_key; +}; + + +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_LIST_OF_HPP + diff --git a/win32/include/boost/bimap/multiset_of.hpp b/win32/include/boost/bimap/multiset_of.hpp new file mode 100755 index 000000000..f1461b82f --- /dev/null +++ b/win32/include/boost/bimap/multiset_of.hpp @@ -0,0 +1,205 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file multiset_of.hpp +/// \brief Include support for multiset constrains for the bimap container + +#ifndef BOOST_BIMAP_MULTISET_OF_HPP +#define BOOST_BIMAP_MULTISET_OF_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +#include +#include + +#include + +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +namespace boost { +namespace bimaps { + +/// \brief Set Type Specification +/** +This struct is used to specify a multiset specification. +It is not a container, it is just a metaprogramming facility to +express the type of a set. Generally, this specification will +be used in other place to create a container. +It has the same syntax that an std::set instantiation, except +that the allocator cannot be specified. The rationale behind +this difference is that the allocator is not part of the set +type specification, rather it is a container configuration +parameter. +The first parameter is the type of the objects in the multiset, +and the second one is a Functor that compares them. +Bimap binding metafunctions can be used with this class in +the following way: + +\code +using namespace support; + +BOOST_STATIC_ASSERT( is_set_type_of< multiset_of >::value ) + +BOOST_STATIC_ASSERT +( + is_same + < + compute_index_type + < + multiset_of, + KeyExtractor, + Tag + + >::type + , + ordered_nonunique< tag, KeyExtractor, KeyCompare > + + >::value +) + +typedef bimap +< + multiset_of, RightKeyType + +> bimap_with_left_type_as_multiset; + +BOOST_STATIC_ASSERT +( + is_same + < + compute_map_view_type + < + member_at::left, + bimap_with_left_type_as_multiset + + >::type, + multimap_view< member_at::left, bimap_with_left_type_as_multiset > + + >::value +) + +\endcode + +See also multiset_of_relation. + **/ + +template +< + class KeyType, + class KeyCompare = std::less< BOOST_DEDUCED_TYPENAME + ::boost::bimaps::tags::support::value_type_of::type > +> +struct multiset_of : public ::boost::bimaps::detail::set_type_of_tag +{ + /// User type, can be tagged + typedef KeyType user_type; + + /// Type of the object that will be stored in the multiset + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support:: + value_type_of::type value_type; + + /// Functor that compare two keys + typedef KeyCompare key_compare; + + struct lazy_concept_checked + { + BOOST_CLASS_REQUIRE ( value_type, + boost, AssignableConcept ); + + BOOST_CLASS_REQUIRE4( key_compare, bool, value_type, value_type, + boost, BinaryFunctionConcept ); + + typedef multiset_of type; + }; + + BOOST_BIMAP_GENERATE_INDEX_BINDER_1CP( + + // binds to + multi_index::ordered_non_unique, + + // with + key_compare + ) + + BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER( + + // binds to + views::multimap_view + ) + + BOOST_BIMAP_GENERATE_SET_VIEW_BINDER( + + // binds to + views::multiset_view + ) + + typedef mpl::bool_ mutable_key; +}; + + +/// \brief Set Of Relation Specification +/** +This struct is similar to multiset_of but it is bind logically to a +relation. It is used in the bimap instantiation to specify the +desired type of the main view. This struct implements internally +a metafunction named bind_to that manages the quite complicated +task of finding the right type of the set for the relation. + +\code +template +struct bind_to +{ + typedef -unspecified- type; +}; +\endcode + +See also multiset_of, is_set_type_of_relation. + **/ + +template< class KeyCompare = std::less< _relation > > +struct multiset_of_relation : public ::boost::bimaps::detail::set_type_of_relation_tag +{ + /// Functor that compare two keys + typedef KeyCompare key_compare; + + + BOOST_BIMAP_GENERATE_RELATION_BINDER_1CP( + + // binds to + multiset_of, + + // with + key_compare + ) + + typedef mpl::bool_ left_mutable_key; + typedef mpl::bool_ right_mutable_key; +}; + +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_MULTISET_OF_HPP diff --git a/win32/include/boost/bimap/property_map/set_support.hpp b/win32/include/boost/bimap/property_map/set_support.hpp new file mode 100755 index 000000000..0db5753fe --- /dev/null +++ b/win32/include/boost/bimap/property_map/set_support.hpp @@ -0,0 +1,55 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file property_map/set_support.hpp +/// \brief Support for the property map concept. + +#ifndef BOOST_BIMAP_PROPERTY_MAP_SET_SUPPORT_HPP +#define BOOST_BIMAP_PROPERTY_MAP_SET_SUPPORT_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { + +template< class Tag, class Bimap > +struct property_traits< ::boost::bimaps::views::map_view > +{ + typedef BOOST_DEDUCED_TYPENAME + ::boost::bimaps::support::data_type_by::type value_type; + typedef BOOST_DEDUCED_TYPENAME + ::boost::bimaps::support:: key_type_by::type key_type; + + typedef readable_property_map_tag category; +}; + + +template< class Tag, class Bimap > +const BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::data_type_by::type & + get(const ::boost::bimaps::views::map_view & m, + const BOOST_DEDUCED_TYPENAME + ::boost::bimaps::support::key_type_by::type & key) +{ + return m.at(key); +} + +} // namespace boost + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_PROPERTY_MAP_SET_SUPPORT_HPP diff --git a/win32/include/boost/bimap/property_map/unordered_set_support.hpp b/win32/include/boost/bimap/property_map/unordered_set_support.hpp new file mode 100755 index 000000000..8a1bb7d57 --- /dev/null +++ b/win32/include/boost/bimap/property_map/unordered_set_support.hpp @@ -0,0 +1,55 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file property_map/unordered_set_support.hpp +/// \brief Support for the property map concept. + +#ifndef BOOST_BIMAP_PROPERTY_MAP_UNORDERED_SET_SUPPORT_HPP +#define BOOST_BIMAP_PROPERTY_MAP_UNORDERED_SET_SUPPORT_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { + +template< class Tag, class Bimap > +struct property_traits< ::boost::bimaps::views::unordered_map_view > +{ + typedef BOOST_DEDUCED_TYPENAME + ::boost::bimaps::support::data_type_by::type value_type; + typedef BOOST_DEDUCED_TYPENAME + ::boost::bimaps::support:: key_type_by::type key_type; + + typedef readable_property_map_tag category; +}; + + +template< class Tag, class Bimap > +const BOOST_DEDUCED_TYPENAME ::boost::bimaps::support::data_type_by::type & + get(const ::boost::bimaps::views::unordered_map_view & m, + const BOOST_DEDUCED_TYPENAME + ::boost::bimaps::support::key_type_by::type & key) +{ + return m.at(key); +} + +} // namespace boost + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_PROPERTY_MAP_UNORDERED_SET_SUPPORT_HPP diff --git a/win32/include/boost/bimap/relation/detail/access_builder.hpp b/win32/include/boost/bimap/relation/detail/access_builder.hpp new file mode 100755 index 000000000..2358430d5 --- /dev/null +++ b/win32/include/boost/bimap/relation/detail/access_builder.hpp @@ -0,0 +1,170 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/detail/access_builder.hpp +/// \brief Define macros to help building metafunctions + +#ifndef BOOST_BIMAP_RELATION_ACCESS_BUILDER_HPP +#define BOOST_BIMAP_RELATION_ACCESS_BUILDER_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + + +/****************************************************************************** + BIMAP SYMMETRIC ACCESS RESULT OF +******************************************************************************* + +namespace result_of { + +template< class Tag, class SymmetricType > +struct NAME +{ + typedef -unspecified- type; +}; + +} // namespace result_of + +******************************************************************************/ + +/*===========================================================================*/ +#define BOOST_BIMAP_SYMMETRIC_ACCESS_RESULT_OF_BUILDER( \ + \ + NAME, \ + METAFUNCTION_BASE \ + ) \ + \ + namespace result_of { \ + \ + template< class Tag, class SymmetricType > \ + struct NAME \ + { \ + typedef BOOST_DEDUCED_TYPENAME METAFUNCTION_BASE \ + < \ + Tag,SymmetricType \ + \ + >::type value_type; \ + \ + typedef BOOST_DEDUCED_TYPENAME mpl::if_< is_const, \ + \ + BOOST_DEDUCED_TYPENAME call_traits::const_reference, \ + \ + BOOST_DEDUCED_TYPENAME call_traits::reference \ + \ + >::type type; \ + }; \ + \ + } +/*===========================================================================*/ + + + +/****************************************************************************** + BIMAP SYMMETRIC ACCESS IMPLEMENTATION +******************************************************************************* + +namespace detail { + +template< class Tag, class SymmetricType > +typename result_of::NAME::type + NAME( Tag , const Relation & ); + +} // namespace detail + +******************************************************************************/ + + +/*===========================================================================*/ +#define BOOST_BIMAP_SYMMETRIC_ACCESS_IMPLEMENTATION_BUILDER( \ + \ + NAME, \ + TP_SYMMETRIC, \ + PARAMETER_NAME, \ + LEFT_BODY, \ + RIGHT_BODY \ + ) \ + \ + namespace detail { \ + \ + \ + \ + template< class TP_SYMMETRIC > \ + BOOST_DEDUCED_TYPENAME result_of::NAME \ + < \ + ::boost::bimaps::relation::member_at::left,TP_SYMMETRIC \ + \ + >::type \ + \ + NAME( ::boost::bimaps::relation::member_at::left, \ + TP_SYMMETRIC & PARAMETER_NAME ) \ + { \ + LEFT_BODY; \ + } \ + \ + template< class TP_SYMMETRIC > \ + BOOST_DEDUCED_TYPENAME result_of::NAME \ + < \ + ::boost::bimaps::relation::member_at::right,TP_SYMMETRIC \ + \ + >::type \ + \ + NAME( ::boost::bimaps::relation::member_at::right, \ + TP_SYMMETRIC & PARAMETER_NAME ) \ + { \ + RIGHT_BODY; \ + } \ + \ + } +/*===========================================================================*/ + + +/****************************************************************************** + BIMAP RELATION ACCESS INTERFACE +******************************************************************************* + +template< class Tag, class SymmetricType > +typename result_of::NAME::type + NAME( const SymmetricType & ); + +******************************************************************************/ + +/*===========================================================================*/ +#define BOOST_BIMAP_SYMMETRIC_ACCESS_INTERFACE_BUILDER( \ + \ + NAME \ + ) \ + \ + template< class Tag, class SymmetricType > \ + BOOST_DEDUCED_TYPENAME result_of::NAME::type \ + NAME( SymmetricType & s ) \ + { \ + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: \ + member_with_tag \ + < \ + Tag,SymmetricType \ + \ + >::type member_at_tag; \ + \ + return detail::NAME(member_at_tag(),s); \ + } +/*===========================================================================*/ + + +#endif // BOOST_BIMAP_RELATION_ACCESS_BUILDER_HPP + diff --git a/win32/include/boost/bimap/relation/detail/metadata_access_builder.hpp b/win32/include/boost/bimap/relation/detail/metadata_access_builder.hpp new file mode 100755 index 000000000..d98e89ac3 --- /dev/null +++ b/win32/include/boost/bimap/relation/detail/metadata_access_builder.hpp @@ -0,0 +1,103 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/detail/metadata_access_builder.hpp +/// \brief Define macros to help building metafunctions + +#ifndef BOOST_BIMAP_RELATION_DETAIL_METADATA_ACCESS_BUILDER_HPP +#define BOOST_BIMAP_RELATION_DETAIL_METADATA_ACCESS_BUILDER_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include + + + +/****************************************************************************** + BIMAP SYMMETRIC METADATA ACCESS INTERFACE +******************************************************************************* + +template< class Tag, class SymmetricType > +struct NAME +{ + typedef -unspecified- type; +}; + +******************************************************************************/ + + +/*===========================================================================*/ +#define BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER( \ + \ + NAME, \ + METADATA_BY_LEFT, \ + METADATA_BY_RIGHT \ + ) \ + \ + template \ + < \ + class Tag, \ + class SymmetricType, \ + class Enable = void \ + > \ + struct NAME \ + { \ + BOOST_BIMAP_STATIC_ERROR( \ + BOOST_PP_CAT(NAME,_FAILURE), \ + (SymmetricType,Tag) \ + ); \ + }; \ + \ + template< class Tag, class SymmetricType > \ + struct NAME \ + < \ + Tag, SymmetricType, \ + BOOST_DEDUCED_TYPENAME enable_if \ + < \ + ::boost::bimaps::relation::support::is_tag_of_member_at_left \ + < \ + Tag, \ + SymmetricType \ + > \ + \ + >::type \ + > \ + { \ + typedef BOOST_DEDUCED_TYPENAME SymmetricType::METADATA_BY_LEFT type; \ + }; \ + \ + template< class Tag, class SymmetricType > \ + struct NAME \ + < \ + Tag, SymmetricType, \ + BOOST_DEDUCED_TYPENAME enable_if \ + < \ + ::boost::bimaps::relation::support::is_tag_of_member_at_right \ + < \ + Tag, \ + SymmetricType \ + > \ + \ + >::type \ + > \ + { \ + typedef BOOST_DEDUCED_TYPENAME SymmetricType::METADATA_BY_RIGHT type; \ + }; +/*===========================================================================*/ + + +#endif // BOOST_BIMAP_RELATION_DETAIL_METADATA_ACCES_BUILDER_HPP + + diff --git a/win32/include/boost/bimap/relation/detail/mutant.hpp b/win32/include/boost/bimap/relation/detail/mutant.hpp new file mode 100755 index 000000000..a2a0e8077 --- /dev/null +++ b/win32/include/boost/bimap/relation/detail/mutant.hpp @@ -0,0 +1,83 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/detail/mutant.hpp +/// \brief Mutate functions to extract views of mutant classes. + +#ifndef BOOST_BIMAP_RELATION_DETAIL_MUTANT_HPP +#define BOOST_BIMAP_RELATION_DETAIL_MUTANT_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace relation { + +/// \brief Relation details, mutant idiom and symmetrical metafunctions builders. + +namespace detail { + +//@{ +/// \brief Converts a mutant class to a view with zero overhead. +/** + +This function is a safe wrapper around reinterpret_cast. It checks at +compile time that the desired view is supported by the mutant class. +See also mutant, can_mutate_in. +\ingroup mutant_group + **/ + + +template< class View, class Type > +BOOST_DEDUCED_TYPENAME enable_if< mpl::not_< is_const< Type > >, + +View& + +>::type mutate( Type & m ) +{ + BOOST_MPL_ASSERT(( + ::boost::mpl::contains + )); + return *reinterpret_cast< View* >(addressof(m)); +} + +template< class View, class Type > +BOOST_DEDUCED_TYPENAME enable_if< is_const< Type >, + +const View& + +>::type mutate( Type & m ) +{ + BOOST_MPL_ASSERT(( + ::boost::mpl::contains + )); + return *reinterpret_cast< const View* >(addressof(m)); +} + +//@} + +} // namespace detail +} // namespace relation +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_RELATION_DETAIL_MUTANT_HPP + diff --git a/win32/include/boost/bimap/relation/detail/static_access_builder.hpp b/win32/include/boost/bimap/relation/detail/static_access_builder.hpp new file mode 100755 index 000000000..7630b4ee6 --- /dev/null +++ b/win32/include/boost/bimap/relation/detail/static_access_builder.hpp @@ -0,0 +1,105 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + + +/// \file relation/detail/static_access_builder.hpp +/// \brief Define macros to help building metafunctions + +#ifndef BOOST_BIMAP_RELATION_DETAIL_STATIC_ACCESS_BUILDER_HPP +#define BOOST_BIMAP_RELATION_DETAIL_STATIC_ACCESS_BUILDER_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include + + + +/****************************************************************************** + BIMAP SYMMETRIC STATIC ACCESS INTERFACE +******************************************************************************* + +template< class Tag, class SYMETRIC_TYPE > +struct NAME +{ + -UNDEFINED BODY-; +}; + +******************************************************************************/ + + +/*===========================================================================*/ +#define BOOST_BIMAP_SYMMETRIC_STATIC_ACCESS_BUILDER( \ + \ + NAME, \ + SYMMETRIC_TYPE, \ + LEFT_BODY, \ + RIGHT_BODY \ + ) \ + \ + template \ + < \ + class Tag, \ + class SYMMETRIC_TYPE, \ + class Enable = void \ + > \ + struct NAME \ + { \ + BOOST_BIMAP_STATIC_ERROR( \ + BOOST_PP_CAT(NAME,_FAILURE), \ + (SYMMETRIC_TYPE,Tag) \ + ); \ + }; \ + \ + template< class Tag, class SYMMETRIC_TYPE > \ + struct NAME \ + < \ + Tag, SYMMETRIC_TYPE, \ + BOOST_DEDUCED_TYPENAME enable_if \ + < \ + ::boost::bimaps::relation::support::is_tag_of_member_at_left \ + < \ + Tag, \ + SYMMETRIC_TYPE \ + > \ + \ + >::type \ + > \ + { \ + LEFT_BODY; \ + }; \ + \ + template< class Tag, class SYMMETRIC_TYPE > \ + struct NAME \ + < \ + Tag, SYMMETRIC_TYPE, \ + BOOST_DEDUCED_TYPENAME enable_if \ + < \ + ::boost::bimaps::relation::support::is_tag_of_member_at_right \ + < \ + Tag, \ + SYMMETRIC_TYPE \ + > \ + \ + >::type \ + > \ + { \ + RIGHT_BODY; \ + }; +/*===========================================================================*/ + + +#endif // BOOST_BIMAP_RELATION_DETAIL_STATIC_ACCES_BUILDER_HPP + + diff --git a/win32/include/boost/bimap/relation/detail/to_mutable_relation_functor.hpp b/win32/include/boost/bimap/relation/detail/to_mutable_relation_functor.hpp new file mode 100755 index 000000000..19bc6ad5e --- /dev/null +++ b/win32/include/boost/bimap/relation/detail/to_mutable_relation_functor.hpp @@ -0,0 +1,102 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/detail/to_mutable_relation_functor.hpp +/// \brief functors to convert types to mutable relations + +#ifndef BOOST_BIMAP_RELATION_DETAIL_TO_MUTABLE_RELATION_FUNCTOR_HPP +#define BOOST_BIMAP_RELATION_DETAIL_TO_MUTABLE_RELATION_FUNCTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace relation { +namespace detail { + +/// \brief Functor used in map views + +template< class Tag, class Relation > +struct pair_to_relation_functor +{ + const Relation + operator()(const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + pair_type_by::type & p) const + { + return Relation(p); + } +}; + +template< class Tag, class TA, class TB, class Info > +struct pair_to_relation_functor< + Tag,::boost::bimaps::relation::mutant_relation > +{ + typedef ::boost::bimaps::relation::mutant_relation Relation; + + Relation & + operator()( BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + pair_type_by::type & p ) const + { + return ::boost::bimaps::relation::detail::mutate(p); + } + + const Relation & + operator()( const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + pair_type_by::type & p) const + { + return ::boost::bimaps::relation::detail::mutate(p); + } +}; + + +/// \brief Used in set views + +template< class Relation > +struct get_mutable_relation_functor +{ + const Relation + operator()( const BOOST_DEDUCED_TYPENAME Relation::above_view & r ) const + { + return Relation(r); + } +}; + +template< class TA, class TB, class Info > +struct get_mutable_relation_functor< ::boost::bimaps::relation::mutant_relation > +{ + typedef ::boost::bimaps::relation::mutant_relation Relation; + + Relation & + operator()( BOOST_DEDUCED_TYPENAME Relation::above_view & r ) const + { + return ::boost::bimaps::relation::detail::mutate(r); + } + + const Relation & + operator()( const BOOST_DEDUCED_TYPENAME Relation::above_view & r ) const + { + return ::boost::bimaps::relation::detail::mutate(r); + } +}; + +} // namespace detail +} // namespace relation +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_RELATION_DETAIL_TO_MUTABLE_RELATION_FUNCTOR_HPP + diff --git a/win32/include/boost/bimap/relation/member_at.hpp b/win32/include/boost/bimap/relation/member_at.hpp new file mode 100755 index 000000000..b4c73710b --- /dev/null +++ b/win32/include/boost/bimap/relation/member_at.hpp @@ -0,0 +1,72 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/member_at.hpp +/// \brief Defines the tags for the member_at::side idiom + +#ifndef BOOST_BIMAP_RELATION_MEMBER_AT_HPP +#define BOOST_BIMAP_RELATION_MEMBER_AT_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +namespace boost { +namespace bimaps { +namespace relation { + +/// \brief member_at::side idiom to access relation values and types using metaprogramming. +/** + +This tags are used to specify which member you want to acces when using a metafunction over +a symmetrical type. The idea is to be able to write code like: + +\code +result_of::get::type data = get(rel); +\endcode + +The relation class supports this idiom even when the elements are tagged. This is useful +because a user can decide to start tagging in any moment of the development. + +See also member_with_tag, is_tag_of_member_at_left, is_tag_of_member_at_right, get +value_type_of, pair_by, pair_type_by. + +\ingroup relation_group + **/ +namespace member_at { + + /// \brief Member at left tag + /** + See also member_at, rigth. + **/ + + struct left {}; + + /// \brief Member at right tag + /** + See also member_at, left. + **/ + + struct right {}; + + /// \brief Member info tag + /** + See also member_at, left, right. + **/ + + struct info {}; + +} + +} // namespace relation +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_RELATION_MEMBER_AT_HPP diff --git a/win32/include/boost/bimap/relation/mutant_relation.hpp b/win32/include/boost/bimap/relation/mutant_relation.hpp new file mode 100755 index 000000000..8e5a205b9 --- /dev/null +++ b/win32/include/boost/bimap/relation/mutant_relation.hpp @@ -0,0 +1,430 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/mutant_relation.hpp +/// \brief Defines the mutant_relation class + +#ifndef BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP +#define BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include + +#include + +#include + +// Boost.Bimap +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace relation { + +namespace detail { + +// This class is included so structured_pair and mutant_relation share +// exactly the same class layout + +template< class LeftType, class RightType, bool force_mutable > +class relation_storage : + public symmetrical_base +{ + typedef symmetrical_base base_; + + typedef relation_storage storage_; + + public: + + typedef relation_storage non_mutable_storage; + + typedef ::boost::mpl::vector2 + < + relation_storage< LeftType, RightType, true >, + relation_storage< LeftType, RightType, false > + + > mutant_views; + + //@{ + /// data + BOOST_DEDUCED_TYPENAME base_::left_value_type left; + BOOST_DEDUCED_TYPENAME base_::right_value_type right; + //@} + + relation_storage() {} + + relation_storage(BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::left_value_type + >::param_type l, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::right_value_type + >::param_type r) + + : left(l), right(r) {} + + BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left() { return left; } + const BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left()const { return left; } + BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right() { return right; } + const BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()const { return right; } +}; + + + +template< class TA, class TB, class Info, bool force_mutable > +class relation_info_hook : public + ::boost::bimaps::relation::detail::relation_storage +{ + typedef ::boost::bimaps::relation::detail:: + relation_storage base_; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support:: + default_tagged::type tagged_info_type; + + public: + typedef BOOST_DEDUCED_TYPENAME tagged_info_type::value_type info_type; + typedef BOOST_DEDUCED_TYPENAME tagged_info_type::tag info_tag; + + info_type info; + + protected: + + relation_info_hook() {} + + relation_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::left_value_type + >::param_type l, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::right_value_type + >::param_type r, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + info_type + >::param_type i = info_type() ) + + : base_(l,r), info(i) {} + + template< class Relation > + relation_info_hook( const Relation & rel ) : + base_(rel.left,rel.right), + info(rel.info) {} + + template< class Relation > + void change_to( const Relation & rel ) + { + base_::left = rel.left ; + base_::right = rel.right; + info = rel.info ; + } + + #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION + template< class Archive > + void serialize(Archive & ar, const unsigned int version) + { + ar & ::boost::serialization::make_nvp("left" , base_::left ); + ar & ::boost::serialization::make_nvp("right", base_::right); + ar & ::boost::serialization::make_nvp("info" , info ); + } + #endif // BOOST_BIMAP_DISABLE_SERIALIZATION +}; + +template< class TA, class TB, bool force_mutable> +class relation_info_hook : + public ::boost::bimaps::relation::detail::relation_storage +{ + typedef ::boost::bimaps::relation::detail:: + relation_storage base_; + + public: + typedef ::boost::mpl::na info_type; + typedef member_at::info info_tag; + + protected: + + relation_info_hook() {} + + relation_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::left_value_type + >::param_type l, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::right_value_type + >::param_type r) + + : base_(l,r) {} + + template< class Relation > + relation_info_hook( const Relation & rel ) : + base_(rel.left,rel.right) {} + + template< class Relation > + void change_to( const Relation & rel ) + { + base_::left = rel.left ; + base_::right = rel.right; + } + + #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION + template< class Archive > + void serialize(Archive & ar, const unsigned int version) + { + ar & ::boost::serialization::make_nvp("left" , base_::left ); + ar & ::boost::serialization::make_nvp("right", base_::right); + } + #endif // BOOST_BIMAP_DISABLE_SERIALIZATION +}; + + +} // namespace detail + +/// \brief Abstraction of a related pair of values, that extends the std::pair class. +/** +The mutant_relation is a mutant class. A mutant class can mutate +with zero overhead in other classes that are called views. +Each view has to be StorageCompatible with the base class +of the mutant. Note that all the views have the following +storage structure: + +\verbatim + __________ + | | + | TA | + |__________| + | | + | TB | + |__________| + +\endverbatim + +See also select_relation, standard_relation. +\ingroup relation_group + **/ + + +template< class TA, class TB, class Info = ::boost::mpl::na, bool force_mutable = false > +class mutant_relation : public + ::boost::bimaps::relation::detail:: + relation_info_hook +{ + typedef ::boost::bimaps::relation::detail:: + relation_info_hook base_; + + public: + + // We have to know the type of the base where the types are + // defined because Boost.MultiIndex requires it. + + typedef ::boost::bimaps::relation::detail:: + relation_storage storage_base; + + /// Above view, non mutable view of the relation + + typedef mutant_relation above_view; + + //@{ + /// A signature compatible std::pair that is a view of the relation. + + typedef structured_pair< TA, TB, Info, normal_layout > left_pair; + typedef structured_pair< TB, TA, Info, mirror_layout > right_pair; + //@} + + typedef ::boost::mpl::vector4 + < + left_pair, + right_pair, + + mutant_relation< TA, TB, Info, true >, + mutant_relation< TA, TB, Info, false > + + > mutant_views; + + mutant_relation() {} + + mutant_relation(BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_:: left_value_type + >::param_type l, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::right_value_type + >::param_type r) : + base_(l,r) {} + + mutant_relation(BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_:: left_value_type + >::param_type l, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::right_value_type + >::param_type r, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::info_type + >::param_type i) : + base_(l,r,i) {} + + mutant_relation(const mutant_relation & rel) : + base_(rel) {} + + mutant_relation(const mutant_relation & rel) : + base_(rel) {} + + // Operators + + template< bool FM > + mutant_relation& operator=(const mutant_relation & rel) + { + base_::change_to(rel); + return *this; + } + + // The following functions are redundant if you only consider this class. + // They are included to make easier the construction of the get and the + // pair_by metafunction. Remember that not all compiler supports the mutant + // idiom. + + left_pair & get_left_pair() + { + return ::boost::bimaps::relation::detail::mutate(*this); + } + + const left_pair & get_left_pair() const + { + return ::boost::bimaps::relation::detail::mutate(*this); + } + + right_pair & get_right_pair() + { + return ::boost::bimaps::relation::detail::mutate(*this); + } + + const right_pair & get_right_pair() const + { + return ::boost::bimaps::relation::detail::mutate(*this); + } + + above_view & get_view() + { + return ::boost::bimaps::relation::detail::mutate(*this); + } + + const above_view & get_view() const + { + return ::boost::bimaps::relation::detail::mutate(*this); + } + + template< class Tag > + const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + result_of::get::type + get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) const + { + return ::boost::bimaps::relation::support::get(*this); + } + + template< class Tag > + BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + result_of::get::type + get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) + { + return ::boost::bimaps::relation::support::get(*this); + } + + #ifndef BOOST_BIMAP_DISABLE_SERIALIZATION + + private: + friend class ::boost::serialization::access; + + template + void serialize(Archive & ar, const unsigned int version) + { + base_::serialize(ar,version); + } + + #endif // BOOST_BIMAP_DISABLE_SERIALIZATION +}; + +// hash value + +template< class FirstType, class SecondType, bool FM > +std::size_t hash_value(const detail::relation_storage & r) +{ + std::size_t seed = 0; + ::boost::hash_combine(seed, r. left ); + ::boost::hash_combine(seed, r.right ); + + return seed; +} + +// mutant_relation - mutant_relation + +template< class FirstType, class SecondType, bool FM1, bool FM2 > +bool operator==(const detail::relation_storage & a, + const detail::relation_storage & b) +{ + return ( ( a.left == b.left ) && + ( a.right == b.right ) ); +} + +template< class FirstType, class SecondType, bool FM1, bool FM2 > +bool operator!=(const detail::relation_storage & a, + const detail::relation_storage & b) +{ + return ! ( a == b ); +} + +template< class FirstType, class SecondType, bool FM1, bool FM2 > +bool operator<(const detail::relation_storage & a, + const detail::relation_storage & b) +{ + return ( ( a.left < b.left ) || + (( a.left == b.left ) && ( a.right < b.right ))); +} + +template< class FirstType, class SecondType, bool FM1, bool FM2 > +bool operator<=(const detail::relation_storage & a, + const detail::relation_storage & b) +{ + return ( ( a.left < b.left ) || + (( a.left == b.left ) && ( a.right <= b.right ))); +} + +template< class FirstType, class SecondType, bool FM1, bool FM2 > +bool operator>(const detail::relation_storage & a, + const detail::relation_storage & b) +{ + return ( ( a.left > b.left ) || + (( a.left == b.left ) && ( a.right > b.right ))); +} + +template< class FirstType, class SecondType, bool FM1, bool FM2 > +bool operator>=(const detail::relation_storage & a, + const detail::relation_storage & b) +{ + return ( ( a.left > b.left ) || + (( a.left == b.left ) && ( a.right >= b.right ))); +} + +} // namespace relation +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_RELATION_MUTANT_RELATION_HPP + + + diff --git a/win32/include/boost/bimap/relation/pair_layout.hpp b/win32/include/boost/bimap/relation/pair_layout.hpp new file mode 100755 index 000000000..09d89b247 --- /dev/null +++ b/win32/include/boost/bimap/relation/pair_layout.hpp @@ -0,0 +1,72 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/pair_layout.hpp +/// \brief Tags for pair layouts + +#ifndef BOOST_BIMAP_RELATION_PAIR_LAYOUT_HPP +#define BOOST_BIMAP_RELATION_PAIR_LAYOUT_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +namespace boost { +namespace bimaps { +namespace relation { + +//@{ + +/// \brief Tag for normal layout. ( A,B -> A,B ) + +struct normal_layout {}; + +/// \brief Tag for mirror layout. ( A,B -> B,A ) + +struct mirror_layout {}; + +//@} + +/** \struct boost::bimaps::relation::inverse_layout +\brief Metafunction to obtain the inverse of a layout. + +\code +template< class Layout > +struct inverse_layout +{ + typedef {InverseLayout} type; +}; +\endcode + +See also normal_layout, mirror_layout. + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class Layout > +struct inverse_layout +{ + typedef normal_layout type; +}; + +template<> +struct inverse_layout< normal_layout > +{ + typedef mirror_layout type; +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +} // namespace relation +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_RELATION_DETAIL_PAIR_LAYOUT_HPP + diff --git a/win32/include/boost/bimap/relation/structured_pair.hpp b/win32/include/boost/bimap/relation/structured_pair.hpp new file mode 100755 index 000000000..53c161865 --- /dev/null +++ b/win32/include/boost/bimap/relation/structured_pair.hpp @@ -0,0 +1,508 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/structured_pair.hpp +/// \brief Defines the structured_pair class. + +#ifndef BOOST_BIMAP_RELATION_STRUCTURED_PAIR_HPP +#define BOOST_BIMAP_RELATION_STRUCTURED_PAIR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + + +namespace boost { +namespace bimaps { +namespace relation { + +namespace detail { + +/// \brief Storage definition of the left view of a mutant relation. +/** + +See also storage_finder, mirror_storage. + **/ + +template< class FirstType, class SecondType > +class normal_storage : + public symmetrical_base +{ + typedef symmetrical_base base_; + + public: + + typedef normal_storage storage_; + + typedef BOOST_DEDUCED_TYPENAME base_::left_value_type first_type; + typedef BOOST_DEDUCED_TYPENAME base_::right_value_type second_type; + + first_type first; + second_type second; + + normal_storage() {} + + normal_storage(BOOST_DEDUCED_TYPENAME ::boost::call_traits< + first_type >::param_type f, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + second_type>::param_type s) + + : first(f), second(s) {} + + BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left() { return first; } + const BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left()const { return first; } + BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right() { return second; } + const BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()const { return second; } +}; + +/// \brief Storage definition of the right view of a mutant relation. +/** + +See also storage_finder, normal_storage. + **/ + +template< class FirstType, class SecondType > +class mirror_storage : + public symmetrical_base +{ + typedef symmetrical_base base_; + + public: + + typedef mirror_storage storage_; + + typedef BOOST_DEDUCED_TYPENAME base_::left_value_type second_type; + typedef BOOST_DEDUCED_TYPENAME base_::right_value_type first_type; + + second_type second; + first_type first; + + mirror_storage() {} + + mirror_storage(BOOST_DEDUCED_TYPENAME ::boost::call_traits::param_type f, + BOOST_DEDUCED_TYPENAME ::boost::call_traits::param_type s) + + : second(s), first(f) {} + + BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left() { return second; } + const BOOST_DEDUCED_TYPENAME base_:: left_value_type & get_left()const { return second; } + BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right() { return first; } + const BOOST_DEDUCED_TYPENAME base_::right_value_type & get_right()const { return first; } +}; + +/** \struct boost::bimaps::relation::storage_finder +\brief Obtain the a storage with the correct layout. + +\code +template< class FirstType, class SecondType, class Layout > +struct storage_finder +{ + typedef {normal/mirror}_storage type; +}; +\endcode + +See also normal_storage, mirror_storage. + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template +< + class FirstType, + class SecondType, + class Layout +> +struct storage_finder +{ + typedef normal_storage type; +}; + +template +< + class FirstType, + class SecondType +> +struct storage_finder +{ + typedef mirror_storage type; +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + + +template< class TA, class TB, class Info, class Layout > +class pair_info_hook : + public ::boost::bimaps::relation::detail::storage_finder::type +{ + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::detail::storage_finder::type base_; + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support:: + default_tagged::type tagged_info_type; + + public: + typedef BOOST_DEDUCED_TYPENAME tagged_info_type::value_type info_type; + typedef BOOST_DEDUCED_TYPENAME tagged_info_type::tag info_tag; + + info_type info; + + protected: + + pair_info_hook() {} + + pair_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::first_type + >::param_type f, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::second_type + >::param_type s, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + info_type + >::param_type i = info_type() ) + : base_(f,s), info(i) {} + + template< class Pair > + pair_info_hook( const Pair & p) : + base_(p.first,p.second), + info(p.info) {} + + template< class Pair > + void change_to( const Pair & p ) + { + base_::first = p.first ; + base_::second = p.second; + info = p.info ; + } + + void clear_info() + { + info = info_type(); + }; +}; + +template< class TA, class TB, class Layout> +class pair_info_hook : + public ::boost::bimaps::relation::detail::storage_finder::type +{ + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::detail::storage_finder::type base_; + + public: + typedef ::boost::mpl::na info_type; + typedef member_at::info info_tag; + + protected: + + pair_info_hook() {} + + pair_info_hook( BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::first_type + >::param_type f, + BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::second_type + >::param_type s) + + : base_(f,s) {} + + template< class Pair > + pair_info_hook( const Pair & p ) : + base_(p.first,p.second) {} + + template< class Pair > + void change_to( const Pair & p ) + { + base_::first = p.first ; + base_::second = p.second; + } + + void clear_info() {}; +}; + + + +} // namespace detail + +template< class TA, class TB, class Info, bool FM > +class mutant_relation; + + +/// \brief A std::pair signature compatible class that allows you to control +/// the internal structure of the data. +/** +This class allows you to specify the order in wich the two data types will be +in the layout of the class. + **/ + +template< class FirstType, class SecondType, class Info, class Layout = normal_layout > +class structured_pair : + + public ::boost::bimaps::relation::detail::pair_info_hook + < + FirstType, SecondType, + Info, + Layout + + > + +{ + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::detail::pair_info_hook + < + FirstType, SecondType, + Info, + Layout + + > base_; + + public: + + typedef ::boost::mpl::vector3< + structured_pair< FirstType, SecondType, Info, normal_layout >, + structured_pair< FirstType, SecondType, Info, mirror_layout >, + BOOST_DEDUCED_TYPENAME ::boost::mpl::if_< + BOOST_DEDUCED_TYPENAME ::boost::is_same::type, + mutant_relation< FirstType, SecondType, Info, true >, + mutant_relation< SecondType, FirstType, Info, true > + >::type + + > mutant_views; + + structured_pair() {} + + structured_pair(BOOST_DEDUCED_TYPENAME boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::first_type >::param_type f, + BOOST_DEDUCED_TYPENAME boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::second_type >::param_type s) + : base_(f,s) {} + + structured_pair(BOOST_DEDUCED_TYPENAME boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::first_type >::param_type f, + BOOST_DEDUCED_TYPENAME boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::second_type >::param_type s, + BOOST_DEDUCED_TYPENAME boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::info_type >::param_type i) + : base_(f,s,i) {} + + template< class OtherLayout > + structured_pair( + const structured_pair & p) + : base_(p) {} + + template< class OtherLayout > + structured_pair& operator=( + const structured_pair & p) + { + base_::change_to(p); + return *this; + } + + template< class First, class Second > + structured_pair(const std::pair & p) : + base_(p.first,p.second) + {} + + template< class First, class Second > + structured_pair& operator=(const std::pair & p) + { + base_::first = p.first; + base_::second = p.second; + base_::clear_info(); + return *this; + } + + template< class Tag > + const BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + result_of::get::type + get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) const + { + return ::boost::bimaps::relation::support::get(*this); + } + + template< class Tag > + BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support:: + result_of::get::type + get(BOOST_EXPLICIT_TEMPLATE_TYPE(Tag)) + { + return ::boost::bimaps::relation::support::get(*this); + } +}; + +// structured_pair - structured_pair + +template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 > +bool operator==(const structured_pair & a, + const structured_pair & b) +{ + return ( ( a.first == b.first ) && + ( a.second == b.second ) ); +} + +template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 > +bool operator!=(const structured_pair & a, + const structured_pair & b) +{ + return ! ( a == b ); +} + +template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 > +bool operator<(const structured_pair & a, + const structured_pair & b) +{ + return ( ( a.first < b.first ) || + (( a.first == b.first ) && ( a.second < b.second ))); +} + +template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 > +bool operator<=(const structured_pair & a, + const structured_pair & b) +{ + return ( ( a.first < b.first ) || + (( a.first == b.first ) && ( a.second <= b.second ))); +} + +template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 > +bool operator>(const structured_pair & a, + const structured_pair & b) +{ + return ( ( a.first > b.first ) || + (( a.first == b.first ) && ( a.second > b.second ))); +} + +template< class FirstType, class SecondType, class Info, class Layout1, class Layout2 > +bool operator>=(const structured_pair & a, + const structured_pair & b) +{ + return ( ( a.first > b.first ) || + (( a.first == b.first ) && ( a.second >= b.second ))); +} + +// structured_pair - std::pair + +template< class FirstType, class SecondType, class Info, class Layout, class F, class S > +bool operator==(const structured_pair & a, + const std::pair & b) +{ + return ( ( a.first == b.first ) && + ( a.second == b.second ) ); +} + +template< class FirstType, class SecondType, class Info, class Layout, class F, class S > +bool operator!=(const structured_pair & a, + const std::pair & b) +{ + return ! ( a == b ); +} + +template< class FirstType, class SecondType, class Info, class Layout, class F, class S > +bool operator<(const structured_pair & a, + const std::pair & b) +{ + return ( ( a.first < b.first ) || + (( a.first == b.first ) && ( a.second < b.second ))); +} + +template< class FirstType, class SecondType, class Info, class Layout, class F, class S > +bool operator<=(const structured_pair & a, + const std::pair & b) +{ + return ( ( a.first < b.first ) || + (( a.first == b.first ) && ( a.second <= b.second ))); +} + +template< class FirstType, class SecondType, class Info, class Layout, class F, class S > +bool operator>(const structured_pair & a, + const std::pair & b) +{ + return ( ( a.first > b.first ) || + (( a.first == b.first ) && ( a.second > b.second ))); +} + +template< class FirstType, class SecondType, class Info, class Layout, class F, class S > +bool operator>=(const structured_pair & a, + const std::pair & b) +{ + return ( ( a.first > b.first ) || + (( a.first == b.first ) && ( a.second >= b.second ))); +} + +// std::pair - sturctured_pair + +template< class FirstType, class SecondType, class Info, class Layout, class F, class S > +bool operator==(const std::pair & a, + const structured_pair & b) +{ + return ( ( a.first == b.first ) && + ( a.second == b.second ) ); +} + +template< class FirstType, class SecondType, class Info, class Layout, class F, class S > +bool operator!=(const std::pair & a, + const structured_pair & b) +{ + return ! ( a == b ); +} + +template< class FirstType, class SecondType, class Info, class Layout, class F, class S > +bool operator<(const std::pair & a, + const structured_pair & b) +{ + return ( ( a.first < b.first ) || + (( a.first == b.first ) && ( a.second < b.second ))); +} + +template< class FirstType, class SecondType, class Info, class Layout, class F, class S > +bool operator<=(const std::pair & a, + const structured_pair & b) +{ + return ( ( a.first < b.first ) || + (( a.first == b.first ) && ( a.second <= b.second ))); +} + +template< class FirstType, class SecondType, class Info, class Layout, class F, class S > +bool operator>(const std::pair & a, + const structured_pair & b) +{ + return ( ( a.first > b.first ) || + (( a.first == b.first ) && ( a.second > b.second ))); +} + +template< class FirstType, class SecondType, class Info, class Layout, class F, class S > +bool operator>=(const std::pair & a, + const structured_pair & b) +{ + return ( ( a.first > b.first ) || + (( a.first == b.first ) && ( a.second >= b.second ))); +} + + + +} // namespace relation +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_RELATION_STRUCTURED_PAIR_HPP + diff --git a/win32/include/boost/bimap/relation/support/data_extractor.hpp b/win32/include/boost/bimap/relation/support/data_extractor.hpp new file mode 100755 index 000000000..fc4a40062 --- /dev/null +++ b/win32/include/boost/bimap/relation/support/data_extractor.hpp @@ -0,0 +1,109 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/support/data_extractor.hpp +/// \brief Data extraction functor. + +#ifndef BOOST_BIMAP_RELATION_SUPPORT_DATA_EXTRACTOR_HPP +#define BOOST_BIMAP_RELATION_SUPPORT_DATA_EXTRACTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +/** \struct boost::bimaps::relation::support::data_extractor + +\brief Data extraction functor. + +\ingroup relation_group + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace relation { +namespace support { + +template< class Tag, class Relation > +struct data_extractor_implementation; + +template< class Relation > +struct data_extractor_implementation< member_at::left, Relation > : + public std::unary_function +{ + BOOST_DEDUCED_TYPENAME Relation::left_value_type const & + operator()(Relation const & rel) const + { + return rel.left; + } + + BOOST_DEDUCED_TYPENAME Relation::left_value_type & + operator()(Relation & rel) const + { + return rel.left; + } +}; + +template< class Relation > +struct data_extractor_implementation< member_at::right, Relation > : + public std::unary_function +{ + BOOST_DEDUCED_TYPENAME Relation::right_value_type const & + operator()(Relation const & rel) const + { + return rel.right; + } + + BOOST_DEDUCED_TYPENAME Relation::right_value_type & + operator()(Relation & rel) const + { + return rel.right; + } +}; + +template< class Tag, class Relation > +struct data_extractor +{ + typedef data_extractor_implementation + < + BOOST_DEDUCED_TYPENAME member_with_tag::type, + Relation + + > type; +}; + +template< class Relation > +struct both_keys_extractor +{ + typedef BOOST_DEDUCED_TYPENAME Relation::storage_base result_type; + + const result_type & operator()(const Relation & rel) const + { + return rel; + } + + result_type & operator()( Relation & rel) const + { + return rel; + } +}; + +} // namespace support +} // namespace relation +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_RELATION_SUPPORT_DATA_EXTRACTOR_HPP + diff --git a/win32/include/boost/bimap/relation/support/get.hpp b/win32/include/boost/bimap/relation/support/get.hpp new file mode 100755 index 000000000..6ed45820d --- /dev/null +++ b/win32/include/boost/bimap/relation/support/get.hpp @@ -0,0 +1,140 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/support/get.hpp +/// \brief get(r) function + +#ifndef BOOST_BIMAP_RELATION_SUPPORT_GET_HPP +#define BOOST_BIMAP_RELATION_SUPPORT_GET_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +#include + +#include +#include +#include + +#ifdef BOOST_BIMAP_ONLY_DOXYGEN_WILL_PROCESS_THE_FOLLOWING_LINES + + +namespace boost { +namespace bimaps { +namespace relation { +namespace support { + +/** \brief Gets a pair view of the relation. + +\ingroup relation_group + **/ + +template< class Tag, class SymmetricType > +BOOST_DEDUCED_TYPENAME result_of::get::type + get( SymmetricType & ); + +} // namespace support +} // namespace relation +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_ONLY_DOXYGEN_WILL_PROCESS_THE_FOLLOWING_LINES + + + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace relation { +namespace support { + +// Since it is very error-prone to directly write the hole bunch +// of relation accesor. They are buil from litle macro blocks that +// are both more readable, leading to self docummenting code and a +// lot more easier to understand and mantain. +// It is very important to note that the three building blocks have +// to laid in the same namespace in order to work. There is also +// important to keep them in order. +// The forward declaration are not necesary but they help a lot to +// the reader, as they undercover what is the signature of the +// result code. +// In the end, it is not quicker to do it in this way because you +// write a lot. But this code has no complexity at all and almost +// every word writed is for documentation. + +// Result of +// ------------------------------------------------------------------------- +/* + namespace result_of { + + template< class Tag, class Relation > + struct get; + { + typedef -unspecified- type; + }; + + } // namespace result_of + +*/ + +BOOST_BIMAP_SYMMETRIC_ACCESS_RESULT_OF_BUILDER +( + get, + value_type_of +) + + + +// Implementation +// ------------------------------------------------------------------------- + +BOOST_BIMAP_SYMMETRIC_ACCESS_IMPLEMENTATION_BUILDER +( + get, + SymmetricType, + st, + return st.get_left(), + return st.get_right() +) + +namespace detail { + +template< class SymmetricType > +BOOST_DEDUCED_TYPENAME result_of::get< + ::boost::bimaps::relation::member_at::info, SymmetricType >::type +get(::boost::bimaps::relation::member_at::info, SymmetricType & rel) +{ + return rel.info; +} + +} // namespace detail + +// Interface +//---------------------------------------------------------------------------- + +BOOST_BIMAP_SYMMETRIC_ACCESS_INTERFACE_BUILDER +( + get +) + + +} // namespace support +} // namespace relation +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_RELATION_SUPPORT_GET_HPP + diff --git a/win32/include/boost/bimap/relation/support/get_pair_functor.hpp b/win32/include/boost/bimap/relation/support/get_pair_functor.hpp new file mode 100755 index 000000000..278d10508 --- /dev/null +++ b/win32/include/boost/bimap/relation/support/get_pair_functor.hpp @@ -0,0 +1,85 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/support/get_pair_functor.hpp +/// \brief get_pair_functor definition + +#ifndef BOOST_BIMAP_RELATION_SUPPORT_GET_PAIR_FUNCTOR_HPP +#define BOOST_BIMAP_RELATION_SUPPORT_GET_PAIR_FUNCTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +namespace boost { +namespace bimaps { +namespace relation { +namespace support { + +/// \brief A Functor that takes a relation as a parameter an return the desired view. +/** + +This functor is included to help users of the relation class when using +stl algorithms. + +See also member_at, pair_by(). +\ingroup relation_group + + **/ + +template< class Tag, class Relation > +struct get_pair_functor +{ + BOOST_DEDUCED_TYPENAME result_of::pair_by::type + operator()( Relation & r ) const + { + return pair_by(r); + } + + BOOST_DEDUCED_TYPENAME result_of::pair_by::type + operator()( const Relation & r ) const + { + return pair_by(r); + } +}; + + +/// \brief A Functor that takes a relation as a parameter an return the above view. +/** + +\ingroup relation_group + **/ + +template< class Relation > +struct get_above_view_functor +{ + BOOST_DEDUCED_TYPENAME Relation::above_view & + operator()( Relation & r ) const + { + return r.get_view(); + } + + const BOOST_DEDUCED_TYPENAME Relation::above_view & + operator()( const Relation & r ) const + { + return r.get_view(); + } +}; + +} // namespace support +} // namespace relation +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_RELATION_SUPPORT_GET_PAIR_FUNCTOR_HPP + diff --git a/win32/include/boost/bimap/relation/support/is_tag_of_member_at.hpp b/win32/include/boost/bimap/relation/support/is_tag_of_member_at.hpp new file mode 100755 index 000000000..151ec116f --- /dev/null +++ b/win32/include/boost/bimap/relation/support/is_tag_of_member_at.hpp @@ -0,0 +1,181 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/support/is_tag_of_member_at.hpp +/// \brief is_tag_of_member_at metafunction + +#ifndef BOOST_BIMAP_RELATION_SUPPORT_IS_TAG_OF_MEMBER_AT_HPP +#define BOOST_BIMAP_RELATION_SUPPORT_IS_TAG_OF_MEMBER_AT_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +#include +#include +#include + +/** \struct boost::bimaps::relation::support::is_tag_of_member_at_left + +\brief Metafunction to test if a user tag is refering to the left member. + +\code + +template< class Tag, class Relation > +struct is_tag_of_member_at_left : {true_|false_} {}; + +\endcode + +This metafunction is somewhat redundant with member_with_tag, but it is included +because it is a lot easier to metaprogram with it. The result type is the +same that: + +\code + + is_same< member_with_tag::type , member_at::left >::type + +\endcode + +See also member_with_tag, member_at, is_tag_of_member_at_right. +\ingroup relation_group + **/ + + +/** \struct boost::bimaps::relation::support::is_tag_of_member_at_right + +\brief Metafunction to test if a user tag is refering to the left member. + +\code + +template< class Tag, class Relation > +struct is_tag_of_member_at_right : {true_|false_} {}; + +\endcode + +This metafunction is somewhat redundat with member_with_tag, but it is included +because it is a lot easier to metaprogram with it. The result type is the +same that: + +\code + + is_same< member_with_tag::type , member_at::right >::type + +\endcode + +See also member_with_tag, member_at, is_tag_of_member_at_left. +\ingroup relation_group + **/ + + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace relation { +namespace support { + +// Metafunction is_tag_of_member_at_left +// Easiear metaprogramming + +template +< + class Tag, + class Relation, + class Enable = void +> +struct is_tag_of_member_at_left : + ::boost::mpl::false_ {}; + +template< class Tag, class Relation > +struct is_tag_of_member_at_left +< + Tag, Relation, + BOOST_DEDUCED_TYPENAME enable_if + < + is_same + < + BOOST_DEDUCED_TYPENAME member_with_tag::type, + member_at::left + > + + >::type +> : + ::boost::mpl::true_ {}; + +// Metafunction is_tag_of_member_at_right +// Easiear metaprogramming + +template +< + class Tag, + class Relation, + class Enable = void +> +struct is_tag_of_member_at_right : + ::boost::mpl::false_ {}; + +template< class Tag, class Relation > +struct is_tag_of_member_at_right +< + Tag, Relation, + BOOST_DEDUCED_TYPENAME enable_if + < + is_same + < + BOOST_DEDUCED_TYPENAME member_with_tag::type, + member_at::right + > + + >::type +> : + ::boost::mpl::true_ {}; + + +// Metafunction is_tag_of_member_at_info +// Easiear metaprogramming + +template +< + class Tag, + class Relation, + class Enable = void +> +struct is_tag_of_member_at_info : + ::boost::mpl::false_ {}; + +template< class Tag, class Relation > +struct is_tag_of_member_at_info +< + Tag, Relation, + BOOST_DEDUCED_TYPENAME enable_if + < + is_same + < + BOOST_DEDUCED_TYPENAME member_with_tag::type, + member_at::info + > + + >::type +> : + ::boost::mpl::true_ {}; + +} // namespace support +} // namespace relation +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_RELATION_SUPPORT_IS_TAG_OF_MEMBER_AT_HPP + + diff --git a/win32/include/boost/bimap/relation/support/member_with_tag.hpp b/win32/include/boost/bimap/relation/support/member_with_tag.hpp new file mode 100755 index 000000000..35844ddfe --- /dev/null +++ b/win32/include/boost/bimap/relation/support/member_with_tag.hpp @@ -0,0 +1,180 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/support/member_with_tag.hpp +/// \brief member_with_tag metafunction + +#ifndef BOOST_BIMAP_RELATION_SUPPORT_MEMBER_WITH_TAG_HPP +#define BOOST_BIMAP_RELATION_SUPPORT_MEMBER_WITH_TAG_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include + +/** \struct boost::bimaps::relation::support::member_with_tag + +\brief Metafunction to convert user tags to the member_at idiom. + +\code + +template< class Tag, class Relation > +struct member_with_tag +{ + typedef member_at::{side} type; +}; + +\endcode + +We have to allow that all the metafunctions that works with tags +and retrieves data from a Relation will work with member_at idiom +even if the type was tagged. This will be great for the user, +because he can choose to tag a member after he is using the +relation and the code will still work. + +If we perform this check in every metafunction it will be very +tedious and error prone, so instead of that all metafunctions +that works with relations first call this metafunction that +convert the tag to a member_at tag. + +See also member_at, is_tag_of_member_at_left, is_tag_of_member_at_right. +\ingroup relation_group + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace relation { +namespace support { + +template +< + class Tag, + class Relation, + class Enable = void +> +struct member_with_tag +{ + BOOST_BIMAP_STATIC_ERROR( MEMBER_WITH_TAG_FAILURE, (Relation,Tag) ); +}; + +template< class Relation > +struct member_with_tag +< + member_at::left, Relation, void +> +{ + typedef member_at::left type; +}; + +template< class Relation > +struct member_with_tag +< + member_at::right, Relation, void +> +{ + typedef member_at::right type; +}; + +template< class Relation > +struct member_with_tag +< + member_at::info, Relation, void +> +{ + typedef member_at::info type; +}; + + +template< class Tag, class Relation > +struct member_with_tag +< + Tag, Relation, + BOOST_DEDUCED_TYPENAME enable_if + < + mpl::and_ + < + mpl::not_< is_same >, + is_same + < + Tag, + BOOST_DEDUCED_TYPENAME Relation::left_tag + > + > + + >::type +> +{ + typedef member_at::left type; +}; + +template< class Tag, class Relation > +struct member_with_tag +< + Tag, + Relation, + BOOST_DEDUCED_TYPENAME enable_if + < + mpl::and_ + < + mpl::not_< is_same >, + is_same + < + Tag, + BOOST_DEDUCED_TYPENAME Relation::right_tag + > + > + + >::type +> +{ + typedef member_at::right type; +}; + +template< class Tag, class Relation > +struct member_with_tag +< + Tag, Relation, + BOOST_DEDUCED_TYPENAME enable_if + < + mpl::and_ + < + mpl::not_< is_same >, + is_same + < + Tag, + BOOST_DEDUCED_TYPENAME Relation::info_tag + > + > + + >::type +> +{ + typedef member_at::info type; +}; + +} // namespace support +} // namespace relation +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_RELATION_SUPPORT_MEMBER_WITH_TAG_HPP + + diff --git a/win32/include/boost/bimap/relation/support/opposite_tag.hpp b/win32/include/boost/bimap/relation/support/opposite_tag.hpp new file mode 100755 index 000000000..24a6a63c2 --- /dev/null +++ b/win32/include/boost/bimap/relation/support/opposite_tag.hpp @@ -0,0 +1,61 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/support/opposite_tag.hpp +/// \brief Metafunction to obtain the opposite tag in a relation. + +#ifndef BOOST_BIMAP_RELATION_SUPPORT_OPPOSITE_TAG_HPP +#define BOOST_BIMAP_RELATION_SUPPORT_OPPOSITE_TAG_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +/** \struct boost::bimaps::relation::support::opposite_tag + +\brief Metafunction to obtain the opposite tag in a relation. + +\code + +template< class Tag, class Relation > +struct opposite_tag +{ + typedef {OppositeTag} type; +}; + +\endcode + +\ingroup relation_group + **/ + +namespace boost { +namespace bimaps { +namespace relation { +namespace support { + +// Implementation of const pair reference type by metafunction + +BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER +( + opossite_tag, + right_tag, + left_tag +) + +} // namespace support +} // namespace relation +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_RELATION_SUPPORT_OPPOSITE_TAG_HPP + diff --git a/win32/include/boost/bimap/relation/support/pair_by.hpp b/win32/include/boost/bimap/relation/support/pair_by.hpp new file mode 100755 index 000000000..218172de7 --- /dev/null +++ b/win32/include/boost/bimap/relation/support/pair_by.hpp @@ -0,0 +1,120 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/support/pair_by.hpp +/// \brief pair_by(r) function + +#ifndef BOOST_BIMAP_RELATION_SUPPORT_PAIR_BY_HPP +#define BOOST_BIMAP_RELATION_SUPPORT_PAIR_BY_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +#ifdef BOOST_BIMAP_ONLY_DOXYGEN_WILL_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace relation { +namespace support { + +/** \brief Gets a pair view of the relation. + +\ingroup relation_group + **/ + +template< class Tag, class Relation > +BOOST_DEDUCED_TYPENAME result_of::pair_by::type + pair_by( Relation & rel ); + +} // namespace support +} // namespace relation +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_ONLY_DOXYGEN_WILL_PROCESS_THE_FOLLOWING_LINES + + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace relation { +namespace support { + + +// Since it is very error-prone to directly write the hole bunch +// of relation accesor. They are buil from litle macro blocks that +// are both more readable, leading to self docummenting code and a +// lot more easier to understand and mantain. +// It is very important to note that the three building blocks have +// to laid in the same namespace in order to work. There is also +// important to keep them in order. +// The forward declaration are not necesary but they help a lot to +// the reader, as they undercover what is the signature of the +// result code. +// In the end, it is not quicker to do it in this way because you +// write a lot. But this code has no complexity at all and almost +// every word writed is for documentation. + +// Result of +// ------------------------------------------------------------------------- +/* + namespace result_of { + + template< class Tag, class Relation > + struct pair_by; + { + typedef -unspecified- type; + }; + + } // namespace result_of +*/ + +BOOST_BIMAP_SYMMETRIC_ACCESS_RESULT_OF_BUILDER +( + pair_by, + pair_type_by +) + + + +// Implementation +// ------------------------------------------------------------------------- + +BOOST_BIMAP_SYMMETRIC_ACCESS_IMPLEMENTATION_BUILDER +( + pair_by, + Relation, + rel, + return rel.get_left_pair(), + return rel.get_right_pair() +) + +// Interface +// -------------------------------------------------------------------------- + +BOOST_BIMAP_SYMMETRIC_ACCESS_INTERFACE_BUILDER +( + pair_by +) + +} // namespace support +} // namespace relation +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_DOXIGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_RELATION_SUPPORT_PAIR_BY_HPP diff --git a/win32/include/boost/bimap/relation/support/pair_type_by.hpp b/win32/include/boost/bimap/relation/support/pair_type_by.hpp new file mode 100755 index 000000000..03fc9455b --- /dev/null +++ b/win32/include/boost/bimap/relation/support/pair_type_by.hpp @@ -0,0 +1,62 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/support/pair_type_by.hpp +/// \brief pair_type_by metafunction + +#ifndef BOOST_BIMAP_RELATION_SUPPORT_PAIR_TYPE_BY_HPP +#define BOOST_BIMAP_RELATION_SUPPORT_PAIR_TYPE_BY_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +/** \struct boost::bimaps::relation::support::pair_type_by + +\brief Metafunction to obtain the view type indexed by one of the sides. + +\code + +template< class Tag, class Relation > +struct pair_type_by +{ + typedef {signature-compatible with std::pair} type; +}; + +\endcode + +See also member_at, pair_by(). +\ingroup relation_group + **/ + +namespace boost { +namespace bimaps { +namespace relation { +namespace support { + +// Implementation of pair type by metafunction + +BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER +( + pair_type_by, + left_pair, + right_pair +) + +} // namespace support +} // namespace relation +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_RELATION_SUPPORT_PAIR_BY_TYPE_HPP + diff --git a/win32/include/boost/bimap/relation/support/value_type_of.hpp b/win32/include/boost/bimap/relation/support/value_type_of.hpp new file mode 100755 index 000000000..fb646549c --- /dev/null +++ b/win32/include/boost/bimap/relation/support/value_type_of.hpp @@ -0,0 +1,91 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/support/value_type_of.hpp +/// \brief value_type_of metafunction + +#ifndef BOOST_BIMAP_RELATION_SUPPORT_VALUE_TYPE_OF_HPP +#define BOOST_BIMAP_RELATION_SUPPORT_VALUE_TYPE_OF_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +/** \struct boost::bimaps::relation::support::value_type_of + +\brief Metafunction to obtain the value type of one of the sides. + +\code + +template< class Tag, class Relation > +struct value_type_of +{ + typedef typename Relation::{side}_type type; +}; + +\endcode + +See also member_at, get(). +\ingroup relation_group + **/ + +namespace boost { +namespace bimaps { +namespace relation { +namespace support { + +// Metafunction value_type_of +/* + + template< class Tag, class Relation > + struct value_type_of + { + typedef -unspecified- type; + }; + +*/ + +BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER +( + value_type_of, + left_value_type, + right_value_type +) + +// Add support for info tags to value_type_of + +template< class Tag, class SymmetricType > +struct value_type_of +< + Tag, SymmetricType, + BOOST_DEDUCED_TYPENAME enable_if + < + ::boost::bimaps::relation::support::is_tag_of_member_at_info + < + Tag, + SymmetricType + > + + >::type +> +{ + typedef BOOST_DEDUCED_TYPENAME SymmetricType::info_type type; +}; + +} // namespace support +} // namespace relation +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_RELATION_SUPPORT_VALUE_TYPE_OF_HPP + diff --git a/win32/include/boost/bimap/relation/symmetrical_base.hpp b/win32/include/boost/bimap/relation/symmetrical_base.hpp new file mode 100755 index 000000000..934aa04a8 --- /dev/null +++ b/win32/include/boost/bimap/relation/symmetrical_base.hpp @@ -0,0 +1,97 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file relation/symmetrical_base.hpp +/// \brief Base class for symmetrical types + +#ifndef BOOST_BIMAP_RELATION_SYMMETRICAL_BASE_HPP +#define BOOST_BIMAP_RELATION_SYMMETRICAL_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +// Boost.Bimap +#include +#include + +#include + + +namespace boost { +namespace bimaps { +namespace relation { + +/// \brief Base of symetrical tagged types. +/** + + **/ + +template< class TA, class TB, bool force_mutable = false > +class symmetrical_base +{ + + public: + + typedef BOOST_DEDUCED_TYPENAME tags::support::default_tagged + < + TA, + member_at::left + + >::type tagged_left_type; + + typedef BOOST_DEDUCED_TYPENAME tags::support::default_tagged + < + TB, + member_at::right + + >::type tagged_right_type; + + public: + + //@{ + /// The type stored in the relation + + typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< force_mutable, + + BOOST_DEDUCED_TYPENAME ::boost::remove_const< + BOOST_DEDUCED_TYPENAME tagged_left_type::value_type >::type, + BOOST_DEDUCED_TYPENAME tagged_left_type::value_type + + >::type left_value_type; + + typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< force_mutable, + + BOOST_DEDUCED_TYPENAME ::boost::remove_const< + BOOST_DEDUCED_TYPENAME tagged_right_type::value_type >::type, + BOOST_DEDUCED_TYPENAME tagged_right_type::value_type + + >::type right_value_type; + //@} + + //@{ + /// The tag of the member. By default it is \c member_at::{side} + typedef BOOST_DEDUCED_TYPENAME tagged_left_type ::tag left_tag; + typedef BOOST_DEDUCED_TYPENAME tagged_right_type::tag right_tag; + //@} +}; + + + +} // namespace relation +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_RELATION_SYMMETRICAL_BASE_HPP + diff --git a/win32/include/boost/bimap/set_of.hpp b/win32/include/boost/bimap/set_of.hpp new file mode 100755 index 000000000..5c8d8e8ea --- /dev/null +++ b/win32/include/boost/bimap/set_of.hpp @@ -0,0 +1,206 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file set_of.hpp +/// \brief Include support for set constrains for the bimap container + +#ifndef BOOST_BIMAP_SET_OF_HPP +#define BOOST_BIMAP_SET_OF_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +namespace boost { +namespace bimaps { + +/// \brief Set Type Specification +/** +This struct is used to specify a set specification. +It is not a container, it is just a metaprogramming facility to +express the type of a set. Generally, this specification will +be used in other place to create a container. +It has the same syntax that an std::set instantiation, except +that the allocator cannot be specified. The rationale behind +this difference is that the allocator is not part of the set +type specification, rather it is a container configuration +parameter. +The first parameter is the type of the objects in the set, and +the second one is a Functor that compares them. +Bimap binding metafunctions can be used with this class in +the following way: + +\code +using namespace support; + +BOOST_STATIC_ASSERT( is_set_type_of< set_of >::value ) + +BOOST_STATIC_ASSERT +( + is_same + < + set_of::index_bind + < + KeyExtractor, + Tag + + >::type, + + ordered_unique< tag, KeyExtractor, KeyCompare > + + >::value +) + +typedef bimap +< + set_of, RightKeyType + +> bimap_with_left_type_as_set; + +BOOST_STATIC_ASSERT +( + is_same + < + set_of::map_view_bind + < + member_at::left, + bimap_with_left_type_as_set + + >::type, + + map_view< member_at::left, bimap_with_left_type_as_set > + + >::value +) + +\endcode + +See also set_of_relation. + **/ + +template +< + class KeyType, + class KeyCompare = std::less< BOOST_DEDUCED_TYPENAME + ::boost::bimaps::tags::support::value_type_of::type > +> +struct set_of : public ::boost::bimaps::detail::set_type_of_tag +{ + /// User type, can be tagged + typedef KeyType user_type; + + /// Type of the object that will be stored in the set + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support:: + value_type_of::type value_type; + + /// Functor that compare two keys + typedef KeyCompare key_compare; + + struct lazy_concept_checked + { + BOOST_CLASS_REQUIRE ( value_type, + boost, AssignableConcept ); + + BOOST_CLASS_REQUIRE4( key_compare, bool, value_type, value_type, + boost, BinaryFunctionConcept ); + + typedef set_of type; + }; + + BOOST_BIMAP_GENERATE_INDEX_BINDER_1CP( + + // binds to + multi_index::ordered_unique, + + // with + key_compare + ) + + BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER( + + // binds to + views::map_view + ) + + BOOST_BIMAP_GENERATE_SET_VIEW_BINDER( + + // binds to + views::set_view + ) + + typedef mpl::bool_ mutable_key; +}; + + +/// \brief Set Of Relation Specification +/** +This struct is similar to set_of but it is bind logically to a +relation. It is used in the bimap instantiation to specify the +desired type of the main view. This struct implements internally +a metafunction named bind_to that manages the quite complicated +task of finding the right type of the set for the relation. + +\code +template +struct bind_to +{ + typedef -unspecified- type; +}; +\endcode + +See also set_of, is_set_type_of_relation. + **/ + +template< class KeyCompare = std::less< _relation > > +struct set_of_relation : public ::boost::bimaps::detail::set_type_of_relation_tag +{ + /// Functor that compare two keys + typedef KeyCompare key_compare; + + BOOST_BIMAP_GENERATE_RELATION_BINDER_1CP( + + // binds to + set_of, + + // with + key_compare + ) + + typedef mpl::bool_ left_mutable_key; + typedef mpl::bool_ right_mutable_key; +}; + +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_SET_OF_HPP + diff --git a/win32/include/boost/bimap/support/data_type_by.hpp b/win32/include/boost/bimap/support/data_type_by.hpp new file mode 100755 index 000000000..c979c78c1 --- /dev/null +++ b/win32/include/boost/bimap/support/data_type_by.hpp @@ -0,0 +1,73 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file support/data_type_by.hpp +/// \brief Metafunction to access the data types of a bimap + +#ifndef BOOST_BIMAP_SUPPORT_DATA_TYPE_BY_HPP +#define BOOST_BIMAP_SUPPORT_DATA_TYPE_BY_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +/** \struct boost::bimaps::support::data_type_by + +\brief Metafunction to obtain the data type of one of the sides in a bimap + +The tag parameter can be either a user defined tag or \c member_at::{side}. +This is the actual data type stored in the bimap. +\code + +template< class Tag, class Bimap > +struct data_type_by +{ + typedef typename Bimap::{side}_data_type type; +}; + +\endcode + +The following holds: + +\code + +BOOST_STATIC_ASSERT +( + is_same< data_type_by< member_at::left, bimap >::type, A >::value +) + +\endcode + +See also member_at. +\ingroup bimap_group + **/ + +namespace boost { +namespace bimaps { +namespace support { + +// Implementation of data type of metafunction + +BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER +( + data_type_by, + left_data_type, + right_data_type +) + +} // namespace support +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_SUPPORT_DATA_TYPE_BY_HPP + diff --git a/win32/include/boost/bimap/support/iterator_type_by.hpp b/win32/include/boost/bimap/support/iterator_type_by.hpp new file mode 100755 index 000000000..3d7f0907f --- /dev/null +++ b/win32/include/boost/bimap/support/iterator_type_by.hpp @@ -0,0 +1,228 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file support/iterator_type_by.hpp +/// \brief Metafunctions to access the iterator types of a bimap + +#ifndef BOOST_BIMAP_SUPPORT_ITERATOR_TYPE_BY_HPP +#define BOOST_BIMAP_SUPPORT_ITERATOR_TYPE_BY_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +#include + +#include + +/** \struct boost::bimaps::support::iterator_type_by + +\brief Metafunction to obtain the iterator type of the map view by one of the sides. + +\code + +template< class Tag, class Bimap > +struct iterator_type_by +{ + typedef -unspecified- type; +}; + +template< class Tag, class Bimap > +struct const_iterator_type_by +{ + typedef -unspecified- type; +}; + +template< class Tag, class Bimap > +struct reverse_iterator_type_by +{ + typedef -unspecified- type; +}; + +template< class Tag, class Bimap > +struct const_reverse_iterator_type_by +{ + typedef -unspecified- type; +}; + +template< class Tag, class Bimap > +struct local_iterator_type_by +{ + typedef -unspecified- type; +}; + +template< class Tag, class Bimap > +struct const_local_iterator_type_by +{ + typedef -unspecified- type; +}; + +\endcode + +See also member_at. +\ingroup bimap_group + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace support { + + +// Implementation of iterator type by metafunction + +BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER +( + iterator_type_by, + left_iterator, + right_iterator +) + +// Implementation of const iterator type by metafunction + +BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER +( + const_iterator_type_by, + left_const_iterator, + right_const_iterator +) + + +// Implementation of reverse iterator type by metafunction + +BOOST_BIMAP_SYMMETRIC_STATIC_ACCESS_BUILDER +( + core_reverse_iterator_type_by, + BimapCore, + + typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE + index + ::type::reverse_iterator type, + + typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE + index + ::type::reverse_iterator type +) + +template< class Tag, class BimapCore > +struct reverse_iterator_type_by +{ + typedef ::boost::bimaps::detail::map_view_iterator + < + Tag, + BOOST_DEDUCED_TYPENAME BimapCore::relation, + BOOST_DEDUCED_TYPENAME core_reverse_iterator_type_by::type + + > type; +}; + +// Implementation of const reverse iterator type by metafunction + +BOOST_BIMAP_SYMMETRIC_STATIC_ACCESS_BUILDER +( + core_const_reverse_iterator_type_by, + BimapCore, + + typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE + index + ::type::const_reverse_iterator type, + + typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE + index + ::type::const_reverse_iterator type +) + +template< class Tag, class BimapCore > +struct const_reverse_iterator_type_by +{ + + typedef ::boost::bimaps::detail::map_view_iterator + < + Tag, + BOOST_DEDUCED_TYPENAME BimapCore::relation, + BOOST_DEDUCED_TYPENAME core_const_reverse_iterator_type_by::type + + > type; +}; + + +// Implementation of local iterator type by metafunction + +BOOST_BIMAP_SYMMETRIC_STATIC_ACCESS_BUILDER +( + core_local_iterator_type_by, + BimapCore, + + typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE + index + ::type::local_iterator type, + + typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE + index + ::type::local_iterator type +) + + +template< class Tag, class BimapCore > +struct local_iterator_type_by +{ + + typedef ::boost::bimaps::detail::map_view_iterator + < + Tag, + BOOST_DEDUCED_TYPENAME BimapCore::relation, + BOOST_DEDUCED_TYPENAME core_local_iterator_type_by::type + + > type; +}; + + +// Implementation of const local iterator type by metafunction + +BOOST_BIMAP_SYMMETRIC_STATIC_ACCESS_BUILDER +( + core_const_local_iterator_type_by, + BimapCore, + + typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE + index + ::type::const_local_iterator type, + + typedef BOOST_DEDUCED_TYPENAME BimapCore::core_type::BOOST_NESTED_TEMPLATE + index + ::type::const_local_iterator type +) + +template< class Tag, class BimapCore > +struct const_local_iterator_type_by +{ + + typedef ::boost::bimaps::detail::map_view_iterator + < + Tag, + BOOST_DEDUCED_TYPENAME BimapCore::relation, + BOOST_DEDUCED_TYPENAME core_const_local_iterator_type_by::type + + > type; +}; + + +} // namespace support +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_SUPPORT_ITERATOR_TYPE_BY_HPP + diff --git a/win32/include/boost/bimap/support/key_type_by.hpp b/win32/include/boost/bimap/support/key_type_by.hpp new file mode 100755 index 000000000..e98b074c7 --- /dev/null +++ b/win32/include/boost/bimap/support/key_type_by.hpp @@ -0,0 +1,64 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file support/key_type_by.hpp +/// \brief Metafunction to access the set types of a bimap + +#ifndef BOOST_BIMAP_SUPPORT_KEY_TYPE_BY_HPP +#define BOOST_BIMAP_SUPPORT_KEY_TYPE_BY_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +/** \struct boost::bimaps::support::key_type_by + +\brief Metafunction to obtain the key type of one of the sides in a bimap + +The tag parameter can be either a user defined tag or \c member_at::{side}. +The returned type is one of the {SetType}_of definition classes. + +\code + +template< class Tag, class Bimap > +struct key_type_by +{ + typedef typename Bimap::{side}_key_type type; +}; + +\endcode + +See also member_at. +\ingroup bimap_group + **/ + + +namespace boost { +namespace bimaps { +namespace support { + +// Implementation of key type type of metafunction + +BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER +( + key_type_by, + left_key_type, + right_key_type +) + + +} // namespace support +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_SUPPORT_KEY_TYPE_BY_HPP + diff --git a/win32/include/boost/bimap/support/lambda.hpp b/win32/include/boost/bimap/support/lambda.hpp new file mode 100755 index 000000000..60f946b4f --- /dev/null +++ b/win32/include/boost/bimap/support/lambda.hpp @@ -0,0 +1,46 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file support/lambda.hpp +/// \brief Placeholders definition to help in bimap modify function + +#ifndef BOOST_BIMAP_SUPPORT_LAMBDA_HPP +#define BOOST_BIMAP_SUPPORT_LAMBDA_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +namespace boost { +namespace bimaps { + +namespace { + +/* +boost::lambda::placeholder1_type & _first = boost::lambda::_1; +boost::lambda::placeholder2_type & _second = boost::lambda::_2; + +boost::lambda::placeholder1_type & _left = boost::lambda::_1; +boost::lambda::placeholder2_type & _right = boost::lambda::_2; +*/ + +boost::lambda::placeholder1_type & _key = boost::lambda::_1; +boost::lambda::placeholder1_type & _data = boost::lambda::_1; + +} + +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_SUPPORT_LAMBDA_HPP + diff --git a/win32/include/boost/bimap/support/map_by.hpp b/win32/include/boost/bimap/support/map_by.hpp new file mode 100755 index 000000000..6b6d69b0d --- /dev/null +++ b/win32/include/boost/bimap/support/map_by.hpp @@ -0,0 +1,132 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file support/map_by.hpp +/// \brief map_by(b) function + +#ifndef BOOST_BIMAP_SUPPORT_MAP_BY_HPP +#define BOOST_BIMAP_SUPPORT_MAP_BY_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + + +#ifdef BOOST_BIMAP_ONLY_DOXYGEN_WILL_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace support { + +/** \brief Gets a map view of a bidirectional map + +Convertible to \c map_type_by::type +Instead of using \c map_type_by::type this functions use +\b Boost.call_traits to find the best way to return this value. To help +the user of this function the following metafunction is provided +\code + +namespace result_of { + +template< class Tag, class Bimap > +struct map_by( Bimap & b ); + +} // namespace result_of + +\endcode + +See also member_at, value_type_of. +\ingroup bimap_group + **/ + +template< class Tag, class Bimap > +BOOST_DEDUCED_TYPENAME result_of::map_by::type + map_by( Bimap & b ); + +} // namespace support +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_ONLY_DOXYGEN_WILL_PROCESS_THE_FOLLOWING_LINES + + + +#ifndef BOOST_BIMAP_DOXIGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace support { + +// Since it is very error-prone to directly write the hole bunch +// of relation accesor. They are buil from litle macro blocks that +// are both more readable, leading to self docummenting code and a +// lot more easier to understand and mantain. +// It is very important to note that the three building blocks have +// to laid in the same namespace in order to work. There is also +// important to keep them in order. +// The forward declaration are not necesary but they help a lot to +// the reader, as they undercover what is the signature of the +// result code. +// In the end, it is not quicker to do it in this way because you +// write a lot. But this code has no complexity at all and almost +// every word writed is for documentation. + +// Result of +// ------------------------------------------------------------------------- +/* + namespace result_of { + + template< class Tag, class Bimap > + struct map_by; + { + typedef -unspecified- type; + }; + + } // namespace result_of + +*/ + +BOOST_BIMAP_SYMMETRIC_ACCESS_RESULT_OF_BUILDER +( + map_by, + map_type_by +) + +// Implementation +// ------------------------------------------------------------------------- + +BOOST_BIMAP_SYMMETRIC_ACCESS_IMPLEMENTATION_BUILDER +( + map_by, + Bimap, + b, + return b.left, + return b.right +) + +// Interface +// -------------------------------------------------------------------------- + +BOOST_BIMAP_SYMMETRIC_ACCESS_INTERFACE_BUILDER +( + map_by +) + +} // namespace support +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DOXIGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_SUPPORT_MAP_BY_HPP + diff --git a/win32/include/boost/bimap/support/map_type_by.hpp b/win32/include/boost/bimap/support/map_type_by.hpp new file mode 100755 index 000000000..57e4831a0 --- /dev/null +++ b/win32/include/boost/bimap/support/map_type_by.hpp @@ -0,0 +1,65 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file support/map_type_by.hpp +/// \brief Metafunction to access the map view types of a bimap + +#ifndef BOOST_BIMAP_SUPPORT_MAP_TYPE_BY_HPP +#define BOOST_BIMAP_SUPPORT_MAP_TYPE_BY_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +/** \struct boost::bimaps::support::map_type_by + +\brief Metafunction to obtain the map view type of a bimap indexed by one of the sides. + +The tag parameter can be either a user defined tag or \c member_at::{side}. +The returned type is signature-compatible with std::pair. + +\code + +template< class Tag, class Bimap > +struct map_type_by +{ + typedef typename Bimap::{side}_map_type type; +}; + +\endcode + +See also member_at. +\ingroup bimap_group + **/ + +namespace boost { +namespace bimaps { +namespace support { + +// Implementation of map type by metafunction + +BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER +( + map_type_by, + left_map, + right_map +) + + + +} // namespace support +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_SUPPORT_MAP_TYPE_BY_HPP + diff --git a/win32/include/boost/bimap/support/value_type_by.hpp b/win32/include/boost/bimap/support/value_type_by.hpp new file mode 100755 index 000000000..9c1e7d9dc --- /dev/null +++ b/win32/include/boost/bimap/support/value_type_by.hpp @@ -0,0 +1,65 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file support/value_type_by.hpp +/// \brief Metafunction to access the value types (std::pair compatibles) of a bimap + +#ifndef BOOST_BIMAP_SUPPORT_VALUE_TYPE_BY_HPP +#define BOOST_BIMAP_SUPPORT_VALUE_TYPE_BY_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +/** \struct boost::bimaps::support::value_type_by + +\brief Metafunction to obtain the value type of a bimap indexed by one of the sides. + +The tag parameter can be either a user defined tag or \c member_at::{side}. +The returned type is signature-compatible with std::pair. + +\code + +template< class Tag, class Bimap > +struct value_type_by +{ + typedef typename Bimap::{side}_value_type type; +}; + +\endcode + +See also member_at. +\ingroup bimap_group + **/ + +namespace boost { +namespace bimaps { +namespace support { + +// Implementation of value type by metafunction + +BOOST_BIMAP_SYMMETRIC_METADATA_ACCESS_BUILDER +( + value_type_by, + left_value_type, + right_value_type +) + + + +} // namespace support +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_SUPPORT_VALUE_TYPE_BY_HPP + diff --git a/win32/include/boost/bimap/tags/support/apply_to_value_type.hpp b/win32/include/boost/bimap/tags/support/apply_to_value_type.hpp new file mode 100755 index 000000000..88249db33 --- /dev/null +++ b/win32/include/boost/bimap/tags/support/apply_to_value_type.hpp @@ -0,0 +1,70 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file tags/support/apply_to_value_type.hpp +/// \brief Similar to mpl::apply but for tagged types. + +#ifndef BOOST_BIMAP_TAGS_SUPPORT_APPLY_TO_VALUE_TYPE_HPP +#define BOOST_BIMAP_TAGS_SUPPORT_APPLY_TO_VALUE_TYPE_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +/** \struct boost::bimaps::tags::support::apply_to_value_type +\brief Higger order metafunction similar to mpl::apply but for tagged types. + +\code +template< class Metafunction, class TaggedType > +struct apply_to_value_type +{ + typedef tagged + < + Metafuntion< value_type_of< TaggedType >::type >::type, + tag_of< TaggedType >::type + + > type; +}; +\endcode + +This higher order metafunctions is very useful, and it can be used with lambda +expresions. + +See also tagged. + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace tags { +namespace support { + +template < class F, class TaggedType > +struct apply_to_value_type; + +template < class F, class ValueType, class Tag > +struct apply_to_value_type > +{ + typedef BOOST_DEDUCED_TYPENAME mpl::apply< F, ValueType >::type new_value_type; + typedef tagged< new_value_type, Tag > type; +}; + +} // namespace support +} // namespace tags +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_TAGS_SUPPORT_APPLY_TO_VALUE_TYPE_HPP diff --git a/win32/include/boost/bimap/tags/support/default_tagged.hpp b/win32/include/boost/bimap/tags/support/default_tagged.hpp new file mode 100755 index 000000000..46fa72e5c --- /dev/null +++ b/win32/include/boost/bimap/tags/support/default_tagged.hpp @@ -0,0 +1,73 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file tags/support/default_tagged.hpp +/// \brief Weak tagging + +#ifndef BOOST_BIMAP_TAGS_SUPPORT_DEFAULT_TAGGED_HPP +#define BOOST_BIMAP_TAGS_SUPPORT_DEFAULT_TAGGED_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +/** \struct boost::bimaps::tags::support::default_tagged +\brief Weak tagging metafunction + +\code +template< class Type, class Tag > +struct default_tagged +{ + typedef {TaggedType} type; +}; +\endcode + +If the type is not tagged, this metafunction returns a tagged type with the +default tag. If it is tagged, the returns the type unchanged. + +See also tagged, overwrite_tagged. + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace tags { +namespace support { + + +// Default Tagging +// A metafunction that create a tagged type with a default tag value. + +template< class Type, class DefaultTag > +struct default_tagged +{ + typedef tagged type; +}; + +template< class Type, class OldTag, class NewTag > +struct default_tagged< tagged< Type, OldTag >, NewTag > +{ + typedef tagged type; +}; + +} // namespace support +} // namespace tags +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_TAGS_SUPPORT_DEFAULT_TAGGED_HPP + + + diff --git a/win32/include/boost/bimap/tags/support/is_tagged.hpp b/win32/include/boost/bimap/tags/support/is_tagged.hpp new file mode 100755 index 000000000..35e25990f --- /dev/null +++ b/win32/include/boost/bimap/tags/support/is_tagged.hpp @@ -0,0 +1,64 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file tags/support/is_tagged.hpp +/// \brief type_traits extension + +#ifndef BOOST_BIMAP_TAGS_SUPPORT_IS_TAGGED_HPP +#define BOOST_BIMAP_TAGS_SUPPORT_IS_TAGGED_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +/** \struct boost::bimaps::tags::support::is_tagged +\brief Type trait to check if a type is tagged. + +\code +template< class Type > +struct is_tagged +{ + typedef {mpl::true_/mpl::false_} type; +}; +\endcode + +See also tagged. + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace tags { +namespace support { + + +// is_tagged metafunction + +template< class Type > +struct is_tagged : + ::boost::mpl::false_ {}; + +template< class Type, class Tag > +struct is_tagged< tagged< Type, Tag > > : + ::boost::mpl::true_ {}; + +} // namespace support +} // namespace tags +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_TAGS_SUPPORT_IS_TAGGED_HPP + diff --git a/win32/include/boost/bimap/tags/support/overwrite_tagged.hpp b/win32/include/boost/bimap/tags/support/overwrite_tagged.hpp new file mode 100755 index 000000000..de21b1c12 --- /dev/null +++ b/win32/include/boost/bimap/tags/support/overwrite_tagged.hpp @@ -0,0 +1,73 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file tags/support/overwrite_tagged.hpp +/// \brief Hard tagging + +#ifndef BOOST_BIMAP_TAGS_SUPPORT_OVERWRITE_TAGGED_HPP +#define BOOST_BIMAP_TAGS_SUPPORT_OVERWRITE_TAGGED_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +/** \struct boost::bimaps::tags::support::overwrite_tagged +\brief Hard tagging metafunction + +\code +template< class Type, class Tag > +struct overwrite_tagged +{ + typedef {TaggedType} type; +}; +\endcode + +If the type is not tagged, this metafunction returns a tagged type with the +passed tag. If it is tagged it returns a new tagged type with the tag replaced +by the one passed as a parameter. + +See also tagged, default_tagged. + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace tags { +namespace support { + + +// Change the tag + +template< class Type, class NewTag > +struct overwrite_tagged +{ + typedef tagged type; +}; + +template< class Type, class OldTag, class NewTag > +struct overwrite_tagged< tagged< Type, OldTag >, NewTag > +{ + typedef tagged type; +}; + + +} // namespace support +} // namespace tags +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_TAGS_SUPPORT_OVERWRITE_TAGGED_HPP + + diff --git a/win32/include/boost/bimap/tags/support/tag_of.hpp b/win32/include/boost/bimap/tags/support/tag_of.hpp new file mode 100755 index 000000000..8e67f0a5f --- /dev/null +++ b/win32/include/boost/bimap/tags/support/tag_of.hpp @@ -0,0 +1,75 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file tags/support/tag_of.hpp +/// \brief Safe way to acces the tag of a type + +#ifndef BOOST_BIMAP_TAGS_SUPPORT_TAG_OF_HPP +#define BOOST_BIMAP_TAGS_SUPPORT_TAG_OF_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +/** \struct boost::bimaps::tags::support::tag_of +\brief Metafunction to obtain the tag of a type. + +\code +template< class TaggedType > +struct tag_of +{ + typedef {Tag} type; +}; +\endcode + +If the type is not tagged you will get a compile timer error with the following message: + +\verbatim +USING_TAG_OF_WITH_AN_UNTAGGED_TYPE, TaggedType +\endverbatim + +See also tagged, value_type_of. + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace boost { +namespace bimaps { +namespace tags { +namespace support { + + +// tag_of metafunction + +template< class Type > +struct tag_of +{ + BOOST_BIMAP_STATIC_ERROR( USING_TAG_OF_WITH_AN_UNTAGGED_TYPE, (Type) ); +}; + +template< class Type, class Tag > +struct tag_of< tagged< Type, Tag > > +{ + typedef Tag type; +}; + + +} // namespace support +} // namespace tags +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_TAGS_SUPPORT_TAG_OF_HPP + diff --git a/win32/include/boost/bimap/tags/support/value_type_of.hpp b/win32/include/boost/bimap/tags/support/value_type_of.hpp new file mode 100755 index 000000000..f79175293 --- /dev/null +++ b/win32/include/boost/bimap/tags/support/value_type_of.hpp @@ -0,0 +1,74 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file tags/support/value_type_of.hpp +/// \brief Consistent way to access the value type of a tagged or untagged type. + +#ifndef BOOST_BIMAP_TAGS_SUPPORT_VALUE_TYPE_OF_HPP +#define BOOST_BIMAP_TAGS_SUPPORT_VALUE_TYPE_OF_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +/** \struct boost::bimaps::tags::support::value_type_of +\brief Metafunction to work with tagged and untagged type uniformly + +\code +template< class Type > +struct value_type_of +{ + typedef {UntaggedType} type; +}; +\endcode + +If the type is tagged this metafunction returns Type::value_type, and if it is not +tagged it return the same type. This allows to work consistenly with tagged and +untagged types. + +See also tagged, tag_of. + **/ + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + + +namespace boost { +namespace bimaps { +namespace tags { +namespace support { + + +// value_type_of metafunction + +template< class Type > +struct value_type_of +{ + typedef Type type; +}; + +template< class Type, class Tag > +struct value_type_of< tagged< Type, Tag > > +{ + typedef Type type; +}; + + +} // namespace support +} // namespace tags +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +#endif // BOOST_BIMAP_TAGS_SUPPORT_VALUE_TYPE_OF_HPP + + diff --git a/win32/include/boost/bimap/tags/tagged.hpp b/win32/include/boost/bimap/tags/tagged.hpp new file mode 100755 index 000000000..7786d1014 --- /dev/null +++ b/win32/include/boost/bimap/tags/tagged.hpp @@ -0,0 +1,107 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file tags/tagged.hpp +/// \brief Defines the tagged class + +#ifndef BOOST_BIMAP_TAGS_TAGGED_HPP +#define BOOST_BIMAP_TAGS_TAGGED_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +namespace boost { +namespace bimaps { + +/// \brief A light non-invasive idiom to tag a type. +/** + +There are a lot of ways of tagging a type. The standard library for example +defines tags (empty structs) that are then inherited by the tagged class. To +support built-in types and other types that simple cannot inherit from the +tag, the standard builds another level of indirection. An example of this is +the type_traits metafunction. This approach is useful if the tags are intended +to be used in the library internals, and if the user does not have to create +new tagged types often. + +Boost.MultiIndex is an example of a library that defines a tagged idiom that +is better suited to the user. As an option, in the indexed by declaration +of a multi-index container a user can \b attach a tag to each index, so it +can be referred by it instead of by the index number. It is a very user +friendly way of specifying a tag but is very invasive from the library writer's +point of view. Each index must now support this additional parameter. Maybe +not in the case of the multi-index container, but in simpler classes +the information of the tags is used by the father class rather than by the +tagged types. + +\b tagged is a light non-invasive idiom to tag a type. It is very intuitive +and user-friendly. With the use of the defined metafunctions the library +writer can enjoy the coding too. + + **/ + +namespace tags { + +/// \brief The tag holder +/** + +The idea is to add a level of indirection to the type being tagged. With this +class you wrapped a type and apply a tag to it. The only thing to remember is +that if you write + +\code +typedef tagged taggedType; +\endcode + +Then instead to use directly the tagged type, in order to access it you have +to write \c taggedType::value_type. The tag can be obtained using \c taggedType::tag. +The idea is not to use this metadata directly but rather using the metafunctions +that are defined in the support namespace. With this metafunctions you can work +with tagged and untagged types in a consistent way. For example, the following +code is valid: + +\code +BOOST_STATIC_ASSERT( is_same< value_type_of, value_type_of >::value ); +\endcode + +The are other useful metafunctions there too. +See also value_type_of, tag_of, is_tagged, apply_to_value_type. + +\ingroup tagged_group + **/ +template< class Type, class Tag > +struct tagged +{ + typedef Type value_type; + typedef Tag tag; +}; + +} // namespace tags +} // namespace bimaps +} // namespace boost + +/** \namespace boost::bimaps::tags::support +\brief Metafunctions to work with tagged types. + +This metafunctions aims to make easier the manage of tagged types. They are all mpl +compatible metafunctions and can be used with lambda expresions. +The metafunction value_type_of and tag_of get the data in a tagged type in a secure +and consistent way. +default_tagged and overwrite_tagged allows to work with the tag of a tagged type, +and apply_to_value_type is a higher order metafunction that allow the user to change +the type of a TaggedType. + **/ + +#endif // BOOST_BIMAP_TAGS_TAGGED_HPP + + + + diff --git a/win32/include/boost/bimap/unconstrained_set_of.hpp b/win32/include/boost/bimap/unconstrained_set_of.hpp new file mode 100755 index 000000000..ffba2f913 --- /dev/null +++ b/win32/include/boost/bimap/unconstrained_set_of.hpp @@ -0,0 +1,150 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file unconstrained_set_of.hpp +/// \brief Include support for set constrains for the bimap container + +#ifndef BOOST_BIMAP_UNCONSTRAINED_SET_OF_HPP +#define BOOST_BIMAP_UNCONSTRAINED_SET_OF_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +#include + +#include + +#include + +#include + +#include +#include +#include + +#include +#include + +namespace boost { +namespace bimaps { + +/// \brief Set Type Specification +/** +This struct is used to specify a set specification. +It is not a container, it is just a metaprogramming facility to +express the type of a set. Generally, this specification will +be used in other place to create a container. +The first parameter is the type of the objects in the set. + +\code + +using namespace support; + +BOOST_STATIC_ASSERT( is_set_type_of< unconstrained_set_of >::value ) + +\endcode + +See also unconstrained_set_of_relation. + **/ + +template +< + class KeyType +> +struct unconstrained_set_of : public ::boost::bimaps::detail::set_type_of_tag +{ + /// User type, can be tagged + typedef KeyType user_type; + + /// Type of the object that will be stored in the container + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support:: + value_type_of::type value_type; + + struct lazy_concept_checked + { + BOOST_CLASS_REQUIRE ( value_type, + boost, AssignableConcept ); + + typedef unconstrained_set_of type; + }; + + BOOST_BIMAP_GENERATE_INDEX_BINDER_FAKE + + BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER( + + // binds to + views::unconstrained_map_view + ) + + BOOST_BIMAP_GENERATE_SET_VIEW_BINDER( + + // binds to + views::unconstrained_set_view + ) + + typedef mpl::bool_ mutable_key; +}; + +/// \brief Set Of Relation Specification +/** +This struct is similar to unconstrained_set_of but it is bind +logically to a relation. It is used in the bimap instantiation to +specify the desired type of the main view. + +See also unconstrained_set_of, is_set_type_of_relation. + **/ + +struct unconstrained_set_of_relation : public ::boost::bimaps::detail::set_type_of_relation_tag +{ + + BOOST_BIMAP_GENERATE_RELATION_BINDER_0CP( + + // binds to + unconstrained_set_of + ) + + typedef mpl::bool_ left_mutable_key; + typedef mpl::bool_ right_mutable_key; +}; + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +namespace detail { + +template +struct is_unconstrained_set_of : + ::boost::mpl::false_ {}; + +template +struct is_unconstrained_set_of< unconstrained_set_of > : + ::boost::mpl::true_ {}; + +} // namespace detail + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +} // namespace bimaps +} // namespace boost + + +/** \struct boost::bimaps::detail::is_unconstrained_set_of +\brief Trait to check if a type is unconstrained_set_of. +\code +template< class T > +struct is_unconstrained_set_of; +\endcode + **/ + + +#endif // BOOST_BIMAP_UNCONSTRAINED_SET_OF_HPP + diff --git a/win32/include/boost/bimap/unordered_multiset_of.hpp b/win32/include/boost/bimap/unordered_multiset_of.hpp new file mode 100755 index 000000000..a8ebc8246 --- /dev/null +++ b/win32/include/boost/bimap/unordered_multiset_of.hpp @@ -0,0 +1,233 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file unordered_multiset_of.hpp +/// \brief Include support for unordered_multiset constrains for the bimap container + +#ifndef BOOST_BIMAP_UNORDERED_MULTISET_OF_HPP +#define BOOST_BIMAP_UNORDERED_MULTISET_OF_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +namespace boost { +namespace bimaps { + + +/// \brief Set Type Specification +/** +This struct is used to specify an unordered_multiset specification. +It is not a container, it is just a metaprogramming facility to +express the type of a set. Generally, this specification will +be used in other place to create a container. +It has the same syntax that an tr1::unordered_multiset instantiation, +except that the allocator cannot be specified. The rationale behind +this difference is that the allocator is not part of the +unordered_multiset type specification, rather it is a container +configuration parameter. +The first parameter is the type of the objects in the set, the +second one is a Hash Functor that takes objects of this type, and +the third one is a Functor that compares them for equality. +Bimap binding metafunctions can be used with this class in +the following way: + +\code +using namespace support; + +BOOST_STATIC_ASSERT( is_set_type_of< unordered_multiset_of >::value ) + +BOOST_STATIC_ASSERT +( + is_same + < + compute_index_type + < + unordered_multiset_of, + KeyExtractor, + Tag + + >::type + , + hashed_nonunique< tag, KeyExtractor, HashFunctor, EqualKey > + + >::value +) + +typedef bimap +< + unordered_multiset_of, RightKeyType + +> bimap_with_left_type_as_unordered_multiset; + +BOOST_STATIC_ASSERT +( + is_same + < + compute_map_view_type + < + member_at::left, + bimap_with_left_type_as_unordered_multiset + + >::type, + + unordered_multimap_view + < + member_at::left, + bimap_with_left_type_as_unordered_multiset + > + + >::value +) + +\endcode + +See also unordered_multiset_of_relation. + **/ + +template +< + class KeyType, + class HashFunctor = hash< BOOST_DEDUCED_TYPENAME + ::boost::bimaps::tags::support::value_type_of::type >, + class EqualKey = std::equal_to< BOOST_DEDUCED_TYPENAME + ::boost::bimaps::tags::support::value_type_of::type > +> +struct unordered_multiset_of : public ::boost::bimaps::detail::set_type_of_tag +{ + /// User type, can be tagged + typedef KeyType user_type; + + /// Type of the object that will be stored in the container + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support:: + value_type_of::type value_type; + + /// Hash Functor that takes value_type objects + typedef HashFunctor hasher; + + /// Functor that compare two value_type objects for equality + typedef EqualKey key_equal; + + struct lazy_concept_checked + { + BOOST_CLASS_REQUIRE ( value_type, + boost, AssignableConcept ); + + BOOST_CLASS_REQUIRE3( hasher, std::size_t, value_type, + boost, UnaryFunctionConcept ); + + BOOST_CLASS_REQUIRE4( key_equal, bool, value_type, value_type, + boost, BinaryFunctionConcept ); + + typedef unordered_multiset_of type; + }; + + BOOST_BIMAP_GENERATE_INDEX_BINDER_2CP( + + // binds to + multi_index::hashed_non_unique, + + // with + hasher, + key_equal + ) + + BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER( + + // binds to + views::unordered_multimap_view + ) + + BOOST_BIMAP_GENERATE_SET_VIEW_BINDER( + + // binds to + views::unordered_multiset_view + ) + + typedef mpl::bool_ mutable_key; +}; + + +/// \brief Set Of Relation Specification +/** +This struct is similar to unordered_multiset_of but it is bind logically +to a relation. It is used in the bimap instantiation to specify the +desired type of the main view. This struct implements internally +a metafunction named bind_to that manages the quite complicated +task of finding the right type of the set for the relation. + +\code +template +struct bind_to +{ + typedef -unspecified- type; +}; +\endcode + +See also unordered_multiset_of, is_set_type_of_relation. + **/ + +template +< + class HashFunctor = hash< _relation >, + class EqualKey = std::equal_to< _relation > +> +struct unordered_multiset_of_relation : public ::boost::bimaps::detail::set_type_of_relation_tag +{ + /// Hash Functor that takes value_type objects + typedef HashFunctor hasher; + + /// Functor that compare two value_type objects for equality + typedef EqualKey key_equal; + + + BOOST_BIMAP_GENERATE_RELATION_BINDER_2CP( + + // binds to + unordered_multiset_of, + + // with + hasher, + key_equal + ) + + typedef mpl::bool_ left_mutable_key; + typedef mpl::bool_ right_mutable_key; +}; + + +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_UNORDERED_MULTISET_OF_HPP + diff --git a/win32/include/boost/bimap/unordered_set_of.hpp b/win32/include/boost/bimap/unordered_set_of.hpp new file mode 100755 index 000000000..034df3d7a --- /dev/null +++ b/win32/include/boost/bimap/unordered_set_of.hpp @@ -0,0 +1,230 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file unordered_set_of.hpp +/// \brief Include support for unordered_set constrains for the bimap container + +#ifndef BOOST_BIMAP_UNORDERED_SET_OF_HPP +#define BOOST_BIMAP_UNORDERED_SET_OF_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +namespace boost { +namespace bimaps { + +/// \brief Set Type Specification +/** +This struct is used to specify an unordered_set specification. +It is not a container, it is just a metaprogramming facility to +express the type of a set. Generally, this specification will +be used in other place to create a container. +It has the same syntax that an tr1::unordered_set instantiation, +except that the allocator cannot be specified. The rationale behind +this difference is that the allocator is not part of the +unordered_set type specification, rather it is a container +configuration parameter. +The first parameter is the type of the objects in the set, the +second one is a Hash Functor that takes objects of this type, and +the third one is a Functor that compares them for equality. +Bimap binding metafunctions can be used with this class in +the following way: + +\code +using namespace support; + +BOOST_STATIC_ASSERT( is_set_type_of< unordered_set_of >::value ) + +BOOST_STATIC_ASSERT +( + is_same + < + unordered_set_of::index_bind + < + KeyExtractor, + Tag + + >::type, + + hashed_unique< tag, KeyExtractor, HashFunctor, EqualKey > + + >::value +) + +typedef bimap +< + unordered_set_of, RightKeyType + +> bimap_with_left_type_as_unordered_set; + +BOOST_STATIC_ASSERT +( + is_same + < + unordered_set_of::map_view_bind + < + member_at::left, + bimap_with_left_type_as_unordered_set + + >::type, + + unordered_map_view + < + member_at::left, + bimap_with_left_type_as_unordered_set + > + + >::value +) + +\endcode + +See also unordered_set_of_relation. + **/ + +template +< + class KeyType, + class HashFunctor = hash< BOOST_DEDUCED_TYPENAME + ::boost::bimaps::tags::support::value_type_of::type >, + class EqualKey = std::equal_to< BOOST_DEDUCED_TYPENAME + ::boost::bimaps::tags::support::value_type_of::type > +> +struct unordered_set_of : public ::boost::bimaps::detail::set_type_of_tag +{ + /// User type, can be tagged + typedef KeyType user_type; + + /// Type of the object that will be stored in the container + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support:: + value_type_of::type value_type; + + /// Hash Functor that takes value_type objects + typedef HashFunctor hasher; + + /// Functor that compare two value_type objects for equality + typedef EqualKey key_equal; + + struct lazy_concept_checked + { + BOOST_CLASS_REQUIRE ( value_type, + boost, AssignableConcept ); + + BOOST_CLASS_REQUIRE3( hasher, std::size_t, value_type, + boost, UnaryFunctionConcept ); + + BOOST_CLASS_REQUIRE4( key_equal, bool, value_type, value_type, + boost, BinaryFunctionConcept ); + + typedef unordered_set_of type; + }; + + BOOST_BIMAP_GENERATE_INDEX_BINDER_2CP( + + // binds to + multi_index::hashed_unique, + + // with + hasher, + key_equal + ) + + BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER( + + // binds to + views::unordered_map_view + ) + + BOOST_BIMAP_GENERATE_SET_VIEW_BINDER( + + // binds to + views::unordered_set_view + ) + + typedef mpl::bool_ mutable_key; +}; + + +/// \brief Set Of Relation Specification +/** +This struct is similar to unordered_set_of but it is bind logically to +a relation. It is used in the bimap instantiation to specify the +desired type of the main view. This struct implements internally +a metafunction named bind_to that manages the quite complicated +task of finding the right type of the set for the relation. + +\code +template +struct bind_to +{ + typedef -unspecified- type; +}; +\endcode + +See also unordered_set_of, is_set_type_of_relation. + **/ + +template +< + class HashFunctor = hash< _relation >, + class EqualKey = std::equal_to< _relation > +> +struct unordered_set_of_relation : public ::boost::bimaps::detail::set_type_of_relation_tag +{ + /// Hash Functor that takes value_type objects + typedef HashFunctor hasher; + + /// Functor that compare two value_type objects for equality + typedef EqualKey key_equal; + + + BOOST_BIMAP_GENERATE_RELATION_BINDER_2CP( + + // binds to + unordered_set_of, + + // with + hasher, + key_equal + ) + + typedef mpl::bool_ left_mutable_key; + typedef mpl::bool_ right_mutable_key; +}; + + +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_UNORDERED_SET_OF_HPP + diff --git a/win32/include/boost/bimap/vector_of.hpp b/win32/include/boost/bimap/vector_of.hpp new file mode 100755 index 000000000..ce8be2185 --- /dev/null +++ b/win32/include/boost/bimap/vector_of.hpp @@ -0,0 +1,186 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file vector_of.hpp +/// \brief Include support for vector constrains for the bimap container + +#ifndef BOOST_BIMAP_VECTOR_OF_HPP +#define BOOST_BIMAP_VECTOR_OF_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +#include + +#include + +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +namespace boost { +namespace bimaps { + + +/// \brief Set Type Specification +/** +This struct is used to specify a set specification. +It is not a container, it is just a metaprogramming facility to +express the type of a set. Generally, this specification will +be used in other place to create a container. +It has the same syntax that an std::vector instantiation, except +that the allocator cannot be specified. The rationale behind +this difference is that the allocator is not part of the set +type specification, rather it is a container configuration +parameter. +The first parameter is the type of the objects in the set, and +the second one is a Functor that compares them. +Bimap binding metafunctions can be used with this class in +the following way: + +\code +using namespace support; + +BOOST_STATIC_ASSERT( is_set_type_of< vector_of >::value ) + +BOOST_STATIC_ASSERT +( + is_same + < + vector_of::index_bind + < + KeyExtractor, + Tag + + >::type, + + random_access< tag, KeyExtractor > + + >::value +) + +typedef bimap +< + vector_of, RightKeyType + +> bimap_with_left_type_as_vector; + +BOOST_STATIC_ASSERT +( + is_same + < + vector_of::map_view_bind + < + member_at::left, + bimap_with_left_type_as_vector + + >::type, + + vector_map_view< member_at::left, bimap_with_left_type_as_vector > + + >::value +) + +\endcode + +See also vector_of_relation. + **/ + +template< class Type > +struct vector_of : public ::boost::bimaps::detail::set_type_of_tag +{ + /// User type, can be tagged + typedef Type user_type; + + /// Type of the object that will be stored in the vector + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::tags::support:: + value_type_of::type value_type; + + + struct lazy_concept_checked + { + BOOST_CLASS_REQUIRE ( value_type, + boost, AssignableConcept ); + + typedef vector_of type; + }; + + BOOST_BIMAP_GENERATE_INDEX_BINDER_0CP_NO_EXTRACTOR( + + // binds to + multi_index::random_access + ) + + BOOST_BIMAP_GENERATE_MAP_VIEW_BINDER( + + // binds to + views::vector_map_view + ) + + BOOST_BIMAP_GENERATE_SET_VIEW_BINDER( + + // binds to + views::vector_set_view + ) + + typedef mpl::bool_ mutable_key; +}; + + +/// \brief Set Of Relation Specification +/** +This struct is similar to vector_of but it is bind logically to a +relation. It is used in the bimap instantiation to specify the +desired type of the main view. This struct implements internally +a metafunction named bind_to that manages the quite complicated +task of finding the right type of the set for the relation. + +\code +template +struct bind_to +{ + typedef -unspecified- type; +}; +\endcode + +See also vector_of, is_set_type_of_relation. + **/ + +struct vector_of_relation : public ::boost::bimaps::detail::set_type_of_relation_tag +{ + BOOST_BIMAP_GENERATE_RELATION_BINDER_0CP( + + // binds to + vector_of + ) + + typedef mpl::bool_ left_mutable_key; + typedef mpl::bool_ right_mutable_key; +}; + + +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_VECTOR_OF_HPP + diff --git a/win32/include/boost/bimap/views/list_map_view.hpp b/win32/include/boost/bimap/views/list_map_view.hpp new file mode 100755 index 000000000..a5dc0582f --- /dev/null +++ b/win32/include/boost/bimap/views/list_map_view.hpp @@ -0,0 +1,182 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file views/list_map_view.hpp +/// \brief View of a side of a bimap. + +#ifndef BOOST_BIMAP_VIEWS_LIST_MAP_VIEW_HPP +#define BOOST_BIMAP_VIEWS_LIST_MAP_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace views { + +#ifndef BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +template< class Tag, class BimapType > +struct list_map_view_base +{ + typedef ::boost::bimaps::container_adaptor::list_map_adaptor + < + BOOST_DEDUCED_TYPENAME BimapType::core_type::BOOST_NESTED_TEMPLATE index::type, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + iterator_type_by::type, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + const_iterator_type_by::type, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + reverse_iterator_type_by::type, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + const_reverse_iterator_type_by::type, + ::boost::bimaps::container_adaptor::support::iterator_facade_to_base + < + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + iterator_type_by::type, + BOOST_DEDUCED_TYPENAME ::boost::bimaps::support:: + const_iterator_type_by::type + + >, + ::boost::mpl::na, + ::boost::mpl::na, + ::boost::bimaps::relation::detail:: + pair_to_relation_functor, + ::boost::bimaps::relation::support:: + get_pair_functor, + + BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::data_extractor + < + Tag, + BOOST_DEDUCED_TYPENAME BimapType::relation + + >::type + + > type; +}; + +#endif // BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES + +/// \brief View of a side of a bimap. +/** + +This class uses container_adaptor and iterator_adaptor to wrapped a index of the +multi_index bimap core. + +See also const_list_map_view. + **/ +template< class Tag, class BimapType > +class list_map_view +: + public list_map_view_base::type, + public ::boost::bimaps::detail:: + map_view_base< list_map_view,Tag,BimapType > + +{ + typedef BOOST_DEDUCED_TYPENAME list_map_view_base::type base_; + + BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(list_map_view,Tag,BimapType) + + public: + + typedef BOOST_DEDUCED_TYPENAME base_::value_type::info_type info_type; + + list_map_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) : + base_(c) {} + + list_map_view & operator=(const list_map_view & v) + { + this->base() = v.base(); + return *this; + } + + BOOST_BIMAP_VIEW_ASSIGN_IMPLEMENTATION(base_) + + BOOST_BIMAP_VIEW_FRONT_BACK_IMPLEMENTATION(base_) + + // Rearrange Operations + + void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position, + BOOST_DEDUCED_TYPENAME base_::iterator i) + { + this->base().relocate( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(i) + ); + } + + void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position, + BOOST_DEDUCED_TYPENAME base_::iterator first, + BOOST_DEDUCED_TYPENAME base_::iterator last) + { + this->base().relocate( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(first), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(last) + ); + } +}; + + +} // namespace views + +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,TYPENAME) \ +typedef BOOST_DEDUCED_TYPENAME MAP_VIEW::TYPENAME \ + BOOST_PP_CAT(SIDE,BOOST_PP_CAT(_,TYPENAME)); +/*===========================================================================*/ + +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(MAP_VIEW,SIDE) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,reverse_iterator) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_reverse_iterator) \ +/*===========================================================================*/ + +namespace detail { + +template< class Tag, class BimapType > +struct left_map_view_extra_typedefs< ::boost::bimaps::views::list_map_view > +{ + private: typedef ::boost::bimaps::views::list_map_view map_view_; + public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,left) +}; + +template< class Tag, class BimapType > +struct right_map_view_extra_typedefs< ::boost::bimaps::views::list_map_view > +{ + private: typedef ::boost::bimaps::views::list_map_view map_view_; + public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,right) +}; + +} // namespace detail + +/*===========================================================================*/ +#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF +#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY +/*===========================================================================*/ + +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_VIEWS_LIST_MAP_VIEW_HPP + diff --git a/win32/include/boost/bimap/views/list_set_view.hpp b/win32/include/boost/bimap/views/list_set_view.hpp new file mode 100755 index 000000000..f837a92eb --- /dev/null +++ b/win32/include/boost/bimap/views/list_set_view.hpp @@ -0,0 +1,108 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file views/list_set_view.hpp +/// \brief View of a side of a bimap that is signature compatible with std::list. + +#ifndef BOOST_BIMAP_VIEWS_LIST_SET_VIEW_HPP +#define BOOST_BIMAP_VIEWS_LIST_SET_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +namespace boost { +namespace bimaps { +namespace views { + +/// \brief View of a bimap that is signature compatible with std::list. +/** + +This class uses container_adaptor and iterator_adaptor to wrapped a index of the +multi_index bimap core so it can be used as a std::list. + +See also const_list_set_view. + **/ + +template< class CoreIndex > +class list_set_view +: + public BOOST_BIMAP_SEQUENCED_SET_VIEW_CONTAINER_ADAPTOR( + list_adaptor, + CoreIndex, + reverse_iterator, const_reverse_iterator + ), + + public ::boost::bimaps::detail:: + set_view_base< list_set_view< CoreIndex >, CoreIndex > +{ + BOOST_BIMAP_SET_VIEW_BASE_FRIEND(list_set_view,CoreIndex) + + typedef BOOST_BIMAP_SEQUENCED_SET_VIEW_CONTAINER_ADAPTOR( + list_adaptor, + CoreIndex, + reverse_iterator, const_reverse_iterator + + ) base_; + + public: + + list_set_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) : + base_(c) {} + + list_set_view & operator=(const list_set_view & v) + { + this->base() = v.base(); + return *this; + } + + BOOST_BIMAP_VIEW_ASSIGN_IMPLEMENTATION(base_) + + BOOST_BIMAP_VIEW_FRONT_BACK_IMPLEMENTATION(base_) + + // Rearrange Operations + + void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position, + BOOST_DEDUCED_TYPENAME base_::iterator i) + { + this->base().relocate( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(i) + ); + } + + void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position, + BOOST_DEDUCED_TYPENAME base_::iterator first, + BOOST_DEDUCED_TYPENAME base_::iterator last) + { + this->base().relocate( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(first), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(last) + ); + } +}; + + +} // namespace views +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_VIEWS_LIST_SET_VIEW_HPP + diff --git a/win32/include/boost/bimap/views/map_view.hpp b/win32/include/boost/bimap/views/map_view.hpp new file mode 100755 index 000000000..efa321700 --- /dev/null +++ b/win32/include/boost/bimap/views/map_view.hpp @@ -0,0 +1,156 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file views/map_view.hpp +/// \brief View of a side of a bimap that is signature compatible with std::map. + +#ifndef BOOST_BIMAP_VIEWS_MAP_VIEW_HPP +#define BOOST_BIMAP_VIEWS_MAP_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +namespace boost { +namespace bimaps { +namespace views { + +/// \brief View of a side of a bimap that is signature compatible with std::map. +/** + +This class uses container_adaptor and iterator_adaptor to wrapped a index of the +multi_index bimap core so it can be used as a std::map. + +See also const_map_view. + **/ + +template< class Tag, class BimapType > +class map_view +: + public BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR( + map_adaptor, + Tag,BimapType, + reverse_iterator_type_by,const_reverse_iterator_type_by + ), + public ::boost::bimaps::detail:: + map_view_base< map_view,Tag,BimapType >, + public ::boost::bimaps::detail:: + unique_map_view_access< map_view, Tag, BimapType>::type +{ + typedef BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR( + map_adaptor, + Tag,BimapType, + reverse_iterator_type_by,const_reverse_iterator_type_by + + ) base_; + + BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(map_view,Tag,BimapType) + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail:: + unique_map_view_access< + map_view, Tag, BimapType + + >::type unique_map_view_access_; + + public: + + typedef BOOST_DEDUCED_TYPENAME base_::value_type::info_type info_type; + + map_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) : base_(c) {} + + using unique_map_view_access_::at; + using unique_map_view_access_::operator[]; + + BOOST_BIMAP_MAP_VIEW_RANGE_IMPLEMENTATION(base_) + + map_view & operator=(const map_view & v) + { + this->base() = v.base(); + return *this; + } + + // It can be used enable_if here but the error message when there + // is no info is very clear like this + + template< class CompatibleKey > + const info_type & info_at(const CompatibleKey& k) const + { + BOOST_DEDUCED_TYPENAME base_::const_iterator iter = this->find(k); + if( iter == this->end() ) + { + ::boost::throw_exception( + std::out_of_range("bimap<>: invalid key") + ); + } + return iter->info; + } + + template< class CompatibleKey > + info_type & info_at(const CompatibleKey& k) + { + BOOST_DEDUCED_TYPENAME base_::iterator iter = this->find(k); + if( iter == this->end() ) + { + ::boost::throw_exception( + std::out_of_range("bimap<>: invalid key") + ); + } + return iter->info; + } +}; + +} // namespace views + +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,TYPENAME) \ +typedef BOOST_DEDUCED_TYPENAME MAP_VIEW::TYPENAME \ + BOOST_PP_CAT(SIDE,BOOST_PP_CAT(_,TYPENAME)); +/*===========================================================================*/ + +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(MAP_VIEW,SIDE) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,reverse_iterator) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_reverse_iterator) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,range_type) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_range_type) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,key_compare) +/*===========================================================================*/ + +namespace detail { + +template< class Tag, class BimapType > +struct left_map_view_extra_typedefs< ::boost::bimaps::views::map_view > +{ + private: typedef ::boost::bimaps::views::map_view map_view_; + public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,left) +}; + +template< class Tag, class BimapType > +struct right_map_view_extra_typedefs< ::boost::bimaps::views::map_view > +{ + private: typedef ::boost::bimaps::views::map_view map_view_; + public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,right) +}; + +} // namespace detail + +/*===========================================================================*/ +#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF +#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY +/*===========================================================================*/ + +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_VIEWS_MAP_VIEW_HPP + diff --git a/win32/include/boost/bimap/views/multimap_view.hpp b/win32/include/boost/bimap/views/multimap_view.hpp new file mode 100755 index 000000000..a991a3245 --- /dev/null +++ b/win32/include/boost/bimap/views/multimap_view.hpp @@ -0,0 +1,123 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file views/multimap_view.hpp +/// \brief View of a side of a bimap that is signature compatible with std::multimap. + +#ifndef BOOST_BIMAP_VIEWS_MULTIMAP_VIEW_HPP +#define BOOST_BIMAP_VIEWS_MULTIMAP_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace views { + +/// \brief View of a side of a bimap that is signature compatible with std::multimap. +/** + +This class uses container_adaptor and iterator_adaptor to wrapped a index of the +multi_index bimap core so it can be used as a std::multimap. + +See also const_multimap_view. + **/ + +template< class Tag, class BimapType > +class multimap_view +: + public BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR( + multimap_adaptor, + Tag,BimapType, + reverse_iterator_type_by,const_reverse_iterator_type_by + ), + public ::boost::bimaps::detail:: + map_view_base< multimap_view,Tag,BimapType > + +{ + typedef BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR( + multimap_adaptor, + Tag,BimapType, + reverse_iterator_type_by,const_reverse_iterator_type_by + + ) base_; + + BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(multimap_view,Tag,BimapType) + + public: + + typedef BOOST_DEDUCED_TYPENAME base_::value_type::info_type info_type; + + multimap_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) + : base_(c) {} + + BOOST_BIMAP_MAP_VIEW_RANGE_IMPLEMENTATION(base_) + + multimap_view & operator=(const multimap_view & v) + { + this->base() = v.base(); + return *this; + } + + BOOST_BIMAP_NON_UNIQUE_VIEW_INSERT_FUNCTIONS +}; + + +} // namespace views + +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,TYPENAME) \ +typedef BOOST_DEDUCED_TYPENAME MAP_VIEW::TYPENAME \ + BOOST_PP_CAT(SIDE,BOOST_PP_CAT(_,TYPENAME)); +/*===========================================================================*/ + +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(MAP_VIEW,SIDE) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,reverse_iterator) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_reverse_iterator) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,range_type) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_range_type) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,key_compare) +/*===========================================================================*/ + +namespace detail { + +template< class Tag, class BimapType > +struct left_map_view_extra_typedefs< ::boost::bimaps::views::multimap_view > +{ + private: typedef ::boost::bimaps::views::multimap_view map_view_; + public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,left) +}; + +template< class Tag, class BimapType > +struct right_map_view_extra_typedefs< ::boost::bimaps::views::multimap_view > +{ + private: typedef ::boost::bimaps::views::multimap_view map_view_; + public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,right) +}; + +} // namespace detail + +/*===========================================================================*/ +#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF +#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY +/*===========================================================================*/ + +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_VIEWS_MAP_VIEW_HPP + diff --git a/win32/include/boost/bimap/views/multiset_view.hpp b/win32/include/boost/bimap/views/multiset_view.hpp new file mode 100755 index 000000000..c6d25134b --- /dev/null +++ b/win32/include/boost/bimap/views/multiset_view.hpp @@ -0,0 +1,110 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file views/multiset_view.hpp +/// \brief View of a bimap that is signature compatible with std::multiset. + +#ifndef BOOST_BIMAP_VIEWS_MULTISET_VIEW_HPP +#define BOOST_BIMAP_VIEWS_MULTISET_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace views { + +/// \brief View of a bimap that is signature compatible with std::multiset. +/** + +This class uses container_adaptor and iterator_adaptor to wrapped a index of the +multi_index bimap core so it can be used as a std::multiset. + +See also const_multiset_view. + **/ + +template< class CoreIndex > +class multiset_view +: + public BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR( + multiset_adaptor, + CoreIndex, + reverse_iterator, + const_reverse_iterator + ), + + public ::boost::bimaps::detail:: + set_view_base< multiset_view< CoreIndex >, CoreIndex > +{ + BOOST_BIMAP_SET_VIEW_BASE_FRIEND(multiset_view, CoreIndex) + + typedef BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR( + multiset_adaptor, + CoreIndex, + reverse_iterator, + const_reverse_iterator + + ) base_; + + public: + + multiset_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) : base_(c) {} + + /* + template< class LowerBounder, class UpperBounder > + std::pair + range(LowerBounder lower,UpperBounder upper) const + { + return this->base().range( + + ::boost::bimaps::container_adaptor::detail::unary_check_adaptor + < + LowerBounder, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( lower, this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() ), + + ::boost::bimaps::container_adaptor::detail::unary_check_adaptor + < + UpperBounder, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( upper, this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() ) + + ); + } + */ + + multiset_view & operator=(const multiset_view & v) + { + this->base() = v.base(); return *this; + } + + BOOST_BIMAP_NON_UNIQUE_VIEW_INSERT_FUNCTIONS +}; + + +} // namespace views +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_VIEWS_MULTISET_VIEW_HPP + diff --git a/win32/include/boost/bimap/views/set_view.hpp b/win32/include/boost/bimap/views/set_view.hpp new file mode 100755 index 000000000..e38a5f8fa --- /dev/null +++ b/win32/include/boost/bimap/views/set_view.hpp @@ -0,0 +1,106 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file views/set_view.hpp +/// \brief View of a bimap that is signature compatible with std::set. + +#ifndef BOOST_BIMAP_VIEWS_SET_VIEW_HPP +#define BOOST_BIMAP_VIEWS_SET_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +namespace boost { +namespace bimaps { +namespace views { + +/// \brief View of a bimap that is signature compatible with std::set. +/** + +This class uses container_adaptor and iterator_adaptor to wrapped a index of the +multi_index bimap core so it can be used as a std::set. + +See also const_set_view. + **/ + +template< class CoreIndex > +class set_view +: + public BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR( + set_adaptor, + CoreIndex, + reverse_iterator, const_reverse_iterator + ), + + public ::boost::bimaps::detail:: + set_view_base< set_view< CoreIndex >, CoreIndex > +{ + typedef BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR( + set_adaptor, + CoreIndex, + reverse_iterator, const_reverse_iterator + + ) base_; + + BOOST_BIMAP_SET_VIEW_BASE_FRIEND(set_view,CoreIndex) + + public: + + set_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) : base_(c) {} + + /* + template< class LowerBounder, class UpperBounder > + std::pair + range(LowerBounder lower,UpperBounder upper) const + { + return this->base().range( + + ::boost::bimaps::container_adaptor::detail::unary_check_adaptor + < + LowerBounder, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( lower, this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() ), + + ::boost::bimaps::container_adaptor::detail::unary_check_adaptor + < + UpperBounder, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( upper, this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() ) + + ); + } + */ + + set_view & operator=(const set_view & v) + { + this->base() = v.base(); + return *this; + } +}; + + +} // namespace views +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_VIEWS_SET_VIEW_HPP + + diff --git a/win32/include/boost/bimap/views/unconstrained_map_view.hpp b/win32/include/boost/bimap/views/unconstrained_map_view.hpp new file mode 100755 index 000000000..7c740deb0 --- /dev/null +++ b/win32/include/boost/bimap/views/unconstrained_map_view.hpp @@ -0,0 +1,44 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file views/unconstrained_map_view.hpp +/// \brief Unconstrained view of a side of a bimap. + +#ifndef BOOST_BIMAP_VIEWS_UNCONSTRAINED_MAP_VIEW_HPP +#define BOOST_BIMAP_VIEWS_UNCONSTRAINED_MAP_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +namespace boost { +namespace bimaps { +namespace views { + +/// \brief Unconstrained view of a side of a bimap. + +template< class Tag, class BimapType> +class unconstrained_map_view +{ + public: + template< class T > + unconstrained_map_view(const T & t) {} + + typedef void reference; + typedef void const_reference; + typedef void info_type; +}; + +} // namespace views +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_VIEWS_UNCONSTRAINED_MAP_VIEW_HPP + diff --git a/win32/include/boost/bimap/views/unconstrained_set_view.hpp b/win32/include/boost/bimap/views/unconstrained_set_view.hpp new file mode 100755 index 000000000..525b6378b --- /dev/null +++ b/win32/include/boost/bimap/views/unconstrained_set_view.hpp @@ -0,0 +1,42 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file views/unconstrained_set_view.hpp +/// \brief Unconstrained view of a bimap. + +#ifndef BOOST_BIMAP_VIEWS_UNCONSTRAINED_SET_VIEW_HPP +#define BOOST_BIMAP_VIEWS_UNCONSTRAINED_SET_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +namespace boost { +namespace bimaps { +namespace views { + +/// \brief Unconstrained view of a bimap. + +template< class CoreIndex > +class unconstrained_set_view +{ + public: + template< class T > + unconstrained_set_view(const T & t) {} + + typedef void iterator; + typedef void const_iterator; +}; + +} // namespace views +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_VIEWS_UNCONSTRAINED_SET_VIEW_HPP diff --git a/win32/include/boost/bimap/views/unordered_map_view.hpp b/win32/include/boost/bimap/views/unordered_map_view.hpp new file mode 100755 index 000000000..0241a338f --- /dev/null +++ b/win32/include/boost/bimap/views/unordered_map_view.hpp @@ -0,0 +1,174 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file views/unordered_map_view.hpp +/// \brief View of a side of a bimap that is signature compatible with tr1::unordered_map. + +#ifndef BOOST_BIMAP_VIEWS_UNOREDERED_MAP_VIEW_HPP +#define BOOST_BIMAP_VIEWS_UNOREDERED_MAP_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +#include +#include + +namespace boost { +namespace bimaps { +namespace views { + +/// \brief Map View of a bimap, signature compatible with tr1::unordered_map. +/** + +This class uses container_adaptor and iterator_adaptor to wrapped a index of the +multi_index bimap core so it can be used as a tr1::unordered_map. + +See also const_unordered_map_view. + **/ + + +template< class Tag, class BimapType > +class unordered_map_view +: + public BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR( + unordered_map_adaptor, + Tag,BimapType, + local_iterator_type_by,const_local_iterator_type_by + ), + + public ::boost::bimaps::detail::map_view_base< + unordered_map_view,Tag,BimapType >, + public ::boost::bimaps::detail:: + unique_map_view_access< + unordered_map_view, Tag, BimapType>::type + +{ + typedef BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR( + unordered_map_adaptor, + Tag,BimapType, + local_iterator_type_by,const_local_iterator_type_by + + ) base_; + + BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(unordered_map_view,Tag,BimapType) + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::detail:: + unique_map_view_access< + unordered_map_view, Tag, BimapType + + >::type unique_map_view_access_; + + public: + + typedef std::pair< + BOOST_DEDUCED_TYPENAME base_::iterator, + BOOST_DEDUCED_TYPENAME base_::iterator + > range_type; + + typedef std::pair< + BOOST_DEDUCED_TYPENAME base_::const_iterator, + BOOST_DEDUCED_TYPENAME base_::const_iterator + > const_range_type; + + typedef BOOST_DEDUCED_TYPENAME base_::value_type::info_type info_type; + + unordered_map_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) + : base_(c) {} + + using unique_map_view_access_::at; + using unique_map_view_access_::operator[]; + + unordered_map_view & operator=(const unordered_map_view & v) + { + this->base() = v.base(); + return *this; + } + + // It can be used enable_if here but the error message when there + // is no info is very clear like this + + template< class CompatibleKey > + const info_type & info_at(const CompatibleKey& k) const + { + BOOST_DEDUCED_TYPENAME base_::const_iterator iter = this->find(k); + if( iter == this->end() ) + { + ::boost::throw_exception( + std::out_of_range("bimap<>: invalid key") + ); + } + return iter->info; + } + + template< class CompatibleKey > + info_type & info_at(const CompatibleKey& k) + { + BOOST_DEDUCED_TYPENAME base_::iterator iter = this->find(k); + if( iter == this->end() ) + { + ::boost::throw_exception( + std::out_of_range("bimap<>: invalid key") + ); + } + return iter->info; + } +}; + + +} // namespace views + +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,TYPENAME) \ +typedef BOOST_DEDUCED_TYPENAME MAP_VIEW::TYPENAME \ + BOOST_PP_CAT(SIDE,BOOST_PP_CAT(_,TYPENAME)); +/*===========================================================================*/ + +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(MAP_VIEW,SIDE) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,local_iterator) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_local_iterator) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,range_type) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_range_type) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,hasher) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,key_equal) +/*===========================================================================*/ + +namespace detail { + +template< class Tag, class BimapType > +struct left_map_view_extra_typedefs< ::boost::bimaps::views::unordered_map_view > +{ + private: typedef ::boost::bimaps::views::unordered_map_view map_view_; + public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,left) +}; + +template< class Tag, class BimapType > +struct right_map_view_extra_typedefs< ::boost::bimaps::views::unordered_map_view > +{ + private: typedef ::boost::bimaps::views::unordered_map_view map_view_; + public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,right) +}; + +} // namespace detail + +/*===========================================================================*/ +#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF +#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY +/*===========================================================================*/ + +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_VIEWS_UNOREDERED_MAP_VIEW_HPP + + diff --git a/win32/include/boost/bimap/views/unordered_multimap_view.hpp b/win32/include/boost/bimap/views/unordered_multimap_view.hpp new file mode 100755 index 000000000..d222adfe4 --- /dev/null +++ b/win32/include/boost/bimap/views/unordered_multimap_view.hpp @@ -0,0 +1,136 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file views/unordered_multimap_view.hpp +/// \brief View of a side of a bimap that is signature compatible with tr1::unordered_multimap. + +#ifndef BOOST_BIMAP_VIEWS_UNOREDERED_MULTIMAP_VIEW_HPP +#define BOOST_BIMAP_VIEWS_UNOREDERED_MULTIMAP_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include + +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace views { + +/// \brief View of a side of a bimap that is signature compatible with tr1::unordered_multimap. +/** + +This class uses container_adaptor and iterator_adaptor to wrapped a index of the +multi_index bimap core so it can be used as a tr1::unordered_multimap. + +See also const_unordered_multimap_view. + **/ + +template< class Tag, class BimapType > +class unordered_multimap_view +: + public BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR( + unordered_multimap_adaptor, + Tag,BimapType, + local_iterator_type_by,const_local_iterator_type_by + ), + + public ::boost::bimaps::detail::map_view_base< + unordered_multimap_view,Tag,BimapType > + +{ + typedef BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR( + unordered_multimap_adaptor, + Tag,BimapType, + local_iterator_type_by,const_local_iterator_type_by + + ) base_; + + BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(unordered_multimap_view,Tag,BimapType) + + public: + + typedef std::pair< + BOOST_DEDUCED_TYPENAME base_::iterator, + BOOST_DEDUCED_TYPENAME base_::iterator + > range_type; + + typedef std::pair< + BOOST_DEDUCED_TYPENAME base_::const_iterator, + BOOST_DEDUCED_TYPENAME base_::const_iterator + > const_range_type; + + typedef BOOST_DEDUCED_TYPENAME base_::value_type::info_type info_type; + + unordered_multimap_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) + : base_(c) {} + + BOOST_BIMAP_NON_UNIQUE_VIEW_INSERT_FUNCTIONS + + unordered_multimap_view & operator=(const unordered_multimap_view & v) + { + this->base() = v.base(); + return *this; + } +}; + + +} // namespace views + +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,TYPENAME) \ +typedef BOOST_DEDUCED_TYPENAME MAP_VIEW::TYPENAME \ + BOOST_PP_CAT(SIDE,BOOST_PP_CAT(_,TYPENAME)); +/*===========================================================================*/ + +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(MAP_VIEW,SIDE) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,local_iterator) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_local_iterator) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,range_type) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_range_type) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,hasher) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,key_equal) +/*===========================================================================*/ + +namespace detail { + +template< class Tag, class BimapType > +struct left_map_view_extra_typedefs< ::boost::bimaps::views::unordered_multimap_view > +{ + private: typedef ::boost::bimaps::views::unordered_multimap_view map_view_; + public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,left) +}; + +template< class Tag, class BimapType > +struct right_map_view_extra_typedefs< ::boost::bimaps::views::unordered_multimap_view > +{ + private: typedef ::boost::bimaps::views::unordered_multimap_view map_view_; + public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,right) +}; + +} // namespace detail + +/*===========================================================================*/ +#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF +#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY +/*===========================================================================*/ + +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_VIEWS_UNOREDERED_MULTIMAP_VIEW_HPP + + diff --git a/win32/include/boost/bimap/views/unordered_multiset_view.hpp b/win32/include/boost/bimap/views/unordered_multiset_view.hpp new file mode 100755 index 000000000..477195239 --- /dev/null +++ b/win32/include/boost/bimap/views/unordered_multiset_view.hpp @@ -0,0 +1,83 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file views/unordered_multiset_view.hpp +/// \brief View of a bimap that is signature compatible with tr1::unordered_multiset. + +#ifndef BOOST_BIMAP_VIEWS_UNORDERED_MULTISET_VIEW_HPP +#define BOOST_BIMAP_VIEWS_UNORDERED_MULTISET_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace views { + +/// \brief View of a bimap that is signature compatible with std::unordered_multiset. +/** + +This class uses container_adaptor and iterator_adaptor to wrapped a index of the +multi_index bimap core so it can be used as a std::unordered_multiset. + +See also const_unordered_multiset_view. + **/ + +template< class CoreIndex > +class unordered_multiset_view +: + public BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR( + unordered_multiset_adaptor, + CoreIndex, + local_iterator, + const_local_iterator + + ), + + public ::boost::bimaps::detail:: + set_view_base< unordered_multiset_view< CoreIndex >, CoreIndex > +{ + BOOST_BIMAP_SET_VIEW_BASE_FRIEND(unordered_multiset_view,CoreIndex) + + typedef BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR( + unordered_multiset_adaptor, + CoreIndex, + local_iterator, + const_local_iterator + + ) base_; + + public: + + unordered_multiset_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) + : base_(c) {} + + BOOST_BIMAP_NON_UNIQUE_VIEW_INSERT_FUNCTIONS + + unordered_multiset_view & operator=(const unordered_multiset_view & v) + { + this->base() = v.base(); + return *this; + } +}; + + +} // namespace views +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_VIEWS_UNORDERED_MULTISET_VIEW_HPP + + diff --git a/win32/include/boost/bimap/views/unordered_set_view.hpp b/win32/include/boost/bimap/views/unordered_set_view.hpp new file mode 100755 index 000000000..df8c7e577 --- /dev/null +++ b/win32/include/boost/bimap/views/unordered_set_view.hpp @@ -0,0 +1,78 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file views/unordered_set_view.hpp +/// \brief View of a bimap that is signature compatible with tr1::unordered_set. + +#ifndef BOOST_BIMAP_VIEWS_UNORDERED_SET_VIEW_HPP +#define BOOST_BIMAP_VIEWS_UNORDERED_SET_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include + +namespace boost { +namespace bimaps { +namespace views { + +/// \brief View of a bimap that is signature compatible with std::unordered_set. +/** + +This class uses container_adaptor and iterator_adaptor to wrapped a index of the +multi_index bimap core so it can be used as a std::unordered_set. + +See also const_unordered_set_view. + **/ + +template< class CoreIndex > +class unordered_set_view +: + public BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR( + unordered_set_adaptor, + CoreIndex, + local_iterator, + const_local_iterator + ), + + public ::boost::bimaps::detail:: + set_view_base< unordered_set_view< CoreIndex >, CoreIndex > +{ + BOOST_BIMAP_SET_VIEW_BASE_FRIEND(unordered_set_view,CoreIndex) + + typedef BOOST_BIMAP_SET_VIEW_CONTAINER_ADAPTOR( + unordered_set_adaptor, + CoreIndex, + local_iterator, + const_local_iterator + + ) base_; + + public: + + unordered_set_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) + : base_(c) {} + + unordered_set_view & operator=(const unordered_set_view & v) + { + this->base() = v.base(); + return *this; + } +}; + + +} // namespace views +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_VIEWS_UNORDERED_SET_VIEW_HPP + diff --git a/win32/include/boost/bimap/views/vector_map_view.hpp b/win32/include/boost/bimap/views/vector_map_view.hpp new file mode 100755 index 000000000..126b884dd --- /dev/null +++ b/win32/include/boost/bimap/views/vector_map_view.hpp @@ -0,0 +1,306 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file views/vector_map_view.hpp +/// \brief View of a side of a bimap. + +#ifndef BOOST_BIMAP_VIEWS_VECTOR_MAP_VIEW_HPP +#define BOOST_BIMAP_VIEWS_VECTOR_MAP_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include +#include + +namespace boost { +namespace bimaps { +namespace views { + +/// \brief View of a side of a bimap. +/** + +This class uses container_adaptor and iterator_adaptor to wrapped a index of the +multi_index bimap core. + +See also const_map_view. + **/ +template< class Tag, class BimapType > +class vector_map_view +: + public BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR( + vector_map_adaptor, + Tag,BimapType, + reverse_iterator_type_by, const_reverse_iterator_type_by + ), + + public ::boost::bimaps::detail:: + map_view_base< vector_map_view,Tag,BimapType > +{ + typedef BOOST_BIMAP_MAP_VIEW_CONTAINER_ADAPTOR( + vector_map_adaptor, + Tag,BimapType, + reverse_iterator_type_by, const_reverse_iterator_type_by + + ) base_; + + BOOST_BIMAP_MAP_VIEW_BASE_FRIEND(vector_map_view,Tag,BimapType) + + typedef BOOST_DEDUCED_TYPENAME ::boost::bimaps::relation::support::data_extractor + < + Tag, + BOOST_DEDUCED_TYPENAME BimapType::relation + + >::type key_from_base_value; + + public: + + typedef BOOST_DEDUCED_TYPENAME base_::value_type::info_type info_type; + + vector_map_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) : + base_(c) {} + + vector_map_view & operator=(const vector_map_view & v) + { + this->base() = v.base(); + return *this; + } + + BOOST_BIMAP_VIEW_ASSIGN_IMPLEMENTATION(base_) + + BOOST_BIMAP_VIEW_FRONT_BACK_IMPLEMENTATION(base_) + + // Lists operations + + void splice(BOOST_DEDUCED_TYPENAME base_::iterator position, vector_map_view & x) + { + this->base().splice( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + x.base() + ); + } + + void splice(BOOST_DEDUCED_TYPENAME base_::iterator position, + vector_map_view & x, + BOOST_DEDUCED_TYPENAME base_::iterator i) + { + this->base().splice( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + x.base(), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(i) + ); + } + + void splice(BOOST_DEDUCED_TYPENAME base_::iterator position, + vector_map_view & x, + BOOST_DEDUCED_TYPENAME base_::iterator first, + BOOST_DEDUCED_TYPENAME base_::iterator last) + { + this->base().splice( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + x.base(), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(first), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(last) + ); + } + + void remove(BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::value_type >::param_type value) + { + this->base().remove( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_to_base>()(value) + ); + } + + template< class Predicate > + void remove_if(Predicate pred) + { + this->base().remove_if( + ::boost::bimaps::container_adaptor::detail::unary_check_adaptor + < + Predicate, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + key_from_base_value + + >( pred, key_from_base_value() ) + ); + } + + void unique() + { + this->base().unique( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::equal_to, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + key_from_base_value + + >(std::equal_to(), + key_from_base_value() ) + ); + } + + template< class BinaryPredicate > + void unique(BinaryPredicate binary_pred) + { + this->base().unique( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + BinaryPredicate, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + key_from_base_value + + >( binary_pred, key_from_base_value() ) + ); + } + + void merge(vector_map_view & x) + { + this->base().merge(x.base(), + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::less, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + key_from_base_value + + >( std::less(), + key_from_base_value() ) + ); + } + + template< class Compare > + void merge(vector_map_view & x, Compare comp) + { + this->base().merge(x.base(), + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + Compare, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + key_from_base_value + + >( comp, key_from_base_value() ) + ); + } + + void sort() + { + this->base().sort( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::less, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + key_from_base_value + + >( std::less(), + key_from_base_value() ) + ); + } + + template< class Compare > + void sort(Compare comp) + { + this->base().sort( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + Compare, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + key_from_base_value + + >( comp, key_from_base_value() ) + ); + } + + void reverse() + { + this->base().reverse(); + } + + // Rearrange Operations + + void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position, + BOOST_DEDUCED_TYPENAME base_::iterator i) + { + this->base().relocate( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(i) + ); + } + + void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position, + BOOST_DEDUCED_TYPENAME base_::iterator first, + BOOST_DEDUCED_TYPENAME base_::iterator last) + { + this->base().relocate( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(first), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(last) + ); + } + +}; + + +} // namespace views + +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,TYPENAME) \ +typedef BOOST_DEDUCED_TYPENAME MAP_VIEW::TYPENAME \ + BOOST_PP_CAT(SIDE,BOOST_PP_CAT(_,TYPENAME)); +/*===========================================================================*/ + +/*===========================================================================*/ +#define BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(MAP_VIEW,SIDE) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,reverse_iterator) \ + BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF(MAP_VIEW,SIDE,const_reverse_iterator) \ +/*===========================================================================*/ + +namespace detail { + +template< class Tag, class BimapType > +struct left_map_view_extra_typedefs< ::boost::bimaps::views::vector_map_view > +{ + private: typedef ::boost::bimaps::views::vector_map_view map_view_; + public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,left) +}; + +template< class Tag, class BimapType > +struct right_map_view_extra_typedefs< ::boost::bimaps::views::vector_map_view > +{ + private: typedef ::boost::bimaps::views::vector_map_view map_view_; + public : BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY(map_view_,right) +}; + +} // namespace detail + +/*===========================================================================*/ +#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEF +#undef BOOST_BIMAP_MAP_VIEW_EXTRA_TYPEDEFS_BODY +/*===========================================================================*/ + +} // namespace bimaps +} // namespace boost + +#endif // BOOST_BIMAP_VIEWS_VECTOR_MAP_VIEW_HPP + diff --git a/win32/include/boost/bimap/views/vector_set_view.hpp b/win32/include/boost/bimap/views/vector_set_view.hpp new file mode 100755 index 000000000..2f5122901 --- /dev/null +++ b/win32/include/boost/bimap/views/vector_set_view.hpp @@ -0,0 +1,279 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// 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) + +/// \file views/vector_set_view.hpp +/// \brief View of a side of a bimap that is signature compatible with std::vector. + +#ifndef BOOST_BIMAP_VIEWS_VECTOR_SET_VIEW_HPP +#define BOOST_BIMAP_VIEWS_VECTOR_SET_VIEW_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include + +#include +#include +#include + + +namespace boost { +namespace bimaps { +namespace views { + +/// \brief View of a bimap that is signature compatible with std::vector. +/** + +This class uses container_adaptor and iterator_adaptor to wrapped a index of the +multi_index bimap core so it can be used as a std::vector. + +See also const_set_view. + **/ + +template< class CoreIndex > +class vector_set_view +: + public BOOST_BIMAP_SEQUENCED_SET_VIEW_CONTAINER_ADAPTOR( + vector_adaptor, + CoreIndex, + reverse_iterator, const_reverse_iterator + ), + + public ::boost::bimaps::detail:: + set_view_base< vector_set_view< CoreIndex >, CoreIndex > +{ + BOOST_BIMAP_SET_VIEW_BASE_FRIEND(vector_set_view,CoreIndex) + + typedef BOOST_BIMAP_SEQUENCED_SET_VIEW_CONTAINER_ADAPTOR( + vector_adaptor, + CoreIndex, + reverse_iterator, const_reverse_iterator + + ) base_; + + public: + + vector_set_view(BOOST_DEDUCED_TYPENAME base_::base_type & c) : + base_(c) {} + + vector_set_view & operator=(const vector_set_view & v) + { + this->base() = v.base(); + return *this; + } + + BOOST_BIMAP_VIEW_ASSIGN_IMPLEMENTATION(base_) + + BOOST_BIMAP_VIEW_FRONT_BACK_IMPLEMENTATION(base_) + + // List operations + + void splice(BOOST_DEDUCED_TYPENAME base_::iterator position, + vector_set_view & x) + { + this->base().splice( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + x.base() + ); + } + + void splice(BOOST_DEDUCED_TYPENAME base_::iterator position, + vector_set_view & x, + BOOST_DEDUCED_TYPENAME base_::iterator i) + { + this->base().splice( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + x.base(), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(i) + ); + } + + void splice(BOOST_DEDUCED_TYPENAME base_::iterator position, + vector_set_view & x, + BOOST_DEDUCED_TYPENAME base_::iterator first, + BOOST_DEDUCED_TYPENAME base_::iterator last) + { + this->base().splice( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + x.base(), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(first), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(last) + ); + } + + void remove(BOOST_DEDUCED_TYPENAME ::boost::call_traits< + BOOST_DEDUCED_TYPENAME base_::value_type >::param_type value) + { + this->base().remove( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_to_base>()(value) + ); + } + + template + void remove_if(Predicate pred) + { + this->base().remove_if( + ::boost::bimaps::container_adaptor::detail::unary_check_adaptor + < + Predicate, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( pred, this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() ) + ); + } + + void unique() + { + this->base().unique( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::equal_to, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( + std::equal_to(), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() + ) + ); + } + + template< class BinaryPredicate > + void unique(BinaryPredicate binary_pred) + { + this->base().unique( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + BinaryPredicate, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( binary_pred, + this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() + ) + ); + } + + void merge(vector_set_view & x) + { + this->base().merge(x.base(), + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::less, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( + std::less(), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() + ) + ); + } + + template< class Compare > + void merge(vector_set_view & x, Compare comp) + { + this->base().merge(x.base(), + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + Compare, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( comp, this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() ) + ); + } + + void sort() + { + this->base().sort( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + std::less, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( + std::less(), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() + ) + ); + } + + template< class Compare > + void sort(Compare comp) + { + this->base().sort( + ::boost::bimaps::container_adaptor::detail::comparison_adaptor + < + Compare, + BOOST_DEDUCED_TYPENAME base_::base_type::value_type, + BOOST_DEDUCED_TYPENAME base_::value_from_base + + >( comp, this->template functor< + BOOST_DEDUCED_TYPENAME base_::value_from_base>() ) + ); + } + + void reverse() + { + this->base().reverse(); + } + + // Rearrange Operations + + void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position, + BOOST_DEDUCED_TYPENAME base_::iterator i) + { + this->base().relocate( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(i) + ); + } + + void relocate(BOOST_DEDUCED_TYPENAME base_::iterator position, + BOOST_DEDUCED_TYPENAME base_::iterator first, + BOOST_DEDUCED_TYPENAME base_::iterator last) + { + this->base().relocate( + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(position), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(first), + this->template functor< + BOOST_DEDUCED_TYPENAME base_::iterator_to_base>()(last) + ); + } + +}; + + +} // namespace views +} // namespace bimaps +} // namespace boost + + +#endif // BOOST_BIMAP_VIEWS_VECTOR_SET_VIEW_HPP + diff --git a/win32/include/boost/bind.hpp b/win32/include/boost/bind.hpp new file mode 100755 index 000000000..e968ebf68 --- /dev/null +++ b/win32/include/boost/bind.hpp @@ -0,0 +1,1719 @@ +#ifndef BOOST_BIND_HPP_INCLUDED +#define BOOST_BIND_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// bind.hpp - binds function objects to arguments +// +// Copyright (c) 2001-2004 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2001 David Abrahams +// Copyright (c) 2005 Peter Dimov +// +// 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) +// +// See http://www.boost.org/libs/bind/bind.html for documentation. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +// Borland-specific bug, visit_each() silently fails to produce code + +#if defined(__BORLANDC__) +# define BOOST_BIND_VISIT_EACH boost::visit_each +#else +# define BOOST_BIND_VISIT_EACH visit_each +#endif + +#include + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable: 4512) // assignment operator could not be generated +#endif + +namespace boost +{ + +namespace _bi // implementation details +{ + +// result_traits + +template struct result_traits +{ + typedef R type; +}; + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + +struct unspecified {}; + +template struct result_traits +{ + typedef typename F::result_type type; +}; + +template struct result_traits< unspecified, reference_wrapper > +{ + typedef typename F::result_type type; +}; + +#endif + +// ref_compare + +template bool ref_compare( T const & a, T const & b, long ) +{ + return a == b; +} + +template bool ref_compare( arg const &, arg const &, int ) +{ + return true; +} + +template bool ref_compare( arg (*) (), arg (*) (), int ) +{ + return true; +} + +template bool ref_compare( reference_wrapper const & a, reference_wrapper const & b, int ) +{ + return a.get_pointer() == b.get_pointer(); +} + +// bind_t forward declaration for listN + +template class bind_t; + +// value + +template class value +{ +public: + + value(T const & t): t_(t) {} + + T & get() { return t_; } + T const & get() const { return t_; } + + bool operator==(value const & rhs) const + { + return t_ == rhs.t_; + } + +private: + + T t_; +}; + +// type + +template class type {}; + +// unwrap + +template struct unwrapper +{ + static inline F & unwrap( F & f, long ) + { + return f; + } + + template static inline F2 & unwrap( reference_wrapper rf, int ) + { + return rf.get(); + } + + template static inline _mfi::dm unwrap( R T::* pm, int ) + { + return _mfi::dm( pm ); + } +}; + +// listN + +class list0 +{ +public: + + list0() {} + + template T & operator[] (_bi::value & v) const { return v.get(); } + + template T const & operator[] (_bi::value const & v) const { return v.get(); } + + template T & operator[] (reference_wrapper const & v) const { return v.get(); } + + template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } + + template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } + + template R operator()(type, F & f, A &, long) + { + return unwrapper::unwrap(f, 0)(); + } + + template R operator()(type, F const & f, A &, long) const + { + return unwrapper::unwrap(f, 0)(); + } + + template void operator()(type, F & f, A &, int) + { + unwrapper::unwrap(f, 0)(); + } + + template void operator()(type, F const & f, A &, int) const + { + unwrapper::unwrap(f, 0)(); + } + + template void accept(V &) const + { + } + + bool operator==(list0 const &) const + { + return true; + } +}; + +template< class A1 > class list1: private storage1< A1 > +{ +private: + + typedef storage1< A1 > base_type; + +public: + + explicit list1( A1 a1 ): base_type( a1 ) {} + + A1 operator[] (boost::arg<1>) const { return base_type::a1_; } + + A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } + + template T & operator[] ( _bi::value & v ) const { return v.get(); } + + template T const & operator[] ( _bi::value const & v ) const { return v.get(); } + + template T & operator[] (reference_wrapper const & v) const { return v.get(); } + + template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } + + template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } + + template R operator()(type, F & f, A & a, long) + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_]); + } + + template R operator()(type, F const & f, A & a, long) const + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_]); + } + + template void operator()(type, F & f, A & a, int) + { + unwrapper::unwrap(f, 0)(a[base_type::a1_]); + } + + template void operator()(type, F const & f, A & a, int) const + { + unwrapper::unwrap(f, 0)(a[base_type::a1_]); + } + + template void accept(V & v) const + { + base_type::accept(v); + } + + bool operator==(list1 const & rhs) const + { + return ref_compare(base_type::a1_, rhs.a1_, 0); + } +}; + +struct logical_and; +struct logical_or; + +template< class A1, class A2 > class list2: private storage2< A1, A2 > +{ +private: + + typedef storage2< A1, A2 > base_type; + +public: + + list2( A1 a1, A2 a2 ): base_type( a1, a2 ) {} + + A1 operator[] (boost::arg<1>) const { return base_type::a1_; } + A2 operator[] (boost::arg<2>) const { return base_type::a2_; } + + A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } + A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } + + template T & operator[] (_bi::value & v) const { return v.get(); } + + template T const & operator[] (_bi::value const & v) const { return v.get(); } + + template T & operator[] (reference_wrapper const & v) const { return v.get(); } + + template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } + + template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } + + template R operator()(type, F & f, A & a, long) + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]); + } + + template R operator()(type, F const & f, A & a, long) const + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]); + } + + template void operator()(type, F & f, A & a, int) + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]); + } + + template void operator()(type, F const & f, A & a, int) const + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]); + } + + template bool operator()( type, logical_and & /*f*/, A & a, int ) + { + return a[ base_type::a1_ ] && a[ base_type::a2_ ]; + } + + template bool operator()( type, logical_and const & /*f*/, A & a, int ) const + { + return a[ base_type::a1_ ] && a[ base_type::a2_ ]; + } + + template bool operator()( type, logical_or & /*f*/, A & a, int ) + { + return a[ base_type::a1_ ] || a[ base_type::a2_ ]; + } + + template bool operator()( type, logical_or const & /*f*/, A & a, int ) const + { + return a[ base_type::a1_ ] || a[ base_type::a2_ ]; + } + + template void accept(V & v) const + { + base_type::accept(v); + } + + bool operator==(list2 const & rhs) const + { + return ref_compare(base_type::a1_, rhs.a1_, 0) && ref_compare(base_type::a2_, rhs.a2_, 0); + } +}; + +template< class A1, class A2, class A3 > class list3: private storage3< A1, A2, A3 > +{ +private: + + typedef storage3< A1, A2, A3 > base_type; + +public: + + list3( A1 a1, A2 a2, A3 a3 ): base_type( a1, a2, a3 ) {} + + A1 operator[] (boost::arg<1>) const { return base_type::a1_; } + A2 operator[] (boost::arg<2>) const { return base_type::a2_; } + A3 operator[] (boost::arg<3>) const { return base_type::a3_; } + + A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } + A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } + A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; } + + template T & operator[] (_bi::value & v) const { return v.get(); } + + template T const & operator[] (_bi::value const & v) const { return v.get(); } + + template T & operator[] (reference_wrapper const & v) const { return v.get(); } + + template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } + + template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } + + template R operator()(type, F & f, A & a, long) + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_]); + } + + template R operator()(type, F const & f, A & a, long) const + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_]); + } + + template void operator()(type, F & f, A & a, int) + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_]); + } + + template void operator()(type, F const & f, A & a, int) const + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_]); + } + + template void accept(V & v) const + { + base_type::accept(v); + } + + bool operator==(list3 const & rhs) const + { + return + + ref_compare( base_type::a1_, rhs.a1_, 0 ) && + ref_compare( base_type::a2_, rhs.a2_, 0 ) && + ref_compare( base_type::a3_, rhs.a3_, 0 ); + } +}; + +template< class A1, class A2, class A3, class A4 > class list4: private storage4< A1, A2, A3, A4 > +{ +private: + + typedef storage4< A1, A2, A3, A4 > base_type; + +public: + + list4( A1 a1, A2 a2, A3 a3, A4 a4 ): base_type( a1, a2, a3, a4 ) {} + + A1 operator[] (boost::arg<1>) const { return base_type::a1_; } + A2 operator[] (boost::arg<2>) const { return base_type::a2_; } + A3 operator[] (boost::arg<3>) const { return base_type::a3_; } + A4 operator[] (boost::arg<4>) const { return base_type::a4_; } + + A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } + A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } + A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; } + A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; } + + template T & operator[] (_bi::value & v) const { return v.get(); } + + template T const & operator[] (_bi::value const & v) const { return v.get(); } + + template T & operator[] (reference_wrapper const & v) const { return v.get(); } + + template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } + + template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } + + template R operator()(type, F & f, A & a, long) + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_]); + } + + template R operator()(type, F const & f, A & a, long) const + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_]); + } + + template void operator()(type, F & f, A & a, int) + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_]); + } + + template void operator()(type, F const & f, A & a, int) const + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_]); + } + + template void accept(V & v) const + { + base_type::accept(v); + } + + bool operator==(list4 const & rhs) const + { + return + + ref_compare( base_type::a1_, rhs.a1_, 0 ) && + ref_compare( base_type::a2_, rhs.a2_, 0 ) && + ref_compare( base_type::a3_, rhs.a3_, 0 ) && + ref_compare( base_type::a4_, rhs.a4_, 0 ); + } +}; + +template< class A1, class A2, class A3, class A4, class A5 > class list5: private storage5< A1, A2, A3, A4, A5 > +{ +private: + + typedef storage5< A1, A2, A3, A4, A5 > base_type; + +public: + + list5( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5 ): base_type( a1, a2, a3, a4, a5 ) {} + + A1 operator[] (boost::arg<1>) const { return base_type::a1_; } + A2 operator[] (boost::arg<2>) const { return base_type::a2_; } + A3 operator[] (boost::arg<3>) const { return base_type::a3_; } + A4 operator[] (boost::arg<4>) const { return base_type::a4_; } + A5 operator[] (boost::arg<5>) const { return base_type::a5_; } + + A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } + A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } + A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; } + A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; } + A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; } + + template T & operator[] (_bi::value & v) const { return v.get(); } + + template T const & operator[] (_bi::value const & v) const { return v.get(); } + + template T & operator[] (reference_wrapper const & v) const { return v.get(); } + + template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } + + template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } + + template R operator()(type, F & f, A & a, long) + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_]); + } + + template R operator()(type, F const & f, A & a, long) const + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_]); + } + + template void operator()(type, F & f, A & a, int) + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_]); + } + + template void operator()(type, F const & f, A & a, int) const + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_]); + } + + template void accept(V & v) const + { + base_type::accept(v); + } + + bool operator==(list5 const & rhs) const + { + return + + ref_compare( base_type::a1_, rhs.a1_, 0 ) && + ref_compare( base_type::a2_, rhs.a2_, 0 ) && + ref_compare( base_type::a3_, rhs.a3_, 0 ) && + ref_compare( base_type::a4_, rhs.a4_, 0 ) && + ref_compare( base_type::a5_, rhs.a5_, 0 ); + } +}; + +template class list6: private storage6< A1, A2, A3, A4, A5, A6 > +{ +private: + + typedef storage6< A1, A2, A3, A4, A5, A6 > base_type; + +public: + + list6( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6 ): base_type( a1, a2, a3, a4, a5, a6 ) {} + + A1 operator[] (boost::arg<1>) const { return base_type::a1_; } + A2 operator[] (boost::arg<2>) const { return base_type::a2_; } + A3 operator[] (boost::arg<3>) const { return base_type::a3_; } + A4 operator[] (boost::arg<4>) const { return base_type::a4_; } + A5 operator[] (boost::arg<5>) const { return base_type::a5_; } + A6 operator[] (boost::arg<6>) const { return base_type::a6_; } + + A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } + A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } + A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; } + A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; } + A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; } + A6 operator[] (boost::arg<6> (*) ()) const { return base_type::a6_; } + + template T & operator[] (_bi::value & v) const { return v.get(); } + + template T const & operator[] (_bi::value const & v) const { return v.get(); } + + template T & operator[] (reference_wrapper const & v) const { return v.get(); } + + template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } + + template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } + + template R operator()(type, F & f, A & a, long) + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_]); + } + + template R operator()(type, F const & f, A & a, long) const + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_]); + } + + template void operator()(type, F & f, A & a, int) + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_]); + } + + template void operator()(type, F const & f, A & a, int) const + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_]); + } + + template void accept(V & v) const + { + base_type::accept(v); + } + + bool operator==(list6 const & rhs) const + { + return + + ref_compare( base_type::a1_, rhs.a1_, 0 ) && + ref_compare( base_type::a2_, rhs.a2_, 0 ) && + ref_compare( base_type::a3_, rhs.a3_, 0 ) && + ref_compare( base_type::a4_, rhs.a4_, 0 ) && + ref_compare( base_type::a5_, rhs.a5_, 0 ) && + ref_compare( base_type::a6_, rhs.a6_, 0 ); + } +}; + +template class list7: private storage7< A1, A2, A3, A4, A5, A6, A7 > +{ +private: + + typedef storage7< A1, A2, A3, A4, A5, A6, A7 > base_type; + +public: + + list7( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7 ): base_type( a1, a2, a3, a4, a5, a6, a7 ) {} + + A1 operator[] (boost::arg<1>) const { return base_type::a1_; } + A2 operator[] (boost::arg<2>) const { return base_type::a2_; } + A3 operator[] (boost::arg<3>) const { return base_type::a3_; } + A4 operator[] (boost::arg<4>) const { return base_type::a4_; } + A5 operator[] (boost::arg<5>) const { return base_type::a5_; } + A6 operator[] (boost::arg<6>) const { return base_type::a6_; } + A7 operator[] (boost::arg<7>) const { return base_type::a7_; } + + A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } + A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } + A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; } + A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; } + A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; } + A6 operator[] (boost::arg<6> (*) ()) const { return base_type::a6_; } + A7 operator[] (boost::arg<7> (*) ()) const { return base_type::a7_; } + + template T & operator[] (_bi::value & v) const { return v.get(); } + + template T const & operator[] (_bi::value const & v) const { return v.get(); } + + template T & operator[] (reference_wrapper const & v) const { return v.get(); } + + template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } + + template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } + + template R operator()(type, F & f, A & a, long) + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_]); + } + + template R operator()(type, F const & f, A & a, long) const + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_]); + } + + template void operator()(type, F & f, A & a, int) + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_]); + } + + template void operator()(type, F const & f, A & a, int) const + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_]); + } + + template void accept(V & v) const + { + base_type::accept(v); + } + + bool operator==(list7 const & rhs) const + { + return + + ref_compare( base_type::a1_, rhs.a1_, 0 ) && + ref_compare( base_type::a2_, rhs.a2_, 0 ) && + ref_compare( base_type::a3_, rhs.a3_, 0 ) && + ref_compare( base_type::a4_, rhs.a4_, 0 ) && + ref_compare( base_type::a5_, rhs.a5_, 0 ) && + ref_compare( base_type::a6_, rhs.a6_, 0 ) && + ref_compare( base_type::a7_, rhs.a7_, 0 ); + } +}; + +template< class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > class list8: private storage8< A1, A2, A3, A4, A5, A6, A7, A8 > +{ +private: + + typedef storage8< A1, A2, A3, A4, A5, A6, A7, A8 > base_type; + +public: + + list8( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8 ): base_type( a1, a2, a3, a4, a5, a6, a7, a8 ) {} + + A1 operator[] (boost::arg<1>) const { return base_type::a1_; } + A2 operator[] (boost::arg<2>) const { return base_type::a2_; } + A3 operator[] (boost::arg<3>) const { return base_type::a3_; } + A4 operator[] (boost::arg<4>) const { return base_type::a4_; } + A5 operator[] (boost::arg<5>) const { return base_type::a5_; } + A6 operator[] (boost::arg<6>) const { return base_type::a6_; } + A7 operator[] (boost::arg<7>) const { return base_type::a7_; } + A8 operator[] (boost::arg<8>) const { return base_type::a8_; } + + A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } + A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } + A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; } + A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; } + A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; } + A6 operator[] (boost::arg<6> (*) ()) const { return base_type::a6_; } + A7 operator[] (boost::arg<7> (*) ()) const { return base_type::a7_; } + A8 operator[] (boost::arg<8> (*) ()) const { return base_type::a8_; } + + template T & operator[] (_bi::value & v) const { return v.get(); } + + template T const & operator[] (_bi::value const & v) const { return v.get(); } + + template T & operator[] (reference_wrapper const & v) const { return v.get(); } + + template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } + + template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } + + template R operator()(type, F & f, A & a, long) + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_]); + } + + template R operator()(type, F const & f, A & a, long) const + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_]); + } + + template void operator()(type, F & f, A & a, int) + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_]); + } + + template void operator()(type, F const & f, A & a, int) const + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_]); + } + + template void accept(V & v) const + { + base_type::accept(v); + } + + bool operator==(list8 const & rhs) const + { + return + + ref_compare( base_type::a1_, rhs.a1_, 0 ) && + ref_compare( base_type::a2_, rhs.a2_, 0 ) && + ref_compare( base_type::a3_, rhs.a3_, 0 ) && + ref_compare( base_type::a4_, rhs.a4_, 0 ) && + ref_compare( base_type::a5_, rhs.a5_, 0 ) && + ref_compare( base_type::a6_, rhs.a6_, 0 ) && + ref_compare( base_type::a7_, rhs.a7_, 0 ) && + ref_compare( base_type::a8_, rhs.a8_, 0 ); + } +}; + +template class list9: private storage9< A1, A2, A3, A4, A5, A6, A7, A8, A9 > +{ +private: + + typedef storage9< A1, A2, A3, A4, A5, A6, A7, A8, A9 > base_type; + +public: + + list9( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9 ): base_type( a1, a2, a3, a4, a5, a6, a7, a8, a9 ) {} + + A1 operator[] (boost::arg<1>) const { return base_type::a1_; } + A2 operator[] (boost::arg<2>) const { return base_type::a2_; } + A3 operator[] (boost::arg<3>) const { return base_type::a3_; } + A4 operator[] (boost::arg<4>) const { return base_type::a4_; } + A5 operator[] (boost::arg<5>) const { return base_type::a5_; } + A6 operator[] (boost::arg<6>) const { return base_type::a6_; } + A7 operator[] (boost::arg<7>) const { return base_type::a7_; } + A8 operator[] (boost::arg<8>) const { return base_type::a8_; } + A9 operator[] (boost::arg<9>) const { return base_type::a9_; } + + A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } + A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } + A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; } + A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; } + A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; } + A6 operator[] (boost::arg<6> (*) ()) const { return base_type::a6_; } + A7 operator[] (boost::arg<7> (*) ()) const { return base_type::a7_; } + A8 operator[] (boost::arg<8> (*) ()) const { return base_type::a8_; } + A9 operator[] (boost::arg<9> (*) ()) const { return base_type::a9_; } + + template T & operator[] (_bi::value & v) const { return v.get(); } + + template T const & operator[] (_bi::value const & v) const { return v.get(); } + + template T & operator[] (reference_wrapper const & v) const { return v.get(); } + + template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } + + template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } + + template R operator()(type, F & f, A & a, long) + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_], a[base_type::a9_]); + } + + template R operator()(type, F const & f, A & a, long) const + { + return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_], a[base_type::a9_]); + } + + template void operator()(type, F & f, A & a, int) + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_], a[base_type::a9_]); + } + + template void operator()(type, F const & f, A & a, int) const + { + unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_], a[base_type::a9_]); + } + + template void accept(V & v) const + { + base_type::accept(v); + } + + bool operator==(list9 const & rhs) const + { + return + + ref_compare( base_type::a1_, rhs.a1_, 0 ) && + ref_compare( base_type::a2_, rhs.a2_, 0 ) && + ref_compare( base_type::a3_, rhs.a3_, 0 ) && + ref_compare( base_type::a4_, rhs.a4_, 0 ) && + ref_compare( base_type::a5_, rhs.a5_, 0 ) && + ref_compare( base_type::a6_, rhs.a6_, 0 ) && + ref_compare( base_type::a7_, rhs.a7_, 0 ) && + ref_compare( base_type::a8_, rhs.a8_, 0 ) && + ref_compare( base_type::a9_, rhs.a9_, 0 ); + } +}; + +// bind_t + +#ifndef BOOST_NO_VOID_RETURNS + +template class bind_t +{ +public: + + typedef bind_t this_type; + + bind_t(F f, L const & l): f_(f), l_(l) {} + +#define BOOST_BIND_RETURN return +#include +#undef BOOST_BIND_RETURN + +}; + +#else + +template struct bind_t_generator +{ + +template class implementation +{ +public: + + typedef implementation this_type; + + implementation(F f, L const & l): f_(f), l_(l) {} + +#define BOOST_BIND_RETURN return +#include +#undef BOOST_BIND_RETURN + +}; + +}; + +template<> struct bind_t_generator +{ + +template class implementation +{ +private: + + typedef void R; + +public: + + typedef implementation this_type; + + implementation(F f, L const & l): f_(f), l_(l) {} + +#define BOOST_BIND_RETURN +#include +#undef BOOST_BIND_RETURN + +}; + +}; + +template class bind_t: public bind_t_generator::BOOST_NESTED_TEMPLATE implementation +{ +public: + + bind_t(F f, L const & l): bind_t_generator::BOOST_NESTED_TEMPLATE implementation(f, l) {} + +}; + +#endif + +// function_equal + +#ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP + +// put overloads in _bi, rely on ADL + +# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +template bool function_equal( bind_t const & a, bind_t const & b ) +{ + return a.compare(b); +} + +# else + +template bool function_equal_impl( bind_t const & a, bind_t const & b, int ) +{ + return a.compare(b); +} + +# endif // #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +#else // BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP + +// put overloads in boost + +} // namespace _bi + +# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +template bool function_equal( _bi::bind_t const & a, _bi::bind_t const & b ) +{ + return a.compare(b); +} + +# else + +template bool function_equal_impl( _bi::bind_t const & a, _bi::bind_t const & b, int ) +{ + return a.compare(b); +} + +# endif // #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +namespace _bi +{ + +#endif // BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP + +// add_value + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || (__SUNPRO_CC >= 0x530) + +#if defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x582) ) + +template struct add_value +{ + typedef _bi::value type; +}; + +#else + +template< class T, int I > struct add_value_2 +{ + typedef boost::arg type; +}; + +template< class T > struct add_value_2< T, 0 > +{ + typedef _bi::value< T > type; +}; + +template struct add_value +{ + typedef typename add_value_2< T, boost::is_placeholder< T >::value >::type type; +}; + +#endif + +template struct add_value< value > +{ + typedef _bi::value type; +}; + +template struct add_value< reference_wrapper > +{ + typedef reference_wrapper type; +}; + +template struct add_value< arg > +{ + typedef boost::arg type; +}; + +template struct add_value< arg (*) () > +{ + typedef boost::arg (*type) (); +}; + +template struct add_value< bind_t > +{ + typedef bind_t type; +}; + +#else + +template struct _avt_0; + +template<> struct _avt_0<1> +{ + template struct inner + { + typedef T type; + }; +}; + +template<> struct _avt_0<2> +{ + template struct inner + { + typedef value type; + }; +}; + +typedef char (&_avt_r1) [1]; +typedef char (&_avt_r2) [2]; + +template _avt_r1 _avt_f(value); +template _avt_r1 _avt_f(reference_wrapper); +template _avt_r1 _avt_f(arg); +template _avt_r1 _avt_f(arg (*) ()); +template _avt_r1 _avt_f(bind_t); + +_avt_r2 _avt_f(...); + +template struct add_value +{ + static T t(); + typedef typename _avt_0::template inner::type type; +}; + +#endif + +// list_av_N + +template struct list_av_1 +{ + typedef typename add_value::type B1; + typedef list1 type; +}; + +template struct list_av_2 +{ + typedef typename add_value::type B1; + typedef typename add_value::type B2; + typedef list2 type; +}; + +template struct list_av_3 +{ + typedef typename add_value::type B1; + typedef typename add_value::type B2; + typedef typename add_value::type B3; + typedef list3 type; +}; + +template struct list_av_4 +{ + typedef typename add_value::type B1; + typedef typename add_value::type B2; + typedef typename add_value::type B3; + typedef typename add_value::type B4; + typedef list4 type; +}; + +template struct list_av_5 +{ + typedef typename add_value::type B1; + typedef typename add_value::type B2; + typedef typename add_value::type B3; + typedef typename add_value::type B4; + typedef typename add_value::type B5; + typedef list5 type; +}; + +template struct list_av_6 +{ + typedef typename add_value::type B1; + typedef typename add_value::type B2; + typedef typename add_value::type B3; + typedef typename add_value::type B4; + typedef typename add_value::type B5; + typedef typename add_value::type B6; + typedef list6 type; +}; + +template struct list_av_7 +{ + typedef typename add_value::type B1; + typedef typename add_value::type B2; + typedef typename add_value::type B3; + typedef typename add_value::type B4; + typedef typename add_value::type B5; + typedef typename add_value::type B6; + typedef typename add_value::type B7; + typedef list7 type; +}; + +template struct list_av_8 +{ + typedef typename add_value::type B1; + typedef typename add_value::type B2; + typedef typename add_value::type B3; + typedef typename add_value::type B4; + typedef typename add_value::type B5; + typedef typename add_value::type B6; + typedef typename add_value::type B7; + typedef typename add_value::type B8; + typedef list8 type; +}; + +template struct list_av_9 +{ + typedef typename add_value::type B1; + typedef typename add_value::type B2; + typedef typename add_value::type B3; + typedef typename add_value::type B4; + typedef typename add_value::type B5; + typedef typename add_value::type B6; + typedef typename add_value::type B7; + typedef typename add_value::type B8; + typedef typename add_value::type B9; + typedef list9 type; +}; + +// operator! + +struct logical_not +{ + template bool operator()(V const & v) const { return !v; } +}; + +template + bind_t< bool, logical_not, list1< bind_t > > + operator! (bind_t const & f) +{ + typedef list1< bind_t > list_type; + return bind_t ( logical_not(), list_type(f) ); +} + +// relational operators + +#define BOOST_BIND_OPERATOR( op, name ) \ +\ +struct name \ +{ \ + template bool operator()(V const & v, W const & w) const { return v op w; } \ +}; \ + \ +template \ + bind_t< bool, name, list2< bind_t, typename add_value::type > > \ + operator op (bind_t const & f, A2 a2) \ +{ \ + typedef typename add_value::type B2; \ + typedef list2< bind_t, B2> list_type; \ + return bind_t ( name(), list_type(f, a2) ); \ +} + +BOOST_BIND_OPERATOR( ==, equal ) +BOOST_BIND_OPERATOR( !=, not_equal ) + +BOOST_BIND_OPERATOR( <, less ) +BOOST_BIND_OPERATOR( <=, less_equal ) + +BOOST_BIND_OPERATOR( >, greater ) +BOOST_BIND_OPERATOR( >=, greater_equal ) + +BOOST_BIND_OPERATOR( &&, logical_and ) +BOOST_BIND_OPERATOR( ||, logical_or ) + +#undef BOOST_BIND_OPERATOR + +#if defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) + +// resolve ambiguity with rel_ops + +#define BOOST_BIND_OPERATOR( op, name ) \ +\ +template \ + bind_t< bool, name, list2< bind_t, bind_t > > \ + operator op (bind_t const & f, bind_t const & g) \ +{ \ + typedef list2< bind_t, bind_t > list_type; \ + return bind_t ( name(), list_type(f, g) ); \ +} + +BOOST_BIND_OPERATOR( !=, not_equal ) +BOOST_BIND_OPERATOR( <=, less_equal ) +BOOST_BIND_OPERATOR( >, greater ) +BOOST_BIND_OPERATOR( >=, greater_equal ) + +#endif + +// visit_each, ADL + +#if !defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) && !defined( __BORLANDC__ ) \ + && !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) + +template void visit_each( V & v, value const & t, int ) +{ + using boost::visit_each; + BOOST_BIND_VISIT_EACH( v, t.get(), 0 ); +} + +template void visit_each( V & v, bind_t const & t, int ) +{ + t.accept( v ); +} + +#endif + +} // namespace _bi + +// visit_each, no ADL + +#if defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) || defined( __BORLANDC__ ) \ + || (defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) + +template void visit_each( V & v, _bi::value const & t, int ) +{ + BOOST_BIND_VISIT_EACH( v, t.get(), 0 ); +} + +template void visit_each( V & v, _bi::bind_t const & t, int ) +{ + t.accept( v ); +} + +#endif + +// is_bind_expression + +template< class T > struct is_bind_expression +{ + enum _vt { value = 0 }; +}; + +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + +template< class R, class F, class L > struct is_bind_expression< _bi::bind_t< R, F, L > > +{ + enum _vt { value = 1 }; +}; + +#endif + +// bind + +#ifndef BOOST_BIND +#define BOOST_BIND bind +#endif + +// generic function objects + +template + _bi::bind_t + BOOST_BIND(F f) +{ + typedef _bi::list0 list_type; + return _bi::bind_t (f, list_type()); +} + +template + _bi::bind_t::type> + BOOST_BIND(F f, A1 a1) +{ + typedef typename _bi::list_av_1::type list_type; + return _bi::bind_t (f, list_type(a1)); +} + +template + _bi::bind_t::type> + BOOST_BIND(F f, A1 a1, A2 a2) +{ + typedef typename _bi::list_av_2::type list_type; + return _bi::bind_t (f, list_type(a1, a2)); +} + +template + _bi::bind_t::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3) +{ + typedef typename _bi::list_av_3::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3)); +} + +template + _bi::bind_t::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4) +{ + typedef typename _bi::list_av_4::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4)); +} + +template + _bi::bind_t::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) +{ + typedef typename _bi::list_av_5::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5)); +} + +template + _bi::bind_t::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) +{ + typedef typename _bi::list_av_6::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6)); +} + +template + _bi::bind_t::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) +{ + typedef typename _bi::list_av_7::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7)); +} + +template + _bi::bind_t::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) +{ + typedef typename _bi::list_av_8::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8)); +} + +template + _bi::bind_t::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) +{ + typedef typename _bi::list_av_9::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); +} + +// generic function objects, alternative syntax + +template + _bi::bind_t + BOOST_BIND(boost::type, F f) +{ + typedef _bi::list0 list_type; + return _bi::bind_t (f, list_type()); +} + +template + _bi::bind_t::type> + BOOST_BIND(boost::type, F f, A1 a1) +{ + typedef typename _bi::list_av_1::type list_type; + return _bi::bind_t (f, list_type(a1)); +} + +template + _bi::bind_t::type> + BOOST_BIND(boost::type, F f, A1 a1, A2 a2) +{ + typedef typename _bi::list_av_2::type list_type; + return _bi::bind_t (f, list_type(a1, a2)); +} + +template + _bi::bind_t::type> + BOOST_BIND(boost::type, F f, A1 a1, A2 a2, A3 a3) +{ + typedef typename _bi::list_av_3::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3)); +} + +template + _bi::bind_t::type> + BOOST_BIND(boost::type, F f, A1 a1, A2 a2, A3 a3, A4 a4) +{ + typedef typename _bi::list_av_4::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4)); +} + +template + _bi::bind_t::type> + BOOST_BIND(boost::type, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) +{ + typedef typename _bi::list_av_5::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5)); +} + +template + _bi::bind_t::type> + BOOST_BIND(boost::type, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) +{ + typedef typename _bi::list_av_6::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6)); +} + +template + _bi::bind_t::type> + BOOST_BIND(boost::type, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) +{ + typedef typename _bi::list_av_7::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7)); +} + +template + _bi::bind_t::type> + BOOST_BIND(boost::type, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) +{ + typedef typename _bi::list_av_8::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8)); +} + +template + _bi::bind_t::type> + BOOST_BIND(boost::type, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) +{ + typedef typename _bi::list_av_9::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); +} + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + +// adaptable function objects + +template + _bi::bind_t<_bi::unspecified, F, _bi::list0> + BOOST_BIND(F f) +{ + typedef _bi::list0 list_type; + return _bi::bind_t<_bi::unspecified, F, list_type> (f, list_type()); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_1::type> + BOOST_BIND(F f, A1 a1) +{ + typedef typename _bi::list_av_1::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type> (f, list_type(a1)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_2::type> + BOOST_BIND(F f, A1 a1, A2 a2) +{ + typedef typename _bi::list_av_2::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type> (f, list_type(a1, a2)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_3::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3) +{ + typedef typename _bi::list_av_3::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_4::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4) +{ + typedef typename _bi::list_av_4::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_5::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) +{ + typedef typename _bi::list_av_5::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_6::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) +{ + typedef typename _bi::list_av_6::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_7::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) +{ + typedef typename _bi::list_av_7::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_8::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) +{ + typedef typename _bi::list_av_8::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8)); +} + +template + _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_9::type> + BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) +{ + typedef typename _bi::list_av_9::type list_type; + return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); +} + +#endif // !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + +// function pointers + +#define BOOST_BIND_CC +#define BOOST_BIND_ST + +#include + +#undef BOOST_BIND_CC +#undef BOOST_BIND_ST + +#ifdef BOOST_BIND_ENABLE_STDCALL + +#define BOOST_BIND_CC __stdcall +#define BOOST_BIND_ST + +#include + +#undef BOOST_BIND_CC +#undef BOOST_BIND_ST + +#endif + +#ifdef BOOST_BIND_ENABLE_FASTCALL + +#define BOOST_BIND_CC __fastcall +#define BOOST_BIND_ST + +#include + +#undef BOOST_BIND_CC +#undef BOOST_BIND_ST + +#endif + +#ifdef BOOST_BIND_ENABLE_PASCAL + +#define BOOST_BIND_ST pascal +#define BOOST_BIND_CC + +#include + +#undef BOOST_BIND_ST +#undef BOOST_BIND_CC + +#endif + +// member function pointers + +#define BOOST_BIND_MF_NAME(X) X +#define BOOST_BIND_MF_CC + +#include +#include + +#undef BOOST_BIND_MF_NAME +#undef BOOST_BIND_MF_CC + +#ifdef BOOST_MEM_FN_ENABLE_CDECL + +#define BOOST_BIND_MF_NAME(X) X##_cdecl +#define BOOST_BIND_MF_CC __cdecl + +#include +#include + +#undef BOOST_BIND_MF_NAME +#undef BOOST_BIND_MF_CC + +#endif + +#ifdef BOOST_MEM_FN_ENABLE_STDCALL + +#define BOOST_BIND_MF_NAME(X) X##_stdcall +#define BOOST_BIND_MF_CC __stdcall + +#include +#include + +#undef BOOST_BIND_MF_NAME +#undef BOOST_BIND_MF_CC + +#endif + +#ifdef BOOST_MEM_FN_ENABLE_FASTCALL + +#define BOOST_BIND_MF_NAME(X) X##_fastcall +#define BOOST_BIND_MF_CC __fastcall + +#include +#include + +#undef BOOST_BIND_MF_NAME +#undef BOOST_BIND_MF_CC + +#endif + +// data member pointers + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ + || ( defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x600 ) ) + +template +_bi::bind_t< R, _mfi::dm, typename _bi::list_av_1::type > + BOOST_BIND(R T::*f, A1 a1) +{ + typedef _mfi::dm F; + typedef typename _bi::list_av_1::type list_type; + return _bi::bind_t( F(f), list_type(a1) ); +} + +#else + +namespace _bi +{ + +template< class Pm, int I > struct add_cref; + +template< class M, class T > struct add_cref< M T::*, 0 > +{ + typedef M type; +}; + +template< class M, class T > struct add_cref< M T::*, 1 > +{ + typedef M const & type; +}; + +template< class R, class T > struct add_cref< R (T::*) (), 1 > +{ + typedef void type; +}; + +#if !( defined(__IBMCPP__) && BOOST_WORKAROUND( __IBMCPP__, BOOST_TESTED_AT(600) ) ) + +template< class R, class T > struct add_cref< R (T::*) () const, 1 > +{ + typedef void type; +}; + +#endif // __IBMCPP__ + +template struct isref +{ + enum value_type { value = 0 }; +}; + +template struct isref< R& > +{ + enum value_type { value = 1 }; +}; + +template struct isref< R* > +{ + enum value_type { value = 1 }; +}; + +template struct dm_result +{ + typedef typename add_cref< Pm, 1 >::type type; +}; + +template struct dm_result< Pm, bind_t > +{ + typedef typename bind_t::result_type result_type; + typedef typename add_cref< Pm, isref< result_type >::value >::type type; +}; + +} // namespace _bi + +template< class A1, class M, class T > + +_bi::bind_t< + typename _bi::dm_result< M T::*, A1 >::type, + _mfi::dm, + typename _bi::list_av_1::type +> + +BOOST_BIND( M T::*f, A1 a1 ) +{ + typedef typename _bi::dm_result< M T::*, A1 >::type result_type; + typedef _mfi::dm F; + typedef typename _bi::list_av_1::type list_type; + return _bi::bind_t< result_type, F, list_type >( F( f ), list_type( a1 ) ); +} + +#endif + +} // namespace boost + +#ifndef BOOST_BIND_NO_PLACEHOLDERS + +# include + +#endif + +#ifdef BOOST_MSVC +# pragma warning(default: 4512) // assignment operator could not be generated +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_BIND_HPP_INCLUDED diff --git a/win32/include/boost/bind/apply.hpp b/win32/include/boost/bind/apply.hpp new file mode 100755 index 000000000..5ca4e1de5 --- /dev/null +++ b/win32/include/boost/bind/apply.hpp @@ -0,0 +1,74 @@ +#ifndef BOOST_BIND_APPLY_HPP_INCLUDED +#define BOOST_BIND_APPLY_HPP_INCLUDED + +// +// apply.hpp +// +// Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd. +// +// 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) +// + +namespace boost +{ + +template struct apply +{ + typedef R result_type; + + template result_type operator()(F & f) const + { + return f(); + } + + template result_type operator()(F & f, A1 & a1) const + { + return f(a1); + } + + template result_type operator()(F & f, A1 & a1, A2 & a2) const + { + return f(a1, a2); + } + + template result_type operator()(F & f, A1 & a1, A2 & a2, A3 & a3) const + { + return f(a1, a2, a3); + } + + template result_type operator()(F & f, A1 & a1, A2 & a2, A3 & a3, A4 & a4) const + { + return f(a1, a2, a3, a4); + } + + template result_type operator()(F & f, A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5) const + { + return f(a1, a2, a3, a4, a5); + } + + template result_type operator()(F & f, A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6) const + { + return f(a1, a2, a3, a4, a5, a6); + } + + template result_type operator()(F & f, A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7) const + { + return f(a1, a2, a3, a4, a5, a6, a7); + } + + template result_type operator()(F & f, A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8) const + { + return f(a1, a2, a3, a4, a5, a6, a7, a8); + } + + template result_type operator()(F & f, A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9) const + { + return f(a1, a2, a3, a4, a5, a6, a7, a8, a9); + } +}; + +} // namespace boost + +#endif // #ifndef BOOST_BIND_APPLY_HPP_INCLUDED diff --git a/win32/include/boost/bind/arg.hpp b/win32/include/boost/bind/arg.hpp new file mode 100755 index 000000000..c08291a36 --- /dev/null +++ b/win32/include/boost/bind/arg.hpp @@ -0,0 +1,62 @@ +#ifndef BOOST_BIND_ARG_HPP_INCLUDED +#define BOOST_BIND_ARG_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// bind/arg.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// 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) +// +// See http://www.boost.org/libs/bind/bind.html for documentation. +// + +#include +#include + +namespace boost +{ + +template< int I > struct arg +{ + arg() + { + } + + template< class T > arg( T const & /* t */ ) + { + // static assert I == is_placeholder::value + typedef char T_must_be_placeholder[ I == is_placeholder::value? 1: -1 ]; + } +}; + +template< int I > bool operator==( arg const &, arg const & ) +{ + return true; +} + +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + +template< int I > struct is_placeholder< arg > +{ + enum _vt { value = I }; +}; + +template< int I > struct is_placeholder< arg (*) () > +{ + enum _vt { value = I }; +}; + +#endif + +} // namespace boost + +#endif // #ifndef BOOST_BIND_ARG_HPP_INCLUDED diff --git a/win32/include/boost/bind/bind_cc.hpp b/win32/include/boost/bind/bind_cc.hpp new file mode 100755 index 000000000..9d8ca2198 --- /dev/null +++ b/win32/include/boost/bind/bind_cc.hpp @@ -0,0 +1,117 @@ +// +// bind/bind_cc.hpp - support for different calling conventions +// +// Do not include this header directly. +// +// Copyright (c) 2001 Peter Dimov and Multi Media Ltd. +// +// 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) +// +// See http://www.boost.org/libs/bind/bind.html for documentation. +// + +template + _bi::bind_t + BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) ()) +{ + typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (); + typedef _bi::list0 list_type; + return _bi::bind_t (f, list_type()); +} + +template + _bi::bind_t::type> + BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1), A1 a1) +{ + typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1); + typedef typename _bi::list_av_1::type list_type; + return _bi::bind_t (f, list_type(a1)); +} + +template + _bi::bind_t::type> + BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2), A1 a1, A2 a2) +{ + typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2); + typedef typename _bi::list_av_2::type list_type; + return _bi::bind_t (f, list_type(a1, a2)); +} + +template + _bi::bind_t::type> + BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3), A1 a1, A2 a2, A3 a3) +{ + typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3); + typedef typename _bi::list_av_3::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3)); +} + +template + _bi::bind_t::type> + BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4), A1 a1, A2 a2, A3 a3, A4 a4) +{ + typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4); + typedef typename _bi::list_av_4::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4)); +} + +template + _bi::bind_t::type> + BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) +{ + typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5); + typedef typename _bi::list_av_5::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5)); +} + +template + _bi::bind_t::type> + BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5, B6), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) +{ + typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5, B6); + typedef typename _bi::list_av_6::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6)); +} + +template + _bi::bind_t::type> + BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5, B6, B7), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) +{ + typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5, B6, B7); + typedef typename _bi::list_av_7::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7)); +} + +template + _bi::bind_t::type> + BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5, B6, B7, B8), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) +{ + typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5, B6, B7, B8); + typedef typename _bi::list_av_8::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8)); +} + +template + _bi::bind_t::type> + BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5, B6, B7, B8, B9), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) +{ + typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5, B6, B7, B8, B9); + typedef typename _bi::list_av_9::type list_type; + return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); +} diff --git a/win32/include/boost/bind/bind_mf2_cc.hpp b/win32/include/boost/bind/bind_mf2_cc.hpp new file mode 100755 index 000000000..e00979ca5 --- /dev/null +++ b/win32/include/boost/bind/bind_mf2_cc.hpp @@ -0,0 +1,228 @@ +// +// bind/bind_mf2_cc.hpp - member functions, type<> syntax +// +// Do not include this header directly. +// +// Copyright (c) 2001 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2008 Peter Dimov +// +// 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 +// +// See http://www.boost.org/libs/bind/bind.html for documentation. +// + +// 0 + +template + _bi::bind_t, typename _bi::list_av_1::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (), A1 a1) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf0) F; + typedef typename _bi::list_av_1::type list_type; + return _bi::bind_t(F(f), list_type(a1)); +} + +template + _bi::bind_t, typename _bi::list_av_1::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) () const, A1 a1) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf0) F; + typedef typename _bi::list_av_1::type list_type; + return _bi::bind_t(F(f), list_type(a1)); +} + +// 1 + +template + _bi::bind_t, typename _bi::list_av_2::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1), A1 a1, A2 a2) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf1) F; + typedef typename _bi::list_av_2::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2)); +} + +template + _bi::bind_t, typename _bi::list_av_2::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1) const, A1 a1, A2 a2) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf1) F; + typedef typename _bi::list_av_2::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2)); +} + +// 2 + +template + _bi::bind_t, typename _bi::list_av_3::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2), A1 a1, A2 a2, A3 a3) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf2) F; + typedef typename _bi::list_av_3::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3)); +} + +template + _bi::bind_t, typename _bi::list_av_3::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2) const, A1 a1, A2 a2, A3 a3) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf2) F; + typedef typename _bi::list_av_3::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3)); +} + +// 3 + +template + _bi::bind_t, typename _bi::list_av_4::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3), A1 a1, A2 a2, A3 a3, A4 a4) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf3) F; + typedef typename _bi::list_av_4::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4)); +} + +template + _bi::bind_t, typename _bi::list_av_4::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3) const, A1 a1, A2 a2, A3 a3, A4 a4) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf3) F; + typedef typename _bi::list_av_4::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4)); +} + +// 4 + +template + _bi::bind_t, typename _bi::list_av_5::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf4) F; + typedef typename _bi::list_av_5::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5)); +} + +template + _bi::bind_t, typename _bi::list_av_5::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf4) F; + typedef typename _bi::list_av_5::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5)); +} + +// 5 + +template + _bi::bind_t, typename _bi::list_av_6::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf5) F; + typedef typename _bi::list_av_6::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6)); +} + +template + _bi::bind_t, typename _bi::list_av_6::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf5) F; + typedef typename _bi::list_av_6::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6)); +} + +// 6 + +template + _bi::bind_t, typename _bi::list_av_7::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf6) F; + typedef typename _bi::list_av_7::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7)); +} + +template + _bi::bind_t, typename _bi::list_av_7::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf6) F; + typedef typename _bi::list_av_7::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7)); +} + +// 7 + +template + _bi::bind_t, typename _bi::list_av_8::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf7) F; + typedef typename _bi::list_av_8::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8)); +} + +template + _bi::bind_t, typename _bi::list_av_8::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf7) F; + typedef typename _bi::list_av_8::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8)); +} + +// 8 + +template + _bi::bind_t, typename _bi::list_av_9::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf8) F; + typedef typename _bi::list_av_9::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); +} + +template + _bi::bind_t, typename _bi::list_av_9::type> + BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf8) F; + typedef typename _bi::list_av_9::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); +} diff --git a/win32/include/boost/bind/bind_mf_cc.hpp b/win32/include/boost/bind/bind_mf_cc.hpp new file mode 100755 index 000000000..49f43a15f --- /dev/null +++ b/win32/include/boost/bind/bind_mf_cc.hpp @@ -0,0 +1,227 @@ +// +// bind/bind_mf_cc.hpp - support for different calling conventions +// +// Do not include this header directly. +// +// Copyright (c) 2001 Peter Dimov and Multi Media Ltd. +// +// 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) +// +// See http://www.boost.org/libs/bind/bind.html for documentation. +// + +// 0 + +template + _bi::bind_t, typename _bi::list_av_1::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (), A1 a1) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf0) F; + typedef typename _bi::list_av_1::type list_type; + return _bi::bind_t(F(f), list_type(a1)); +} + +template + _bi::bind_t, typename _bi::list_av_1::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) () const, A1 a1) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf0) F; + typedef typename _bi::list_av_1::type list_type; + return _bi::bind_t(F(f), list_type(a1)); +} + +// 1 + +template + _bi::bind_t, typename _bi::list_av_2::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1), A1 a1, A2 a2) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf1) F; + typedef typename _bi::list_av_2::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2)); +} + +template + _bi::bind_t, typename _bi::list_av_2::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1) const, A1 a1, A2 a2) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf1) F; + typedef typename _bi::list_av_2::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2)); +} + +// 2 + +template + _bi::bind_t, typename _bi::list_av_3::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2), A1 a1, A2 a2, A3 a3) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf2) F; + typedef typename _bi::list_av_3::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3)); +} + +template + _bi::bind_t, typename _bi::list_av_3::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2) const, A1 a1, A2 a2, A3 a3) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf2) F; + typedef typename _bi::list_av_3::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3)); +} + +// 3 + +template + _bi::bind_t, typename _bi::list_av_4::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3), A1 a1, A2 a2, A3 a3, A4 a4) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf3) F; + typedef typename _bi::list_av_4::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4)); +} + +template + _bi::bind_t, typename _bi::list_av_4::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3) const, A1 a1, A2 a2, A3 a3, A4 a4) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf3) F; + typedef typename _bi::list_av_4::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4)); +} + +// 4 + +template + _bi::bind_t, typename _bi::list_av_5::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf4) F; + typedef typename _bi::list_av_5::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5)); +} + +template + _bi::bind_t, typename _bi::list_av_5::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf4) F; + typedef typename _bi::list_av_5::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5)); +} + +// 5 + +template + _bi::bind_t, typename _bi::list_av_6::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf5) F; + typedef typename _bi::list_av_6::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6)); +} + +template + _bi::bind_t, typename _bi::list_av_6::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf5) F; + typedef typename _bi::list_av_6::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6)); +} + +// 6 + +template + _bi::bind_t, typename _bi::list_av_7::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf6) F; + typedef typename _bi::list_av_7::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7)); +} + +template + _bi::bind_t, typename _bi::list_av_7::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf6) F; + typedef typename _bi::list_av_7::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7)); +} + +// 7 + +template + _bi::bind_t, typename _bi::list_av_8::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf7) F; + typedef typename _bi::list_av_8::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8)); +} + +template + _bi::bind_t, typename _bi::list_av_8::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf7) F; + typedef typename _bi::list_av_8::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8)); +} + +// 8 + +template + _bi::bind_t, typename _bi::list_av_9::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) +{ + typedef _mfi::BOOST_BIND_MF_NAME(mf8) F; + typedef typename _bi::list_av_9::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); +} + +template + _bi::bind_t, typename _bi::list_av_9::type> + BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) +{ + typedef _mfi::BOOST_BIND_MF_NAME(cmf8) F; + typedef typename _bi::list_av_9::type list_type; + return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); +} diff --git a/win32/include/boost/bind/bind_template.hpp b/win32/include/boost/bind/bind_template.hpp new file mode 100755 index 000000000..d394a9bf1 --- /dev/null +++ b/win32/include/boost/bind/bind_template.hpp @@ -0,0 +1,345 @@ +// +// bind/bind_template.hpp +// +// Do not include this header directly. +// +// Copyright (c) 2001-2004 Peter Dimov and Multi Media Ltd. +// +// 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) +// +// See http://www.boost.org/libs/bind/bind.html for documentation. +// + + typedef typename result_traits::type result_type; + + result_type operator()() + { + list0 a; + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + result_type operator()() const + { + list0 a; + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 & a1) + { + list1 a(a1); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 & a1) const + { + list1 a(a1); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ + && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) + + template result_type operator()(A1 const & a1) + { + list1 a(a1); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 const & a1) const + { + list1 a(a1); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#endif + + template result_type operator()(A1 & a1, A2 & a2) + { + list2 a(a1, a2); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 & a1, A2 & a2) const + { + list2 a(a1, a2); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ + && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) + + template result_type operator()(A1 const & a1, A2 & a2) + { + list2 a(a1, a2); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 const & a1, A2 & a2) const + { + list2 a(a1, a2); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + + template result_type operator()(A1 & a1, A2 const & a2) + { + list2 a(a1, a2); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 & a1, A2 const & a2) const + { + list2 a(a1, a2); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + + template result_type operator()(A1 const & a1, A2 const & a2) + { + list2 a(a1, a2); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 const & a1, A2 const & a2) const + { + list2 a(a1, a2); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#endif + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3) + { + list3 a(a1, a2, a3); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3) const + { + list3 a(a1, a2, a3); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ + && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) + + template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3) + { + list3 a(a1, a2, a3); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3) const + { + list3 a(a1, a2, a3); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#endif + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4) + { + list4 a(a1, a2, a3, a4); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4) const + { + list4 a(a1, a2, a3, a4); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ + && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) + + template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4) + { + list4 a(a1, a2, a3, a4); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4) const + { + list4 a(a1, a2, a3, a4); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#endif + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5) + { + list5 a(a1, a2, a3, a4, a5); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5) const + { + list5 a(a1, a2, a3, a4, a5); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ + && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) + + template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5) + { + list5 a(a1, a2, a3, a4, a5); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5) const + { + list5 a(a1, a2, a3, a4, a5); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#endif + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6) + { + list6 a(a1, a2, a3, a4, a5, a6); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6) const + { + list6 a(a1, a2, a3, a4, a5, a6); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ + && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) + + template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6) + { + list6 a(a1, a2, a3, a4, a5, a6); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6) const + { + list6 a(a1, a2, a3, a4, a5, a6); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#endif + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7) + { + list7 a(a1, a2, a3, a4, a5, a6, a7); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7) const + { + list7 a(a1, a2, a3, a4, a5, a6, a7); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ + && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) + + template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7) + { + list7 a(a1, a2, a3, a4, a5, a6, a7); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7) const + { + list7 a(a1, a2, a3, a4, a5, a6, a7); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#endif + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8) + { + list8 a(a1, a2, a3, a4, a5, a6, a7, a8); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8) const + { + list8 a(a1, a2, a3, a4, a5, a6, a7, a8); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ + && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) + + template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8) + { + list8 a(a1, a2, a3, a4, a5, a6, a7, a8); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8) const + { + list8 a(a1, a2, a3, a4, a5, a6, a7, a8); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#endif + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9) + { + list9 a(a1, a2, a3, a4, a5, a6, a7, a8, a9); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9) const + { + list9 a(a1, a2, a3, a4, a5, a6, a7, a8, a9); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ + && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) + + template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9) + { + list9 a(a1, a2, a3, a4, a5, a6, a7, a8, a9); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9) const + { + list9 a(a1, a2, a3, a4, a5, a6, a7, a8, a9); + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + +#endif + + template result_type eval(A & a) + { + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template result_type eval(A & a) const + { + BOOST_BIND_RETURN l_(type(), f_, a, 0); + } + + template void accept(V & v) const + { +#if !defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) && !defined( __BORLANDC__ ) + + using boost::visit_each; + +#endif + BOOST_BIND_VISIT_EACH(v, f_, 0); + l_.accept(v); + } + + bool compare(this_type const & rhs) const + { + return ref_compare(f_, rhs.f_, 0) && l_ == rhs.l_; + } + +private: + + F f_; + L l_; diff --git a/win32/include/boost/bind/make_adaptable.hpp b/win32/include/boost/bind/make_adaptable.hpp new file mode 100755 index 000000000..06ecccffd --- /dev/null +++ b/win32/include/boost/bind/make_adaptable.hpp @@ -0,0 +1,187 @@ +#ifndef BOOST_BIND_MAKE_ADAPTABLE_HPP_INCLUDED +#define BOOST_BIND_MAKE_ADAPTABLE_HPP_INCLUDED + +// +// make_adaptable.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// 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) +// + +namespace boost +{ + +namespace _bi +{ + +template class af0 +{ +public: + + typedef R result_type; + + explicit af0(F f): f_(f) + { + } + + result_type operator()() + { + return f_(); + } + + result_type operator()() const + { + return f_(); + } + +private: + + F f_; +}; + +template class af1 +{ +public: + + typedef R result_type; + typedef A1 argument_type; + typedef A1 arg1_type; + + explicit af1(F f): f_(f) + { + } + + result_type operator()(A1 a1) + { + return f_(a1); + } + + result_type operator()(A1 a1) const + { + return f_(a1); + } + +private: + + F f_; +}; + +template class af2 +{ +public: + + typedef R result_type; + typedef A1 first_argument_type; + typedef A2 second_argument_type; + typedef A1 arg1_type; + typedef A2 arg2_type; + + explicit af2(F f): f_(f) + { + } + + result_type operator()(A1 a1, A2 a2) + { + return f_(a1, a2); + } + + result_type operator()(A1 a1, A2 a2) const + { + return f_(a1, a2); + } + +private: + + F f_; +}; + +template class af3 +{ +public: + + typedef R result_type; + typedef A1 arg1_type; + typedef A2 arg2_type; + typedef A3 arg3_type; + + explicit af3(F f): f_(f) + { + } + + result_type operator()(A1 a1, A2 a2, A3 a3) + { + return f_(a1, a2, a3); + } + + result_type operator()(A1 a1, A2 a2, A3 a3) const + { + return f_(a1, a2, a3); + } + +private: + + F f_; +}; + +template class af4 +{ +public: + + typedef R result_type; + typedef A1 arg1_type; + typedef A2 arg2_type; + typedef A3 arg3_type; + typedef A4 arg4_type; + + explicit af4(F f): f_(f) + { + } + + result_type operator()(A1 a1, A2 a2, A3 a3, A4 a4) + { + return f_(a1, a2, a3, a4); + } + + result_type operator()(A1 a1, A2 a2, A3 a3, A4 a4) const + { + return f_(a1, a2, a3, a4); + } + +private: + + F f_; +}; + +} // namespace _bi + +template _bi::af0 make_adaptable(F f) +{ + return _bi::af0(f); +} + +template _bi::af1 make_adaptable(F f) +{ + return _bi::af1(f); +} + +template _bi::af2 make_adaptable(F f) +{ + return _bi::af2(f); +} + +template _bi::af3 make_adaptable(F f) +{ + return _bi::af3(f); +} + +template _bi::af4 make_adaptable(F f) +{ + return _bi::af4(f); +} + +} // namespace boost + +#endif // #ifndef BOOST_BIND_MAKE_ADAPTABLE_HPP_INCLUDED diff --git a/win32/include/boost/bind/mem_fn_cc.hpp b/win32/include/boost/bind/mem_fn_cc.hpp new file mode 100755 index 000000000..afc35bf11 --- /dev/null +++ b/win32/include/boost/bind/mem_fn_cc.hpp @@ -0,0 +1,103 @@ +// +// bind/mem_fn_cc.hpp - support for different calling conventions +// +// Do not include this header directly. +// +// Copyright (c) 2001 Peter Dimov and Multi Media Ltd. +// +// 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) +// +// See http://www.boost.org/libs/bind/mem_fn.html for documentation. +// + +template _mfi::BOOST_MEM_FN_NAME(mf0) mem_fn(R (BOOST_MEM_FN_CC T::*f) ()) +{ + return _mfi::BOOST_MEM_FN_NAME(mf0)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(cmf0) mem_fn(R (BOOST_MEM_FN_CC T::*f) () const) +{ + return _mfi::BOOST_MEM_FN_NAME(cmf0)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(mf1) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1)) +{ + return _mfi::BOOST_MEM_FN_NAME(mf1)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(cmf1) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1) const) +{ + return _mfi::BOOST_MEM_FN_NAME(cmf1)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(mf2) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2)) +{ + return _mfi::BOOST_MEM_FN_NAME(mf2)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(cmf2) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2) const) +{ + return _mfi::BOOST_MEM_FN_NAME(cmf2)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(mf3) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3)) +{ + return _mfi::BOOST_MEM_FN_NAME(mf3)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(cmf3) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3) const) +{ + return _mfi::BOOST_MEM_FN_NAME(cmf3)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(mf4) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4)) +{ + return _mfi::BOOST_MEM_FN_NAME(mf4)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(cmf4) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4) const) +{ + return _mfi::BOOST_MEM_FN_NAME(cmf4)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(mf5) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5)) +{ + return _mfi::BOOST_MEM_FN_NAME(mf5)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(cmf5) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5) const) +{ + return _mfi::BOOST_MEM_FN_NAME(cmf5)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(mf6) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5, A6)) +{ + return _mfi::BOOST_MEM_FN_NAME(mf6)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(cmf6) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5, A6) const) +{ + return _mfi::BOOST_MEM_FN_NAME(cmf6)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(mf7) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5, A6, A7)) +{ + return _mfi::BOOST_MEM_FN_NAME(mf7)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(cmf7) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5, A6, A7) const) +{ + return _mfi::BOOST_MEM_FN_NAME(cmf7)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(mf8) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5, A6, A7, A8)) +{ + return _mfi::BOOST_MEM_FN_NAME(mf8)(f); +} + +template _mfi::BOOST_MEM_FN_NAME(cmf8) mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5, A6, A7, A8) const) +{ + return _mfi::BOOST_MEM_FN_NAME(cmf8)(f); +} diff --git a/win32/include/boost/bind/mem_fn_template.hpp b/win32/include/boost/bind/mem_fn_template.hpp new file mode 100755 index 000000000..ab42d631c --- /dev/null +++ b/win32/include/boost/bind/mem_fn_template.hpp @@ -0,0 +1,1020 @@ +// +// bind/mem_fn_template.hpp +// +// Do not include this header directly +// +// Copyright (c) 2001 Peter Dimov and Multi Media Ltd. +// +// 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) +// +// See http://www.boost.org/libs/bind/mem_fn.html for documentation. +// + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) +# define BOOST_MEM_FN_ENABLE_CONST_OVERLOADS +#endif + +// mf0 + +template class BOOST_MEM_FN_NAME(mf0) +{ +public: + + typedef R result_type; + typedef T * argument_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) ()) + F f_; + + template R call(U & u, T const *) const + { + BOOST_MEM_FN_RETURN (u.*f_)(); + } + + template R call(U & u, void const *) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(); + } + +public: + + explicit BOOST_MEM_FN_NAME(mf0)(F f): f_(f) {} + + R operator()(T * p) const + { + BOOST_MEM_FN_RETURN (p->*f_)(); + } + + template R operator()(U & u) const + { + BOOST_MEM_FN_RETURN call(u, &u); + } + +#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS + + template R operator()(U const & u) const + { + BOOST_MEM_FN_RETURN call(u, &u); + } + +#endif + + R operator()(T & t) const + { + BOOST_MEM_FN_RETURN (t.*f_)(); + } + + bool operator==(BOOST_MEM_FN_NAME(mf0) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(mf0) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// cmf0 + +template class BOOST_MEM_FN_NAME(cmf0) +{ +public: + + typedef R result_type; + typedef T const * argument_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) () const) + F f_; + + template R call(U & u, T const *) const + { + BOOST_MEM_FN_RETURN (u.*f_)(); + } + + template R call(U & u, void const *) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(); + } + +public: + + explicit BOOST_MEM_FN_NAME(cmf0)(F f): f_(f) {} + + template R operator()(U const & u) const + { + BOOST_MEM_FN_RETURN call(u, &u); + } + + R operator()(T const & t) const + { + BOOST_MEM_FN_RETURN (t.*f_)(); + } + + bool operator==(BOOST_MEM_FN_NAME(cmf0) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(cmf0) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// mf1 + +template class BOOST_MEM_FN_NAME(mf1) +{ +public: + + typedef R result_type; + typedef T * first_argument_type; + typedef A1 second_argument_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1)) + F f_; + + template R call(U & u, T const *, B1 & b1) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1); + } + + template R call(U & u, void const *, B1 & b1) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1); + } + +public: + + explicit BOOST_MEM_FN_NAME(mf1)(F f): f_(f) {} + + R operator()(T * p, A1 a1) const + { + BOOST_MEM_FN_RETURN (p->*f_)(a1); + } + + template R operator()(U & u, A1 a1) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1); + } + +#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS + + template R operator()(U const & u, A1 a1) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1); + } + +#endif + + R operator()(T & t, A1 a1) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1); + } + + bool operator==(BOOST_MEM_FN_NAME(mf1) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(mf1) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// cmf1 + +template class BOOST_MEM_FN_NAME(cmf1) +{ +public: + + typedef R result_type; + typedef T const * first_argument_type; + typedef A1 second_argument_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1) const) + F f_; + + template R call(U & u, T const *, B1 & b1) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1); + } + + template R call(U & u, void const *, B1 & b1) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1); + } + +public: + + explicit BOOST_MEM_FN_NAME(cmf1)(F f): f_(f) {} + + template R operator()(U const & u, A1 a1) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1); + } + + R operator()(T const & t, A1 a1) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1); + } + + bool operator==(BOOST_MEM_FN_NAME(cmf1) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(cmf1) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// mf2 + +template class BOOST_MEM_FN_NAME(mf2) +{ +public: + + typedef R result_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2)) + F f_; + + template R call(U & u, T const *, B1 & b1, B2 & b2) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1, b2); + } + + template R call(U & u, void const *, B1 & b1, B2 & b2) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2); + } + +public: + + explicit BOOST_MEM_FN_NAME(mf2)(F f): f_(f) {} + + R operator()(T * p, A1 a1, A2 a2) const + { + BOOST_MEM_FN_RETURN (p->*f_)(a1, a2); + } + + template R operator()(U & u, A1 a1, A2 a2) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2); + } + +#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS + + template R operator()(U const & u, A1 a1, A2 a2) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2); + } + +#endif + + R operator()(T & t, A1 a1, A2 a2) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1, a2); + } + + bool operator==(BOOST_MEM_FN_NAME(mf2) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(mf2) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// cmf2 + +template class BOOST_MEM_FN_NAME(cmf2) +{ +public: + + typedef R result_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2) const) + F f_; + + template R call(U & u, T const *, B1 & b1, B2 & b2) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1, b2); + } + + template R call(U & u, void const *, B1 & b1, B2 & b2) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2); + } + +public: + + explicit BOOST_MEM_FN_NAME(cmf2)(F f): f_(f) {} + + template R operator()(U const & u, A1 a1, A2 a2) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2); + } + + R operator()(T const & t, A1 a1, A2 a2) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1, a2); + } + + bool operator==(BOOST_MEM_FN_NAME(cmf2) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(cmf2) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// mf3 + +template class BOOST_MEM_FN_NAME(mf3) +{ +public: + + typedef R result_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3)) + F f_; + + template R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3); + } + + template R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3); + } + +public: + + explicit BOOST_MEM_FN_NAME(mf3)(F f): f_(f) {} + + R operator()(T * p, A1 a1, A2 a2, A3 a3) const + { + BOOST_MEM_FN_RETURN (p->*f_)(a1, a2, a3); + } + + template R operator()(U & u, A1 a1, A2 a2, A3 a3) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3); + } + +#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS + + template R operator()(U const & u, A1 a1, A2 a2, A3 a3) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3); + } + +#endif + + R operator()(T & t, A1 a1, A2 a2, A3 a3) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3); + } + + bool operator==(BOOST_MEM_FN_NAME(mf3) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(mf3) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// cmf3 + +template class BOOST_MEM_FN_NAME(cmf3) +{ +public: + + typedef R result_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3) const) + F f_; + + template R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3); + } + + template R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3); + } + +public: + + explicit BOOST_MEM_FN_NAME(cmf3)(F f): f_(f) {} + + template R operator()(U const & u, A1 a1, A2 a2, A3 a3) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3); + } + + R operator()(T const & t, A1 a1, A2 a2, A3 a3) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3); + } + + bool operator==(BOOST_MEM_FN_NAME(cmf3) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(cmf3) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// mf4 + +template class BOOST_MEM_FN_NAME(mf4) +{ +public: + + typedef R result_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4)) + F f_; + + template R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4); + } + + template R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4); + } + +public: + + explicit BOOST_MEM_FN_NAME(mf4)(F f): f_(f) {} + + R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4) const + { + BOOST_MEM_FN_RETURN (p->*f_)(a1, a2, a3, a4); + } + + template R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4); + } + +#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS + + template R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4); + } + +#endif + + R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4); + } + + bool operator==(BOOST_MEM_FN_NAME(mf4) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(mf4) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// cmf4 + +template class BOOST_MEM_FN_NAME(cmf4) +{ +public: + + typedef R result_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4) const) + F f_; + + template R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4); + } + + template R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4); + } + +public: + + explicit BOOST_MEM_FN_NAME(cmf4)(F f): f_(f) {} + + template R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4); + } + + R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4); + } + + bool operator==(BOOST_MEM_FN_NAME(cmf4) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(cmf4) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// mf5 + +template class BOOST_MEM_FN_NAME(mf5) +{ +public: + + typedef R result_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5)) + F f_; + + template R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5); + } + + template R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5); + } + +public: + + explicit BOOST_MEM_FN_NAME(mf5)(F f): f_(f) {} + + R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const + { + BOOST_MEM_FN_RETURN (p->*f_)(a1, a2, a3, a4, a5); + } + + template R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4, a5); + } + +#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS + + template R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4, a5); + } + +#endif + + R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5); + } + + bool operator==(BOOST_MEM_FN_NAME(mf5) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(mf5) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// cmf5 + +template class BOOST_MEM_FN_NAME(cmf5) +{ +public: + + typedef R result_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5) const) + F f_; + + template R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5); + } + + template R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5); + } + +public: + + explicit BOOST_MEM_FN_NAME(cmf5)(F f): f_(f) {} + + template R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4, a5); + } + + R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5); + } + + bool operator==(BOOST_MEM_FN_NAME(cmf5) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(cmf5) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// mf6 + +template class BOOST_MEM_FN_NAME(mf6) +{ +public: + + typedef R result_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6)) + F f_; + + template R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5, b6); + } + + template R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5, b6); + } + +public: + + explicit BOOST_MEM_FN_NAME(mf6)(F f): f_(f) {} + + R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const + { + BOOST_MEM_FN_RETURN (p->*f_)(a1, a2, a3, a4, a5, a6); + } + + template R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4, a5, a6); + } + +#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS + + template R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4, a5, a6); + } + +#endif + + R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5, a6); + } + + bool operator==(BOOST_MEM_FN_NAME(mf6) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(mf6) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// cmf6 + +template class BOOST_MEM_FN_NAME(cmf6) +{ +public: + + typedef R result_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6) const) + F f_; + + template R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5, b6); + } + + template R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5, b6); + } + +public: + + explicit BOOST_MEM_FN_NAME(cmf6)(F f): f_(f) {} + + template R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4, a5, a6); + } + + R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5, a6); + } + + bool operator==(BOOST_MEM_FN_NAME(cmf6) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(cmf6) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// mf7 + +template class BOOST_MEM_FN_NAME(mf7) +{ +public: + + typedef R result_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6, A7)) + F f_; + + template R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5, b6, b7); + } + + template R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5, b6, b7); + } + +public: + + explicit BOOST_MEM_FN_NAME(mf7)(F f): f_(f) {} + + R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const + { + BOOST_MEM_FN_RETURN (p->*f_)(a1, a2, a3, a4, a5, a6, a7); + } + + template R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4, a5, a6, a7); + } + +#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS + + template R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4, a5, a6, a7); + } + +#endif + + R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5, a6, a7); + } + + bool operator==(BOOST_MEM_FN_NAME(mf7) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(mf7) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// cmf7 + +template class BOOST_MEM_FN_NAME(cmf7) +{ +public: + + typedef R result_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6, A7) const) + F f_; + + template R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5, b6, b7); + } + + template R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5, b6, b7); + } + +public: + + explicit BOOST_MEM_FN_NAME(cmf7)(F f): f_(f) {} + + template R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4, a5, a6, a7); + } + + R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5, a6, a7); + } + + bool operator==(BOOST_MEM_FN_NAME(cmf7) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(cmf7) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// mf8 + +template class BOOST_MEM_FN_NAME(mf8) +{ +public: + + typedef R result_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6, A7, A8)) + F f_; + + template R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7, B8 & b8) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5, b6, b7, b8); + } + + template R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7, B8 & b8) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5, b6, b7, b8); + } + +public: + + explicit BOOST_MEM_FN_NAME(mf8)(F f): f_(f) {} + + R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const + { + BOOST_MEM_FN_RETURN (p->*f_)(a1, a2, a3, a4, a5, a6, a7, a8); + } + + template R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4, a5, a6, a7, a8); + } + +#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS + + template R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4, a5, a6, a7, a8); + } + +#endif + + R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5, a6, a7, a8); + } + + bool operator==(BOOST_MEM_FN_NAME(mf8) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(mf8) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +// cmf8 + +template class BOOST_MEM_FN_NAME(cmf8) +{ +public: + + typedef R result_type; + +private: + + BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6, A7, A8) const) + F f_; + + template R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7, B8 & b8) const + { + BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5, b6, b7, b8); + } + + template R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7, B8 & b8) const + { + BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5, b6, b7, b8); + } + +public: + + explicit BOOST_MEM_FN_NAME(cmf8)(F f): f_(f) {} + + R operator()(T const * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const + { + BOOST_MEM_FN_RETURN (p->*f_)(a1, a2, a3, a4, a5, a6, a7, a8); + } + + template R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const + { + BOOST_MEM_FN_RETURN call(u, &u, a1, a2, a3, a4, a5, a6, a7, a8); + } + + R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const + { + BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5, a6, a7, a8); + } + + bool operator==(BOOST_MEM_FN_NAME(cmf8) const & rhs) const + { + return f_ == rhs.f_; + } + + bool operator!=(BOOST_MEM_FN_NAME(cmf8) const & rhs) const + { + return f_ != rhs.f_; + } +}; + +#undef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS diff --git a/win32/include/boost/bind/mem_fn_vw.hpp b/win32/include/boost/bind/mem_fn_vw.hpp new file mode 100755 index 000000000..7f7daef2d --- /dev/null +++ b/win32/include/boost/bind/mem_fn_vw.hpp @@ -0,0 +1,130 @@ +// +// bind/mem_fn_vw.hpp - void return helper wrappers +// +// Do not include this header directly +// +// Copyright (c) 2001 Peter Dimov and Multi Media Ltd. +// +// 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) +// +// See http://www.boost.org/libs/bind/mem_fn.html for documentation. +// + +template struct BOOST_MEM_FN_NAME(mf0): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf0) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (); + explicit BOOST_MEM_FN_NAME(mf0)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf0)(f) {} +}; + +template struct BOOST_MEM_FN_NAME(cmf0): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf0) +{ + typedef R (BOOST_MEM_FN_CC T::*F) () const; + explicit BOOST_MEM_FN_NAME(cmf0)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf0)(f) {} +}; + + +template struct BOOST_MEM_FN_NAME(mf1): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf1) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1); + explicit BOOST_MEM_FN_NAME(mf1)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf1)(f) {} +}; + +template struct BOOST_MEM_FN_NAME(cmf1): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf1) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1) const; + explicit BOOST_MEM_FN_NAME(cmf1)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf1)(f) {} +}; + + +template struct BOOST_MEM_FN_NAME(mf2): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf2) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1, A2); + explicit BOOST_MEM_FN_NAME(mf2)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf2)(f) {} +}; + +template struct BOOST_MEM_FN_NAME(cmf2): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf2) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1, A2) const; + explicit BOOST_MEM_FN_NAME(cmf2)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf2)(f) {} +}; + + +template struct BOOST_MEM_FN_NAME(mf3): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf3) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3); + explicit BOOST_MEM_FN_NAME(mf3)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf3)(f) {} +}; + +template struct BOOST_MEM_FN_NAME(cmf3): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf3) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3) const; + explicit BOOST_MEM_FN_NAME(cmf3)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf3)(f) {} +}; + + +template struct BOOST_MEM_FN_NAME(mf4): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf4) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4); + explicit BOOST_MEM_FN_NAME(mf4)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf4)(f) {} +}; + +template struct BOOST_MEM_FN_NAME(cmf4): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf4) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4) const; + explicit BOOST_MEM_FN_NAME(cmf4)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf4)(f) {} +}; + + +template struct BOOST_MEM_FN_NAME(mf5): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf5) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5); + explicit BOOST_MEM_FN_NAME(mf5)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf5)(f) {} +}; + +template struct BOOST_MEM_FN_NAME(cmf5): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf5) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5) const; + explicit BOOST_MEM_FN_NAME(cmf5)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf5)(f) {} +}; + + +template struct BOOST_MEM_FN_NAME(mf6): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf6) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6); + explicit BOOST_MEM_FN_NAME(mf6)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf6)(f) {} +}; + +template struct BOOST_MEM_FN_NAME(cmf6): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf6) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6) const; + explicit BOOST_MEM_FN_NAME(cmf6)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf6)(f) {} +}; + + +template struct BOOST_MEM_FN_NAME(mf7): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf7) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6, A7); + explicit BOOST_MEM_FN_NAME(mf7)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf7)(f) {} +}; + +template struct BOOST_MEM_FN_NAME(cmf7): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf7) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6, A7) const; + explicit BOOST_MEM_FN_NAME(cmf7)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf7)(f) {} +}; + + +template struct BOOST_MEM_FN_NAME(mf8): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf8) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6, A7, A8); + explicit BOOST_MEM_FN_NAME(mf8)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(mf8)(f) {} +}; + +template struct BOOST_MEM_FN_NAME(cmf8): public mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf8) +{ + typedef R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6, A7, A8) const; + explicit BOOST_MEM_FN_NAME(cmf8)(F f): mf::BOOST_NESTED_TEMPLATE BOOST_MEM_FN_NAME2(cmf8)(f) {} +}; + diff --git a/win32/include/boost/bind/placeholders.hpp b/win32/include/boost/bind/placeholders.hpp new file mode 100755 index 000000000..dae5de310 --- /dev/null +++ b/win32/include/boost/bind/placeholders.hpp @@ -0,0 +1,68 @@ +#ifndef BOOST_BIND_PLACEHOLDERS_HPP_INCLUDED +#define BOOST_BIND_PLACEHOLDERS_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// bind/placeholders.hpp - _N definitions +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// 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) +// +// See http://www.boost.org/libs/bind/bind.html for documentation. +// + +#include +#include + +namespace +{ + +#if defined(__BORLANDC__) || defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ <= 400) + +static inline boost::arg<1> _1() { return boost::arg<1>(); } +static inline boost::arg<2> _2() { return boost::arg<2>(); } +static inline boost::arg<3> _3() { return boost::arg<3>(); } +static inline boost::arg<4> _4() { return boost::arg<4>(); } +static inline boost::arg<5> _5() { return boost::arg<5>(); } +static inline boost::arg<6> _6() { return boost::arg<6>(); } +static inline boost::arg<7> _7() { return boost::arg<7>(); } +static inline boost::arg<8> _8() { return boost::arg<8>(); } +static inline boost::arg<9> _9() { return boost::arg<9>(); } + +#elif defined(BOOST_MSVC) || (defined(__DECCXX_VER) && __DECCXX_VER <= 60590031) || defined(__MWERKS__) + +static boost::arg<1> _1; +static boost::arg<2> _2; +static boost::arg<3> _3; +static boost::arg<4> _4; +static boost::arg<5> _5; +static boost::arg<6> _6; +static boost::arg<7> _7; +static boost::arg<8> _8; +static boost::arg<9> _9; + +#else + +boost::arg<1> _1; +boost::arg<2> _2; +boost::arg<3> _3; +boost::arg<4> _4; +boost::arg<5> _5; +boost::arg<6> _6; +boost::arg<7> _7; +boost::arg<8> _8; +boost::arg<9> _9; + +#endif + +} // unnamed namespace + +#endif // #ifndef BOOST_BIND_PLACEHOLDERS_HPP_INCLUDED diff --git a/win32/include/boost/bind/protect.hpp b/win32/include/boost/bind/protect.hpp new file mode 100755 index 000000000..74ee1b913 --- /dev/null +++ b/win32/include/boost/bind/protect.hpp @@ -0,0 +1,144 @@ +#ifndef BOOST_BIND_PROTECT_HPP_INCLUDED +#define BOOST_BIND_PROTECT_HPP_INCLUDED + +// +// protect.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// 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) +// + +namespace boost +{ + +namespace _bi +{ + +template class protected_bind_t +{ +public: + + typedef typename F::result_type result_type; + + explicit protected_bind_t(F f): f_(f) + { + } + + result_type operator()() + { + return f_(); + } + + result_type operator()() const + { + return f_(); + } + + template result_type operator()(A1 & a1) + { + return f_(a1); + } + + template result_type operator()(A1 & a1) const + { + return f_(a1); + } + + template result_type operator()(A1 & a1, A2 & a2) + { + return f_(a1, a2); + } + + template result_type operator()(A1 & a1, A2 & a2) const + { + return f_(a1, a2); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3) + { + return f_(a1, a2, a3); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3) const + { + return f_(a1, a2, a3); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4) + { + return f_(a1, a2, a3, a4); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4) const + { + return f_(a1, a2, a3, a4); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5) + { + return f_(a1, a2, a3, a4, a5); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5) const + { + return f_(a1, a2, a3, a4, a5); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6) + { + return f_(a1, a2, a3, a4, a5, a6); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6) const + { + return f_(a1, a2, a3, a4, a5, a6); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7) + { + return f_(a1, a2, a3, a4, a5, a6, a7); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7) const + { + return f_(a1, a2, a3, a4, a5, a6, a7); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8) + { + return f_(a1, a2, a3, a4, a5, a6, a7, a8); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8) const + { + return f_(a1, a2, a3, a4, a5, a6, a7, a8); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9) + { + return f_(a1, a2, a3, a4, a5, a6, a7, a8, a9); + } + + template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9) const + { + return f_(a1, a2, a3, a4, a5, a6, a7, a8, a9); + } + +private: + + F f_; +}; + +} // namespace _bi + +template _bi::protected_bind_t protect(F f) +{ + return _bi::protected_bind_t(f); +} + +} // namespace boost + +#endif // #ifndef BOOST_BIND_PROTECT_HPP_INCLUDED diff --git a/win32/include/boost/bind/storage.hpp b/win32/include/boost/bind/storage.hpp new file mode 100755 index 000000000..512adc56f --- /dev/null +++ b/win32/include/boost/bind/storage.hpp @@ -0,0 +1,475 @@ +#ifndef BOOST_BIND_STORAGE_HPP_INCLUDED +#define BOOST_BIND_STORAGE_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// bind/storage.hpp +// +// boost/bind.hpp support header, optimized storage +// +// Copyright (c) 2006 Peter Dimov +// +// 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 +// +// See http://www.boost.org/libs/bind/bind.html for documentation. +// + +#include +#include + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable: 4512) // assignment operator could not be generated +#endif + +namespace boost +{ + +namespace _bi +{ + +// 1 + +template struct storage1 +{ + explicit storage1( A1 a1 ): a1_( a1 ) {} + + template void accept(V & v) const + { + BOOST_BIND_VISIT_EACH(v, a1_, 0); + } + + A1 a1_; +}; + +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( __BORLANDC__ ) + +template struct storage1< boost::arg > +{ + explicit storage1( boost::arg ) {} + + template void accept(V &) const { } + + static boost::arg a1_() { return boost::arg(); } +}; + +template struct storage1< boost::arg (*) () > +{ + explicit storage1( boost::arg (*) () ) {} + + template void accept(V &) const { } + + static boost::arg a1_() { return boost::arg(); } +}; + +#endif + +// 2 + +template struct storage2: public storage1 +{ + typedef storage1 inherited; + + storage2( A1 a1, A2 a2 ): storage1( a1 ), a2_( a2 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + BOOST_BIND_VISIT_EACH(v, a2_, 0); + } + + A2 a2_; +}; + +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + +template struct storage2< A1, boost::arg >: public storage1 +{ + typedef storage1 inherited; + + storage2( A1 a1, boost::arg ): storage1( a1 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a2_() { return boost::arg(); } +}; + +template struct storage2< A1, boost::arg (*) () >: public storage1 +{ + typedef storage1 inherited; + + storage2( A1 a1, boost::arg (*) () ): storage1( a1 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a2_() { return boost::arg(); } +}; + +#endif + +// 3 + +template struct storage3: public storage2< A1, A2 > +{ + typedef storage2 inherited; + + storage3( A1 a1, A2 a2, A3 a3 ): storage2( a1, a2 ), a3_( a3 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + BOOST_BIND_VISIT_EACH(v, a3_, 0); + } + + A3 a3_; +}; + +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + +template struct storage3< A1, A2, boost::arg >: public storage2< A1, A2 > +{ + typedef storage2 inherited; + + storage3( A1 a1, A2 a2, boost::arg ): storage2( a1, a2 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a3_() { return boost::arg(); } +}; + +template struct storage3< A1, A2, boost::arg (*) () >: public storage2< A1, A2 > +{ + typedef storage2 inherited; + + storage3( A1 a1, A2 a2, boost::arg (*) () ): storage2( a1, a2 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a3_() { return boost::arg(); } +}; + +#endif + +// 4 + +template struct storage4: public storage3< A1, A2, A3 > +{ + typedef storage3 inherited; + + storage4( A1 a1, A2 a2, A3 a3, A4 a4 ): storage3( a1, a2, a3 ), a4_( a4 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + BOOST_BIND_VISIT_EACH(v, a4_, 0); + } + + A4 a4_; +}; + +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + +template struct storage4< A1, A2, A3, boost::arg >: public storage3< A1, A2, A3 > +{ + typedef storage3 inherited; + + storage4( A1 a1, A2 a2, A3 a3, boost::arg ): storage3( a1, a2, a3 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a4_() { return boost::arg(); } +}; + +template struct storage4< A1, A2, A3, boost::arg (*) () >: public storage3< A1, A2, A3 > +{ + typedef storage3 inherited; + + storage4( A1 a1, A2 a2, A3 a3, boost::arg (*) () ): storage3( a1, a2, a3 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a4_() { return boost::arg(); } +}; + +#endif + +// 5 + +template struct storage5: public storage4< A1, A2, A3, A4 > +{ + typedef storage4 inherited; + + storage5( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5 ): storage4( a1, a2, a3, a4 ), a5_( a5 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + BOOST_BIND_VISIT_EACH(v, a5_, 0); + } + + A5 a5_; +}; + +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + +template struct storage5< A1, A2, A3, A4, boost::arg >: public storage4< A1, A2, A3, A4 > +{ + typedef storage4 inherited; + + storage5( A1 a1, A2 a2, A3 a3, A4 a4, boost::arg ): storage4( a1, a2, a3, a4 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a5_() { return boost::arg(); } +}; + +template struct storage5< A1, A2, A3, A4, boost::arg (*) () >: public storage4< A1, A2, A3, A4 > +{ + typedef storage4 inherited; + + storage5( A1 a1, A2 a2, A3 a3, A4 a4, boost::arg (*) () ): storage4( a1, a2, a3, a4 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a5_() { return boost::arg(); } +}; + +#endif + +// 6 + +template struct storage6: public storage5< A1, A2, A3, A4, A5 > +{ + typedef storage5 inherited; + + storage6( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6 ): storage5( a1, a2, a3, a4, a5 ), a6_( a6 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + BOOST_BIND_VISIT_EACH(v, a6_, 0); + } + + A6 a6_; +}; + +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + +template struct storage6< A1, A2, A3, A4, A5, boost::arg >: public storage5< A1, A2, A3, A4, A5 > +{ + typedef storage5 inherited; + + storage6( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, boost::arg ): storage5( a1, a2, a3, a4, a5 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a6_() { return boost::arg(); } +}; + +template struct storage6< A1, A2, A3, A4, A5, boost::arg (*) () >: public storage5< A1, A2, A3, A4, A5 > +{ + typedef storage5 inherited; + + storage6( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, boost::arg (*) () ): storage5( a1, a2, a3, a4, a5 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a6_() { return boost::arg(); } +}; + +#endif + +// 7 + +template struct storage7: public storage6< A1, A2, A3, A4, A5, A6 > +{ + typedef storage6 inherited; + + storage7( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7 ): storage6( a1, a2, a3, a4, a5, a6 ), a7_( a7 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + BOOST_BIND_VISIT_EACH(v, a7_, 0); + } + + A7 a7_; +}; + +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + +template struct storage7< A1, A2, A3, A4, A5, A6, boost::arg >: public storage6< A1, A2, A3, A4, A5, A6 > +{ + typedef storage6 inherited; + + storage7( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, boost::arg ): storage6( a1, a2, a3, a4, a5, a6 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a7_() { return boost::arg(); } +}; + +template struct storage7< A1, A2, A3, A4, A5, A6, boost::arg (*) () >: public storage6< A1, A2, A3, A4, A5, A6 > +{ + typedef storage6 inherited; + + storage7( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, boost::arg (*) () ): storage6( a1, a2, a3, a4, a5, a6 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a7_() { return boost::arg(); } +}; + +#endif + +// 8 + +template struct storage8: public storage7< A1, A2, A3, A4, A5, A6, A7 > +{ + typedef storage7 inherited; + + storage8( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8 ): storage7( a1, a2, a3, a4, a5, a6, a7 ), a8_( a8 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + BOOST_BIND_VISIT_EACH(v, a8_, 0); + } + + A8 a8_; +}; + +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + +template struct storage8< A1, A2, A3, A4, A5, A6, A7, boost::arg >: public storage7< A1, A2, A3, A4, A5, A6, A7 > +{ + typedef storage7 inherited; + + storage8( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, boost::arg ): storage7( a1, a2, a3, a4, a5, a6, a7 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a8_() { return boost::arg(); } +}; + +template struct storage8< A1, A2, A3, A4, A5, A6, A7, boost::arg (*) () >: public storage7< A1, A2, A3, A4, A5, A6, A7 > +{ + typedef storage7 inherited; + + storage8( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, boost::arg (*) () ): storage7( a1, a2, a3, a4, a5, a6, a7 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a8_() { return boost::arg(); } +}; + +#endif + +// 9 + +template struct storage9: public storage8< A1, A2, A3, A4, A5, A6, A7, A8 > +{ + typedef storage8 inherited; + + storage9( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9 ): storage8( a1, a2, a3, a4, a5, a6, a7, a8 ), a9_( a9 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + BOOST_BIND_VISIT_EACH(v, a9_, 0); + } + + A9 a9_; +}; + +#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) + +template struct storage9< A1, A2, A3, A4, A5, A6, A7, A8, boost::arg >: public storage8< A1, A2, A3, A4, A5, A6, A7, A8 > +{ + typedef storage8 inherited; + + storage9( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, boost::arg ): storage8( a1, a2, a3, a4, a5, a6, a7, a8 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a9_() { return boost::arg(); } +}; + +template struct storage9< A1, A2, A3, A4, A5, A6, A7, A8, boost::arg (*) () >: public storage8< A1, A2, A3, A4, A5, A6, A7, A8 > +{ + typedef storage8 inherited; + + storage9( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, boost::arg (*) () ): storage8( a1, a2, a3, a4, a5, a6, a7, a8 ) {} + + template void accept(V & v) const + { + inherited::accept(v); + } + + static boost::arg a9_() { return boost::arg(); } +}; + +#endif + +} // namespace _bi + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(default: 4512) // assignment operator could not be generated +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_BIND_STORAGE_HPP_INCLUDED diff --git a/win32/include/boost/blank.hpp b/win32/include/boost/blank.hpp new file mode 100755 index 000000000..d67c86917 --- /dev/null +++ b/win32/include/boost/blank.hpp @@ -0,0 +1,100 @@ +//----------------------------------------------------------------------------- +// boost blank.hpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_BLANK_HPP +#define BOOST_BLANK_HPP + +#include "boost/blank_fwd.hpp" + +#include // for std::basic_ostream forward declare + +#include "boost/detail/templated_streams.hpp" +#include "boost/mpl/bool.hpp" +#include "boost/type_traits/is_empty.hpp" +#include "boost/type_traits/is_pod.hpp" +#include "boost/type_traits/is_stateless.hpp" + +namespace boost { + +struct blank +{ +}; + +// type traits specializations +// + +template <> +struct is_pod< blank > + : mpl::true_ +{ +}; + +template <> +struct is_empty< blank > + : mpl::true_ +{ +}; + +template <> +struct is_stateless< blank > + : mpl::true_ +{ +}; + +// relational operators +// + +inline bool operator==(const blank&, const blank&) +{ + return true; +} + +inline bool operator<=(const blank&, const blank&) +{ + return true; +} + +inline bool operator>=(const blank&, const blank&) +{ + return true; +} + +inline bool operator!=(const blank&, const blank&) +{ + return false; +} + +inline bool operator<(const blank&, const blank&) +{ + return false; +} + +inline bool operator>(const blank&, const blank&) +{ + return false; +} + +// streaming support +// +BOOST_TEMPLATED_STREAM_TEMPLATE(E,T) +inline BOOST_TEMPLATED_STREAM(ostream, E,T)& operator<<( + BOOST_TEMPLATED_STREAM(ostream, E,T)& out + , const blank& + ) +{ + // (output nothing) + return out; +} + +} // namespace boost + +#endif // BOOST_BLANK_HPP diff --git a/win32/include/boost/blank_fwd.hpp b/win32/include/boost/blank_fwd.hpp new file mode 100755 index 000000000..076a1f5fa --- /dev/null +++ b/win32/include/boost/blank_fwd.hpp @@ -0,0 +1,22 @@ +//----------------------------------------------------------------------------- +// boost blank_fwd.hpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_BLANK_FWD_HPP +#define BOOST_BLANK_FWD_HPP + +namespace boost { + +struct blank; + +} // namespace boost + +#endif // BOOST_BLANK_FWD_HPP diff --git a/win32/include/boost/call_traits.hpp b/win32/include/boost/call_traits.hpp new file mode 100755 index 000000000..9add20ed9 --- /dev/null +++ b/win32/include/boost/call_traits.hpp @@ -0,0 +1,24 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/utility for most recent version including documentation. + +// See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp +// for full copyright notices. + +#ifndef BOOST_CALL_TRAITS_HPP +#define BOOST_CALL_TRAITS_HPP + +#ifndef BOOST_CONFIG_HPP +#include +#endif + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +#include +#else +#include +#endif + +#endif // BOOST_CALL_TRAITS_HPP diff --git a/win32/include/boost/cast.hpp b/win32/include/boost/cast.hpp new file mode 100755 index 000000000..c2fadeae6 --- /dev/null +++ b/win32/include/boost/cast.hpp @@ -0,0 +1,107 @@ +// boost cast.hpp header file ----------------------------------------------// + +// (C) Copyright Kevlin Henney and Dave Abrahams 1999. +// 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) + +// See http://www.boost.org/libs/conversion for Documentation. + +// Revision History +// 23 JUn 05 numeric_cast removed and redirected to the new verion (Fernando Cacciola) +// 02 Apr 01 Removed BOOST_NO_LIMITS workarounds and included +// instead (the workaround did not +// actually compile when BOOST_NO_LIMITS was defined in +// any case, so we loose nothing). (John Maddock) +// 21 Jan 01 Undid a bug I introduced yesterday. numeric_cast<> never +// worked with stock GCC; trying to get it to do that broke +// vc-stlport. +// 20 Jan 01 Moved BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS to config.hpp. +// Removed unused BOOST_EXPLICIT_TARGET macro. Moved +// boost::detail::type to boost/type.hpp. Made it compile with +// stock gcc again (Dave Abrahams) +// 29 Nov 00 Remove nested namespace cast, cleanup spacing before Formal +// Review (Beman Dawes) +// 19 Oct 00 Fix numeric_cast for floating-point types (Dave Abrahams) +// 15 Jul 00 Suppress numeric_cast warnings for GCC, Borland and MSVC +// (Dave Abrahams) +// 30 Jun 00 More MSVC6 wordarounds. See comments below. (Dave Abrahams) +// 28 Jun 00 Removed implicit_cast<>. See comment below. (Beman Dawes) +// 27 Jun 00 More MSVC6 workarounds +// 15 Jun 00 Add workarounds for MSVC6 +// 2 Feb 00 Remove bad_numeric_cast ";" syntax error (Doncho Angelov) +// 26 Jan 00 Add missing throw() to bad_numeric_cast::what(0 (Adam Levar) +// 29 Dec 99 Change using declarations so usages in other namespaces work +// correctly (Dave Abrahams) +// 23 Sep 99 Change polymorphic_downcast assert to also detect M.I. errors +// as suggested Darin Adler and improved by Valentin Bonnard. +// 2 Sep 99 Remove controversial asserts, simplify, rename. +// 30 Aug 99 Move to cast.hpp, replace value_cast with numeric_cast, +// place in nested namespace. +// 3 Aug 99 Initial version + +#ifndef BOOST_CAST_HPP +#define BOOST_CAST_HPP + +# include +# include +# include +# include +# include +# include + +// It has been demonstrated numerous times that MSVC 6.0 fails silently at link +// time if you use a template function which has template parameters that don't +// appear in the function's argument list. +// +// TODO: Add this to config.hpp? +# if defined(BOOST_MSVC) && BOOST_MSVC < 1300 +# define BOOST_EXPLICIT_DEFAULT_TARGET , ::boost::type* = 0 +# else +# define BOOST_EXPLICIT_DEFAULT_TARGET +# endif + +namespace boost +{ +// See the documentation for descriptions of how to choose between +// static_cast<>, dynamic_cast<>, polymorphic_cast<> and polymorphic_downcast<> + +// polymorphic_cast --------------------------------------------------------// + + // Runtime checked polymorphic downcasts and crosscasts. + // Suggested in The C++ Programming Language, 3rd Ed, Bjarne Stroustrup, + // section 15.8 exercise 1, page 425. + + template + inline Target polymorphic_cast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET) + { + Target tmp = dynamic_cast(x); + if ( tmp == 0 ) throw std::bad_cast(); + return tmp; + } + +// polymorphic_downcast ----------------------------------------------------// + + // BOOST_ASSERT() checked polymorphic downcast. Crosscasts prohibited. + + // WARNING: Because this cast uses BOOST_ASSERT(), it violates + // the One Definition Rule if used in multiple translation units + // where BOOST_DISABLE_ASSERTS, BOOST_ENABLE_ASSERT_HANDLER + // NDEBUG are defined inconsistently. + + // Contributed by Dave Abrahams + + template + inline Target polymorphic_downcast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET) + { + BOOST_ASSERT( dynamic_cast(x) == x ); // detect logic error + return static_cast(x); + } + +# undef BOOST_EXPLICIT_DEFAULT_TARGET + +} // namespace boost + +# include + +#endif // BOOST_CAST_HPP diff --git a/win32/include/boost/cerrno.hpp b/win32/include/boost/cerrno.hpp new file mode 100755 index 000000000..1205455e9 --- /dev/null +++ b/win32/include/boost/cerrno.hpp @@ -0,0 +1,331 @@ +// Boost cerrno.hpp header -------------------------------------------------// + +// Copyright Beman Dawes 2005. +// Use, modification, and distribution is subject to 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) + +// See library home page at http://www.boost.org/libs/system + +#ifndef BOOST_CERRNO_HPP +#define BOOST_CERRNO_HPP + +#include + +// supply errno values likely to be missing, particularly on Windows + +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT 9901 +#endif + +#ifndef EADDRINUSE +#define EADDRINUSE 9902 +#endif + +#ifndef EADDRNOTAVAIL +#define EADDRNOTAVAIL 9903 +#endif + +#ifndef EISCONN +#define EISCONN 9904 +#endif + +#ifndef EBADMSG +#define EBADMSG 9905 +#endif + +#ifndef ECONNABORTED +#define ECONNABORTED 9906 +#endif + +#ifndef EALREADY +#define EALREADY 9907 +#endif + +#ifndef ECONNREFUSED +#define ECONNREFUSED 9908 +#endif + +#ifndef ECONNRESET +#define ECONNRESET 9909 +#endif + +#ifndef EDESTADDRREQ +#define EDESTADDRREQ 9910 +#endif + +#ifndef EHOSTUNREACH +#define EHOSTUNREACH 9911 +#endif + +#ifndef EIDRM +#define EIDRM 9912 +#endif + +#ifndef EMSGSIZE +#define EMSGSIZE 9913 +#endif + +#ifndef ENETDOWN +#define ENETDOWN 9914 +#endif + +#ifndef ENETRESET +#define ENETRESET 9915 +#endif + +#ifndef ENETUNREACH +#define ENETUNREACH 9916 +#endif + +#ifndef ENOBUFS +#define ENOBUFS 9917 +#endif + +#ifndef ENOLINK +#define ENOLINK 9918 +#endif + +#ifndef ENODATA +#define ENODATA 9919 +#endif + +#ifndef ENOMSG +#define ENOMSG 9920 +#endif + +#ifndef ENOPROTOOPT +#define ENOPROTOOPT 9921 +#endif + +#ifndef ENOSR +#define ENOSR 9922 +#endif + +#ifndef ENOTSOCK +#define ENOTSOCK 9923 +#endif + +#ifndef ENOSTR +#define ENOSTR 9924 +#endif + +#ifndef ENOTCONN +#define ENOTCONN 9925 +#endif + +#ifndef ENOTSUP +#define ENOTSUP 9926 +#endif + +#ifndef ECANCELED +#define ECANCELED 9927 +#endif + +#ifndef EINPROGRESS +#define EINPROGRESS 9928 +#endif + +#ifndef EOPNOTSUPP +#define EOPNOTSUPP 9929 +#endif + +#ifndef EWOULDBLOCK +#define EWOULDBLOCK 9930 +#endif + +#ifndef EOWNERDEAD +#define EOWNERDEAD 9931 +#endif + +#ifndef EPROTO +#define EPROTO 9932 +#endif + +#ifndef EPROTONOSUPPORT +#define EPROTONOSUPPORT 9933 +#endif + +#ifndef ENOTRECOVERABLE +#define ENOTRECOVERABLE 9934 +#endif + +#ifndef ETIME +#define ETIME 9935 +#endif + +#ifndef ETXTBSY +#define ETXTBSY 9936 +#endif + +#ifndef ETIMEDOUT +#define ETIMEDOUT 9938 +#endif + +#ifndef ELOOP +#define ELOOP 9939 +#endif + +#ifndef EOVERFLOW +#define EOVERFLOW 9940 +#endif + +#ifndef EPROTOTYPE +#define EPROTOTYPE 9941 +#endif + +#ifndef ENOSYS +#define ENOSYS 9942 +#endif + +#ifndef EINVAL +#define EINVAL 9943 +#endif + +#ifndef ERANGE +#define ERANGE 9944 +#endif + +#ifndef EILSEQ +#define EILSEQ 9945 +#endif + +// Windows Mobile doesn't appear to define these: + +#ifndef E2BIG +#define E2BIG 9946 +#endif + +#ifndef EDOM +#define EDOM 9947 +#endif + +#ifndef EFAULT +#define EFAULT 9948 +#endif + +#ifndef EBADF +#define EBADF 9949 +#endif + +#ifndef EPIPE +#define EPIPE 9950 +#endif + +#ifndef EXDEV +#define EXDEV 9951 +#endif + +#ifndef EBUSY +#define EBUSY 9952 +#endif + +#ifndef ENOTEMPTY +#define ENOTEMPTY 9953 +#endif + +#ifndef ENOEXEC +#define ENOEXEC 9954 +#endif + +#ifndef EEXIST +#define EEXIST 9955 +#endif + +#ifndef EFBIG +#define EFBIG 9956 +#endif + +#ifndef ENAMETOOLONG +#define ENAMETOOLONG 9957 +#endif + +#ifndef ENOTTY +#define ENOTTY 9958 +#endif + +#ifndef EINTR +#define EINTR 9959 +#endif + +#ifndef ESPIPE +#define ESPIPE 9960 +#endif + +#ifndef EIO +#define EIO 9961 +#endif + +#ifndef EISDIR +#define EISDIR 9962 +#endif + +#ifndef ECHILD +#define ECHILD 9963 +#endif + +#ifndef ENOLCK +#define ENOLCK 9964 +#endif + +#ifndef ENOSPC +#define ENOSPC 9965 +#endif + +#ifndef ENXIO +#define ENXIO 9966 +#endif + +#ifndef ENODEV +#define ENODEV 9967 +#endif + +#ifndef ENOENT +#define ENOENT 9968 +#endif + +#ifndef ESRCH +#define ESRCH 9969 +#endif + +#ifndef ENOTDIR +#define ENOTDIR 9970 +#endif + +#ifndef ENOMEM +#define ENOMEM 9971 +#endif + +#ifndef EPERM +#define EPERM 9972 +#endif + +#ifndef EACCES +#define EACCES 9973 +#endif + +#ifndef EROFS +#define EROFS 9974 +#endif + +#ifndef EDEADLK +#define EDEADLK 9975 +#endif + +#ifndef EAGAIN +#define EAGAIN 9976 +#endif + +#ifndef ENFILE +#define ENFILE 9977 +#endif + +#ifndef EMFILE +#define EMFILE 9978 +#endif + +#ifndef EMLINK +#define EMLINK 9979 +#endif + +#endif // include guard diff --git a/win32/include/boost/checked_delete.hpp b/win32/include/boost/checked_delete.hpp new file mode 100755 index 000000000..e8f479f05 --- /dev/null +++ b/win32/include/boost/checked_delete.hpp @@ -0,0 +1,69 @@ +#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED +#define BOOST_CHECKED_DELETE_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/checked_delete.hpp +// +// Copyright (c) 2002, 2003 Peter Dimov +// Copyright (c) 2003 Daniel Frey +// Copyright (c) 2003 Howard Hinnant +// +// 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) +// +// See http://www.boost.org/libs/utility/checked_delete.html for documentation. +// + +namespace boost +{ + +// verify that types are complete for increased safety + +template inline void checked_delete(T * x) +{ + // intentionally complex - simplification causes regressions + typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; + (void) sizeof(type_must_be_complete); + delete x; +} + +template inline void checked_array_delete(T * x) +{ + typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; + (void) sizeof(type_must_be_complete); + delete [] x; +} + +template struct checked_deleter +{ + typedef void result_type; + typedef T * argument_type; + + void operator()(T * x) const + { + // boost:: disables ADL + boost::checked_delete(x); + } +}; + +template struct checked_array_deleter +{ + typedef void result_type; + typedef T * argument_type; + + void operator()(T * x) const + { + boost::checked_array_delete(x); + } +}; + +} // namespace boost + +#endif // #ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED diff --git a/win32/include/boost/circular_buffer.hpp b/win32/include/boost/circular_buffer.hpp new file mode 100755 index 000000000..01c6b9019 --- /dev/null +++ b/win32/include/boost/circular_buffer.hpp @@ -0,0 +1,74 @@ +// Circular buffer library header file. + +// Copyright (c) 2003-2007 Jan Gaspar + +// Use, modification, and distribution is subject to 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) + +// See www.boost.org/libs/circular_buffer for documentation. + +#if !defined(BOOST_CIRCULAR_BUFFER_HPP) +#define BOOST_CIRCULAR_BUFFER_HPP + +#if defined(_MSC_VER) && _MSC_VER >= 1200 + #pragma once +#endif + +#include "circular_buffer_fwd.hpp" +#include + +// BOOST_CB_ENABLE_DEBUG: Debug support control. +#if defined(NDEBUG) || defined(BOOST_CB_DISABLE_DEBUG) + #define BOOST_CB_ENABLE_DEBUG 0 +#else + #define BOOST_CB_ENABLE_DEBUG 1 +#endif + +// BOOST_CB_ASSERT: Runtime assertion. +#if BOOST_CB_ENABLE_DEBUG + #include + #define BOOST_CB_ASSERT(Expr) BOOST_ASSERT(Expr) +#else + #define BOOST_CB_ASSERT(Expr) ((void)0) +#endif + +// BOOST_CB_STATIC_ASSERT: Compile time assertion. +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + #define BOOST_CB_STATIC_ASSERT(Expr) ((void)0) +#else + #include + #define BOOST_CB_STATIC_ASSERT(Expr) BOOST_STATIC_ASSERT(Expr) +#endif + +// BOOST_CB_IS_CONVERTIBLE: Check if Iterator::value_type is convertible to Type. +#if BOOST_WORKAROUND(__BORLANDC__, <= 0x0550) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407) || \ + BOOST_WORKAROUND(BOOST_MSVC, < 1300) + #define BOOST_CB_IS_CONVERTIBLE(Iterator, Type) ((void)0) +#else + #include + #include + #define BOOST_CB_IS_CONVERTIBLE(Iterator, Type) \ + BOOST_CB_STATIC_ASSERT((is_convertible::value_type, Type>::value)) +#endif + +// BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS: +// Check if the STL provides templated iterator constructors for its containers. +#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS) + #define BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS BOOST_CB_STATIC_ASSERT(false); +#else + #define BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS ((void)0); +#endif + +#include "circular_buffer/debug.hpp" +#include "circular_buffer/details.hpp" +#include "circular_buffer/base.hpp" +#include "circular_buffer/space_optimized.hpp" + +#undef BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS +#undef BOOST_CB_IS_CONVERTIBLE +#undef BOOST_CB_STATIC_ASSERT +#undef BOOST_CB_ASSERT +#undef BOOST_CB_ENABLE_DEBUG + +#endif // #if !defined(BOOST_CIRCULAR_BUFFER_HPP) diff --git a/win32/include/boost/circular_buffer/base.hpp b/win32/include/boost/circular_buffer/base.hpp new file mode 100755 index 000000000..5c087f586 --- /dev/null +++ b/win32/include/boost/circular_buffer/base.hpp @@ -0,0 +1,2618 @@ +// Implementation of the base circular buffer. + +// Copyright (c) 2003-2007 Jan Gaspar + +// Use, modification, and distribution is subject to 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_CIRCULAR_BUFFER_BASE_HPP) +#define BOOST_CIRCULAR_BUFFER_BASE_HPP + +#if defined(_MSC_VER) && _MSC_VER >= 1200 + #pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(BOOST_NO_EXCEPTIONS) + #include +#endif +#if BOOST_CB_ENABLE_DEBUG + #include +#endif +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) + #include +#endif + +namespace boost { + +/*! + \class circular_buffer + \brief Circular buffer - a STL compliant container. + \param T The type of the elements stored in the circular_buffer. + \par Type Requirements T + The T has to be + SGIAssignable (SGI STL defined combination of + Assignable and CopyConstructible). + Moreover T has to be + DefaultConstructible if supplied as a default parameter when invoking some of the + circular_buffer's methods e.g. + insert(iterator pos, const value_type& item = %value_type()). And + EqualityComparable and/or + LessThanComparable if the circular_buffer + will be compared with another container. + \param Alloc The allocator type used for all internal memory management. + \par Type Requirements Alloc + The Alloc has to meet the allocator requirements imposed by STL. + \par Default Alloc + std::allocator + + For detailed documentation of the circular_buffer visit: + http://www.boost.org/libs/circular_buffer/doc/circular_buffer.html +*/ +template +class circular_buffer +/*! \cond */ +#if BOOST_CB_ENABLE_DEBUG +: public cb_details::debug_iterator_registry +#endif +/*! \endcond */ +{ + +// Requirements + BOOST_CLASS_REQUIRE(T, boost, SGIAssignableConcept); + +public: +// Basic types + + //! The type of elements stored in the circular_buffer. + typedef typename Alloc::value_type value_type; + + //! A pointer to an element. + typedef typename Alloc::pointer pointer; + + //! A const pointer to the element. + typedef typename Alloc::const_pointer const_pointer; + + //! A reference to an element. + typedef typename Alloc::reference reference; + + //! A const reference to an element. + typedef typename Alloc::const_reference const_reference; + + //! The distance type. + /*! + (A signed integral type used to represent the distance between two iterators.) + */ + typedef typename Alloc::difference_type difference_type; + + //! The size type. + /*! + (An unsigned integral type that can represent any non-negative value of the container's distance type.) + */ + typedef typename Alloc::size_type size_type; + + //! The type of an allocator used in the circular_buffer. + typedef Alloc allocator_type; + +// Iterators + + //! A const (random access) iterator used to iterate through the circular_buffer. + typedef cb_details::iterator< circular_buffer, cb_details::const_traits > const_iterator; + + //! A (random access) iterator used to iterate through the circular_buffer. + typedef cb_details::iterator< circular_buffer, cb_details::nonconst_traits > iterator; + + //! A const iterator used to iterate backwards through a circular_buffer. + typedef boost::reverse_iterator const_reverse_iterator; + + //! An iterator used to iterate backwards through a circular_buffer. + typedef boost::reverse_iterator reverse_iterator; + +// Container specific types + + //! An array range. + /*! + (A typedef for the std::pair where + its first element is a pointer to a beginning of an array and its second element represents + a size of the array.) + */ + typedef std::pair array_range; + + //! A range of a const array. + /*! + (A typedef for the std::pair where + its first element is a pointer to a beginning of a const array and its second element represents + a size of the const array.) + */ + typedef std::pair const_array_range; + + //! The capacity type. + /*! + (Same as size_type - defined for consistency with the + circular_buffer_space_optimized.) + */ + typedef size_type capacity_type; + +// Helper types + + // A type representing the "best" way to pass the value_type to a method. + typedef typename call_traits::param_type param_value_type; + + // A type representing the "best" way to return the value_type from a const method. + typedef typename call_traits::param_type return_value_type; + +private: +// Member variables + + //! The internal buffer used for storing elements in the circular buffer. + pointer m_buff; + + //! The internal buffer's end (end of the storage space). + pointer m_end; + + //! The virtual beginning of the circular buffer. + pointer m_first; + + //! The virtual end of the circular buffer (one behind the last element). + pointer m_last; + + //! The number of items currently stored in the circular buffer. + size_type m_size; + + //! The allocator. + allocator_type m_alloc; + +// Friends +#if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + friend iterator; + friend const_iterator; +#else + template friend struct cb_details::iterator; +#endif + +public: +// Allocator + + //! Get the allocator. + /*! + \return The allocator. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa get_allocator() for obtaining an allocator %reference. + */ + allocator_type get_allocator() const { return m_alloc; } + + //! Get the allocator reference. + /*! + \return A reference to the allocator. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \note This method was added in order to optimize obtaining of the allocator with a state, + although use of stateful allocators in STL is discouraged. + \sa get_allocator() const + */ + allocator_type& get_allocator() { return m_alloc; } + +// Element access + + //! Get the iterator pointing to the beginning of the circular_buffer. + /*! + \return A random access iterator pointing to the first element of the circular_buffer. If the + circular_buffer is empty it returns an iterator equal to the one returned by + end(). + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa end(), rbegin(), rend() + */ + iterator begin() { return iterator(this, empty() ? 0 : m_first); } + + //! Get the iterator pointing to the end of the circular_buffer. + /*! + \return A random access iterator pointing to the element "one behind" the last element of the + circular_buffer. If the circular_buffer is empty it returns an iterator equal to + the one returned by begin(). + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa begin(), rbegin(), rend() + */ + iterator end() { return iterator(this, 0); } + + //! Get the const iterator pointing to the beginning of the circular_buffer. + /*! + \return A const random access iterator pointing to the first element of the circular_buffer. If + the circular_buffer is empty it returns an iterator equal to the one returned by + end() const. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa end() const, rbegin() const, rend() const + */ + const_iterator begin() const { return const_iterator(this, empty() ? 0 : m_first); } + + //! Get the const iterator pointing to the end of the circular_buffer. + /*! + \return A const random access iterator pointing to the element "one behind" the last element of the + circular_buffer. If the circular_buffer is empty it returns an iterator equal to + the one returned by begin() const const. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa begin() const, rbegin() const, rend() const + */ + const_iterator end() const { return const_iterator(this, 0); } + + //! Get the iterator pointing to the beginning of the "reversed" circular_buffer. + /*! + \return A reverse random access iterator pointing to the last element of the circular_buffer. + If the circular_buffer is empty it returns an iterator equal to the one returned by + rend(). + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa rend(), begin(), end() + */ + reverse_iterator rbegin() { return reverse_iterator(end()); } + + //! Get the iterator pointing to the end of the "reversed" circular_buffer. + /*! + \return A reverse random access iterator pointing to the element "one before" the first element of the + circular_buffer. If the circular_buffer is empty it returns an iterator equal to + the one returned by rbegin(). + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa rbegin(), begin(), end() + */ + reverse_iterator rend() { return reverse_iterator(begin()); } + + //! Get the const iterator pointing to the beginning of the "reversed" circular_buffer. + /*! + \return A const reverse random access iterator pointing to the last element of the + circular_buffer. If the circular_buffer is empty it returns an iterator equal + to the one returned by rend() const. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa rend() const, begin() const, end() const + */ + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + + //! Get the const iterator pointing to the end of the "reversed" circular_buffer. + /*! + \return A const reverse random access iterator pointing to the element "one before" the first element of the + circular_buffer. If the circular_buffer is empty it returns an iterator equal + to the one returned by rbegin() const. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa rbegin() const, begin() const, end() const + */ + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + + //! Get the element at the index position. + /*! + \pre 0 \<= index \&\& index \< size() + \param index The position of the element. + \return A reference to the element at the index position. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa at() + */ + reference operator [] (size_type index) { + BOOST_CB_ASSERT(index < size()); // check for invalid index + return *add(m_first, index); + } + + //! Get the element at the index position. + /*! + \pre 0 \<= index \&\& index \< size() + \param index The position of the element. + \return A const reference to the element at the index position. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa \link at(size_type)const at() const \endlink + */ + return_value_type operator [] (size_type index) const { + BOOST_CB_ASSERT(index < size()); // check for invalid index + return *add(m_first, index); + } + + //! Get the element at the index position. + /*! + \param index The position of the element. + \return A reference to the element at the index position. + \throws std::out_of_range when the index is invalid (when + index >= size()). + \par Exception Safety + Strong. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa operator[] + */ + reference at(size_type index) { + check_position(index); + return (*this)[index]; + } + + //! Get the element at the index position. + /*! + \param index The position of the element. + \return A const reference to the element at the index position. + \throws std::out_of_range when the index is invalid (when + index >= size()). + \par Exception Safety + Strong. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa \link operator[](size_type)const operator[] const \endlink + */ + return_value_type at(size_type index) const { + check_position(index); + return (*this)[index]; + } + + //! Get the first element. + /*! + \pre !empty() + \return A reference to the first element of the circular_buffer. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa back() + */ + reference front() { + BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available) + return *m_first; + } + + //! Get the last element. + /*! + \pre !empty() + \return A reference to the last element of the circular_buffer. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa front() + */ + reference back() { + BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available) + return *((m_last == m_buff ? m_end : m_last) - 1); + } + + //! Get the first element. + /*! + \pre !empty() + \return A const reference to the first element of the circular_buffer. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa back() const + */ + return_value_type front() const { + BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available) + return *m_first; + } + + //! Get the last element. + /*! + \pre !empty() + \return A const reference to the last element of the circular_buffer. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa front() const + */ + return_value_type back() const { + BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available) + return *((m_last == m_buff ? m_end : m_last) - 1); + } + + //! Get the first continuous array of the internal buffer. + /*! + This method in combination with array_two() can be useful when passing the stored data into + a legacy C API as an array. Suppose there is a circular_buffer of capacity 10, containing 7 + characters 'a', 'b', ..., 'g' where buff[0] == 'a', buff[1] == 'b', + ... and buff[6] == 'g':

+ circular_buffer buff(10);

+ The internal representation is often not linear and the state of the internal buffer may look like this:
+
+ |e|f|g| | | |a|b|c|d|
+ end ---^
+ begin -------^


+ where |a|b|c|d| represents the "array one", |e|f|g| represents the "array two" and + | | | | is a free space.
+ Now consider a typical C style function for writing data into a file:

+ int write(int file_desc, char* buff, int num_bytes);

+ There are two ways how to write the content of the circular_buffer into a file. Either relying + on array_one() and array_two() methods and calling the write function twice:

+ array_range ar = buff.array_one();
+ write(file_desc, ar.first, ar.second);
+ ar = buff.array_two();
+ write(file_desc, ar.first, ar.second);


+ Or relying on the linearize() method:

+ write(file_desc, buff.linearize(), buff.size());

+ Since the complexity of array_one() and array_two() methods is constant the first + option is suitable when calling the write method is "cheap". On the other hand the second option is more + suitable when calling the write method is more "expensive" than calling the linearize() method + whose complexity is linear. + \return The array range of the first continuous array of the internal buffer. In the case the + circular_buffer is empty the size of the returned array is 0. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \warning In general invoking any method which modifies the internal state of the circular_buffer may + delinearize the internal buffer and invalidate the array ranges returned by array_one() + and array_two() (and their const versions). + \note In the case the internal buffer is linear e.g. |a|b|c|d|e|f|g| | | | the "array one" is + represented by |a|b|c|d|e|f|g| and the "array two" does not exist (the + array_two() method returns an array with the size 0). + \sa array_two(), linearize() + */ + array_range array_one() { + return array_range(m_first, (m_last <= m_first && !empty() ? m_end : m_last) - m_first); + } + + //! Get the second continuous array of the internal buffer. + /*! + This method in combination with array_one() can be useful when passing the stored data into + a legacy C API as an array. + \return The array range of the second continuous array of the internal buffer. In the case the internal buffer + is linear or the circular_buffer is empty the size of the returned array is + 0. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa array_one() + */ + array_range array_two() { + return array_range(m_buff, m_last <= m_first && !empty() ? m_last - m_buff : 0); + } + + //! Get the first continuous array of the internal buffer. + /*! + This method in combination with array_two() const can be useful when passing the stored data into + a legacy C API as an array. + \return The array range of the first continuous array of the internal buffer. In the case the + circular_buffer is empty the size of the returned array is 0. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa array_two() const; array_one() for more details how to pass data into a legacy C + API. + */ + const_array_range array_one() const { + return const_array_range(m_first, (m_last <= m_first && !empty() ? m_end : m_last) - m_first); + } + + //! Get the second continuous array of the internal buffer. + /*! + This method in combination with array_one() const can be useful when passing the stored data into + a legacy C API as an array. + \return The array range of the second continuous array of the internal buffer. In the case the internal buffer + is linear or the circular_buffer is empty the size of the returned array is + 0. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa array_one() const + */ + const_array_range array_two() const { + return const_array_range(m_buff, m_last <= m_first && !empty() ? m_last - m_buff : 0); + } + + //! Linearize the internal buffer into a continuous array. + /*! + This method can be useful when passing the stored data into a legacy C API as an array. + \post \&(*this)[0] \< \&(*this)[1] \< ... \< \&(*this)[size() - 1] + \return A pointer to the beginning of the array or 0 if empty. + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic; no-throw if the operations in the Throws section do not throw anything. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer (except iterators equal to + end()); does not invalidate any iterators if the postcondition (the Effect) is already + met prior calling this method. + \par Complexity + Linear (in the size of the circular_buffer); constant if the postcondition (the + Effect) is already met. + \warning In general invoking any method which modifies the internal state of the circular_buffer + may delinearize the internal buffer and invalidate the returned pointer. + \sa array_one() and array_two() for the other option how to pass data into a legacy + C API. + */ + pointer linearize() { + if (empty()) + return 0; + if (m_first < m_last || m_last == m_buff) + return m_first; + pointer src = m_first; + pointer dest = m_buff; + size_type moved = 0; + size_type constructed = 0; + BOOST_TRY { + for (pointer first = m_first; dest < src; src = first) { + for (size_type ii = 0; src < m_end; ++src, ++dest, ++moved, ++ii) { + if (moved == size()) { + first = dest; + break; + } + if (dest == first) { + first += ii; + break; + } + if (is_uninitialized(dest)) { + m_alloc.construct(dest, *src); + ++constructed; + } else { + value_type tmp = *src; + replace(src, *dest); + replace(dest, tmp); + } + } + } + } BOOST_CATCH(...) { + m_last += constructed; + m_size += constructed; + BOOST_RETHROW + } + BOOST_CATCH_END + for (src = m_end - constructed; src < m_end; ++src) + destroy_item(src); + m_first = m_buff; + m_last = add(m_buff, size()); +#if BOOST_CB_ENABLE_DEBUG + invalidate_iterators_except(end()); +#endif + return m_buff; + } + +// Size and capacity + + //! Get the number of elements currently stored in the circular_buffer. + /*! + \return The number of elements stored in the circular_buffer. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa capacity(), max_size(), reserve(), + \link resize() resize(size_type, const_reference)\endlink + */ + size_type size() const { return m_size; } + + /*! \brief Get the largest possible size or capacity of the circular_buffer. (It depends on + allocator's %max_size()). + \return The maximum size/capacity the circular_buffer can be set to. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa size(), capacity(), reserve() + */ + size_type max_size() const { + return (std::min)(m_alloc.max_size(), (std::numeric_limits::max)()); + } + + //! Is the circular_buffer empty? + /*! + \return true if there are no elements stored in the circular_buffer; + false otherwise. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa full() + */ + bool empty() const { return size() == 0; } + + //! Is the circular_buffer full? + /*! + \return true if the number of elements stored in the circular_buffer + equals the capacity of the circular_buffer; false otherwise. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa empty() + */ + bool full() const { return capacity() == size(); } + + /*! \brief Get the maximum number of elements which can be inserted into the circular_buffer without + overwriting any of already stored elements. + \return capacity() - size() + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa capacity(), size(), max_size() + */ + size_type reserve() const { return capacity() - size(); } + + //! Get the capacity of the circular_buffer. + /*! + \return The maximum number of elements which can be stored in the circular_buffer. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer). + \sa reserve(), size(), max_size(), + set_capacity(capacity_type) + */ + capacity_type capacity() const { return m_end - m_buff; } + + //! Change the capacity of the circular_buffer. + /*! + \post capacity() == new_capacity \&\& size() \<= new_capacity

+ If the current number of elements stored in the circular_buffer is greater than the desired + new capacity then number of [size() - new_capacity] last elements will be removed and + the new size will be equal to new_capacity. + \param new_capacity The new capacity. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Strong. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer (except iterators equal to + end()) if the new capacity is different from the original. + \par Complexity + Linear (in min[size(), new_capacity]). + \sa rset_capacity(capacity_type), + \link resize() resize(size_type, const_reference)\endlink + */ + void set_capacity(capacity_type new_capacity) { + if (new_capacity == capacity()) + return; + pointer buff = allocate(new_capacity); + iterator b = begin(); + BOOST_TRY { + reset(buff, + cb_details::uninitialized_copy_with_alloc(b, b + (std::min)(new_capacity, size()), buff, m_alloc), + new_capacity); + } BOOST_CATCH(...) { + deallocate(buff, new_capacity); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + //! Change the size of the circular_buffer. + /*! + \post size() == new_size \&\& capacity() >= new_size

+ If the new size is greater than the current size, copies of item will be inserted at the + back of the of the circular_buffer in order to achieve the desired size. In the case + the resulting size exceeds the current capacity the capacity will be set to new_size.
+ If the current number of elements stored in the circular_buffer is greater than the desired + new size then number of [size() - new_size] last elements will be removed. (The + capacity will remain unchanged.) + \param new_size The new size. + \param item The element the circular_buffer will be filled with in order to gain the requested + size. (See the Effect.) + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer (except iterators equal to + end()) if the new size is greater than the current capacity. Invalidates iterators pointing + to the removed elements if the new size is lower that the original size. Otherwise it does not invalidate + any iterator. + \par Complexity + Linear (in the new size of the circular_buffer). + \sa \link rresize() rresize(size_type, const_reference)\endlink, + set_capacity(capacity_type) + */ + void resize(size_type new_size, param_value_type item = value_type()) { + if (new_size > size()) { + if (new_size > capacity()) + set_capacity(new_size); + insert(end(), new_size - size(), item); + } else { + iterator e = end(); + erase(e - (size() - new_size), e); + } + } + + //! Change the capacity of the circular_buffer. + /*! + \post capacity() == new_capacity \&\& size() \<= new_capacity

+ If the current number of elements stored in the circular_buffer is greater than the desired + new capacity then number of [size() - new_capacity] first elements will be removed + and the new size will be equal to new_capacity. + \param new_capacity The new capacity. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Strong. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer (except iterators equal to + end()) if the new capacity is different from the original. + \par Complexity + Linear (in min[size(), new_capacity]). + \sa set_capacity(capacity_type), + \link rresize() rresize(size_type, const_reference)\endlink + */ + void rset_capacity(capacity_type new_capacity) { + if (new_capacity == capacity()) + return; + pointer buff = allocate(new_capacity); + iterator e = end(); + BOOST_TRY { + reset(buff, cb_details::uninitialized_copy_with_alloc(e - (std::min)(new_capacity, size()), + e, buff, m_alloc), new_capacity); + } BOOST_CATCH(...) { + deallocate(buff, new_capacity); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + //! Change the size of the circular_buffer. + /*! + \post size() == new_size \&\& capacity() >= new_size

+ If the new size is greater than the current size, copies of item will be inserted at the + front of the of the circular_buffer in order to achieve the desired size. In the case + the resulting size exceeds the current capacity the capacity will be set to new_size.
+ If the current number of elements stored in the circular_buffer is greater than the desired + new size then number of [size() - new_size] first elements will be removed. (The + capacity will remain unchanged.) + \param new_size The new size. + \param item The element the circular_buffer will be filled with in order to gain the requested + size. (See the Effect.) + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer (except iterators equal to + end()) if the new size is greater than the current capacity. Invalidates iterators pointing + to the removed elements if the new size is lower that the original size. Otherwise it does not invalidate + any iterator. + \par Complexity + Linear (in the new size of the circular_buffer). + \sa \link resize() resize(size_type, const_reference)\endlink, + rset_capacity(capacity_type) + */ + void rresize(size_type new_size, param_value_type item = value_type()) { + if (new_size > size()) { + if (new_size > capacity()) + set_capacity(new_size); + rinsert(begin(), new_size - size(), item); + } else { + rerase(begin(), end() - new_size); + } + } + +// Construction/Destruction + + //! Create an empty circular_buffer with zero capacity. + /*! + \post capacity() == 0 \&\& size() == 0 + \param alloc The allocator. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \par Complexity + Constant. + \warning Since Boost version 1.36 the behaviour of this constructor has changed. Now the constructor does not + allocate any memory and both capacity and size are set to zero. Also note when inserting an element + into a circular_buffer with zero capacity (e.g. by + \link push_back() push_back(const_reference)\endlink or + \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink) nothing + will be inserted and the size (as well as capacity) remains zero. + */ + explicit circular_buffer(const allocator_type& alloc = allocator_type()) + : m_buff(0), m_end(0), m_first(0), m_last(0), m_size(0), m_alloc(alloc) {} + + //! Create an empty circular_buffer with the specified capacity. + /*! + \post capacity() == capacity \&\& size() == 0 + \param capacity The maximum number of elements which can be stored in the circular_buffer. + \param alloc The allocator. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \par Complexity + Constant. + */ + explicit circular_buffer(capacity_type capacity, const allocator_type& alloc = allocator_type()) + : m_size(0), m_alloc(alloc) { + initialize(capacity); + } + + /*! \brief Create a full circular_buffer with the specified capacity and filled with n + copies of item. + \post capacity() == n \&\& full() \&\& (*this)[0] == item \&\& (*this)[1] == item \&\& ... \&\& + (*this)[n - 1] == item + \param n The number of elements the created circular_buffer will be filled with. + \param item The element the created circular_buffer will be filled with. + \param alloc The allocator. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Complexity + Linear (in the n). + */ + circular_buffer(size_type n, param_value_type item, const allocator_type& alloc = allocator_type()) + : m_size(n), m_alloc(alloc) { + initialize(n, item); + } + + /*! \brief Create a circular_buffer with the specified capacity and filled with n + copies of item. + \pre capacity >= n + \post capacity() == capacity \&\& size() == n \&\& (*this)[0] == item \&\& (*this)[1] == item \&\& ... + \&\& (*this)[n - 1] == item + \param capacity The capacity of the created circular_buffer. + \param n The number of elements the created circular_buffer will be filled with. + \param item The element the created circular_buffer will be filled with. + \param alloc The allocator. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Complexity + Linear (in the n). + */ + circular_buffer(capacity_type capacity, size_type n, param_value_type item, + const allocator_type& alloc = allocator_type()) + : m_size(n), m_alloc(alloc) { + BOOST_CB_ASSERT(capacity >= size()); // check for capacity lower than size + initialize(capacity, item); + } + + //! The copy constructor. + /*! + Creates a copy of the specified circular_buffer. + \post *this == cb + \param cb The circular_buffer to be copied. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Complexity + Linear (in the size of cb). + */ + circular_buffer(const circular_buffer& cb) + : m_size(cb.size()), m_alloc(cb.get_allocator()) { + m_first = m_last = m_buff = allocate(cb.capacity()); + BOOST_TRY { + m_end = cb_details::uninitialized_copy_with_alloc(cb.begin(), cb.end(), m_buff, m_alloc); + } BOOST_CATCH(...) { + deallocate(m_buff, cb.capacity()); + BOOST_RETHROW + } + BOOST_CATCH_END + } + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + + /*! \cond */ + template + circular_buffer(InputIterator first, InputIterator last) + : m_alloc(allocator_type()) { + initialize(first, last, is_integral()); + } + + template + circular_buffer(capacity_type capacity, InputIterator first, InputIterator last) + : m_alloc(allocator_type()) { + initialize(capacity, first, last, is_integral()); + } + /*! \endcond */ + +#else + + //! Create a full circular_buffer filled with a copy of the range. + /*! + \pre Valid range [first, last).
+ first and last have to meet the requirements of + InputIterator. + \post capacity() == std::distance(first, last) \&\& full() \&\& (*this)[0]== *first \&\& + (*this)[1] == *(first + 1) \&\& ... \&\& (*this)[std::distance(first, last) - 1] == *(last - 1) + \param first The beginning of the range to be copied. + \param last The end of the range to be copied. + \param alloc The allocator. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Complexity + Linear (in the std::distance(first, last)). + */ + template + circular_buffer(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()) + : m_alloc(alloc) { + initialize(first, last, is_integral()); + } + + //! Create a circular_buffer with the specified capacity and filled with a copy of the range. + /*! + \pre Valid range [first, last).
+ first and last have to meet the requirements of + InputIterator. + \post capacity() == capacity \&\& size() \<= std::distance(first, last) \&\& + (*this)[0]== *(last - capacity) \&\& (*this)[1] == *(last - capacity + 1) \&\& ... \&\& + (*this)[capacity - 1] == *(last - 1)

+ If the number of items to be copied from the range [first, last) is greater than the + specified capacity then only elements from the range [last - capacity, last) + will be copied. + \param capacity The capacity of the created circular_buffer. + \param first The beginning of the range to be copied. + \param last The end of the range to be copied. + \param alloc The allocator. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Complexity + Linear (in std::distance(first, last); in + min[capacity, std::distance(first, last)] if the InputIterator is a + RandomAccessIterator). + */ + template + circular_buffer(capacity_type capacity, InputIterator first, InputIterator last, + const allocator_type& alloc = allocator_type()) + : m_alloc(alloc) { + initialize(capacity, first, last, is_integral()); + } + +#endif // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + + //! The destructor. + /*! + Destroys the circular_buffer. + \throws Nothing. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer (including iterators equal to + end()). + \par Complexity + Linear (in the size of the circular_buffer). + \sa clear() + */ + ~circular_buffer() { + destroy(); +#if BOOST_CB_ENABLE_DEBUG + invalidate_all_iterators(); +#endif + } + +public: +// Assign methods + + //! The assign operator. + /*! + Makes this circular_buffer to become a copy of the specified circular_buffer. + \post *this == cb + \param cb The circular_buffer to be copied. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Strong. + \par Iterator Invalidation + Invalidates all iterators pointing to this circular_buffer (except iterators equal to + end()). + \par Complexity + Linear (in the size of cb). + \sa \link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink, + \link assign(capacity_type, size_type, param_value_type) + assign(capacity_type, size_type, const_reference)\endlink, + assign(InputIterator, InputIterator), + assign(capacity_type, InputIterator, InputIterator) + */ + circular_buffer& operator = (const circular_buffer& cb) { + if (this == &cb) + return *this; + pointer buff = allocate(cb.capacity()); + BOOST_TRY { + reset(buff, cb_details::uninitialized_copy_with_alloc(cb.begin(), cb.end(), buff, m_alloc), cb.capacity()); + } BOOST_CATCH(...) { + deallocate(buff, cb.capacity()); + BOOST_RETHROW + } + BOOST_CATCH_END + return *this; + } + + //! Assign n items into the circular_buffer. + /*! + The content of the circular_buffer will be removed and replaced with n copies of the + item. + \post capacity() == n \&\& size() == n \&\& (*this)[0] == item \&\& (*this)[1] == item \&\& ... \&\& + (*this) [n - 1] == item + \param n The number of elements the circular_buffer will be filled with. + \param item The element the circular_buffer will be filled with. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer (except iterators equal to + end()). + \par Complexity + Linear (in the n). + \sa operator=, \link assign(capacity_type, size_type, param_value_type) + assign(capacity_type, size_type, const_reference)\endlink, + assign(InputIterator, InputIterator), + assign(capacity_type, InputIterator, InputIterator) + */ + void assign(size_type n, param_value_type item) { + assign_n(n, n, cb_details::assign_n(n, item, m_alloc)); + } + + //! Assign n items into the circular_buffer specifying the capacity. + /*! + The capacity of the circular_buffer will be set to the specified value and the content of the + circular_buffer will be removed and replaced with n copies of the item. + \pre capacity >= n + \post capacity() == capacity \&\& size() == n \&\& (*this)[0] == item \&\& (*this)[1] == item + \&\& ... \&\& (*this) [n - 1] == item + \param capacity The new capacity. + \param n The number of elements the circular_buffer will be filled with. + \param item The element the circular_buffer will be filled with. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer (except iterators equal to + end()). + \par Complexity + Linear (in the n). + \sa operator=, \link assign(size_type, param_value_type) + assign(size_type, const_reference)\endlink, assign(InputIterator, InputIterator), + assign(capacity_type, InputIterator, InputIterator) + */ + void assign(capacity_type capacity, size_type n, param_value_type item) { + BOOST_CB_ASSERT(capacity >= n); // check for new capacity lower than n + assign_n(capacity, n, cb_details::assign_n(n, item, m_alloc)); + } + + //! Assign a copy of the range into the circular_buffer. + /*! + The content of the circular_buffer will be removed and replaced with copies of elements from the + specified range. + \pre Valid range [first, last).
+ first and last have to meet the requirements of + InputIterator. + \post capacity() == std::distance(first, last) \&\& size() == std::distance(first, last) \&\& + (*this)[0]== *first \&\& (*this)[1] == *(first + 1) \&\& ... \&\& (*this)[std::distance(first, last) - 1] + == *(last - 1) + \param first The beginning of the range to be copied. + \param last The end of the range to be copied. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer (except iterators equal to + end()). + \par Complexity + Linear (in the std::distance(first, last)). + \sa operator=, \link assign(size_type, param_value_type) + assign(size_type, const_reference)\endlink, + \link assign(capacity_type, size_type, param_value_type) + assign(capacity_type, size_type, const_reference)\endlink, + assign(capacity_type, InputIterator, InputIterator) + */ + template + void assign(InputIterator first, InputIterator last) { + assign(first, last, is_integral()); + } + + //! Assign a copy of the range into the circular_buffer specifying the capacity. + /*! + The capacity of the circular_buffer will be set to the specified value and the content of the + circular_buffer will be removed and replaced with copies of elements from the specified range. + \pre Valid range [first, last).
+ first and last have to meet the requirements of + InputIterator. + \post capacity() == capacity \&\& size() \<= std::distance(first, last) \&\& + (*this)[0]== *(last - capacity) \&\& (*this)[1] == *(last - capacity + 1) \&\& ... \&\& + (*this)[capacity - 1] == *(last - 1)

+ If the number of items to be copied from the range [first, last) is greater than the + specified capacity then only elements from the range [last - capacity, last) + will be copied. + \param capacity The new capacity. + \param first The beginning of the range to be copied. + \param last The end of the range to be copied. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer (except iterators equal to + end()). + \par Complexity + Linear (in std::distance(first, last); in + min[capacity, std::distance(first, last)] if the InputIterator is a + RandomAccessIterator). + \sa operator=, \link assign(size_type, param_value_type) + assign(size_type, const_reference)\endlink, + \link assign(capacity_type, size_type, param_value_type) + assign(capacity_type, size_type, const_reference)\endlink, + assign(InputIterator, InputIterator) + */ + template + void assign(capacity_type capacity, InputIterator first, InputIterator last) { + assign(capacity, first, last, is_integral()); + } + + //! Swap the contents of two circular_buffers. + /*! + \post this contains elements of cb and vice versa; the capacity of this + equals to the capacity of cb and vice versa. + \param cb The circular_buffer whose content will be swapped. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Invalidates all iterators of both circular_buffers. (On the other hand the iterators still + point to the same elements but within another container. If you want to rely on this feature you have to + turn the Debug Support off otherwise an assertion will report an error if such + invalidated iterator is used.) + \par Complexity + Constant (in the size of the circular_buffer). + \sa swap(circular_buffer&, circular_buffer&) + */ + void swap(circular_buffer& cb) { + swap_allocator(cb, is_stateless()); + std::swap(m_buff, cb.m_buff); + std::swap(m_end, cb.m_end); + std::swap(m_first, cb.m_first); + std::swap(m_last, cb.m_last); + std::swap(m_size, cb.m_size); +#if BOOST_CB_ENABLE_DEBUG + invalidate_all_iterators(); + cb.invalidate_all_iterators(); +#endif + } + +// push and pop + + //! Insert a new element at the end of the circular_buffer. + /*! + \post if capacity() > 0 then back() == item
+ If the circular_buffer is full, the first element will be removed. If the capacity is + 0, nothing will be inserted. + \param item The element to be inserted. + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic; no-throw if the operation in the Throws section does not throw anything. + \par Iterator Invalidation + Does not invalidate any iterators with the exception of iterators pointing to the overwritten element. + \par Complexity + Constant (in the size of the circular_buffer). + \sa \link push_front() push_front(const_reference)\endlink, + pop_back(), pop_front() + */ + void push_back(param_value_type item = value_type()) { + if (full()) { + if (empty()) + return; + replace(m_last, item); + increment(m_last); + m_first = m_last; + } else { + m_alloc.construct(m_last, item); + increment(m_last); + ++m_size; + } + } + + //! Insert a new element at the beginning of the circular_buffer. + /*! + \post if capacity() > 0 then front() == item
+ If the circular_buffer is full, the last element will be removed. If the capacity is + 0, nothing will be inserted. + \param item The element to be inserted. + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic; no-throw if the operation in the Throws section does not throw anything. + \par Iterator Invalidation + Does not invalidate any iterators with the exception of iterators pointing to the overwritten element. + \par Complexity + Constant (in the size of the circular_buffer). + \sa \link push_back() push_back(const_reference)\endlink, + pop_back(), pop_front() + */ + void push_front(param_value_type item = value_type()) { + BOOST_TRY { + if (full()) { + if (empty()) + return; + decrement(m_first); + replace(m_first, item); + m_last = m_first; + } else { + decrement(m_first); + m_alloc.construct(m_first, item); + ++m_size; + } + } BOOST_CATCH(...) { + increment(m_first); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + //! Remove the last element from the circular_buffer. + /*! + \pre !empty() + \post The last element is removed from the circular_buffer. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Invalidates only iterators pointing to the removed element. + \par Complexity + Constant (in the size of the circular_buffer). + \sa pop_front(), \link push_back() push_back(const_reference)\endlink, + \link push_front() push_front(const_reference)\endlink + */ + void pop_back() { + BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available) + decrement(m_last); + destroy_item(m_last); + --m_size; + } + + //! Remove the first element from the circular_buffer. + /*! + \pre !empty() + \post The first element is removed from the circular_buffer. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Invalidates only iterators pointing to the removed element. + \par Complexity + Constant (in the size of the circular_buffer). + \sa pop_back(), \link push_back() push_back(const_reference)\endlink, + \link push_front() push_front(const_reference)\endlink + */ + void pop_front() { + BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available) + destroy_item(m_first); + increment(m_first); + --m_size; + } + +public: +// Insert + + //! Insert an element at the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer or its end. + \post The item will be inserted at the position pos.
+ If the circular_buffer is full, the first element will be overwritten. If the + circular_buffer is full and the pos points to begin(), then the + item will not be inserted. If the capacity is 0, nothing will be inserted. + \param pos An iterator specifying the position where the item will be inserted. + \param item The element to be inserted. + \return Iterator to the inserted element or begin() if the item is not inserted. (See + the Effect.) + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic; no-throw if the operation in the Throws section does not throw anything. + \par Iterator Invalidation + Invalidates iterators pointing to the elements at the insertion point (including pos) and + iterators behind the insertion point (towards the end; except iterators equal to end()). It + also invalidates iterators pointing to the overwritten element. + \par Complexity + Linear (in std::distance(pos, end())). + \sa \link insert(iterator, size_type, param_value_type) + insert(iterator, size_type, value_type)\endlink, + insert(iterator, InputIterator, InputIterator), + \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, + \link rinsert(iterator, size_type, param_value_type) + rinsert(iterator, size_type, value_type)\endlink, + rinsert(iterator, InputIterator, InputIterator) + */ + iterator insert(iterator pos, param_value_type item = value_type()) { + BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator + iterator b = begin(); + if (full() && pos == b) + return b; + return insert_item(pos, item); + } + + //! Insert n copies of the item at the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer or its end. + \post The number of min[n, (pos - begin()) + reserve()] elements will be inserted at the position + pos.
The number of min[pos - begin(), max[0, n - reserve()]] elements will + be overwritten at the beginning of the circular_buffer.
(See Example for the + explanation.) + \param pos An iterator specifying the position where the items will be inserted. + \param n The number of items the to be inserted. + \param item The element whose copies will be inserted. + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic; no-throw if the operations in the Throws section do not throw anything. + \par Iterator Invalidation + Invalidates iterators pointing to the elements at the insertion point (including pos) and + iterators behind the insertion point (towards the end; except iterators equal to end()). It + also invalidates iterators pointing to the overwritten elements. + \par Complexity + Linear (in min[capacity(), std::distance(pos, end()) + n]). + \par Example + Consider a circular_buffer with the capacity of 6 and the size of 4. Its internal buffer may + look like the one below.

+ |1|2|3|4| | |
+ p ---^

After inserting 5 elements at the position p:

+ insert(p, (size_t)5, 0);

actually only 4 elements get inserted and elements + 1 and 2 are overwritten. This is due to the fact the insert operation preserves + the capacity. After insertion the internal buffer looks like this:

|0|0|0|0|3|4|
+
For comparison if the capacity would not be preserved the internal buffer would then result in + |1|2|0|0|0|0|0|3|4|. + \sa \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, + insert(iterator, InputIterator, InputIterator), + \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, + \link rinsert(iterator, size_type, param_value_type) + rinsert(iterator, size_type, value_type)\endlink, + rinsert(iterator, InputIterator, InputIterator) + */ + void insert(iterator pos, size_type n, param_value_type item) { + BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator + if (n == 0) + return; + size_type copy = capacity() - (end() - pos); + if (copy == 0) + return; + if (n > copy) + n = copy; + insert_n(pos, n, cb_details::item_wrapper(item)); + } + + //! Insert the range [first, last) at the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer or its end.
+ Valid range [first, last) where first and last meet the + requirements of an InputIterator. + \post Elements from the range + [first + max[0, distance(first, last) - (pos - begin()) - reserve()], last) will be + inserted at the position pos.
The number of min[pos - begin(), max[0, + distance(first, last) - reserve()]] elements will be overwritten at the beginning of the + circular_buffer.
(See Example for the explanation.) + \param pos An iterator specifying the position where the range will be inserted. + \param first The beginning of the range to be inserted. + \param last The end of the range to be inserted. + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic; no-throw if the operations in the Throws section do not throw anything. + \par Iterator Invalidation + Invalidates iterators pointing to the elements at the insertion point (including pos) and + iterators behind the insertion point (towards the end; except iterators equal to end()). It + also invalidates iterators pointing to the overwritten elements. + \par Complexity + Linear (in [std::distance(pos, end()) + std::distance(first, last)]; in + min[capacity(), std::distance(pos, end()) + std::distance(first, last)] if the + InputIterator is a + RandomAccessIterator). + \par Example + Consider a circular_buffer with the capacity of 6 and the size of 4. Its internal buffer may + look like the one below.

+ |1|2|3|4| | |
+ p ---^

After inserting a range of elements at the position p:

+ int array[] = { 5, 6, 7, 8, 9 };
insert(p, array, array + 5);

+ actually only elements 6, 7, 8 and 9 from the + specified range get inserted and elements 1 and 2 are overwritten. This is due + to the fact the insert operation preserves the capacity. After insertion the internal buffer looks like + this:

|6|7|8|9|3|4|

For comparison if the capacity would not be preserved the + internal buffer would then result in |1|2|5|6|7|8|9|3|4|. + \sa \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, + \link insert(iterator, size_type, param_value_type) + insert(iterator, size_type, value_type)\endlink, \link rinsert(iterator, param_value_type) + rinsert(iterator, value_type)\endlink, \link rinsert(iterator, size_type, param_value_type) + rinsert(iterator, size_type, value_type)\endlink, + rinsert(iterator, InputIterator, InputIterator) + */ + template + void insert(iterator pos, InputIterator first, InputIterator last) { + BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator + insert(pos, first, last, is_integral()); + } + + //! Insert an element before the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer or its end. + \post The item will be inserted before the position pos.
+ If the circular_buffer is full, the last element will be overwritten. If the + circular_buffer is full and the pos points to end(), then the + item will not be inserted. If the capacity is 0, nothing will be inserted. + \param pos An iterator specifying the position before which the item will be inserted. + \param item The element to be inserted. + \return Iterator to the inserted element or end() if the item is not inserted. (See + the Effect.) + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic; no-throw if the operations in the Throws section do not throw anything. + \par Iterator Invalidation + Invalidates iterators pointing to the elements before the insertion point (towards the beginning and + excluding pos). It also invalidates iterators pointing to the overwritten element. + \par Complexity + Linear (in std::distance(begin(), pos)). + \sa \link rinsert(iterator, size_type, param_value_type) + rinsert(iterator, size_type, value_type)\endlink, + rinsert(iterator, InputIterator, InputIterator), + \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, + \link insert(iterator, size_type, param_value_type) + insert(iterator, size_type, value_type)\endlink, + insert(iterator, InputIterator, InputIterator) + */ + iterator rinsert(iterator pos, param_value_type item = value_type()) { + BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator + if (full() && pos.m_it == 0) + return end(); + if (pos == begin()) { + BOOST_TRY { + decrement(m_first); + construct_or_replace(!full(), m_first, item); + } BOOST_CATCH(...) { + increment(m_first); + BOOST_RETHROW + } + BOOST_CATCH_END + pos.m_it = m_first; + } else { + pointer src = m_first; + pointer dest = m_first; + decrement(dest); + pos.m_it = map_pointer(pos.m_it); + bool construct = !full(); + BOOST_TRY { + while (src != pos.m_it) { + construct_or_replace(construct, dest, *src); + increment(src); + increment(dest); + construct = false; + } + decrement(pos.m_it); + replace(pos.m_it, item); + } BOOST_CATCH(...) { + if (!construct && !full()) { + decrement(m_first); + ++m_size; + } + BOOST_RETHROW + } + BOOST_CATCH_END + decrement(m_first); + } + if (full()) + m_last = m_first; + else + ++m_size; + return iterator(this, pos.m_it); + } + + //! Insert n copies of the item before the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer or its end. + \post The number of min[n, (end() - pos) + reserve()] elements will be inserted before the + position pos.
The number of min[end() - pos, max[0, n - reserve()]] elements + will be overwritten at the end of the circular_buffer.
(See Example for the + explanation.) + \param pos An iterator specifying the position where the items will be inserted. + \param n The number of items the to be inserted. + \param item The element whose copies will be inserted. + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic; no-throw if the operations in the Throws section do not throw anything. + \par Iterator Invalidation + Invalidates iterators pointing to the elements before the insertion point (towards the beginning and + excluding pos). It also invalidates iterators pointing to the overwritten elements. + \par Complexity + Linear (in min[capacity(), std::distance(begin(), pos) + n]). + \par Example + Consider a circular_buffer with the capacity of 6 and the size of 4. Its internal buffer may + look like the one below.

+ |1|2|3|4| | |
+ p ---^

After inserting 5 elements before the position p:

+ rinsert(p, (size_t)5, 0);

actually only 4 elements get inserted and elements + 3 and 4 are overwritten. This is due to the fact the rinsert operation preserves + the capacity. After insertion the internal buffer looks like this:

|1|2|0|0|0|0|
+
For comparison if the capacity would not be preserved the internal buffer would then result in + |1|2|0|0|0|0|0|3|4|. + \sa \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, + rinsert(iterator, InputIterator, InputIterator), + \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, + \link insert(iterator, size_type, param_value_type) + insert(iterator, size_type, value_type)\endlink, + insert(iterator, InputIterator, InputIterator) + */ + void rinsert(iterator pos, size_type n, param_value_type item) { + BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator + rinsert_n(pos, n, cb_details::item_wrapper(item)); + } + + //! Insert the range [first, last) before the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer or its end.
+ Valid range [first, last) where first and last meet the + requirements of an InputIterator. + \post Elements from the range + [first, last - max[0, distance(first, last) - (end() - pos) - reserve()]) will be inserted + before the position pos.
The number of min[end() - pos, max[0, + distance(first, last) - reserve()]] elements will be overwritten at the end of the + circular_buffer.
(See Example for the explanation.) + \param pos An iterator specifying the position where the range will be inserted. + \param first The beginning of the range to be inserted. + \param last The end of the range to be inserted. + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic; no-throw if the operations in the Throws section do not throw anything. + \par Iterator Invalidation + Invalidates iterators pointing to the elements before the insertion point (towards the beginning and + excluding pos). It also invalidates iterators pointing to the overwritten elements. + \par Complexity + Linear (in [std::distance(begin(), pos) + std::distance(first, last)]; in + min[capacity(), std::distance(begin(), pos) + std::distance(first, last)] if the + InputIterator is a + RandomAccessIterator). + \par Example + Consider a circular_buffer with the capacity of 6 and the size of 4. Its internal buffer may + look like the one below.

+ |1|2|3|4| | |
+ p ---^

After inserting a range of elements before the position p:

+ int array[] = { 5, 6, 7, 8, 9 };
insert(p, array, array + 5);

+ actually only elements 5, 6, 7 and 8 from the + specified range get inserted and elements 3 and 4 are overwritten. This is due + to the fact the rinsert operation preserves the capacity. After insertion the internal buffer looks like + this:

|1|2|5|6|7|8|

For comparison if the capacity would not be preserved the + internal buffer would then result in |1|2|5|6|7|8|9|3|4|. + \sa \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, + \link rinsert(iterator, size_type, param_value_type) + rinsert(iterator, size_type, value_type)\endlink, \link insert(iterator, param_value_type) + insert(iterator, value_type)\endlink, \link insert(iterator, size_type, param_value_type) + insert(iterator, size_type, value_type)\endlink, + insert(iterator, InputIterator, InputIterator) + */ + template + void rinsert(iterator pos, InputIterator first, InputIterator last) { + BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator + rinsert(pos, first, last, is_integral()); + } + +// Erase + + //! Remove an element at the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer (but not an + end()). + \post The element at the position pos is removed. + \param pos An iterator pointing at the element to be removed. + \return Iterator to the first element remaining beyond the removed element or end() if no such + element exists. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic; no-throw if the operation in the Throws section does not throw anything. + \par Iterator Invalidation + Invalidates iterators pointing to the erased element and iterators pointing to the elements behind + the erased element (towards the end; except iterators equal to end()). + \par Complexity + Linear (in std::distance(pos, end())). + \sa erase(iterator, iterator), rerase(iterator), + rerase(iterator, iterator), clear() + */ + iterator erase(iterator pos) { + BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(pos.m_it != 0); // check for iterator pointing to end() + pointer next = pos.m_it; + increment(next); + for (pointer p = pos.m_it; next != m_last; p = next, increment(next)) + replace(p, *next); + decrement(m_last); + destroy_item(m_last); + --m_size; +#if BOOST_CB_ENABLE_DEBUG + return m_last == pos.m_it ? end() : iterator(this, pos.m_it); +#else + return m_last == pos.m_it ? end() : pos; +#endif + } + + //! Erase the range [first, last). + /*! + \pre Valid range [first, last). + \post The elements from the range [first, last) are removed. (If first == last + nothing is removed.) + \param first The beginning of the range to be removed. + \param last The end of the range to be removed. + \return Iterator to the first element remaining beyond the removed elements or end() if no such + element exists. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic; no-throw if the operation in the Throws section does not throw anything. + \par Iterator Invalidation + Invalidates iterators pointing to the erased elements and iterators pointing to the elements behind + the erased range (towards the end; except iterators equal to end()). + \par Complexity + Linear (in std::distance(first, end())). + \sa erase(iterator), rerase(iterator), rerase(iterator, iterator), + clear() + */ + iterator erase(iterator first, iterator last) { + BOOST_CB_ASSERT(first.is_valid(this)); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(last.is_valid(this)); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(first <= last); // check for wrong range + if (first == last) + return first; + pointer p = first.m_it; + while (last.m_it != 0) + replace((first++).m_it, *last++); + do { + decrement(m_last); + destroy_item(m_last); + --m_size; + } while(m_last != first.m_it); + return m_last == p ? end() : iterator(this, p); + } + + //! Remove an element at the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer (but not an + end()). + \post The element at the position pos is removed. + \param pos An iterator pointing at the element to be removed. + \return Iterator to the first element remaining in front of the removed element or begin() if no + such element exists. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic; no-throw if the operation in the Throws section does not throw anything. + \par Iterator Invalidation + Invalidates iterators pointing to the erased element and iterators pointing to the elements in front of + the erased element (towards the beginning). + \par Complexity + Linear (in std::distance(begin(), pos)). + \note This method is symetric to the erase(iterator) method and is more effective than + erase(iterator) if the iterator pos is close to the beginning of the + circular_buffer. (See the Complexity.) + \sa erase(iterator), erase(iterator, iterator), + rerase(iterator, iterator), clear() + */ + iterator rerase(iterator pos) { + BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(pos.m_it != 0); // check for iterator pointing to end() + pointer prev = pos.m_it; + pointer p = prev; + for (decrement(prev); p != m_first; p = prev, decrement(prev)) + replace(p, *prev); + destroy_item(m_first); + increment(m_first); + --m_size; +#if BOOST_CB_ENABLE_DEBUG + return p == pos.m_it ? begin() : iterator(this, pos.m_it); +#else + return p == pos.m_it ? begin() : pos; +#endif + } + + //! Erase the range [first, last). + /*! + \pre Valid range [first, last). + \post The elements from the range [first, last) are removed. (If first == last + nothing is removed.) + \param first The beginning of the range to be removed. + \param last The end of the range to be removed. + \return Iterator to the first element remaining in front of the removed elements or begin() if no + such element exists. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic; no-throw if the operation in the Throws section does not throw anything. + \par Iterator Invalidation + Invalidates iterators pointing to the erased elements and iterators pointing to the elements in front of + the erased range (towards the beginning). + \par Complexity + Linear (in std::distance(begin(), last)). + \note This method is symetric to the erase(iterator, iterator) method and is more effective than + erase(iterator, iterator) if std::distance(begin(), first) is lower that + std::distance(last, end()). + \sa erase(iterator), erase(iterator, iterator), rerase(iterator), + clear() + */ + iterator rerase(iterator first, iterator last) { + BOOST_CB_ASSERT(first.is_valid(this)); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(last.is_valid(this)); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(first <= last); // check for wrong range + if (first == last) + return first; + pointer p = map_pointer(last.m_it); + last.m_it = p; + while (first.m_it != m_first) { + decrement(first.m_it); + decrement(p); + replace(p, *first.m_it); + } + do { + destroy_item(m_first); + increment(m_first); + --m_size; + } while(m_first != p); + if (m_first == last.m_it) + return begin(); + decrement(last.m_it); + return iterator(this, last.m_it); + } + + //! Remove all stored elements from the circular_buffer. + /*! + \post size() == 0 + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer (except iterators equal to + end()). + \par Complexity + Linear (in the size of the circular_buffer). + \sa ~circular_buffer(), erase(iterator), erase(iterator, iterator), + rerase(iterator), rerase(iterator, iterator) + */ + void clear() { + destroy_content(); + m_size = 0; + } + +private: +// Helper methods + + //! Check if the index is valid. + void check_position(size_type index) const { + if (index >= size()) + throw_exception(std::out_of_range("circular_buffer")); + } + + //! Increment the pointer. + template + void increment(Pointer& p) const { + if (++p == m_end) + p = m_buff; + } + + //! Decrement the pointer. + template + void decrement(Pointer& p) const { + if (p == m_buff) + p = m_end; + --p; + } + + //! Add n to the pointer. + template + Pointer add(Pointer p, difference_type n) const { + return p + (n < (m_end - p) ? n : n - capacity()); + } + + //! Subtract n from the pointer. + template + Pointer sub(Pointer p, difference_type n) const { + return p - (n > (p - m_buff) ? n - capacity() : n); + } + + //! Map the null pointer to virtual end of circular buffer. + pointer map_pointer(pointer p) const { return p == 0 ? m_last : p; } + + //! Allocate memory. + pointer allocate(size_type n) { + if (n > max_size()) + throw_exception(std::length_error("circular_buffer")); +#if BOOST_CB_ENABLE_DEBUG + pointer p = (n == 0) ? 0 : m_alloc.allocate(n, 0); + ::memset(p, cb_details::UNINITIALIZED, sizeof(value_type) * n); + return p; +#else + return (n == 0) ? 0 : m_alloc.allocate(n, 0); +#endif + } + + //! Deallocate memory. + void deallocate(pointer p, size_type n) { + if (p != 0) + m_alloc.deallocate(p, n); + } + + //! Does the pointer point to the uninitialized memory? + bool is_uninitialized(const_pointer p) const { + return p >= m_last && (m_first < m_last || p < m_first); + } + + //! Replace an element. + void replace(pointer pos, param_value_type item) { + *pos = item; +#if BOOST_CB_ENABLE_DEBUG + invalidate_iterators(iterator(this, pos)); +#endif + } + + //! Construct or replace an element. + /*! + construct has to be set to true if and only if + pos points to an uninitialized memory. + */ + void construct_or_replace(bool construct, pointer pos, param_value_type item) { + if (construct) + m_alloc.construct(pos, item); + else + replace(pos, item); + } + + //! Destroy an item. + void destroy_item(pointer p) { + m_alloc.destroy(p); +#if BOOST_CB_ENABLE_DEBUG + invalidate_iterators(iterator(this, p)); + ::memset(p, cb_details::UNINITIALIZED, sizeof(value_type)); +#endif + } + + //! Destroy an item only if it has been constructed. + void destroy_if_constructed(pointer pos) { + if (is_uninitialized(pos)) + destroy_item(pos); + } + + //! Destroy the whole content of the circular buffer. + void destroy_content() { + for (size_type ii = 0; ii < size(); ++ii, increment(m_first)) + destroy_item(m_first); + } + + //! Destroy content and free allocated memory. + void destroy() { + destroy_content(); + deallocate(m_buff, capacity()); +#if BOOST_CB_ENABLE_DEBUG + m_buff = 0; + m_first = 0; + m_last = 0; + m_end = 0; +#endif + } + + //! Initialize the circular buffer. + void initialize(capacity_type capacity) { + m_first = m_last = m_buff = allocate(capacity); + m_end = m_buff + capacity; + } + + //! Initialize the circular buffer. + void initialize(capacity_type capacity, param_value_type item) { + initialize(capacity); + BOOST_TRY { + cb_details::uninitialized_fill_n_with_alloc(m_buff, size(), item, m_alloc); + } BOOST_CATCH(...) { + deallocate(m_buff, size()); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + //! Specialized initialize method. + template + void initialize(IntegralType n, IntegralType item, const true_type&) { + m_size = static_cast(n); + initialize(size(), item); + } + + //! Specialized initialize method. + template + void initialize(Iterator first, Iterator last, const false_type&) { + BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581)) + initialize(first, last, BOOST_ITERATOR_CATEGORY::type()); +#else + initialize(first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY::type()); +#endif + } + + //! Specialized initialize method. + template + void initialize(InputIterator first, InputIterator last, const std::input_iterator_tag&) { + BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS // check if the STL provides templated iterator constructors + // for containers + std::deque tmp(first, last, m_alloc); + size_type distance = tmp.size(); + initialize(distance, tmp.begin(), tmp.end(), distance); + } + + //! Specialized initialize method. + template + void initialize(ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) { + BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range + size_type distance = std::distance(first, last); + initialize(distance, first, last, distance); + } + + //! Specialized initialize method. + template + void initialize(capacity_type capacity, IntegralType n, IntegralType item, const true_type&) { + BOOST_CB_ASSERT(capacity >= static_cast(n)); // check for capacity lower than n + m_size = static_cast(n); + initialize(capacity, item); + } + + //! Specialized initialize method. + template + void initialize(capacity_type capacity, Iterator first, Iterator last, const false_type&) { + BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581)) + initialize(capacity, first, last, BOOST_ITERATOR_CATEGORY::type()); +#else + initialize(capacity, first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY::type()); +#endif + } + + //! Specialized initialize method. + template + void initialize(capacity_type capacity, + InputIterator first, + InputIterator last, + const std::input_iterator_tag&) { + initialize(capacity); + m_size = 0; + if (capacity == 0) + return; + while (first != last && !full()) { + m_alloc.construct(m_last, *first++); + increment(m_last); + ++m_size; + } + while (first != last) { + replace(m_last, *first++); + increment(m_last); + m_first = m_last; + } + } + + //! Specialized initialize method. + template + void initialize(capacity_type capacity, + ForwardIterator first, + ForwardIterator last, + const std::forward_iterator_tag&) { + BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range + initialize(capacity, first, last, std::distance(first, last)); + } + + //! Helper initialize method. + template + void initialize(capacity_type capacity, + ForwardIterator first, + ForwardIterator last, + size_type distance) { + initialize(capacity); + if (distance > capacity) { + std::advance(first, distance - capacity); + m_size = capacity; + } else { + m_size = distance; + if (distance != capacity) + m_last = m_buff + size(); + } + BOOST_TRY { + cb_details::uninitialized_copy_with_alloc(first, last, m_buff, m_alloc); + } BOOST_CATCH(...) { + deallocate(m_buff, capacity); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + //! Reset the circular buffer. + void reset(pointer buff, pointer last, capacity_type new_capacity) { + destroy(); + m_size = last - buff; + m_first = m_buff = buff; + m_end = m_buff + new_capacity; + m_last = last == m_end ? m_buff : last; + } + + //! Specialized method for swapping the allocator. + void swap_allocator(circular_buffer& cb, const true_type&) { + // Swap is not needed because allocators have no state. + } + + //! Specialized method for swapping the allocator. + void swap_allocator(circular_buffer& cb, const false_type&) { + std::swap(m_alloc, cb.m_alloc); + } + + //! Specialized assign method. + template + void assign(IntegralType n, IntegralType item, const true_type&) { + assign(static_cast(n), static_cast(item)); + } + + //! Specialized assign method. + template + void assign(Iterator first, Iterator last, const false_type&) { + BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581)) + assign(first, last, BOOST_ITERATOR_CATEGORY::type()); +#else + assign(first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY::type()); +#endif + } + + //! Specialized assign method. + template + void assign(InputIterator first, InputIterator last, const std::input_iterator_tag&) { + BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS // check if the STL provides templated iterator constructors + // for containers + std::deque tmp(first, last, m_alloc); + size_type distance = tmp.size(); + assign_n(distance, distance, + cb_details::assign_range::iterator, + allocator_type>(tmp.begin(), tmp.end(), m_alloc)); + } + + //! Specialized assign method. + template + void assign(ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) { + BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range + size_type distance = std::distance(first, last); + assign_n(distance, distance, cb_details::assign_range(first, last, m_alloc)); + } + + //! Specialized assign method. + template + void assign(capacity_type new_capacity, IntegralType n, IntegralType item, const true_type&) { + assign(new_capacity, static_cast(n), static_cast(item)); + } + + //! Specialized assign method. + template + void assign(capacity_type new_capacity, Iterator first, Iterator last, const false_type&) { + BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581)) + assign(new_capacity, first, last, BOOST_ITERATOR_CATEGORY::type()); +#else + assign(new_capacity, first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY::type()); +#endif + } + + //! Specialized assign method. + template + void assign(capacity_type new_capacity, InputIterator first, InputIterator last, const std::input_iterator_tag&) { + if (new_capacity == capacity()) { + clear(); + insert(begin(), first, last); + } else { +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + circular_buffer tmp(new_capacity, m_alloc); + tmp.insert(begin(), first, last); +#else + circular_buffer tmp(new_capacity, first, last, m_alloc); +#endif + tmp.swap(*this); + } + } + + //! Specialized assign method. + template + void assign(capacity_type new_capacity, ForwardIterator first, ForwardIterator last, + const std::forward_iterator_tag&) { + BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range + size_type distance = std::distance(first, last); + if (distance > new_capacity) { + std::advance(first, distance - new_capacity); + distance = new_capacity; + } + assign_n(new_capacity, distance, + cb_details::assign_range(first, last, m_alloc)); + } + + //! Helper assign method. + template + void assign_n(capacity_type new_capacity, size_type n, const Functor& fnc) { + if (new_capacity == capacity()) { + destroy_content(); + BOOST_TRY { + fnc(m_buff); + } BOOST_CATCH(...) { + m_size = 0; + BOOST_RETHROW + } + BOOST_CATCH_END + } else { + pointer buff = allocate(new_capacity); + BOOST_TRY { + fnc(buff); + } BOOST_CATCH(...) { + deallocate(buff, new_capacity); + BOOST_RETHROW + } + BOOST_CATCH_END + destroy(); + m_buff = buff; + m_end = m_buff + new_capacity; + } + m_size = n; + m_first = m_buff; + m_last = add(m_buff, size()); + } + + //! Helper insert method. + iterator insert_item(const iterator& pos, param_value_type item) { + pointer p = pos.m_it; + if (p == 0) { + construct_or_replace(!full(), m_last, item); + p = m_last; + } else { + pointer src = m_last; + pointer dest = m_last; + bool construct = !full(); + BOOST_TRY { + while (src != p) { + decrement(src); + construct_or_replace(construct, dest, *src); + decrement(dest); + construct = false; + } + replace(p, item); + } BOOST_CATCH(...) { + if (!construct && !full()) { + increment(m_last); + ++m_size; + } + BOOST_RETHROW + } + BOOST_CATCH_END + } + increment(m_last); + if (full()) + m_first = m_last; + else + ++m_size; + return iterator(this, p); + } + + //! Specialized insert method. + template + void insert(const iterator& pos, IntegralType n, IntegralType item, const true_type&) { + insert(pos, static_cast(n), static_cast(item)); + } + + //! Specialized insert method. + template + void insert(const iterator& pos, Iterator first, Iterator last, const false_type&) { + BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581)) + insert(pos, first, last, BOOST_ITERATOR_CATEGORY::type()); +#else + insert(pos, first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY::type()); +#endif + } + + //! Specialized insert method. + template + void insert(iterator pos, InputIterator first, InputIterator last, const std::input_iterator_tag&) { + if (!full() || pos != begin()) { + for (;first != last; ++pos) + pos = insert_item(pos, *first++); + } + } + + //! Specialized insert method. + template + void insert(const iterator& pos, ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) { + BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range + size_type n = std::distance(first, last); + if (n == 0) + return; + size_type copy = capacity() - (end() - pos); + if (copy == 0) + return; + if (n > copy) { + std::advance(first, n - copy); + n = copy; + } + insert_n(pos, n, cb_details::iterator_wrapper(first)); + } + + //! Helper insert method. + template + void insert_n(const iterator& pos, size_type n, const Wrapper& wrapper) { + size_type construct = reserve(); + if (construct > n) + construct = n; + if (pos.m_it == 0) { + size_type ii = 0; + pointer p = m_last; + BOOST_TRY { + for (; ii < construct; ++ii, increment(p)) + m_alloc.construct(p, *wrapper()); + for (;ii < n; ++ii, increment(p)) + replace(p, *wrapper()); + } BOOST_CATCH(...) { + size_type constructed = (std::min)(ii, construct); + m_last = add(m_last, constructed); + m_size += constructed; + BOOST_RETHROW + } + BOOST_CATCH_END + } else { + pointer src = m_last; + pointer dest = add(m_last, n - 1); + pointer p = pos.m_it; + size_type ii = 0; + BOOST_TRY { + while (src != pos.m_it) { + decrement(src); + construct_or_replace(is_uninitialized(dest), dest, *src); + decrement(dest); + } + for (; ii < n; ++ii, increment(p)) + construct_or_replace(is_uninitialized(p), p, *wrapper()); + } BOOST_CATCH(...) { + for (p = add(m_last, n - 1); p != dest; decrement(p)) + destroy_if_constructed(p); + for (n = 0, p = pos.m_it; n < ii; ++n, increment(p)) + destroy_if_constructed(p); + BOOST_RETHROW + } + BOOST_CATCH_END + } + m_last = add(m_last, n); + m_first = add(m_first, n - construct); + m_size += construct; + } + + //! Specialized rinsert method. + template + void rinsert(const iterator& pos, IntegralType n, IntegralType item, const true_type&) { + rinsert(pos, static_cast(n), static_cast(item)); + } + + //! Specialized rinsert method. + template + void rinsert(const iterator& pos, Iterator first, Iterator last, const false_type&) { + BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581)) + rinsert(pos, first, last, BOOST_ITERATOR_CATEGORY::type()); +#else + rinsert(pos, first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY::type()); +#endif + } + + //! Specialized insert method. + template + void rinsert(iterator pos, InputIterator first, InputIterator last, const std::input_iterator_tag&) { + if (!full() || pos.m_it != 0) { + for (;first != last; ++pos) { + pos = rinsert(pos, *first++); + if (pos.m_it == 0) + break; + } + } + } + + //! Specialized rinsert method. + template + void rinsert(const iterator& pos, ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) { + BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range + rinsert_n(pos, std::distance(first, last), cb_details::iterator_wrapper(first)); + } + + //! Helper rinsert method. + template + void rinsert_n(const iterator& pos, size_type n, const Wrapper& wrapper) { + if (n == 0) + return; + iterator b = begin(); + size_type copy = capacity() - (pos - b); + if (copy == 0) + return; + if (n > copy) + n = copy; + size_type construct = reserve(); + if (construct > n) + construct = n; + if (pos == b) { + pointer p = sub(m_first, n); + size_type ii = n; + BOOST_TRY { + for (;ii > construct; --ii, increment(p)) + replace(p, *wrapper()); + for (; ii > 0; --ii, increment(p)) + m_alloc.construct(p, *wrapper()); + } BOOST_CATCH(...) { + size_type constructed = ii < construct ? construct - ii : 0; + m_last = add(m_last, constructed); + m_size += constructed; + BOOST_RETHROW + } + BOOST_CATCH_END + } else { + pointer src = m_first; + pointer dest = sub(m_first, n); + pointer p = map_pointer(pos.m_it); + BOOST_TRY { + while (src != p) { + construct_or_replace(is_uninitialized(dest), dest, *src); + increment(src); + increment(dest); + } + for (size_type ii = 0; ii < n; ++ii, increment(dest)) + construct_or_replace(is_uninitialized(dest), dest, *wrapper()); + } BOOST_CATCH(...) { + for (src = sub(m_first, n); src != dest; increment(src)) + destroy_if_constructed(src); + BOOST_RETHROW + } + BOOST_CATCH_END + } + m_first = sub(m_first, n); + m_last = sub(m_last, n - construct); + m_size += construct; + } +}; + +// Non-member functions + +//! Compare two circular_buffers element-by-element to determine if they are equal. +/*! + \param lhs The circular_buffer to compare. + \param rhs The circular_buffer to compare. + \return lhs.\link circular_buffer::size() size()\endlink == rhs.\link circular_buffer::size() size()\endlink + && std::equal(lhs.\link circular_buffer::begin() + begin()\endlink, lhs.\link circular_buffer::end() end()\endlink, + rhs.\link circular_buffer::begin() begin()\endlink) + \throws Nothing. + \par Complexity + Linear (in the size of the circular_buffers). + \par Iterator Invalidation + Does not invalidate any iterators. +*/ +template +inline bool operator == (const circular_buffer& lhs, const circular_buffer& rhs) { + return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +/*! + \brief Compare two circular_buffers element-by-element to determine if the left one is lesser than the + right one. + \param lhs The circular_buffer to compare. + \param rhs The circular_buffer to compare. + \return + std::lexicographical_compare(lhs.\link circular_buffer::begin() begin()\endlink, + lhs.\link circular_buffer::end() end()\endlink, rhs.\link circular_buffer::begin() begin()\endlink, + rhs.\link circular_buffer::end() end()\endlink) + \throws Nothing. + \par Complexity + Linear (in the size of the circular_buffers). + \par Iterator Invalidation + Does not invalidate any iterators. +*/ +template +inline bool operator < (const circular_buffer& lhs, const circular_buffer& rhs) { + return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_MSVC) + +//! Compare two circular_buffers element-by-element to determine if they are non-equal. +/*! + \param lhs The circular_buffer to compare. + \param rhs The circular_buffer to compare. + \return !(lhs == rhs) + \throws Nothing. + \par Complexity + Linear (in the size of the circular_buffers). + \par Iterator Invalidation + Does not invalidate any iterators. + \sa operator==(const circular_buffer&, const circular_buffer&) +*/ +template +inline bool operator != (const circular_buffer& lhs, const circular_buffer& rhs) { + return !(lhs == rhs); +} + +/*! + \brief Compare two circular_buffers element-by-element to determine if the left one is greater than + the right one. + \param lhs The circular_buffer to compare. + \param rhs The circular_buffer to compare. + \return rhs \< lhs + \throws Nothing. + \par Complexity + Linear (in the size of the circular_buffers). + \par Iterator Invalidation + Does not invalidate any iterators. + \sa operator<(const circular_buffer&, const circular_buffer&) +*/ +template +inline bool operator > (const circular_buffer& lhs, const circular_buffer& rhs) { + return rhs < lhs; +} + +/*! + \brief Compare two circular_buffers element-by-element to determine if the left one is lesser or equal + to the right one. + \param lhs The circular_buffer to compare. + \param rhs The circular_buffer to compare. + \return !(rhs \< lhs) + \throws Nothing. + \par Complexity + Linear (in the size of the circular_buffers). + \par Iterator Invalidation + Does not invalidate any iterators. + \sa operator<(const circular_buffer&, const circular_buffer&) +*/ +template +inline bool operator <= (const circular_buffer& lhs, const circular_buffer& rhs) { + return !(rhs < lhs); +} + +/*! + \brief Compare two circular_buffers element-by-element to determine if the left one is greater or + equal to the right one. + \param lhs The circular_buffer to compare. + \param rhs The circular_buffer to compare. + \return !(lhs < rhs) + \throws Nothing. + \par Complexity + Linear (in the size of the circular_buffers). + \par Iterator Invalidation + Does not invalidate any iterators. + \sa operator<(const circular_buffer&, const circular_buffer&) +*/ +template +inline bool operator >= (const circular_buffer& lhs, const circular_buffer& rhs) { + return !(lhs < rhs); +} + +//! Swap the contents of two circular_buffers. +/*! + \post lhs contains elements of rhs and vice versa. + \param lhs The circular_buffer whose content will be swapped with rhs. + \param rhs The circular_buffer whose content will be swapped with lhs. + \throws Nothing. + \par Complexity + Constant (in the size of the circular_buffers). + \par Iterator Invalidation + Invalidates all iterators of both circular_buffers. (On the other hand the iterators still + point to the same elements but within another container. If you want to rely on this feature you have to + turn the Debug Support off otherwise an assertion will report an error if such + invalidated iterator is used.) + \sa \link circular_buffer::swap(circular_buffer&) swap(circular_buffer&)\endlink +*/ +template +inline void swap(circular_buffer& lhs, circular_buffer& rhs) { + lhs.swap(rhs); +} + +#endif // #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_MSVC) + +} // namespace boost + +#endif // #if !defined(BOOST_CIRCULAR_BUFFER_BASE_HPP) diff --git a/win32/include/boost/circular_buffer/debug.hpp b/win32/include/boost/circular_buffer/debug.hpp new file mode 100755 index 000000000..06ba45f1e --- /dev/null +++ b/win32/include/boost/circular_buffer/debug.hpp @@ -0,0 +1,227 @@ +// Debug support for the circular buffer library. + +// Copyright (c) 2003-2007 Jan Gaspar + +// Use, modification, and distribution is subject to 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_CIRCULAR_BUFFER_DEBUG_HPP) +#define BOOST_CIRCULAR_BUFFER_DEBUG_HPP + +#if defined(_MSC_VER) && _MSC_VER >= 1200 + #pragma once +#endif + +namespace boost { + +namespace cb_details { + +#if BOOST_CB_ENABLE_DEBUG + +// The value the uninitialized memory is filled with. +const int UNINITIALIZED = 0xcc; + +class debug_iterator_registry; + +/*! + \class debug_iterator_base + \brief Registers/unregisters iterators into the registry of valid iterators. + + This class is intended to be a base class of an iterator. +*/ +class debug_iterator_base { + +private: +// Members + + //! Iterator registry. + mutable const debug_iterator_registry* m_registry; + + //! Next iterator in the iterator chain. + mutable const debug_iterator_base* m_next; + +public: +// Construction/destruction + + //! Default constructor. + debug_iterator_base(); + + //! Constructor taking the iterator registry as a parameter. + debug_iterator_base(const debug_iterator_registry* registry); + + //! Copy constructor. + debug_iterator_base(const debug_iterator_base& rhs); + + //! Destructor. + ~debug_iterator_base(); + +// Methods + + //! Assign operator. + debug_iterator_base& operator = (const debug_iterator_base& rhs); + + //! Is the iterator valid? + bool is_valid(const debug_iterator_registry* registry) const; + + //! Invalidate the iterator. + /*! + \note The method is const in order to invalidate const iterators, too. + */ + void invalidate() const; + + //! Return the next iterator in the iterator chain. + const debug_iterator_base* next() const; + + //! Set the next iterator in the iterator chain. + /*! + \note The method is const in order to set a next iterator to a const iterator, too. + */ + void set_next(const debug_iterator_base* it) const; + +private: +// Helpers + + //! Register self as a valid iterator. + void register_self(); + + //! Unregister self from valid iterators. + void unregister_self(); +}; + +/*! + \class debug_iterator_registry + \brief Registry of valid iterators. + + This class is intended to be a base class of a container. +*/ +class debug_iterator_registry { + + //! Pointer to the chain of valid iterators. + mutable const debug_iterator_base* m_iterators; + +public: +// Methods + + //! Default constructor. + debug_iterator_registry() : m_iterators(0) {} + + //! Register an iterator into the list of valid iterators. + /*! + \note The method is const in order to register iterators into const containers, too. + */ + void register_iterator(const debug_iterator_base* it) const { + it->set_next(m_iterators); + m_iterators = it; + } + + //! Unregister an iterator from the list of valid iterators. + /*! + \note The method is const in order to unregister iterators from const containers, too. + */ + void unregister_iterator(const debug_iterator_base* it) const { + const debug_iterator_base* previous = 0; + for (const debug_iterator_base* p = m_iterators; p != it; previous = p, p = p->next()) {} + remove(it, previous); + } + + //! Invalidate every iterator pointing to the same element as the iterator passed as a parameter. + template + void invalidate_iterators(const Iterator& it) { + const debug_iterator_base* previous = 0; + for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) { + if (((Iterator*)p)->m_it == it.m_it) { + p->invalidate(); + remove(p, previous); + continue; + } + previous = p; + } + } + + //! Invalidate all iterators except an iterator poining to the same element as the iterator passed as a parameter. + template + void invalidate_iterators_except(const Iterator& it) { + const debug_iterator_base* previous = 0; + for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) { + if (((Iterator*)p)->m_it != it.m_it) { + p->invalidate(); + remove(p, previous); + continue; + } + previous = p; + } + } + + //! Invalidate all iterators. + void invalidate_all_iterators() { + for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) + p->invalidate(); + m_iterators = 0; + } + +private: +// Helpers + + //! Remove the current iterator from the iterator chain. + void remove(const debug_iterator_base* current, + const debug_iterator_base* previous) const { + if (previous == 0) + m_iterators = m_iterators->next(); + else + previous->set_next(current->next()); + } +}; + +// Implementation of the debug_iterator_base methods. + +inline debug_iterator_base::debug_iterator_base() : m_registry(0), m_next(0) {} + +inline debug_iterator_base::debug_iterator_base(const debug_iterator_registry* registry) +: m_registry(registry), m_next(0) { + register_self(); +} + +inline debug_iterator_base::debug_iterator_base(const debug_iterator_base& rhs) +: m_registry(rhs.m_registry), m_next(0) { + register_self(); +} + +inline debug_iterator_base::~debug_iterator_base() { unregister_self(); } + +inline debug_iterator_base& debug_iterator_base::operator = (const debug_iterator_base& rhs) { + if (m_registry == rhs.m_registry) + return *this; + unregister_self(); + m_registry = rhs.m_registry; + register_self(); + return *this; +} + +inline bool debug_iterator_base::is_valid(const debug_iterator_registry* registry) const { + return m_registry == registry; +} + +inline void debug_iterator_base::invalidate() const { m_registry = 0; } + +inline const debug_iterator_base* debug_iterator_base::next() const { return m_next; } + +inline void debug_iterator_base::set_next(const debug_iterator_base* it) const { m_next = it; } + +inline void debug_iterator_base::register_self() { + if (m_registry != 0) + m_registry->register_iterator(this); +} + +inline void debug_iterator_base::unregister_self() { + if (m_registry != 0) + m_registry->unregister_iterator(this); +} + +#endif // #if BOOST_CB_ENABLE_DEBUG + +} // namespace cb_details + +} // namespace boost + +#endif // #if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP) diff --git a/win32/include/boost/circular_buffer/details.hpp b/win32/include/boost/circular_buffer/details.hpp new file mode 100755 index 000000000..7e5272e74 --- /dev/null +++ b/win32/include/boost/circular_buffer/details.hpp @@ -0,0 +1,519 @@ +// Helper classes and functions for the circular buffer. + +// Copyright (c) 2003-2007 Jan Gaspar + +// Use, modification, and distribution is subject to 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_CIRCULAR_BUFFER_DETAILS_HPP) +#define BOOST_CIRCULAR_BUFFER_DETAILS_HPP + +#if defined(_MSC_VER) && _MSC_VER >= 1200 + #pragma once +#endif + +#include +#include +#include +#include + +namespace boost { + +namespace cb_details { + +template struct nonconst_traits; + +template +void uninitialized_fill_n_with_alloc( + ForwardIterator first, Diff n, const T& item, Alloc& alloc); + +template +ForwardIterator uninitialized_copy_with_alloc( + InputIterator first, InputIterator last, ForwardIterator dest, Alloc& alloc); + +/*! + \struct const_traits + \brief Defines the data types for a const iterator. +*/ +template +struct const_traits { + // Basic types + typedef typename Traits::value_type value_type; + typedef typename Traits::const_pointer pointer; + typedef typename Traits::const_reference reference; + typedef typename Traits::size_type size_type; + typedef typename Traits::difference_type difference_type; + + // Non-const traits + typedef nonconst_traits nonconst_self; +}; + +/*! + \struct nonconst_traits + \brief Defines the data types for a non-const iterator. +*/ +template +struct nonconst_traits { + // Basic types + typedef typename Traits::value_type value_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + typedef typename Traits::size_type size_type; + typedef typename Traits::difference_type difference_type; + + // Non-const traits + typedef nonconst_traits nonconst_self; +}; + +/*! + \struct helper_pointer + \brief Helper pointer used in the iterator. +*/ +template +struct helper_pointer { + bool m_end; + typename Traits::pointer m_it; +}; + +/*! + \struct iterator_wrapper + \brief Helper iterator dereference wrapper. +*/ +template +struct iterator_wrapper { + mutable Iterator m_it; + explicit iterator_wrapper(Iterator it) : m_it(it) {} + Iterator operator () () const { return m_it++; } +private: + iterator_wrapper& operator = (const iterator_wrapper&); // do not generate +}; + +/*! + \struct item_wrapper + \brief Helper item dereference wrapper. +*/ +template +struct item_wrapper { + Value m_item; + explicit item_wrapper(Value item) : m_item(item) {} + Pointer operator () () const { return &m_item; } +private: + item_wrapper& operator = (const item_wrapper&); // do not generate +}; + +/*! + \struct assign_n + \brief Helper functor for assigning n items. +*/ +template +struct assign_n { + typedef typename Alloc::size_type size_type; + size_type m_n; + Value m_item; + Alloc& m_alloc; + assign_n(size_type n, Value item, Alloc& alloc) : m_n(n), m_item(item), m_alloc(alloc) {} + template + void operator () (Pointer p) const { + uninitialized_fill_n_with_alloc(p, m_n, m_item, m_alloc); + } +private: + assign_n& operator = (const assign_n&); // do not generate +}; + +/*! + \struct assign_range + \brief Helper functor for assigning range of items. +*/ +template +struct assign_range { + const Iterator& m_first; + const Iterator& m_last; + Alloc& m_alloc; + assign_range(const Iterator& first, const Iterator& last, Alloc& alloc) + : m_first(first), m_last(last), m_alloc(alloc) {} + template + void operator () (Pointer p) const { + uninitialized_copy_with_alloc(m_first, m_last, p, m_alloc); + } +private: + assign_range& operator = (const assign_range&); // do not generate +}; + +/*! + \struct capacity_control + \brief Capacity controller of the space optimized circular buffer. +*/ +template +class capacity_control { + + //! The capacity of the space optimized circular buffer. + Size m_capacity; + + //! The lowest guaranteed capacity of the adapted circular buffer. + Size m_min_capacity; + +public: + + //! Constructor. + capacity_control(Size capacity, Size min_capacity = 0) + : m_capacity(capacity), m_min_capacity(min_capacity) { + BOOST_CB_ASSERT(capacity >= min_capacity); // check for capacity lower than min_capacity + } + + // Default copy constructor. + + // Default assign operator. + + //! Get the capacity of the space optimized circular buffer. + Size capacity() const { return m_capacity; } + + //! Get the minimal capacity of the space optimized circular buffer. + Size min_capacity() const { return m_min_capacity; } + + //! Size operator - returns the capacity of the space optimized circular buffer. + operator Size() const { return m_capacity; } +}; + +/*! + \class iterator + \brief Random access iterator for the circular buffer. + \param Buff The type of the underlying circular buffer. + \param Traits Basic iterator types. + \note This iterator is not circular. It was designed + for iterating from begin() to end() of the circular buffer. +*/ +template +class iterator : + public boost::iterator< + std::random_access_iterator_tag, + typename Traits::value_type, + typename Traits::difference_type, + typename Traits::pointer, + typename Traits::reference> +#if BOOST_CB_ENABLE_DEBUG + , public debug_iterator_base +#endif // #if BOOST_CB_ENABLE_DEBUG +{ +private: +// Helper types + + //! Base iterator. + typedef boost::iterator< + std::random_access_iterator_tag, + typename Traits::value_type, + typename Traits::difference_type, + typename Traits::pointer, + typename Traits::reference> base_iterator; + + //! Non-const iterator. + typedef iterator nonconst_self; + +public: +// Basic types + + //! The type of the elements stored in the circular buffer. + typedef typename base_iterator::value_type value_type; + + //! Pointer to the element. + typedef typename base_iterator::pointer pointer; + + //! Reference to the element. + typedef typename base_iterator::reference reference; + + //! Size type. + typedef typename Traits::size_type size_type; + + //! Difference type. + typedef typename base_iterator::difference_type difference_type; + +public: +// Member variables + + //! The circular buffer where the iterator points to. + const Buff* m_buff; + + //! An internal iterator. + pointer m_it; + +public: +// Construction & assignment + + // Default copy constructor. + + //! Default constructor. + iterator() : m_buff(0), m_it(0) {} + +#if BOOST_CB_ENABLE_DEBUG + + //! Copy constructor (used for converting from a non-const to a const iterator). + iterator(const nonconst_self& it) : debug_iterator_base(it), m_buff(it.m_buff), m_it(it.m_it) {} + + //! Internal constructor. + /*! + \note This constructor is not intended to be used directly by the user. + */ + iterator(const Buff* cb, const pointer p) : debug_iterator_base(cb), m_buff(cb), m_it(p) {} + +#else + + iterator(const nonconst_self& it) : m_buff(it.m_buff), m_it(it.m_it) {} + + iterator(const Buff* cb, const pointer p) : m_buff(cb), m_it(p) {} + +#endif // #if BOOST_CB_ENABLE_DEBUG + + //! Assign operator. + iterator& operator = (const iterator& it) { + if (this == &it) + return *this; +#if BOOST_CB_ENABLE_DEBUG + debug_iterator_base::operator =(it); +#endif // #if BOOST_CB_ENABLE_DEBUG + m_buff = it.m_buff; + m_it = it.m_it; + return *this; + } + +// Random access iterator methods + + //! Dereferencing operator. + reference operator * () const { + BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(m_it != 0); // check for iterator pointing to end() + return *m_it; + } + + //! Dereferencing operator. + pointer operator -> () const { return &(operator*()); } + + //! Difference operator. + difference_type operator - (const iterator& it) const { + BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator + helper_pointer lhs = create_helper_pointer(*this); + helper_pointer rhs = create_helper_pointer(it); + if (less(rhs, lhs) && lhs.m_it <= rhs.m_it) + return (lhs.m_it - rhs.m_it) + static_cast(m_buff->capacity()); + if (less(lhs, rhs) && lhs.m_it >= rhs.m_it) + return (lhs.m_it - rhs.m_it) - static_cast(m_buff->capacity()); + return lhs.m_it - rhs.m_it; + } + + //! Increment operator (prefix). + iterator& operator ++ () { + BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(m_it != 0); // check for iterator pointing to end() + m_buff->increment(m_it); + if (m_it == m_buff->m_last) + m_it = 0; + return *this; + } + + //! Increment operator (postfix). + iterator operator ++ (int) { + iterator tmp = *this; + ++*this; + return tmp; + } + + //! Decrement operator (prefix). + iterator& operator -- () { + BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(m_it != m_buff->m_first); // check for iterator pointing to begin() + if (m_it == 0) + m_it = m_buff->m_last; + m_buff->decrement(m_it); + return *this; + } + + //! Decrement operator (postfix). + iterator operator -- (int) { + iterator tmp = *this; + --*this; + return tmp; + } + + //! Iterator addition. + iterator& operator += (difference_type n) { + BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator + if (n > 0) { + BOOST_CB_ASSERT(m_buff->end() - *this >= n); // check for too large n + m_it = m_buff->add(m_it, n); + if (m_it == m_buff->m_last) + m_it = 0; + } else if (n < 0) { + *this -= -n; + } + return *this; + } + + //! Iterator addition. + iterator operator + (difference_type n) const { return iterator(*this) += n; } + + //! Iterator subtraction. + iterator& operator -= (difference_type n) { + BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator + if (n > 0) { + BOOST_CB_ASSERT(m_buff->begin() - *this <= -n); // check for too large n + m_it = m_buff->sub(m_it == 0 ? m_buff->m_last : m_it, n); + } else if (n < 0) { + *this += -n; + } + return *this; + } + + //! Iterator subtraction. + iterator operator - (difference_type n) const { return iterator(*this) -= n; } + + //! Element access operator. + reference operator [] (difference_type n) const { return *(*this + n); } + +// Equality & comparison + + //! Equality. + template + bool operator == (const iterator& it) const { + BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator + return m_it == it.m_it; + } + + //! Inequality. + template + bool operator != (const iterator& it) const { + BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator + return m_it != it.m_it; + } + + //! Less. + template + bool operator < (const iterator& it) const { + BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator + BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator + return less(create_helper_pointer(*this), create_helper_pointer(it)); + } + + //! Greater. + template + bool operator > (const iterator& it) const { return it < *this; } + + //! Less or equal. + template + bool operator <= (const iterator& it) const { return !(it < *this); } + + //! Greater or equal. + template + bool operator >= (const iterator& it) const { return !(*this < it); } + +private: +// Helpers + + //! Create helper pointer. + template + helper_pointer create_helper_pointer(const iterator& it) const { + helper_pointer helper; + helper.m_end = (it.m_it == 0); + helper.m_it = helper.m_end ? m_buff->m_last : it.m_it; + return helper; + } + + //! Less. + template + bool less(const InternalIterator0& lhs, const InternalIterator1& rhs) const { + difference_type ldiff = lhs.m_it - m_buff->m_first; + difference_type rdiff = rhs.m_it - m_buff->m_first; + if (ldiff < 0) { + if (rdiff < 0) + return lhs.m_it < rhs.m_it; + else if (rdiff == 0) + return rhs.m_end; + } else if (ldiff == 0) { + if (rdiff < 0) + return !lhs.m_end; + else if (rdiff == 0) + return !lhs.m_end && rhs.m_end; + else + return !lhs.m_end; + } else { // ldiff > 0 + if (rdiff < 0) + return true; + else if (rdiff == 0) + return rhs.m_end; + else + return lhs.m_it < rhs.m_it; + } + return false; + } +}; + +//! Iterator addition. +template +inline iterator +operator + (typename Traits::difference_type n, const iterator& it) { + return it + n; +} + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) + +//! Iterator category. +template +inline std::random_access_iterator_tag iterator_category(const iterator&) { + return std::random_access_iterator_tag(); +} + +//! The type of the elements stored in the circular buffer. +template +inline typename Traits::value_type* value_type(const iterator&) { return 0; } + +//! Distance type. +template +inline typename Traits::difference_type* distance_type(const iterator&) { return 0; } + +#endif // #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) + +/*! + \fn ForwardIterator uninitialized_copy_with_alloc(InputIterator first, InputIterator last, ForwardIterator dest, + Alloc& alloc) + \brief Equivalent of std::uninitialized_copy with allocator. +*/ +template +inline ForwardIterator uninitialized_copy_with_alloc(InputIterator first, InputIterator last, ForwardIterator dest, + Alloc& alloc) { + ForwardIterator next = dest; + BOOST_TRY { + for (; first != last; ++first, ++dest) + alloc.construct(dest, *first); + } BOOST_CATCH(...) { + for (; next != dest; ++next) + alloc.destroy(next); + BOOST_RETHROW + } + BOOST_CATCH_END + return dest; +} + +/*! + \fn void uninitialized_fill_n_with_alloc(ForwardIterator first, Diff n, const T& item, Alloc& alloc) + \brief Equivalent of std::uninitialized_fill_n with allocator. +*/ +template +inline void uninitialized_fill_n_with_alloc(ForwardIterator first, Diff n, const T& item, Alloc& alloc) { + ForwardIterator next = first; + BOOST_TRY { + for (; n > 0; ++first, --n) + alloc.construct(first, item); + } BOOST_CATCH(...) { + for (; next != first; ++next) + alloc.destroy(next); + BOOST_RETHROW + } + BOOST_CATCH_END +} + +} // namespace cb_details + +} // namespace boost + +#endif // #if !defined(BOOST_CIRCULAR_BUFFER_DETAILS_HPP) diff --git a/win32/include/boost/circular_buffer/space_optimized.hpp b/win32/include/boost/circular_buffer/space_optimized.hpp new file mode 100755 index 000000000..7aa2069c3 --- /dev/null +++ b/win32/include/boost/circular_buffer/space_optimized.hpp @@ -0,0 +1,1422 @@ +// Implementation of the circular buffer adaptor. + +// Copyright (c) 2003-2007 Jan Gaspar + +// Use, modification, and distribution is subject to 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_CIRCULAR_BUFFER_SPACE_OPTIMIZED_HPP) +#define BOOST_CIRCULAR_BUFFER_SPACE_OPTIMIZED_HPP + +#if defined(_MSC_VER) && _MSC_VER >= 1200 + #pragma once +#endif + +#include +#include + +namespace boost { + +/*! + \class circular_buffer_space_optimized + \brief Space optimized circular buffer container adaptor. + + For detailed documentation of the space_optimized_circular_buffer visit: + http://www.boost.org/libs/circular_buffer/doc/space_optimized.html +*/ +template +class circular_buffer_space_optimized : +/*! \cond */ +#if BOOST_CB_ENABLE_DEBUG +public +#endif +/*! \endcond */ +circular_buffer { +public: +// Typedefs + + typedef typename circular_buffer::value_type value_type; + typedef typename circular_buffer::pointer pointer; + typedef typename circular_buffer::const_pointer const_pointer; + typedef typename circular_buffer::reference reference; + typedef typename circular_buffer::const_reference const_reference; + typedef typename circular_buffer::size_type size_type; + typedef typename circular_buffer::difference_type difference_type; + typedef typename circular_buffer::allocator_type allocator_type; + typedef typename circular_buffer::const_iterator const_iterator; + typedef typename circular_buffer::iterator iterator; + typedef typename circular_buffer::const_reverse_iterator const_reverse_iterator; + typedef typename circular_buffer::reverse_iterator reverse_iterator; + typedef typename circular_buffer::array_range array_range; + typedef typename circular_buffer::const_array_range const_array_range; + typedef typename circular_buffer::param_value_type param_value_type; + typedef typename circular_buffer::return_value_type return_value_type; + + //! Capacity controller of the space optimized circular buffer. + /*! +

+class capacity_control {
+   size_type m_capacity;
+   size_type m_min_capacity;
+public:
+   capacity_control(size_type capacity, size_type min_capacity = 0) : m_capacity(capacity), m_min_capacity(min_capacity) {};
+   size_type %capacity() const { return m_capacity; }
+   size_type min_capacity() const { return m_min_capacity; }
+   operator size_type() const { return m_capacity; }
+};

+ \pre capacity >= min_capacity +

The capacity() represents the capacity of the circular_buffer_space_optimized and + the min_capacity() determines the minimal allocated size of its internal buffer.

+

The converting constructor of the capacity_control allows implicit conversion from + size_type-like types which ensures compatibility of creating an instance of the + circular_buffer_space_optimized with other STL containers. On the other hand the operator + %size_type() provides implicit conversion to the size_type which allows to treat the + capacity of the circular_buffer_space_optimized the same way as in the + circular_buffer.

+ */ + typedef cb_details::capacity_control capacity_type; + +// Inherited + + using circular_buffer::get_allocator; + using circular_buffer::begin; + using circular_buffer::end; + using circular_buffer::rbegin; + using circular_buffer::rend; + using circular_buffer::at; + using circular_buffer::front; + using circular_buffer::back; + using circular_buffer::array_one; + using circular_buffer::array_two; + using circular_buffer::linearize; + using circular_buffer::size; + using circular_buffer::max_size; + using circular_buffer::empty; + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + reference operator [] (size_type n) { return circular_buffer::operator[](n); } + return_value_type operator [] (size_type n) const { return circular_buffer::operator[](n); } +#else + using circular_buffer::operator[]; +#endif + +private: +// Member variables + + //! The capacity controller of the space optimized circular buffer. + capacity_type m_capacity_ctrl; + +public: +// Overridden + + //! Is the circular_buffer_space_optimized full? + /*! + \return true if the number of elements stored in the circular_buffer_space_optimized + equals the capacity of the circular_buffer_space_optimized; false otherwise. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer_space_optimized). + \sa empty() + */ + bool full() const { return m_capacity_ctrl == size(); } + + /*! \brief Get the maximum number of elements which can be inserted into the + circular_buffer_space_optimized without overwriting any of already stored elements. + \return capacity().%capacity() - size() + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer_space_optimized). + \sa capacity(), size(), max_size() + */ + size_type reserve() const { return m_capacity_ctrl - size(); } + + //! Get the capacity of the circular_buffer_space_optimized. + /*! + \return The capacity controller representing the maximum number of elements which can be stored in the + circular_buffer_space_optimized and the minimal allocated size of the internal buffer. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Does not invalidate any iterators. + \par Complexity + Constant (in the size of the circular_buffer_space_optimized). + \sa reserve(), size(), max_size(), + set_capacity(const capacity_type&) + */ + const capacity_type& capacity() const { return m_capacity_ctrl; } + +#if defined(BOOST_CB_TEST) + + // Return the current capacity of the adapted circular buffer. + /* + \note This method is not intended to be used directly by the user. + It is defined only for testing purposes. + */ + size_type internal_capacity() const { return circular_buffer::capacity(); } + +#endif // #if defined(BOOST_CB_TEST) + + /*! \brief Change the capacity (and the minimal guaranteed amount of allocated memory) of the + circular_buffer_space_optimized. + \post capacity() == capacity_ctrl \&\& size() \<= capacity_ctrl.capacity()

+ If the current number of elements stored in the circular_buffer_space_optimized is greater + than the desired new capacity then number of [size() - capacity_ctrl.capacity()] last + elements will be removed and the new size will be equal to capacity_ctrl.capacity().

+ If the current number of elements stored in the circular_buffer_space_optimized is lower + than the new capacity then the amount of allocated memory in the internal buffer may be accommodated as + necessary but it will never drop below capacity_ctrl.min_capacity(). + \param capacity_ctrl The new capacity controller. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Strong. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in min[size(), capacity_ctrl.%capacity()]). + \note To explicitly clear the extra allocated memory use the shrink-to-fit technique:

+ boost::%circular_buffer_space_optimized\ cb(1000);
+ ...
+ boost::%circular_buffer_space_optimized\(cb).swap(cb);


+ For more information about the shrink-to-fit technique in STL see + http://www.gotw.ca/gotw/054.htm. + \sa rset_capacity(const capacity_type&), + \link resize() resize(size_type, const_reference)\endlink + */ + void set_capacity(const capacity_type& capacity_ctrl) { + m_capacity_ctrl = capacity_ctrl; + if (capacity_ctrl < size()) { + iterator e = end(); + circular_buffer::erase(e - (size() - capacity_ctrl), e); + } + adjust_min_capacity(); + } + + //! Change the size of the circular_buffer_space_optimized. + /*! + \post size() == new_size \&\& capacity().%capacity() >= new_size

+ If the new size is greater than the current size, copies of item will be inserted at the + back of the of the circular_buffer_space_optimized in order to achieve the desired + size. In the case the resulting size exceeds the current capacity the capacity will be set to + new_size.

+ If the current number of elements stored in the circular_buffer_space_optimized is greater + than the desired new size then number of [size() - new_size] last elements will be + removed. (The capacity will remain unchanged.)

+ The amount of allocated memory in the internal buffer may be accommodated as necessary. + \param new_size The new size. + \param item The element the circular_buffer_space_optimized will be filled with in order to gain + the requested size. (See the Effect.) + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the new size of the circular_buffer_space_optimized). + \sa \link rresize() rresize(size_type, const_reference)\endlink, + set_capacity(const capacity_type&) + */ + void resize(size_type new_size, param_value_type item = value_type()) { + if (new_size > size()) { + if (new_size > m_capacity_ctrl) + m_capacity_ctrl = capacity_type(new_size, m_capacity_ctrl.min_capacity()); + insert(end(), new_size - size(), item); + } else { + iterator e = end(); + erase(e - (size() - new_size), e); + } + } + + /*! \brief Change the capacity (and the minimal guaranteed amount of allocated memory) of the + circular_buffer_space_optimized. + \post capacity() == capacity_ctrl \&\& size() \<= capacity_ctrl

+ If the current number of elements stored in the circular_buffer_space_optimized is greater + than the desired new capacity then number of [size() - capacity_ctrl.capacity()] + first elements will be removed and the new size will be equal to + capacity_ctrl.capacity().

+ If the current number of elements stored in the circular_buffer_space_optimized is lower + than the new capacity then the amount of allocated memory in the internal buffer may be accommodated as + necessary but it will never drop below capacity_ctrl.min_capacity(). + \param capacity_ctrl The new capacity controller. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Strong. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in min[size(), capacity_ctrl.%capacity()]). + \sa set_capacity(const capacity_type&), + \link rresize() rresize(size_type, const_reference)\endlink + */ + void rset_capacity(const capacity_type& capacity_ctrl) { + m_capacity_ctrl = capacity_ctrl; + if (capacity_ctrl < size()) { + iterator b = begin(); + circular_buffer::rerase(b, b + (size() - capacity_ctrl)); + } + adjust_min_capacity(); + } + + //! Change the size of the circular_buffer_space_optimized. + /*! + \post size() == new_size \&\& capacity().%capacity() >= new_size

+ If the new size is greater than the current size, copies of item will be inserted at the + front of the of the circular_buffer_space_optimized in order to achieve the desired + size. In the case the resulting size exceeds the current capacity the capacity will be set to + new_size.

+ If the current number of elements stored in the circular_buffer_space_optimized is greater + than the desired new size then number of [size() - new_size] first elements will be + removed. (The capacity will remain unchanged.)

+ The amount of allocated memory in the internal buffer may be accommodated as necessary. + \param new_size The new size. + \param item The element the circular_buffer_space_optimized will be filled with in order to gain + the requested size. (See the Effect.) + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the new size of the circular_buffer_space_optimized). + \sa \link resize() resize(size_type, const_reference)\endlink, + rset_capacity(const capacity_type&) + */ + void rresize(size_type new_size, param_value_type item = value_type()) { + if (new_size > size()) { + if (new_size > m_capacity_ctrl) + m_capacity_ctrl = capacity_type(new_size, m_capacity_ctrl.min_capacity()); + rinsert(begin(), new_size - size(), item); + } else { + rerase(begin(), end() - new_size); + } + } + + //! Create an empty space optimized circular buffer with a maximum capacity. + /*! + \post capacity().%capacity() == max_size() \&\& capacity().min_capacity() == 0 \&\& size() == 0 +

There is no memory allocated in the internal buffer. + \param alloc The allocator. + \throws Nothing. + \par Complexity + Constant. + */ + explicit circular_buffer_space_optimized(const allocator_type& alloc = allocator_type()) + : circular_buffer(0, alloc) + , m_capacity_ctrl(max_size()) {} + + //! Create an empty space optimized circular buffer with the specified capacity. + /*! + \post capacity() == capacity_ctrl \&\& size() == 0

+ The amount of allocated memory in the internal buffer is capacity_ctrl.min_capacity(). + \param capacity_ctrl The capacity controller representing the maximum number of elements which can be stored in + the circular_buffer_space_optimized and the minimal allocated size of the + internal buffer. + \param alloc The allocator. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \par Complexity + Constant. + */ + explicit circular_buffer_space_optimized(capacity_type capacity_ctrl, + const allocator_type& alloc = allocator_type()) + : circular_buffer(capacity_ctrl.min_capacity(), alloc) + , m_capacity_ctrl(capacity_ctrl) {} + + /*! \brief Create a full space optimized circular buffer with the specified capacity filled with + capacity_ctrl.%capacity() copies of item. + \post capacity() == capacity_ctrl \&\& full() \&\& (*this)[0] == item \&\& (*this)[1] == item \&\& ... + \&\& (*this) [capacity_ctrl.%capacity() - 1] == item

+ The amount of allocated memory in the internal buffer is capacity_ctrl.capacity(). + \param capacity_ctrl The capacity controller representing the maximum number of elements which can be stored in + the circular_buffer_space_optimized and the minimal allocated size of the + internal buffer. + \param item The element the created circular_buffer_space_optimized will be filled with. + \param alloc The allocator. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Complexity + Linear (in the capacity_ctrl.%capacity()). + */ + circular_buffer_space_optimized(capacity_type capacity_ctrl, param_value_type item, + const allocator_type& alloc = allocator_type()) + : circular_buffer(capacity_ctrl.capacity(), item, alloc) + , m_capacity_ctrl(capacity_ctrl) {} + + /*! \brief Create a space optimized circular buffer with the specified capacity filled with n copies + of item. + \pre capacity_ctrl.%capacity() >= n + \post capacity() == capacity_ctrl \&\& size() == n \&\& (*this)[0] == item \&\& (*this)[1] == item + \&\& ... \&\& (*this)[n - 1] == item

+ The amount of allocated memory in the internal buffer is + max[n, capacity_ctrl.min_capacity()]. + \param capacity_ctrl The capacity controller representing the maximum number of elements which can be stored in + the circular_buffer_space_optimized and the minimal allocated size of the + internal buffer. + \param n The number of elements the created circular_buffer_space_optimized will be filled with. + \param item The element the created circular_buffer_space_optimized will be filled with. + \param alloc The allocator. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Complexity + Linear (in the n). + */ + circular_buffer_space_optimized(capacity_type capacity_ctrl, size_type n, param_value_type item, + const allocator_type& alloc = allocator_type()) + : circular_buffer(init_capacity(capacity_ctrl, n), n, item, alloc) + , m_capacity_ctrl(capacity_ctrl) {} + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + + /*! \cond */ + circular_buffer_space_optimized(const circular_buffer_space_optimized& cb) + : circular_buffer(cb.begin(), cb.end()) + , m_capacity_ctrl(cb.m_capacity_ctrl) {} + + template + circular_buffer_space_optimized(InputIterator first, InputIterator last) + : circular_buffer(first, last) + , m_capacity_ctrl(circular_buffer::capacity()) {} + + template + circular_buffer_space_optimized(capacity_type capacity_ctrl, InputIterator first, InputIterator last) + : circular_buffer( + init_capacity(capacity_ctrl, first, last, is_integral()), + first, last) + , m_capacity_ctrl(capacity_ctrl) { + reduce_capacity( + is_same< BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY::type, std::input_iterator_tag >()); + } + /*! \endcond */ + +#else + + //! The copy constructor. + /*! + Creates a copy of the specified circular_buffer_space_optimized. + \post *this == cb

+ The amount of allocated memory in the internal buffer is cb.size(). + \param cb The circular_buffer_space_optimized to be copied. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Complexity + Linear (in the size of cb). + */ + circular_buffer_space_optimized(const circular_buffer_space_optimized& cb) + : circular_buffer(cb.begin(), cb.end(), cb.get_allocator()) + , m_capacity_ctrl(cb.m_capacity_ctrl) {} + + //! Create a full space optimized circular buffer filled with a copy of the range. + /*! + \pre Valid range [first, last).
+ first and last have to meet the requirements of + InputIterator. + \post capacity().%capacity() == std::distance(first, last) \&\& capacity().min_capacity() == 0 \&\& + full() \&\& (*this)[0]== *first \&\& (*this)[1] == *(first + 1) \&\& ... \&\& + (*this)[std::distance(first, last) - 1] == *(last - 1)

+ The amount of allocated memory in the internal buffer is std::distance(first, last). + \param first The beginning of the range to be copied. + \param last The end of the range to be copied. + \param alloc The allocator. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Complexity + Linear (in the std::distance(first, last)). + */ + template + circular_buffer_space_optimized(InputIterator first, InputIterator last, + const allocator_type& alloc = allocator_type()) + : circular_buffer(first, last, alloc) + , m_capacity_ctrl(circular_buffer::capacity()) {} + + /*! \brief Create a space optimized circular buffer with the specified capacity (and the minimal guaranteed amount + of allocated memory) filled with a copy of the range. + \pre Valid range [first, last).
+ first and last have to meet the requirements of + InputIterator. + \post capacity() == capacity_ctrl \&\& size() \<= std::distance(first, last) \&\& (*this)[0]== + *(last - capacity_ctrl.%capacity()) \&\& (*this)[1] == *(last - capacity_ctrl.%capacity() + 1) \&\& ... + \&\& (*this)[capacity_ctrl.%capacity() - 1] == *(last - 1)

+ If the number of items to be copied from the range [first, last) is greater than the + specified capacity_ctrl.%capacity() then only elements from the range + [last - capacity_ctrl.%capacity(), last) will be copied.

+ The amount of allocated memory in the internal buffer is max[capacity_ctrl.min_capacity(), + min[capacity_ctrl.%capacity(), std::distance(first, last)]]. + \param capacity_ctrl The capacity controller representing the maximum number of elements which can be stored in + the circular_buffer_space_optimized and the minimal allocated size of the + internal buffer. + \param first The beginning of the range to be copied. + \param last The end of the range to be copied. + \param alloc The allocator. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Complexity + Linear (in std::distance(first, last); in + min[capacity_ctrl.%capacity(), std::distance(first, last)] if the InputIterator + is a RandomAccessIterator). + */ + template + circular_buffer_space_optimized(capacity_type capacity_ctrl, InputIterator first, InputIterator last, + const allocator_type& alloc = allocator_type()) + : circular_buffer( + init_capacity(capacity_ctrl, first, last, is_integral()), + first, last, alloc) + , m_capacity_ctrl(capacity_ctrl) { + reduce_capacity( + is_same< BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY::type, std::input_iterator_tag >()); + } + +#endif // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + +#if defined(BOOST_CB_NEVER_DEFINED) +// This section will never be compiled - the default destructor will be generated instead. +// Declared only for documentation purpose. + + //! The destructor. + /*! + Destroys the circular_buffer_space_optimized. + \throws Nothing. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (including + iterators equal to end()). + \par Complexity + Linear (in the size of the circular_buffer_space_optimized). + \sa clear() + */ + ~circular_buffer_space_optimized(); + +#endif // #if defined(BOOST_CB_NEVER_DEFINED) + + //! The assign operator. + /*! + Makes this circular_buffer_space_optimized to become a copy of the specified + circular_buffer_space_optimized. + \post *this == cb

+ The amount of allocated memory in the internal buffer is cb.size(). + \param cb The circular_buffer_space_optimized to be copied. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Strong. + \par Iterator Invalidation + Invalidates all iterators pointing to this circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the size of cb). + \sa \link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink, + \link assign(capacity_type, size_type, param_value_type) + assign(capacity_type, size_type, const_reference)\endlink, + assign(InputIterator, InputIterator), + assign(capacity_type, InputIterator, InputIterator) + */ + circular_buffer_space_optimized& operator = (const circular_buffer_space_optimized& cb) { + if (this == &cb) + return *this; + circular_buffer::assign(cb.begin(), cb.end()); + m_capacity_ctrl = cb.m_capacity_ctrl; + return *this; + } + + //! Assign n items into the space optimized circular buffer. + /*! + The content of the circular_buffer_space_optimized will be removed and replaced with + n copies of the item. + \post capacity().%capacity() == n \&\& capacity().min_capacity() == 0 \&\& size() == n \&\& (*this)[0] == + item \&\& (*this)[1] == item \&\& ... \&\& (*this) [n - 1] == item

+ The amount of allocated memory in the internal buffer is n. + \param n The number of elements the circular_buffer_space_optimized will be filled with. + \param item The element the circular_buffer_space_optimized will be filled with. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the n). + \sa operator=, \link assign(capacity_type, size_type, param_value_type) + assign(capacity_type, size_type, const_reference)\endlink, + assign(InputIterator, InputIterator), + assign(capacity_type, InputIterator, InputIterator) + */ + void assign(size_type n, param_value_type item) { + circular_buffer::assign(n, item); + m_capacity_ctrl = capacity_type(n); + } + + //! Assign n items into the space optimized circular buffer specifying the capacity. + /*! + The capacity of the circular_buffer_space_optimized will be set to the specified value and the + content of the circular_buffer_space_optimized will be removed and replaced with n + copies of the item. + \pre capacity_ctrl.%capacity() >= n + \post capacity() == capacity_ctrl \&\& size() == n \&\& (*this)[0] == item \&\& (*this)[1] == item + \&\& ... \&\& (*this) [n - 1] == item

+ The amount of allocated memory will be max[n, capacity_ctrl.min_capacity()]. + \param capacity_ctrl The new capacity controller. + \param n The number of elements the circular_buffer_space_optimized will be filled with. + \param item The element the circular_buffer_space_optimized will be filled with. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the n). + \sa operator=, \link assign(size_type, param_value_type) + assign(size_type, const_reference)\endlink, assign(InputIterator, InputIterator), + assign(capacity_type, InputIterator, InputIterator) + */ + void assign(capacity_type capacity_ctrl, size_type n, param_value_type item) { + BOOST_CB_ASSERT(capacity_ctrl.capacity() >= n); // check for new capacity lower than n + circular_buffer::assign((std::max)(capacity_ctrl.min_capacity(), n), n, item); + m_capacity_ctrl = capacity_ctrl; + } + + //! Assign a copy of the range into the space optimized circular buffer. + /*! + The content of the circular_buffer_space_optimized will be removed and replaced with copies of + elements from the specified range. + \pre Valid range [first, last).
+ first and last have to meet the requirements of + InputIterator. + \post capacity().%capacity() == std::distance(first, last) \&\& capacity().min_capacity() == 0 \&\& + size() == std::distance(first, last) \&\& (*this)[0]== *first \&\& (*this)[1] == *(first + 1) \&\& ... + \&\& (*this)[std::distance(first, last) - 1] == *(last - 1)

+ The amount of allocated memory in the internal buffer is std::distance(first, last). + \param first The beginning of the range to be copied. + \param last The end of the range to be copied. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the std::distance(first, last)). + \sa operator=, \link assign(size_type, param_value_type) + assign(size_type, const_reference)\endlink, + \link assign(capacity_type, size_type, param_value_type) + assign(capacity_type, size_type, const_reference)\endlink, + assign(capacity_type, InputIterator, InputIterator) + */ + template + void assign(InputIterator first, InputIterator last) { + circular_buffer::assign(first, last); + m_capacity_ctrl = capacity_type(circular_buffer::capacity()); + } + + //! Assign a copy of the range into the space optimized circular buffer specifying the capacity. + /*! + The capacity of the circular_buffer_space_optimized will be set to the specified value and the + content of the circular_buffer_space_optimized will be removed and replaced with copies of + elements from the specified range. + \pre Valid range [first, last).
+ first and last have to meet the requirements of + InputIterator. + \post capacity() == capacity_ctrl \&\& size() \<= std::distance(first, last) \&\& + (*this)[0]== *(last - capacity) \&\& (*this)[1] == *(last - capacity + 1) \&\& ... \&\& + (*this)[capacity - 1] == *(last - 1)

+ If the number of items to be copied from the range [first, last) is greater than the + specified capacity then only elements from the range [last - capacity, last) + will be copied.

The amount of allocated memory in the internal buffer is + max[std::distance(first, last), capacity_ctrl.min_capacity()]. + \param capacity_ctrl The new capacity controller. + \param first The beginning of the range to be copied. + \param last The end of the range to be copied. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in std::distance(first, last); in + min[capacity_ctrl.%capacity(), std::distance(first, last)] if the InputIterator + is a RandomAccessIterator). + \sa operator=, \link assign(size_type, param_value_type) + assign(size_type, const_reference)\endlink, + \link assign(capacity_type, size_type, param_value_type) + assign(capacity_type, size_type, const_reference)\endlink, + assign(InputIterator, InputIterator) + */ + template + void assign(capacity_type capacity_ctrl, InputIterator first, InputIterator last) { + m_capacity_ctrl = capacity_ctrl; + circular_buffer::assign(capacity_ctrl, first, last); + } + + //! Swap the contents of two space optimized circular buffers. + /*! + \post this contains elements of cb and vice versa; the capacity and the amount of + allocated memory in the internal buffer of this equal to the capacity and the amount of + allocated memory of cb and vice versa. + \param cb The circular_buffer_space_optimized whose content will be swapped. + \throws Nothing. + \par Exception Safety + No-throw. + \par Iterator Invalidation + Invalidates all iterators of both circular_buffer_space_optimized containers. (On the other + hand the iterators still point to the same elements but within another container. If you want to rely on + this feature you have to turn the Debug Support off otherwise an + assertion will report an error if such invalidated iterator is used.) + \par Complexity + Constant (in the size of the circular_buffer_space_optimized). + \sa \link swap(circular_buffer&, circular_buffer&) + swap(circular_buffer_space_optimized&, circular_buffer_space_optimized&)\endlink + */ + void swap(circular_buffer_space_optimized& cb) { + std::swap(m_capacity_ctrl, cb.m_capacity_ctrl); + circular_buffer::swap(cb); + } + + //! Insert a new element at the end of the space optimized circular buffer. + /*! + \post if capacity().%capacity() > 0 then back() == item
+ If the circular_buffer_space_optimized is full, the first element will be removed. If the + capacity is 0, nothing will be inserted.

+ The amount of allocated memory in the internal buffer may be predictively increased. + \param item The element to be inserted. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the size of the circular_buffer_space_optimized). + \sa \link push_front() push_front(const_reference)\endlink, pop_back(), + pop_front() + */ + void push_back(param_value_type item = value_type()) { + check_low_capacity(); + circular_buffer::push_back(item); + } + + //! Insert a new element at the beginning of the space optimized circular buffer. + /*! + \post if capacity().%capacity() > 0 then front() == item
+ If the circular_buffer_space_optimized is full, the last element will be removed. If the + capacity is 0, nothing will be inserted.

+ The amount of allocated memory in the internal buffer may be predictively increased. + \param item The element to be inserted. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the size of the circular_buffer_space_optimized). + \sa \link push_back() push_back(const_reference)\endlink, pop_back(), + pop_front() + */ + void push_front(param_value_type item = value_type()) { + check_low_capacity(); + circular_buffer::push_front(item); + } + + //! Remove the last element from the space optimized circular buffer. + /*! + \pre !empty() + \post The last element is removed from the circular_buffer_space_optimized.

+ The amount of allocated memory in the internal buffer may be predictively decreased. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the size of the circular_buffer_space_optimized). + \sa pop_front(), \link push_back() push_back(const_reference)\endlink, + \link push_front() push_front(const_reference)\endlink + */ + void pop_back() { + circular_buffer::pop_back(); + check_high_capacity(); + } + + //! Remove the first element from the space optimized circular buffer. + /*! + \pre !empty() + \post The first element is removed from the circular_buffer_space_optimized.

+ The amount of allocated memory in the internal buffer may be predictively decreased. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the size of the circular_buffer_space_optimized). + \sa pop_back(), \link push_back() push_back(const_reference)\endlink, + \link push_front() push_front(const_reference)\endlink + */ + void pop_front() { + circular_buffer::pop_front(); + check_high_capacity(); + } + + //! Insert an element at the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its + end. + \post The item will be inserted at the position pos.
+ If the circular_buffer_space_optimized is full, the first element will be overwritten. If + the circular_buffer_space_optimized is full and the pos points to + begin(), then the item will not be inserted. If the capacity is 0, + nothing will be inserted.

+ The amount of allocated memory in the internal buffer may be predictively increased. + \param pos An iterator specifying the position where the item will be inserted. + \param item The element to be inserted. + \return Iterator to the inserted element or begin() if the item is not inserted. (See + the Effect.) + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the size of the circular_buffer_space_optimized). + \sa \link insert(iterator, size_type, param_value_type) + insert(iterator, size_type, value_type)\endlink, + insert(iterator, InputIterator, InputIterator), + \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, + \link rinsert(iterator, size_type, param_value_type) + rinsert(iterator, size_type, value_type)\endlink, + rinsert(iterator, InputIterator, InputIterator) + */ + iterator insert(iterator pos, param_value_type item = value_type()) { + size_type index = pos - begin(); + check_low_capacity(); + return circular_buffer::insert(begin() + index, item); + } + + //! Insert n copies of the item at the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its + end. + \post The number of min[n, (pos - begin()) + reserve()] elements will be inserted at the position + pos.
The number of min[pos - begin(), max[0, n - reserve()]] elements will + be overwritten at the beginning of the circular_buffer_space_optimized.
(See + Example for the explanation.)

+ The amount of allocated memory in the internal buffer may be predictively increased. + \param pos An iterator specifying the position where the items will be inserted. + \param n The number of items the to be inserted. + \param item The element whose copies will be inserted. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in min[capacity().%capacity(), size() + n]). + \par Example + Consider a circular_buffer_space_optimized with the capacity of 6 and the size of 4. Its + internal buffer may look like the one below.

+ |1|2|3|4| | |
+ p ---^

After inserting 5 elements at the position p:

+ insert(p, (size_t)5, 0);

actually only 4 elements get inserted and elements + 1 and 2 are overwritten. This is due to the fact the insert operation preserves + the capacity. After insertion the internal buffer looks like this:

|0|0|0|0|3|4|
+
For comparison if the capacity would not be preserved the internal buffer would then result in + |1|2|0|0|0|0|0|3|4|. + \sa \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, + insert(iterator, InputIterator, InputIterator), + \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, + \link rinsert(iterator, size_type, param_value_type) + rinsert(iterator, size_type, value_type)\endlink, + rinsert(iterator, InputIterator, InputIterator) + */ + void insert(iterator pos, size_type n, param_value_type item) { + size_type index = pos - begin(); + check_low_capacity(n); + circular_buffer::insert(begin() + index, n, item); + } + + //! Insert the range [first, last) at the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its + end.
Valid range [first, last) where first and last meet the + requirements of an InputIterator. + \post Elements from the range + [first + max[0, distance(first, last) - (pos - begin()) - reserve()], last) will be + inserted at the position pos.
The number of min[pos - begin(), max[0, + distance(first, last) - reserve()]] elements will be overwritten at the beginning of the + circular_buffer_space_optimized.
(See Example for the explanation.)

+ The amount of allocated memory in the internal buffer may be predictively increased. + \param pos An iterator specifying the position where the range will be inserted. + \param first The beginning of the range to be inserted. + \param last The end of the range to be inserted. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in [size() + std::distance(first, last)]; in + min[capacity().%capacity(), size() + std::distance(first, last)] if the + InputIterator is a + RandomAccessIterator). + \par Example + Consider a circular_buffer_space_optimized with the capacity of 6 and the size of 4. Its + internal buffer may look like the one below.

+ |1|2|3|4| | |
+ p ---^

After inserting a range of elements at the position p:

+ int array[] = { 5, 6, 7, 8, 9 };
insert(p, array, array + 5);

+ actually only elements 6, 7, 8 and 9 from the + specified range get inserted and elements 1 and 2 are overwritten. This is due + to the fact the insert operation preserves the capacity. After insertion the internal buffer looks like + this:

|6|7|8|9|3|4|

For comparison if the capacity would not be preserved the + internal buffer would then result in |1|2|5|6|7|8|9|3|4|. + \sa \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, + \link insert(iterator, size_type, param_value_type) + insert(iterator, size_type, value_type)\endlink, \link rinsert(iterator, param_value_type) + rinsert(iterator, value_type)\endlink, \link rinsert(iterator, size_type, param_value_type) + rinsert(iterator, size_type, value_type)\endlink, + rinsert(iterator, InputIterator, InputIterator) + */ + template + void insert(iterator pos, InputIterator first, InputIterator last) { + insert(pos, first, last, is_integral()); + } + + //! Insert an element before the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its + end. + \post The item will be inserted before the position pos.
+ If the circular_buffer_space_optimized is full, the last element will be overwritten. If the + circular_buffer_space_optimized is full and the pos points to + end(), then the item will not be inserted. If the capacity is 0, + nothing will be inserted.

+ The amount of allocated memory in the internal buffer may be predictively increased. + \param pos An iterator specifying the position before which the item will be inserted. + \param item The element to be inserted. + \return Iterator to the inserted element or end() if the item is not inserted. (See + the Effect.) + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the size of the circular_buffer_space_optimized). + \sa \link rinsert(iterator, size_type, param_value_type) + rinsert(iterator, size_type, value_type)\endlink, + rinsert(iterator, InputIterator, InputIterator), + \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, + \link insert(iterator, size_type, param_value_type) + insert(iterator, size_type, value_type)\endlink, + insert(iterator, InputIterator, InputIterator) + */ + iterator rinsert(iterator pos, param_value_type item = value_type()) { + size_type index = pos - begin(); + check_low_capacity(); + return circular_buffer::rinsert(begin() + index, item); + } + + //! Insert n copies of the item before the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its + end. + \post The number of min[n, (end() - pos) + reserve()] elements will be inserted before the + position pos.
The number of min[end() - pos, max[0, n - reserve()]] elements + will be overwritten at the end of the circular_buffer_space_optimized.
(See + Example for the explanation.)

+ The amount of allocated memory in the internal buffer may be predictively increased. + \param pos An iterator specifying the position where the items will be inserted. + \param n The number of items the to be inserted. + \param item The element whose copies will be inserted. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in min[capacity().%capacity(), size() + n]). + \par Example + Consider a circular_buffer_space_optimized with the capacity of 6 and the size of 4. Its + internal buffer may look like the one below.

+ |1|2|3|4| | |
+ p ---^

After inserting 5 elements before the position p:

+ rinsert(p, (size_t)5, 0);

actually only 4 elements get inserted and elements + 3 and 4 are overwritten. This is due to the fact the rinsert operation preserves + the capacity. After insertion the internal buffer looks like this:

|1|2|0|0|0|0|
+
For comparison if the capacity would not be preserved the internal buffer would then result in + |1|2|0|0|0|0|0|3|4|. + \sa \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, + rinsert(iterator, InputIterator, InputIterator), + \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, + \link insert(iterator, size_type, param_value_type) + insert(iterator, size_type, value_type)\endlink, + insert(iterator, InputIterator, InputIterator) + */ + void rinsert(iterator pos, size_type n, param_value_type item) { + size_type index = pos - begin(); + check_low_capacity(n); + circular_buffer::rinsert(begin() + index, n, item); + } + + //! Insert the range [first, last) before the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its + end.
+ Valid range [first, last) where first and last meet the + requirements of an InputIterator. + \post Elements from the range + [first, last - max[0, distance(first, last) - (end() - pos) - reserve()]) will be inserted + before the position pos.
The number of min[end() - pos, max[0, + distance(first, last) - reserve()]] elements will be overwritten at the end of the + circular_buffer.
(See Example for the explanation.)

+ The amount of allocated memory in the internal buffer may be predictively increased. + \param pos An iterator specifying the position where the range will be inserted. + \param first The beginning of the range to be inserted. + \param last The end of the range to be inserted. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::T(const T&) throws. + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in [size() + std::distance(first, last)]; in + min[capacity().%capacity(), size() + std::distance(first, last)] if the + InputIterator is a + RandomAccessIterator). + \par Example + Consider a circular_buffer_space_optimized with the capacity of 6 and the size of 4. Its + internal buffer may look like the one below.

+ |1|2|3|4| | |
+ p ---^

After inserting a range of elements before the position p:

+ int array[] = { 5, 6, 7, 8, 9 };
insert(p, array, array + 5);

+ actually only elements 5, 6, 7 and 8 from the + specified range get inserted and elements 3 and 4 are overwritten. This is due + to the fact the rinsert operation preserves the capacity. After insertion the internal buffer looks like + this:

|1|2|5|6|7|8|

For comparison if the capacity would not be preserved the + internal buffer would then result in |1|2|5|6|7|8|9|3|4|. + \sa \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, + \link rinsert(iterator, size_type, param_value_type) + rinsert(iterator, size_type, value_type)\endlink, \link insert(iterator, param_value_type) + insert(iterator, value_type)\endlink, \link insert(iterator, size_type, param_value_type) + insert(iterator, size_type, value_type)\endlink, + insert(iterator, InputIterator, InputIterator) + */ + template + void rinsert(iterator pos, InputIterator first, InputIterator last) { + rinsert(pos, first, last, is_integral()); + } + + //! Remove an element at the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer_space_optimized (but not + an end()). + \post The element at the position pos is removed.

+ The amount of allocated memory in the internal buffer may be predictively decreased. + \param pos An iterator pointing at the element to be removed. + \return Iterator to the first element remaining beyond the removed element or end() if no such + element exists. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the size of the circular_buffer_space_optimized). + \sa erase(iterator, iterator), rerase(iterator), + rerase(iterator, iterator), clear() + */ + iterator erase(iterator pos) { + iterator it = circular_buffer::erase(pos); + size_type index = it - begin(); + check_high_capacity(); + return begin() + index; + } + + //! Erase the range [first, last). + /*! + \pre Valid range [first, last). + \post The elements from the range [first, last) are removed. (If first == last + nothing is removed.)

+ The amount of allocated memory in the internal buffer may be predictively decreased. + \param first The beginning of the range to be removed. + \param last The end of the range to be removed. + \return Iterator to the first element remaining beyond the removed elements or end() if no such + element exists. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the size of the circular_buffer_space_optimized). + \sa erase(iterator), rerase(iterator), rerase(iterator, iterator), + clear() + */ + iterator erase(iterator first, iterator last) { + iterator it = circular_buffer::erase(first, last); + size_type index = it - begin(); + check_high_capacity(); + return begin() + index; + } + + //! Remove an element at the specified position. + /*! + \pre pos is a valid iterator pointing to the circular_buffer_space_optimized (but not + an end()).

+ The amount of allocated memory in the internal buffer may be predictively decreased. + \post The element at the position pos is removed. + \param pos An iterator pointing at the element to be removed. + \return Iterator to the first element remaining in front of the removed element or begin() if no + such element exists. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the size of the circular_buffer_space_optimized). + \note Basically there is no difference between erase(iterator) and this method. It is implemented + only for consistency with the base circular_buffer. + \sa erase(iterator), erase(iterator, iterator), + rerase(iterator, iterator), clear() + */ + iterator rerase(iterator pos) { + iterator it = circular_buffer::rerase(pos); + size_type index = it - begin(); + check_high_capacity(); + return begin() + index; + } + + //! Erase the range [first, last). + /*! + \pre Valid range [first, last). + \post The elements from the range [first, last) are removed. (If first == last + nothing is removed.)

+ The amount of allocated memory in the internal buffer may be predictively decreased. + \param first The beginning of the range to be removed. + \param last The end of the range to be removed. + \return Iterator to the first element remaining in front of the removed elements or begin() if no + such element exists. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \throws Whatever T::operator = (const T&) throws. + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the size of the circular_buffer_space_optimized). + \note Basically there is no difference between erase(iterator, iterator) and this method. It is + implemented only for consistency with the base + circular_buffer. + \sa erase(iterator), erase(iterator, iterator), rerase(iterator), + clear() + */ + iterator rerase(iterator first, iterator last) { + iterator it = circular_buffer::rerase(first, last); + size_type index = it - begin(); + check_high_capacity(); + return begin() + index; + } + + //! Remove all stored elements from the space optimized circular buffer. + /*! + \post size() == 0

+ The amount of allocated memory in the internal buffer may be predictively decreased. + \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is + used). + \par Exception Safety + Basic. + \par Iterator Invalidation + Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators + equal to end()). + \par Complexity + Linear (in the size of the circular_buffer_space_optimized). + \sa ~circular_buffer_space_optimized(), erase(iterator), + erase(iterator, iterator), rerase(iterator), + rerase(iterator, iterator) + */ + void clear() { erase(begin(), end()); } + +private: +// Helper methods + + //! Adjust the amount of allocated memory. + void adjust_min_capacity() { + if (m_capacity_ctrl.min_capacity() > circular_buffer::capacity()) + circular_buffer::set_capacity(m_capacity_ctrl.min_capacity()); + else + check_high_capacity(); + } + + //! Ensure the reserve for possible growth up. + size_type ensure_reserve(size_type new_capacity, size_type size) const { + if (size + new_capacity / 5 >= new_capacity) + new_capacity *= 2; // ensure at least 20% reserve + if (new_capacity > m_capacity_ctrl) + return m_capacity_ctrl; + return new_capacity; + } + + //! Check for low capacity. + /* + \post If the capacity is low it will be increased. + */ + void check_low_capacity(size_type n = 1) { + size_type new_size = size() + n; + size_type new_capacity = circular_buffer::capacity(); + if (new_size > new_capacity) { + if (new_capacity == 0) + new_capacity = 1; + for (; new_size > new_capacity; new_capacity *= 2) {} + circular_buffer::set_capacity( + ensure_reserve(new_capacity, new_size)); + } +#if BOOST_CB_ENABLE_DEBUG +# if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(70190006)) + this->invalidate_iterators_except(end()); +# else + invalidate_iterators_except(end()); +# endif +#endif + } + + //! Check for high capacity. + /* + \post If the capacity is high it will be decreased. + */ + void check_high_capacity() { + size_type new_capacity = circular_buffer::capacity(); + while (new_capacity / 3 >= size()) { // (new_capacity / 3) -> avoid oscillations + new_capacity /= 2; + if (new_capacity <= m_capacity_ctrl.min_capacity()) { + new_capacity = m_capacity_ctrl.min_capacity(); + break; + } + } + circular_buffer::set_capacity( + ensure_reserve(new_capacity, size())); +#if BOOST_CB_ENABLE_DEBUG +# if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(70190006)) + this->invalidate_iterators_except(end()); +# else + invalidate_iterators_except(end()); +# endif +#endif + } + + //! Specialized method for reducing the capacity. + void reduce_capacity(const true_type&) { + circular_buffer::set_capacity((std::max)(m_capacity_ctrl.min_capacity(), size())); + } + + //! Specialized method for reducing the capacity. + void reduce_capacity(const false_type&) {} + + //! Determine the initial capacity. + static size_type init_capacity(const capacity_type& capacity_ctrl, size_type n) { + BOOST_CB_ASSERT(capacity_ctrl.capacity() >= n); // check for capacity lower than n + return (std::max)(capacity_ctrl.min_capacity(), n); + } + + //! Specialized method for determining the initial capacity. + template + static size_type init_capacity(const capacity_type& capacity_ctrl, IntegralType n, IntegralType item, + const true_type&) { + return init_capacity(capacity_ctrl, static_cast(n)); + } + + //! Specialized method for determining the initial capacity. + template + static size_type init_capacity(const capacity_type& capacity_ctrl, Iterator first, Iterator last, + const false_type&) { + BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581)) + return init_capacity(capacity_ctrl, first, last, BOOST_ITERATOR_CATEGORY::type()); +#else + return init_capacity( + capacity_ctrl, first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY::type()); +#endif + } + + //! Specialized method for determining the initial capacity. + template + static size_type init_capacity(const capacity_type& capacity_ctrl, InputIterator first, InputIterator last, + const std::input_iterator_tag&) { + return capacity_ctrl.capacity(); + } + + //! Specialized method for determining the initial capacity. + template + static size_type init_capacity(const capacity_type& capacity_ctrl, ForwardIterator first, ForwardIterator last, + const std::forward_iterator_tag&) { + BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range + return (std::max)(capacity_ctrl.min_capacity(), + (std::min)(capacity_ctrl.capacity(), static_cast(std::distance(first, last)))); + } + + //! Specialized insert method. + template + void insert(const iterator& pos, IntegralType n, IntegralType item, const true_type&) { + insert(pos, static_cast(n), static_cast(item)); + } + + //! Specialized insert method. + template + void insert(const iterator& pos, Iterator first, Iterator last, const false_type&) { + size_type index = pos - begin(); + check_low_capacity(std::distance(first, last)); + circular_buffer::insert(begin() + index, first, last); + } + + //! Specialized rinsert method. + template + void rinsert(const iterator& pos, IntegralType n, IntegralType item, const true_type&) { + rinsert(pos, static_cast(n), static_cast(item)); + } + + //! Specialized rinsert method. + template + void rinsert(const iterator& pos, Iterator first, Iterator last, const false_type&) { + size_type index = pos - begin(); + check_low_capacity(std::distance(first, last)); + circular_buffer::rinsert(begin() + index, first, last); + } +}; + +// Non-member functions + +//! Test two space optimized circular buffers for equality. +template +inline bool operator == (const circular_buffer_space_optimized& lhs, + const circular_buffer_space_optimized& rhs) { + return lhs.size() == rhs.size() && + std::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +//! Lexicographical comparison. +template +inline bool operator < (const circular_buffer_space_optimized& lhs, + const circular_buffer_space_optimized& rhs) { + return std::lexicographical_compare( + lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) + +//! Test two space optimized circular buffers for non-equality. +template +inline bool operator != (const circular_buffer_space_optimized& lhs, + const circular_buffer_space_optimized& rhs) { + return !(lhs == rhs); +} + +//! Lexicographical comparison. +template +inline bool operator > (const circular_buffer_space_optimized& lhs, + const circular_buffer_space_optimized& rhs) { + return rhs < lhs; +} + +//! Lexicographical comparison. +template +inline bool operator <= (const circular_buffer_space_optimized& lhs, + const circular_buffer_space_optimized& rhs) { + return !(rhs < lhs); +} + +//! Lexicographical comparison. +template +inline bool operator >= (const circular_buffer_space_optimized& lhs, + const circular_buffer_space_optimized& rhs) { + return !(lhs < rhs); +} + +//! Swap the contents of two space optimized circular buffers. +template +inline void swap(circular_buffer_space_optimized& lhs, + circular_buffer_space_optimized& rhs) { + lhs.swap(rhs); +} + +#endif // #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) + +} // namespace boost + +#endif // #if !defined(BOOST_CIRCULAR_BUFFER_SPACE_OPTIMIZED_HPP) diff --git a/win32/include/boost/circular_buffer_fwd.hpp b/win32/include/boost/circular_buffer_fwd.hpp new file mode 100755 index 000000000..2b87bfd91 --- /dev/null +++ b/win32/include/boost/circular_buffer_fwd.hpp @@ -0,0 +1,43 @@ +// Forward declaration of the circular buffer and its adaptor. + +// Copyright (c) 2003-2007 Jan Gaspar + +// Use, modification, and distribution is subject to 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) + +// See www.boost.org/libs/circular_buffer for documentation. + +#if !defined(BOOST_CIRCULAR_BUFFER_FWD_HPP) +#define BOOST_CIRCULAR_BUFFER_FWD_HPP + +#if defined(_MSC_VER) && _MSC_VER >= 1200 + #pragma once +#endif + +#include +#if !defined(BOOST_NO_STD_ALLOCATOR) + #include +#else + #include +#endif + +namespace boost { + +#if !defined(BOOST_NO_STD_ALLOCATOR) + #define BOOST_CB_DEFAULT_ALLOCATOR(T) std::allocator +#else + #define BOOST_CB_DEFAULT_ALLOCATOR(T) BOOST_DEDUCED_TYPENAME std::vector::allocator_type +#endif + +template +class circular_buffer; + +template +class circular_buffer_space_optimized; + +#undef BOOST_CB_DEFAULT_ALLOCATOR + +} // namespace boost + +#endif // #if !defined(BOOST_CIRCULAR_BUFFER_FWD_HPP) diff --git a/win32/include/boost/compatibility/cpp_c_headers/cassert b/win32/include/boost/compatibility/cpp_c_headers/cassert new file mode 100755 index 000000000..5bc7329dd --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/cassert @@ -0,0 +1,10 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CASSERT_HEADER +#define __CASSERT_HEADER + +#include + +#endif // CASSERT_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/cctype b/win32/include/boost/compatibility/cpp_c_headers/cctype new file mode 100755 index 000000000..1ad03cb5c --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/cctype @@ -0,0 +1,26 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CCTYPE_HEADER +#define __CCTYPE_HEADER + +#include + +namespace std { + using ::isalnum; + using ::isdigit; + using ::isprint; + using ::isupper; + using ::tolower; + using ::isalpha; + using ::isgraph; + using ::ispunct; + using ::isxdigit; + using ::toupper; + using ::iscntrl; + using ::islower; + using ::isspace; +} + +#endif // CCTYPE_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/cerrno b/win32/include/boost/compatibility/cpp_c_headers/cerrno new file mode 100755 index 000000000..4d57b8087 --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/cerrno @@ -0,0 +1,10 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CERRNO_HEADER +#define __CERRNO_HEADER + +#include + +#endif // CERRNO_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/cfloat b/win32/include/boost/compatibility/cpp_c_headers/cfloat new file mode 100755 index 000000000..9d3d53318 --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/cfloat @@ -0,0 +1,10 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CFLOAT_HEADER +#define __CFLOAT_HEADER + +#include + +#endif // CFLOAT_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/climits b/win32/include/boost/compatibility/cpp_c_headers/climits new file mode 100755 index 000000000..b71b7f5eb --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/climits @@ -0,0 +1,10 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CLIMITS_HEADER +#define __CLIMITS_HEADER + +#include + +#endif // CLIMITS_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/clocale b/win32/include/boost/compatibility/cpp_c_headers/clocale new file mode 100755 index 000000000..b3ba3c859 --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/clocale @@ -0,0 +1,16 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CLOCALE_HEADER +#define __CLOCALE_HEADER + +#include + +namespace std { + using ::lconv; + using ::localeconv; + using ::setlocale; +} + +#endif // CLOCALE_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/cmath b/win32/include/boost/compatibility/cpp_c_headers/cmath new file mode 100755 index 000000000..70dc8843e --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/cmath @@ -0,0 +1,35 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CMATH_HEADER +#define __CMATH_HEADER + +#include + +namespace std { + using ::acos; + using ::cos; + using ::fmod; + using ::modf; + using ::tan; + using ::asin; + using ::cosh; + using ::frexp; + using ::pow; + using ::tanh; + using ::atan; + using ::exp; + using ::ldexp; + using ::sin; + using ::atan2; + using ::fabs; + using ::log; + using ::sinh; + using ::ceil; + using ::floor; + using ::log10; + using ::sqrt; +} + +#endif // CMATH_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/csetjmp b/win32/include/boost/compatibility/cpp_c_headers/csetjmp new file mode 100755 index 000000000..aa6a019df --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/csetjmp @@ -0,0 +1,15 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CSETJMP_HEADER +#define __CSETJMP_HEADER + +#include + +namespace std { + using ::jmp_buf; + using ::longjmp; +} + +#endif // CSETJMP_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/csignal b/win32/include/boost/compatibility/cpp_c_headers/csignal new file mode 100755 index 000000000..37e11d9e4 --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/csignal @@ -0,0 +1,16 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CSIGNAL_HEADER +#define __CSIGNAL_HEADER + +#include + +namespace std { + using ::sig_atomic_t; + using ::raise; + using ::signal; +} + +#endif // CSIGNAL_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/cstdarg b/win32/include/boost/compatibility/cpp_c_headers/cstdarg new file mode 100755 index 000000000..5e1dd749f --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/cstdarg @@ -0,0 +1,14 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CSTDARG_HEADER +#define __CSTDARG_HEADER + +#include + +namespace std { + using ::va_list; +} + +#endif // CSTDARG_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/cstddef b/win32/include/boost/compatibility/cpp_c_headers/cstddef new file mode 100755 index 000000000..c00a55c1f --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/cstddef @@ -0,0 +1,15 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CSTDDEF_HEADER +#define __CSTDDEF_HEADER + +#include + +namespace std { + using ::ptrdiff_t; + using ::size_t; +} + +#endif // CSTDDEF_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/cstdio b/win32/include/boost/compatibility/cpp_c_headers/cstdio new file mode 100755 index 000000000..8a48077ce --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/cstdio @@ -0,0 +1,57 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CSTDIO_HEADER +#define __CSTDIO_HEADER + +#include + +namespace std { + using ::FILE; + using ::fpos_t; + using ::size_t; + using ::clearerr; + using ::fgets; + using ::fscanf; + using ::gets; + using ::rename; + using ::tmpfile; + using ::fclose; + using ::fopen; + using ::fseek; + using ::perror; + using ::rewind; + using ::tmpnam; + using ::feof; + using ::fprintf; + using ::fsetpos; + using ::printf; + using ::scanf; + using ::ungetc; + using ::ferror; + using ::fputc; + using ::ftell; + using ::putc; + using ::setbuf; + using ::vfprintf; + using ::fflush; + using ::fputs; + using ::fwrite; + using ::putchar; + using ::setvbuf; + using ::vprintf; + using ::fgetc; + using ::fread; + using ::getc; + using ::puts; + using ::sprintf; + using ::vsprintf; + using ::fgetpos; + using ::freopen; + using ::getchar; + using ::remove; + using ::sscanf; +} + +#endif // CSTDIO_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/cstdlib b/win32/include/boost/compatibility/cpp_c_headers/cstdlib new file mode 100755 index 000000000..7592ffcf3 --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/cstdlib @@ -0,0 +1,43 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CSTDLIB_HEADER +#define __CSTDLIB_HEADER + +#include + +namespace std { + using ::abort; + using ::atexit; + using ::exit; + using ::getenv; + using ::system; + using ::calloc; + using ::malloc; + using ::free; + using ::realloc; + using ::atol; + using ::mblen; + using ::strtod; + using ::wctomb; + using ::atof; + using ::mbstowcs; + using ::strtol; + using ::wcstombs; + using ::atoi; + using ::mbtowc; + using ::strtoul; + using ::bsearch; + using ::qsort; + using ::div_t; + using ::ldiv_t; + using ::abs; + using ::labs; + using ::srand; + using ::div; + using ::ldiv; + using ::rand; +} + +#endif // CSTDLIB_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/cstring b/win32/include/boost/compatibility/cpp_c_headers/cstring new file mode 100755 index 000000000..e913597a6 --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/cstring @@ -0,0 +1,36 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CSTRING_HEADER +#define __CSTRING_HEADER + +#include + +namespace std { + using ::size_t; + using ::memchr; + using ::strcat; + using ::strcspn; + using ::strncpy; + using ::strtok; + using ::memcmp; + using ::strchr; + using ::strerror; + using ::strpbrk; + using ::strxfrm; + using ::memcpy; + using ::strcmp; + using ::strlen; + using ::strrchr; + using ::memmove; + using ::strcoll; + using ::strncat; + using ::strspn; + using ::memset; + using ::strcpy; + using ::strncmp; + using ::strstr; +} + +#endif // CSTRING_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/ctime b/win32/include/boost/compatibility/cpp_c_headers/ctime new file mode 100755 index 000000000..0c8ac9abf --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/ctime @@ -0,0 +1,26 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CTIME_HEADER +#define __CTIME_HEADER + +#include + +namespace std { + using ::size_t; + using ::clock_t; + using ::time_t; + using ::tm; + using ::asctime; + using ::clock; + using ::difftime; + using ::localtime; + using ::strftime; + using ::ctime; + using ::gmtime; + using ::mktime; + using ::time; +} + +#endif // CTIME_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/cwchar b/win32/include/boost/compatibility/cpp_c_headers/cwchar new file mode 100755 index 000000000..f9fbd3095 --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/cwchar @@ -0,0 +1,156 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CWCHAR_HEADER +#define __CWCHAR_HEADER + +#include + +namespace std { + using ::mbstate_t; + using ::wint_t; + using ::size_t; +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::btowc; +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) + using ::getwchar; +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) + using ::ungetwc; +#endif + using ::wcscpy; +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::wcsrtombs; +#endif +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::wmemchr; +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) + using ::fgetwc; +#endif +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::mbrlen; +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::vfwprintf; +#endif +#endif + using ::wcscspn; + using ::wcsspn; +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::wmemcmp; +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) + using ::fgetws; +#endif +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::mbrtowc; +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::vswprintf; +#endif +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) + using ::wcsftime; +#endif + using ::wcsstr; +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::wmemcpy; +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) + using ::fputwc; +#endif +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::mbsinit; +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::vwprintf; +#endif +#endif + using ::wcslen; + using ::wcstod; +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::wmemmove; +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) + using ::fputws; +#endif +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::mbsrtowcs; +#endif +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::wcrtomb; +#endif + using ::wcsncat; + using ::wcstok; +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::wmemset; +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) +#if !(defined(__DECCXX_VER) && __DECCXX_VER <= 60290024) + using ::fwide; +#endif +#endif +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) + using ::putwc; +#endif + using ::wcscat; + using ::wcsncmp; + using ::wcstol; +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::wprintf; +#endif +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::fwprintf; +#endif +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) + using ::putwchar; +#endif + using ::wcschr; + using ::wcsncpy; + using ::wcstoul; +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::wscanf; +#endif +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::fwscanf; +#endif +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::swprintf; +#endif +#endif + using ::wcscmp; + using ::wcspbrk; + using ::wcsxfrm; +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) + using ::getwc; +#endif +#if !(defined(__linux) && defined(__DECCXX_VER) && __DECCXX_VER <= 60390005) +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::swscanf; +#endif +#endif + using ::wcscoll; + using ::wcsrchr; +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::wctob; +#endif +} + +#endif // CWCHAR_HEADER diff --git a/win32/include/boost/compatibility/cpp_c_headers/cwctype b/win32/include/boost/compatibility/cpp_c_headers/cwctype new file mode 100755 index 000000000..cf8f07b07 --- /dev/null +++ b/win32/include/boost/compatibility/cpp_c_headers/cwctype @@ -0,0 +1,39 @@ +// This file is automatically generated. Do not edit. +// ['../../libs/compatibility/generate_cpp_c_headers.py'] +// Wed Jul 23 12:11:19 2003 ('GMTST', 'GMTST') + +#ifndef __CWCTYPE_HEADER +#define __CWCTYPE_HEADER + +#include + +namespace std { +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::wctrans_t; +#endif + using ::wctype_t; + using ::wint_t; + using ::iswalnum; + using ::iswctype; + using ::iswlower; + using ::iswspace; +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::towctrans; +#endif +#if !(defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 740) + using ::wctrans; +#endif + using ::iswalpha; + using ::iswdigit; + using ::iswprint; + using ::iswupper; + using ::towlower; + using ::wctype; + using ::iswcntrl; + using ::iswgraph; + using ::iswpunct; + using ::iswxdigit; + using ::towupper; +} + +#endif // CWCTYPE_HEADER diff --git a/win32/include/boost/compressed_pair.hpp b/win32/include/boost/compressed_pair.hpp new file mode 100755 index 000000000..512c2a0c1 --- /dev/null +++ b/win32/include/boost/compressed_pair.hpp @@ -0,0 +1,24 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/utility for most recent version including documentation. + +// See boost/detail/compressed_pair.hpp and boost/detail/ob_compressed_pair.hpp +// for full copyright notices. + +#ifndef BOOST_COMPRESSED_PAIR_HPP +#define BOOST_COMPRESSED_PAIR_HPP + +#ifndef BOOST_CONFIG_HPP +#include +#endif + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +#include +#else +#include +#endif + +#endif // BOOST_COMPRESSED_PAIR_HPP diff --git a/win32/include/boost/concept/assert.hpp b/win32/include/boost/concept/assert.hpp new file mode 100755 index 000000000..11c86cc88 --- /dev/null +++ b/win32/include/boost/concept/assert.hpp @@ -0,0 +1,46 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_CONCEPT_ASSERT_DWA2006430_HPP +# define BOOST_CONCEPT_ASSERT_DWA2006430_HPP + +# include +# include + +// The old protocol used a constraints() member function in concept +// checking classes. If the compiler supports SFINAE, we can detect +// that function and seamlessly support the old concept checking +// classes. In this release, backward compatibility with the old +// concept checking classes is enabled by default, where available. +// The old protocol is deprecated, though, and backward compatibility +// will no longer be the default in the next release. + +# if !defined(BOOST_NO_OLD_CONCEPT_SUPPORT) \ + && !defined(BOOST_NO_SFINAE) \ + \ + && !(BOOST_WORKAROUND(__GNUC__, == 3) && BOOST_WORKAROUND(__GNUC_MINOR__, < 4)) \ + && !(BOOST_WORKAROUND(__GNUC__, == 2)) + +// Note: gcc-2.96 through 3.3.x have some SFINAE, but no ability to +// check for the presence of particularmember functions. + +# define BOOST_OLD_CONCEPT_SUPPORT + +# endif + +# ifdef BOOST_MSVC +# include +# elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +# include +# else +# include +# endif + + // Usage, in class or function context: + // + // BOOST_CONCEPT_ASSERT((UnaryFunctionConcept)); + // +# define BOOST_CONCEPT_ASSERT(ModelInParens) \ + BOOST_CONCEPT_ASSERT_FN(void(*)ModelInParens) + +#endif // BOOST_CONCEPT_ASSERT_DWA2006430_HPP diff --git a/win32/include/boost/concept/detail/borland.hpp b/win32/include/boost/concept/detail/borland.hpp new file mode 100755 index 000000000..cbc2ee0c9 --- /dev/null +++ b/win32/include/boost/concept/detail/borland.hpp @@ -0,0 +1,29 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_CONCEPT_DETAIL_BORLAND_DWA2006429_HPP +# define BOOST_CONCEPT_DETAIL_BORLAND_DWA2006429_HPP + +# include + +namespace boost { namespace concept { + +template +struct require; + +template +struct require +{ + enum { instantiate = sizeof((((Model*)0)->~Model()), 3) }; +}; + +# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ + enum \ + { \ + BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + boost::concept::require::instantiate \ + } + +}} // namespace boost::concept + +#endif // BOOST_CONCEPT_DETAIL_BORLAND_DWA2006429_HPP diff --git a/win32/include/boost/concept/detail/concept_def.hpp b/win32/include/boost/concept/detail/concept_def.hpp new file mode 100755 index 000000000..f2474a81c --- /dev/null +++ b/win32/include/boost/concept/detail/concept_def.hpp @@ -0,0 +1,51 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP +# define BOOST_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP +# include +# include +# include +# include +#endif // BOOST_CONCEPT_DETAIL_CONCEPT_DEF_DWA200651_HPP + +// BOOST_concept(SomeName, (p1)(p2)...(pN)) +// +// Expands to "template struct SomeName" +// +// Also defines an equivalent SomeNameConcept for backward compatibility. +// Maybe in the next release we can kill off the "Concept" suffix for good. +#if BOOST_WORKAROUND(__GNUC__, <= 3) +# define BOOST_concept(name, params) \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ + struct name; /* forward declaration */ \ + \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ + struct BOOST_PP_CAT(name,Concept) \ + : name< BOOST_PP_SEQ_ENUM(params) > \ + { \ + /* at least 2.96 and 3.4.3 both need this */ \ + BOOST_PP_CAT(name,Concept)(); \ + }; \ + \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ + struct name +#else +# define BOOST_concept(name, params) \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ + struct name; /* forward declaration */ \ + \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ + struct BOOST_PP_CAT(name,Concept) \ + : name< BOOST_PP_SEQ_ENUM(params) > \ + { \ + }; \ + \ + template < BOOST_PP_SEQ_FOR_EACH_I(BOOST_CONCEPT_typename,~,params) > \ + struct name +#endif + +// Helper for BOOST_concept, above. +# define BOOST_CONCEPT_typename(r, ignored, index, t) \ + BOOST_PP_COMMA_IF(index) typename t + diff --git a/win32/include/boost/concept/detail/concept_undef.hpp b/win32/include/boost/concept/detail/concept_undef.hpp new file mode 100755 index 000000000..fa36abd63 --- /dev/null +++ b/win32/include/boost/concept/detail/concept_undef.hpp @@ -0,0 +1,5 @@ +// Copyright David Abrahams 2006. 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) +# undef BOOST_concept_typename +# undef BOOST_concept diff --git a/win32/include/boost/concept/detail/general.hpp b/win32/include/boost/concept/detail/general.hpp new file mode 100755 index 000000000..859a880e8 --- /dev/null +++ b/win32/include/boost/concept/detail/general.hpp @@ -0,0 +1,66 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_CONCEPT_DETAIL_GENERAL_DWA2006429_HPP +# define BOOST_CONCEPT_DETAIL_GENERAL_DWA2006429_HPP + +# include + +# ifdef BOOST_OLD_CONCEPT_SUPPORT +# include +# include +# endif + +// This implementation works on Comeau and GCC, all the way back to +// 2.95 +namespace boost { namespace concept { + +template +struct requirement_; + +namespace detail +{ + template struct instantiate {}; +} + +template +struct requirement +{ + static void failed() { ((Model*)0)->~Model(); } +}; + +# ifdef BOOST_OLD_CONCEPT_SUPPORT + +template +struct constraint +{ + static void failed() { ((Model*)0)->constraints(); } +}; + +template +struct requirement_ + : mpl::if_< + concept::not_satisfied + , constraint + , requirement + >::type +{}; + +# else + +// For GCC-2.x, these can't have exactly the same name +template +struct requirement_ + : requirement +{}; + +# endif + +# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ + typedef ::boost::concept::detail::instantiate< \ + &::boost::concept::requirement_::failed> \ + BOOST_PP_CAT(boost_concept_check,__LINE__) + +}} + +#endif // BOOST_CONCEPT_DETAIL_GENERAL_DWA2006429_HPP diff --git a/win32/include/boost/concept/detail/has_constraints.hpp b/win32/include/boost/concept/detail/has_constraints.hpp new file mode 100755 index 000000000..02c03e066 --- /dev/null +++ b/win32/include/boost/concept/detail/has_constraints.hpp @@ -0,0 +1,48 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_CONCEPT_DETAIL_HAS_CONSTRAINTS_DWA2006429_HPP +# define BOOST_CONCEPT_DETAIL_HAS_CONSTRAINTS_DWA2006429_HPP + +# include +# include +namespace boost { namespace concept { + +namespace detail +{ + +// Here we implement the metafunction that detects whether a +// constraints metafunction exists + typedef char yes; + typedef char (&no)[2]; + + template + struct wrap_constraints {}; + +#if BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) + // Work around the following bogus error in Sun Studio 11, by + // turning off the has_constraints function entirely: + // Error: complex expression not allowed in dependent template + // argument expression + inline no has_constraints_(...); +#else + template + inline yes has_constraints_(Model*, wrap_constraints* = 0); + inline no has_constraints_(...); +#endif +} + +// This would be called "detail::has_constraints," but it has a strong +// tendency to show up in error messages. +template +struct not_satisfied +{ + BOOST_STATIC_CONSTANT( + bool + , value = sizeof( detail::has_constraints_((Model*)0) ) == sizeof(detail::yes) ); + typedef mpl::bool_ type; +}; + +}} // namespace boost::concept::detail + +#endif // BOOST_CONCEPT_DETAIL_HAS_CONSTRAINTS_DWA2006429_HPP diff --git a/win32/include/boost/concept/detail/msvc.hpp b/win32/include/boost/concept/detail/msvc.hpp new file mode 100755 index 000000000..c19d0a538 --- /dev/null +++ b/win32/include/boost/concept/detail/msvc.hpp @@ -0,0 +1,92 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP +# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP + +# include + +# ifdef BOOST_OLD_CONCEPT_SUPPORT +# include +# include +# endif + + +namespace boost { namespace concept { + +template +struct check +{ + virtual void failed(Model* x) + { + x->~Model(); + } +}; + +# ifdef BOOST_OLD_CONCEPT_SUPPORT + +namespace detail +{ + // No need for a virtual function here, since evaluating + // not_satisfied below will have already instantiated the + // constraints() member. + struct constraint {}; +} + +template +struct require + : mpl::if_c< + not_satisfied::value + , detail::constraint + , check + >::type +{}; + +# else + +template +struct require + : check +{}; + +# endif + +# if BOOST_WORKAROUND(BOOST_MSVC, == 1310) + +// +// The iterator library sees some really strange errors unless we +// do things this way. +// +template +struct require +{ + virtual void failed(Model*) + { + require(); + } +}; + +# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ +enum \ +{ \ + BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + sizeof(::boost::concept::require) \ +} + +# else // Not vc-7.1 + +template +require +require_(void(*)(Model)); + +# define BOOST_CONCEPT_ASSERT_FN( ModelFnPtr ) \ +enum \ +{ \ + BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + sizeof(::boost::concept::require_((ModelFnPtr)0)) \ +} + +# endif +}} + +#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP diff --git a/win32/include/boost/concept/requires.hpp b/win32/include/boost/concept/requires.hpp new file mode 100755 index 000000000..a060dd765 --- /dev/null +++ b/win32/include/boost/concept/requires.hpp @@ -0,0 +1,78 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_CONCEPT_REQUIRES_DWA2006430_HPP +# define BOOST_CONCEPT_REQUIRES_DWA2006430_HPP + +# include +# include +# include +# include + +namespace boost { + +// Template for use in handwritten assertions +template +struct requires_ : More +{ +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + typedef typename More::type type; +# endif + BOOST_CONCEPT_ASSERT((Model)); +}; + +// Template for use by macros, where models must be wrapped in parens. +// This isn't in namespace detail to keep extra cruft out of resulting +// error messages. +template +struct _requires_ +{ + enum { value = 0 }; + BOOST_CONCEPT_ASSERT_FN(ModelFn); +}; + +template +struct Requires_ : ::boost::parameter::aux::unaryfunptr_arg_type +{ +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + typedef typename ::boost::parameter::aux::unaryfunptr_arg_type::type type; +# endif +}; + +# if BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(1010)) +# define BOOST_CONCEPT_REQUIRES_(r,data,t) | (::boost::_requires_::value) +# else +# define BOOST_CONCEPT_REQUIRES_(r,data,t) + (::boost::_requires_::value) +# endif + +#if defined(NDEBUG) || BOOST_WORKAROUND(BOOST_MSVC, < 1300) + +# define BOOST_CONCEPT_REQUIRES(models, result) \ + typename ::boost::parameter::aux::unaryfunptr_arg_type::type + +#elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + +// Same thing as below without the initial typename +# define BOOST_CONCEPT_REQUIRES(models, result) \ + ::boost::Requires_< \ + (0 BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_REQUIRES_, ~, models)), \ + ::boost::parameter::aux::unaryfunptr_arg_type \ + >::type + +#else + +// This just ICEs on MSVC6 :( +# define BOOST_CONCEPT_REQUIRES(models, result) \ + typename ::boost::Requires_< \ + (0 BOOST_PP_SEQ_FOR_EACH(BOOST_CONCEPT_REQUIRES_, ~, models)), \ + void(*)result \ + >::type + +#endif + +// C++0x proposed syntax changed. This supports an older usage +#define BOOST_CONCEPT_WHERE(models,result) BOOST_CONCEPT_REQUIRES(models,result) + +} // namespace boost::concept_check + +#endif // BOOST_CONCEPT_REQUIRES_DWA2006430_HPP diff --git a/win32/include/boost/concept/usage.hpp b/win32/include/boost/concept/usage.hpp new file mode 100755 index 000000000..71b2da7e2 --- /dev/null +++ b/win32/include/boost/concept/usage.hpp @@ -0,0 +1,43 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_CONCEPT_USAGE_DWA2006919_HPP +# define BOOST_CONCEPT_USAGE_DWA2006919_HPP + +# include +# include + +namespace boost { namespace concept { + +# if BOOST_WORKAROUND(__GNUC__, == 2) + +# define BOOST_CONCEPT_USAGE(model) ~model() + +# else + +template +struct usage_requirements +{ + ~usage_requirements() { ((Model*)0)->~Model(); } +}; + +# if BOOST_WORKAROUND(__GNUC__, <= 3) + +# define BOOST_CONCEPT_USAGE(model) \ + model(); /* at least 2.96 and 3.4.3 both need this :( */ \ + BOOST_CONCEPT_ASSERT((boost::concept::usage_requirements)); \ + ~model() + +# else + +# define BOOST_CONCEPT_USAGE(model) \ + BOOST_CONCEPT_ASSERT((boost::concept::usage_requirements)); \ + ~model() + +# endif + +# endif + +}} // namespace boost::concept + +#endif // BOOST_CONCEPT_USAGE_DWA2006919_HPP diff --git a/win32/include/boost/concept_archetype.hpp b/win32/include/boost/concept_archetype.hpp new file mode 100755 index 000000000..c69578b26 --- /dev/null +++ b/win32/include/boost/concept_archetype.hpp @@ -0,0 +1,669 @@ +// +// (C) Copyright Jeremy Siek 2000. +// 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) +// +// Revision History: +// +// 17 July 2001: Added const to some member functions. (Jeremy Siek) +// 05 May 2001: Removed static dummy_cons object. (Jeremy Siek) + +// See http://www.boost.org/libs/concept_check for documentation. + +#ifndef BOOST_CONCEPT_ARCHETYPES_HPP +#define BOOST_CONCEPT_ARCHETYPES_HPP + +#include +#include +#include +#include + +namespace boost { + + //=========================================================================== + // Basic Archetype Classes + + namespace detail { + class dummy_constructor { }; + } + + // A type that models no concept. The template parameter + // is only there so that null_archetype types can be created + // that have different type. + template + class null_archetype { + private: + null_archetype() { } + null_archetype(const null_archetype&) { } + null_archetype& operator=(const null_archetype&) { return *this; } + public: + null_archetype(detail::dummy_constructor) { } +#ifndef __MWERKS__ + template + friend void dummy_friend(); // just to avoid warnings +#endif + }; + + // This is a helper class that provides a way to get a reference to + // an object. The get() function will never be called at run-time + // (nothing in this file will) so this seemingly very bad function + // is really quite innocent. The name of this class needs to be + // changed. + template + class static_object + { + public: + static T& get() + { +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + return *reinterpret_cast(0); +#else + static char d[sizeof(T)]; + return *reinterpret_cast(d); +#endif + } + }; + + template > + class default_constructible_archetype : public Base { + public: + default_constructible_archetype() + : Base(static_object::get()) { } + default_constructible_archetype(detail::dummy_constructor x) : Base(x) { } + }; + + template > + class assignable_archetype : public Base { + assignable_archetype() { } + assignable_archetype(const assignable_archetype&) { } + public: + assignable_archetype& operator=(const assignable_archetype&) { + return *this; + } + assignable_archetype(detail::dummy_constructor x) : Base(x) { } + }; + + template > + class copy_constructible_archetype : public Base { + public: + copy_constructible_archetype() + : Base(static_object::get()) { } + copy_constructible_archetype(const copy_constructible_archetype&) + : Base(static_object::get()) { } + copy_constructible_archetype(detail::dummy_constructor x) : Base(x) { } + }; + + template > + class sgi_assignable_archetype : public Base { + public: + sgi_assignable_archetype(const sgi_assignable_archetype&) + : Base(static_object::get()) { } + sgi_assignable_archetype& operator=(const sgi_assignable_archetype&) { + return *this; + } + sgi_assignable_archetype(const detail::dummy_constructor& x) : Base(x) { } + }; + + struct default_archetype_base { + default_archetype_base(detail::dummy_constructor) { } + }; + + // Careful, don't use same type for T and Base. That results in the + // conversion operator being invalid. Since T is often + // null_archetype, can't use null_archetype for Base. + template + class convertible_to_archetype : public Base { + private: + convertible_to_archetype() { } + convertible_to_archetype(const convertible_to_archetype& ) { } + convertible_to_archetype& operator=(const convertible_to_archetype&) + { return *this; } + public: + convertible_to_archetype(detail::dummy_constructor x) : Base(x) { } + operator const T&() const { return static_object::get(); } + }; + + template + class convertible_from_archetype : public Base { + private: + convertible_from_archetype() { } + convertible_from_archetype(const convertible_from_archetype& ) { } + convertible_from_archetype& operator=(const convertible_from_archetype&) + { return *this; } + public: + convertible_from_archetype(detail::dummy_constructor x) : Base(x) { } + convertible_from_archetype(const T&) { } + convertible_from_archetype& operator=(const T&) + { return *this; } + }; + + class boolean_archetype { + public: + boolean_archetype(const boolean_archetype&) { } + operator bool() const { return true; } + boolean_archetype(detail::dummy_constructor) { } + private: + boolean_archetype() { } + boolean_archetype& operator=(const boolean_archetype&) { return *this; } + }; + + template > + class equality_comparable_archetype : public Base { + public: + equality_comparable_archetype(detail::dummy_constructor x) : Base(x) { } + }; + template + boolean_archetype + operator==(const equality_comparable_archetype&, + const equality_comparable_archetype&) + { + return boolean_archetype(static_object::get()); + } + template + boolean_archetype + operator!=(const equality_comparable_archetype&, + const equality_comparable_archetype&) + { + return boolean_archetype(static_object::get()); + } + + + template > + class equality_comparable2_first_archetype : public Base { + public: + equality_comparable2_first_archetype(detail::dummy_constructor x) + : Base(x) { } + }; + template > + class equality_comparable2_second_archetype : public Base { + public: + equality_comparable2_second_archetype(detail::dummy_constructor x) + : Base(x) { } + }; + template + boolean_archetype + operator==(const equality_comparable2_first_archetype&, + const equality_comparable2_second_archetype&) + { + return boolean_archetype(static_object::get()); + } + template + boolean_archetype + operator!=(const equality_comparable2_first_archetype&, + const equality_comparable2_second_archetype&) + { + return boolean_archetype(static_object::get()); + } + + + template > + class less_than_comparable_archetype : public Base { + public: + less_than_comparable_archetype(detail::dummy_constructor x) : Base(x) { } + }; + template + boolean_archetype + operator<(const less_than_comparable_archetype&, + const less_than_comparable_archetype&) + { + return boolean_archetype(static_object::get()); + } + + + + template > + class comparable_archetype : public Base { + public: + comparable_archetype(detail::dummy_constructor x) : Base(x) { } + }; + template + boolean_archetype + operator<(const comparable_archetype&, + const comparable_archetype&) + { + return boolean_archetype(static_object::get()); + } + template + boolean_archetype + operator<=(const comparable_archetype&, + const comparable_archetype&) + { + return boolean_archetype(static_object::get()); + } + template + boolean_archetype + operator>(const comparable_archetype&, + const comparable_archetype&) + { + return boolean_archetype(static_object::get()); + } + template + boolean_archetype + operator>=(const comparable_archetype&, + const comparable_archetype&) + { + return boolean_archetype(static_object::get()); + } + + + // The purpose of the optags is so that one can specify + // exactly which types the operator< is defined between. + // This is useful for allowing the operations: + // + // A a; B b; + // a < b + // b < a + // + // without also allowing the combinations: + // + // a < a + // b < b + // + struct optag1 { }; + struct optag2 { }; + struct optag3 { }; + +#define BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(OP, NAME) \ + template , class Tag = optag1 > \ + class NAME##_first_archetype : public Base { \ + public: \ + NAME##_first_archetype(detail::dummy_constructor x) : Base(x) { } \ + }; \ + \ + template , class Tag = optag1 > \ + class NAME##_second_archetype : public Base { \ + public: \ + NAME##_second_archetype(detail::dummy_constructor x) : Base(x) { } \ + }; \ + \ + template \ + boolean_archetype \ + operator OP (const NAME##_first_archetype&, \ + const NAME##_second_archetype&) \ + { \ + return boolean_archetype(static_object::get()); \ + } + + BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(==, equal_op) + BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(!=, not_equal_op) + BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(<, less_than_op) + BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(<=, less_equal_op) + BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(>, greater_than_op) + BOOST_DEFINE_BINARY_PREDICATE_ARCHETYPE(>=, greater_equal_op) + +#define BOOST_DEFINE_OPERATOR_ARCHETYPE(OP, NAME) \ + template > \ + class NAME##_archetype : public Base { \ + public: \ + NAME##_archetype(detail::dummy_constructor x) : Base(x) { } \ + NAME##_archetype(const NAME##_archetype&) \ + : Base(static_object::get()) { } \ + NAME##_archetype& operator=(const NAME##_archetype&) { return *this; } \ + }; \ + template \ + NAME##_archetype \ + operator OP (const NAME##_archetype&,\ + const NAME##_archetype&) \ + { \ + return \ + NAME##_archetype(static_object::get()); \ + } + + BOOST_DEFINE_OPERATOR_ARCHETYPE(+, addable) + BOOST_DEFINE_OPERATOR_ARCHETYPE(-, subtractable) + BOOST_DEFINE_OPERATOR_ARCHETYPE(*, multipliable) + BOOST_DEFINE_OPERATOR_ARCHETYPE(/, dividable) + BOOST_DEFINE_OPERATOR_ARCHETYPE(%, modable) + + // As is, these are useless because of the return type. + // Need to invent a better way... +#define BOOST_DEFINE_BINARY_OPERATOR_ARCHETYPE(OP, NAME) \ + template > \ + class NAME##_first_archetype : public Base { \ + public: \ + NAME##_first_archetype(detail::dummy_constructor x) : Base(x) { } \ + }; \ + \ + template > \ + class NAME##_second_archetype : public Base { \ + public: \ + NAME##_second_archetype(detail::dummy_constructor x) : Base(x) { } \ + }; \ + \ + template \ + Return \ + operator OP (const NAME##_first_archetype&, \ + const NAME##_second_archetype&) \ + { \ + return Return(static_object::get()); \ + } + + BOOST_DEFINE_BINARY_OPERATOR_ARCHETYPE(+, plus_op) + BOOST_DEFINE_BINARY_OPERATOR_ARCHETYPE(*, time_op) + BOOST_DEFINE_BINARY_OPERATOR_ARCHETYPE(/, divide_op) + BOOST_DEFINE_BINARY_OPERATOR_ARCHETYPE(-, subtract_op) + BOOST_DEFINE_BINARY_OPERATOR_ARCHETYPE(%, mod_op) + + //=========================================================================== + // Function Object Archetype Classes + + template + class generator_archetype { + public: + const Return& operator()() { + return static_object::get(); + } + }; + + class void_generator_archetype { + public: + void operator()() { } + }; + + template + class unary_function_archetype { + private: + unary_function_archetype() { } + public: + unary_function_archetype(detail::dummy_constructor) { } + const Return& operator()(const Arg&) const { + return static_object::get(); + } + }; + + template + class binary_function_archetype { + private: + binary_function_archetype() { } + public: + binary_function_archetype(detail::dummy_constructor) { } + const Return& operator()(const Arg1&, const Arg2&) const { + return static_object::get(); + } + }; + + template + class unary_predicate_archetype { + typedef boolean_archetype Return; + unary_predicate_archetype() { } + public: + unary_predicate_archetype(detail::dummy_constructor) { } + const Return& operator()(const Arg&) const { + return static_object::get(); + } + }; + + template > + class binary_predicate_archetype { + typedef boolean_archetype Return; + binary_predicate_archetype() { } + public: + binary_predicate_archetype(detail::dummy_constructor) { } + const Return& operator()(const Arg1&, const Arg2&) const { + return static_object::get(); + } + }; + + //=========================================================================== + // Iterator Archetype Classes + + template + class input_iterator_archetype + { + private: + typedef input_iterator_archetype self; + public: + typedef std::input_iterator_tag iterator_category; + typedef T value_type; + struct reference { + operator const value_type&() const { return static_object::get(); } + }; + typedef const T* pointer; + typedef std::ptrdiff_t difference_type; + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return reference(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + }; + + template + class input_iterator_archetype_no_proxy + { + private: + typedef input_iterator_archetype_no_proxy self; + public: + typedef std::input_iterator_tag iterator_category; + typedef T value_type; + typedef const T& reference; + typedef const T* pointer; + typedef std::ptrdiff_t difference_type; + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return static_object::get(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + }; + + template + struct output_proxy { + output_proxy& operator=(const T&) { return *this; } + }; + + template + class output_iterator_archetype + { + public: + typedef output_iterator_archetype self; + public: + typedef std::output_iterator_tag iterator_category; + typedef output_proxy value_type; + typedef output_proxy reference; + typedef void pointer; + typedef void difference_type; + output_iterator_archetype(detail::dummy_constructor) { } + output_iterator_archetype(const self&) { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return output_proxy(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + private: + output_iterator_archetype() { } + }; + + template + class input_output_iterator_archetype + { + private: + typedef input_output_iterator_archetype self; + struct in_out_tag : public std::input_iterator_tag, public std::output_iterator_tag { }; + public: + typedef in_out_tag iterator_category; + typedef T value_type; + struct reference { + reference& operator=(const T&) { return *this; } + operator value_type() { return static_object::get(); } + }; + typedef const T* pointer; + typedef std::ptrdiff_t difference_type; + input_output_iterator_archetype() { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return reference(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + }; + + template + class forward_iterator_archetype + { + public: + typedef forward_iterator_archetype self; + public: + typedef std::forward_iterator_tag iterator_category; + typedef T value_type; + typedef const T& reference; + typedef T const* pointer; + typedef std::ptrdiff_t difference_type; + forward_iterator_archetype() { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return static_object::get(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + }; + + template + class mutable_forward_iterator_archetype + { + public: + typedef mutable_forward_iterator_archetype self; + public: + typedef std::forward_iterator_tag iterator_category; + typedef T value_type; + typedef T& reference; + typedef T* pointer; + typedef std::ptrdiff_t difference_type; + mutable_forward_iterator_archetype() { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return static_object::get(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + }; + + template + class bidirectional_iterator_archetype + { + public: + typedef bidirectional_iterator_archetype self; + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef T value_type; + typedef const T& reference; + typedef T* pointer; + typedef std::ptrdiff_t difference_type; + bidirectional_iterator_archetype() { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return static_object::get(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + self& operator--() { return *this; } + self operator--(int) { return *this; } + }; + + template + class mutable_bidirectional_iterator_archetype + { + public: + typedef mutable_bidirectional_iterator_archetype self; + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef T value_type; + typedef T& reference; + typedef T* pointer; + typedef std::ptrdiff_t difference_type; + mutable_bidirectional_iterator_archetype() { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return static_object::get(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + self& operator--() { return *this; } + self operator--(int) { return *this; } + }; + + template + class random_access_iterator_archetype + { + public: + typedef random_access_iterator_archetype self; + public: + typedef std::random_access_iterator_tag iterator_category; + typedef T value_type; + typedef const T& reference; + typedef T* pointer; + typedef std::ptrdiff_t difference_type; + random_access_iterator_archetype() { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return static_object::get(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + self& operator--() { return *this; } + self operator--(int) { return *this; } + reference operator[](difference_type) const + { return static_object::get(); } + self& operator+=(difference_type) { return *this; } + self& operator-=(difference_type) { return *this; } + difference_type operator-(const self&) const + { return difference_type(); } + self operator+(difference_type) const { return *this; } + self operator-(difference_type) const { return *this; } + bool operator<(const self&) const { return true; } + bool operator<=(const self&) const { return true; } + bool operator>(const self&) const { return true; } + bool operator>=(const self&) const { return true; } + }; + template + random_access_iterator_archetype + operator+(typename random_access_iterator_archetype::difference_type, + const random_access_iterator_archetype& x) + { return x; } + + + template + class mutable_random_access_iterator_archetype + { + public: + typedef mutable_random_access_iterator_archetype self; + public: + typedef std::random_access_iterator_tag iterator_category; + typedef T value_type; + typedef T& reference; + typedef T* pointer; + typedef std::ptrdiff_t difference_type; + mutable_random_access_iterator_archetype() { } + self& operator=(const self&) { return *this; } + bool operator==(const self&) const { return true; } + bool operator!=(const self&) const { return true; } + reference operator*() const { return static_object::get(); } + self& operator++() { return *this; } + self operator++(int) { return *this; } + self& operator--() { return *this; } + self operator--(int) { return *this; } + reference operator[](difference_type) const + { return static_object::get(); } + self& operator+=(difference_type) { return *this; } + self& operator-=(difference_type) { return *this; } + difference_type operator-(const self&) const + { return difference_type(); } + self operator+(difference_type) const { return *this; } + self operator-(difference_type) const { return *this; } + bool operator<(const self&) const { return true; } + bool operator<=(const self&) const { return true; } + bool operator>(const self&) const { return true; } + bool operator>=(const self&) const { return true; } + }; + template + mutable_random_access_iterator_archetype + operator+ + (typename mutable_random_access_iterator_archetype::difference_type, + const mutable_random_access_iterator_archetype& x) + { return x; } + +} // namespace boost + +#endif // BOOST_CONCEPT_ARCHETYPES_H diff --git a/win32/include/boost/concept_check.hpp b/win32/include/boost/concept_check.hpp new file mode 100755 index 000000000..daaf7cfe2 --- /dev/null +++ b/win32/include/boost/concept_check.hpp @@ -0,0 +1,988 @@ +// +// (C) Copyright Jeremy Siek 2000. +// 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) +// +// Revision History: +// 05 May 2001: Workarounds for HP aCC from Thomas Matelich. (Jeremy Siek) +// 02 April 2001: Removed limits header altogether. (Jeremy Siek) +// 01 April 2001: Modified to use new header. (JMaddock) +// + +// See http://www.boost.org/libs/concept_check for documentation. + +#ifndef BOOST_CONCEPT_CHECKS_HPP +# define BOOST_CONCEPT_CHECKS_HPP + +# include + +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# include +# include + +namespace boost +{ + + // + // Backward compatibility + // + + template + inline void function_requires(Model* = 0) + { + BOOST_CONCEPT_ASSERT((Model)); + } + template inline void ignore_unused_variable_warning(T const&) {} + +# define BOOST_CLASS_REQUIRE(type_var, ns, concept) \ + BOOST_CONCEPT_ASSERT((ns::concept)) + +# define BOOST_CLASS_REQUIRE2(type_var1, type_var2, ns, concept) \ + BOOST_CONCEPT_ASSERT((ns::concept)) + +# define BOOST_CLASS_REQUIRE3(tv1, tv2, tv3, ns, concept) \ + BOOST_CONCEPT_ASSERT((ns::concept)) + +# define BOOST_CLASS_REQUIRE4(tv1, tv2, tv3, tv4, ns, concept) \ + BOOST_CONCEPT_ASSERT((ns::concept)) + + + // + // Begin concept definitions + // + BOOST_concept(Integer, (T)) + { + BOOST_CONCEPT_USAGE(Integer) + { + x.error_type_must_be_an_integer_type(); + } + private: + T x; + }; + + template <> struct Integer {}; + template <> struct Integer {}; + template <> struct Integer {}; + template <> struct Integer {}; + template <> struct Integer {}; + template <> struct Integer {}; + template <> struct Integer {}; + template <> struct Integer {}; +# if defined(BOOST_HAS_LONG_LONG) + template <> struct Integer< ::boost::long_long_type> {}; + template <> struct Integer< ::boost::ulong_long_type> {}; +# elif defined(BOOST_HAS_MS_INT64) + template <> struct Integer<__int64> {}; + template <> struct Integer {}; +# endif + + BOOST_concept(SignedInteger,(T)) { + BOOST_CONCEPT_USAGE(SignedInteger) { + x.error_type_must_be_a_signed_integer_type(); + } + private: + T x; + }; + template <> struct SignedInteger { }; + template <> struct SignedInteger {}; + template <> struct SignedInteger {}; + template <> struct SignedInteger {}; +# if defined(BOOST_HAS_LONG_LONG) + template <> struct SignedInteger< ::boost::long_long_type> {}; +# elif defined(BOOST_HAS_MS_INT64) + template <> struct SignedInteger<__int64> {}; +# endif + + BOOST_concept(UnsignedInteger,(T)) { + BOOST_CONCEPT_USAGE(UnsignedInteger) { + x.error_type_must_be_an_unsigned_integer_type(); + } + private: + T x; + }; + + template <> struct UnsignedInteger {}; + template <> struct UnsignedInteger {}; + template <> struct UnsignedInteger {}; + template <> struct UnsignedInteger {}; +# if defined(BOOST_HAS_LONG_LONG) + template <> struct UnsignedInteger< ::boost::ulong_long_type> {}; +# elif defined(BOOST_HAS_MS_INT64) + template <> struct UnsignedInteger {}; +# endif + + //=========================================================================== + // Basic Concepts + + BOOST_concept(DefaultConstructible,(TT)) + { + BOOST_CONCEPT_USAGE(DefaultConstructible) { + TT a; // require default constructor + ignore_unused_variable_warning(a); + } + }; + + BOOST_concept(Assignable,(TT)) + { + BOOST_CONCEPT_USAGE(Assignable) { +#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL + a = a; // require assignment operator +#endif + const_constraints(a); + } + private: + void const_constraints(const TT& b) { +#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL + a = b; // const required for argument to assignment +#endif + } + private: + TT a; + }; + + + BOOST_concept(CopyConstructible,(TT)) + { + BOOST_CONCEPT_USAGE(CopyConstructible) { + TT a(b); // require copy constructor + TT* ptr = &a; // require address of operator + const_constraints(a); + ignore_unused_variable_warning(ptr); + } + private: + void const_constraints(const TT& a) { + TT c(a); // require const copy constructor + const TT* ptr = &a; // require const address of operator + ignore_unused_variable_warning(c); + ignore_unused_variable_warning(ptr); + } + TT b; + }; + + // The SGI STL version of Assignable requires copy constructor and operator= + BOOST_concept(SGIAssignable,(TT)) + { + BOOST_CONCEPT_USAGE(SGIAssignable) { + TT b(a); +#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL + a = a; // require assignment operator +#endif + const_constraints(a); + ignore_unused_variable_warning(b); + } + private: + void const_constraints(const TT& b) { + TT c(b); +#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL + a = b; // const required for argument to assignment +#endif + ignore_unused_variable_warning(c); + } + TT a; + }; + + BOOST_concept(Convertible,(X)(Y)) + { + BOOST_CONCEPT_USAGE(Convertible) { + Y y = x; + ignore_unused_variable_warning(y); + } + private: + X x; + }; + + // The C++ standard requirements for many concepts talk about return + // types that must be "convertible to bool". The problem with this + // requirement is that it leaves the door open for evil proxies that + // define things like operator|| with strange return types. Two + // possible solutions are: + // 1) require the return type to be exactly bool + // 2) stay with convertible to bool, and also + // specify stuff about all the logical operators. + // For now we just test for convertible to bool. + template + void require_boolean_expr(const TT& t) { + bool x = t; + ignore_unused_variable_warning(x); + } + + BOOST_concept(EqualityComparable,(TT)) + { + BOOST_CONCEPT_USAGE(EqualityComparable) { + require_boolean_expr(a == b); + require_boolean_expr(a != b); + } + private: + TT a, b; + }; + + BOOST_concept(LessThanComparable,(TT)) + { + BOOST_CONCEPT_USAGE(LessThanComparable) { + require_boolean_expr(a < b); + } + private: + TT a, b; + }; + + // This is equivalent to SGI STL's LessThanComparable. + BOOST_concept(Comparable,(TT)) + { + BOOST_CONCEPT_USAGE(Comparable) { + require_boolean_expr(a < b); + require_boolean_expr(a > b); + require_boolean_expr(a <= b); + require_boolean_expr(a >= b); + } + private: + TT a, b; + }; + +#define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \ + BOOST_concept(NAME, (First)(Second)) \ + { \ + BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ + private: \ + bool constraints_() { return a OP b; } \ + First a; \ + Second b; \ + } + +#define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \ + BOOST_concept(NAME, (Ret)(First)(Second)) \ + { \ + BOOST_CONCEPT_USAGE(NAME) { (void)constraints_(); } \ + private: \ + Ret constraints_() { return a OP b; } \ + First a; \ + Second b; \ + } + + BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOp); + BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOp); + BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, LessThanOp); + BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, LessEqualOp); + BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, GreaterThanOp); + BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, GreaterEqualOp); + + BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, PlusOp); + BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, TimesOp); + BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, DivideOp); + BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, SubtractOp); + BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, ModOp); + + //=========================================================================== + // Function Object Concepts + + BOOST_concept(Generator,(Func)(Return)) + { + BOOST_CONCEPT_USAGE(Generator) { test(is_void()); } + + private: + void test(boost::mpl::false_) + { + // Do we really want a reference here? + const Return& r = f(); + ignore_unused_variable_warning(r); + } + + void test(boost::mpl::true_) + { + f(); + } + + Func f; + }; + + BOOST_concept(UnaryFunction,(Func)(Return)(Arg)) + { + BOOST_CONCEPT_USAGE(UnaryFunction) { test(is_void()); } + + private: + void test(boost::mpl::false_) + { + f(arg); // "priming the pump" this way keeps msvc6 happy (ICE) + Return r = f(arg); + ignore_unused_variable_warning(r); + } + + void test(boost::mpl::true_) + { + f(arg); + } + + Func f; + Arg arg; + }; + + BOOST_concept(BinaryFunction,(Func)(Return)(First)(Second)) + { + BOOST_CONCEPT_USAGE(BinaryFunction) { test(is_void()); } + private: + void test(boost::mpl::false_) + { + f(first,second); + Return r = f(first, second); // require operator() + (void)r; + } + + void test(boost::mpl::true_) + { + f(first,second); + } + + Func f; + First first; + Second second; + }; + + BOOST_concept(UnaryPredicate,(Func)(Arg)) + { + BOOST_CONCEPT_USAGE(UnaryPredicate) { + require_boolean_expr(f(arg)); // require operator() returning bool + } + private: + Func f; + Arg arg; + }; + + BOOST_concept(BinaryPredicate,(Func)(First)(Second)) + { + BOOST_CONCEPT_USAGE(BinaryPredicate) { + require_boolean_expr(f(a, b)); // require operator() returning bool + } + private: + Func f; + First a; + Second b; + }; + + // use this when functor is used inside a container class like std::set + BOOST_concept(Const_BinaryPredicate,(Func)(First)(Second)) + : BinaryPredicate + { + BOOST_CONCEPT_USAGE(Const_BinaryPredicate) { + const_constraints(f); + } + private: + void const_constraints(const Func& fun) { + // operator() must be a const member function + require_boolean_expr(fun(a, b)); + } + Func f; + First a; + Second b; + }; + + BOOST_concept(AdaptableGenerator,(Func)(Return)) + : Generator + { + typedef typename Func::result_type result_type; + + BOOST_CONCEPT_USAGE(AdaptableGenerator) + { + BOOST_CONCEPT_ASSERT((Convertible)); + } + }; + + BOOST_concept(AdaptableUnaryFunction,(Func)(Return)(Arg)) + : UnaryFunction + { + typedef typename Func::argument_type argument_type; + typedef typename Func::result_type result_type; + + ~AdaptableUnaryFunction() + { + BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_CONCEPT_ASSERT((Convertible)); + } + }; + + BOOST_concept(AdaptableBinaryFunction,(Func)(Return)(First)(Second)) + : BinaryFunction< + Func + , typename Func::result_type + , typename Func::first_argument_type + , typename Func::second_argument_type + > + { + typedef typename Func::first_argument_type first_argument_type; + typedef typename Func::second_argument_type second_argument_type; + typedef typename Func::result_type result_type; + + ~AdaptableBinaryFunction() + { + BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_CONCEPT_ASSERT((Convertible)); + BOOST_CONCEPT_ASSERT((Convertible)); + } + }; + + BOOST_concept(AdaptablePredicate,(Func)(Arg)) + : UnaryPredicate + , AdaptableUnaryFunction + { + }; + + BOOST_concept(AdaptableBinaryPredicate,(Func)(First)(Second)) + : BinaryPredicate + , AdaptableBinaryFunction + { + }; + + //=========================================================================== + // Iterator Concepts + + BOOST_concept(InputIterator,(TT)) + : Assignable + , EqualityComparable + { + typedef typename boost::detail::iterator_traits::value_type value_type; + typedef typename boost::detail::iterator_traits::difference_type difference_type; + typedef typename boost::detail::iterator_traits::reference reference; + typedef typename boost::detail::iterator_traits::pointer pointer; + typedef typename boost::detail::iterator_traits::iterator_category iterator_category; + + BOOST_CONCEPT_USAGE(InputIterator) + { + BOOST_CONCEPT_ASSERT((SignedInteger)); + BOOST_CONCEPT_ASSERT((Convertible)); + + TT j(i); + (void)*i; // require dereference operator + ++j; // require preincrement operator + i++; // require postincrement operator + } + private: + TT i; + }; + + BOOST_concept(OutputIterator,(TT)(ValueT)) + : Assignable + { + BOOST_CONCEPT_USAGE(OutputIterator) { + + ++i; // require preincrement operator + i++; // require postincrement operator + *i++ = t; // require postincrement and assignment + } + private: + TT i, j; + ValueT t; + }; + + BOOST_concept(ForwardIterator,(TT)) + : InputIterator + { + BOOST_CONCEPT_USAGE(ForwardIterator) + { + BOOST_CONCEPT_ASSERT((Convertible< + BOOST_DEDUCED_TYPENAME ForwardIterator::iterator_category + , std::forward_iterator_tag + >)); + + typename InputIterator::reference r = *i; + ignore_unused_variable_warning(r); + } + + private: + TT i; + }; + + BOOST_concept(Mutable_ForwardIterator,(TT)) + : ForwardIterator + { + BOOST_CONCEPT_USAGE(Mutable_ForwardIterator) { + *i++ = *i; // require postincrement and assignment + } + private: + TT i; + }; + + BOOST_concept(BidirectionalIterator,(TT)) + : ForwardIterator + { + BOOST_CONCEPT_USAGE(BidirectionalIterator) + { + BOOST_CONCEPT_ASSERT((Convertible< + BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category + , std::bidirectional_iterator_tag + >)); + + --i; // require predecrement operator + i--; // require postdecrement operator + } + private: + TT i; + }; + + BOOST_concept(Mutable_BidirectionalIterator,(TT)) + : BidirectionalIterator + , Mutable_ForwardIterator + { + BOOST_CONCEPT_USAGE(Mutable_BidirectionalIterator) + { + *i-- = *i; // require postdecrement and assignment + } + private: + TT i; + }; + + BOOST_concept(RandomAccessIterator,(TT)) + : BidirectionalIterator + , Comparable + { + BOOST_CONCEPT_USAGE(RandomAccessIterator) + { + BOOST_CONCEPT_ASSERT((Convertible< + BOOST_DEDUCED_TYPENAME BidirectionalIterator::iterator_category + , std::random_access_iterator_tag + >)); + + i += n; // require assignment addition operator + i = i + n; i = n + i; // require addition with difference type + i -= n; // require assignment subtraction operator + i = i - n; // require subtraction with difference type + n = i - j; // require difference operator + (void)i[n]; // require element access operator + } + + private: + TT a, b; + TT i, j; + typename boost::detail::iterator_traits::difference_type n; + }; + + BOOST_concept(Mutable_RandomAccessIterator,(TT)) + : RandomAccessIterator + , Mutable_BidirectionalIterator + { + BOOST_CONCEPT_USAGE(Mutable_RandomAccessIterator) + { + i[n] = *i; // require element access and assignment + } + private: + TT i; + typename boost::detail::iterator_traits::difference_type n; + }; + + //=========================================================================== + // Container s + + BOOST_concept(Container,(C)) + : Assignable + { + typedef typename C::value_type value_type; + typedef typename C::difference_type difference_type; + typedef typename C::size_type size_type; + typedef typename C::const_reference const_reference; + typedef typename C::const_pointer const_pointer; + typedef typename C::const_iterator const_iterator; + + BOOST_CONCEPT_USAGE(Container) + { + BOOST_CONCEPT_ASSERT((InputIterator)); + const_constraints(c); + } + + private: + void const_constraints(const C& cc) { + i = cc.begin(); + i = cc.end(); + n = cc.size(); + n = cc.max_size(); + b = cc.empty(); + } + C c; + bool b; + const_iterator i; + size_type n; + }; + + BOOST_concept(Mutable_Container,(C)) + : Container + { + typedef typename C::reference reference; + typedef typename C::iterator iterator; + typedef typename C::pointer pointer; + + BOOST_CONCEPT_USAGE(Mutable_Container) + { + BOOST_CONCEPT_ASSERT(( + Assignable)); + + BOOST_CONCEPT_ASSERT((InputIterator)); + + i = c.begin(); + i = c.end(); + c.swap(c2); + } + + private: + iterator i; + C c, c2; + }; + + BOOST_concept(ForwardContainer,(C)) + : Container + { + BOOST_CONCEPT_USAGE(ForwardContainer) + { + BOOST_CONCEPT_ASSERT(( + ForwardIterator< + typename ForwardContainer::const_iterator + >)); + } + }; + + BOOST_concept(Mutable_ForwardContainer,(C)) + : ForwardContainer + , Mutable_Container + { + BOOST_CONCEPT_USAGE(Mutable_ForwardContainer) + { + BOOST_CONCEPT_ASSERT(( + Mutable_ForwardIterator< + typename Mutable_ForwardContainer::iterator + >)); + } + }; + + BOOST_concept(ReversibleContainer,(C)) + : ForwardContainer + { + typedef typename + C::const_reverse_iterator + const_reverse_iterator; + + BOOST_CONCEPT_USAGE(ReversibleContainer) + { + BOOST_CONCEPT_ASSERT(( + BidirectionalIterator< + typename ReversibleContainer::const_iterator>)); + + BOOST_CONCEPT_ASSERT((BidirectionalIterator)); + + const_constraints(c); + } + private: + void const_constraints(const C& cc) + { + const_reverse_iterator i = cc.rbegin(); + i = cc.rend(); + } + C c; + }; + + BOOST_concept(Mutable_ReversibleContainer,(C)) + : Mutable_ForwardContainer + , ReversibleContainer + { + typedef typename C::reverse_iterator reverse_iterator; + + BOOST_CONCEPT_USAGE(Mutable_ReversibleContainer) + { + typedef typename Mutable_ForwardContainer::iterator iterator; + BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator)); + BOOST_CONCEPT_ASSERT((Mutable_BidirectionalIterator)); + + reverse_iterator i = c.rbegin(); + i = c.rend(); + } + private: + C c; + }; + + BOOST_concept(RandomAccessContainer,(C)) + : ReversibleContainer + { + typedef typename C::size_type size_type; + typedef typename C::const_reference const_reference; + + BOOST_CONCEPT_USAGE(RandomAccessContainer) + { + BOOST_CONCEPT_ASSERT(( + RandomAccessIterator< + typename RandomAccessContainer::const_iterator + >)); + + const_constraints(c); + } + private: + void const_constraints(const C& cc) + { + const_reference r = cc[n]; + ignore_unused_variable_warning(r); + } + + C c; + size_type n; + }; + + BOOST_concept(Mutable_RandomAccessContainer,(C)) + : Mutable_ReversibleContainer + , RandomAccessContainer + { + private: + typedef Mutable_RandomAccessContainer self; + public: + BOOST_CONCEPT_USAGE(Mutable_RandomAccessContainer) + { + BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator)); + BOOST_CONCEPT_ASSERT((Mutable_RandomAccessIterator)); + + typename self::reference r = c[i]; + ignore_unused_variable_warning(r); + } + + private: + typename Mutable_ReversibleContainer::size_type i; + C c; + }; + + // A Sequence is inherently mutable + BOOST_concept(Sequence,(S)) + : Mutable_ForwardContainer + // Matt Austern's book puts DefaultConstructible here, the C++ + // standard places it in Container --JGS + // ... so why aren't we following the standard? --DWA + , DefaultConstructible + { + BOOST_CONCEPT_USAGE(Sequence) + { + S + c(n), + c2(n, t), + c3(first, last); + + c.insert(p, t); + c.insert(p, n, t); + c.insert(p, first, last); + + c.erase(p); + c.erase(p, q); + + typename Sequence::reference r = c.front(); + + ignore_unused_variable_warning(c); + ignore_unused_variable_warning(c2); + ignore_unused_variable_warning(c3); + ignore_unused_variable_warning(r); + const_constraints(c); + } + private: + void const_constraints(const S& c) { + typename Sequence::const_reference r = c.front(); + ignore_unused_variable_warning(r); + } + + typename S::value_type t; + typename S::size_type n; + typename S::value_type* first, *last; + typename S::iterator p, q; + }; + + BOOST_concept(FrontInsertionSequence,(S)) + : Sequence + { + BOOST_CONCEPT_USAGE(FrontInsertionSequence) + { + c.push_front(t); + c.pop_front(); + } + private: + S c; + typename S::value_type t; + }; + + BOOST_concept(BackInsertionSequence,(S)) + : Sequence + { + BOOST_CONCEPT_USAGE(BackInsertionSequence) + { + c.push_back(t); + c.pop_back(); + typename BackInsertionSequence::reference r = c.back(); + ignore_unused_variable_warning(r); + const_constraints(c); + } + private: + void const_constraints(const S& cc) { + typename BackInsertionSequence::const_reference + r = cc.back(); + ignore_unused_variable_warning(r); + }; + S c; + typename S::value_type t; + }; + + BOOST_concept(AssociativeContainer,(C)) + : ForwardContainer + , DefaultConstructible + { + typedef typename C::key_type key_type; + typedef typename C::key_compare key_compare; + typedef typename C::value_compare value_compare; + typedef typename C::iterator iterator; + + BOOST_CONCEPT_USAGE(AssociativeContainer) + { + i = c.find(k); + r = c.equal_range(k); + c.erase(k); + c.erase(i); + c.erase(r.first, r.second); + const_constraints(c); + BOOST_CONCEPT_ASSERT((BinaryPredicate)); + + typedef typename AssociativeContainer::value_type value_type_; + BOOST_CONCEPT_ASSERT((BinaryPredicate)); + } + + // Redundant with the base concept, but it helps below. + typedef typename C::const_iterator const_iterator; + private: + void const_constraints(const C& cc) + { + ci = cc.find(k); + n = cc.count(k); + cr = cc.equal_range(k); + } + + C c; + iterator i; + std::pair r; + const_iterator ci; + std::pair cr; + typename C::key_type k; + typename C::size_type n; + }; + + BOOST_concept(UniqueAssociativeContainer,(C)) + : AssociativeContainer + { + BOOST_CONCEPT_USAGE(UniqueAssociativeContainer) + { + C c(first, last); + + pos_flag = c.insert(t); + c.insert(first, last); + + ignore_unused_variable_warning(c); + } + private: + std::pair pos_flag; + typename C::value_type t; + typename C::value_type* first, *last; + }; + + BOOST_concept(MultipleAssociativeContainer,(C)) + : AssociativeContainer + { + BOOST_CONCEPT_USAGE(MultipleAssociativeContainer) + { + C c(first, last); + + pos = c.insert(t); + c.insert(first, last); + + ignore_unused_variable_warning(c); + ignore_unused_variable_warning(pos); + } + private: + typename C::iterator pos; + typename C::value_type t; + typename C::value_type* first, *last; + }; + + BOOST_concept(SimpleAssociativeContainer,(C)) + : AssociativeContainer + { + BOOST_CONCEPT_USAGE(SimpleAssociativeContainer) + { + typedef typename C::key_type key_type; + typedef typename C::value_type value_type; + BOOST_MPL_ASSERT((boost::is_same)); + } + }; + + BOOST_concept(PairAssociativeContainer,(C)) + : AssociativeContainer + { + BOOST_CONCEPT_USAGE(PairAssociativeContainer) + { + typedef typename C::key_type key_type; + typedef typename C::value_type value_type; + typedef typename C::mapped_type mapped_type; + typedef std::pair required_value_type; + BOOST_MPL_ASSERT((boost::is_same)); + } + }; + + BOOST_concept(SortedAssociativeContainer,(C)) + : AssociativeContainer + , ReversibleContainer + { + BOOST_CONCEPT_USAGE(SortedAssociativeContainer) + { + C + c(kc), + c2(first, last), + c3(first, last, kc); + + p = c.upper_bound(k); + p = c.lower_bound(k); + r = c.equal_range(k); + + c.insert(p, t); + + ignore_unused_variable_warning(c); + ignore_unused_variable_warning(c2); + ignore_unused_variable_warning(c3); + const_constraints(c); + } + + void const_constraints(const C& c) + { + kc = c.key_comp(); + vc = c.value_comp(); + + cp = c.upper_bound(k); + cp = c.lower_bound(k); + cr = c.equal_range(k); + } + + private: + typename C::key_compare kc; + typename C::value_compare vc; + typename C::value_type t; + typename C::key_type k; + typedef typename C::iterator iterator; + typedef typename C::const_iterator const_iterator; + + typedef SortedAssociativeContainer self; + iterator p; + const_iterator cp; + std::pair r; + std::pair cr; + typename C::value_type* first, *last; + }; + + // HashedAssociativeContainer + +} // namespace boost + +# include + +#endif // BOOST_CONCEPT_CHECKS_HPP + diff --git a/win32/include/boost/concept_check/borland.hpp b/win32/include/boost/concept_check/borland.hpp new file mode 100755 index 000000000..dbb0166b5 --- /dev/null +++ b/win32/include/boost/concept_check/borland.hpp @@ -0,0 +1,25 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP +# define BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP + +namespace boost { + +template +struct concept_check; + +template +struct concept_check +{ + enum { instantiate = sizeof((((Model*)0)->~Model()), 3) }; +}; + +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ + enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + boost::concept_check::instantiate \ + } + +} // namespace boost::concept_checking + +#endif // BOOST_CONCEPT_CHECK_BORLAND_DWA2006429_HPP diff --git a/win32/include/boost/concept_check/general.hpp b/win32/include/boost/concept_check/general.hpp new file mode 100755 index 000000000..06c3b82f9 --- /dev/null +++ b/win32/include/boost/concept_check/general.hpp @@ -0,0 +1,82 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP +# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP + +# ifdef BOOST_OLD_CONCEPT_SUPPORT +# include +# include +# endif + + +// This implementation works on GCC and Comeau, but has actually been +// fairly carefully tuned to work on GCC versions starting with +// gcc-2.95.x. If you're trying to get an additional compiler to pass +// the tests you might consider breaking out a separate gcc.hpp and +// starting over on the general case. +namespace boost +{ + namespace concept_checking + { + template struct instantiate {}; + } + + template struct concept_check_; + + template + void concept_check_failed() + { + ((Model*)0)->~Model(); + } + + template + struct concept_check + { + concept_checking::instantiate > x; + enum { instantiate = 1 }; + }; + +# ifdef BOOST_OLD_CONCEPT_SUPPORT + + template + void constraint_check_failed() + { + ((Model*)0)->constraints(); + } + + template + struct constraint_check + { + concept_checking::instantiate > x; + enum { instantiate = 1 }; + }; + + template + struct concept_check_ + : mpl::if_c< + concept_checking::has_constraints::value + , constraint_check + , concept_check + >::type + {}; + +# else + + template + struct concept_check_ + : concept_check + {}; + +# endif + + // Usage, in class or function context: + // + // BOOST_CONCEPT_ASSERT((UnaryFunctionConcept)); +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ + enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + ::boost::concept_check_::instantiate \ + } +} + +#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP diff --git a/win32/include/boost/concept_check/has_constraints.hpp b/win32/include/boost/concept_check/has_constraints.hpp new file mode 100755 index 000000000..571b18170 --- /dev/null +++ b/win32/include/boost/concept_check/has_constraints.hpp @@ -0,0 +1,31 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP +# define BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP + +namespace boost { namespace concept_checking { + +// Here we implement the "metafunction" that detects whether a +// constraints metafunction exists +typedef char yes; +typedef char (&no)[2]; + +template +struct wrap_constraints {}; + +template +inline yes has_constraints_(Model*, wrap_constraints* = 0); +inline no has_constraints_(...); + +template +struct has_constraints +{ + BOOST_STATIC_CONSTANT( + bool + , value = sizeof( concept_checking::has_constraints_((Model*)0) ) == 1 ); +}; + +}} // namespace boost::concept_checking + +#endif // BOOST_CONCEPT_CHECK_HAS_CONSTRAINTS_DWA2006429_HPP diff --git a/win32/include/boost/concept_check/msvc.hpp b/win32/include/boost/concept_check/msvc.hpp new file mode 100755 index 000000000..513f7bb3d --- /dev/null +++ b/win32/include/boost/concept_check/msvc.hpp @@ -0,0 +1,90 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP +# define BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP + +# ifdef BOOST_OLD_CONCEPT_SUPPORT +# include +# include +# endif + + +namespace boost +{ + namespace concept_checking + { + template + struct concept_check_ + { + virtual void failed(Model* x) + { + x->~Model(); + } + }; + } + +# ifdef BOOST_OLD_CONCEPT_SUPPORT + + namespace concept_checking + { + template + struct constraint_check + { + virtual void failed(Model* x) + { + x->constraints(); + } + }; + } + + template + struct concept_check + : mpl::if_c< + concept_checking::has_constraints::value + , concept_checking::constraint_check + , concept_checking::concept_check_ + >::type + {}; + +# else + + template + struct concept_check + : concept_checking::concept_check_ + {}; + +# endif + +# if BOOST_WORKAROUND(BOOST_MSVC, == 1310) + + // + // The iterator library sees some really strange errors unless we + // use partial specialization to extract the model type with + // msvc-7.1 + // + template + struct concept_check + : concept_check + { }; + +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ + enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + sizeof(::boost::concept_check) \ + } + +# else + + template + concept_check + concept_check_(void(*)(Model)); + +# define BOOST_CONCEPT_ASSERT( ModelInParens ) \ + enum { BOOST_PP_CAT(boost_concept_check,__LINE__) = \ + sizeof(::boost::concept_check_((void(*) ModelInParens)0)) \ + } + +# endif +} + +#endif // BOOST_CONCEPT_CHECK_MSVC_DWA2006429_HPP diff --git a/win32/include/boost/config.hpp b/win32/include/boost/config.hpp new file mode 100755 index 000000000..cb5037afd --- /dev/null +++ b/win32/include/boost/config.hpp @@ -0,0 +1,70 @@ +// Boost config.hpp configuration header file ------------------------------// + +// (C) Copyright John Maddock 2002. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org/libs/config for most recent version. + +// Boost config.hpp policy and rationale documentation has been moved to +// http://www.boost.org/libs/config +// +// CAUTION: This file is intended to be completely stable - +// DO NOT MODIFY THIS FILE! +// + +#ifndef BOOST_CONFIG_HPP +#define BOOST_CONFIG_HPP + +// if we don't have a user config, then use the default location: +#if !defined(BOOST_USER_CONFIG) && !defined(BOOST_NO_USER_CONFIG) +# define BOOST_USER_CONFIG +#endif +// include it first: +#ifdef BOOST_USER_CONFIG +# include BOOST_USER_CONFIG +#endif + +// if we don't have a compiler config set, try and find one: +#if !defined(BOOST_COMPILER_CONFIG) && !defined(BOOST_NO_COMPILER_CONFIG) && !defined(BOOST_NO_CONFIG) +# include +#endif +// if we have a compiler config, include it now: +#ifdef BOOST_COMPILER_CONFIG +# include BOOST_COMPILER_CONFIG +#endif + +// if we don't have a std library config set, try and find one: +#if !defined(BOOST_STDLIB_CONFIG) && !defined(BOOST_NO_STDLIB_CONFIG) && !defined(BOOST_NO_CONFIG) +# include +#endif +// if we have a std library config, include it now: +#ifdef BOOST_STDLIB_CONFIG +# include BOOST_STDLIB_CONFIG +#endif + +// if we don't have a platform config set, try and find one: +#if !defined(BOOST_PLATFORM_CONFIG) && !defined(BOOST_NO_PLATFORM_CONFIG) && !defined(BOOST_NO_CONFIG) +# include +#endif +// if we have a platform config, include it now: +#ifdef BOOST_PLATFORM_CONFIG +# include BOOST_PLATFORM_CONFIG +#endif + +// get config suffix code: +#include + +#endif // BOOST_CONFIG_HPP + + + + + + + + + + + diff --git a/win32/include/boost/config/abi/borland_prefix.hpp b/win32/include/boost/config/abi/borland_prefix.hpp new file mode 100755 index 000000000..614819510 --- /dev/null +++ b/win32/include/boost/config/abi/borland_prefix.hpp @@ -0,0 +1,27 @@ +// (C) Copyright John Maddock 2003. +// Use, modification and distribution are subject to 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) + +// for C++ Builder the following options effect the ABI: +// +// -b (on or off - effect emum sizes) +// -Vx (on or off - empty members) +// -Ve (on or off - empty base classes) +// -aX (alignment - 5 options). +// -pX (Calling convention - 4 options) +// -VmX (member pointer size and layout - 5 options) +// -VC (on or off, changes name mangling) +// -Vl (on or off, changes struct layout). + +// In addition the following warnings are sufficiently annoying (and +// unfixable) to have them turned off by default: +// +// 8027 - functions containing [for|while] loops are not expanded inline +// 8026 - functions taking class by value arguments are not expanded inline + +#pragma nopushoptwarn +# pragma option push -Vx -Ve -a8 -b -pc -Vmv -VC- -Vl- -w-8027 -w-8026 + + + diff --git a/win32/include/boost/config/abi/borland_suffix.hpp b/win32/include/boost/config/abi/borland_suffix.hpp new file mode 100755 index 000000000..110b3c35f --- /dev/null +++ b/win32/include/boost/config/abi/borland_suffix.hpp @@ -0,0 +1,12 @@ +// (C) Copyright John Maddock 2003. +// Use, modification and distribution are subject to 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) + +# pragma option pop +#pragma nopushoptwarn + + + + + diff --git a/win32/include/boost/config/abi/msvc_prefix.hpp b/win32/include/boost/config/abi/msvc_prefix.hpp new file mode 100755 index 000000000..7f80cc9c6 --- /dev/null +++ b/win32/include/boost/config/abi/msvc_prefix.hpp @@ -0,0 +1,8 @@ +// (C) Copyright John Maddock 2003. +// Use, modification and distribution are subject to 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) + +#pragma pack(push,8) + + diff --git a/win32/include/boost/config/abi/msvc_suffix.hpp b/win32/include/boost/config/abi/msvc_suffix.hpp new file mode 100755 index 000000000..8c1edd056 --- /dev/null +++ b/win32/include/boost/config/abi/msvc_suffix.hpp @@ -0,0 +1,8 @@ +// (C) Copyright John Maddock 2003. +// Use, modification and distribution are subject to 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) + +#pragma pack(pop) + + diff --git a/win32/include/boost/config/abi_prefix.hpp b/win32/include/boost/config/abi_prefix.hpp new file mode 100755 index 000000000..10cf51d62 --- /dev/null +++ b/win32/include/boost/config/abi_prefix.hpp @@ -0,0 +1,25 @@ +// abi_prefix header -------------------------------------------------------// + +// (c) Copyright John Maddock 2003 + +// Use, modification and distribution are subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt). + +#ifndef BOOST_CONFIG_ABI_PREFIX_HPP +# define BOOST_CONFIG_ABI_PREFIX_HPP +#else +# error double inclusion of header boost/config/abi_prefix.hpp is an error +#endif + +#include + +// this must occur after all other includes and before any code appears: +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +#if defined( __BORLANDC__ ) +#pragma nopushoptwarn +#endif + diff --git a/win32/include/boost/config/abi_suffix.hpp b/win32/include/boost/config/abi_suffix.hpp new file mode 100755 index 000000000..21da961fd --- /dev/null +++ b/win32/include/boost/config/abi_suffix.hpp @@ -0,0 +1,27 @@ +// abi_sufffix header -------------------------------------------------------// + +// (c) Copyright John Maddock 2003 + +// Use, modification and distribution are subject to 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). + +// This header should be #included AFTER code that was preceded by a #include +// . + +#ifndef BOOST_CONFIG_ABI_PREFIX_HPP +# error Header boost/config/abi_suffix.hpp must only be used after boost/config/abi_prefix.hpp +#else +# undef BOOST_CONFIG_ABI_PREFIX_HPP +#endif + +// the suffix header occurs after all of our code: +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#if defined( __BORLANDC__ ) +#pragma nopushoptwarn +#endif + + diff --git a/win32/include/boost/config/auto_link.hpp b/win32/include/boost/config/auto_link.hpp new file mode 100755 index 000000000..c340a3451 --- /dev/null +++ b/win32/include/boost/config/auto_link.hpp @@ -0,0 +1,368 @@ +// (C) Copyright John Maddock 2003. +// Use, modification and distribution are subject to 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) + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE auto_link.hpp + * VERSION see + * DESCRIPTION: Automatic library inclusion for Borland/Microsoft compilers. + */ + +/************************************************************************* + +USAGE: +~~~~~~ + +Before including this header you must define one or more of define the following macros: + +BOOST_LIB_NAME: Required: A string containing the basename of the library, + for example boost_regex. +BOOST_LIB_TOOLSET: Optional: the base name of the toolset. +BOOST_DYN_LINK: Optional: when set link to dll rather than static library. +BOOST_LIB_DIAGNOSTIC: Optional: when set the header will print out the name + of the library selected (useful for debugging). +BOOST_AUTO_LINK_NOMANGLE: Specifies that we should link to BOOST_LIB_NAME.lib, + rather than a mangled-name version. + +These macros will be undef'ed at the end of the header, further this header +has no include guards - so be sure to include it only once from your library! + +Algorithm: +~~~~~~~~~~ + +Libraries for Borland and Microsoft compilers are automatically +selected here, the name of the lib is selected according to the following +formula: + +BOOST_LIB_PREFIX + + BOOST_LIB_NAME + + "_" + + BOOST_LIB_TOOLSET + + BOOST_LIB_THREAD_OPT + + BOOST_LIB_RT_OPT + "-" + + BOOST_LIB_VERSION + +These are defined as: + +BOOST_LIB_PREFIX: "lib" for static libraries otherwise "". + +BOOST_LIB_NAME: The base name of the lib ( for example boost_regex). + +BOOST_LIB_TOOLSET: The compiler toolset name (vc6, vc7, bcb5 etc). + +BOOST_LIB_THREAD_OPT: "-mt" for multithread builds, otherwise nothing. + +BOOST_LIB_RT_OPT: A suffix that indicates the runtime library used, + contains one or more of the following letters after + a hiphen: + + s static runtime (dynamic if not present). + d debug build (release if not present). + g debug/diagnostic runtime (release if not present). + p STLPort Build. + +BOOST_LIB_VERSION: The Boost version, in the form x_y, for Boost version x.y. + + +***************************************************************************/ + +#ifdef __cplusplus +# ifndef BOOST_CONFIG_HPP +# include +# endif +#elif defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__EDG_VERSION__) +// +// C language compatability (no, honestly) +// +# define BOOST_MSVC _MSC_VER +# define BOOST_STRINGIZE(X) BOOST_DO_STRINGIZE(X) +# define BOOST_DO_STRINGIZE(X) #X +#endif +// +// Only include what follows for known and supported compilers: +// +#if defined(BOOST_MSVC) \ + || defined(__BORLANDC__) \ + || (defined(__MWERKS__) && defined(_WIN32) && (__MWERKS__ >= 0x3000)) \ + || (defined(__ICL) && defined(_MSC_EXTENSIONS) && (_MSC_VER >= 1200)) + +#ifndef BOOST_VERSION_HPP +# include +#endif + +#ifndef BOOST_LIB_NAME +# error "Macro BOOST_LIB_NAME not set (internal error)" +#endif + +// +// error check: +// +#if defined(__MSVC_RUNTIME_CHECKS) && !defined(_DEBUG) +# pragma message("Using the /RTC option without specifying a debug runtime will lead to linker errors") +# pragma message("Hint: go to the code generation options and switch to one of the debugging runtimes") +# error "Incompatible build options" +#endif +// +// select toolset if not defined already: +// +#ifndef BOOST_LIB_TOOLSET +// Note: no compilers before 1200 are supported +#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) + +# ifdef UNDER_CE + // vc6: +# define BOOST_LIB_TOOLSET "evc4" +# else + // vc6: +# define BOOST_LIB_TOOLSET "vc6" +# endif + +#elif defined(BOOST_MSVC) && (BOOST_MSVC == 1300) + + // vc7: +# define BOOST_LIB_TOOLSET "vc7" + +#elif defined(BOOST_MSVC) && (BOOST_MSVC == 1310) + + // vc71: +# define BOOST_LIB_TOOLSET "vc71" + +#elif defined(BOOST_MSVC) && (BOOST_MSVC == 1400) + + // vc80: +# define BOOST_LIB_TOOLSET "vc80" + +#elif defined(BOOST_MSVC) && (BOOST_MSVC >= 1500) + + // vc90: +# define BOOST_LIB_TOOLSET "vc90" + +#elif defined(__BORLANDC__) + + // CBuilder 6: +# define BOOST_LIB_TOOLSET "bcb" + +#elif defined(__ICL) + + // Intel C++, no version number: +# define BOOST_LIB_TOOLSET "iw" + +#elif defined(__MWERKS__) && (__MWERKS__ <= 0x31FF ) + + // Metrowerks CodeWarrior 8.x +# define BOOST_LIB_TOOLSET "cw8" + +#elif defined(__MWERKS__) && (__MWERKS__ <= 0x32FF ) + + // Metrowerks CodeWarrior 9.x +# define BOOST_LIB_TOOLSET "cw9" + +#endif +#endif // BOOST_LIB_TOOLSET + +// +// select thread opt: +// +#if defined(_MT) || defined(__MT__) +# define BOOST_LIB_THREAD_OPT "-mt" +#else +# define BOOST_LIB_THREAD_OPT +#endif + +#if defined(_MSC_VER) || defined(__MWERKS__) + +# ifdef _DLL + +# if (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) && (defined(_STLP_OWN_IOSTREAMS) || defined(__STL_OWN_IOSTREAMS)) + +# if defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG)) +# define BOOST_LIB_RT_OPT "-gdp" +# elif defined(_DEBUG) +# define BOOST_LIB_RT_OPT "-gdp" +# pragma message("warning: STLPort debug versions are built with /D_STLP_DEBUG=1") +# error "Build options aren't compatible with pre-built libraries" +# else +# define BOOST_LIB_RT_OPT "-p" +# endif + +# elif defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION) + +# if defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG)) +# define BOOST_LIB_RT_OPT "-gdpn" +# elif defined(_DEBUG) +# define BOOST_LIB_RT_OPT "-gdpn" +# pragma message("warning: STLPort debug versions are built with /D_STLP_DEBUG=1") +# error "Build options aren't compatible with pre-built libraries" +# else +# define BOOST_LIB_RT_OPT "-pn" +# endif + +# else + +# if defined(_DEBUG) +# define BOOST_LIB_RT_OPT "-gd" +# else +# define BOOST_LIB_RT_OPT +# endif + +# endif + +# else + +# if (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) && (defined(_STLP_OWN_IOSTREAMS) || defined(__STL_OWN_IOSTREAMS)) + +# if defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG)) +# define BOOST_LIB_RT_OPT "-sgdp" +# elif defined(_DEBUG) +# define BOOST_LIB_RT_OPT "-sgdp" +# pragma message("warning: STLPort debug versions are built with /D_STLP_DEBUG=1") +# error "Build options aren't compatible with pre-built libraries" +# else +# define BOOST_LIB_RT_OPT "-sp" +# endif + +# elif defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION) + +# if defined(_DEBUG) && (defined(__STL_DEBUG) || defined(_STLP_DEBUG)) +# define BOOST_LIB_RT_OPT "-sgdpn" +# elif defined(_DEBUG) +# define BOOST_LIB_RT_OPT "-sgdpn" +# pragma message("warning: STLPort debug versions are built with /D_STLP_DEBUG=1") +# error "Build options aren't compatible with pre-built libraries" +# else +# define BOOST_LIB_RT_OPT "-spn" +# endif + +# else + +# if defined(_DEBUG) +# define BOOST_LIB_RT_OPT "-sgd" +# else +# define BOOST_LIB_RT_OPT "-s" +# endif + +# endif + +# endif + +#elif defined(__BORLANDC__) + +// +// figure out whether we want the debug builds or not: +// +#if __BORLANDC__ > 0x561 +#pragma defineonoption BOOST_BORLAND_DEBUG -v +#endif +// +// sanity check: +// +#if defined(__STL_DEBUG) || defined(_STLP_DEBUG) +#error "Pre-built versions of the Boost libraries are not provided in STLPort-debug form" +#endif + +# ifdef _RTLDLL + +# ifdef BOOST_BORLAND_DEBUG +# define BOOST_LIB_RT_OPT "-d" +# else +# define BOOST_LIB_RT_OPT +# endif + +# else + +# ifdef BOOST_BORLAND_DEBUG +# define BOOST_LIB_RT_OPT "-sd" +# else +# define BOOST_LIB_RT_OPT "-s" +# endif + +# endif + +#endif + +// +// select linkage opt: +// +#if (defined(_DLL) || defined(_RTLDLL)) && defined(BOOST_DYN_LINK) +# define BOOST_LIB_PREFIX +#elif defined(BOOST_DYN_LINK) +# error "Mixing a dll boost library with a static runtime is a really bad idea..." +#else +# define BOOST_LIB_PREFIX "lib" +#endif + +// +// now include the lib: +// +#if defined(BOOST_LIB_NAME) \ + && defined(BOOST_LIB_PREFIX) \ + && defined(BOOST_LIB_TOOLSET) \ + && defined(BOOST_LIB_THREAD_OPT) \ + && defined(BOOST_LIB_RT_OPT) \ + && defined(BOOST_LIB_VERSION) + +#ifndef BOOST_AUTO_LINK_NOMANGLE +# pragma comment(lib, BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT "-" BOOST_LIB_VERSION ".lib") +# ifdef BOOST_LIB_DIAGNOSTIC +# pragma message ("Linking to lib file: " BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT "-" BOOST_LIB_VERSION ".lib") +# endif +#else +# pragma comment(lib, BOOST_STRINGIZE(BOOST_LIB_NAME) ".lib") +# ifdef BOOST_LIB_DIAGNOSTIC +# pragma message ("Linking to lib file: " BOOST_STRINGIZE(BOOST_LIB_NAME) ".lib") +# endif +#endif + +#else +# error "some required macros where not defined (internal logic error)." +#endif + + +#endif // _MSC_VER || __BORLANDC__ + +// +// finally undef any macros we may have set: +// +#ifdef BOOST_LIB_PREFIX +# undef BOOST_LIB_PREFIX +#endif +#if defined(BOOST_LIB_NAME) +# undef BOOST_LIB_NAME +#endif +// Don't undef this one: it can be set by the user and should be the +// same for all libraries: +//#if defined(BOOST_LIB_TOOLSET) +//# undef BOOST_LIB_TOOLSET +//#endif +#if defined(BOOST_LIB_THREAD_OPT) +# undef BOOST_LIB_THREAD_OPT +#endif +#if defined(BOOST_LIB_RT_OPT) +# undef BOOST_LIB_RT_OPT +#endif +#if defined(BOOST_LIB_LINK_OPT) +# undef BOOST_LIB_LINK_OPT +#endif +#if defined(BOOST_LIB_DEBUG_OPT) +# undef BOOST_LIB_DEBUG_OPT +#endif +#if defined(BOOST_DYN_LINK) +# undef BOOST_DYN_LINK +#endif +#if defined(BOOST_AUTO_LINK_NOMANGLE) +# undef BOOST_AUTO_LINK_NOMANGLE +#endif + + + + + + + + + + + diff --git a/win32/include/boost/config/compiler/borland.hpp b/win32/include/boost/config/compiler/borland.hpp new file mode 100755 index 000000000..6e2461cec --- /dev/null +++ b/win32/include/boost/config/compiler/borland.hpp @@ -0,0 +1,209 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright David Abrahams 2002 - 2003. +// (C) Copyright Aleksey Gurtovoy 2002. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Borland C++ compiler setup: + +// +// versions check: +// we don't support Borland prior to version 5.4: +#if __BORLANDC__ < 0x540 +# error "Compiler not supported or configured - please reconfigure" +#endif + +// last known and checked version is 0x600 (Builder X preview) +// or 0x593 (CodeGear C++ Builder 2007 December 2007 update): +#if (__BORLANDC__ > 0x593) && (__BORLANDC__ != 0x600) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# else +# pragma message( "Unknown compiler version - please run the configure tests and report the results") +# endif +#endif + +// +// Support macros to help with standard library detection +#if (__BORLANDC__ < 0x560) || defined(_USE_OLD_RW_STL) +# define BOOST_BCB_WITH_ROGUE_WAVE +#elif __BORLANDC__ < 0x570 +# define BOOST_BCB_WITH_STLPORT +#else +# define BOOST_BCB_WITH_DINKUMWARE +#endif + +// +// Version 5.0 and below: +# if __BORLANDC__ <= 0x0550 +// Borland C++Builder 4 and 5: +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# if __BORLANDC__ == 0x0550 +// Borland C++Builder 5, command-line compiler 5.5: +# define BOOST_NO_OPERATORS_IN_NAMESPACE +# endif +# endif + +// Version 5.51 and below: +#if (__BORLANDC__ <= 0x551) +# define BOOST_NO_CV_SPECIALIZATIONS +# define BOOST_NO_CV_VOID_SPECIALIZATIONS +# define BOOST_NO_DEDUCED_TYPENAME +// workaround for missing WCHAR_MAX/WCHAR_MIN: +#include +#include +#ifndef WCHAR_MAX +# define WCHAR_MAX 0xffff +#endif +#ifndef WCHAR_MIN +# define WCHAR_MIN 0 +#endif +#endif + +// Borland C++ Builder 6 and below: +#if (__BORLANDC__ <= 0x564) +# define BOOST_NO_INTEGRAL_INT64_T + +# ifdef NDEBUG + // fix broken so that Boost.test works: +# include +# undef strcmp +# endif + // fix broken errno declaration: +# include +# ifndef errno +# define errno errno +# endif + +#endif + +// +// new bug in 5.61: +#if (__BORLANDC__ >= 0x561) && (__BORLANDC__ <= 0x580) + // this seems to be needed by the command line compiler, but not the IDE: +# define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS +#endif + +// Borland C++ Builder 2006 Update 2 and below: +#if (__BORLANDC__ <= 0x582) +# define BOOST_NO_SFINAE +# define BOOST_BCB_PARTIAL_SPECIALIZATION_BUG +# define BOOST_NO_TEMPLATE_TEMPLATES + +# define BOOST_NO_PRIVATE_IN_AGGREGATE + +# ifdef _WIN32 +# define BOOST_NO_SWPRINTF +# elif defined(linux) || defined(__linux__) || defined(__linux) + // we should really be able to do without this + // but the wcs* functions aren't imported into std:: +# define BOOST_NO_STDC_NAMESPACE + // _CPPUNWIND doesn't get automatically set for some reason: +# pragma defineonoption BOOST_CPPUNWIND -x +# endif +#endif + +// Borland C++ Builder 2007 December 2007 Update and below: +#if (__BORLANDC__ <= 0x593) +# define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS +# define BOOST_NO_USING_TEMPLATE +# define BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS + // we shouldn't really need this - but too many things choke + // without it, this needs more investigation: +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +# define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL +# define BOOST_NO_IS_ABSTRACT +# define BOOST_NO_FUNCTION_TYPE_SPECIALIZATIONS +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP + +// Temporary workaround +#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS + +#endif + +#if __BORLANDC__ >= 0x590 +# define BOOST_HAS_TR1_HASH + +# define BOOST_HAS_MACRO_USE_FACET +#endif + +// +// Post 0x561 we have long long and stdint.h: +#if __BORLANDC__ >= 0x561 +# ifndef __NO_LONG_LONG +# define BOOST_HAS_LONG_LONG +# endif + // On non-Win32 platforms let the platform config figure this out: +# ifdef _WIN32 +# define BOOST_HAS_STDINT_H +# endif +#endif + +// Borland C++Builder 6 defaults to using STLPort. If _USE_OLD_RW_STL is +// defined, then we have 0x560 or greater with the Rogue Wave implementation +// which presumably has the std::DBL_MAX bug. +#if defined( BOOST_BCB_WITH_ROGUE_WAVE ) +// is partly broken, some macros define symbols that are really in +// namespace std, so you end up having to use illegal constructs like +// std::DBL_MAX, as a fix we'll just include float.h and have done with: +#include +#endif +// +// __int64: +// +#if (__BORLANDC__ >= 0x530) && !defined(__STRICT_ANSI__) +# define BOOST_HAS_MS_INT64 +#endif +// +// check for exception handling support: +// +#if !defined(_CPPUNWIND) && !defined(BOOST_CPPUNWIND) && !defined(__EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +#endif +// +// all versions have a : +// +#ifndef __STRICT_ANSI__ +# define BOOST_HAS_DIRENT_H +#endif +// +// all versions support __declspec: +// +#ifndef __STRICT_ANSI__ +# define BOOST_HAS_DECLSPEC +#endif +// +// ABI fixing headers: +// +#if __BORLANDC__ < 0x600 // not implemented for version 6 compiler yet +#ifndef BOOST_ABI_PREFIX +# define BOOST_ABI_PREFIX "boost/config/abi/borland_prefix.hpp" +#endif +#ifndef BOOST_ABI_SUFFIX +# define BOOST_ABI_SUFFIX "boost/config/abi/borland_suffix.hpp" +#endif +#endif +// +// Disable Win32 support in ANSI mode: +// +#if __BORLANDC__ < 0x600 +# pragma defineonoption BOOST_DISABLE_WIN32 -A +#elif defined(__STRICT_ANSI__) +# define BOOST_DISABLE_WIN32 +#endif +// +// MSVC compatibility mode does some nasty things: +// TODO: look up if this doesn't apply to the whole 12xx range +// +#if defined(_MSC_VER) && (_MSC_VER <= 1200) +# define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +# define BOOST_NO_VOID_RETURNS +#endif + +#define BOOST_COMPILER "Borland C++ version " BOOST_STRINGIZE(__BORLANDC__) + + diff --git a/win32/include/boost/config/compiler/comeau.hpp b/win32/include/boost/config/compiler/comeau.hpp new file mode 100755 index 000000000..c2cb68ca8 --- /dev/null +++ b/win32/include/boost/config/compiler/comeau.hpp @@ -0,0 +1,59 @@ +// (C) Copyright John Maddock 2001. +// (C) Copyright Douglas Gregor 2001. +// (C) Copyright Peter Dimov 2001. +// (C) Copyright Aleksey Gurtovoy 2003. +// (C) Copyright Beman Dawes 2003. +// (C) Copyright Jens Maurer 2003. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Comeau C++ compiler setup: + +#include "boost/config/compiler/common_edg.hpp" + +#if (__COMO_VERSION__ <= 4245) + +# if defined(_MSC_VER) && _MSC_VER <= 1300 +# if _MSC_VER > 100 + // only set this in non-strict mode: +# define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +# endif +# endif + +// Void returns don't work when emulating VC 6 (Peter Dimov) +// TODO: look up if this doesn't apply to the whole 12xx range +# if defined(_MSC_VER) && (_MSC_VER < 1300) +# define BOOST_NO_VOID_RETURNS +# endif + +#endif // version 4245 + +// +// enable __int64 support in VC emulation mode +// +# if defined(_MSC_VER) && (_MSC_VER >= 1200) +# define BOOST_HAS_MS_INT64 +# endif + +#define BOOST_COMPILER "Comeau compiler version " BOOST_STRINGIZE(__COMO_VERSION__) + +// +// versions check: +// we don't know Comeau prior to version 4245: +#if __COMO_VERSION__ < 4245 +# error "Compiler not configured - please reconfigure" +#endif +// +// last known and checked version is 4245: +#if (__COMO_VERSION__ > 4245) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + + + diff --git a/win32/include/boost/config/compiler/common_edg.hpp b/win32/include/boost/config/compiler/common_edg.hpp new file mode 100755 index 000000000..0a1fdf473 --- /dev/null +++ b/win32/include/boost/config/compiler/common_edg.hpp @@ -0,0 +1,62 @@ +// (C) Copyright John Maddock 2001 - 2002. +// (C) Copyright Jens Maurer 2001. +// (C) Copyright David Abrahams 2002. +// (C) Copyright Aleksey Gurtovoy 2002. +// (C) Copyright Markus Schoepflin 2005. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// +// Options common to all edg based compilers. +// +// This is included from within the individual compiler mini-configs. + +#ifndef __EDG_VERSION__ +# error This file requires that __EDG_VERSION__ be defined. +#endif + +#if (__EDG_VERSION__ <= 238) +# define BOOST_NO_INTEGRAL_INT64_T +# define BOOST_NO_SFINAE +#endif + +#if (__EDG_VERSION__ <= 240) +# define BOOST_NO_VOID_RETURNS +#endif + +#if (__EDG_VERSION__ <= 241) && !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +# define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +#endif + +#if (__EDG_VERSION__ <= 244) && !defined(BOOST_NO_TEMPLATE_TEMPLATES) +# define BOOST_NO_TEMPLATE_TEMPLATES +#endif + +#if (__EDG_VERSION__ < 300) && !defined(BOOST_NO_IS_ABSTRACT) +# define BOOST_NO_IS_ABSTRACT +#endif + +#if (__EDG_VERSION__ <= 303) && !defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL) +# define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL +#endif + +// See also kai.hpp which checks a Kai-specific symbol for EH +# if !defined(__KCC) && !defined(__EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +# endif + +# if !defined(__NO_LONG_LONG) +# define BOOST_HAS_LONG_LONG +# endif + +#ifdef c_plusplus +// EDG has "long long" in non-strict mode +// However, some libraries have insufficient "long long" support +// #define BOOST_HAS_LONG_LONG +#endif + + + diff --git a/win32/include/boost/config/compiler/compaq_cxx.hpp b/win32/include/boost/config/compiler/compaq_cxx.hpp new file mode 100755 index 000000000..8fb73fbae --- /dev/null +++ b/win32/include/boost/config/compiler/compaq_cxx.hpp @@ -0,0 +1,19 @@ +// (C) Copyright John Maddock 2001 - 2003. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Tru64 C++ compiler setup (now HP): + +#define BOOST_COMPILER "HP Tru64 C++ " BOOST_STRINGIZE(__DECCXX_VER) + +#include "boost/config/compiler/common_edg.hpp" + +// +// versions check: +// Nothing to do here? + + + diff --git a/win32/include/boost/config/compiler/digitalmars.hpp b/win32/include/boost/config/compiler/digitalmars.hpp new file mode 100755 index 000000000..41f49a8b6 --- /dev/null +++ b/win32/include/boost/config/compiler/digitalmars.hpp @@ -0,0 +1,67 @@ +// Copyright (C) Christof Meerwald 2003 +// Copyright (C) Dan Watkins 2003 +// +// Use, modification and distribution are subject to 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) + +// Digital Mars C++ compiler setup: +#define BOOST_COMPILER __DMC_VERSION_STRING__ + +#define BOOST_HAS_LONG_LONG +#define BOOST_HAS_PRAGMA_ONCE + +#if (__DMC__ <= 0x833) +#define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL +#define BOOST_NO_TEMPLATE_TEMPLATES +#define BOOST_NEEDS_TOKEN_PASTING_OP_FOR_TOKENS_JUXTAPOSING +#define BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS +#define BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS +#endif +#if (__DMC__ <= 0x840) || !defined(BOOST_STRICT_CONFIG) +#define BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS +#define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +#define BOOST_NO_OPERATORS_IN_NAMESPACE +#define BOOST_NO_UNREACHABLE_RETURN_DETECTION +#define BOOST_NO_SFINAE +#define BOOST_NO_USING_TEMPLATE +#define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL +#endif + +// +// has macros: +#if (__DMC__ >= 0x840) +#define BOOST_HAS_DIRENT_H +#define BOOST_HAS_STDINT_H +#define BOOST_HAS_WINTHREADS +#endif + +#if (__DMC__ >= 0x847) +#define BOOST_HAS_EXPM1 +#define BOOST_HAS_LOG1P +#endif + +// +// Is this really the best way to detect whether the std lib is in namespace std? +// +#include +#if !defined(__STL_IMPORT_VENDOR_CSTD) && !defined(_STLP_IMPORT_VENDOR_CSTD) +# define BOOST_NO_STDC_NAMESPACE +#endif + + +// check for exception handling support: +#ifndef _CPPUNWIND +# define BOOST_NO_EXCEPTIONS +#endif + +#if __DMC__ < 0x800 +#error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is ...: +#if (__DMC__ > 0x848) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif diff --git a/win32/include/boost/config/compiler/gcc.hpp b/win32/include/boost/config/compiler/gcc.hpp new file mode 100755 index 000000000..c71870f62 --- /dev/null +++ b/win32/include/boost/config/compiler/gcc.hpp @@ -0,0 +1,149 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Darin Adler 2001 - 2002. +// (C) Copyright Jens Maurer 2001 - 2002. +// (C) Copyright Beman Dawes 2001 - 2003. +// (C) Copyright Douglas Gregor 2002. +// (C) Copyright David Abrahams 2002 - 2003. +// (C) Copyright Synge Todo 2003. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// GNU C++ compiler setup: + +#if __GNUC__ < 3 +# if __GNUC_MINOR__ == 91 + // egcs 1.1 won't parse shared_ptr.hpp without this: +# define BOOST_NO_AUTO_PTR +# endif +# if __GNUC_MINOR__ < 95 + // + // Prior to gcc 2.95 member templates only partly + // work - define BOOST_MSVC6_MEMBER_TEMPLATES + // instead since inline member templates mostly work. + // +# define BOOST_NO_MEMBER_TEMPLATES +# if __GNUC_MINOR__ >= 9 +# define BOOST_MSVC6_MEMBER_TEMPLATES +# endif +# endif + +# if __GNUC_MINOR__ < 96 +# define BOOST_NO_SFINAE +# endif + +# if __GNUC_MINOR__ <= 97 +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# define BOOST_NO_OPERATORS_IN_NAMESPACE +# endif + +# define BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE +# define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL +# define BOOST_NO_IS_ABSTRACT +#elif __GNUC__ == 3 +# if defined (__PATHSCALE__) +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +# define BOOST_NO_IS_ABSTRACT +# endif + // + // gcc-3.x problems: + // + // Bug specific to gcc 3.1 and 3.2: + // +# if ((__GNUC_MINOR__ == 1) || (__GNUC_MINOR__ == 2)) +# define BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS +# endif +# if __GNUC_MINOR__ < 4 +# define BOOST_NO_IS_ABSTRACT +# endif +#endif +#if __GNUC__ < 4 +// +// All problems to gcc-3.x and earlier here: +// +#define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#endif + +#ifndef __EXCEPTIONS +# define BOOST_NO_EXCEPTIONS +#endif + + +// +// Threading support: Turn this on unconditionally here (except for +// those platforms where we can know for sure). It will get turned off again +// later if no threading API is detected. +// +#if !defined(__MINGW32__) && !defined(linux) && !defined(__linux) && !defined(__linux__) +# define BOOST_HAS_THREADS +#endif + +// +// gcc has "long long" +// +#define BOOST_HAS_LONG_LONG + +// +// gcc implements the named return value optimization since version 3.1 +// +#if __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 1 ) +#define BOOST_HAS_NRVO +#endif + +// +// C++0x features +// +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2) +// C++0x features are only enabled when -std=c++0x or -std=gnu++0x are +// passed on the command line, which in turn defines +// __GXX_EXPERIMENTAL_CXX0X__. +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_HAS_STATIC_ASSERT +# define BOOST_HAS_VARIADIC_TMPL +# define BOOST_HAS_RVALUE_REFS +# define BOOST_HAS_DECLTYPE +# endif +#endif + +// +// Potential C++0x features +// + +// Variadic templates compiler: +// http://www.generic-programming.org/~dgregor/cpp/variadic-templates.html +#ifdef __VARIADIC_TEMPLATES +# define BOOST_HAS_VARIADIC_TMPL +#endif + +// ConceptGCC compiler: +// http://www.generic-programming.org/software/ConceptGCC/ +#ifdef __GXX_CONCEPTS__ +# define BOOST_HAS_CONCEPTS +# define BOOST_COMPILER "ConceptGCC version " __VERSION__ +#endif + +#ifndef BOOST_COMPILER +# define BOOST_COMPILER "GNU C++ version " __VERSION__ +#endif + +// +// versions check: +// we don't know gcc prior to version 2.90: +#if (__GNUC__ == 2) && (__GNUC_MINOR__ < 90) +# error "Compiler not configured - please reconfigure" +#endif +// +// last known and checked version is 4.3 (Pre-release): +#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 3)) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# else +// we don't emit warnings here anymore since there are no defect macros defined for +// gcc post 3.4, so any failures are gcc regressions... +//# warning "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + diff --git a/win32/include/boost/config/compiler/gcc_xml.hpp b/win32/include/boost/config/compiler/gcc_xml.hpp new file mode 100755 index 000000000..76954a9f7 --- /dev/null +++ b/win32/include/boost/config/compiler/gcc_xml.hpp @@ -0,0 +1,30 @@ +// (C) Copyright John Maddock 2006. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// GCC-XML C++ compiler setup: + +# if !defined(__GCCXML_GNUC__) || ((__GCCXML_GNUC__ <= 3) && (__GCCXML_GNUC_MINOR__ <= 3)) +# define BOOST_NO_IS_ABSTRACT +# endif + +// +// Threading support: Turn this on unconditionally here (except for +// those platforms where we can know for sure). It will get turned off again +// later if no threading API is detected. +// +#if !defined(__MINGW32__) && !defined(_MSC_VER) && !defined(linux) && !defined(__linux) && !defined(__linux__) +# define BOOST_HAS_THREADS +#endif + +// +// gcc has "long long" +// +#define BOOST_HAS_LONG_LONG + +#define BOOST_COMPILER "GCC-XML C++ version " __GCCXML__ + + diff --git a/win32/include/boost/config/compiler/greenhills.hpp b/win32/include/boost/config/compiler/greenhills.hpp new file mode 100755 index 000000000..1dd89d1f0 --- /dev/null +++ b/win32/include/boost/config/compiler/greenhills.hpp @@ -0,0 +1,28 @@ +// (C) Copyright John Maddock 2001. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Greenhills C++ compiler setup: + +#define BOOST_COMPILER "Greenhills C++ version " BOOST_STRINGIZE(__ghs) + +#include "boost/config/compiler/common_edg.hpp" + +// +// versions check: +// we don't support Greenhills prior to version 0: +#if __ghs < 0 +# error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 0: +#if (__ghs > 0) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + diff --git a/win32/include/boost/config/compiler/hp_acc.hpp b/win32/include/boost/config/compiler/hp_acc.hpp new file mode 100755 index 000000000..a0798d765 --- /dev/null +++ b/win32/include/boost/config/compiler/hp_acc.hpp @@ -0,0 +1,95 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2001 - 2003. +// (C) Copyright Aleksey Gurtovoy 2002. +// (C) Copyright David Abrahams 2002 - 2003. +// (C) Copyright Toon Knapen 2003. +// (C) Copyright Boris Gubenko 2006 - 2007. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// HP aCC C++ compiler setup: + +#if defined(__EDG__) +#include "boost/config/compiler/common_edg.hpp" +#endif + +#if (__HP_aCC <= 33100) +# define BOOST_NO_INTEGRAL_INT64_T +# define BOOST_NO_OPERATORS_IN_NAMESPACE +# if !defined(_NAMESPACE_STD) +# define BOOST_NO_STD_LOCALE +# define BOOST_NO_STRINGSTREAM +# endif +#endif + +#if (__HP_aCC <= 33300) +// member templates are sufficiently broken that we disable them for now +# define BOOST_NO_MEMBER_TEMPLATES +# define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS +# define BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE +#endif + +#if (__HP_aCC <= 38000) +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#endif + +#if (__HP_aCC > 50000) && (__HP_aCC < 60000) +# define BOOST_NO_UNREACHABLE_RETURN_DETECTION +# define BOOST_NO_TEMPLATE_TEMPLATES +# define BOOST_NO_SWPRINTF +# define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS +# define BOOST_NO_IS_ABSTRACT +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +#endif + +// optional features rather than defects: +#if (__HP_aCC >= 33900) +# define BOOST_HAS_LONG_LONG +# define BOOST_HAS_PARTIAL_STD_ALLOCATOR +#endif + +#if (__HP_aCC >= 50000 ) && (__HP_aCC <= 53800 ) || (__HP_aCC < 31300 ) +# define BOOST_NO_MEMBER_TEMPLATE_KEYWORD +#endif + +// This macro should not be defined when compiling in strict ansi +// mode, but, currently, we don't have the ability to determine +// what standard mode we are compiling with. Some future version +// of aCC6 compiler will provide predefined macros reflecting the +// compilation options, including the standard mode. +#if (__HP_aCC >= 60000) || ((__HP_aCC > 38000) && defined(__hpxstd98)) +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#endif + +#define BOOST_COMPILER "HP aCC version " BOOST_STRINGIZE(__HP_aCC) + +// +// versions check: +// we don't support HP aCC prior to version 33000: +#if __HP_aCC < 33000 +# error "Compiler not supported or configured - please reconfigure" +#endif + +// +// Extended checks for supporting aCC on PA-RISC +#if __HP_aCC > 30000 && __HP_aCC < 50000 +# if __HP_aCC < 38000 + // versions prior to version A.03.80 not supported +# error "Compiler version not supported - version A.03.80 or higher is required" +# elif !defined(__hpxstd98) + // must compile using the option +hpxstd98 with version A.03.80 and above +# error "Compiler option '+hpxstd98' is required for proper support" +# endif //PA-RISC +#endif + +// +// last known and checked version for HP-UX/ia64 is 61300 +// last known and checked version for PA-RISC is 38000 +#if ((__HP_aCC > 61300) || ((__HP_aCC > 38000) && defined(__hpxstd98))) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif diff --git a/win32/include/boost/config/compiler/intel.hpp b/win32/include/boost/config/compiler/intel.hpp new file mode 100755 index 000000000..130efc466 --- /dev/null +++ b/win32/include/boost/config/compiler/intel.hpp @@ -0,0 +1,168 @@ +// (C) Copyright John Maddock 2001-8. +// (C) Copyright Peter Dimov 2001. +// (C) Copyright Jens Maurer 2001. +// (C) Copyright David Abrahams 2002 - 2003. +// (C) Copyright Aleksey Gurtovoy 2002 - 2003. +// (C) Copyright Guillaume Melquiond 2002 - 2003. +// (C) Copyright Beman Dawes 2003. +// (C) Copyright Martin Wille 2003. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Intel compiler setup: + +#include "boost/config/compiler/common_edg.hpp" + +#if defined(__INTEL_COMPILER) +# define BOOST_INTEL_CXX_VERSION __INTEL_COMPILER +#elif defined(__ICL) +# define BOOST_INTEL_CXX_VERSION __ICL +#elif defined(__ICC) +# define BOOST_INTEL_CXX_VERSION __ICC +#elif defined(__ECC) +# define BOOST_INTEL_CXX_VERSION __ECC +#endif + +#define BOOST_COMPILER "Intel C++ version " BOOST_STRINGIZE(BOOST_INTEL_CXX_VERSION) +#define BOOST_INTEL BOOST_INTEL_CXX_VERSION + +#if defined(_WIN32) || defined(_WIN64) +# define BOOST_INTEL_WIN BOOST_INTEL +#else +# define BOOST_INTEL_LINUX BOOST_INTEL +#endif + +#if (BOOST_INTEL_CXX_VERSION <= 500) && defined(_MSC_VER) +# define BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS +# define BOOST_NO_TEMPLATE_TEMPLATES +#endif + +#if (BOOST_INTEL_CXX_VERSION <= 600) + +# if defined(_MSC_VER) && (_MSC_VER <= 1300) // added check for <= VC 7 (Peter Dimov) + +// Boost libraries assume strong standard conformance unless otherwise +// indicated by a config macro. As configured by Intel, the EDG front-end +// requires certain compiler options be set to achieve that strong conformance. +// Particularly /Qoption,c,--arg_dep_lookup (reported by Kirk Klobe & Thomas Witt) +// and /Zc:wchar_t,forScope. See boost-root/tools/build/intel-win32-tools.jam for +// details as they apply to particular versions of the compiler. When the +// compiler does not predefine a macro indicating if an option has been set, +// this config file simply assumes the option has been set. +// Thus BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP will not be defined, even if +// the compiler option is not enabled. + +# define BOOST_NO_SWPRINTF +# endif + +// Void returns, 64 bit integrals don't work when emulating VC 6 (Peter Dimov) + +# if defined(_MSC_VER) && (_MSC_VER <= 1200) +# define BOOST_NO_VOID_RETURNS +# define BOOST_NO_INTEGRAL_INT64_T +# endif + +#endif + +#if (BOOST_INTEL_CXX_VERSION <= 710) && defined(_WIN32) +# define BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS +#endif + +// See http://aspn.activestate.com/ASPN/Mail/Message/boost/1614864 +#if BOOST_INTEL_CXX_VERSION < 600 +# define BOOST_NO_INTRINSIC_WCHAR_T +#else +// We should test the macro _WCHAR_T_DEFINED to check if the compiler +// supports wchar_t natively. *BUT* there is a problem here: the standard +// headers define this macro if they typedef wchar_t. Anyway, we're lucky +// because they define it without a value, while Intel C++ defines it +// to 1. So we can check its value to see if the macro was defined natively +// or not. +// Under UNIX, the situation is exactly the same, but the macro _WCHAR_T +// is used instead. +# if ((_WCHAR_T_DEFINED + 0) == 0) && ((_WCHAR_T + 0) == 0) +# define BOOST_NO_INTRINSIC_WCHAR_T +# endif +#endif + +#if defined(__GNUC__) && !defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL) +// +// Figure out when Intel is emulating this gcc bug +// (All Intel versions prior to 9.0.26, and versions +// later than that if they are set up to emulate gcc 3.2 +// or earlier): +// +# if ((__GNUC__ == 3) && (__GNUC_MINOR__ <= 2)) || (BOOST_INTEL < 900) || (__INTEL_COMPILER_BUILD_DATE < 20050912) +# define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL +# endif +#endif +#if (defined(__GNUC__) && (__GNUC__ < 4)) || defined(_WIN32) +// GCC or VC emulation: +#define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#endif +// +// Verify that we have actually got BOOST_NO_INTRINSIC_WCHAR_T +// set correctly, if we don't do this now, we will get errors later +// in type_traits code among other things, getting this correct +// for the Intel compiler is actually remarkably fragile and tricky: +// +#if defined(BOOST_NO_INTRINSIC_WCHAR_T) +#include +template< typename T > struct assert_no_intrinsic_wchar_t; +template<> struct assert_no_intrinsic_wchar_t { typedef void type; }; +// if you see an error here then you need to unset BOOST_NO_INTRINSIC_WCHAR_T +// where it is defined above: +typedef assert_no_intrinsic_wchar_t::type assert_no_intrinsic_wchar_t_; +#else +template< typename T > struct assert_intrinsic_wchar_t; +template<> struct assert_intrinsic_wchar_t {}; +// if you see an error here then define BOOST_NO_INTRINSIC_WCHAR_T on the command line: +template<> struct assert_intrinsic_wchar_t {}; +#endif + +#if _MSC_VER+0 >= 1000 +# if _MSC_VER >= 1200 +# define BOOST_HAS_MS_INT64 +# endif +# define BOOST_NO_SWPRINTF +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#elif defined(_WIN32) +# define BOOST_DISABLE_WIN32 +#endif + +// I checked version 6.0 build 020312Z, it implements the NRVO. +// Correct this as you find out which version of the compiler +// implemented the NRVO first. (Daniel Frey) +#if (BOOST_INTEL_CXX_VERSION >= 600) +# define BOOST_HAS_NRVO +#endif + +// +// versions check: +// we don't support Intel prior to version 5.0: +#if BOOST_INTEL_CXX_VERSION < 500 +# error "Compiler not supported or configured - please reconfigure" +#endif + +// Intel on MacOS requires +#if defined(__APPLE__) && defined(__INTEL_COMPILER) +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#endif + +// +// last known and checked version: +#if (BOOST_INTEL_CXX_VERSION > 1010) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# elif defined(_MSC_VER) +// +// We don't emit this warning any more, since we have so few +// defect macros set anyway (just the one). +// +//# pragma message("Unknown compiler version - please run the configure tests and report the results") +# endif +#endif + diff --git a/win32/include/boost/config/compiler/kai.hpp b/win32/include/boost/config/compiler/kai.hpp new file mode 100755 index 000000000..839341c5a --- /dev/null +++ b/win32/include/boost/config/compiler/kai.hpp @@ -0,0 +1,35 @@ +// (C) Copyright John Maddock 2001. +// (C) Copyright David Abrahams 2002. +// (C) Copyright Aleksey Gurtovoy 2002. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Kai C++ compiler setup: + +#include "boost/config/compiler/common_edg.hpp" + +# if (__KCC_VERSION <= 4001) || !defined(BOOST_STRICT_CONFIG) + // at least on Sun, the contents of is not in namespace std +# define BOOST_NO_STDC_NAMESPACE +# endif + +// see also common_edg.hpp which needs a special check for __KCC +# if !defined(_EXCEPTIONS) +# define BOOST_NO_EXCEPTIONS +# endif + +#define BOOST_COMPILER "Kai C++ version " BOOST_STRINGIZE(__KCC_VERSION) + +// +// last known and checked version is 4001: +#if (__KCC_VERSION > 4001) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + + diff --git a/win32/include/boost/config/compiler/metrowerks.hpp b/win32/include/boost/config/compiler/metrowerks.hpp new file mode 100755 index 000000000..0f27b774d --- /dev/null +++ b/win32/include/boost/config/compiler/metrowerks.hpp @@ -0,0 +1,111 @@ +// (C) Copyright John Maddock 2001. +// (C) Copyright Darin Adler 2001. +// (C) Copyright Peter Dimov 2001. +// (C) Copyright David Abrahams 2001 - 2002. +// (C) Copyright Beman Dawes 2001 - 2003. +// (C) Copyright Stefan Slapeta 2004. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Metrowerks C++ compiler setup: + +// locale support is disabled when linking with the dynamic runtime +# ifdef _MSL_NO_LOCALE +# define BOOST_NO_STD_LOCALE +# endif + +# if __MWERKS__ <= 0x2301 // 5.3 +# define BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# define BOOST_NO_POINTER_TO_MEMBER_CONST +# define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS +# define BOOST_NO_MEMBER_TEMPLATE_KEYWORD +# endif + +# if __MWERKS__ <= 0x2401 // 6.2 +//# define BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# endif + +# if(__MWERKS__ <= 0x2407) // 7.x +# define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS +# define BOOST_NO_UNREACHABLE_RETURN_DETECTION +# endif + +# if(__MWERKS__ <= 0x3003) // 8.x +# define BOOST_NO_SFINAE +# endif + +// the "|| !defined(BOOST_STRICT_CONFIG)" part should apply to the last +// tested version *only*: +# if(__MWERKS__ <= 0x3206) || !defined(BOOST_STRICT_CONFIG) // 9.5 +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# define BOOST_NO_IS_ABSTRACT +# endif + +#if !__option(wchar_type) +# define BOOST_NO_INTRINSIC_WCHAR_T +#endif + +#if !__option(exceptions) +# define BOOST_NO_EXCEPTIONS +#endif + +#if (__INTEL__ && _WIN32) || (__POWERPC__ && macintosh) +# if __MWERKS__ == 0x3000 +# define BOOST_COMPILER_VERSION 8.0 +# elif __MWERKS__ == 0x3001 +# define BOOST_COMPILER_VERSION 8.1 +# elif __MWERKS__ == 0x3002 +# define BOOST_COMPILER_VERSION 8.2 +# elif __MWERKS__ == 0x3003 +# define BOOST_COMPILER_VERSION 8.3 +# elif __MWERKS__ == 0x3200 +# define BOOST_COMPILER_VERSION 9.0 +# elif __MWERKS__ == 0x3201 +# define BOOST_COMPILER_VERSION 9.1 +# elif __MWERKS__ == 0x3202 +# define BOOST_COMPILER_VERSION 9.2 +# elif __MWERKS__ == 0x3204 +# define BOOST_COMPILER_VERSION 9.3 +# elif __MWERKS__ == 0x3205 +# define BOOST_COMPILER_VERSION 9.4 +# elif __MWERKS__ == 0x3206 +# define BOOST_COMPILER_VERSION 9.5 +# else +# define BOOST_COMPILER_VERSION __MWERKS__ +# endif +#else +# define BOOST_COMPILER_VERSION __MWERKS__ +#endif + +// +// C++0x features +// +#if __MWERKS__ > 0x3206 && __option(rvalue_refs) +# define BOOST_HAS_RVALUE_REFS +#endif + +#define BOOST_COMPILER "Metrowerks CodeWarrior C++ version " BOOST_STRINGIZE(BOOST_COMPILER_VERSION) + +// +// versions check: +// we don't support Metrowerks prior to version 5.3: +#if __MWERKS__ < 0x2301 +# error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version: +#if (__MWERKS__ > 0x3205) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + + + + + + diff --git a/win32/include/boost/config/compiler/mpw.hpp b/win32/include/boost/config/compiler/mpw.hpp new file mode 100755 index 000000000..fc211f8cc --- /dev/null +++ b/win32/include/boost/config/compiler/mpw.hpp @@ -0,0 +1,51 @@ +// (C) Copyright John Maddock 2001 - 2002. +// (C) Copyright Aleksey Gurtovoy 2002. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// MPW C++ compilers setup: + +# if defined(__SC__) +# define BOOST_COMPILER "MPW SCpp version " BOOST_STRINGIZE(__SC__) +# elif defined(__MRC__) +# define BOOST_COMPILER "MPW MrCpp version " BOOST_STRINGIZE(__MRC__) +# else +# error "Using MPW compiler configuration by mistake. Please update." +# endif + +// +// MPW 8.90: +// +#if (MPW_CPLUS <= 0x890) || !defined(BOOST_STRICT_CONFIG) +# define BOOST_NO_CV_SPECIALIZATIONS +# define BOOST_NO_DEPENDENT_NESTED_DERIVATIONS +# define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# define BOOST_NO_INTRINSIC_WCHAR_T +# define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# define BOOST_NO_USING_TEMPLATE + +# define BOOST_NO_CWCHAR +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + +# define BOOST_NO_STD_ALLOCATOR /* actually a bug with const reference overloading */ +#endif + +// +// versions check: +// we don't support MPW prior to version 8.9: +#if MPW_CPLUS < 0x890 +# error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 0x890: +#if (MPW_CPLUS > 0x890) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + diff --git a/win32/include/boost/config/compiler/pgi.hpp b/win32/include/boost/config/compiler/pgi.hpp new file mode 100755 index 000000000..a80a483ef --- /dev/null +++ b/win32/include/boost/config/compiler/pgi.hpp @@ -0,0 +1,33 @@ +// (C) Copyright Noel Belcourt 2007. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// PGI C++ compiler setup: + +#define BOOST_COMPILER_VERSION __PGIC__##__PGIC_MINOR__ +#define BOOST_COMPILER "PGI compiler version " BOOST_STRINGIZE(_COMPILER_VERSION) + +// +// Threading support: +// Turn this on unconditionally here, it will get turned off again later +// if no threading API is detected. +// + +#if (__PGIC__ == 7) && (__PGIC_MINOR__ == 1) + +#define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL +#define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#define BOOST_NO_SWPRINTF + +#else + +# error "Pgi compiler not configured - please reconfigure" + +#endif +// +// version check: +// probably nothing to do here? + diff --git a/win32/include/boost/config/compiler/sgi_mipspro.hpp b/win32/include/boost/config/compiler/sgi_mipspro.hpp new file mode 100755 index 000000000..9139c05a7 --- /dev/null +++ b/win32/include/boost/config/compiler/sgi_mipspro.hpp @@ -0,0 +1,28 @@ +// (C) Copyright John Maddock 2001 - 2002. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// SGI C++ compiler setup: + +#define BOOST_COMPILER "SGI Irix compiler version " BOOST_STRINGIZE(_COMPILER_VERSION) + +#include "boost/config/compiler/common_edg.hpp" + +// +// Threading support: +// Turn this on unconditionally here, it will get turned off again later +// if no threading API is detected. +// +#define BOOST_HAS_THREADS +#define BOOST_NO_TWO_PHASE_NAME_LOOKUP + +#undef BOOST_NO_SWPRINTF +#undef BOOST_DEDUCED_TYPENAME +// +// version check: +// probably nothing to do here? + + diff --git a/win32/include/boost/config/compiler/sunpro_cc.hpp b/win32/include/boost/config/compiler/sunpro_cc.hpp new file mode 100755 index 000000000..6dcec62dc --- /dev/null +++ b/win32/include/boost/config/compiler/sunpro_cc.hpp @@ -0,0 +1,99 @@ +// (C) Copyright John Maddock 2001. +// (C) Copyright Jens Maurer 2001 - 2003. +// (C) Copyright Peter Dimov 2002. +// (C) Copyright Aleksey Gurtovoy 2002 - 2003. +// (C) Copyright David Abrahams 2002. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Sun C++ compiler setup: + +# if __SUNPRO_CC <= 0x500 +# define BOOST_NO_MEMBER_TEMPLATES +# define BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# endif + +# if (__SUNPRO_CC <= 0x520) + // + // Sunpro 5.2 and earler: + // + // although sunpro 5.2 supports the syntax for + // inline initialization it often gets the value + // wrong, especially where the value is computed + // from other constants (J Maddock 6th May 2001) +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION + + // Although sunpro 5.2 supports the syntax for + // partial specialization, it often seems to + // bind to the wrong specialization. Better + // to disable it until suppport becomes more stable + // (J Maddock 6th May 2001). +# define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# endif + +# if (__SUNPRO_CC <= 0x530) + // Requesting debug info (-g) with Boost.Python results + // in an internal compiler error for "static const" + // initialized in-class. + // >> Assertion: (../links/dbg_cstabs.cc, line 611) + // while processing ../test.cpp at line 0. + // (Jens Maurer according to Gottfried Ganssauge 04 Mar 2002) +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION + + // SunPro 5.3 has better support for partial specialization, + // but breaks when compiling std::less > + // (Jens Maurer 4 Nov 2001). + + // std::less specialization fixed as reported by George + // Heintzelman; partial specialization re-enabled + // (Peter Dimov 17 Jan 2002) + +//# define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // integral constant expressions with 64 bit numbers fail +# define BOOST_NO_INTEGRAL_INT64_T +# endif + +# if (__SUNPRO_CC < 0x570) +# define BOOST_NO_TEMPLATE_TEMPLATES + // see http://lists.boost.org/MailArchives/boost/msg47184.php + // and http://lists.boost.org/MailArchives/boost/msg47220.php +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# define BOOST_NO_SFINAE +# define BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS +# endif +# if (__SUNPRO_CC <= 0x580) +# define BOOST_NO_IS_ABSTRACT +# endif + +// +// Issues that effect all known versions: +// +#define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#define BOOST_NO_ADL_BARRIER + + +#define BOOST_COMPILER "Sun compiler version " BOOST_STRINGIZE(__SUNPRO_CC) + +// +// versions check: +// we don't support sunpro prior to version 4: +#if __SUNPRO_CC < 0x400 +#error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 0x590: +#if (__SUNPRO_CC > 0x590) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + + + + + + diff --git a/win32/include/boost/config/compiler/vacpp.hpp b/win32/include/boost/config/compiler/vacpp.hpp new file mode 100755 index 000000000..b91325205 --- /dev/null +++ b/win32/include/boost/config/compiler/vacpp.hpp @@ -0,0 +1,60 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Toon Knapen 2001 - 2003. +// (C) Copyright Lie-Quan Lee 2001. +// (C) Copyright Markus Schoepflin 2002 - 2003. +// (C) Copyright Beman Dawes 2002 - 2003. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Visual Age (IBM) C++ compiler setup: + +#if __IBMCPP__ <= 501 +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS +#endif + +#if (__IBMCPP__ <= 502) +// Actually the compiler supports inclass member initialization but it +// requires a definition for the class member and it doesn't recognize +// it as an integral constant expression when used as a template argument. +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# define BOOST_NO_INTEGRAL_INT64_T +# define BOOST_NO_MEMBER_TEMPLATE_KEYWORD +#endif + +#if (__IBMCPP__ <= 600) || !defined(BOOST_STRICT_CONFIG) +# define BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS +#endif + +// +// On AIX thread support seems to be indicated by _THREAD_SAFE: +// +#ifdef _THREAD_SAFE +# define BOOST_HAS_THREADS +#endif + +#define BOOST_COMPILER "IBM Visual Age version " BOOST_STRINGIZE(__IBMCPP__) + +// +// versions check: +// we don't support Visual age prior to version 5: +#if __IBMCPP__ < 500 +#error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 600: +#if (__IBMCPP__ > 600) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# endif +#endif + +// Some versions of the compiler have issues with default arguments on partial specializations +#define BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS + + + + diff --git a/win32/include/boost/config/compiler/visualc.hpp b/win32/include/boost/config/compiler/visualc.hpp new file mode 100755 index 000000000..6072487ed --- /dev/null +++ b/win32/include/boost/config/compiler/visualc.hpp @@ -0,0 +1,196 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Darin Adler 2001 - 2002. +// (C) Copyright Peter Dimov 2001. +// (C) Copyright Aleksey Gurtovoy 2002. +// (C) Copyright David Abrahams 2002 - 2003. +// (C) Copyright Beman Dawes 2002 - 2003. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Microsoft Visual C++ compiler setup: + +#define BOOST_MSVC _MSC_VER + +// turn off the warnings before we #include anything +#pragma warning( disable : 4503 ) // warning: decorated name length exceeded + +#if _MSC_VER < 1300 // 1200 == VC++ 6.0, 1200-1202 == eVC++4 +# pragma warning( disable : 4786 ) // ident trunc to '255' chars in debug info +# define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS +# define BOOST_NO_VOID_RETURNS +# define BOOST_NO_EXCEPTION_STD_NAMESPACE + // disable min/max macro defines on vc6: + // +#endif + +#if (_MSC_VER <= 1300) // 1300 == VC++ 7.0 + +# if !defined(_MSC_EXTENSIONS) && !defined(BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS) // VC7 bug with /Za +# define BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS +# endif + +# define BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS +# define BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# define BOOST_NO_PRIVATE_IN_AGGREGATE +# define BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +# define BOOST_NO_INTEGRAL_INT64_T +# define BOOST_NO_DEDUCED_TYPENAME +# define BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE + +// VC++ 6/7 has member templates but they have numerous problems including +// cases of silent failure, so for safety we define: +# define BOOST_NO_MEMBER_TEMPLATES +// For VC++ experts wishing to attempt workarounds, we define: +# define BOOST_MSVC6_MEMBER_TEMPLATES + +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +# define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# define BOOST_NO_CV_VOID_SPECIALIZATIONS +# define BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# define BOOST_NO_USING_TEMPLATE +# define BOOST_NO_SWPRINTF +# define BOOST_NO_TEMPLATE_TEMPLATES +# define BOOST_NO_SFINAE +# define BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS +# define BOOST_NO_IS_ABSTRACT +# define BOOST_NO_FUNCTION_TYPE_SPECIALIZATIONS +// TODO: what version is meant here? Have there really been any fixes in cl 12.01 (as e.g. shipped with eVC4)? +# if (_MSC_VER > 1200) +# define BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS +# endif + +#endif + +#if _MSC_VER < 1400 +// although a conforming signature for swprint exists in VC7.1 +// it appears not to actually work: +# define BOOST_NO_SWPRINTF +#endif + +#if defined(UNDER_CE) +// Windows CE does not have a conforming signature for swprintf +# define BOOST_NO_SWPRINTF +#endif + +#if _MSC_VER <= 1400 // 1400 == VC++ 8.0 +# define BOOST_NO_MEMBER_TEMPLATE_FRIENDS +#endif + +#if _MSC_VER <= 1500 // 1500 == VC++ 9.0 +# define BOOST_NO_TWO_PHASE_NAME_LOOKUP +#endif + +#if _MSC_VER == 1500 // 1500 == VC++ 9.0 + // A bug in VC9: +# define BOOST_NO_ADL_BARRIER +#endif + +#ifndef _NATIVE_WCHAR_T_DEFINED +# define BOOST_NO_INTRINSIC_WCHAR_T +#endif + +#if defined(_WIN32_WCE) || defined(UNDER_CE) +# define BOOST_NO_THREADEX +# define BOOST_NO_GETSYSTEMTIMEASFILETIME +# define BOOST_NO_SWPRINTF +#endif + +// +// check for exception handling support: +#ifndef _CPPUNWIND +# define BOOST_NO_EXCEPTIONS +#endif + +// +// __int64 support: +// +#if (_MSC_VER >= 1200) +# define BOOST_HAS_MS_INT64 +#endif +#if (_MSC_VER >= 1310) && defined(_MSC_EXTENSIONS) +# define BOOST_HAS_LONG_LONG +#endif +#if (_MSC_VER >= 1400) && !defined(_DEBUG) +# define BOOST_HAS_NRVO +#endif +// +// disable Win32 API's if compiler extentions are +// turned off: +// +#ifndef _MSC_EXTENSIONS +# define BOOST_DISABLE_WIN32 +#endif + +// +// all versions support __declspec: +// +#define BOOST_HAS_DECLSPEC +// +// prefix and suffix headers: +// +#ifndef BOOST_ABI_PREFIX +# define BOOST_ABI_PREFIX "boost/config/abi/msvc_prefix.hpp" +#endif +#ifndef BOOST_ABI_SUFFIX +# define BOOST_ABI_SUFFIX "boost/config/abi/msvc_suffix.hpp" +#endif + +// TODO: +// these things are mostly bogus. 1200 means version 12.0 of the compiler. The +// artificial versions assigned to them only refer to the versions of some IDE +// these compilers have been shipped with, and even that is not all of it. Some +// were shipped with freely downloadable SDKs, others as crosscompilers in eVC. +// IOW, you can't use these 'versions' in any sensible way. Sorry. +# if defined(UNDER_CE) +# if _MSC_VER < 1200 + // Note: these are so far off, they are not really supported +# elif _MSC_VER < 1300 // eVC++ 4 comes with 1200-1202 +# define BOOST_COMPILER_VERSION evc4.0 +# elif _MSC_VER == 1400 +# define BOOST_COMPILER_VERSION evc8 +# else +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown EVC++ compiler version - please run the configure tests and report the results" +# else +# pragma message("Unknown EVC++ compiler version - please run the configure tests and report the results") +# endif +# endif +# else +# if _MSC_VER < 1200 + // Note: these are so far off, they are not really supported +# define BOOST_COMPILER_VERSION 5.0 +# elif _MSC_VER < 1300 +# define BOOST_COMPILER_VERSION 6.0 +# elif _MSC_VER == 1300 +# define BOOST_COMPILER_VERSION 7.0 +# elif _MSC_VER == 1310 +# define BOOST_COMPILER_VERSION 7.1 +# elif _MSC_VER == 1400 +# define BOOST_COMPILER_VERSION 8.0 +# elif _MSC_VER == 1500 +# define BOOST_COMPILER_VERSION 9.0 +# else +# define BOOST_COMPILER_VERSION _MSC_VER +# endif +# endif + +#define BOOST_COMPILER "Microsoft Visual C++ version " BOOST_STRINGIZE(BOOST_COMPILER_VERSION) + +// +// versions check: +// we don't support Visual C++ prior to version 6: +#if _MSC_VER < 1200 +#error "Compiler not supported or configured - please reconfigure" +#endif +// +// last known and checked version is 1500 (VC9): +#if (_MSC_VER > 1500) +# if defined(BOOST_ASSERT_CONFIG) +# error "Unknown compiler version - please run the configure tests and report the results" +# else +# pragma message("Unknown compiler version - please run the configure tests and report the results") +# endif +#endif diff --git a/win32/include/boost/config/no_tr1/complex.hpp b/win32/include/boost/config/no_tr1/complex.hpp new file mode 100755 index 000000000..c6f42543f --- /dev/null +++ b/win32/include/boost/config/no_tr1/complex.hpp @@ -0,0 +1,28 @@ +// (C) Copyright John Maddock 2005. +// Use, modification and distribution are subject to 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) +// +// The aim of this header is just to include but to do +// so in a way that does not result in recursive inclusion of +// the Boost TR1 components if boost/tr1/tr1/complex is in the +// include search path. We have to do this to avoid circular +// dependencies: +// + +#ifndef BOOST_CONFIG_COMPLEX +# define BOOST_CONFIG_COMPLEX + +# ifndef BOOST_TR1_NO_RECURSION +# define BOOST_TR1_NO_RECURSION +# define BOOST_CONFIG_NO_COMPLEX_RECURSION +# endif + +# include + +# ifdef BOOST_CONFIG_NO_COMPLEX_RECURSION +# undef BOOST_TR1_NO_RECURSION +# undef BOOST_CONFIG_NO_COMPLEX_RECURSION +# endif + +#endif diff --git a/win32/include/boost/config/no_tr1/functional.hpp b/win32/include/boost/config/no_tr1/functional.hpp new file mode 100755 index 000000000..08d46fc4a --- /dev/null +++ b/win32/include/boost/config/no_tr1/functional.hpp @@ -0,0 +1,28 @@ +// (C) Copyright John Maddock 2005. +// Use, modification and distribution are subject to 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) +// +// The aim of this header is just to include but to do +// so in a way that does not result in recursive inclusion of +// the Boost TR1 components if boost/tr1/tr1/functional is in the +// include search path. We have to do this to avoid circular +// dependencies: +// + +#ifndef BOOST_CONFIG_FUNCTIONAL +# define BOOST_CONFIG_FUNCTIONAL + +# ifndef BOOST_TR1_NO_RECURSION +# define BOOST_TR1_NO_RECURSION +# define BOOST_CONFIG_NO_FUNCTIONAL_RECURSION +# endif + +# include + +# ifdef BOOST_CONFIG_NO_FUNCTIONAL_RECURSION +# undef BOOST_TR1_NO_RECURSION +# undef BOOST_CONFIG_NO_FUNCTIONAL_RECURSION +# endif + +#endif diff --git a/win32/include/boost/config/no_tr1/memory.hpp b/win32/include/boost/config/no_tr1/memory.hpp new file mode 100755 index 000000000..d998a54e4 --- /dev/null +++ b/win32/include/boost/config/no_tr1/memory.hpp @@ -0,0 +1,28 @@ +// (C) Copyright John Maddock 2005. +// Use, modification and distribution are subject to 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) +// +// The aim of this header is just to include but to do +// so in a way that does not result in recursive inclusion of +// the Boost TR1 components if boost/tr1/tr1/memory is in the +// include search path. We have to do this to avoid circular +// dependencies: +// + +#ifndef BOOST_CONFIG_MEMORY +# define BOOST_CONFIG_MEMORY + +# ifndef BOOST_TR1_NO_RECURSION +# define BOOST_TR1_NO_RECURSION +# define BOOST_CONFIG_NO_MEMORY_RECURSION +# endif + +# include + +# ifdef BOOST_CONFIG_NO_MEMORY_RECURSION +# undef BOOST_TR1_NO_RECURSION +# undef BOOST_CONFIG_NO_MEMORY_RECURSION +# endif + +#endif diff --git a/win32/include/boost/config/no_tr1/utility.hpp b/win32/include/boost/config/no_tr1/utility.hpp new file mode 100755 index 000000000..40f223486 --- /dev/null +++ b/win32/include/boost/config/no_tr1/utility.hpp @@ -0,0 +1,28 @@ +// (C) Copyright John Maddock 2005. +// Use, modification and distribution are subject to 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) +// +// The aim of this header is just to include but to do +// so in a way that does not result in recursive inclusion of +// the Boost TR1 components if boost/tr1/tr1/utility is in the +// include search path. We have to do this to avoid circular +// dependencies: +// + +#ifndef BOOST_CONFIG_UTILITY +# define BOOST_CONFIG_UTILITY + +# ifndef BOOST_TR1_NO_RECURSION +# define BOOST_TR1_NO_RECURSION +# define BOOST_CONFIG_NO_UTILITY_RECURSION +# endif + +# include + +# ifdef BOOST_CONFIG_NO_UTILITY_RECURSION +# undef BOOST_TR1_NO_RECURSION +# undef BOOST_CONFIG_NO_UTILITY_RECURSION +# endif + +#endif diff --git a/win32/include/boost/config/platform/aix.hpp b/win32/include/boost/config/platform/aix.hpp new file mode 100755 index 000000000..36b6ab250 --- /dev/null +++ b/win32/include/boost/config/platform/aix.hpp @@ -0,0 +1,33 @@ +// (C) Copyright John Maddock 2001 - 2002. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// IBM/Aix specific config options: + +#define BOOST_PLATFORM "IBM Aix" + +#define BOOST_HAS_UNISTD_H +#define BOOST_HAS_NL_TYPES_H +#define BOOST_HAS_NANOSLEEP +#define BOOST_HAS_CLOCK_GETTIME + +// This needs support in "boost/cstdint.hpp" exactly like FreeBSD. +// This platform has header named which includes all +// the things needed. +#define BOOST_HAS_STDINT_H + +// Threading API's: +#define BOOST_HAS_PTHREADS +#define BOOST_HAS_PTHREAD_DELAY_NP +#define BOOST_HAS_SCHED_YIELD +//#define BOOST_HAS_PTHREAD_YIELD + +// boilerplate code: +#include + + + + diff --git a/win32/include/boost/config/platform/amigaos.hpp b/win32/include/boost/config/platform/amigaos.hpp new file mode 100755 index 000000000..fe22635a9 --- /dev/null +++ b/win32/include/boost/config/platform/amigaos.hpp @@ -0,0 +1,15 @@ +// (C) Copyright John Maddock 2002. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +#define BOOST_PLATFORM "AmigaOS" + +#define BOOST_DISABLE_THREADS +#define BOOST_NO_CWCHAR +#define BOOST_NO_STD_WSTRING +#define BOOST_NO_INTRINSIC_WCHAR_T + + diff --git a/win32/include/boost/config/platform/beos.hpp b/win32/include/boost/config/platform/beos.hpp new file mode 100755 index 000000000..507ef826f --- /dev/null +++ b/win32/include/boost/config/platform/beos.hpp @@ -0,0 +1,26 @@ +// (C) Copyright John Maddock 2001. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// BeOS specific config options: + +#define BOOST_PLATFORM "BeOS" + +#define BOOST_NO_CWCHAR +#define BOOST_NO_CWCTYPE +#define BOOST_HAS_UNISTD_H + +#define BOOST_HAS_BETHREADS + +#ifndef BOOST_DISABLE_THREADS +# define BOOST_HAS_THREADS +#endif + +// boilerplate code: +#include + + + diff --git a/win32/include/boost/config/platform/bsd.hpp b/win32/include/boost/config/platform/bsd.hpp new file mode 100755 index 000000000..b027d83be --- /dev/null +++ b/win32/include/boost/config/platform/bsd.hpp @@ -0,0 +1,73 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Darin Adler 2001. +// (C) Copyright Douglas Gregor 2002. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// generic BSD config options: + +#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) +#error "This platform is not BSD" +#endif + +#ifdef __FreeBSD__ +#define BOOST_PLATFORM "FreeBSD " BOOST_STRINGIZE(__FreeBSD__) +#elif defined(__NetBSD__) +#define BOOST_PLATFORM "NetBSD " BOOST_STRINGIZE(__NetBSD__) +#elif defined(__OpenBSD__) +#define BOOST_PLATFORM "OpenBSD " BOOST_STRINGIZE(__OpenBSD__) +#elif defined(__DragonFly__) +#define BOOST_PLATFORM "DragonFly " BOOST_STRINGIZE(__DragonFly__) +#endif + +// +// is this the correct version check? +// FreeBSD has but does not +// advertise the fact in : +// +#if (defined(__FreeBSD__) && (__FreeBSD__ >= 3)) || defined(__DragonFly__) +# define BOOST_HAS_NL_TYPES_H +#endif + +// +// FreeBSD 3.x has pthreads support, but defines _POSIX_THREADS in +// and not in +// +#if (defined(__FreeBSD__) && (__FreeBSD__ <= 3)) || defined(__OpenBSD__) +# define BOOST_HAS_PTHREADS +#endif + +// +// No wide character support in the BSD header files: +// +#if !(defined(__FreeBSD__) && (__FreeBSD__ >= 5)) +# define BOOST_NO_CWCHAR +#endif +// +// The BSD has macros only, no functions: +// +#if !defined(__OpenBSD__) +# define BOOST_NO_CTYPE_FUNCTIONS +#endif + +// +// thread API's not auto detected: +// +#define BOOST_HAS_SCHED_YIELD +#define BOOST_HAS_NANOSLEEP +#define BOOST_HAS_GETTIMEOFDAY +#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +#define BOOST_HAS_SIGACTION + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include + + + + + + diff --git a/win32/include/boost/config/platform/cygwin.hpp b/win32/include/boost/config/platform/cygwin.hpp new file mode 100755 index 000000000..514ad25be --- /dev/null +++ b/win32/include/boost/config/platform/cygwin.hpp @@ -0,0 +1,51 @@ +// (C) Copyright John Maddock 2001 - 2003. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// cygwin specific config options: + +#define BOOST_PLATFORM "Cygwin" +#define BOOST_NO_CWCTYPE +#define BOOST_NO_CWCHAR +#define BOOST_NO_SWPRINTF +#define BOOST_HAS_DIRENT_H +#define BOOST_HAS_LOG1P +#define BOOST_HAS_EXPM1 + +// +// Threading API: +// See if we have POSIX threads, if we do use them, otherwise +// revert to native Win threads. +#define BOOST_HAS_UNISTD_H +#include +#if defined(_POSIX_THREADS) && (_POSIX_THREADS+0 >= 0) && !defined(BOOST_HAS_WINTHREADS) +# define BOOST_HAS_PTHREADS +# define BOOST_HAS_SCHED_YIELD +# define BOOST_HAS_GETTIMEOFDAY +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# define BOOST_HAS_SIGACTION +#else +# if !defined(BOOST_HAS_WINTHREADS) +# define BOOST_HAS_WINTHREADS +# endif +# define BOOST_HAS_FTIME +#endif + +// +// find out if we have a stdint.h, there should be a better way to do this: +// +#include +#ifdef _STDINT_H +#define BOOST_HAS_STDINT_H +#endif + +// boilerplate code: +#include + + + + + diff --git a/win32/include/boost/config/platform/hpux.hpp b/win32/include/boost/config/platform/hpux.hpp new file mode 100755 index 000000000..8e79892b1 --- /dev/null +++ b/win32/include/boost/config/platform/hpux.hpp @@ -0,0 +1,87 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2001 - 2003. +// (C) Copyright David Abrahams 2002. +// (C) Copyright Toon Knapen 2003. +// (C) Copyright Boris Gubenko 2006 - 2007. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// hpux specific config options: + +#define BOOST_PLATFORM "HP-UX" + +// In principle, HP-UX has a nice under the name +// However, it has the following problem: +// Use of UINT32_C(0) results in "0u l" for the preprocessed source +// (verifyable with gcc 2.95.3) +#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__HP_aCC) +# define BOOST_HAS_STDINT_H +#endif + +#if !(defined(__HP_aCC) || !defined(_INCLUDE__STDC_A1_SOURCE)) +# define BOOST_NO_SWPRINTF +#endif +#if defined(__HP_aCC) && !defined(_INCLUDE__STDC_A1_SOURCE) +# define BOOST_NO_CWCTYPE +#endif + +#if defined(__GNUC__) +# if (__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 3)) + // GNU C on HP-UX does not support threads (checked up to gcc 3.3) +# define BOOST_DISABLE_THREADS +# elif !defined(BOOST_DISABLE_THREADS) + // threads supported from gcc-3.3 onwards: +# define BOOST_HAS_THREADS +# define BOOST_HAS_PTHREADS +# endif +#elif defined(__HP_aCC) && !defined(BOOST_DISABLE_THREADS) +# define BOOST_HAS_PTHREADS +#endif + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include + +// the following are always available: +#ifndef BOOST_HAS_GETTIMEOFDAY +# define BOOST_HAS_GETTIMEOFDAY +#endif +#ifndef BOOST_HAS_SCHED_YIELD +# define BOOST_HAS_SCHED_YIELD +#endif +#ifndef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +#endif +#ifndef BOOST_HAS_NL_TYPES_H +# define BOOST_HAS_NL_TYPES_H +#endif +#ifndef BOOST_HAS_NANOSLEEP +# define BOOST_HAS_NANOSLEEP +#endif +#ifndef BOOST_HAS_GETTIMEOFDAY +# define BOOST_HAS_GETTIMEOFDAY +#endif +#ifndef BOOST_HAS_DIRENT_H +# define BOOST_HAS_DIRENT_H +#endif +#ifndef BOOST_HAS_CLOCK_GETTIME +# define BOOST_HAS_CLOCK_GETTIME +#endif +#ifndef BOOST_HAS_SIGACTION +# define BOOST_HAS_SIGACTION +#endif +#ifndef BOOST_HAS_NRVO +# ifndef __parisc +# define BOOST_HAS_NRVO +# endif +#endif +#ifndef BOOST_HAS_LOG1P +# define BOOST_HAS_LOG1P +#endif +#ifndef BOOST_HAS_EXPM1 +# define BOOST_HAS_EXPM1 +#endif + diff --git a/win32/include/boost/config/platform/irix.hpp b/win32/include/boost/config/platform/irix.hpp new file mode 100755 index 000000000..e0691a41d --- /dev/null +++ b/win32/include/boost/config/platform/irix.hpp @@ -0,0 +1,31 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2003. +// Use, modification and distribution are subject to 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) + + +// See http://www.boost.org for most recent version. + +// SGI Irix specific config options: + +#define BOOST_PLATFORM "SGI Irix" + +#define BOOST_NO_SWPRINTF +// +// these are not auto detected by POSIX feature tests: +// +#define BOOST_HAS_GETTIMEOFDAY +#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE + +#ifdef __GNUC__ + // GNU C on IRIX does not support threads (checked up to gcc 3.3) +# define BOOST_DISABLE_THREADS +#endif + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include + + + diff --git a/win32/include/boost/config/platform/linux.hpp b/win32/include/boost/config/platform/linux.hpp new file mode 100755 index 000000000..b87db7946 --- /dev/null +++ b/win32/include/boost/config/platform/linux.hpp @@ -0,0 +1,98 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2001 - 2003. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// linux specific config options: + +#define BOOST_PLATFORM "linux" + +// make sure we have __GLIBC_PREREQ if available at all +#include + +// +// added to glibc 2.1.1 +// We can only test for 2.1 though: +// +#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))) + // defines int64_t unconditionally, but defines + // int64_t only if __GNUC__. Thus, assume a fully usable + // only when using GCC. +# if defined __GNUC__ +# define BOOST_HAS_STDINT_H +# endif +#endif + +#if defined(__LIBCOMO__) + // + // como on linux doesn't have std:: c functions: + // NOTE: versions of libcomo prior to beta28 have octal version numbering, + // e.g. version 25 is 21 (dec) + // +# if __LIBCOMO_VERSION__ <= 20 +# define BOOST_NO_STDC_NAMESPACE +# endif + +# if __LIBCOMO_VERSION__ <= 21 +# define BOOST_NO_SWPRINTF +# endif + +#endif + +// +// If glibc is past version 2 then we definitely have +// gettimeofday, earlier versions may or may not have it: +// +#if defined(__GLIBC__) && (__GLIBC__ >= 2) +# define BOOST_HAS_GETTIMEOFDAY +#endif + +#ifdef __USE_POSIX199309 +# define BOOST_HAS_NANOSLEEP +#endif + +#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +// __GLIBC_PREREQ is available since 2.1.2 + + // swprintf is available since glibc 2.2.0 +# if !__GLIBC_PREREQ(2,2) || (!defined(__USE_ISOC99) && !defined(__USE_UNIX98)) +# define BOOST_NO_SWPRINTF +# endif +#else +# define BOOST_NO_SWPRINTF +#endif + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include + +#ifndef __GNUC__ +// +// if the compiler is not gcc we still need to be able to parse +// the GNU system headers, some of which (mainly ) +// use GNU specific extensions: +// +# ifndef __extension__ +# define __extension__ +# endif +# ifndef __const__ +# define __const__ const +# endif +# ifndef __volatile__ +# define __volatile__ volatile +# endif +# ifndef __signed__ +# define __signed__ signed +# endif +# ifndef __typeof__ +# define __typeof__ typeof +# endif +# ifndef __inline__ +# define __inline__ inline +# endif +#endif + + diff --git a/win32/include/boost/config/platform/macos.hpp b/win32/include/boost/config/platform/macos.hpp new file mode 100755 index 000000000..f21d6fcda --- /dev/null +++ b/win32/include/boost/config/platform/macos.hpp @@ -0,0 +1,86 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Darin Adler 2001 - 2002. +// (C) Copyright Bill Kempf 2002. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Mac OS specific config options: + +#define BOOST_PLATFORM "Mac OS" + +#if __MACH__ && !defined(_MSL_USING_MSL_C) + +// Using the Mac OS X system BSD-style C library. + +# ifndef BOOST_HAS_UNISTD_H +# define BOOST_HAS_UNISTD_H +# endif +// +// Begin by including our boilerplate code for POSIX +// feature detection, this is safe even when using +// the MSL as Metrowerks supply their own +// to replace the platform-native BSD one. G++ users +// should also always be able to do this on MaxOS X. +// +# include +# ifndef BOOST_HAS_STDINT_H +# define BOOST_HAS_STDINT_H +# endif + +// +// BSD runtime has pthreads, sigaction, sched_yield and gettimeofday, +// of these only pthreads are advertised in , so set the +// other options explicitly: +// +# define BOOST_HAS_SCHED_YIELD +# define BOOST_HAS_GETTIMEOFDAY +# define BOOST_HAS_SIGACTION + +# if (__GNUC__ < 3) && !defined( __APPLE_CC__) + +// GCC strange "ignore std" mode works better if you pretend everything +// is in the std namespace, for the most part. + +# define BOOST_NO_STDC_NAMESPACE +# endif + +# if (__GNUC__ == 4) + +// Both gcc and intel require these. +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# define BOOST_HAS_NANOSLEEP + +# endif + +#else + +// Using the MSL C library. + +// We will eventually support threads in non-Carbon builds, but we do +// not support this yet. +# if ( defined(TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON ) || ( defined(TARGET_CARBON) && TARGET_CARBON ) + +# if !defined(BOOST_HAS_PTHREADS) +# define BOOST_HAS_MPTASKS +# elif ( __dest_os == __mac_os_x ) +// We are doing a Carbon/Mach-O/MSL build which has pthreads, but only the +// gettimeofday and no posix. +# define BOOST_HAS_GETTIMEOFDAY +# endif + +// The MP task implementation of Boost Threads aims to replace MP-unsafe +// parts of the MSL, so we turn on threads unconditionally. +# define BOOST_HAS_THREADS + +// The remote call manager depends on this. +# define BOOST_BIND_ENABLE_PASCAL + +# endif + +#endif + + + diff --git a/win32/include/boost/config/platform/qnxnto.hpp b/win32/include/boost/config/platform/qnxnto.hpp new file mode 100755 index 000000000..102f27c69 --- /dev/null +++ b/win32/include/boost/config/platform/qnxnto.hpp @@ -0,0 +1,31 @@ +// (C) Copyright Jim Douglas 2005. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// QNX specific config options: + +#define BOOST_PLATFORM "QNX" + +#define BOOST_HAS_UNISTD_H +#include + +// QNX claims XOpen version 5 compatibility, but doesn't have an nl_types.h +// or log1p and expm1: +#undef BOOST_HAS_NL_TYPES_H +#undef BOOST_HAS_LOG1P +#undef BOOST_HAS_EXPM1 + +#define BOOST_HAS_PTHREADS +#define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE + +#define BOOST_HAS_GETTIMEOFDAY +#define BOOST_HAS_CLOCK_GETTIME +#define BOOST_HAS_NANOSLEEP + + + + + diff --git a/win32/include/boost/config/platform/solaris.hpp b/win32/include/boost/config/platform/solaris.hpp new file mode 100755 index 000000000..af776bddb --- /dev/null +++ b/win32/include/boost/config/platform/solaris.hpp @@ -0,0 +1,28 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2003. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// sun specific config options: + +#define BOOST_PLATFORM "Sun Solaris" + +#define BOOST_HAS_GETTIMEOFDAY + +// boilerplate code: +#define BOOST_HAS_UNISTD_H +#include + +// +// pthreads don't actually work with gcc unless _PTHREADS is defined: +// +#if defined(__GNUC__) && defined(_POSIX_THREADS) && !defined(_PTHREADS) +# undef BOOST_HAS_PTHREADS +#endif + + + + diff --git a/win32/include/boost/config/platform/win32.hpp b/win32/include/boost/config/platform/win32.hpp new file mode 100755 index 000000000..d18b68918 --- /dev/null +++ b/win32/include/boost/config/platform/win32.hpp @@ -0,0 +1,58 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Bill Kempf 2001. +// (C) Copyright Aleksey Gurtovoy 2003. +// (C) Copyright Rene Rivera 2005. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Win32 specific config options: + +#define BOOST_PLATFORM "Win32" + +// Get the information about the MinGW runtime, i.e. __MINGW32_*VERSION. +#if defined(__MINGW32__) +# include <_mingw.h> +#endif + +#if defined(__GNUC__) && !defined(BOOST_NO_SWPRINTF) +# define BOOST_NO_SWPRINTF +#endif + +#if !defined(__GNUC__) && !defined(BOOST_HAS_DECLSPEC) +# define BOOST_HAS_DECLSPEC +#endif + +#if defined(__MINGW32__) && ((__MINGW32_MAJOR_VERSION > 2) || ((__MINGW32_MAJOR_VERSION == 2) && (__MINGW32_MINOR_VERSION >= 0))) +# define BOOST_HAS_STDINT_H +# define __STDC_LIMIT_MACROS +# define BOOST_HAS_DIRENT_H +# define BOOST_HAS_UNISTD_H +#endif + +// +// Win32 will normally be using native Win32 threads, +// but there is a pthread library avaliable as an option, +// we used to disable this when BOOST_DISABLE_WIN32 was +// defined but no longer - this should allow some +// files to be compiled in strict mode - while maintaining +// a consistent setting of BOOST_HAS_THREADS across +// all translation units (needed for shared_ptr etc). +// + +#ifdef _WIN32_WCE +# define BOOST_NO_ANSI_APIS +#endif + +#ifndef BOOST_HAS_PTHREADS +# define BOOST_HAS_WINTHREADS +#endif + +#ifndef BOOST_DISABLE_WIN32 +// WEK: Added +#define BOOST_HAS_FTIME +#define BOOST_WINDOWS 1 + +#endif diff --git a/win32/include/boost/config/posix_features.hpp b/win32/include/boost/config/posix_features.hpp new file mode 100755 index 000000000..bc3921cf8 --- /dev/null +++ b/win32/include/boost/config/posix_features.hpp @@ -0,0 +1,95 @@ +// (C) Copyright John Maddock 2001 - 2003. +// Use, modification and distribution are subject to 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) + + +// See http://www.boost.org for most recent version. + +// All POSIX feature tests go in this file, +// Note that we test _POSIX_C_SOURCE and _XOPEN_SOURCE as well +// _POSIX_VERSION and _XOPEN_VERSION: on some systems POSIX API's +// may be present but none-functional unless _POSIX_C_SOURCE and +// _XOPEN_SOURCE have been defined to the right value (it's up +// to the user to do this *before* including any header, although +// in most cases the compiler will do this for you). + +# if defined(BOOST_HAS_UNISTD_H) +# include + + // XOpen has , but is this the correct version check? +# if defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 3) +# define BOOST_HAS_NL_TYPES_H +# endif + + // POSIX version 6 requires +# if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 200100) +# define BOOST_HAS_STDINT_H +# endif + + // POSIX version 2 requires +# if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 199009L) +# define BOOST_HAS_DIRENT_H +# endif + + // POSIX version 3 requires to have sigaction: +# if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 199506L) +# define BOOST_HAS_SIGACTION +# endif + // POSIX defines _POSIX_THREADS > 0 for pthread support, + // however some platforms define _POSIX_THREADS without + // a value, hence the (_POSIX_THREADS+0 >= 0) check. + // Strictly speaking this may catch platforms with a + // non-functioning stub , but such occurrences should + // occur very rarely if at all. +# if defined(_POSIX_THREADS) && (_POSIX_THREADS+0 >= 0) && !defined(BOOST_HAS_WINTHREADS) && !defined(BOOST_HAS_MPTASKS) +# define BOOST_HAS_PTHREADS +# endif + + // BOOST_HAS_NANOSLEEP: + // This is predicated on _POSIX_TIMERS or _XOPEN_REALTIME: +# if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS+0 >= 0)) \ + || (defined(_XOPEN_REALTIME) && (_XOPEN_REALTIME+0 >= 0)) +# define BOOST_HAS_NANOSLEEP +# endif + + // BOOST_HAS_CLOCK_GETTIME: + // This is predicated on _POSIX_TIMERS (also on _XOPEN_REALTIME + // but at least one platform - linux - defines that flag without + // defining clock_gettime): +# if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS+0 >= 0)) +# define BOOST_HAS_CLOCK_GETTIME +# endif + + // BOOST_HAS_SCHED_YIELD: + // This is predicated on _POSIX_PRIORITY_SCHEDULING or + // on _POSIX_THREAD_PRIORITY_SCHEDULING or on _XOPEN_REALTIME. +# if defined(_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING+0 > 0)\ + || (defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING+0 > 0))\ + || (defined(_XOPEN_REALTIME) && (_XOPEN_REALTIME+0 >= 0)) +# define BOOST_HAS_SCHED_YIELD +# endif + + // BOOST_HAS_GETTIMEOFDAY: + // BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE: + // These are predicated on _XOPEN_VERSION, and appears to be first released + // in issue 4, version 2 (_XOPEN_VERSION > 500). + // Likewise for the functions log1p and expm1. +# if defined(_XOPEN_VERSION) && (_XOPEN_VERSION+0 >= 500) +# define BOOST_HAS_GETTIMEOFDAY +# if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE+0 >= 500) +# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# endif +# ifndef BOOST_HAS_LOG1P +# define BOOST_HAS_LOG1P +# endif +# ifndef BOOST_HAS_EXPM1 +# define BOOST_HAS_EXPM1 +# endif +# endif + +# endif + + + + diff --git a/win32/include/boost/config/requires_threads.hpp b/win32/include/boost/config/requires_threads.hpp new file mode 100755 index 000000000..b79723b88 --- /dev/null +++ b/win32/include/boost/config/requires_threads.hpp @@ -0,0 +1,92 @@ +// (C) Copyright John Maddock 2003. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_CONFIG_REQUIRES_THREADS_HPP +#define BOOST_CONFIG_REQUIRES_THREADS_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif + +#if defined(BOOST_DISABLE_THREADS) + +// +// special case to handle versions of gcc which don't currently support threads: +// +#if defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC_MINOR__ <= 3) || !defined(BOOST_STRICT_CONFIG)) +// +// this is checked up to gcc 3.3: +// +#if defined(__sgi) || defined(__hpux) +# error "Multi-threaded programs are not supported by gcc on HPUX or Irix (last checked with gcc 3.3)" +#endif + +#endif + +# error "Threading support unavaliable: it has been explicitly disabled with BOOST_DISABLE_THREADS" + +#elif !defined(BOOST_HAS_THREADS) + +# if defined __COMO__ +// Comeau C++ +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -D_MT (Windows) or -D_REENTRANT (Unix)" + +#elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) +// Intel +#ifdef _WIN32 +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: either /MT /MTd /MD or /MDd" +#else +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -openmp" +#endif + +# elif defined __GNUC__ +// GNU C++: +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)" + +#elif defined __sgi +// SGI MIPSpro C++ +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -D_SGI_MP_SOURCE" + +#elif defined __DECCXX +// Compaq Tru64 Unix cxx +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -pthread" + +#elif defined __BORLANDC__ +// Borland +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -tWM" + +#elif defined __MWERKS__ +// Metrowerks CodeWarrior +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: either -runtime sm, -runtime smd, -runtime dm, or -runtime dmd" + +#elif defined __SUNPRO_CC +// Sun Workshop Compiler C++ +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -mt" + +#elif defined __HP_aCC +// HP aCC +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: -mt" + +#elif defined(__IBMCPP__) +// IBM Visual Age +# error "Compiler threading support is not turned on. Please compile the code with the xlC_r compiler" + +#elif defined _MSC_VER +// Microsoft Visual C++ +// +// Must remain the last #elif since some other vendors (Metrowerks, for +// example) also #define _MSC_VER +# error "Compiler threading support is not turned on. Please set the correct command line options for threading: either /MT /MTd /MD or /MDd" + +#else + +# error "Compiler threading support is not turned on. Please consult your compiler's documentation for the appropriate options to use" + +#endif // compilers + +#endif // BOOST_HAS_THREADS + +#endif // BOOST_CONFIG_REQUIRES_THREADS_HPP diff --git a/win32/include/boost/config/select_compiler_config.hpp b/win32/include/boost/config/select_compiler_config.hpp new file mode 100755 index 000000000..0605fefd0 --- /dev/null +++ b/win32/include/boost/config/select_compiler_config.hpp @@ -0,0 +1,115 @@ +// Boost compiler configuration selection header file + +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Martin Wille 2003. +// (C) Copyright Guillaume Melquiond 2003. +// +// 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) + +// See http://www.boost.org/ for most recent version. + + +// one identification macro for each of the +// compilers we support: + +# define BOOST_CXX_GCCXML 0 +# define BOOST_CXX_COMO 0 +# define BOOST_CXX_DMC 0 +# define BOOST_CXX_INTEL 0 +# define BOOST_CXX_GNUC 0 +# define BOOST_CXX_KCC 0 +# define BOOST_CXX_SGI 0 +# define BOOST_CXX_TRU64 0 +# define BOOST_CXX_GHS 0 +# define BOOST_CXX_BORLAND 0 +# define BOOST_CXX_CW 0 +# define BOOST_CXX_SUNPRO 0 +# define BOOST_CXX_HPACC 0 +# define BOOST_CXX_MPW 0 +# define BOOST_CXX_IBMCPP 0 +# define BOOST_CXX_MSVC 0 +# define BOOST_CXX_PGI 0 + + +// locate which compiler we are using and define +// BOOST_COMPILER_CONFIG as needed: + +#if defined(__GCCXML__) +// GCC-XML emulates other compilers, it has to appear first here! +# define BOOST_COMPILER_CONFIG "boost/config/compiler/gcc_xml.hpp" + +#elif defined __COMO__ +// Comeau C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/comeau.hpp" + +#elif defined __DMC__ +// Digital Mars C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/digitalmars.hpp" + +#elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) +// Intel +# define BOOST_COMPILER_CONFIG "boost/config/compiler/intel.hpp" + +# elif defined __GNUC__ +// GNU C++: +# define BOOST_COMPILER_CONFIG "boost/config/compiler/gcc.hpp" + +#elif defined __KCC +// Kai C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/kai.hpp" + +#elif defined __sgi +// SGI MIPSpro C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/sgi_mipspro.hpp" + +#elif defined __DECCXX +// Compaq Tru64 Unix cxx +# define BOOST_COMPILER_CONFIG "boost/config/compiler/compaq_cxx.hpp" + +#elif defined __ghs +// Greenhills C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/greenhills.hpp" + +#elif defined __BORLANDC__ +// Borland +# define BOOST_COMPILER_CONFIG "boost/config/compiler/borland.hpp" + +#elif defined __MWERKS__ +// Metrowerks CodeWarrior +# define BOOST_COMPILER_CONFIG "boost/config/compiler/metrowerks.hpp" + +#elif defined __SUNPRO_CC +// Sun Workshop Compiler C++ +# define BOOST_COMPILER_CONFIG "boost/config/compiler/sunpro_cc.hpp" + +#elif defined __HP_aCC +// HP aCC +# define BOOST_COMPILER_CONFIG "boost/config/compiler/hp_acc.hpp" + +#elif defined(__MRC__) || defined(__SC__) +// MPW MrCpp or SCpp +# define BOOST_COMPILER_CONFIG "boost/config/compiler/mpw.hpp" + +#elif defined(__IBMCPP__) +// IBM Visual Age +# define BOOST_COMPILER_CONFIG "boost/config/compiler/vacpp.hpp" + +#elif defined(__PGI) +// Portland Group Inc. +# define BOOST_COMPILER_CONFIG "boost/config/compiler/pgi.hpp" + +#elif defined _MSC_VER +// Microsoft Visual C++ +// +// Must remain the last #elif since some other vendors (Metrowerks, for +// example) also #define _MSC_VER +# define BOOST_COMPILER_CONFIG "boost/config/compiler/visualc.hpp" + +#elif defined (BOOST_ASSERT_CONFIG) +// this must come last - generate an error if we don't +// recognise the compiler: +# error "Unknown compiler - please configure (http://www.boost.org/libs/config/config.htm#configuring) and report the results to the main boost mailing list (http://www.boost.org/more/mailing_lists.htm#main)" + +#endif diff --git a/win32/include/boost/config/select_platform_config.hpp b/win32/include/boost/config/select_platform_config.hpp new file mode 100755 index 000000000..3d3a69d30 --- /dev/null +++ b/win32/include/boost/config/select_platform_config.hpp @@ -0,0 +1,90 @@ +// Boost compiler configuration selection header file + +// (C) Copyright John Maddock 2001 - 2002. +// (C) Copyright Jens Maurer 2001. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// locate which platform we are on and define BOOST_PLATFORM_CONFIG as needed. +// Note that we define the headers to include using "header_name" not +// in order to prevent macro expansion within the header +// name (for example "linux" is a macro on linux systems). + +#if defined(linux) || defined(__linux) || defined(__linux__) +// linux: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/linux.hpp" + +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) +// BSD: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/bsd.hpp" + +#elif defined(sun) || defined(__sun) +// solaris: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/solaris.hpp" + +#elif defined(__sgi) +// SGI Irix: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/irix.hpp" + +#elif defined(__hpux) +// hp unix: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/hpux.hpp" + +#elif defined(__CYGWIN__) +// cygwin is not win32: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/cygwin.hpp" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +// win32: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/win32.hpp" + +#elif defined(__BEOS__) +// BeOS +# define BOOST_PLATFORM_CONFIG "boost/config/platform/beos.hpp" + +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +// MacOS +# define BOOST_PLATFORM_CONFIG "boost/config/platform/macos.hpp" + +#elif defined(__IBMCPP__) || defined(_AIX) +// IBM +# define BOOST_PLATFORM_CONFIG "boost/config/platform/aix.hpp" + +#elif defined(__amigaos__) +// AmigaOS +# define BOOST_PLATFORM_CONFIG "boost/config/platform/amigaos.hpp" + +#elif defined(__QNXNTO__) +// QNX: +# define BOOST_PLATFORM_CONFIG "boost/config/platform/qnxnto.hpp" + +#else + +# if defined(unix) \ + || defined(__unix) \ + || defined(_XOPEN_SOURCE) \ + || defined(_POSIX_SOURCE) + + // generic unix platform: + +# ifndef BOOST_HAS_UNISTD_H +# define BOOST_HAS_UNISTD_H +# endif + +# include + +# endif + +# if defined (BOOST_ASSERT_CONFIG) + // this must come last - generate an error if we don't + // recognise the platform: +# error "Unknown platform - please configure and report the results to boost.org" +# endif + +#endif + + + diff --git a/win32/include/boost/config/select_stdlib_config.hpp b/win32/include/boost/config/select_stdlib_config.hpp new file mode 100755 index 000000000..7c094fc38 --- /dev/null +++ b/win32/include/boost/config/select_stdlib_config.hpp @@ -0,0 +1,68 @@ +// Boost compiler configuration selection header file + +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2001 - 2002. +// Use, modification and distribution are subject to 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) + + +// See http://www.boost.org for most recent version. + +// locate which std lib we are using and define BOOST_STDLIB_CONFIG as needed: + +// we need to include a std lib header here in order to detect which +// library is in use, use as it's about the smallest +// of the std lib headers - do not rely on this header being included - +// users can short-circuit this header if they know whose std lib +// they are using. + +#include + +#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION) +// STLPort library; this _must_ come first, otherwise since +// STLport typically sits on top of some other library, we +// can end up detecting that first rather than STLport: +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/stlport.hpp" + +#elif defined(__LIBCOMO__) +// Comeau STL: +#define BOOST_STDLIB_CONFIG "boost/config/stdlib/libcomo.hpp" + +#elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER) +// Rogue Wave library: +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/roguewave.hpp" + +#elif defined(__GLIBCPP__) || defined(__GLIBCXX__) +// GNU libstdc++ 3 +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/libstdcpp3.hpp" + +#elif defined(__STL_CONFIG_H) +// generic SGI STL +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/sgi.hpp" + +#elif defined(__MSL_CPP__) +// MSL standard lib: +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/msl.hpp" + +#elif defined(__IBMCPP__) +// take the default VACPP std lib +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/vacpp.hpp" + +#elif defined(MSIPL_COMPILE_H) +// Modena C++ standard library +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/modena.hpp" + +#elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER) +// Dinkumware Library (this has to appear after any possible replacement libraries): +# define BOOST_STDLIB_CONFIG "boost/config/stdlib/dinkumware.hpp" + +#elif defined (BOOST_ASSERT_CONFIG) +// this must come last - generate an error if we don't +// recognise the library: +# error "Unknown standard library - please configure and report the results to boost.org" + +#endif + + + diff --git a/win32/include/boost/config/stdlib/dinkumware.hpp b/win32/include/boost/config/stdlib/dinkumware.hpp new file mode 100755 index 000000000..fb6e10182 --- /dev/null +++ b/win32/include/boost/config/stdlib/dinkumware.hpp @@ -0,0 +1,106 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2001. +// (C) Copyright Peter Dimov 2001. +// (C) Copyright David Abrahams 2002. +// (C) Copyright Guillaume Melquiond 2003. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Dinkumware standard library config: + +#if !defined(_YVALS) && !defined(_CPPLIB_VER) +#include +#if !defined(_YVALS) && !defined(_CPPLIB_VER) +#error This is not the Dinkumware lib! +#endif +#endif + + +#if defined(_CPPLIB_VER) && (_CPPLIB_VER >= 306) + // full dinkumware 3.06 and above + // fully conforming provided the compiler supports it: +# if !(defined(_GLOBAL_USING) && (_GLOBAL_USING+0 > 0)) && !defined(__BORLANDC__) && !defined(_STD) && !(defined(__ICC) && (__ICC >= 700)) // can be defined in yvals.h +# define BOOST_NO_STDC_NAMESPACE +# endif +# if !(defined(_HAS_MEMBER_TEMPLATES_REBIND) && (_HAS_MEMBER_TEMPLATES_REBIND+0 > 0)) && !(defined(_MSC_VER) && (_MSC_VER > 1300)) && defined(BOOST_MSVC) +# define BOOST_NO_STD_ALLOCATOR +# endif +# define BOOST_HAS_PARTIAL_STD_ALLOCATOR +# if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) + // if this lib version is set up for vc6 then there is no std::use_facet: +# define BOOST_NO_STD_USE_FACET +# define BOOST_HAS_TWO_ARG_USE_FACET + // C lib functions aren't in namespace std either: +# define BOOST_NO_STDC_NAMESPACE + // and nor is +# define BOOST_NO_EXCEPTION_STD_NAMESPACE +# endif +// There's no numeric_limits support unless _LONGLONG is defined: +# if !defined(_LONGLONG) && (_CPPLIB_VER <= 310) +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +# endif +// 3.06 appears to have (non-sgi versions of) & , +// and no at all +#else +# define BOOST_MSVC_STD_ITERATOR 1 +# define BOOST_NO_STD_ITERATOR +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +# define BOOST_NO_STD_ALLOCATOR +# define BOOST_NO_STDC_NAMESPACE +# define BOOST_NO_STD_USE_FACET +# define BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN +# define BOOST_HAS_MACRO_USE_FACET +# ifndef _CPPLIB_VER + // Updated Dinkum library defines this, and provides + // its own min and max definitions. +# define BOOST_NO_STD_MIN_MAX +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +# endif +#endif + +// +// std extension namespace is stdext for vc7.1 and later, +// the same applies to other compilers that sit on top +// of vc7.1 (Intel and Comeau): +// +#if defined(_MSC_VER) && (_MSC_VER >= 1310) && !defined(__BORLANDC__) +# define BOOST_STD_EXTENSION_NAMESPACE stdext +#endif + + +#if (defined(_MSC_VER) && (_MSC_VER <= 1300) && !defined(__BORLANDC__)) || !defined(_CPPLIB_VER) || (_CPPLIB_VER < 306) + // if we're using a dinkum lib that's + // been configured for VC6/7 then there is + // no iterator traits (true even for icl) +# define BOOST_NO_STD_ITERATOR_TRAITS +#endif + +#if defined(__ICL) && (__ICL < 800) && defined(_CPPLIB_VER) && (_CPPLIB_VER <= 310) +// Intel C++ chokes over any non-trivial use of +// this may be an overly restrictive define, but regex fails without it: +# define BOOST_NO_STD_LOCALE +#endif + +#ifdef _CPPLIB_VER +# define BOOST_DINKUMWARE_STDLIB _CPPLIB_VER +#else +# define BOOST_DINKUMWARE_STDLIB 1 +#endif + +#ifdef _CPPLIB_VER +# define BOOST_STDLIB "Dinkumware standard library version " BOOST_STRINGIZE(_CPPLIB_VER) +#else +# define BOOST_STDLIB "Dinkumware standard library version 1.x" +#endif + + + + + + + + + diff --git a/win32/include/boost/config/stdlib/libcomo.hpp b/win32/include/boost/config/stdlib/libcomo.hpp new file mode 100755 index 000000000..74cbb8c66 --- /dev/null +++ b/win32/include/boost/config/stdlib/libcomo.hpp @@ -0,0 +1,46 @@ +// (C) Copyright John Maddock 2002 - 2003. +// (C) Copyright Jens Maurer 2002 - 2003. +// (C) Copyright Beman Dawes 2002 - 2003. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Comeau STL: + +#if !defined(__LIBCOMO__) +# include +# if !defined(__LIBCOMO__) +# error "This is not the Comeau STL!" +# endif +#endif + +// +// std::streambuf is non-standard +// NOTE: versions of libcomo prior to beta28 have octal version numbering, +// e.g. version 25 is 21 (dec) +#if __LIBCOMO_VERSION__ <= 22 +# define BOOST_NO_STD_WSTREAMBUF +#endif + +#if (__LIBCOMO_VERSION__ <= 31) && defined(_WIN32) +#define BOOST_NO_SWPRINTF +#endif + +#if __LIBCOMO_VERSION__ >= 31 +# define BOOST_HAS_HASH +# define BOOST_HAS_SLIST +#endif + +// +// Intrinsic type_traits support. +// The SGI STL has it's own __type_traits class, which +// has intrinsic compiler support with SGI's compilers. +// Whatever map SGI style type traits to boost equivalents: +// +#define BOOST_HAS_SGI_TYPE_TRAITS + +#define BOOST_STDLIB "Comeau standard library " BOOST_STRINGIZE(__LIBCOMO_VERSION__) + + diff --git a/win32/include/boost/config/stdlib/libstdcpp3.hpp b/win32/include/boost/config/stdlib/libstdcpp3.hpp new file mode 100755 index 000000000..ab48ecf3d --- /dev/null +++ b/win32/include/boost/config/stdlib/libstdcpp3.hpp @@ -0,0 +1,78 @@ +// (C) Copyright John Maddock 2001. +// (C) Copyright Jens Maurer 2001. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// config for libstdc++ v3 +// not much to go in here: + +#ifdef __GLIBCXX__ +#define BOOST_STDLIB "GNU libstdc++ version " BOOST_STRINGIZE(__GLIBCXX__) +#else +#define BOOST_STDLIB "GNU libstdc++ version " BOOST_STRINGIZE(__GLIBCPP__) +#endif + +#if !defined(_GLIBCPP_USE_WCHAR_T) && !defined(_GLIBCXX_USE_WCHAR_T) +# define BOOST_NO_CWCHAR +# define BOOST_NO_CWCTYPE +# define BOOST_NO_STD_WSTRING +# define BOOST_NO_STD_WSTREAMBUF +#endif + +#if defined(__osf__) && !defined(_REENTRANT) \ + && ( defined(_GLIBCXX_HAVE_GTHR_DEFAULT) || defined(_GLIBCPP_HAVE_GTHR_DEFAULT) ) +// GCC 3 on Tru64 forces the definition of _REENTRANT when any std lib header +// file is included, therefore for consistency we define it here as well. +# define _REENTRANT +#endif + +#ifdef __GLIBCXX__ // gcc 3.4 and greater: +# if defined(_GLIBCXX_HAVE_GTHR_DEFAULT) \ + || defined(_GLIBCXX__PTHREADS) + // + // If the std lib has thread support turned on, then turn it on in Boost + // as well. We do this because some gcc-3.4 std lib headers define _REENTANT + // while others do not... + // +# define BOOST_HAS_THREADS +# else +# define BOOST_DISABLE_THREADS +# endif +#elif defined(__GLIBCPP__) \ + && !defined(_GLIBCPP_HAVE_GTHR_DEFAULT) \ + && !defined(_GLIBCPP__PTHREADS) + // disable thread support if the std lib was built single threaded: +# define BOOST_DISABLE_THREADS +#endif + +#if (defined(linux) || defined(__linux) || defined(__linux__)) && defined(__arm__) && defined(_GLIBCPP_HAVE_GTHR_DEFAULT) +// linux on arm apparently doesn't define _REENTRANT +// so just turn on threading support whenever the std lib is thread safe: +# define BOOST_HAS_THREADS +#endif + + +#if !defined(_GLIBCPP_USE_LONG_LONG) \ + && !defined(_GLIBCXX_USE_LONG_LONG)\ + && defined(BOOST_HAS_LONG_LONG) +// May have been set by compiler/*.hpp, but "long long" without library +// support is useless. +# undef BOOST_HAS_LONG_LONG +#endif + +#if defined(__GLIBCXX__) || (defined(__GLIBCPP__) && __GLIBCPP__>=20020514) // GCC >= 3.1.0 +# define BOOST_STD_EXTENSION_NAMESPACE __gnu_cxx +# define BOOST_HAS_SLIST +# define BOOST_HAS_HASH +# define BOOST_SLIST_HEADER +# if !defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) +# define BOOST_HASH_SET_HEADER +# define BOOST_HASH_MAP_HEADER +# else +# define BOOST_HASH_SET_HEADER +# define BOOST_HASH_MAP_HEADER +# endif +#endif diff --git a/win32/include/boost/config/stdlib/modena.hpp b/win32/include/boost/config/stdlib/modena.hpp new file mode 100755 index 000000000..40b851e60 --- /dev/null +++ b/win32/include/boost/config/stdlib/modena.hpp @@ -0,0 +1,30 @@ +// (C) Copyright Jens Maurer 2001. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Modena C++ standard library (comes with KAI C++) + +#if !defined(MSIPL_COMPILE_H) +# include +# if !defined(__MSIPL_COMPILE_H) +# error "This is not the Modena C++ library!" +# endif +#endif + +#ifndef MSIPL_NL_TYPES +#define BOOST_NO_STD_MESSAGES +#endif + +#ifndef MSIPL_WCHART +#define BOOST_NO_STD_WSTRING +#endif + +#define BOOST_STDLIB "Modena C++ standard library" + + + + + diff --git a/win32/include/boost/config/stdlib/msl.hpp b/win32/include/boost/config/stdlib/msl.hpp new file mode 100755 index 000000000..d6ccdd25a --- /dev/null +++ b/win32/include/boost/config/stdlib/msl.hpp @@ -0,0 +1,59 @@ +// (C) Copyright John Maddock 2001. +// (C) Copyright Darin Adler 2001. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Metrowerks standard library: + +#ifndef __MSL_CPP__ +# include +# ifndef __MSL_CPP__ +# error This is not the MSL standard library! +# endif +#endif + +#if __MSL_CPP__ >= 0x6000 // Pro 6 +# define BOOST_HAS_HASH +# define BOOST_STD_EXTENSION_NAMESPACE Metrowerks +#endif +#define BOOST_HAS_SLIST + +#if __MSL_CPP__ < 0x6209 +# define BOOST_NO_STD_MESSAGES +#endif + +// check C lib version for +#include + +#if defined(__MSL__) && (__MSL__ >= 0x5000) +# define BOOST_HAS_STDINT_H +# if !defined(__PALMOS_TRAPS__) +# define BOOST_HAS_UNISTD_H +# endif + // boilerplate code: +# include +#endif + +#if defined(_MWMT) || _MSL_THREADSAFE +# define BOOST_HAS_THREADS +#endif + +#ifdef _MSL_NO_EXPLICIT_FUNC_TEMPLATE_ARG +# define BOOST_NO_STD_USE_FACET +# define BOOST_HAS_TWO_ARG_USE_FACET +#endif + + +#define BOOST_STDLIB "Metrowerks Standard Library version " BOOST_STRINGIZE(__MSL_CPP__) + + + + + + + + + diff --git a/win32/include/boost/config/stdlib/roguewave.hpp b/win32/include/boost/config/stdlib/roguewave.hpp new file mode 100755 index 000000000..524742a63 --- /dev/null +++ b/win32/include/boost/config/stdlib/roguewave.hpp @@ -0,0 +1,153 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2001. +// (C) Copyright David Abrahams 2003. +// (C) Copyright Boris Gubenko 2007. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Rogue Wave std lib: + +#if !defined(__STD_RWCOMPILER_H__) && !defined(_RWSTD_VER) +# include +# if !defined(__STD_RWCOMPILER_H__) && !defined(_RWSTD_VER) +# error This is not the Rogue Wave standard library +# endif +#endif +// +// figure out a consistent version number: +// +#ifndef _RWSTD_VER +# define BOOST_RWSTD_VER 0x010000 +#elif _RWSTD_VER < 0x010000 +# define BOOST_RWSTD_VER (_RWSTD_VER << 8) +#else +# define BOOST_RWSTD_VER _RWSTD_VER +#endif + +#ifndef _RWSTD_VER +# define BOOST_STDLIB "Rogue Wave standard library version (Unknown version)" +#elif _RWSTD_VER < 0x04010200 + # define BOOST_STDLIB "Rogue Wave standard library version " BOOST_STRINGIZE(_RWSTD_VER) +#else +# ifdef _RWSTD_VER_STR +# define BOOST_STDLIB "Apache STDCXX standard library version " _RWSTD_VER_STR +# else +# define BOOST_STDLIB "Apache STDCXX standard library version " BOOST_STRINGIZE(_RWSTD_VER) +# endif +#endif + +// +// Prior to version 2.2.0 the primary template for std::numeric_limits +// does not have compile time constants, even though specializations of that +// template do: +// +#if BOOST_RWSTD_VER < 0x020200 +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#endif + +// Sun CC 5.5 patch 113817-07 adds long long specialization, but does not change the +// library version number (http://sunsolve6.sun.com/search/document.do?assetkey=1-21-113817): +#if BOOST_RWSTD_VER <= 0x020101 && (!defined(__SUNPRO_CC) || (__SUNPRO_CC < 0x550)) +# define BOOST_NO_LONG_LONG_NUMERIC_LIMITS +# endif + +// +// Borland version of numeric_limits lacks __int64 specialisation: +// +#ifdef __BORLANDC__ +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +#endif + +// +// No std::iterator if it can't figure out default template args: +// +#if defined(_RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES) || defined(RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES) || (BOOST_RWSTD_VER < 0x020000) +# define BOOST_NO_STD_ITERATOR +#endif + +// +// No iterator traits without partial specialization: +// +#if defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) || defined(RWSTD_NO_CLASS_PARTIAL_SPEC) +# define BOOST_NO_STD_ITERATOR_TRAITS +#endif + +// +// Prior to version 2.0, std::auto_ptr was buggy, and there were no +// new-style iostreams, and no conformant std::allocator: +// +#if (BOOST_RWSTD_VER < 0x020000) +# define BOOST_NO_AUTO_PTR +# define BOOST_NO_STRINGSTREAM +# define BOOST_NO_STD_ALLOCATOR +# define BOOST_NO_STD_LOCALE +#endif + +// +// No template iterator constructors without member template support: +// +#if defined(RWSTD_NO_MEMBER_TEMPLATES) || defined(_RWSTD_NO_MEMBER_TEMPLATES) +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +#endif + +// +// RW defines _RWSTD_ALLOCATOR if the allocator is conformant and in use +// (the or _HPACC_ part is a hack - the library seems to define _RWSTD_ALLOCATOR +// on HP aCC systems even though the allocator is in fact broken): +// +#if !defined(_RWSTD_ALLOCATOR) || (defined(__HP_aCC) && __HP_aCC <= 33100) +# define BOOST_NO_STD_ALLOCATOR +#endif + +// +// If we have a std::locale, we still may not have std::use_facet: +// +#if defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE) && !defined(BOOST_NO_STD_LOCALE) +# define BOOST_NO_STD_USE_FACET +# define BOOST_HAS_TWO_ARG_USE_FACET +#endif + +// +// There's no std::distance prior to version 2, or without +// partial specialization support: +// +#if (BOOST_RWSTD_VER < 0x020000) || defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) + #define BOOST_NO_STD_DISTANCE +#endif + +// +// Some versions of the rogue wave library don't have assignable +// OutputIterators: +// +#if BOOST_RWSTD_VER < 0x020100 +# define BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN +#endif + +// +// Disable BOOST_HAS_LONG_LONG when the library has no support for it. +// +#if !defined(_RWSTD_LONG_LONG) && defined(BOOST_HAS_LONG_LONG) +# undef BOOST_HAS_LONG_LONG +#endif + +// +// check that on HP-UX, the proper RW library is used +// +#if defined(__HP_aCC) && !defined(_HP_NAMESPACE_STD) +# error "Boost requires Standard RW library. Please compile and link with -AA" +#endif + +// +// Define macros specific to RW V2.2 on HP-UX +// +#if defined(__HP_aCC) && (BOOST_RWSTD_VER == 0x02020100) +# ifndef __HP_TC1_MAKE_PAIR +# define __HP_TC1_MAKE_PAIR +# endif +# ifndef _HP_INSTANTIATE_STD2_VL +# define _HP_INSTANTIATE_STD2_VL +# endif +#endif diff --git a/win32/include/boost/config/stdlib/sgi.hpp b/win32/include/boost/config/stdlib/sgi.hpp new file mode 100755 index 000000000..6e9c55b87 --- /dev/null +++ b/win32/include/boost/config/stdlib/sgi.hpp @@ -0,0 +1,111 @@ +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Darin Adler 2001. +// (C) Copyright Jens Maurer 2001 - 2003. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// generic SGI STL: + +#if !defined(__STL_CONFIG_H) +# include +# if !defined(__STL_CONFIG_H) +# error "This is not the SGI STL!" +# endif +#endif + +// +// No std::iterator traits without partial specialisation: +// +#if !defined(__STL_CLASS_PARTIAL_SPECIALIZATION) +# define BOOST_NO_STD_ITERATOR_TRAITS +#endif + +// +// No std::stringstream with gcc < 3 +// +#if defined(__GNUC__) && (__GNUC__ < 3) && \ + ((__GNUC_MINOR__ < 95) || (__GNUC_MINOR__ == 96)) && \ + !defined(__STL_USE_NEW_IOSTREAMS) || \ + defined(__APPLE_CC__) + // Note that we only set this for GNU C++ prior to 2.95 since the + // latest patches for that release do contain a minimal + // If you are running a 2.95 release prior to 2.95.3 then this will need + // setting, but there is no way to detect that automatically (other + // than by running the configure script). + // Also, the unofficial GNU C++ 2.96 included in RedHat 7.1 doesn't + // have . +# define BOOST_NO_STRINGSTREAM +#endif + +// +// Assume no std::locale without own iostreams (this may be an +// incorrect assumption in some cases): +// +#if !defined(__SGI_STL_OWN_IOSTREAMS) && !defined(__STL_USE_NEW_IOSTREAMS) +# define BOOST_NO_STD_LOCALE +#endif + +// +// Original native SGI streams have non-standard std::messages facet: +// +#if defined(__sgi) && (_COMPILER_VERSION <= 650) && !defined(__SGI_STL_OWN_IOSTREAMS) +# define BOOST_NO_STD_LOCALE +#endif + +// +// SGI's new iostreams have missing "const" in messages<>::open +// +#if defined(__sgi) && (_COMPILER_VERSION <= 740) && defined(__STL_USE_NEW_IOSTREAMS) +# define BOOST_NO_STD_MESSAGES +#endif + +// +// No template iterator constructors, or std::allocator +// without member templates: +// +#if !defined(__STL_MEMBER_TEMPLATES) +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +# define BOOST_NO_STD_ALLOCATOR +#endif + +// +// We always have SGI style hash_set, hash_map, and slist: +// +#define BOOST_HAS_HASH +#define BOOST_HAS_SLIST + +// +// If this is GNU libstdc++2, then no and no std::wstring: +// +#if (defined(__GNUC__) && (__GNUC__ < 3)) +# include +# if defined(__BASTRING__) +# define BOOST_NO_LIMITS +// Note: will provide compile-time constants +# undef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +# define BOOST_NO_STD_WSTRING +# endif +#endif + +// +// There is no standard iterator unless we have namespace support: +// +#if !defined(__STL_USE_NAMESPACES) +# define BOOST_NO_STD_ITERATOR +#endif + +// +// Intrinsic type_traits support. +// The SGI STL has it's own __type_traits class, which +// has intrinsic compiler support with SGI's compilers. +// Whatever map SGI style type traits to boost equivalents: +// +#define BOOST_HAS_SGI_TYPE_TRAITS + +#define BOOST_STDLIB "SGI standard library" + + + diff --git a/win32/include/boost/config/stdlib/stlport.hpp b/win32/include/boost/config/stdlib/stlport.hpp new file mode 100755 index 000000000..8adfb2971 --- /dev/null +++ b/win32/include/boost/config/stdlib/stlport.hpp @@ -0,0 +1,203 @@ +// (C) Copyright John Maddock 2001 - 2002. +// (C) Copyright Darin Adler 2001. +// (C) Copyright Jens Maurer 2001. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// STLPort standard library config: + +#if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) +# include +# if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) +# error "This is not STLPort!" +# endif +#endif + +// +// __STL_STATIC_CONST_INIT_BUG implies BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +// for versions prior to 4.1(beta) +// +#if (defined(__STL_STATIC_CONST_INIT_BUG) || defined(_STLP_STATIC_CONST_INIT_BUG)) && (__SGI_STL_PORT <= 0x400) +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +#endif + +// +// If STLport thinks that there is no partial specialisation, then there is no +// std::iterator traits: +// +#if !(defined(_STLP_CLASS_PARTIAL_SPECIALIZATION) || defined(__STL_CLASS_PARTIAL_SPECIALIZATION)) +# define BOOST_NO_STD_ITERATOR_TRAITS +#endif + +// +// No new style iostreams on GCC without STLport's iostreams enabled: +// +#if (defined(__GNUC__) && (__GNUC__ < 3)) && !(defined(__SGI_STL_OWN_IOSTREAMS) || defined(_STLP_OWN_IOSTREAMS)) +# define BOOST_NO_STRINGSTREAM +#endif + +// +// No new iostreams implies no std::locale, and no std::stringstream: +// +#if defined(__STL_NO_IOSTREAMS) || defined(__STL_NO_NEW_IOSTREAMS) || defined(_STLP_NO_IOSTREAMS) || defined(_STLP_NO_NEW_IOSTREAMS) +# define BOOST_NO_STD_LOCALE +# define BOOST_NO_STRINGSTREAM +#endif + +// +// If the streams are not native, and we have a "using ::x" compiler bug +// then the io stream facets are not available in namespace std:: +// +#ifdef _STLPORT_VERSION +# if !(_STLPORT_VERSION >= 0x500) && !defined(_STLP_OWN_IOSTREAMS) && defined(_STLP_USE_NAMESPACES) && defined(BOOST_NO_USING_TEMPLATE) && !defined(__BORLANDC__) +# define BOOST_NO_STD_LOCALE +# endif +#else +# if !defined(__SGI_STL_OWN_IOSTREAMS) && defined(__STL_USE_NAMESPACES) && defined(BOOST_NO_USING_TEMPLATE) && !defined(__BORLANDC__) +# define BOOST_NO_STD_LOCALE +# endif +#endif + +// +// Without member template support enabled, their are no template +// iterate constructors, and no std::allocator: +// +#if !(defined(__STL_MEMBER_TEMPLATES) || defined(_STLP_MEMBER_TEMPLATES)) +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +# define BOOST_NO_STD_ALLOCATOR +#endif +// +// however we always have at least a partial allocator: +// +#define BOOST_HAS_PARTIAL_STD_ALLOCATOR + +#if !defined(_STLP_MEMBER_TEMPLATE_CLASSES) || defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) +# define BOOST_NO_STD_ALLOCATOR +#endif + +#if defined(_STLP_NO_MEMBER_TEMPLATE_KEYWORD) && defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) +# define BOOST_NO_STD_ALLOCATOR +#endif + +// +// If STLport thinks there is no wchar_t at all, then we have to disable +// the support for the relevant specilazations of std:: templates. +// +#if !defined(_STLP_HAS_WCHAR_T) && !defined(_STLP_WCHAR_T_IS_USHORT) +# ifndef BOOST_NO_STD_WSTRING +# define BOOST_NO_STD_WSTRING +# endif +# ifndef BOOST_NO_STD_WSTREAMBUF +# define BOOST_NO_STD_WSTREAMBUF +# endif +#endif + +// +// We always have SGI style hash_set, hash_map, and slist: +// +#ifndef _STLP_NO_EXTENSIONS +#define BOOST_HAS_HASH +#define BOOST_HAS_SLIST +#endif + +// +// STLport does a good job of importing names into namespace std::, +// but doesn't always get them all, define BOOST_NO_STDC_NAMESPACE, since our +// workaround does not conflict with STLports: +// +// +// Harold Howe says: +// Borland switched to STLport in BCB6. Defining BOOST_NO_STDC_NAMESPACE with +// BCB6 does cause problems. If we detect C++ Builder, then don't define +// BOOST_NO_STDC_NAMESPACE +// +#if !defined(__BORLANDC__) && !defined(__DMC__) +// +// If STLport is using it's own namespace, and the real names are in +// the global namespace, then we duplicate STLport's using declarations +// (by defining BOOST_NO_STDC_NAMESPACE), we do this because STLport doesn't +// necessarily import all the names we need into namespace std:: +// +# if (defined(__STL_IMPORT_VENDOR_CSTD) \ + || defined(__STL_USE_OWN_NAMESPACE) \ + || defined(_STLP_IMPORT_VENDOR_CSTD) \ + || defined(_STLP_USE_OWN_NAMESPACE)) \ + && (defined(__STL_VENDOR_GLOBAL_CSTD) || defined (_STLP_VENDOR_GLOBAL_CSTD)) +# define BOOST_NO_STDC_NAMESPACE +# define BOOST_NO_EXCEPTION_STD_NAMESPACE +# endif +#elif defined(__BORLANDC__) && __BORLANDC__ < 0x560 +// STLport doesn't import std::abs correctly: +#include +namespace std { using ::abs; } +// and strcmp/strcpy don't get imported either ('cos they are macros) +#include +#ifdef strcpy +# undef strcpy +#endif +#ifdef strcmp +# undef strcmp +#endif +#ifdef _STLP_VENDOR_CSTD +namespace std{ using _STLP_VENDOR_CSTD::strcmp; using _STLP_VENDOR_CSTD::strcpy; } +#endif +#endif + +// +// std::use_facet may be non-standard, uses a class instead: +// +#if defined(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) || defined(_STLP_NO_EXPLICIT_FUNCTION_TMPL_ARGS) +# define BOOST_NO_STD_USE_FACET +# define BOOST_HAS_STLP_USE_FACET +#endif + +// +// If STLport thinks there are no wide functions, etc. is not working; but +// only if BOOST_NO_STDC_NAMESPACE is not defined (if it is then we do the import +// into std:: ourselves). +// +#if defined(_STLP_NO_NATIVE_WIDE_FUNCTIONS) && !defined(BOOST_NO_STDC_NAMESPACE) +# define BOOST_NO_CWCHAR +# define BOOST_NO_CWCTYPE +#endif + +// +// If STLport for some reason was configured so that it thinks that wchar_t +// is not an intrinsic type, then we have to disable the support for it as +// well (we would be missing required specializations otherwise). +// +#if !defined( _STLP_HAS_WCHAR_T) || defined(_STLP_WCHAR_T_IS_USHORT) +# undef BOOST_NO_INTRINSIC_WCHAR_T +# define BOOST_NO_INTRINSIC_WCHAR_T +#endif + +// +// Borland ships a version of STLport with C++ Builder 6 that lacks +// hashtables and the like: +// +#if defined(__BORLANDC__) && (__BORLANDC__ == 0x560) +# undef BOOST_HAS_HASH +#endif + +// +// gcc-2.95.3/STLPort does not like the using declarations we use to get ADL with std::min/max +// +#if defined(__GNUC__) && (__GNUC__ < 3) +# include // for std::min and std::max +# define BOOST_USING_STD_MIN() ((void)0) +# define BOOST_USING_STD_MAX() ((void)0) +namespace boost { using std::min; using std::max; } +#endif + +#define BOOST_STDLIB "STLPort standard library version " BOOST_STRINGIZE(__SGI_STL_PORT) + + + + + + + + diff --git a/win32/include/boost/config/stdlib/vacpp.hpp b/win32/include/boost/config/stdlib/vacpp.hpp new file mode 100755 index 000000000..1e2c8b34a --- /dev/null +++ b/win32/include/boost/config/stdlib/vacpp.hpp @@ -0,0 +1,18 @@ +// (C) Copyright John Maddock 2001 - 2002. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +#if __IBMCPP__ <= 501 +# define BOOST_NO_STD_ALLOCATOR +#endif + +#define BOOST_HAS_MACRO_USE_FACET +#define BOOST_NO_STD_MESSAGES + +#define BOOST_STDLIB "Visual Age default standard library" + + + diff --git a/win32/include/boost/config/suffix.hpp b/win32/include/boost/config/suffix.hpp new file mode 100755 index 000000000..e1d1a3660 --- /dev/null +++ b/win32/include/boost/config/suffix.hpp @@ -0,0 +1,577 @@ +// Boost config.hpp configuration header file ------------------------------// + +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Darin Adler 2001. +// (C) Copyright Peter Dimov 2001. +// (C) Copyright Bill Kempf 2002. +// (C) Copyright Jens Maurer 2002. +// (C) Copyright David Abrahams 2002 - 2003. +// (C) Copyright Gennaro Prota 2003. +// (C) Copyright Eric Friedman 2003. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org for most recent version. + +// Boost config.hpp policy and rationale documentation has been moved to +// http://www.boost.org/libs/config +// +// This file is intended to be stable, and relatively unchanging. +// It should contain boilerplate code only - no compiler specific +// code unless it is unavoidable - no changes unless unavoidable. + +#ifndef BOOST_CONFIG_SUFFIX_HPP +#define BOOST_CONFIG_SUFFIX_HPP + +// +// look for long long by looking for the appropriate macros in . +// Note that we use limits.h rather than climits for maximal portability, +// remember that since these just declare a bunch of macros, there should be +// no namespace issues from this. +// +#if !defined(BOOST_HAS_LONG_LONG) \ + && !defined(BOOST_MSVC) && !defined(__BORLANDC__) +# include +# if (defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) || defined(ULONGLONG_MAX)) +# define BOOST_HAS_LONG_LONG +# endif +#endif + +// GCC 3.x will clean up all of those nasty macro definitions that +// BOOST_NO_CTYPE_FUNCTIONS is intended to help work around, so undefine +// it under GCC 3.x. +#if defined(__GNUC__) && (__GNUC__ >= 3) && defined(BOOST_NO_CTYPE_FUNCTIONS) +# undef BOOST_NO_CTYPE_FUNCTIONS +#endif + +// +// Assume any extensions are in namespace std:: unless stated otherwise: +// +# ifndef BOOST_STD_EXTENSION_NAMESPACE +# define BOOST_STD_EXTENSION_NAMESPACE std +# endif + +// +// If cv-qualified specializations are not allowed, then neither are cv-void ones: +// +# if defined(BOOST_NO_CV_SPECIALIZATIONS) \ + && !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) +# define BOOST_NO_CV_VOID_SPECIALIZATIONS +# endif + +// +// If there is no numeric_limits template, then it can't have any compile time +// constants either! +// +# if defined(BOOST_NO_LIMITS) \ + && !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) +# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +# define BOOST_NO_LONG_LONG_NUMERIC_LIMITS +# endif + +// +// if there is no long long then there is no specialisation +// for numeric_limits either: +// +#if !defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_LONG_LONG_NUMERIC_LIMITS) +# define BOOST_NO_LONG_LONG_NUMERIC_LIMITS +#endif + +// +// if there is no __int64 then there is no specialisation +// for numeric_limits<__int64> either: +// +#if !defined(BOOST_HAS_MS_INT64) && !defined(BOOST_NO_MS_INT64_NUMERIC_LIMITS) +# define BOOST_NO_MS_INT64_NUMERIC_LIMITS +#endif + +// +// if member templates are supported then so is the +// VC6 subset of member templates: +// +# if !defined(BOOST_NO_MEMBER_TEMPLATES) \ + && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) +# define BOOST_MSVC6_MEMBER_TEMPLATES +# endif + +// +// Without partial specialization, can't test for partial specialisation bugs: +// +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) +# define BOOST_BCB_PARTIAL_SPECIALIZATION_BUG +# endif + +// +// Without partial specialization, we can't have array-type partial specialisations: +// +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS) +# define BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS +# endif + +// +// Without partial specialization, std::iterator_traits can't work: +// +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_NO_STD_ITERATOR_TRAITS) +# define BOOST_NO_STD_ITERATOR_TRAITS +# endif + +// +// Without partial specialization, partial +// specialization with default args won't work either: +// +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) +# define BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS +# endif + +// +// Without member template support, we can't have template constructors +// in the standard library either: +// +# if defined(BOOST_NO_MEMBER_TEMPLATES) \ + && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) \ + && !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS) +# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +# endif + +// +// Without member template support, we can't have a conforming +// std::allocator template either: +// +# if defined(BOOST_NO_MEMBER_TEMPLATES) \ + && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) \ + && !defined(BOOST_NO_STD_ALLOCATOR) +# define BOOST_NO_STD_ALLOCATOR +# endif + +// +// without ADL support then using declarations will break ADL as well: +// +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) && !defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL) +# define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL +#endif + +// +// If we have a standard allocator, then we have a partial one as well: +// +#if !defined(BOOST_NO_STD_ALLOCATOR) +# define BOOST_HAS_PARTIAL_STD_ALLOCATOR +#endif + +// +// We can't have a working std::use_facet if there is no std::locale: +// +# if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_USE_FACET) +# define BOOST_NO_STD_USE_FACET +# endif + +// +// We can't have a std::messages facet if there is no std::locale: +// +# if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_MESSAGES) +# define BOOST_NO_STD_MESSAGES +# endif + +// +// We can't have a working std::wstreambuf if there is no std::locale: +// +# if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_WSTREAMBUF) +# define BOOST_NO_STD_WSTREAMBUF +# endif + +// +// We can't have a if there is no : +// +# if defined(BOOST_NO_CWCHAR) && !defined(BOOST_NO_CWCTYPE) +# define BOOST_NO_CWCTYPE +# endif + +// +// We can't have a swprintf if there is no : +// +# if defined(BOOST_NO_CWCHAR) && !defined(BOOST_NO_SWPRINTF) +# define BOOST_NO_SWPRINTF +# endif + +// +// If Win32 support is turned off, then we must turn off +// threading support also, unless there is some other +// thread API enabled: +// +#if defined(BOOST_DISABLE_WIN32) && defined(_WIN32) \ + && !defined(BOOST_DISABLE_THREADS) && !defined(BOOST_HAS_PTHREADS) +# define BOOST_DISABLE_THREADS +#endif + +// +// Turn on threading support if the compiler thinks that it's in +// multithreaded mode. We put this here because there are only a +// limited number of macros that identify this (if there's any missing +// from here then add to the appropriate compiler section): +// +#if (defined(__MT__) || defined(_MT) || defined(_REENTRANT) \ + || defined(_PTHREADS)) && !defined(BOOST_HAS_THREADS) +# define BOOST_HAS_THREADS +#endif + +// +// Turn threading support off if BOOST_DISABLE_THREADS is defined: +// +#if defined(BOOST_DISABLE_THREADS) && defined(BOOST_HAS_THREADS) +# undef BOOST_HAS_THREADS +#endif + +// +// Turn threading support off if we don't recognise the threading API: +// +#if defined(BOOST_HAS_THREADS) && !defined(BOOST_HAS_PTHREADS)\ + && !defined(BOOST_HAS_WINTHREADS) && !defined(BOOST_HAS_BETHREADS)\ + && !defined(BOOST_HAS_MPTASKS) +# undef BOOST_HAS_THREADS +#endif + +// +// Turn threading detail macros off if we don't (want to) use threading +// +#ifndef BOOST_HAS_THREADS +# undef BOOST_HAS_PTHREADS +# undef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE +# undef BOOST_HAS_PTHREAD_YIELD +# undef BOOST_HAS_PTHREAD_DELAY_NP +# undef BOOST_HAS_WINTHREADS +# undef BOOST_HAS_BETHREADS +# undef BOOST_HAS_MPTASKS +#endif + +// +// If the compiler claims to be C99 conformant, then it had better +// have a : +// +# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) +# define BOOST_HAS_STDINT_H +# ifndef BOOST_HAS_LOG1P +# define BOOST_HAS_LOG1P +# endif +# ifndef BOOST_HAS_EXPM1 +# define BOOST_HAS_EXPM1 +# endif +# endif + +// +// Define BOOST_NO_SLIST and BOOST_NO_HASH if required. +// Note that this is for backwards compatibility only. +// +# ifndef BOOST_HAS_SLIST +# define BOOST_NO_SLIST +# endif + +# ifndef BOOST_HAS_HASH +# define BOOST_NO_HASH +# endif + +// +// Set BOOST_SLIST_HEADER if not set already: +// +#if defined(BOOST_HAS_SLIST) && !defined(BOOST_SLIST_HEADER) +# define BOOST_SLIST_HEADER +#endif + +// +// Set BOOST_HASH_SET_HEADER if not set already: +// +#if defined(BOOST_HAS_HASH) && !defined(BOOST_HASH_SET_HEADER) +# define BOOST_HASH_SET_HEADER +#endif + +// +// Set BOOST_HASH_MAP_HEADER if not set already: +// +#if defined(BOOST_HAS_HASH) && !defined(BOOST_HASH_MAP_HEADER) +# define BOOST_HASH_MAP_HEADER +#endif + +// BOOST_HAS_ABI_HEADERS +// This macro gets set if we have headers that fix the ABI, +// and prevent ODR violations when linking to external libraries: +#if defined(BOOST_ABI_PREFIX) && defined(BOOST_ABI_SUFFIX) && !defined(BOOST_HAS_ABI_HEADERS) +# define BOOST_HAS_ABI_HEADERS +#endif + +#if defined(BOOST_HAS_ABI_HEADERS) && defined(BOOST_DISABLE_ABI_HEADERS) +# undef BOOST_HAS_ABI_HEADERS +#endif + +// BOOST_NO_STDC_NAMESPACE workaround --------------------------------------// +// Because std::size_t usage is so common, even in boost headers which do not +// otherwise use the C library, the workaround is included here so +// that ugly workaround code need not appear in many other boost headers. +// NOTE WELL: This is a workaround for non-conforming compilers; +// must still be #included in the usual places so that inclusion +// works as expected with standard conforming compilers. The resulting +// double inclusion of is harmless. + +# ifdef BOOST_NO_STDC_NAMESPACE +# include + namespace std { using ::ptrdiff_t; using ::size_t; } +# endif + +// Workaround for the unfortunate min/max macros defined by some platform headers + +#define BOOST_PREVENT_MACRO_SUBSTITUTION + +#ifndef BOOST_USING_STD_MIN +# define BOOST_USING_STD_MIN() using std::min +#endif + +#ifndef BOOST_USING_STD_MAX +# define BOOST_USING_STD_MAX() using std::max +#endif + +// BOOST_NO_STD_MIN_MAX workaround -----------------------------------------// + +# ifdef BOOST_NO_STD_MIN_MAX + +namespace std { + template + inline const _Tp& min BOOST_PREVENT_MACRO_SUBSTITUTION (const _Tp& __a, const _Tp& __b) { + return __b < __a ? __b : __a; + } + template + inline const _Tp& max BOOST_PREVENT_MACRO_SUBSTITUTION (const _Tp& __a, const _Tp& __b) { + return __a < __b ? __b : __a; + } +} + +# endif + +// BOOST_STATIC_CONSTANT workaround --------------------------------------- // +// On compilers which don't allow in-class initialization of static integral +// constant members, we must use enums as a workaround if we want the constants +// to be available at compile-time. This macro gives us a convenient way to +// declare such constants. + +# ifdef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# define BOOST_STATIC_CONSTANT(type, assignment) enum { assignment } +# else +# define BOOST_STATIC_CONSTANT(type, assignment) static const type assignment +# endif + +// BOOST_USE_FACET / HAS_FACET workaround ----------------------------------// +// When the standard library does not have a conforming std::use_facet there +// are various workarounds available, but they differ from library to library. +// The same problem occurs with has_facet. +// These macros provide a consistent way to access a locale's facets. +// Usage: +// replace +// std::use_facet(loc); +// with +// BOOST_USE_FACET(Type, loc); +// Note do not add a std:: prefix to the front of BOOST_USE_FACET! +// Use for BOOST_HAS_FACET is analagous. + +#if defined(BOOST_NO_STD_USE_FACET) +# ifdef BOOST_HAS_TWO_ARG_USE_FACET +# define BOOST_USE_FACET(Type, loc) std::use_facet(loc, static_cast(0)) +# define BOOST_HAS_FACET(Type, loc) std::has_facet(loc, static_cast(0)) +# elif defined(BOOST_HAS_MACRO_USE_FACET) +# define BOOST_USE_FACET(Type, loc) std::_USE(loc, Type) +# define BOOST_HAS_FACET(Type, loc) std::_HAS(loc, Type) +# elif defined(BOOST_HAS_STLP_USE_FACET) +# define BOOST_USE_FACET(Type, loc) (*std::_Use_facet(loc)) +# define BOOST_HAS_FACET(Type, loc) std::has_facet< Type >(loc) +# endif +#else +# define BOOST_USE_FACET(Type, loc) std::use_facet< Type >(loc) +# define BOOST_HAS_FACET(Type, loc) std::has_facet< Type >(loc) +#endif + +// BOOST_NESTED_TEMPLATE workaround ------------------------------------------// +// Member templates are supported by some compilers even though they can't use +// the A::template member syntax, as a workaround replace: +// +// typedef typename A::template rebind binder; +// +// with: +// +// typedef typename A::BOOST_NESTED_TEMPLATE rebind binder; + +#ifndef BOOST_NO_MEMBER_TEMPLATE_KEYWORD +# define BOOST_NESTED_TEMPLATE template +#else +# define BOOST_NESTED_TEMPLATE +#endif + +// BOOST_UNREACHABLE_RETURN(x) workaround -------------------------------------// +// Normally evaluates to nothing, unless BOOST_NO_UNREACHABLE_RETURN_DETECTION +// is defined, in which case it evaluates to return x; Use when you have a return +// statement that can never be reached. + +#ifdef BOOST_NO_UNREACHABLE_RETURN_DETECTION +# define BOOST_UNREACHABLE_RETURN(x) return x; +#else +# define BOOST_UNREACHABLE_RETURN(x) +#endif + +// BOOST_DEDUCED_TYPENAME workaround ------------------------------------------// +// +// Some compilers don't support the use of `typename' for dependent +// types in deduced contexts, e.g. +// +// template void f(T, typename T::type); +// ^^^^^^^^ +// Replace these declarations with: +// +// template void f(T, BOOST_DEDUCED_TYPENAME T::type); + +#ifndef BOOST_NO_DEDUCED_TYPENAME +# define BOOST_DEDUCED_TYPENAME typename +#else +# define BOOST_DEDUCED_TYPENAME +#endif + +// long long workaround ------------------------------------------// +// On gcc (and maybe other compilers?) long long is alway supported +// but it's use may generate either warnings (with -ansi), or errors +// (with -pedantic -ansi) unless it's use is prefixed by __extension__ +// +#if defined(BOOST_HAS_LONG_LONG) +namespace boost{ +# ifdef __GNUC__ + __extension__ typedef long long long_long_type; + __extension__ typedef unsigned long long ulong_long_type; +# else + typedef long long long_long_type; + typedef unsigned long long ulong_long_type; +# endif +} +#endif + +// BOOST_[APPEND_]EXPLICIT_TEMPLATE_[NON_]TYPE macros --------------------------// +// +// Some compilers have problems with function templates whose +// template parameters don't appear in the function parameter +// list (basically they just link one instantiation of the +// template in the final executable). These macros provide a +// uniform way to cope with the problem with no effects on the +// calling syntax. + +// Example: +// +// #include +// #include +// #include +// +// template +// void f() { std::cout << n << ' '; } +// +// template +// void g() { std::cout << typeid(T).name() << ' '; } +// +// int main() { +// f<1>(); +// f<2>(); +// +// g(); +// g(); +// } +// +// With VC++ 6.0 the output is: +// +// 2 2 double double +// +// To fix it, write +// +// template +// void f(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int, n)) { ... } +// +// template +// void g(BOOST_EXPLICIT_TEMPLATE_TYPE(T)) { ... } +// + + +#if defined BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS + +# include "boost/type.hpp" +# include "boost/non_type.hpp" + +# define BOOST_EXPLICIT_TEMPLATE_TYPE(t) boost::type* = 0 +# define BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(t) boost::type* +# define BOOST_EXPLICIT_TEMPLATE_NON_TYPE(t, v) boost::non_type* = 0 +# define BOOST_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) boost::non_type* + +# define BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(t) \ + , BOOST_EXPLICIT_TEMPLATE_TYPE(t) +# define BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(t) \ + , BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(t) +# define BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(t, v) \ + , BOOST_EXPLICIT_TEMPLATE_NON_TYPE(t, v) +# define BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) \ + , BOOST_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) + +#else + +// no workaround needed: expand to nothing + +# define BOOST_EXPLICIT_TEMPLATE_TYPE(t) +# define BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(t) +# define BOOST_EXPLICIT_TEMPLATE_NON_TYPE(t, v) +# define BOOST_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) + +# define BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(t) +# define BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(t) +# define BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(t, v) +# define BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v) + + +#endif // defined BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS + + +// ---------------------------------------------------------------------------// + +// +// Helper macro BOOST_STRINGIZE: +// Converts the parameter X to a string after macro replacement +// on X has been performed. +// +#define BOOST_STRINGIZE(X) BOOST_DO_STRINGIZE(X) +#define BOOST_DO_STRINGIZE(X) #X + +// +// Helper macro BOOST_JOIN: +// The following piece of macro magic joins the two +// arguments together, even when one of the arguments is +// itself a macro (see 16.3.1 in C++ standard). The key +// is that macro expansion of macro arguments does not +// occur in BOOST_DO_JOIN2 but does in BOOST_DO_JOIN. +// +#define BOOST_JOIN( X, Y ) BOOST_DO_JOIN( X, Y ) +#define BOOST_DO_JOIN( X, Y ) BOOST_DO_JOIN2(X,Y) +#define BOOST_DO_JOIN2( X, Y ) X##Y + +// +// Set some default values for compiler/library/platform names. +// These are for debugging config setup only: +// +# ifndef BOOST_COMPILER +# define BOOST_COMPILER "Unknown ISO C++ Compiler" +# endif +# ifndef BOOST_STDLIB +# define BOOST_STDLIB "Unknown ISO standard library" +# endif +# ifndef BOOST_PLATFORM +# if defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) \ + || defined(_POSIX_SOURCE) +# define BOOST_PLATFORM "Generic Unix" +# else +# define BOOST_PLATFORM "Unknown" +# endif +# endif + +#endif + + diff --git a/win32/include/boost/config/user.hpp b/win32/include/boost/config/user.hpp new file mode 100755 index 000000000..3b998d16b --- /dev/null +++ b/win32/include/boost/config/user.hpp @@ -0,0 +1,124 @@ +// boost/config/user.hpp ---------------------------------------------------// + +// (C) Copyright John Maddock 2001. +// Use, modification and distribution are subject to 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) + +// Do not check in modified versions of this file, +// This file may be customized by the end user, but not by boost. + +// +// Use this file to define a site and compiler specific +// configuration policy: +// + +// define this to locate a compiler config file: +// #define BOOST_COMPILER_CONFIG + +// define this to locate a stdlib config file: +// #define BOOST_STDLIB_CONFIG + +// define this to locate a platform config file: +// #define BOOST_PLATFORM_CONFIG + +// define this to disable compiler config, +// use if your compiler config has nothing to set: +// #define BOOST_NO_COMPILER_CONFIG + +// define this to disable stdlib config, +// use if your stdlib config has nothing to set: +// #define BOOST_NO_STDLIB_CONFIG + +// define this to disable platform config, +// use if your platform config has nothing to set: +// #define BOOST_NO_PLATFORM_CONFIG + +// define this to disable all config options, +// excluding the user config. Use if your +// setup is fully ISO compliant, and has no +// useful extensions, or for autoconf generated +// setups: +// #define BOOST_NO_CONFIG + +// define this to make the config "optimistic" +// about unknown compiler versions. Normally +// unknown compiler versions are assumed to have +// all the defects of the last known version, however +// setting this flag, causes the config to assume +// that unknown compiler versions are fully conformant +// with the standard: +// #define BOOST_STRICT_CONFIG + +// define this to cause the config to halt compilation +// with an #error if it encounters anything unknown -- +// either an unknown compiler version or an unknown +// compiler/platform/library: +// #define BOOST_ASSERT_CONFIG + + +// define if you want to disable threading support, even +// when available: +// #define BOOST_DISABLE_THREADS + +// define when you want to disable Win32 specific features +// even when available: +// #define BOOST_DISABLE_WIN32 + +// BOOST_DISABLE_ABI_HEADERS: Stops boost headers from including any +// prefix/suffix headers that normally control things like struct +// packing and alignment. +// #define BOOST_DISABLE_ABI_HEADERS + +// BOOST_ABI_PREFIX: A prefix header to include in place of whatever +// boost.config would normally select, any replacement should set up +// struct packing and alignment options as required. +// #define BOOST_ABI_PREFIX my-header-name + +// BOOST_ABI_SUFFIX: A suffix header to include in place of whatever +// boost.config would normally select, any replacement should undo +// the effects of the prefix header. +// #define BOOST_ABI_SUFFIX my-header-name + +// BOOST_ALL_DYN_LINK: Forces all libraries that have separate source, +// to be linked as dll's rather than static libraries on Microsoft Windows +// (this macro is used to turn on __declspec(dllimport) modifiers, so that +// the compiler knows which symbols to look for in a dll rather than in a +// static library). Note that there may be some libraries that can only +// be statically linked (Boost.Test for example) and others which may only +// be dynamically linked (Boost.Threads for example), in these cases this +// macro has no effect. +// #define BOOST_ALL_DYN_LINK + +// BOOST_WHATEVER_DYN_LINK: Forces library "whatever" to be linked as a dll +// rather than a static library on Microsoft Windows: replace the WHATEVER +// part of the macro name with the name of the library that you want to +// dynamically link to, for example use BOOST_DATE_TIME_DYN_LINK or +// BOOST_REGEX_DYN_LINK etc (this macro is used to turn on __declspec(dllimport) +// modifiers, so that the compiler knows which symbols to look for in a dll +// rather than in a static library). +// Note that there may be some libraries that can only be statically linked +// (Boost.Test for example) and others which may only be dynamically linked +// (Boost.Threads for example), in these cases this macro is unsupported. +// #define BOOST_WHATEVER_DYN_LINK + +// BOOST_ALL_NO_LIB: Tells the config system not to automatically select +// which libraries to link against. +// Normally if a compiler supports #pragma lib, then the correct library +// build variant will be automatically selected and linked against, +// simply by the act of including one of that library's headers. +// This macro turns that feature off. +// #define BOOST_ALL_NO_LIB + +// BOOST_WHATEVER_NO_LIB: Tells the config system not to automatically +// select which library to link against for library "whatever", +// replace WHATEVER in the macro name with the name of the library; +// for example BOOST_DATE_TIME_NO_LIB or BOOST_REGEX_NO_LIB. +// Normally if a compiler supports #pragma lib, then the correct library +// build variant will be automatically selected and linked against, simply +// by the act of including one of that library's headers. This macro turns +// that feature off. +// #define BOOST_WHATEVER_NO_LIB + + + diff --git a/win32/include/boost/config/warning_disable.hpp b/win32/include/boost/config/warning_disable.hpp new file mode 100755 index 000000000..8fd46ff73 --- /dev/null +++ b/win32/include/boost/config/warning_disable.hpp @@ -0,0 +1,47 @@ +// Copyright John Maddock 2008 +// Use, modification, and distribution is subject to 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) +// +// This file exists to turn off some overly-pedantic warning emitted +// by certain compilers. You should include this header only in: +// +// * A test case, before any other headers, or, +// * A library source file before any other headers. +// +// IT SHOULD NOT BE INCLUDED BY ANY BOOST HEADER. +// +// YOU SHOULD NOT INCLUDE IT IF YOU CAN REASONABLY FIX THE WARNING. +// +// The only warnings disabled here are those that are: +// +// * Quite unreasonably pedantic. +// * Generally only emitted by a single compiler. +// * Can't easily be fixed: for example if the vendors own std lib +// code emits these warnings! +// +// Note that THIS HEADER MUST NOT INCLUDE ANY OTHER HEADERS: +// not even std library ones! Doing so may turn the warning +// off too late to be of any use. For example the VC++ C4996 +// warning can be omitted from if that header is included +// before or by this one :-( +// + +#ifndef BOOST_CONFIG_WARNING_DISABLE_HPP +#define BOOST_CONFIG_WARNING_DISABLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + // Error 'function': was declared deprecated + // http://msdn2.microsoft.com/en-us/library/ttcz0bys(VS.80).aspx + // This error is emitted when you use some perfectly conforming + // std lib functions in a perfectly correct way, and also by + // some of Microsoft's own std lib code ! +# pragma warning(disable:4996) +#endif +#if defined(__INTEL_COMPILER) || defined(__ICL) + // As above: gives warning when a "deprecated" + // std library function is encountered. +# pragma warning(disable:1786) +#endif + +#endif // BOOST_CONFIG_WARNING_DISABLE_HPP diff --git a/win32/include/boost/crc.hpp b/win32/include/boost/crc.hpp new file mode 100755 index 000000000..5824812c5 --- /dev/null +++ b/win32/include/boost/crc.hpp @@ -0,0 +1,1106 @@ +// Boost CRC library crc.hpp header file -----------------------------------// + +// Copyright 2001, 2004 Daryle Walker. Use, modification, and distribution are +// subject to the Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or a copy at .) + +// See for the library's home page. + +#ifndef BOOST_CRC_HPP +#define BOOST_CRC_HPP + +#include // for BOOST_STATIC_CONSTANT, etc. +#include // for boost::uint_t + +#include // for CHAR_BIT, etc. +#include // for std::size_t + +#include // for std::numeric_limits + + +// The type of CRC parameters that can go in a template should be related +// on the CRC's bit count. This macro expresses that type in a compact +// form, but also allows an alternate type for compilers that don't support +// dependent types (in template value-parameters). +#if !(defined(BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS) || (defined(BOOST_MSVC) && (BOOST_MSVC <= 1300))) +#define BOOST_CRC_PARM_TYPE typename ::boost::uint_t::fast +#else +#define BOOST_CRC_PARM_TYPE unsigned long +#endif + +// Some compilers [MS VC++ 6] cannot correctly set up several versions of a +// function template unless every template argument can be unambiguously +// deduced from the function arguments. (The bug is hidden if only one version +// is needed.) Since all of the CRC function templates have this problem, the +// workaround is to make up a dummy function argument that encodes the template +// arguments. Calls to such template functions need all their template +// arguments explicitly specified. At least one compiler that needs this +// workaround also needs the default value for the dummy argument to be +// specified in the definition. +#if defined(__GNUC__) || !defined(BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS) +#define BOOST_CRC_DUMMY_PARM_TYPE +#define BOOST_CRC_DUMMY_INIT +#define BOOST_ACRC_DUMMY_PARM_TYPE +#define BOOST_ACRC_DUMMY_INIT +#else +namespace boost { namespace detail { + template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > + struct dummy_crc_argument { }; +} } +#define BOOST_CRC_DUMMY_PARM_TYPE , detail::dummy_crc_argument *p_ +#define BOOST_CRC_DUMMY_INIT BOOST_CRC_DUMMY_PARM_TYPE = 0 +#define BOOST_ACRC_DUMMY_PARM_TYPE , detail::dummy_crc_argument *p_ +#define BOOST_ACRC_DUMMY_INIT BOOST_ACRC_DUMMY_PARM_TYPE = 0 +#endif + + +namespace boost +{ + + +// Forward declarations ----------------------------------------------------// + +template < std::size_t Bits > + class crc_basic; + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly = 0u, + BOOST_CRC_PARM_TYPE InitRem = 0u, + BOOST_CRC_PARM_TYPE FinalXor = 0u, bool ReflectIn = false, + bool ReflectRem = false > + class crc_optimal; + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > + typename uint_t::fast crc( void const *buffer, + std::size_t byte_count + BOOST_CRC_DUMMY_PARM_TYPE ); + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly > + typename uint_t::fast augmented_crc( void const *buffer, + std::size_t byte_count, typename uint_t::fast initial_remainder + BOOST_ACRC_DUMMY_PARM_TYPE ); + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly > + typename uint_t::fast augmented_crc( void const *buffer, + std::size_t byte_count + BOOST_ACRC_DUMMY_PARM_TYPE ); + +typedef crc_optimal<16, 0x8005, 0, 0, true, true> crc_16_type; +typedef crc_optimal<16, 0x1021, 0xFFFF, 0, false, false> crc_ccitt_type; +typedef crc_optimal<16, 0x8408, 0, 0, true, true> crc_xmodem_type; + +typedef crc_optimal<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true> + crc_32_type; + + +// Forward declarations for implementation detail stuff --------------------// +// (Just for the stuff that will be needed for the next two sections) + +namespace detail +{ + template < std::size_t Bits > + struct mask_uint_t; + + template < > + struct mask_uint_t< std::numeric_limits::digits >; + + #if USHRT_MAX > UCHAR_MAX + template < > + struct mask_uint_t< std::numeric_limits::digits >; + #endif + + #if UINT_MAX > USHRT_MAX + template < > + struct mask_uint_t< std::numeric_limits::digits >; + #endif + + #if ULONG_MAX > UINT_MAX + template < > + struct mask_uint_t< std::numeric_limits::digits >; + #endif + + template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, bool Reflect > + struct crc_table_t; + + template < std::size_t Bits, bool DoReflect > + class crc_helper; + + #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template < std::size_t Bits > + class crc_helper< Bits, false >; + #endif + +} // namespace detail + + +// Simple cyclic redundancy code (CRC) class declaration -------------------// + +template < std::size_t Bits > +class crc_basic +{ + // Implementation type + typedef detail::mask_uint_t masking_type; + +public: + // Type + typedef typename masking_type::least value_type; + + // Constant for the template parameter + BOOST_STATIC_CONSTANT( std::size_t, bit_count = Bits ); + + // Constructor + explicit crc_basic( value_type truncated_polynominal, + value_type initial_remainder = 0, value_type final_xor_value = 0, + bool reflect_input = false, bool reflect_remainder = false ); + + // Internal Operations + value_type get_truncated_polynominal() const; + value_type get_initial_remainder() const; + value_type get_final_xor_value() const; + bool get_reflect_input() const; + bool get_reflect_remainder() const; + + value_type get_interim_remainder() const; + void reset( value_type new_rem ); + void reset(); + + // External Operations + void process_bit( bool bit ); + void process_bits( unsigned char bits, std::size_t bit_count ); + void process_byte( unsigned char byte ); + void process_block( void const *bytes_begin, void const *bytes_end ); + void process_bytes( void const *buffer, std::size_t byte_count ); + + value_type checksum() const; + +private: + // Member data + value_type rem_; + value_type poly_, init_, final_; // non-const to allow assignability + bool rft_in_, rft_out_; // non-const to allow assignability + +}; // boost::crc_basic + + +// Optimized cyclic redundancy code (CRC) class declaration ----------------// + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +class crc_optimal +{ + // Implementation type + typedef detail::mask_uint_t masking_type; + +public: + // Type + typedef typename masking_type::fast value_type; + + // Constants for the template parameters + BOOST_STATIC_CONSTANT( std::size_t, bit_count = Bits ); + BOOST_STATIC_CONSTANT( value_type, truncated_polynominal = TruncPoly ); + BOOST_STATIC_CONSTANT( value_type, initial_remainder = InitRem ); + BOOST_STATIC_CONSTANT( value_type, final_xor_value = FinalXor ); + BOOST_STATIC_CONSTANT( bool, reflect_input = ReflectIn ); + BOOST_STATIC_CONSTANT( bool, reflect_remainder = ReflectRem ); + + // Constructor + explicit crc_optimal( value_type init_rem = InitRem ); + + // Internal Operations + value_type get_truncated_polynominal() const; + value_type get_initial_remainder() const; + value_type get_final_xor_value() const; + bool get_reflect_input() const; + bool get_reflect_remainder() const; + + value_type get_interim_remainder() const; + void reset( value_type new_rem = InitRem ); + + // External Operations + void process_byte( unsigned char byte ); + void process_block( void const *bytes_begin, void const *bytes_end ); + void process_bytes( void const *buffer, std::size_t byte_count ); + + value_type checksum() const; + + // Operators + void operator ()( unsigned char byte ); + value_type operator ()() const; + +private: + // The implementation of output reflection depends on both reflect states. + BOOST_STATIC_CONSTANT( bool, reflect_output = (ReflectRem != ReflectIn) ); + + #ifndef __BORLANDC__ + #define BOOST_CRC_REF_OUT_VAL reflect_output + #else + typedef crc_optimal self_type; + #define BOOST_CRC_REF_OUT_VAL (self_type::reflect_output) + #endif + + // More implementation types + typedef detail::crc_table_t crc_table_type; + typedef detail::crc_helper helper_type; + typedef detail::crc_helper reflect_out_type; + + #undef BOOST_CRC_REF_OUT_VAL + + // Member data + value_type rem_; + +}; // boost::crc_optimal + + +// Implementation detail stuff ---------------------------------------------// + +namespace detail +{ + // Forward declarations for more implementation details + template < std::size_t Bits > + struct high_uint_t; + + template < std::size_t Bits > + struct reflector; + + + // Traits class for mask; given the bit number + // (1-based), get the mask for that bit by itself. + template < std::size_t Bits > + struct high_uint_t + : boost::uint_t< Bits > + { + typedef boost::uint_t base_type; + typedef typename base_type::least least; + typedef typename base_type::fast fast; + +#if defined(__EDG_VERSION__) && __EDG_VERSION__ <= 243 + static const least high_bit = 1ul << ( Bits - 1u ); + static const fast high_bit_fast = 1ul << ( Bits - 1u ); +#else + BOOST_STATIC_CONSTANT( least, high_bit = (least( 1u ) << ( Bits + - 1u )) ); + BOOST_STATIC_CONSTANT( fast, high_bit_fast = (fast( 1u ) << ( Bits + - 1u )) ); +#endif + + }; // boost::detail::high_uint_t + + + // Reflection routine class wrapper + // (since MS VC++ 6 couldn't handle the unwrapped version) + template < std::size_t Bits > + struct reflector + { + typedef typename boost::uint_t::fast value_type; + + static value_type reflect( value_type x ); + + }; // boost::detail::reflector + + // Function that reflects its argument + template < std::size_t Bits > + typename reflector::value_type + reflector::reflect + ( + typename reflector::value_type x + ) + { + value_type reflection = 0; + value_type const one = 1; + + for ( std::size_t i = 0 ; i < Bits ; ++i, x >>= 1 ) + { + if ( x & one ) + { + reflection |= ( one << (Bits - 1u - i) ); + } + } + + return reflection; + } + + + // Traits class for masks; given the bit number (1-based), + // get the mask for that bit and its lower bits. + template < std::size_t Bits > + struct mask_uint_t + : high_uint_t< Bits > + { + typedef high_uint_t base_type; + typedef typename base_type::least least; + typedef typename base_type::fast fast; + + #ifndef __BORLANDC__ + using base_type::high_bit; + using base_type::high_bit_fast; + #else + BOOST_STATIC_CONSTANT( least, high_bit = base_type::high_bit ); + BOOST_STATIC_CONSTANT( fast, high_bit_fast = base_type::high_bit_fast ); + #endif + +#if defined(__EDG_VERSION__) && __EDG_VERSION__ <= 243 + static const least sig_bits = (~( ~( 0ul ) << Bits )) ; +#else + BOOST_STATIC_CONSTANT( least, sig_bits = (~( ~(least( 0u )) << Bits )) ); +#endif +#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 2 + // Work around a weird bug that ICEs the compiler in build_c_cast + BOOST_STATIC_CONSTANT( fast, sig_bits_fast = static_cast(sig_bits) ); +#else + BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); +#endif + }; // boost::detail::mask_uint_t + + template < > + struct mask_uint_t< std::numeric_limits::digits > + : high_uint_t< std::numeric_limits::digits > + { + typedef high_uint_t::digits> + base_type; + typedef base_type::least least; + typedef base_type::fast fast; + + #ifndef __BORLANDC__ + using base_type::high_bit; + using base_type::high_bit_fast; + #else + BOOST_STATIC_CONSTANT( least, high_bit = base_type::high_bit ); + BOOST_STATIC_CONSTANT( fast, high_bit_fast = base_type::high_bit_fast ); + #endif + + BOOST_STATIC_CONSTANT( least, sig_bits = (~( least(0u) )) ); + BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); + + }; // boost::detail::mask_uint_t + + #if USHRT_MAX > UCHAR_MAX + template < > + struct mask_uint_t< std::numeric_limits::digits > + : high_uint_t< std::numeric_limits::digits > + { + typedef high_uint_t::digits> + base_type; + typedef base_type::least least; + typedef base_type::fast fast; + + #ifndef __BORLANDC__ + using base_type::high_bit; + using base_type::high_bit_fast; + #else + BOOST_STATIC_CONSTANT( least, high_bit = base_type::high_bit ); + BOOST_STATIC_CONSTANT( fast, high_bit_fast = base_type::high_bit_fast ); + #endif + + BOOST_STATIC_CONSTANT( least, sig_bits = (~( least(0u) )) ); + BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); + + }; // boost::detail::mask_uint_t + #endif + + #if UINT_MAX > USHRT_MAX + template < > + struct mask_uint_t< std::numeric_limits::digits > + : high_uint_t< std::numeric_limits::digits > + { + typedef high_uint_t::digits> + base_type; + typedef base_type::least least; + typedef base_type::fast fast; + + #ifndef __BORLANDC__ + using base_type::high_bit; + using base_type::high_bit_fast; + #else + BOOST_STATIC_CONSTANT( least, high_bit = base_type::high_bit ); + BOOST_STATIC_CONSTANT( fast, high_bit_fast = base_type::high_bit_fast ); + #endif + + BOOST_STATIC_CONSTANT( least, sig_bits = (~( least(0u) )) ); + BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); + + }; // boost::detail::mask_uint_t + #endif + + #if ULONG_MAX > UINT_MAX + template < > + struct mask_uint_t< std::numeric_limits::digits > + : high_uint_t< std::numeric_limits::digits > + { + typedef high_uint_t::digits> + base_type; + typedef base_type::least least; + typedef base_type::fast fast; + + #ifndef __BORLANDC__ + using base_type::high_bit; + using base_type::high_bit_fast; + #else + BOOST_STATIC_CONSTANT( least, high_bit = base_type::high_bit ); + BOOST_STATIC_CONSTANT( fast, high_bit_fast = base_type::high_bit_fast ); + #endif + + BOOST_STATIC_CONSTANT( least, sig_bits = (~( least(0u) )) ); + BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); + + }; // boost::detail::mask_uint_t + #endif + + + // CRC table generator + template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, bool Reflect > + struct crc_table_t + { + BOOST_STATIC_CONSTANT( std::size_t, byte_combos = (1ul << CHAR_BIT) ); + + typedef mask_uint_t masking_type; + typedef typename masking_type::fast value_type; +#if defined(__BORLANDC__) && defined(_M_IX86) && (__BORLANDC__ == 0x560) + // for some reason Borland's command line compiler (version 0x560) + // chokes over this unless we do the calculation for it: + typedef value_type table_type[ 0x100 ]; +#else + typedef value_type table_type[ byte_combos ]; +#endif + + static void init_table(); + + static table_type table_; + + }; // boost::detail::crc_table_t + + // CRC table generator static data member definition + // (Some compilers [Borland C++] require the initializer to be present.) + template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, bool Reflect > + typename crc_table_t::table_type + crc_table_t::table_ + = { 0 }; + + // Populate CRC lookup table + template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, bool Reflect > + void + crc_table_t::init_table + ( + ) + { + // compute table only on the first run + static bool did_init = false; + if ( did_init ) return; + + // factor-out constants to avoid recalculation + value_type const fast_hi_bit = masking_type::high_bit_fast; + unsigned char const byte_hi_bit = 1u << (CHAR_BIT - 1u); + + // loop over every possible dividend value + unsigned char dividend = 0; + do + { + value_type remainder = 0; + + // go through all the dividend's bits + for ( unsigned char mask = byte_hi_bit ; mask ; mask >>= 1 ) + { + // check if divisor fits + if ( dividend & mask ) + { + remainder ^= fast_hi_bit; + } + + // do polynominal division + if ( remainder & fast_hi_bit ) + { + remainder <<= 1; + remainder ^= TruncPoly; + } + else + { + remainder <<= 1; + } + } + + table_[ crc_helper::reflect(dividend) ] + = crc_helper::reflect( remainder ); + } + while ( ++dividend ); + + did_init = true; + } + + #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // Align the msb of the remainder to a byte + template < std::size_t Bits, bool RightShift > + class remainder + { + public: + typedef typename uint_t::fast value_type; + + static unsigned char align_msb( value_type rem ) + { return rem >> (Bits - CHAR_BIT); } + }; + + // Specialization for the case that the remainder has less + // bits than a byte: align the remainder msb to the byte msb + template < std::size_t Bits > + class remainder< Bits, false > + { + public: + typedef typename uint_t::fast value_type; + + static unsigned char align_msb( value_type rem ) + { return rem << (CHAR_BIT - Bits); } + }; + #endif + + // CRC helper routines + template < std::size_t Bits, bool DoReflect > + class crc_helper + { + public: + // Type + typedef typename uint_t::fast value_type; + + #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // Possibly reflect a remainder + static value_type reflect( value_type x ) + { return detail::reflector::reflect( x ); } + + // Compare a byte to the remainder's highest byte + static unsigned char index( value_type rem, unsigned char x ) + { return x ^ rem; } + + // Shift out the remainder's highest byte + static value_type shift( value_type rem ) + { return rem >> CHAR_BIT; } + #else + // Possibly reflect a remainder + static value_type reflect( value_type x ) + { return DoReflect ? detail::reflector::reflect( x ) : x; } + + // Compare a byte to the remainder's highest byte + static unsigned char index( value_type rem, unsigned char x ) + { return x ^ ( DoReflect ? rem : + ((Bits>CHAR_BIT)?( rem >> (Bits - CHAR_BIT) ) : + ( rem << (CHAR_BIT - Bits) ))); } + + // Shift out the remainder's highest byte + static value_type shift( value_type rem ) + { return DoReflect ? rem >> CHAR_BIT : rem << CHAR_BIT; } + #endif + + }; // boost::detail::crc_helper + + #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template < std::size_t Bits > + class crc_helper + { + public: + // Type + typedef typename uint_t::fast value_type; + + // Possibly reflect a remainder + static value_type reflect( value_type x ) + { return x; } + + // Compare a byte to the remainder's highest byte + static unsigned char index( value_type rem, unsigned char x ) + { return x ^ remainderCHAR_BIT)>::align_msb( rem ); } + + // Shift out the remainder's highest byte + static value_type shift( value_type rem ) + { return rem << CHAR_BIT; } + + }; // boost::detail::crc_helper + #endif + + +} // namespace detail + + +// Simple CRC class function definitions -----------------------------------// + +template < std::size_t Bits > +inline +crc_basic::crc_basic +( + typename crc_basic::value_type truncated_polynominal, + typename crc_basic::value_type initial_remainder, // = 0 + typename crc_basic::value_type final_xor_value, // = 0 + bool reflect_input, // = false + bool reflect_remainder // = false +) + : rem_( initial_remainder ), poly_( truncated_polynominal ) + , init_( initial_remainder ), final_( final_xor_value ) + , rft_in_( reflect_input ), rft_out_( reflect_remainder ) +{ +} + +template < std::size_t Bits > +inline +typename crc_basic::value_type +crc_basic::get_truncated_polynominal +( +) const +{ + return poly_; +} + +template < std::size_t Bits > +inline +typename crc_basic::value_type +crc_basic::get_initial_remainder +( +) const +{ + return init_; +} + +template < std::size_t Bits > +inline +typename crc_basic::value_type +crc_basic::get_final_xor_value +( +) const +{ + return final_; +} + +template < std::size_t Bits > +inline +bool +crc_basic::get_reflect_input +( +) const +{ + return rft_in_; +} + +template < std::size_t Bits > +inline +bool +crc_basic::get_reflect_remainder +( +) const +{ + return rft_out_; +} + +template < std::size_t Bits > +inline +typename crc_basic::value_type +crc_basic::get_interim_remainder +( +) const +{ + return rem_ & masking_type::sig_bits; +} + +template < std::size_t Bits > +inline +void +crc_basic::reset +( + typename crc_basic::value_type new_rem +) +{ + rem_ = new_rem; +} + +template < std::size_t Bits > +inline +void +crc_basic::reset +( +) +{ + this->reset( this->get_initial_remainder() ); +} + +template < std::size_t Bits > +inline +void +crc_basic::process_bit +( + bool bit +) +{ + value_type const high_bit_mask = masking_type::high_bit; + + // compare the new bit with the remainder's highest + rem_ ^= ( bit ? high_bit_mask : 0u ); + + // a full polynominal division step is done when the highest bit is one + bool const do_poly_div = static_cast( rem_ & high_bit_mask ); + + // shift out the highest bit + rem_ <<= 1; + + // carry out the division, if needed + if ( do_poly_div ) + { + rem_ ^= poly_; + } +} + +template < std::size_t Bits > +void +crc_basic::process_bits +( + unsigned char bits, + std::size_t bit_count +) +{ + // ignore the bits above the ones we want + bits <<= CHAR_BIT - bit_count; + + // compute the CRC for each bit, starting with the upper ones + unsigned char const high_bit_mask = 1u << ( CHAR_BIT - 1u ); + for ( std::size_t i = bit_count ; i > 0u ; --i, bits <<= 1u ) + { + process_bit( static_cast(bits & high_bit_mask) ); + } +} + +template < std::size_t Bits > +inline +void +crc_basic::process_byte +( + unsigned char byte +) +{ + process_bits( (rft_in_ ? detail::reflector::reflect(byte) + : byte), CHAR_BIT ); +} + +template < std::size_t Bits > +void +crc_basic::process_block +( + void const * bytes_begin, + void const * bytes_end +) +{ + for ( unsigned char const * p + = static_cast(bytes_begin) ; p < bytes_end ; ++p ) + { + process_byte( *p ); + } +} + +template < std::size_t Bits > +inline +void +crc_basic::process_bytes +( + void const * buffer, + std::size_t byte_count +) +{ + unsigned char const * const b = static_cast( + buffer ); + + process_block( b, b + byte_count ); +} + +template < std::size_t Bits > +inline +typename crc_basic::value_type +crc_basic::checksum +( +) const +{ + return ( (rft_out_ ? detail::reflector::reflect( rem_ ) : rem_) + ^ final_ ) & masking_type::sig_bits; +} + + +// Optimized CRC class function definitions --------------------------------// + +// Macro to compact code +#define BOOST_CRC_OPTIMAL_NAME crc_optimal + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +inline +BOOST_CRC_OPTIMAL_NAME::crc_optimal +( + typename BOOST_CRC_OPTIMAL_NAME::value_type init_rem // = InitRem +) + : rem_( helper_type::reflect(init_rem) ) +{ + crc_table_type::init_table(); +} + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +inline +typename BOOST_CRC_OPTIMAL_NAME::value_type +BOOST_CRC_OPTIMAL_NAME::get_truncated_polynominal +( +) const +{ + return TruncPoly; +} + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +inline +typename BOOST_CRC_OPTIMAL_NAME::value_type +BOOST_CRC_OPTIMAL_NAME::get_initial_remainder +( +) const +{ + return InitRem; +} + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +inline +typename BOOST_CRC_OPTIMAL_NAME::value_type +BOOST_CRC_OPTIMAL_NAME::get_final_xor_value +( +) const +{ + return FinalXor; +} + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +inline +bool +BOOST_CRC_OPTIMAL_NAME::get_reflect_input +( +) const +{ + return ReflectIn; +} + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +inline +bool +BOOST_CRC_OPTIMAL_NAME::get_reflect_remainder +( +) const +{ + return ReflectRem; +} + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +inline +typename BOOST_CRC_OPTIMAL_NAME::value_type +BOOST_CRC_OPTIMAL_NAME::get_interim_remainder +( +) const +{ + // Interim remainder should be _un_-reflected, so we have to undo it. + return helper_type::reflect( rem_ ) & masking_type::sig_bits_fast; +} + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +inline +void +BOOST_CRC_OPTIMAL_NAME::reset +( + typename BOOST_CRC_OPTIMAL_NAME::value_type new_rem // = InitRem +) +{ + rem_ = helper_type::reflect( new_rem ); +} + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +inline +void +BOOST_CRC_OPTIMAL_NAME::process_byte +( + unsigned char byte +) +{ + process_bytes( &byte, sizeof(byte) ); +} + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +void +BOOST_CRC_OPTIMAL_NAME::process_block +( + void const * bytes_begin, + void const * bytes_end +) +{ + // Recompute the CRC for each byte passed + for ( unsigned char const * p + = static_cast(bytes_begin) ; p < bytes_end ; ++p ) + { + // Compare the new byte with the remainder's higher bits to + // get the new bits, shift out the remainder's current higher + // bits, and update the remainder with the polynominal division + // of the new bits. + unsigned char const byte_index = helper_type::index( rem_, *p ); + rem_ = helper_type::shift( rem_ ); + rem_ ^= crc_table_type::table_[ byte_index ]; + } +} + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +inline +void +BOOST_CRC_OPTIMAL_NAME::process_bytes +( + void const * buffer, + std::size_t byte_count +) +{ + unsigned char const * const b = static_cast( + buffer ); + process_block( b, b + byte_count ); +} + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +inline +typename BOOST_CRC_OPTIMAL_NAME::value_type +BOOST_CRC_OPTIMAL_NAME::checksum +( +) const +{ + return ( reflect_out_type::reflect(rem_) ^ get_final_xor_value() ) + & masking_type::sig_bits_fast; +} + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +inline +void +BOOST_CRC_OPTIMAL_NAME::operator () +( + unsigned char byte +) +{ + process_byte( byte ); +} + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +inline +typename BOOST_CRC_OPTIMAL_NAME::value_type +BOOST_CRC_OPTIMAL_NAME::operator () +( +) const +{ + return checksum(); +} + + +// CRC computation function definition -------------------------------------// + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, + BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, + bool ReflectIn, bool ReflectRem > +inline +typename uint_t::fast +crc +( + void const * buffer, + std::size_t byte_count + BOOST_CRC_DUMMY_INIT +) +{ + BOOST_CRC_OPTIMAL_NAME computer; + computer.process_bytes( buffer, byte_count ); + return computer.checksum(); +} + + +// Augmented-message CRC computation function definitions ------------------// + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly > +typename uint_t::fast +augmented_crc +( + void const * buffer, + std::size_t byte_count, + typename uint_t::fast initial_remainder + BOOST_ACRC_DUMMY_INIT +) +{ + typedef unsigned char byte_type; + typedef detail::mask_uint_t masking_type; + typedef detail::crc_table_t crc_table_type; + + typename masking_type::fast rem = initial_remainder; + byte_type const * const b = static_cast( buffer ); + byte_type const * const e = b + byte_count; + + crc_table_type::init_table(); + for ( byte_type const * p = b ; p < e ; ++p ) + { + // Use the current top byte as the table index to the next + // "partial product." Shift out that top byte, shifting in + // the next augmented-message byte. Complete the division. + byte_type const byte_index = rem >> ( Bits - CHAR_BIT ); + rem <<= CHAR_BIT; + rem |= *p; + rem ^= crc_table_type::table_[ byte_index ]; + } + + return rem & masking_type::sig_bits_fast; +} + +template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly > +inline +typename uint_t::fast +augmented_crc +( + void const * buffer, + std::size_t byte_count + BOOST_ACRC_DUMMY_INIT +) +{ + // The last function argument has its type specified so the other version of + // augmented_crc will be called. If the cast wasn't in place, and the + // BOOST_ACRC_DUMMY_INIT added a third argument (for a workaround), the "0" + // would match as that third argument, leading to infinite recursion. + return augmented_crc( buffer, byte_count, + static_cast::fast>(0) ); +} + + +} // namespace boost + + +// Undo header-private macros +#undef BOOST_CRC_OPTIMAL_NAME +#undef BOOST_ACRC_DUMMY_INIT +#undef BOOST_ACRC_DUMMY_PARM_TYPE +#undef BOOST_CRC_DUMMY_INIT +#undef BOOST_CRC_DUMMY_PARM_TYPE +#undef BOOST_CRC_PARM_TYPE + + +#endif // BOOST_CRC_HPP + diff --git a/win32/include/boost/cregex.hpp b/win32/include/boost/cregex.hpp new file mode 100755 index 000000000..81d0343d5 --- /dev/null +++ b/win32/include/boost/cregex.hpp @@ -0,0 +1,39 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org/libs/regex for most recent version. + * FILE cregex.cpp + * VERSION see + * DESCRIPTION: Declares POSIX API functions + * + boost::RegEx high level wrapper. + */ + +#ifndef BOOST_RE_CREGEX_HPP +#define BOOST_RE_CREGEX_HPP + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif + +#include + +#endif /* include guard */ + + + + + + + + + + diff --git a/win32/include/boost/cstdint.hpp b/win32/include/boost/cstdint.hpp new file mode 100755 index 000000000..b3bb26996 --- /dev/null +++ b/win32/include/boost/cstdint.hpp @@ -0,0 +1,446 @@ +// boost cstdint.hpp header file ------------------------------------------// + +// (C) Copyright Beman Dawes 1999. +// (C) Copyright Jens Mauer 2001 +// (C) Copyright John Maddock 2001 +// 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) + +// See http://www.boost.org/libs/integer for documentation. + +// Revision History +// 31 Oct 01 use BOOST_HAS_LONG_LONG to check for "long long" (Jens M.) +// 16 Apr 01 check LONGLONG_MAX when looking for "long long" (Jens Maurer) +// 23 Jan 01 prefer "long" over "int" for int32_t and intmax_t (Jens Maurer) +// 12 Nov 00 Merged (Jens Maurer) +// 23 Sep 00 Added INTXX_C macro support (John Maddock). +// 22 Sep 00 Better 64-bit support (John Maddock) +// 29 Jun 00 Reimplement to avoid including stdint.h within namespace boost +// 8 Aug 99 Initial version (Beman Dawes) + + +#ifndef BOOST_CSTDINT_HPP +#define BOOST_CSTDINT_HPP + +#include + + +#ifdef BOOST_HAS_STDINT_H + +// The following #include is an implementation artifact; not part of interface. +# ifdef __hpux +// HP-UX has a vaguely nice in a non-standard location +# include +# ifdef __STDC_32_MODE__ + // this is triggered with GCC, because it defines __cplusplus < 199707L +# define BOOST_NO_INT64_T +# endif +# elif defined(__FreeBSD__) || defined(__IBMCPP__) +# include +# else +# include + +// There is a bug in Cygwin two _C macros +# if defined(__STDC_CONSTANT_MACROS) && defined(__CYGWIN__) +# undef INTMAX_C +# undef UINTMAX_C +# define INTMAX_C(c) c##LL +# define UINTMAX_C(c) c##ULL +# endif + +# endif + +#ifdef __QNX__ + +// QNX (Dinkumware stdlib) defines these as non-standard names. +// Reflect to the standard names. + +typedef ::intleast8_t int_least8_t; +typedef ::intfast8_t int_fast8_t; +typedef ::uintleast8_t uint_least8_t; +typedef ::uintfast8_t uint_fast8_t; + +typedef ::intleast16_t int_least16_t; +typedef ::intfast16_t int_fast16_t; +typedef ::uintleast16_t uint_least16_t; +typedef ::uintfast16_t uint_fast16_t; + +typedef ::intleast32_t int_least32_t; +typedef ::intfast32_t int_fast32_t; +typedef ::uintleast32_t uint_least32_t; +typedef ::uintfast32_t uint_fast32_t; + +# ifndef BOOST_NO_INT64_T + +typedef ::intleast64_t int_least64_t; +typedef ::intfast64_t int_fast64_t; +typedef ::uintleast64_t uint_least64_t; +typedef ::uintfast64_t uint_fast64_t; + +# endif + +#endif + +namespace boost +{ + + using ::int8_t; + using ::int_least8_t; + using ::int_fast8_t; + using ::uint8_t; + using ::uint_least8_t; + using ::uint_fast8_t; + + using ::int16_t; + using ::int_least16_t; + using ::int_fast16_t; + using ::uint16_t; + using ::uint_least16_t; + using ::uint_fast16_t; + + using ::int32_t; + using ::int_least32_t; + using ::int_fast32_t; + using ::uint32_t; + using ::uint_least32_t; + using ::uint_fast32_t; + +# ifndef BOOST_NO_INT64_T + + using ::int64_t; + using ::int_least64_t; + using ::int_fast64_t; + using ::uint64_t; + using ::uint_least64_t; + using ::uint_fast64_t; + +# endif + + using ::intmax_t; + using ::uintmax_t; + +} // namespace boost + +#elif defined(__FreeBSD__) && (__FreeBSD__ <= 4) || defined(__osf__) +// FreeBSD and Tru64 have an that contains much of what we need. +# include + +namespace boost { + + using ::int8_t; + typedef int8_t int_least8_t; + typedef int8_t int_fast8_t; + using ::uint8_t; + typedef uint8_t uint_least8_t; + typedef uint8_t uint_fast8_t; + + using ::int16_t; + typedef int16_t int_least16_t; + typedef int16_t int_fast16_t; + using ::uint16_t; + typedef uint16_t uint_least16_t; + typedef uint16_t uint_fast16_t; + + using ::int32_t; + typedef int32_t int_least32_t; + typedef int32_t int_fast32_t; + using ::uint32_t; + typedef uint32_t uint_least32_t; + typedef uint32_t uint_fast32_t; + +# ifndef BOOST_NO_INT64_T + + using ::int64_t; + typedef int64_t int_least64_t; + typedef int64_t int_fast64_t; + using ::uint64_t; + typedef uint64_t uint_least64_t; + typedef uint64_t uint_fast64_t; + + typedef int64_t intmax_t; + typedef uint64_t uintmax_t; + +# else + + typedef int32_t intmax_t; + typedef uint32_t uintmax_t; + +# endif + +} // namespace boost + +#else // BOOST_HAS_STDINT_H + +# include // implementation artifact; not part of interface +# include // needed for limits macros + + +namespace boost +{ + +// These are fairly safe guesses for some 16-bit, and most 32-bit and 64-bit +// platforms. For other systems, they will have to be hand tailored. +// +// Because the fast types are assumed to be the same as the undecorated types, +// it may be possible to hand tailor a more efficient implementation. Such +// an optimization may be illusionary; on the Intel x86-family 386 on, for +// example, byte arithmetic and load/stores are as fast as "int" sized ones. + +// 8-bit types ------------------------------------------------------------// + +# if UCHAR_MAX == 0xff + typedef signed char int8_t; + typedef signed char int_least8_t; + typedef signed char int_fast8_t; + typedef unsigned char uint8_t; + typedef unsigned char uint_least8_t; + typedef unsigned char uint_fast8_t; +# else +# error defaults not correct; you must hand modify boost/cstdint.hpp +# endif + +// 16-bit types -----------------------------------------------------------// + +# if USHRT_MAX == 0xffff +# if defined(__crayx1) + // The Cray X1 has a 16-bit short, however it is not recommend + // for use in performance critical code. + typedef short int16_t; + typedef short int_least16_t; + typedef int int_fast16_t; + typedef unsigned short uint16_t; + typedef unsigned short uint_least16_t; + typedef unsigned int uint_fast16_t; +# else + typedef short int16_t; + typedef short int_least16_t; + typedef short int_fast16_t; + typedef unsigned short uint16_t; + typedef unsigned short uint_least16_t; + typedef unsigned short uint_fast16_t; +# endif +# elif (USHRT_MAX == 0xffffffff) && defined(CRAY) + // no 16-bit types on Cray: + typedef short int_least16_t; + typedef short int_fast16_t; + typedef unsigned short uint_least16_t; + typedef unsigned short uint_fast16_t; +# else +# error defaults not correct; you must hand modify boost/cstdint.hpp +# endif + +// 32-bit types -----------------------------------------------------------// + +# if ULONG_MAX == 0xffffffff + typedef long int32_t; + typedef long int_least32_t; + typedef long int_fast32_t; + typedef unsigned long uint32_t; + typedef unsigned long uint_least32_t; + typedef unsigned long uint_fast32_t; +# elif UINT_MAX == 0xffffffff + typedef int int32_t; + typedef int int_least32_t; + typedef int int_fast32_t; + typedef unsigned int uint32_t; + typedef unsigned int uint_least32_t; + typedef unsigned int uint_fast32_t; +# else +# error defaults not correct; you must hand modify boost/cstdint.hpp +# endif + +// 64-bit types + intmax_t and uintmax_t ----------------------------------// + +# if defined(BOOST_HAS_LONG_LONG) && \ + !defined(BOOST_MSVC) && !defined(__BORLANDC__) && \ + (!defined(__GLIBCPP__) || defined(_GLIBCPP_USE_LONG_LONG)) && \ + (defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) || defined(ULONGLONG_MAX)) +# if defined(__hpux) + // HP-UX's value of ULONG_LONG_MAX is unusable in preprocessor expressions +# elif (defined(ULLONG_MAX) && ULLONG_MAX == 18446744073709551615ULL) || (defined(ULONG_LONG_MAX) && ULONG_LONG_MAX == 18446744073709551615ULL) || (defined(ULONGLONG_MAX) && ULONGLONG_MAX == 18446744073709551615ULL) + // 2**64 - 1 +# else +# error defaults not correct; you must hand modify boost/cstdint.hpp +# endif + + typedef ::boost::long_long_type intmax_t; + typedef ::boost::ulong_long_type uintmax_t; + typedef ::boost::long_long_type int64_t; + typedef ::boost::long_long_type int_least64_t; + typedef ::boost::long_long_type int_fast64_t; + typedef ::boost::ulong_long_type uint64_t; + typedef ::boost::ulong_long_type uint_least64_t; + typedef ::boost::ulong_long_type uint_fast64_t; + +# elif ULONG_MAX != 0xffffffff + +# if ULONG_MAX == 18446744073709551615 // 2**64 - 1 + typedef long intmax_t; + typedef unsigned long uintmax_t; + typedef long int64_t; + typedef long int_least64_t; + typedef long int_fast64_t; + typedef unsigned long uint64_t; + typedef unsigned long uint_least64_t; + typedef unsigned long uint_fast64_t; +# else +# error defaults not correct; you must hand modify boost/cstdint.hpp +# endif +# elif defined(__GNUC__) && defined(BOOST_HAS_LONG_LONG) + __extension__ typedef long long intmax_t; + __extension__ typedef unsigned long long uintmax_t; + __extension__ typedef long long int64_t; + __extension__ typedef long long int_least64_t; + __extension__ typedef long long int_fast64_t; + __extension__ typedef unsigned long long uint64_t; + __extension__ typedef unsigned long long uint_least64_t; + __extension__ typedef unsigned long long uint_fast64_t; +# elif defined(BOOST_HAS_MS_INT64) + // + // we have Borland/Intel/Microsoft __int64: + // + typedef __int64 intmax_t; + typedef unsigned __int64 uintmax_t; + typedef __int64 int64_t; + typedef __int64 int_least64_t; + typedef __int64 int_fast64_t; + typedef unsigned __int64 uint64_t; + typedef unsigned __int64 uint_least64_t; + typedef unsigned __int64 uint_fast64_t; +# else // assume no 64-bit integers +# define BOOST_NO_INT64_T + typedef int32_t intmax_t; + typedef uint32_t uintmax_t; +# endif + +} // namespace boost + + +#endif // BOOST_HAS_STDINT_H + +#endif // BOOST_CSTDINT_HPP + + +/**************************************************** + +Macro definition section: + +Define various INTXX_C macros only if +__STDC_CONSTANT_MACROS is defined. + +Undefine the macros if __STDC_CONSTANT_MACROS is +not defined and the macros are (cf ). + +Added 23rd September 2000 (John Maddock). +Modified 11th September 2001 to be excluded when +BOOST_HAS_STDINT_H is defined (John Maddock). + +******************************************************/ + +#if defined(__STDC_CONSTANT_MACROS) && !defined(BOOST__STDC_CONSTANT_MACROS_DEFINED) && !defined(BOOST_HAS_STDINT_H) +# define BOOST__STDC_CONSTANT_MACROS_DEFINED +# if defined(BOOST_HAS_MS_INT64) +// +// Borland/Intel/Microsoft compilers have width specific suffixes: +// +# define INT8_C(value) value##i8 +# define INT16_C(value) value##i16 +# define INT32_C(value) value##i32 +# define INT64_C(value) value##i64 +# ifdef __BORLANDC__ + // Borland bug: appending ui8 makes the type a signed char +# define UINT8_C(value) static_cast(value##u) +# else +# define UINT8_C(value) value##ui8 +# endif +# define UINT16_C(value) value##ui16 +# define UINT32_C(value) value##ui32 +# define UINT64_C(value) value##ui64 +# define INTMAX_C(value) value##i64 +# define UINTMAX_C(value) value##ui64 + +# else +// do it the old fashioned way: + +// 8-bit types ------------------------------------------------------------// + +# if UCHAR_MAX == 0xff +# define INT8_C(value) static_cast(value) +# define UINT8_C(value) static_cast(value##u) +# endif + +// 16-bit types -----------------------------------------------------------// + +# if USHRT_MAX == 0xffff +# define INT16_C(value) static_cast(value) +# define UINT16_C(value) static_cast(value##u) +# endif + +// 32-bit types -----------------------------------------------------------// + +# if UINT_MAX == 0xffffffff +# define INT32_C(value) value +# define UINT32_C(value) value##u +# elif ULONG_MAX == 0xffffffff +# define INT32_C(value) value##L +# define UINT32_C(value) value##uL +# endif + +// 64-bit types + intmax_t and uintmax_t ----------------------------------// + +# if defined(BOOST_HAS_LONG_LONG) && \ + (defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) || defined(ULONGLONG_MAX)) + +# if defined(__hpux) + // HP-UX's value of ULONG_LONG_MAX is unusable in preprocessor expressions +# elif (defined(ULLONG_MAX) && ULLONG_MAX == 18446744073709551615U) || \ + (defined(ULONG_LONG_MAX) && ULONG_LONG_MAX == 18446744073709551615U) || \ + (defined(ULONGLONG_MAX) && ULONGLONG_MAX == 18446744073709551615U) + +# else +# error defaults not correct; you must hand modify boost/cstdint.hpp +# endif +# define INT64_C(value) value##LL +# define UINT64_C(value) value##uLL +# elif ULONG_MAX != 0xffffffff + +# if ULONG_MAX == 18446744073709551615 // 2**64 - 1 +# define INT64_C(value) value##L +# define UINT64_C(value) value##uL +# else +# error defaults not correct; you must hand modify boost/cstdint.hpp +# endif +# endif + +# ifdef BOOST_NO_INT64_T +# define INTMAX_C(value) INT32_C(value) +# define UINTMAX_C(value) UINT32_C(value) +# else +# define INTMAX_C(value) INT64_C(value) +# define UINTMAX_C(value) UINT64_C(value) +# endif + +# endif // Borland/Microsoft specific width suffixes + + +#elif defined(BOOST__STDC_CONSTANT_MACROS_DEFINED) && !defined(__STDC_CONSTANT_MACROS) && !defined(BOOST_HAS_STDINT_H) +// +// undef all the macros: +// +# undef INT8_C +# undef INT16_C +# undef INT32_C +# undef INT64_C +# undef UINT8_C +# undef UINT16_C +# undef UINT32_C +# undef UINT64_C +# undef INTMAX_C +# undef UINTMAX_C + +#endif // __STDC_CONSTANT_MACROS_DEFINED etc. + + + + diff --git a/win32/include/boost/cstdlib.hpp b/win32/include/boost/cstdlib.hpp new file mode 100755 index 000000000..9f43030ff --- /dev/null +++ b/win32/include/boost/cstdlib.hpp @@ -0,0 +1,41 @@ +// boost/cstdlib.hpp header ------------------------------------------------// + +// Copyright Beman Dawes 2001. 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) + +// See http://www.boost.org/libs/utility/cstdlib.html for documentation. + +// Revision History +// 26 Feb 01 Initial version (Beman Dawes) + +#ifndef BOOST_CSTDLIB_HPP +#define BOOST_CSTDLIB_HPP + +#include + +namespace boost +{ + // The intent is to propose the following for addition to namespace std + // in the C++ Standard Library, and to then deprecate EXIT_SUCCESS and + // EXIT_FAILURE. As an implementation detail, this header defines the + // new constants in terms of EXIT_SUCCESS and EXIT_FAILURE. In a new + // standard, the constants would be implementation-defined, although it + // might be worthwhile to "suggest" (which a standard is allowed to do) + // values of 0 and 1 respectively. + + // Rationale for having multiple failure values: some environments may + // wish to distinguish between different classes of errors. + // Rationale for choice of values: programs often use values < 100 for + // their own error reporting. Values > 255 are sometimes reserved for + // system detected errors. 200/201 were suggested to minimize conflict. + + const int exit_success = EXIT_SUCCESS; // implementation-defined value + const int exit_failure = EXIT_FAILURE; // implementation-defined value + const int exit_exception_failure = 200; // otherwise uncaught exception + const int exit_test_failure = 201; // report_error or + // report_critical_error called. +} + +#endif + diff --git a/win32/include/boost/current_function.hpp b/win32/include/boost/current_function.hpp new file mode 100755 index 000000000..3714e9e3b --- /dev/null +++ b/win32/include/boost/current_function.hpp @@ -0,0 +1,67 @@ +#ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED +#define BOOST_CURRENT_FUNCTION_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/current_function.hpp - BOOST_CURRENT_FUNCTION +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// 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) +// +// http://www.boost.org/libs/utility/current_function.html +// + +namespace boost +{ + +namespace detail +{ + +inline void current_function_helper() +{ + +#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) + +# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__ + +#elif defined(__DMC__) && (__DMC__ >= 0x810) + +# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__ + +#elif defined(__FUNCSIG__) + +# define BOOST_CURRENT_FUNCTION __FUNCSIG__ + +#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500)) + +# define BOOST_CURRENT_FUNCTION __FUNCTION__ + +#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550) + +# define BOOST_CURRENT_FUNCTION __FUNC__ + +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901) + +# define BOOST_CURRENT_FUNCTION __func__ + +#else + +# define BOOST_CURRENT_FUNCTION "(unknown)" + +#endif + +} + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED diff --git a/win32/include/boost/date_time.hpp b/win32/include/boost/date_time.hpp new file mode 100755 index 000000000..6cb1ec36d --- /dev/null +++ b/win32/include/boost/date_time.hpp @@ -0,0 +1,17 @@ +#ifndef BOOST_DATE_TIME_ALL_HPP___ +#define BOOST_DATE_TIME_ALL_HPP___ + +/* Copyright (c) 2006 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + // See www.boost.org/libs/date_time for documentation. + +//gregorian and posix time included by indirectly +#include "boost/date_time/local_time/local_time.hpp" + +#endif // BOOST_DATE_TIME_ALL_HPP___ diff --git a/win32/include/boost/date_time/adjust_functors.hpp b/win32/include/boost/date_time/adjust_functors.hpp new file mode 100755 index 000000000..960c83103 --- /dev/null +++ b/win32/include/boost/date_time/adjust_functors.hpp @@ -0,0 +1,178 @@ +#ifndef _DATE_TIME_ADJUST_FUNCTORS_HPP___ +#define _DATE_TIME_ADJUST_FUNCTORS_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/date.hpp" +#include "boost/date_time/wrapping_int.hpp" + +namespace boost { +namespace date_time { + + + //! Functor to iterate a fixed number of days + template + class day_functor + { + public: + typedef typename date_type::duration_type duration_type; + day_functor(int f) : f_(f) {} + duration_type get_offset(const date_type& d) const + { + // why is 'd' a parameter??? + // fix compiler warnings + d.year(); + return duration_type(f_); + } + duration_type get_neg_offset(const date_type& d) const + { + // fix compiler warnings + d.year(); + return duration_type(-f_); + } + private: + int f_; + }; + + + //! Provides calculation to find next nth month given a date + /*! This adjustment function provides the logic for 'month-based' + * advancement on a ymd based calendar. The policy it uses + * to handle the non existant end of month days is to back + * up to the last day of the month. Also, if the starting + * date is the last day of a month, this functor will attempt + * to adjust to the end of the month. + + */ + template + class month_functor + { + public: + typedef typename date_type::duration_type duration_type; + typedef typename date_type::calendar_type cal_type; + typedef typename cal_type::ymd_type ymd_type; + typedef typename cal_type::day_type day_type; + + month_functor(int f) : f_(f), origDayOfMonth_(0) {} + duration_type get_offset(const date_type& d) const + { + ymd_type ymd(d.year_month_day()); + if (origDayOfMonth_ == 0) { + origDayOfMonth_ = ymd.day; + day_type endOfMonthDay(cal_type::end_of_month_day(ymd.year,ymd.month)); + if (endOfMonthDay == ymd.day) { + origDayOfMonth_ = -1; //force the value to the end of month + } + } + typedef date_time::wrapping_int2 wrap_int2; + typedef typename wrap_int2::int_type int_type; + wrap_int2 wi(ymd.month); + //calc the year wrap around, add() returns 0 or 1 if wrapped + int_type year = wi.add(static_cast(f_)); + year = static_cast(year + ymd.year); //calculate resulting year +// std::cout << "trace wi: " << wi.as_int() << std::endl; +// std::cout << "trace year: " << year << std::endl; + //find the last day for the new month + day_type resultingEndOfMonthDay(cal_type::end_of_month_day(year, wi.as_int())); + //original was the end of month -- force to last day of month + if (origDayOfMonth_ == -1) { + return date_type(year, wi.as_int(), resultingEndOfMonthDay) - d; + } + day_type dayOfMonth = origDayOfMonth_; + if (dayOfMonth > resultingEndOfMonthDay) { + dayOfMonth = resultingEndOfMonthDay; + } + return date_type(year, wi.as_int(), dayOfMonth) - d; + } + //! Returns a negative duration_type + duration_type get_neg_offset(const date_type& d) const + { + ymd_type ymd(d.year_month_day()); + if (origDayOfMonth_ == 0) { + origDayOfMonth_ = ymd.day; + day_type endOfMonthDay(cal_type::end_of_month_day(ymd.year,ymd.month)); + if (endOfMonthDay == ymd.day) { + origDayOfMonth_ = -1; //force the value to the end of month + } + } + typedef date_time::wrapping_int2 wrap_int2; + typedef typename wrap_int2::int_type int_type; + wrap_int2 wi(ymd.month); + //calc the year wrap around, add() returns 0 or 1 if wrapped + int_type year = wi.subtract(static_cast(f_)); + year = static_cast(year + ymd.year); //calculate resulting year + //find the last day for the new month + day_type resultingEndOfMonthDay(cal_type::end_of_month_day(year, wi.as_int())); + //original was the end of month -- force to last day of month + if (origDayOfMonth_ == -1) { + return date_type(year, wi.as_int(), resultingEndOfMonthDay) - d; + } + day_type dayOfMonth = origDayOfMonth_; + if (dayOfMonth > resultingEndOfMonthDay) { + dayOfMonth = resultingEndOfMonthDay; + } + return date_type(year, wi.as_int(), dayOfMonth) - d; + } + private: + int f_; + mutable short origDayOfMonth_; + }; + + + //! Functor to iterate a over weeks + template + class week_functor + { + public: + typedef typename date_type::duration_type duration_type; + typedef typename date_type::calendar_type calendar_type; + week_functor(int f) : f_(f) {} + duration_type get_offset(const date_type& d) const + { + // why is 'd' a parameter??? + // fix compiler warnings + d.year(); + return duration_type(f_*calendar_type::days_in_week()); + } + duration_type get_neg_offset(const date_type& d) const + { + // fix compiler warnings + d.year(); + return duration_type(-f_*calendar_type::days_in_week()); + } + private: + int f_; + }; + + //! Functor to iterate by a year adjusting for leap years + template + class year_functor + { + public: + //typedef typename date_type::year_type year_type; + typedef typename date_type::duration_type duration_type; + year_functor(int f) : _mf(f * 12) {} + duration_type get_offset(const date_type& d) const + { + return _mf.get_offset(d); + } + duration_type get_neg_offset(const date_type& d) const + { + return _mf.get_neg_offset(d); + } + private: + month_functor _mf; + }; + + +} }//namespace date_time + + +#endif + diff --git a/win32/include/boost/date_time/c_local_time_adjustor.hpp b/win32/include/boost/date_time/c_local_time_adjustor.hpp new file mode 100755 index 000000000..093a56d8b --- /dev/null +++ b/win32/include/boost/date_time/c_local_time_adjustor.hpp @@ -0,0 +1,64 @@ +#ifndef DATE_TIME_C_LOCAL_TIME_ADJUSTOR_HPP__ +#define DATE_TIME_C_LOCAL_TIME_ADJUSTOR_HPP__ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! @file c_local_time_adjustor.hpp + Time adjustment calculations based on machine +*/ + +#include +#include "boost/date_time/c_time.hpp" + +namespace boost { +namespace date_time { + + //! Adjust to / from utc using the C API + /*! Warning!!! This class assumes that timezone settings of the + * machine are correct. This can be a very dangerous assumption. + */ + template + class c_local_adjustor { + public: + typedef typename time_type::time_duration_type time_duration_type; + typedef typename time_type::date_type date_type; + typedef typename date_type::duration_type date_duration_type; + //! Convert a utc time to local time + static time_type utc_to_local(const time_type& t) + { + date_type time_t_start_day(1970,1,1); + time_type time_t_start_time(time_t_start_day,time_duration_type(0,0,0)); + if (t < time_t_start_time) { + throw std::out_of_range("Cannot convert dates prior to Jan 1, 1970"); + } + date_duration_type dd = t.date() - time_t_start_day; + time_duration_type td = t.time_of_day(); + std::time_t t2 = dd.days()*86400 + td.hours()*3600 + td.minutes()*60 + td.seconds(); + std::tm tms, *tms_ptr; + tms_ptr = c_time::localtime(&t2, &tms); + //tms_ptr = std::localtime(&t2); + date_type d(static_cast(tms_ptr->tm_year + 1900), + static_cast(tms_ptr->tm_mon + 1), + static_cast(tms_ptr->tm_mday)); + time_duration_type td2(tms_ptr->tm_hour, + tms_ptr->tm_min, + tms_ptr->tm_sec, + t.time_of_day().fractional_seconds()); + + return time_type(d,td2); + } + }; + + + +} } //namespace date_time + + + +#endif diff --git a/win32/include/boost/date_time/c_time.hpp b/win32/include/boost/date_time/c_time.hpp new file mode 100755 index 000000000..f76c637b8 --- /dev/null +++ b/win32/include/boost/date_time/c_time.hpp @@ -0,0 +1,91 @@ +#ifndef DATE_TIME_C_TIME_HPP___ +#define DATE_TIME_C_TIME_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +/*! @file c_time.hpp + Provide workarounds related to the ctime header +*/ + +#include "boost/date_time/compiler_config.hpp" +#include +//Work around libraries that don't put time_t and time in namespace std + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::time_t; using ::time; using ::localtime; + using ::tm; using ::gmtime; } +#endif // BOOST_NO_STDC_NAMESPACE + +//The following is used to support high precision time clocks +#ifdef BOOST_HAS_GETTIMEOFDAY +#include +#endif + +#ifdef BOOST_HAS_FTIME +#include +#endif + +namespace boost { +namespace date_time { + //! Provides a uniform interface to some 'ctime' functions + /*! Provides a uniform interface to some ctime functions and + * their '_r' counterparts. The '_r' functions require a pointer to a + * user created std::tm struct whereas the regular functions use a + * staticly created struct and return a pointer to that. These wrapper + * functions require the user to create a std::tm struct and send in a + * pointer to it. A pointer to the user created struct will be returned. */ + struct c_time { + public: +#if defined(BOOST_DATE_TIME_HAS_REENTRANT_STD_FUNCTIONS) + //! requires a pointer to a user created std::tm struct + inline + static std::tm* localtime(const std::time_t* t, std::tm* result) + { + // localtime_r() not in namespace std??? + result = localtime_r(t, result); + return result; + } + //! requires a pointer to a user created std::tm struct + inline + static std::tm* gmtime(const std::time_t* t, std::tm* result) + { + // gmtime_r() not in namespace std??? + result = gmtime_r(t, result); + return result; + } +#else // BOOST_HAS_THREADS + +#if (defined(_MSC_VER) && (_MSC_VER >= 1400)) +#pragma warning(push) // preserve warning settings +#pragma warning(disable : 4996) // disable depricated localtime/gmtime warning on vc8 +#endif // _MSC_VER >= 1400 + //! requires a pointer to a user created std::tm struct + inline + static std::tm* localtime(const std::time_t* t, std::tm* result) + { + result = std::localtime(t); + return result; + } + //! requires a pointer to a user created std::tm struct + inline + static std::tm* gmtime(const std::time_t* t, std::tm* result) + { + result = std::gmtime(t); + return result; + } +#if (defined(_MSC_VER) && (_MSC_VER >= 1400)) +#pragma warning(pop) // restore warnings to previous state +#endif // _MSC_VER >= 1400 + +#endif // BOOST_HAS_THREADS + }; +}} // namespaces + +#endif // DATE_TIME_C_TIME_HPP___ diff --git a/win32/include/boost/date_time/compiler_config.hpp b/win32/include/boost/date_time/compiler_config.hpp new file mode 100755 index 000000000..4fbebbaa5 --- /dev/null +++ b/win32/include/boost/date_time/compiler_config.hpp @@ -0,0 +1,149 @@ +#ifndef DATE_TIME_COMPILER_CONFIG_HPP___ +#define DATE_TIME_COMPILER_CONFIG_HPP___ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + #include "boost/detail/workaround.hpp" + +// With boost release 1.33, date_time will be using a different, +// more flexible, IO system. This new system is not compatible with +// old compilers. The original date_time IO system remains for those +// compilers. They must define this macro to use the legacy IO. +// (defined(__BORLANDC__) && (__BORLANDC__ <= 0x0581) ) ) && + #if( BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581) ) \ + || BOOST_WORKAROUND( __GNUC__, < 3) \ + || (BOOST_WORKAROUND( _MSC_VER, <= 1300) ) \ + ) \ + && !defined(USE_DATE_TIME_PRE_1_33_FACET_IO) +# define USE_DATE_TIME_PRE_1_33_FACET_IO +#endif + + +// This file performs some local compiler configurations + +#include "boost/date_time/locale_config.hpp" //set up locale configurations + +//Set up a configuration parameter for platforms that have +//GetTimeOfDay +#if defined(BOOST_HAS_GETTIMEOFDAY) || defined(BOOST_HAS_FTIME) +#define BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK +#endif + +// To Force no default constructors for date & ptime, un-comment following +//#define DATE_TIME_NO_DEFAULT_CONSTRUCTOR + +// Include extensions to date_duration - comment out to remove this feature +#define BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES +// these extensions are known to cause problems with gcc295 +#if defined(__GNUC__) && (__GNUC__ < 3) +#undef BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES +#endif + +#if (defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) || BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581) ) ) +#define BOOST_DATE_TIME_NO_MEMBER_INIT +#endif + +// include these types before we try to re-define them +#include "boost/cstdint.hpp" + +//Define INT64_C for compilers that don't have it +#if (!defined(INT64_C)) +#define INT64_C(value) int64_t(value) +#endif + + +/* Workaround for Borland iterator error. Error was "Cannot convert 'istream *' to 'wistream *' in function istream_iterator<>::istream_iterator() */ +#if defined(__BORLANDC__) && defined(BOOST_BCB_WITH_RW_LIB) +#define BOOST_DATE_TIME_NO_WISTREAM_ITERATOR +#endif + + +// Borland v5.64 does not have the following in std namespace; v5.5.1 does +#if defined(__BORLANDC__) && defined(BOOST_BCB_WITH_STLPORT) +#include +namespace std { + using stlport::tolower; + using stlport::ctype; + using stlport::use_facet; +} +#endif + +// workaround for errors associated with output for date classes +// modifications and input streaming for time classes. +// Compilers affected are: +// gcc295, msvc (neither with STLPort), any borland +// +#if (((defined(__GNUC__) && (__GNUC__ < 3)) || \ + (defined(_MSC_VER) && (_MSC_VER < 1300)) ) && \ + !defined(_STLP_OWN_IOSTREAMS) ) || \ + BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581) ) +#define BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS +#endif + +/* The following handles the definition of the necessary macros + * for dll building on Win32 platforms. + * + * For code that will be placed in the date_time .dll, + * it must be properly prefixed with BOOST_DATE_TIME_DECL. + * The corresponding .cpp file must have BOOST_DATE_TIME_SOURCES + * defined before including its header. For examples see: + * greg_month.hpp & greg_month.cpp + * + */ + +#ifdef BOOST_HAS_DECLSPEC // defined in config system + // we need to import/export our code only if the user has specifically + // asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost + // libraries to be dynamically linked, or BOOST_DATE_TIME_DYN_LINK + // if they want just this one to be dynamically liked: +# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_DATE_TIME_DYN_LINK) + // export if this is our own source, otherwise import: +# ifdef BOOST_DATE_TIME_SOURCE +# define BOOST_DATE_TIME_DECL __declspec(dllexport) +# else +# define BOOST_DATE_TIME_DECL __declspec(dllimport) +# endif // BOOST_DATE_TIME_SOURCE +# endif // DYN_LINK +#endif // BOOST_HAS_DECLSPEC +// +// if BOOST_WHATEVER_DECL isn't defined yet define it now: +#ifndef BOOST_DATE_TIME_DECL +# define BOOST_DATE_TIME_DECL +#endif + +// +// Automatically link to the correct build variant where possible. +// +#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_DATE_TIME_NO_LIB) && !defined(BOOST_DATE_TIME_SOURCE) +// +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it: +// +#define BOOST_LIB_NAME boost_date_time +// +// If we're importing code from a dll, then tell auto_link.hpp about it: +// +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_DATE_TIME_DYN_LINK) +# define BOOST_DYN_LINK +#endif +// +// And include the header that does the work: +// +#include +#endif // auto-linking disabled + +#if defined(BOOST_HAS_THREADS) +# if defined(_MSC_VER) || defined(__MWERKS__) || defined(__MINGW32__) || defined(__BORLANDC__) + //no reentrant posix functions (eg: localtime_r) +# elif (!defined(__hpux) || (defined(__hpux) && defined(_REENTRANT))) +# define BOOST_DATE_TIME_HAS_REENTRANT_STD_FUNCTIONS +# endif +#endif + + +#endif diff --git a/win32/include/boost/date_time/constrained_value.hpp b/win32/include/boost/date_time/constrained_value.hpp new file mode 100755 index 000000000..c5c3cf86d --- /dev/null +++ b/win32/include/boost/date_time/constrained_value.hpp @@ -0,0 +1,98 @@ +#ifndef CONSTRAINED_VALUE_HPP___ +#define CONSTRAINED_VALUE_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include + +namespace boost { + +//! Namespace containing constrained_value template and types +namespace CV { + //! Represent a min or max violation type + enum violation_enum {min_violation, max_violation}; + + //! A template to specify a constrained basic value type + /*! This template provides a quick way to generate + * an integer type with a constrained range. The type + * provides for the ability to specify the min, max, and + * and error handling policy. + * + * value policies + * A class that provides the range limits via the min and + * max functions as well as a function on_error that + * determines how errors are handled. A common strategy + * would be to assert or throw and exception. The on_error + * is passed both the current value and the new value that + * is in error. + * + */ + template + class constrained_value { + public: + typedef typename value_policies::value_type value_type; + // typedef except_type exception_type; + constrained_value(value_type value) + { + assign(value); + }; + constrained_value& operator=(value_type v) + { + assign(v); + return *this; + } + //! Return the max allowed value (traits method) + static value_type max BOOST_PREVENT_MACRO_SUBSTITUTION () {return (value_policies::max)();}; + //! Return the min allowed value (traits method) + static value_type min BOOST_PREVENT_MACRO_SUBSTITUTION () {return (value_policies::min)();}; + //! Coerce into the representation type + operator value_type() const {return value_;}; + protected: + value_type value_; + private: + void assign(value_type value) + { + //adding 1 below gets rid of a compiler warning which occurs when the + //min_value is 0 and the type is unsigned.... + if (value+1 < (min)()+1) { + value_policies::on_error(value_, value, min_violation); + return; + } + if (value > (max)()) { + value_policies::on_error(value_, value, max_violation); + return; + } + value_ = value; + + } +}; + + //! Template to shortcut the constrained_value policy creation process + template + class simple_exception_policy + { + public: + typedef rep_type value_type; + static rep_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return min_value; }; + static rep_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return max_value;}; + static void on_error(rep_type, rep_type, violation_enum) + { + throw exception_type(); + } + }; + + + +} } //namespace CV + + + + +#endif diff --git a/win32/include/boost/date_time/date.hpp b/win32/include/boost/date_time/date.hpp new file mode 100755 index 000000000..c96ce6fb3 --- /dev/null +++ b/win32/include/boost/date_time/date.hpp @@ -0,0 +1,197 @@ +#ifndef DATE_TIME_DATE_HPP___ +#define DATE_TIME_DATE_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/year_month_day.hpp" +#include "boost/date_time/special_defs.hpp" +#include "boost/operators.hpp" + +namespace boost { +namespace date_time { + + //!Representation of timepoint at the one day level resolution. + /*! + The date template represents an interface shell for a date class + that is based on a year-month-day system such as the gregorian + or iso systems. It provides basic operations to enable calculation + and comparisons. + + Theory + + This date representation fundamentally departs from the C tm struct + approach. The goal for this type is to provide efficient date + operations (add, subtract) and storage (minimize space to represent) + in a concrete class. Thus, the date uses a count internally to + represent a particular date. The calendar parameter defines + the policies for converting the the year-month-day and internal + counted form here. Applications that need to perform heavy + formatting of the same date repeatedly will perform better + by using the year-month-day representation. + + Internally the date uses a day number to represent the date. + This is a monotonic time representation. This representation + allows for fast comparison as well as simplifying + the creation of writing numeric operations. Essentially, the + internal day number is like adjusted julian day. The adjustment + is determined by the Epoch date which is represented as day 1 of + the calendar. Day 0 is reserved for negative infinity so that + any actual date is automatically greater than negative infinity. + When a date is constructed from a date or formatted for output, + the appropriate conversions are applied to create the year, month, + day representations. + */ + + + template + class date : private + boost::less_than_comparable > + { + public: + typedef T date_type; + typedef calendar calendar_type; + typedef typename calendar::date_traits_type traits_type; + typedef duration_type_ duration_type; + typedef typename calendar::year_type year_type; + typedef typename calendar::month_type month_type; + typedef typename calendar::day_type day_type; + typedef typename calendar::ymd_type ymd_type; + typedef typename calendar::date_rep_type date_rep_type; + typedef typename calendar::date_int_type date_int_type; + typedef typename calendar::day_of_week_type day_of_week_type; + date(year_type y, month_type m, day_type d) + : days_(calendar::day_number(ymd_type(y, m, d))) + {} + date(const ymd_type& ymd) + : days_(calendar::day_number(ymd)) + {} + //let the compiler write copy, assignment, and destructor + year_type year() const + { + ymd_type ymd = calendar::from_day_number(days_); + return ymd.year; + } + month_type month() const + { + ymd_type ymd = calendar::from_day_number(days_); + return ymd.month; + } + day_type day() const + { + ymd_type ymd = calendar::from_day_number(days_); + return ymd.day; + } + day_of_week_type day_of_week() const + { + ymd_type ymd = calendar::from_day_number(days_); + return calendar::day_of_week(ymd); + } + ymd_type year_month_day() const + { + return calendar::from_day_number(days_); + } + bool operator<(const date_type& rhs) const + { + return days_ < rhs.days_; + } + bool operator==(const date_type& rhs) const + { + return days_ == rhs.days_; + } + //! check to see if date is a special value + bool is_special()const + { + return(is_not_a_date() || is_infinity()); + } + //! check to see if date is not a value + bool is_not_a_date() const + { + return traits_type::is_not_a_number(days_); + } + //! check to see if date is one of the infinity values + bool is_infinity() const + { + return traits_type::is_inf(days_); + } + //! check to see if date is greater than all possible dates + bool is_pos_infinity() const + { + return traits_type::is_pos_inf(days_); + } + //! check to see if date is greater than all possible dates + bool is_neg_infinity() const + { + return traits_type::is_neg_inf(days_); + } + //! return as a special value or a not_special if a normal date + special_values as_special() const + { + return traits_type::to_special(days_); + } + duration_type operator-(const date_type& d) const + { + date_rep_type val = date_rep_type(days_) - date_rep_type(d.days_); + return duration_type(val.as_number()); + } + + date_type operator-(const duration_type& dd) const + { + if(dd.is_special()) + { + return date_type(date_rep_type(days_) - dd.get_rep()); + } + return date_type(date_rep_type(days_) - dd.days()); + } + date_type operator-=(const duration_type& dd) + { + *this = *this - dd; + return date_type(days_); + } + date_rep_type day_count() const + { + return days_; + }; + //allow internal access from operators + date_type operator+(const duration_type& dd) const + { + if(dd.is_special()) + { + return date_type(date_rep_type(days_) + dd.get_rep()); + } + return date_type(date_rep_type(days_) + dd.days()); + } + date_type operator+=(const duration_type& dd) + { + *this = *this + dd; + return date_type(days_); + } + + //see reference + protected: + /*! This is a private constructor which allows for the creation of new + dates. It is not exposed to users since that would require class + users to understand the inner workings of the date class. + */ + explicit date(date_int_type days) : days_(days) {}; + explicit date(date_rep_type days) : days_(days.as_number()) {}; + date_int_type days_; + + }; + + + + +} } // namespace date_time + + + + +#endif diff --git a/win32/include/boost/date_time/date_clock_device.hpp b/win32/include/boost/date_time/date_clock_device.hpp new file mode 100755 index 000000000..407d41a0e --- /dev/null +++ b/win32/include/boost/date_time/date_clock_device.hpp @@ -0,0 +1,77 @@ +#ifndef DATE_CLOCK_DEVICE_HPP___ +#define DATE_CLOCK_DEVICE_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/c_time.hpp" + + +namespace boost { +namespace date_time { + + //! A clock providing day level services based on C time_t capabilities + /*! This clock uses Posix interfaces as its implementation and hence + * uses the timezone settings of the operating system. Incorrect + * user settings will result in incorrect results for the calls + * to local_day. + */ + template + class day_clock + { + public: + typedef typename date_type::ymd_type ymd_type; + //! Get the local day as a date type + static date_type local_day() + { + return date_type(local_day_ymd()); + } + //! Get the local day as a ymd_type + static typename date_type::ymd_type local_day_ymd() + { + ::std::tm result; + ::std::tm* curr = get_local_time(result); + return ymd_type(curr->tm_year + 1900, + curr->tm_mon + 1, + curr->tm_mday); + } + //! Get the current day in universal date as a ymd_type + static typename date_type::ymd_type universal_day_ymd() + { + ::std::tm result; + ::std::tm* curr = get_universal_time(result); + return ymd_type(curr->tm_year + 1900, + curr->tm_mon + 1, + curr->tm_mday); + } + //! Get the UTC day as a date type + static date_type universal_day() + { + return date_type(universal_day_ymd()); + } + + private: + static ::std::tm* get_local_time(std::tm& result) + { + ::std::time_t t; + ::std::time(&t); + return c_time::localtime(&t, &result); + } + static ::std::tm* get_universal_time(std::tm& result) + { + ::std::time_t t; + ::std::time(&t); + return c_time::gmtime(&t, &result); + } + + }; + +} } //namespace date_time + + +#endif diff --git a/win32/include/boost/date_time/date_defs.hpp b/win32/include/boost/date_time/date_defs.hpp new file mode 100755 index 000000000..b3b623b14 --- /dev/null +++ b/win32/include/boost/date_time/date_defs.hpp @@ -0,0 +1,26 @@ +#ifndef DATE_TIME_DATE_DEFS_HPP +#define DATE_TIME_DATE_DEFS_HPP + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +namespace boost { +namespace date_time { + + //! An enumeration of weekday names + enum weekdays {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday}; + + //! Simple enum to allow for nice programming with Jan, Feb, etc + enum months_of_year {Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec,NotAMonth,NumMonths}; + +} } //namespace date_time + + + +#endif diff --git a/win32/include/boost/date_time/date_duration.hpp b/win32/include/boost/date_time/date_duration.hpp new file mode 100755 index 000000000..063a96086 --- /dev/null +++ b/win32/include/boost/date_time/date_duration.hpp @@ -0,0 +1,147 @@ +#ifndef DATE_TIME_DATE_DURATION__ +#define DATE_TIME_DATE_DURATION__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include + +namespace boost { +namespace date_time { + + + //! Duration type with date level resolution + template + class date_duration : private + boost::less_than_comparable + , boost::equality_comparable< date_duration< duration_rep_traits> + , boost::addable< date_duration< duration_rep_traits> + , boost::subtractable< date_duration< duration_rep_traits> + > > > > + { + public: + typedef typename duration_rep_traits::int_type duration_rep_type; + typedef typename duration_rep_traits::impl_type duration_rep; + + //! Construct from a day count + explicit date_duration(duration_rep day_count) : days_(day_count) {}; + + /*! construct from special_values - only works when + * instantiated with duration_traits_adapted */ + date_duration(special_values sv) : + days_(duration_rep::from_special(sv)) + {} + + // copy constructor required for addable<> & subtractable<> + //! Construct from another date_duration (Copy Constructor) + date_duration(const date_duration& other) : + days_(other.days_) + {} + + //! returns days_ as it's instantiated type - used for streaming + duration_rep get_rep()const + { + return days_; + } + bool is_special()const + { + return days_.is_special(); + } + //! returns days as value, not object. + duration_rep_type days() const + { + return duration_rep_traits::as_number(days_); + } + //! Returns the smallest duration -- used by to calculate 'end' + static date_duration unit() + { + return date_duration(1); + } + //! Equality + bool operator==(const date_duration& rhs) const + { + return days_ == rhs.days_; + } + //! Less + bool operator<(const date_duration& rhs) const + { + return days_ < rhs.days_; + } + + /* For shortcut operators (+=, -=, etc) simply using + * "days_ += days_" may not work. If instantiated with + * an int_adapter, shortcut operators are not present, + * so this will not compile */ + + //! Subtract another duration -- result is signed + date_duration operator-=(const date_duration& rhs) + { + //days_ -= rhs.days_; + days_ = days_ - rhs.days_; + return *this; + } + //! Add a duration -- result is signed + date_duration operator+=(const date_duration& rhs) + { + days_ = days_ + rhs.days_; + return *this; + } + + //! unary- Allows for dd = -date_duration(2); -> dd == -2 + date_duration operator-()const + { + return date_duration(get_rep() * (-1)); + } + //! Division operations on a duration with an integer. + date_duration operator/=(int divisor) + { + days_ = days_ / divisor; + return *this; + } + date_duration operator/(int divisor) + { + return date_duration(days_ / divisor); + } + + //! return sign information + bool is_negative() const + { + return days_ < 0; + } + private: + duration_rep days_; + }; + + + /*! Struct for instantiating date_duration with NO special values + * functionality. Allows for transparent implementation of either + * date_duration or date_duration > */ + struct duration_traits_long + { + typedef long int_type; + typedef long impl_type; + static int_type as_number(impl_type i) { return i; }; + }; + + /*! Struct for instantiating date_duration WITH special values + * functionality. Allows for transparent implementation of either + * date_duration or date_duration > */ + struct duration_traits_adapted + { + typedef long int_type; + typedef boost::date_time::int_adapter impl_type; + static int_type as_number(impl_type i) { return i.as_number(); }; + }; + + +} } //namspace date_time + + +#endif + diff --git a/win32/include/boost/date_time/date_duration_types.hpp b/win32/include/boost/date_time/date_duration_types.hpp new file mode 100755 index 000000000..1309b4838 --- /dev/null +++ b/win32/include/boost/date_time/date_duration_types.hpp @@ -0,0 +1,269 @@ +#ifndef DATE_DURATION_TYPES_HPP___ +#define DATE_DURATION_TYPES_HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or + * http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include +#include +#include + +namespace boost { +namespace date_time { + + + //! Additional duration type that represents a number of n*7 days + template + class weeks_duration : public date_duration { + public: + weeks_duration(typename duration_config::impl_type w) + : date_duration(w * 7) {} + weeks_duration(special_values sv) + : date_duration(sv) {} + }; + + // predeclare + template + class years_duration; + + //! additional duration type that represents a logical month + /*! A logical month enables things like: "date(2002,Mar,2) + months(2) -> + * 2002-May2". If the date is a last day-of-the-month, the result will + * also be a last-day-of-the-month. + */ + template + class months_duration + { + private: + typedef typename base_config::int_rep int_rep; + typedef typename int_rep::int_type int_type; + typedef typename base_config::date_type date_type; + typedef typename date_type::duration_type duration_type; + typedef typename base_config::month_adjustor_type month_adjustor_type; + typedef months_duration months_type; + typedef years_duration years_type; + public: + months_duration(int_rep num) : _m(num) {} + months_duration(special_values sv) : _m(sv) + { + _m = int_rep::from_special(sv); + } + int_rep number_of_months() const { return _m; } + //! returns a negative duration + duration_type get_neg_offset(const date_type& d) const + { + month_adjustor_type m_adj(_m.as_number()); + return duration_type(m_adj.get_neg_offset(d)); + } + duration_type get_offset(const date_type& d) const + { + month_adjustor_type m_adj(_m.as_number()); + return duration_type(m_adj.get_offset(d)); + } + bool operator==(const months_type& rhs) const + { + return(_m == rhs._m); + } + bool operator!=(const months_type& rhs) const + { + return(_m != rhs._m); + } + months_type operator+(const months_type& rhs)const + { + return months_type(_m + rhs._m); + } + months_type& operator+=(const months_type& rhs) + { + _m = _m + rhs._m; + return *this; + } + months_type operator-(const months_type& rhs)const + { + return months_type(_m - rhs._m); + } + months_type& operator-=(const months_type& rhs) + { + _m = _m - rhs._m; + return *this; + } + months_type operator*(const int_type rhs)const + { + return months_type(_m * rhs); + } + months_type& operator*=(const int_type rhs) + { + _m = _m * rhs; + return *this; + } + months_type operator/(const int_type rhs)const + { + return months_type(_m / rhs); + } + months_type& operator/=(const int_type rhs) + { + _m = _m / rhs; + return *this; + } + months_type operator+(const years_type& y)const + { + return months_type(y.number_of_years() * 12 + _m); + } + months_type& operator+=(const years_type& y) + { + _m = y.number_of_years() * 12 + _m; + return *this; + } + months_type operator-(const years_type& y) const + { + return months_type(_m - y.number_of_years() * 12); + } + months_type& operator-=(const years_type& y) + { + _m = _m - y.number_of_years() * 12; + return *this; + } + + // + friend date_type operator+(const date_type& d, const months_type& m) + { + return d + m.get_offset(d); + } + friend date_type operator+=(date_type& d, const months_type& m) + { + return d += m.get_offset(d); + } + friend date_type operator-(const date_type& d, const months_type& m) + { + // get_neg_offset returns a negative duration, so we add + return d + m.get_neg_offset(d); + } + friend date_type operator-=(date_type& d, const months_type& m) + { + // get_neg_offset returns a negative duration, so we add + return d += m.get_neg_offset(d); + } + + private: + int_rep _m; + }; + + //! additional duration type that represents a logical year + /*! A logical year enables things like: "date(2002,Mar,2) + years(2) -> + * 2004-Mar-2". If the date is a last day-of-the-month, the result will + * also be a last-day-of-the-month (ie date(2001-Feb-28) + years(3) -> + * 2004-Feb-29). + */ + template + class years_duration + { + private: + typedef typename base_config::int_rep int_rep; + typedef typename int_rep::int_type int_type; + typedef typename base_config::date_type date_type; + typedef typename date_type::duration_type duration_type; + typedef typename base_config::month_adjustor_type month_adjustor_type; + typedef years_duration years_type; + typedef months_duration months_type; + public: + years_duration(int_rep num) : _y(num) {} + years_duration(special_values sv) : _y(sv) + { + _y = int_rep::from_special(sv); + } + int_rep number_of_years() const { return _y; } + //! returns a negative duration + duration_type get_neg_offset(const date_type& d) const + { + month_adjustor_type m_adj(_y.as_number() * 12); + return duration_type(m_adj.get_neg_offset(d)); + } + duration_type get_offset(const date_type& d) const + { + month_adjustor_type m_adj(_y.as_number() * 12); + return duration_type(m_adj.get_offset(d)); + } + bool operator==(const years_type& rhs) const + { + return(_y == rhs._y); + } + bool operator!=(const years_type& rhs) const + { + return(_y != rhs._y); + } + years_type operator+(const years_type& rhs)const + { + return years_type(_y + rhs._y); + } + years_type& operator+=(const years_type& rhs) + { + _y = _y + rhs._y; + return *this; + } + years_type operator-(const years_type& rhs)const + { + return years_type(_y - rhs._y); + } + years_type& operator-=(const years_type& rhs) + { + _y = _y - rhs._y; + return *this; + } + years_type operator*(const int_type rhs)const + { + return years_type(_y * rhs); + } + years_type& operator*=(const int_type rhs) + { + _y = _y * rhs; + return *this; + } + years_type operator/(const int_type rhs)const + { + return years_type(_y / rhs); + } + years_type& operator/=(const int_type rhs) + { + _y = _y / rhs; + return *this; + } + months_type operator+(const months_type& m) const + { + return(months_type(_y * 12 + m.number_of_months())); + } + months_type operator-(const months_type& m) const + { + return(months_type(_y * 12 - m.number_of_months())); + } + + // + friend date_type operator+(const date_type& d, const years_type& y) + { + return d + y.get_offset(d); + } + friend date_type operator+=(date_type& d, const years_type& y) + { + return d += y.get_offset(d); + } + friend date_type operator-(const date_type& d, const years_type& y) + { + // get_neg_offset returns a negative duration, so we add + return d + y.get_neg_offset(d); + } + friend date_type operator-=(date_type& d, const years_type& y) + { + // get_neg_offset returns a negative duration, so we add + return d += y.get_neg_offset(d); + } + + private: + int_rep _y; + }; + +}} // namespace boost::date_time + +#endif // DATE_DURATION_TYPES_HPP___ diff --git a/win32/include/boost/date_time/date_facet.hpp b/win32/include/boost/date_time/date_facet.hpp new file mode 100755 index 000000000..06bda951f --- /dev/null +++ b/win32/include/boost/date_time/date_facet.hpp @@ -0,0 +1,775 @@ +#ifndef _DATE_TIME_DATE_FACET__HPP___ +#define _DATE_TIME_DATE_FACET__HPP___ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Martin Andrian, Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/algorithm/string/replace.hpp" +#include "boost/date_time/period.hpp" +#include "boost/date_time/special_values_formatter.hpp" +#include "boost/date_time/period_formatter.hpp" +#include "boost/date_time/period_parser.hpp" +#include "boost/date_time/date_generator_formatter.hpp" +#include "boost/date_time/date_generator_parser.hpp" +#include "boost/date_time/format_date_parser.hpp" +#include +#include + +namespace boost { namespace date_time { + + + /*! Class that provides format based I/O facet for date types. + * + * This class allows the formatting of dates by using format string. + * Format strings are: + * + * - %A => long_weekday_format - Full name Ex: Tuesday + * - %a => short_weekday_format - Three letter abbreviation Ex: Tue + * - %B => long_month_format - Full name Ex: October + * - %b => short_month_format - Three letter abbreviation Ex: Oct + * - %x => standard_format_specifier - defined by the locale + * - %Y-%b-%d => default_date_format - YYYY-Mon-dd + * + * Default month format == %b + * Default weekday format == %a + */ + template > > + class date_facet : public std::locale::facet { + public: + typedef typename date_type::duration_type duration_type; + // greg_weekday is gregorian_calendar::day_of_week_type + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::day_type day_type; + typedef typename date_type::month_type month_type; + typedef boost::date_time::period period_type; + typedef std::basic_string string_type; + typedef CharT char_type; + typedef boost::date_time::period_formatter period_formatter_type; + typedef boost::date_time::special_values_formatter special_values_formatter_type; + typedef std::vector > input_collection_type; + // used for the output of the date_generators + typedef date_generator_formatter date_gen_formatter_type; + typedef partial_date partial_date_type; + typedef nth_kday_of_month nth_kday_type; + typedef first_kday_of_month first_kday_type; + typedef last_kday_of_month last_kday_type; + typedef first_kday_after kday_after_type; + typedef first_kday_before kday_before_type; + static const char_type long_weekday_format[3]; + static const char_type short_weekday_format[3]; + static const char_type long_month_format[3]; + static const char_type short_month_format[3]; + static const char_type default_period_separator[4]; + static const char_type standard_format_specifier[3]; + static const char_type iso_format_specifier[7]; + static const char_type iso_format_extended_specifier[9]; + static const char_type default_date_format[9]; // YYYY-Mon-DD + static std::locale::id id; + +#if defined (__SUNPRO_CC) && defined (_RWSTD_VER) + std::locale::id& __get_id (void) const { return id; } +#endif + + explicit date_facet(::size_t a_ref = 0) + : std::locale::facet(a_ref), + //m_format(standard_format_specifier) + m_format(default_date_format), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format) + {} + + explicit date_facet(const char_type* format_str, + const input_collection_type& short_names, + ::size_t ref_count = 0) + : std::locale::facet(ref_count), + m_format(format_str), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format), + m_month_short_names(short_names) + {} + + + explicit date_facet(const char_type* format_str, + period_formatter_type per_formatter = period_formatter_type(), + special_values_formatter_type sv_formatter = special_values_formatter_type(), + date_gen_formatter_type dg_formatter = date_gen_formatter_type(), + ::size_t ref_count = 0) + : std::locale::facet(ref_count), + m_format(format_str), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format), + m_period_formatter(per_formatter), + m_date_gen_formatter(dg_formatter), + m_special_values_formatter(sv_formatter) + {} + void format(const char_type* const format_str) { + m_format = format_str; + } + virtual void set_iso_format() + { + m_format = iso_format_specifier; + } + virtual void set_iso_extended_format() + { + m_format = iso_format_extended_specifier; + } + void month_format(const char_type* const format_str) { + m_month_format = format_str; + } + void weekday_format(const char_type* const format_str) { + m_weekday_format = format_str; + } + + void period_formatter(period_formatter_type per_formatter) { + m_period_formatter= per_formatter; + } + void special_values_formatter(const special_values_formatter_type& svf) + { + m_special_values_formatter = svf; + } + void short_weekday_names(const input_collection_type& short_names) + { + m_weekday_short_names = short_names; + } + void long_weekday_names(const input_collection_type& long_names) + { + m_weekday_long_names = long_names; + } + + void short_month_names(const input_collection_type& short_names) + { + m_month_short_names = short_names; + } + + void long_month_names(const input_collection_type& long_names) + { + m_month_long_names = long_names; + } + + void date_gen_phrase_strings(const input_collection_type& new_strings, + typename date_gen_formatter_type::phrase_elements beg_pos=date_gen_formatter_type::first) + { + m_date_gen_formatter.elements(new_strings, beg_pos); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const date_type& d) const + { + if (d.is_special()) { + return do_put_special(next, a_ios, fill_char, d.as_special()); + } + //The following line of code required the date to support a to_tm function + return do_put_tm(next, a_ios, fill_char, to_tm(d), m_format); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const duration_type& dd) const + { + if (dd.is_special()) { + return do_put_special(next, a_ios, fill_char, dd.get_rep().as_special()); + } + + typedef std::num_put num_put; + if (std::has_facet(a_ios.getloc())) { + return std::use_facet(a_ios.getloc()).put(next, a_ios, fill_char, dd.get_rep().as_number()); + } + else { + num_put* f = new num_put(); + std::locale l = std::locale(a_ios.getloc(), f); + a_ios.imbue(l); + return f->put(next, a_ios, fill_char, dd.get_rep().as_number()); + } + + } + + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const month_type& m) const + { + //if (d.is_special()) { + // return do_put_special(next, a_ios, fill_char, d.as_special()); + //} + //The following line of code required the date to support a to_tm function + tm dtm; + init_tm(dtm); + dtm.tm_mon = m -1; + return do_put_tm(next, a_ios, fill_char, dtm, m_month_format); + } + + //! puts the day of month + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const day_type& day) const + { + tm dtm; + init_tm(dtm); + dtm.tm_mday = day.as_number(); + char_type tmp[3] = {'%','d'}; + string_type temp_format(tmp); + return do_put_tm(next, a_ios, fill_char, dtm, temp_format); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const day_of_week_type& dow) const + { + //if (d.is_special()) { + // return do_put_special(next, a_ios, fill_char, d.as_special()); + //} + //The following line of code required the date to support a to_tm function + tm dtm; + init_tm(dtm); + dtm.tm_wday = dow; + return do_put_tm(next, a_ios, fill_char, dtm, m_weekday_format); + } + + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const period_type& p) const + { + return m_period_formatter.put_period(next, a_ios, fill_char, p, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const partial_date_type& pd) const + { + return m_date_gen_formatter.put_partial_date(next, a_ios, fill_char, pd, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const nth_kday_type& nkd) const + { + return m_date_gen_formatter.put_nth_kday(next, a_ios, fill_char, nkd, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const first_kday_type& fkd) const + { + return m_date_gen_formatter.put_first_kday(next, a_ios, fill_char, fkd, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const last_kday_type& lkd) const + { + return m_date_gen_formatter.put_last_kday(next, a_ios, fill_char, lkd, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const kday_before_type& fkb) const + { + return m_date_gen_formatter.put_kday_before(next, a_ios, fill_char, fkb, *this); + } + + OutItrT put(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const kday_after_type& fka) const + { + return m_date_gen_formatter.put_kday_after(next, a_ios, fill_char, fka, *this); + } + + protected: + //! Helper function to initialize all fields in a tm struct + tm init_tm(tm& tm_value) const + { + tm_value.tm_sec = 0; /* seconds */ + tm_value.tm_min = 0; /* minutes */ + tm_value.tm_hour = 0; /* hours */ + tm_value.tm_mday = 0; /* day of the month */ + tm_value.tm_mon = 0; /* month */ + tm_value.tm_year = 0; /* year */ + tm_value.tm_wday = 0; /* day of the week */ + tm_value.tm_yday = 0; /* day in the year */ + tm_value.tm_isdst = 0; /* daylight saving time */ + return tm_value; + } + virtual OutItrT do_put_special(OutItrT next, + std::ios_base& /*a_ios*/, + char_type /*fill_char*/, + const boost::date_time::special_values sv) const + { + m_special_values_formatter.put_special(next, sv); + return next; + } + virtual OutItrT do_put_tm(OutItrT next, + std::ios_base& a_ios, + char_type fill_char, + const tm& tm_value, + string_type a_format) const + { + // update format string with custom names + if (m_weekday_long_names.size()) { + boost::algorithm::replace_all(a_format, + long_weekday_format, + m_weekday_long_names[tm_value.tm_wday]); + } + if (m_weekday_short_names.size()) { + boost::algorithm::replace_all(a_format, + short_weekday_format, + m_weekday_short_names[tm_value.tm_wday]); + + } + if (m_month_long_names.size()) { + boost::algorithm::replace_all(a_format, + long_month_format, + m_month_long_names[tm_value.tm_mon]); + } + if (m_month_short_names.size()) { + boost::algorithm::replace_all(a_format, + short_month_format, + m_month_short_names[tm_value.tm_mon]); + } + // use time_put facet to create final string + return std::use_facet >(a_ios.getloc()).put(next, a_ios, + fill_char, + &tm_value, + &*a_format.begin(), + &*a_format.begin()+a_format.size()); + } + protected: + string_type m_format; + string_type m_month_format; + string_type m_weekday_format; + period_formatter_type m_period_formatter; + date_gen_formatter_type m_date_gen_formatter; + special_values_formatter_type m_special_values_formatter; + input_collection_type m_month_short_names; + input_collection_type m_month_long_names; + input_collection_type m_weekday_short_names; + input_collection_type m_weekday_long_names; + private: + }; + + template + std::locale::id date_facet::id; + + template + const typename date_facet::char_type + date_facet::long_weekday_format[3] = {'%','A'}; + + template + const typename date_facet::char_type + date_facet::short_weekday_format[3] = {'%','a'}; + + template + const typename date_facet::char_type + date_facet::long_month_format[3] = {'%','B'}; + + template + const typename date_facet::char_type + date_facet::short_month_format[3] = {'%','b'}; + + template + const typename date_facet::char_type + date_facet::default_period_separator[4] = { ' ', '/', ' '}; + + template + const typename date_facet::char_type + date_facet::standard_format_specifier[3] = + {'%', 'x' }; + + template + const typename date_facet::char_type + date_facet::iso_format_specifier[7] = + {'%', 'Y', '%', 'm', '%', 'd' }; + + template + const typename date_facet::char_type + date_facet::iso_format_extended_specifier[9] = + {'%', 'Y', '-', '%', 'm', '-', '%', 'd' }; + + template + const typename date_facet::char_type + date_facet::default_date_format[9] = + {'%','Y','-','%','b','-','%','d'}; + + + + //! Input facet + template > > + class date_input_facet : public std::locale::facet { + public: + typedef typename date_type::duration_type duration_type; + // greg_weekday is gregorian_calendar::day_of_week_type + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::day_type day_type; + typedef typename date_type::month_type month_type; + typedef typename date_type::year_type year_type; + typedef boost::date_time::period period_type; + typedef std::basic_string string_type; + typedef CharT char_type; + typedef boost::date_time::period_parser period_parser_type; + typedef boost::date_time::special_values_parser special_values_parser_type; + typedef std::vector > input_collection_type; + typedef format_date_parser format_date_parser_type; + // date_generators stuff goes here + typedef date_generator_parser date_gen_parser_type; + typedef partial_date partial_date_type; + typedef nth_kday_of_month nth_kday_type; + typedef first_kday_of_month first_kday_type; + typedef last_kday_of_month last_kday_type; + typedef first_kday_after kday_after_type; + typedef first_kday_before kday_before_type; + + static const char_type long_weekday_format[3]; + static const char_type short_weekday_format[3]; + static const char_type long_month_format[3]; + static const char_type short_month_format[3]; + static const char_type four_digit_year_format[3]; + static const char_type two_digit_year_format[3]; + static const char_type default_period_separator[4]; + static const char_type standard_format_specifier[3]; + static const char_type iso_format_specifier[7]; + static const char_type iso_format_extended_specifier[9]; + static const char_type default_date_format[9]; // YYYY-Mon-DD + static std::locale::id id; + + explicit date_input_facet(::size_t a_ref = 0) + : std::locale::facet(a_ref), + m_format(default_date_format), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format), + m_year_format(four_digit_year_format), + m_parser(m_format, std::locale::classic()) + // default period_parser & special_values_parser used + {} + + explicit date_input_facet(const string_type& format_str, + ::size_t a_ref = 0) + : std::locale::facet(a_ref), + m_format(format_str), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format), + m_year_format(four_digit_year_format), + m_parser(m_format, std::locale::classic()) + // default period_parser & special_values_parser used + {} + + explicit date_input_facet(const string_type& format_str, + const format_date_parser_type& date_parser, + const special_values_parser_type& sv_parser, + const period_parser_type& per_parser, + const date_gen_parser_type& date_gen_parser, + ::size_t ref_count = 0) + : std::locale::facet(ref_count), + m_format(format_str), + m_month_format(short_month_format), + m_weekday_format(short_weekday_format), + m_year_format(four_digit_year_format), + m_parser(date_parser), + m_date_gen_parser(date_gen_parser), + m_period_parser(per_parser), + m_sv_parser(sv_parser) + {} + + + void format(const char_type* const format_str) { + m_format = format_str; + } + virtual void set_iso_format() + { + m_format = iso_format_specifier; + } + virtual void set_iso_extended_format() + { + m_format = iso_format_extended_specifier; + } + void month_format(const char_type* const format_str) { + m_month_format = format_str; + } + void weekday_format(const char_type* const format_str) { + m_weekday_format = format_str; + } + void year_format(const char_type* const format_str) { + m_year_format = format_str; + } + + void period_parser(period_parser_type per_parser) { + m_period_parser = per_parser; + } + void short_weekday_names(const input_collection_type& weekday_names) + { + m_parser.short_weekday_names(weekday_names); + } + void long_weekday_names(const input_collection_type& weekday_names) + { + m_parser.long_weekday_names(weekday_names); + } + + void short_month_names(const input_collection_type& month_names) + { + m_parser.short_month_names(month_names); + } + + void long_month_names(const input_collection_type& month_names) + { + m_parser.long_month_names(month_names); + } + + void date_gen_element_strings(const input_collection_type& col) + { + m_date_gen_parser.element_strings(col); + } + void date_gen_element_strings(const string_type& first, + const string_type& second, + const string_type& third, + const string_type& fourth, + const string_type& fifth, + const string_type& last, + const string_type& before, + const string_type& after, + const string_type& of) + + { + m_date_gen_parser.element_strings(first,second,third,fourth,fifth,last,before,after,of); + } + + void special_values_parser(special_values_parser_type sv_parser) + { + m_sv_parser = sv_parser; + } + + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& /*a_ios*/, + date_type& d) const + { + d = m_parser.parse_date(from, to, m_format, m_sv_parser); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& /*a_ios*/, + month_type& m) const + { + m = m_parser.parse_month(from, to, m_month_format); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& /*a_ios*/, + day_of_week_type& wd) const + { + wd = m_parser.parse_weekday(from, to, m_weekday_format); + return from; + } + //! Expects 1 or 2 digit day range: 1-31 + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& /*a_ios*/, + day_type& d) const + { + d = m_parser.parse_var_day_of_month(from, to); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& /*a_ios*/, + year_type& y) const + { + y = m_parser.parse_year(from, to, m_year_format); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + duration_type& dd) const + { + // skip leading whitespace + while(std::isspace(*from) && from != to) { ++from; } + + /* num_get.get() will always consume the first character if it + * is a sign indicator (+/-). Special value strings may begin + * with one of these signs so we'll need a copy of it + * in case num_get.get() fails. */ + char_type c = '\0'; + // TODO Are these characters somewhere in the locale? + if(*from == '-' || *from == '+') { + c = *from; + } + typedef std::num_get num_get; + typename duration_type::duration_rep_type val = 0; + std::ios_base::iostate err = std::ios_base::goodbit; + + if (std::has_facet(a_ios.getloc())) { + from = std::use_facet(a_ios.getloc()).get(from, to, a_ios, err, val); + } + else { + num_get* ng = new num_get(); + std::locale l = std::locale(a_ios.getloc(), ng); + a_ios.imbue(l); + from = ng->get(from, to, a_ios, err, val); + } + if(err & std::ios_base::failbit){ + typedef typename special_values_parser_type::match_results match_results; + match_results mr; + if(c == '-' || c == '+') { // was the first character consumed? + mr.cache += c; + } + m_sv_parser.match(from, to, mr); + if(mr.current_match == match_results::PARSE_ERROR) { + throw std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'"); + } + dd = duration_type(static_cast(mr.current_match)); + } + else { + dd = duration_type(val); + } + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + period_type& p) const + { + p = m_period_parser.get_period(from, to, a_ios, p, duration_type::unit(), *this); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + nth_kday_type& nkd) const + { + nkd = m_date_gen_parser.get_nth_kday_type(from, to, a_ios, *this); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + partial_date_type& pd) const + { + + pd = m_date_gen_parser.get_partial_date_type(from, to, a_ios, *this); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + first_kday_type& fkd) const + { + fkd = m_date_gen_parser.get_first_kday_type(from, to, a_ios, *this); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + last_kday_type& lkd) const + { + lkd = m_date_gen_parser.get_last_kday_type(from, to, a_ios, *this); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + kday_before_type& fkb) const + { + fkb = m_date_gen_parser.get_kday_before_type(from, to, a_ios, *this); + return from; + } + InItrT get(InItrT& from, + InItrT& to, + std::ios_base& a_ios, + kday_after_type& fka) const + { + fka = m_date_gen_parser.get_kday_after_type(from, to, a_ios, *this); + return from; + } + + protected: + string_type m_format; + string_type m_month_format; + string_type m_weekday_format; + string_type m_year_format; + format_date_parser_type m_parser; + date_gen_parser_type m_date_gen_parser; + period_parser_type m_period_parser; + special_values_parser_type m_sv_parser; + private: + }; + + + template + std::locale::id date_input_facet::id; + + template + const typename date_input_facet::char_type + date_input_facet::long_weekday_format[3] = {'%','A'}; + + template + const typename date_input_facet::char_type + date_input_facet::short_weekday_format[3] = {'%','a'}; + + template + const typename date_input_facet::char_type + date_input_facet::long_month_format[3] = {'%','B'}; + + template + const typename date_input_facet::char_type + date_input_facet::short_month_format[3] = {'%','b'}; + + template + const typename date_input_facet::char_type + date_input_facet::four_digit_year_format[3] = {'%','Y'}; + + template + const typename date_input_facet::char_type + date_input_facet::two_digit_year_format[3] = {'%','y'}; + + template + const typename date_input_facet::char_type + date_input_facet::default_period_separator[4] = { ' ', '/', ' '}; + + template + const typename date_input_facet::char_type + date_input_facet::standard_format_specifier[3] = + {'%', 'x' }; + + template + const typename date_input_facet::char_type + date_input_facet::iso_format_specifier[7] = + {'%', 'Y', '%', 'm', '%', 'd' }; + + template + const typename date_input_facet::char_type + date_input_facet::iso_format_extended_specifier[9] = + {'%', 'Y', '-', '%', 'm', '-', '%', 'd' }; + + template + const typename date_input_facet::char_type + date_input_facet::default_date_format[9] = + {'%','Y','-','%','b','-','%','d'}; + +} } // namespaces + + +#endif diff --git a/win32/include/boost/date_time/date_format_simple.hpp b/win32/include/boost/date_time/date_format_simple.hpp new file mode 100755 index 000000000..d1fa8f1cd --- /dev/null +++ b/win32/include/boost/date_time/date_format_simple.hpp @@ -0,0 +1,159 @@ +#ifndef DATE_TIME_SIMPLE_FORMAT_HPP___ +#define DATE_TIME_SIMPLE_FORMAT_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/parse_format_base.hpp" + +namespace boost { +namespace date_time { + +//! Class to provide simple basic formatting rules +template +class simple_format { +public: + + //! String used printed is date is invalid + static const charT* not_a_date() + { + return "not-a-date-time"; + } + //! String used to for positive infinity value + static const charT* pos_infinity() + { + return "+infinity"; + } + //! String used to for positive infinity value + static const charT* neg_infinity() + { + return "-infinity"; + } + //! Describe month format + static month_format_spec month_format() + { + return month_as_short_string; + } + static ymd_order_spec date_order() + { + return ymd_order_iso; //YYYY-MM-DD + } + //! This format uses '-' to separate date elements + static bool has_date_sep_chars() + { + return true; + } + //! Char to sep? + static charT year_sep_char() + { + return '-'; + } + //! char between year-month + static charT month_sep_char() + { + return '-'; + } + //! Char to separate month-day + static charT day_sep_char() + { + return '-'; + } + //! char between date-hours + static charT hour_sep_char() + { + return ' '; + } + //! char between hour and minute + static charT minute_sep_char() + { + return ':'; + } + //! char for second + static charT second_sep_char() + { + return ':'; + } + +}; + +#ifndef BOOST_NO_STD_WSTRING + +//! Specialization of formmating rules for wchar_t +template<> +class simple_format { +public: + + //! String used printed is date is invalid + static const wchar_t* not_a_date() + { + return L"not-a-date-time"; + } + //! String used to for positive infinity value + static const wchar_t* pos_infinity() + { + return L"+infinity"; + } + //! String used to for positive infinity value + static const wchar_t* neg_infinity() + { + return L"-infinity"; + } + //! Describe month format + static month_format_spec month_format() + { + return month_as_short_string; + } + static ymd_order_spec date_order() + { + return ymd_order_iso; //YYYY-MM-DD + } + //! This format uses '-' to separate date elements + static bool has_date_sep_chars() + { + return true; + } + //! Char to sep? + static wchar_t year_sep_char() + { + return '-'; + } + //! char between year-month + static wchar_t month_sep_char() + { + return '-'; + } + //! Char to separate month-day + static wchar_t day_sep_char() + { + return '-'; + } + //! char between date-hours + static wchar_t hour_sep_char() + { + return ' '; + } + //! char between hour and minute + static wchar_t minute_sep_char() + { + return ':'; + } + //! char for second + static wchar_t second_sep_char() + { + return ':'; + } + +}; + +#endif // BOOST_NO_STD_WSTRING +} } //namespace date_time + + + + +#endif diff --git a/win32/include/boost/date_time/date_formatting.hpp b/win32/include/boost/date_time/date_formatting.hpp new file mode 100755 index 000000000..65ab39f95 --- /dev/null +++ b/win32/include/boost/date_time/date_formatting.hpp @@ -0,0 +1,127 @@ +#ifndef DATE_TIME_DATE_FORMATTING_HPP___ +#define DATE_TIME_DATE_FORMATTING_HPP___ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/iso_format.hpp" +#include "boost/date_time/compiler_config.hpp" +#include +#include +#include + +/* NOTE: "formatter" code for older compilers, ones that define + * BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS, is located in + * date_formatting_limited.hpp + */ + +namespace boost { +namespace date_time { + + //! Formats a month as as string into an ostream + template + class month_formatter + { + typedef std::basic_ostream ostream_type; + public: + //! Formats a month as as string into an ostream + /*! This function demands that month_type provide + * functions for converting to short and long strings + * if that capability is used. + */ + static ostream_type& format_month(const month_type& month, + ostream_type &os) + { + switch (format_type::month_format()) + { + case month_as_short_string: + { + os << month.as_short_string(); + break; + } + case month_as_long_string: + { + os << month.as_long_string(); + break; + } + case month_as_integer: + { + os << std::setw(2) << std::setfill(os.widen('0')) << month.as_number(); + break; + } + + } + return os; + } // format_month + }; + + + //! Convert ymd to a standard string formatting policies + template + class ymd_formatter + { + public: + //! Convert ymd to a standard string formatting policies + /*! This is standard code for handling date formatting with + * year-month-day based date information. This function + * uses the format_type to control whether the string will + * contain separator characters, and if so what the character + * will be. In addtion, it can format the month as either + * an integer or a string as controled by the formatting + * policy + */ + static std::basic_string ymd_to_string(ymd_type ymd) + { + typedef typename ymd_type::month_type month_type; + std::basic_ostringstream ss; + ss << ymd.year; + if (format_type::has_date_sep_chars()) { + ss << format_type::month_sep_char(); + } + //this name is a bit ugly, oh well.... + month_formatter::format_month(ymd.month, ss); + if (format_type::has_date_sep_chars()) { + ss << format_type::day_sep_char(); + } + ss << std::setw(2) << std::setfill(ss.widen('0')) + << ymd.day; + return ss.str(); + } + }; + + + //! Convert a date to string using format policies + template + class date_formatter + { + public: + typedef std::basic_string string_type; + //! Convert to a date to standard string using format policies + static string_type date_to_string(date_type d) + { + typedef typename date_type::ymd_type ymd_type; + if (d.is_not_a_date()) { + return string_type(format_type::not_a_date()); + } + if (d.is_neg_infinity()) { + return string_type(format_type::neg_infinity()); + } + if (d.is_pos_infinity()) { + return string_type(format_type::pos_infinity()); + } + ymd_type ymd = d.year_month_day(); + return ymd_formatter::ymd_to_string(ymd); + } + }; + + +} } //namespace date_time + + +#endif + diff --git a/win32/include/boost/date_time/date_formatting_limited.hpp b/win32/include/boost/date_time/date_formatting_limited.hpp new file mode 100755 index 000000000..91a2f042c --- /dev/null +++ b/win32/include/boost/date_time/date_formatting_limited.hpp @@ -0,0 +1,121 @@ +#ifndef DATE_TIME_DATE_FORMATTING_LIMITED_HPP___ +#define DATE_TIME_DATE_FORMATTING_LIMITED_HPP___ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/iso_format.hpp" +#include "boost/date_time/compiler_config.hpp" +#include +#include +#include + + +namespace boost { +namespace date_time { + + //! Formats a month as as string into an ostream + template + class month_formatter + { + public: + //! Formats a month as as string into an ostream + /*! This function demands that month_type provide + * functions for converting to short and long strings + * if that capability is used. + */ + static std::ostream& format_month(const month_type& month, + std::ostream& os) + { + switch (format_type::month_format()) + { + case month_as_short_string: + { + os << month.as_short_string(); + break; + } + case month_as_long_string: + { + os << month.as_long_string(); + break; + } + case month_as_integer: + { + os << std::setw(2) << std::setfill('0') << month.as_number(); + break; + } + + } + return os; + } // format_month + }; + + + //! Convert ymd to a standard string formatting policies + template + class ymd_formatter + { + public: + //! Convert ymd to a standard string formatting policies + /*! This is standard code for handling date formatting with + * year-month-day based date information. This function + * uses the format_type to control whether the string will + * contain separator characters, and if so what the character + * will be. In addtion, it can format the month as either + * an integer or a string as controled by the formatting + * policy + */ + static std::string ymd_to_string(ymd_type ymd) + { + typedef typename ymd_type::month_type month_type; + std::ostringstream ss; + ss << ymd.year; + if (format_type::has_date_sep_chars()) { + ss << format_type::month_sep_char(); + } + //this name is a bit ugly, oh well.... + month_formatter::format_month(ymd.month, ss); + if (format_type::has_date_sep_chars()) { + ss << format_type::day_sep_char(); + } + ss << std::setw(2) << std::setfill('0') + << ymd.day; + return ss.str(); + } + }; + + + //! Convert a date to string using format policies + template + class date_formatter + { + public: + //! Convert to a date to standard string using format policies + static std::string date_to_string(date_type d) + { + typedef typename date_type::ymd_type ymd_type; + if (d.is_not_a_date()) { + return format_type::not_a_date(); + } + if (d.is_neg_infinity()) { + return format_type::neg_infinity(); + } + if (d.is_pos_infinity()) { + return format_type::pos_infinity(); + } + ymd_type ymd = d.year_month_day(); + return ymd_formatter::ymd_to_string(ymd); + } + }; + + +} } //namespace date_time + + +#endif + diff --git a/win32/include/boost/date_time/date_formatting_locales.hpp b/win32/include/boost/date_time/date_formatting_locales.hpp new file mode 100755 index 000000000..84bd25573 --- /dev/null +++ b/win32/include/boost/date_time/date_formatting_locales.hpp @@ -0,0 +1,233 @@ +#ifndef DATE_TIME_DATE_FORMATTING_LOCALES_HPP___ +#define DATE_TIME_DATE_FORMATTING_LOCALES_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/locale_config.hpp" // set BOOST_DATE_TIME_NO_LOCALE + +#ifndef BOOST_DATE_TIME_NO_LOCALE + +#include "boost/date_time/iso_format.hpp" +#include "boost/date_time/date_names_put.hpp" +#include "boost/date_time/parse_format_base.hpp" +//#include +#include +#include + + +namespace boost { +namespace date_time { + + //! Formats a month as as string into an ostream + template + class ostream_month_formatter + { + public: + typedef typename facet_type::month_type month_type; + typedef std::basic_ostream ostream_type; + + //! Formats a month as as string into an output iterator + static void format_month(const month_type& month, + ostream_type& os, + const facet_type& f) + { + + switch (f.month_format()) + { + case month_as_short_string: + { + std::ostreambuf_iterator oitr(os); + f.put_month_short(oitr, month.as_enum()); + break; + } + case month_as_long_string: + { + std::ostreambuf_iterator oitr(os); + f.put_month_long(oitr, month.as_enum()); + break; + } + case month_as_integer: + { + charT fill_char = '0'; + os << std::setw(2) << std::setfill(fill_char) << month.as_number(); + break; + } + + } + } // format_month + + }; + + + //! Formats a weekday + template + class ostream_weekday_formatter + { + public: + typedef typename facet_type::month_type month_type; + typedef std::basic_ostream ostream_type; + + //! Formats a month as as string into an output iterator + static void format_weekday(const weekday_type& wd, + ostream_type& os, + const facet_type& f, + bool as_long_string) + { + + std::ostreambuf_iterator oitr(os); + if (as_long_string) { + f.put_weekday_long(oitr, wd.as_enum()); + } + else { + f.put_weekday_short(oitr, wd.as_enum()); + } + + } // format_weekday + + }; + + + //! Convert ymd to a standard string formatting policies + template + class ostream_ymd_formatter + { + public: + typedef typename ymd_type::month_type month_type; + typedef ostream_month_formatter month_formatter_type; + typedef std::basic_ostream ostream_type; + typedef std::basic_string foo_type; + + //! Convert ymd to a standard string formatting policies + /*! This is standard code for handling date formatting with + * year-month-day based date information. This function + * uses the format_type to control whether the string will + * contain separator characters, and if so what the character + * will be. In addtion, it can format the month as either + * an integer or a string as controled by the formatting + * policy + */ + // static string_type ymd_to_string(ymd_type ymd) +// { +// std::ostringstream ss; +// facet_type dnp; +// ymd_put(ymd, ss, dnp); +// return ss.str(); +// } + + + // Put ymd to ostream -- part of ostream refactor + static void ymd_put(ymd_type ymd, + ostream_type& os, + const facet_type& f) + { + std::ostreambuf_iterator oitr(os); + charT fill_char = '0'; + switch (f.date_order()) { + case ymd_order_iso: { + os << ymd.year; + if (f.has_date_sep_chars()) { + f.month_sep_char(oitr); + } + month_formatter_type::format_month(ymd.month, os, f); + if (f.has_date_sep_chars()) { + f.day_sep_char(oitr); + } + os << std::setw(2) << std::setfill(fill_char) + << ymd.day; + break; + } + case ymd_order_us: { + month_formatter_type::format_month(ymd.month, os, f); + if (f.has_date_sep_chars()) { + f.day_sep_char(oitr); + } + os << std::setw(2) << std::setfill(fill_char) + << ymd.day; + if (f.has_date_sep_chars()) { + f.month_sep_char(oitr); + } + os << ymd.year; + break; + } + case ymd_order_dmy: { + os << std::setw(2) << std::setfill(fill_char) + << ymd.day; + if (f.has_date_sep_chars()) { + f.day_sep_char(oitr); + } + month_formatter_type::format_month(ymd.month, os, f); + if (f.has_date_sep_chars()) { + f.month_sep_char(oitr); + } + os << ymd.year; + break; + } + } + } + }; + + + //! Convert a date to string using format policies + template + class ostream_date_formatter + { + public: + typedef std::basic_ostream ostream_type; + typedef typename date_type::ymd_type ymd_type; + + //! Put date into an ostream + static void date_put(const date_type& d, + ostream_type& os, + const facet_type& f) + { + special_values sv = d.as_special(); + if (sv == not_special) { + ymd_type ymd = d.year_month_day(); + ostream_ymd_formatter::ymd_put(ymd, os, f); + } + else { // output a special value + std::ostreambuf_iterator coi(os); + f.put_special_value(coi, sv); + } + } + + + //! Put date into an ostream + static void date_put(const date_type& d, + ostream_type& os) + { + //retrieve the local from the ostream + std::locale locale = os.getloc(); + if (std::has_facet(locale)) { + const facet_type& f = std::use_facet(locale); + date_put(d, os, f); + } + else { + //default to something sensible if no facet installed + facet_type default_facet; + date_put(d, os, default_facet); + } + } // date_to_ostream + }; //class date_formatter + + +} } //namespace date_time + +#endif + +#endif + diff --git a/win32/include/boost/date_time/date_generator_formatter.hpp b/win32/include/boost/date_time/date_generator_formatter.hpp new file mode 100755 index 000000000..b4f9e7e3c --- /dev/null +++ b/win32/include/boost/date_time/date_generator_formatter.hpp @@ -0,0 +1,263 @@ +#ifndef _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ +#define _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include +#include +#include +#include +#include "boost/date_time/date_generators.hpp" + +namespace boost { +namespace date_time { + + //! Formats date_generators for output + /*! Formatting of date_generators follows specific orders for the + * various types of date_generators. + * - partial_date => "dd Month" + * - nth_day_of_the_week_in_month => "nth weekday of month" + * - first_day_of_the_week_in_month => "first weekday of month" + * - last_day_of_the_week_in_month => "last weekday of month" + * - first_day_of_the_week_after => "weekday after" + * - first_day_of_the_week_before => "weekday before" + * While the order of the elements in these phrases cannot be changed, + * the elements themselves can be. Weekday and Month get their formats + * and names from the date_facet. The remaining elements are stored in + * the date_generator_formatter and can be customized upon construction + * or via a member function. The default elements are those shown in the + * examples above. + */ + template > > + class date_generator_formatter { + public: + typedef partial_date partial_date_type; + typedef nth_kday_of_month nth_kday_type; + typedef first_kday_of_month first_kday_type; + typedef last_kday_of_month last_kday_type; + typedef first_kday_after kday_after_type; + typedef first_kday_before kday_before_type; + + typedef CharT char_type; + typedef std::basic_string string_type; + typedef std::vector collection_type; + static const char_type first_string[6]; + static const char_type second_string[7]; + static const char_type third_string[6]; + static const char_type fourth_string[7]; + static const char_type fifth_string[6]; + static const char_type last_string[5]; + static const char_type before_string[8]; + static const char_type after_string[6]; + static const char_type of_string[3]; + + enum phrase_elements {first=0, second, third, fourth, fifth, last, + before, after, of, number_of_phrase_elements}; + + //! Default format elements used + date_generator_formatter() + { + phrase_strings.push_back(string_type(first_string)); + phrase_strings.push_back(string_type(second_string)); + phrase_strings.push_back(string_type(third_string)); + phrase_strings.push_back(string_type(fourth_string)); + phrase_strings.push_back(string_type(fifth_string)); + phrase_strings.push_back(string_type(last_string)); + phrase_strings.push_back(string_type(before_string)); + phrase_strings.push_back(string_type(after_string)); + phrase_strings.push_back(string_type(of_string)); + } + + //! Constructor that allows for a custom set of phrase elements + date_generator_formatter(const string_type& first, + const string_type& second, + const string_type& third, + const string_type& fourth, + const string_type& fifth, + const string_type& last, + const string_type& before, + const string_type& after, + const string_type& of) + { + phrase_strings.push_back(string_type(first_string)); + phrase_strings.push_back(string_type(second_string)); + phrase_strings.push_back(string_type(third_string)); + phrase_strings.push_back(string_type(fourth_string)); + phrase_strings.push_back(string_type(fifth_string)); + phrase_strings.push_back(string_type(last_string)); + phrase_strings.push_back(string_type(before_string)); + phrase_strings.push_back(string_type(after_string)); + phrase_strings.push_back(string_type(of_string)); + } + + //! Replace the set of phrase elements with those contained in new_strings + /*! The order of the strings in the given collection is important. + * They must follow: + * - first, second, third, fourth, fifth, last, before, after, of. + * + * It is not necessary to send in a complete set if only a few + * elements are to be replaced as long as the correct beg_pos is used. + * + * Ex: To keep the default first through fifth elements, but replace + * the rest with a collection of: + * - "final", "prior", "following", "in". + * The beg_pos of date_generator_formatter::last would be used. + */ + void elements(const collection_type& new_strings, + phrase_elements beg_pos=first) + { + if(beg_pos < number_of_phrase_elements) { + typename collection_type::iterator itr = phrase_strings.begin(); + itr += beg_pos; + std::copy(new_strings.begin(), new_strings.end(), + itr); + //phrase_strings.begin()); + } + } + + //!Put a partial_date => "dd Month" + template + OutItrT put_partial_date(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const partial_date_type& pd, + const facet_type& facet) const + { + facet.put(next, a_ios, a_fill, pd.day()); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, pd.month()); + return next; + } + + //! Put an nth_day_of_the_week_in_month => "nth weekday of month" + template + OutItrT put_nth_kday(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const nth_kday_type& nkd, + const facet_type& facet) const + { + put_string(next, phrase_strings[nkd.nth_week() -1]); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, nkd.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, string_type(of_string)); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, nkd.month()); + return next; + } + + //! Put a first_day_of_the_week_in_month => "first weekday of month" + template + OutItrT put_first_kday(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const first_kday_type& fkd, + const facet_type& facet) const + { + put_string(next, phrase_strings[first]); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, fkd.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, string_type(of_string)); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, fkd.month()); + return next; + } + + //! Put a last_day_of_the_week_in_month => "last weekday of month" + template + OutItrT put_last_kday(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const last_kday_type& lkd, + const facet_type& facet) const + { + put_string(next, phrase_strings[last]); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, lkd.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, string_type(of_string)); + next = a_fill; //TODO change this ??? + facet.put(next, a_ios, a_fill, lkd.month()); + return next; + } + + //! Put a first_day_of_the_week_before => "weekday before" + template + OutItrT put_kday_before(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const kday_before_type& fkb, + const facet_type& facet) const + { + facet.put(next, a_ios, a_fill, fkb.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, phrase_strings[before]); + return next; + } + + //! Put a first_day_of_the_week_after => "weekday after" + template + OutItrT put_kday_after(OutItrT next, std::ios_base& a_ios, + CharT a_fill, const kday_after_type& fka, + const facet_type& facet) const + { + facet.put(next, a_ios, a_fill, fka.day_of_week()); + next = a_fill; //TODO change this ??? + put_string(next, phrase_strings[after]); + return next; + } + + + private: + collection_type phrase_strings; + + //! helper function to put the various member string into stream + OutItrT put_string(OutItrT next, const string_type& str) const + { + typename string_type::const_iterator itr = str.begin(); + while(itr != str.end()) { + *next = *itr; + ++itr; + ++next; + } + return next; + } + }; + + template + const typename date_generator_formatter::char_type + date_generator_formatter::first_string[6] = + {'f','i','r','s','t'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::second_string[7] = + {'s','e','c','o','n','d'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::third_string[6] = + {'t','h','i','r','d'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::fourth_string[7] = + {'f','o','u','r','t','h'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::fifth_string[6] = + {'f','i','f','t','h'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::last_string[5] = + {'l','a','s','t'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::before_string[8] = + {'b','e','f','o','r','e'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::after_string[6] = + {'a','f','t','e','r'}; + template + const typename date_generator_formatter::char_type + date_generator_formatter::of_string[3] = + {'o','f'}; +} } // namespaces + +#endif // _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ diff --git a/win32/include/boost/date_time/date_generator_parser.hpp b/win32/include/boost/date_time/date_generator_parser.hpp new file mode 100755 index 000000000..fc198db7b --- /dev/null +++ b/win32/include/boost/date_time/date_generator_parser.hpp @@ -0,0 +1,329 @@ + +#ifndef DATE_TIME_DATE_GENERATOR_PARSER_HPP__ +#define DATE_TIME_DATE_GENERATOR_PARSER_HPP__ + +/* Copyright (c) 2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/string_parse_tree.hpp" +#include "boost/date_time/date_generators.hpp" +#include "boost/date_time/format_date_parser.hpp" +#include +#include + +namespace boost { namespace date_time { + + //! Class for date_generator parsing + /*! The elements of a date_generator "phrase" are parsed from the input stream in a + * particular order. All elements are required and the order in which they appear + * cannot change, however, the elements themselves can be changed. The default + * elements and their order are as follows: + * + * - partial_date => "dd Month" + * - nth_day_of_the_week_in_month => "nth weekday of month" + * - first_day_of_the_week_in_month => "first weekday of month" + * - last_day_of_the_week_in_month => "last weekday of month" + * - first_day_of_the_week_after => "weekday after" + * - first_day_of_the_week_before => "weekday before" + * + * Weekday and Month names and formats are handled via the date_input_facet. + * + */ + template + class date_generator_parser + { + public: + typedef std::basic_string string_type; + typedef std::istreambuf_iterator stream_itr_type; + + typedef typename date_type::month_type month_type; + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::day_type day_type; + + typedef string_parse_tree parse_tree_type; + typedef typename parse_tree_type::parse_match_result_type match_results; + typedef std::vector > collection_type; + + typedef partial_date partial_date_type; + typedef nth_kday_of_month nth_kday_type; + typedef first_kday_of_month first_kday_type; + typedef last_kday_of_month last_kday_type; + typedef first_kday_after kday_after_type; + typedef first_kday_before kday_before_type; + + typedef charT char_type; + static const char_type first_string[6]; + static const char_type second_string[7]; + static const char_type third_string[6]; + static const char_type fourth_string[7]; + static const char_type fifth_string[6]; + static const char_type last_string[5]; + static const char_type before_string[8]; + static const char_type after_string[6]; + static const char_type of_string[3]; + + enum phrase_elements {first=0, second, third, fourth, fifth, last, + before, after, of, number_of_phrase_elements}; + + //! Creates a date_generator_parser with the default set of "element_strings" + date_generator_parser() + { + element_strings(string_type(first_string), + string_type(second_string), + string_type(third_string), + string_type(fourth_string), + string_type(fifth_string), + string_type(last_string), + string_type(before_string), + string_type(after_string), + string_type(of_string)); + } + + //! Creates a date_generator_parser using a user defined set of element strings + date_generator_parser(const string_type& first_str, + const string_type& second_str, + const string_type& third_str, + const string_type& fourth_str, + const string_type& fifth_str, + const string_type& last_str, + const string_type& before_str, + const string_type& after_str, + const string_type& of_str) + { + element_strings(first_str, second_str, third_str, fourth_str, fifth_str, + last_str, before_str, after_str, of_str); + } + + //! Replace strings that determine nth week for generator + void element_strings(const string_type& first_str, + const string_type& second_str, + const string_type& third_str, + const string_type& fourth_str, + const string_type& fifth_str, + const string_type& last_str, + const string_type& before_str, + const string_type& after_str, + const string_type& of_str) + { + collection_type phrases; + phrases.push_back(first_str); + phrases.push_back(second_str); + phrases.push_back(third_str); + phrases.push_back(fourth_str); + phrases.push_back(fifth_str); + phrases.push_back(last_str); + phrases.push_back(before_str); + phrases.push_back(after_str); + phrases.push_back(of_str); + m_element_strings = parse_tree_type(phrases, this->first); // enum first + } + + void element_strings(const collection_type& col) + { + m_element_strings = parse_tree_type(col, this->first); // enum first + } + + + //! returns partial_date parsed from stream + template + partial_date_type + get_partial_date_type(stream_itr_type& sitr, + stream_itr_type& stream_end, + std::ios_base& a_ios, + const facet_type& facet) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + day_type d(1); + month_type m(1); + facet.get(sitr, stream_end, a_ios, d); + facet.get(sitr, stream_end, a_ios, m); + + return partial_date_type(d,m); + } + + //! returns nth_kday_of_week parsed from stream + template + nth_kday_type + get_nth_kday_type(stream_itr_type& sitr, + stream_itr_type& stream_end, + std::ios_base& a_ios, + const facet_type& facet) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + typename nth_kday_type::week_num wn; + day_of_week_type wd(0); // no default constructor + month_type m(1); // no default constructor + + match_results mr = m_element_strings.match(sitr, stream_end); + switch(mr.current_match) { + case first : { wn = nth_kday_type::first; break; } + case second : { wn = nth_kday_type::second; break; } + case third : { wn = nth_kday_type::third; break; } + case fourth : { wn = nth_kday_type::fourth; break; } + case fifth : { wn = nth_kday_type::fifth; break; } + default: + { + throw std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'"); + break; + } + } // week num + facet.get(sitr, stream_end, a_ios, wd); // day_of_week + extract_element(sitr, stream_end, of); // "of" element + facet.get(sitr, stream_end, a_ios, m); // month + + return nth_kday_type(wn, wd, m); + } + + //! returns first_kday_of_week parsed from stream + template + first_kday_type + get_first_kday_type(stream_itr_type& sitr, + stream_itr_type& stream_end, + std::ios_base& a_ios, + const facet_type& facet) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + day_of_week_type wd(0); // no default constructor + month_type m(1); // no default constructor + + extract_element(sitr, stream_end, first); // "first" element + facet.get(sitr, stream_end, a_ios, wd); // day_of_week + extract_element(sitr, stream_end, of); // "of" element + facet.get(sitr, stream_end, a_ios, m); // month + + + return first_kday_type(wd, m); + } + + //! returns last_kday_of_week parsed from stream + template + last_kday_type + get_last_kday_type(stream_itr_type& sitr, + stream_itr_type& stream_end, + std::ios_base& a_ios, + const facet_type& facet) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + day_of_week_type wd(0); // no default constructor + month_type m(1); // no default constructor + + extract_element(sitr, stream_end, last); // "last" element + facet.get(sitr, stream_end, a_ios, wd); // day_of_week + extract_element(sitr, stream_end, of); // "of" element + facet.get(sitr, stream_end, a_ios, m); // month + + + return last_kday_type(wd, m); + } + + //! returns first_kday_of_week parsed from stream + template + kday_before_type + get_kday_before_type(stream_itr_type& sitr, + stream_itr_type& stream_end, + std::ios_base& a_ios, + const facet_type& facet) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + day_of_week_type wd(0); // no default constructor + + facet.get(sitr, stream_end, a_ios, wd); // day_of_week + extract_element(sitr, stream_end, before);// "before" element + + return kday_before_type(wd); + } + + //! returns first_kday_of_week parsed from stream + template + kday_after_type + get_kday_after_type(stream_itr_type& sitr, + stream_itr_type& stream_end, + std::ios_base& a_ios, + const facet_type& facet) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + day_of_week_type wd(0); // no default constructor + + facet.get(sitr, stream_end, a_ios, wd); // day_of_week + extract_element(sitr, stream_end, after); // "after" element + + return kday_after_type(wd); + } + + private: + parse_tree_type m_element_strings; + + //! Extracts phrase element from input. Throws ios_base::failure on error. + void extract_element(stream_itr_type& sitr, + stream_itr_type& stream_end, + typename date_generator_parser::phrase_elements ele) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + match_results mr = m_element_strings.match(sitr, stream_end); + if(mr.current_match != ele) { + throw std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'"); + } + } + + }; + + template + const typename date_generator_parser::char_type + date_generator_parser::first_string[6] = + {'f','i','r','s','t'}; + template + const typename date_generator_parser::char_type + date_generator_parser::second_string[7] = + {'s','e','c','o','n','d'}; + template + const typename date_generator_parser::char_type + date_generator_parser::third_string[6] = + {'t','h','i','r','d'}; + template + const typename date_generator_parser::char_type + date_generator_parser::fourth_string[7] = + {'f','o','u','r','t','h'}; + template + const typename date_generator_parser::char_type + date_generator_parser::fifth_string[6] = + {'f','i','f','t','h'}; + template + const typename date_generator_parser::char_type + date_generator_parser::last_string[5] = + {'l','a','s','t'}; + template + const typename date_generator_parser::char_type + date_generator_parser::before_string[8] = + {'b','e','f','o','r','e'}; + template + const typename date_generator_parser::char_type + date_generator_parser::after_string[6] = + {'a','f','t','e','r'}; + template + const typename date_generator_parser::char_type + date_generator_parser::of_string[3] = + {'o','f'}; + +} } //namespace + +#endif // DATE_TIME_DATE_GENERATOR_PARSER_HPP__ + diff --git a/win32/include/boost/date_time/date_generators.hpp b/win32/include/boost/date_time/date_generators.hpp new file mode 100755 index 000000000..fc82b4df0 --- /dev/null +++ b/win32/include/boost/date_time/date_generators.hpp @@ -0,0 +1,509 @@ +#ifndef DATE_TIME_DATE_GENERATORS_HPP__ +#define DATE_TIME_DATE_GENERATORS_HPP__ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! @file date_generators.hpp + Definition and implementation of date algorithm templates +*/ +#include +#include +#include "boost/date_time/date.hpp" +#include "boost/date_time/compiler_config.hpp" + +namespace boost { +namespace date_time { + + //! Base class for all generators that take a year and produce a date. + /*! This class is a base class for polymorphic function objects that take + a year and produce a concrete date. + @param date_type The type representing a date. This type must + export a calender_type which defines a year_type. + */ + template + class year_based_generator + { + public: + typedef typename date_type::calendar_type calendar_type; + typedef typename calendar_type::year_type year_type; + year_based_generator() {}; + virtual ~year_based_generator() {}; + virtual date_type get_date(year_type y) const = 0; + //! Returns a string for use in a POSIX time_zone string + virtual std::string to_string() const =0; + }; + + //! Generates a date by applying the year to the given month and day. + /*! + Example usage: + @code + partial_date pd(1, Jan); + partial_date pd2(70); + date d = pd.get_date(2002); //2002-Jan-01 + date d2 = pd2.get_date(2002); //2002-Mar-10 + @endcode + \ingroup date_alg + */ + template + class partial_date : public year_based_generator + { + public: + typedef typename date_type::calendar_type calendar_type; + typedef typename calendar_type::day_type day_type; + typedef typename calendar_type::month_type month_type; + typedef typename calendar_type::year_type year_type; + typedef typename date_type::duration_type duration_type; + typedef typename duration_type::duration_rep duration_rep; + partial_date(day_type d, month_type m) : + day_(d), + month_(m) + {} + //! Partial date created from number of days into year. Range 1-366 + /*! Allowable values range from 1 to 366. 1=Jan1, 366=Dec31. If argument + * exceeds range, partial_date will be created with closest in-range value. + * 60 will always be Feb29, if get_date() is called with a non-leap year + * an exception will be thrown */ + partial_date(duration_rep days) : + day_(1), // default values + month_(1) + { + date_type d1(2000,1,1); + if(days > 1) { + if(days > 366) // prevents wrapping + { + days = 366; + } + days = days - 1; + duration_type dd(days); + d1 = d1 + dd; + } + day_ = d1.day(); + month_ = d1.month(); + } + //! Return a concrete date when provided with a year specific year. + /*! Will throw an 'invalid_argument' exception if a partial_date object, + * instantiated with Feb-29, has get_date called with a non-leap year. + * Example: + * @code + * partial_date pd(29, Feb); + * pd.get_date(2003); // throws invalid_argument exception + * pg.get_date(2000); // returns 2000-2-29 + * @endcode + */ + date_type get_date(year_type y) const + { + if((day_ == 29) && (month_ == 2) && !(calendar_type::is_leap_year(y))) { + std::stringstream ss(""); + ss << "No Feb 29th in given year of " << y << "."; + throw std::invalid_argument(ss.str()); + //return date_type(1,1,1); // should never reach + } else { + return date_type(y, month_, day_); + } + } + date_type operator()(year_type y) const + { + return get_date(y); + //return date_type(y, month_, day_); + } + bool operator==(const partial_date& rhs) const + { + return (month_ == rhs.month_) && (day_ == rhs.day_); + } + bool operator<(const partial_date& rhs) const + { + if (month_ < rhs.month_) return true; + if (month_ > rhs.month_) return false; + //months are equal + return (day_ < rhs.day_); + } + + // added for streaming purposes + month_type month() const + { + return month_; + } + day_type day() const + { + return day_; + } + + //! Returns string suitable for use in POSIX time zone string + /*! Returns string formatted with up to 3 digits: + * Jan-01 == "0" + * Feb-29 == "58" + * Dec-31 == "365" */ + virtual std::string to_string() const + { + std::stringstream ss; + date_type d(2004, month_, day_); + unsigned short c = d.day_of_year(); + c--; // numbered 0-365 while day_of_year is 1 based... + ss << c; + return ss.str(); + } + private: + day_type day_; + month_type month_; + }; + + + //! Useful generator functor for finding holidays + /*! Based on the idea in Cal. Calc. for finding holidays that are + * the 'first Monday of September'. When instantiated with + * 'fifth' kday of month, the result will be the last kday of month + * which can be the fourth or fifth depending on the structure of + * the month. + * + * The algorithm here basically guesses for the first + * day of the month. Then finds the first day of the correct + * type. That is, if the first of the month is a Tuesday + * and it needs Wenesday then we simply increment by a day + * and then we can add the length of a week until we get + * to the 'nth kday'. There are probably more efficient + * algorithms based on using a mod 7, but this one works + * reasonably well for basic applications. + * \ingroup date_alg + */ + template + class nth_kday_of_month : public year_based_generator + { + public: + typedef typename date_type::calendar_type calendar_type; + typedef typename calendar_type::day_of_week_type day_of_week_type; + typedef typename calendar_type::month_type month_type; + typedef typename calendar_type::year_type year_type; + typedef typename date_type::duration_type duration_type; + enum week_num {first=1, second, third, fourth, fifth}; + nth_kday_of_month(week_num week_no, + day_of_week_type dow, + month_type m) : + month_(m), + wn_(week_no), + dow_(dow) + {} + //! Return a concrete date when provided with a year specific year. + date_type get_date(year_type y) const + { + date_type d(y, month_, 1); //first day of month + duration_type one_day(1); + duration_type one_week(7); + while (dow_ != d.day_of_week()) { + d = d + one_day; + } + int week = 1; + while (week < wn_) { + d = d + one_week; + week++; + } + // remove wrapping to next month behavior + if(d.month() != month_) { + d = d - one_week; + } + return d; + } + // added for streaming + month_type month() const + { + return month_; + } + week_num nth_week() const + { + return wn_; + } + day_of_week_type day_of_week() const + { + return dow_; + } + const char* nth_week_as_str() const + { + return nth_as_str(wn_); + } + //! Returns string suitable for use in POSIX time zone string + /*! Returns a string formatted as "M4.3.0" ==> 3rd Sunday in April. */ + virtual std::string to_string() const + { + std::stringstream ss; + ss << 'M' + << static_cast(month_) << '.' + << static_cast(wn_) << '.' + << static_cast(dow_); + return ss.str(); + } + private: + month_type month_; + week_num wn_; + day_of_week_type dow_; + }; + + //! Returns nth arg as string. 1 -> "first", 2 -> "second", max is 5. + BOOST_DATE_TIME_DECL const char* nth_as_str(int n); + + //! Useful generator functor for finding holidays and daylight savings + /*! Similar to nth_kday_of_month, but requires less paramters + * \ingroup date_alg + */ + template + class first_kday_of_month : public year_based_generator + { + public: + typedef typename date_type::calendar_type calendar_type; + typedef typename calendar_type::day_of_week_type day_of_week_type; + typedef typename calendar_type::month_type month_type; + typedef typename calendar_type::year_type year_type; + typedef typename date_type::duration_type duration_type; + //!Specify the first 'Sunday' in 'April' spec + /*!@param dow The day of week, eg: Sunday, Monday, etc + * @param m The month of the year, eg: Jan, Feb, Mar, etc + */ + first_kday_of_month(day_of_week_type dow, month_type m) : + month_(m), + dow_(dow) + {} + //! Return a concrete date when provided with a year specific year. + date_type get_date(year_type year) const + { + date_type d(year, month_,1); + duration_type one_day(1); + while (dow_ != d.day_of_week()) { + d = d + one_day; + } + return d; + } + // added for streaming + month_type month() const + { + return month_; + } + day_of_week_type day_of_week() const + { + return dow_; + } + //! Returns string suitable for use in POSIX time zone string + /*! Returns a string formatted as "M4.1.0" ==> 1st Sunday in April. */ + virtual std::string to_string() const + { + std::stringstream ss; + ss << 'M' + << static_cast(month_) << '.' + << 1 << '.' + << static_cast(dow_); + return ss.str(); + } + private: + month_type month_; + day_of_week_type dow_; + }; + + + + //! Calculate something like Last Sunday of January + /*! Useful generator functor for finding holidays and daylight savings + * Get the last day of the month and then calculate the difference + * to the last previous day. + * @param date_type A date class that exports day_of_week, month_type, etc. + * \ingroup date_alg + */ + template + class last_kday_of_month : public year_based_generator + { + public: + typedef typename date_type::calendar_type calendar_type; + typedef typename calendar_type::day_of_week_type day_of_week_type; + typedef typename calendar_type::month_type month_type; + typedef typename calendar_type::year_type year_type; + typedef typename date_type::duration_type duration_type; + //!Specify the date spec like last 'Sunday' in 'April' spec + /*!@param dow The day of week, eg: Sunday, Monday, etc + * @param m The month of the year, eg: Jan, Feb, Mar, etc + */ + last_kday_of_month(day_of_week_type dow, month_type m) : + month_(m), + dow_(dow) + {} + //! Return a concrete date when provided with a year specific year. + date_type get_date(year_type year) const + { + date_type d(year, month_, calendar_type::end_of_month_day(year,month_)); + duration_type one_day(1); + while (dow_ != d.day_of_week()) { + d = d - one_day; + } + return d; + } + // added for streaming + month_type month() const + { + return month_; + } + day_of_week_type day_of_week() const + { + return dow_; + } + //! Returns string suitable for use in POSIX time zone string + /*! Returns a string formatted as "M4.5.0" ==> last Sunday in April. */ + virtual std::string to_string() const + { + std::stringstream ss; + ss << 'M' + << static_cast(month_) << '.' + << 5 << '.' + << static_cast(dow_); + return ss.str(); + } + private: + month_type month_; + day_of_week_type dow_; + }; + + + //! Calculate something like "First Sunday after Jan 1,2002 + /*! Date generator that takes a date and finds kday after + *@code + typedef boost::date_time::first_kday_after firstkdayafter; + firstkdayafter fkaf(Monday); + fkaf.get_date(date(2002,Feb,1)); + @endcode + * \ingroup date_alg + */ + template + class first_kday_after + { + public: + typedef typename date_type::calendar_type calendar_type; + typedef typename calendar_type::day_of_week_type day_of_week_type; + typedef typename date_type::duration_type duration_type; + first_kday_after(day_of_week_type dow) : + dow_(dow) + {} + //! Return next kday given. + date_type get_date(date_type start_day) const + { + duration_type one_day(1); + date_type d = start_day + one_day; + while (dow_ != d.day_of_week()) { + d = d + one_day; + } + return d; + } + // added for streaming + day_of_week_type day_of_week() const + { + return dow_; + } + private: + day_of_week_type dow_; + }; + + //! Calculate something like "First Sunday before Jan 1,2002 + /*! Date generator that takes a date and finds kday after + *@code + typedef boost::date_time::first_kday_before firstkdaybefore; + firstkdaybefore fkbf(Monday); + fkbf.get_date(date(2002,Feb,1)); + @endcode + * \ingroup date_alg + */ + template + class first_kday_before + { + public: + typedef typename date_type::calendar_type calendar_type; + typedef typename calendar_type::day_of_week_type day_of_week_type; + typedef typename date_type::duration_type duration_type; + first_kday_before(day_of_week_type dow) : + dow_(dow) + {} + //! Return next kday given. + date_type get_date(date_type start_day) const + { + duration_type one_day(1); + date_type d = start_day - one_day; + while (dow_ != d.day_of_week()) { + d = d - one_day; + } + return d; + } + // added for streaming + day_of_week_type day_of_week() const + { + return dow_; + } + private: + day_of_week_type dow_; + }; + + //! Calculates the number of days until the next weekday + /*! Calculates the number of days until the next weekday. + * If the date given falls on a Sunday and the given weekday + * is Tuesday the result will be 2 days */ + template + inline + typename date_type::duration_type days_until_weekday(const date_type& d, const weekday_type& wd) + { + typedef typename date_type::duration_type duration_type; + duration_type wks(0); + duration_type dd(wd.as_number() - d.day_of_week().as_number()); + if(dd.is_negative()){ + wks = duration_type(7); + } + return dd + wks; + } + + //! Calculates the number of days since the previous weekday + /*! Calculates the number of days since the previous weekday + * If the date given falls on a Sunday and the given weekday + * is Tuesday the result will be 5 days. The answer will be a positive + * number because Tuesday is 5 days before Sunday, not -5 days before. */ + template + inline + typename date_type::duration_type days_before_weekday(const date_type& d, const weekday_type& wd) + { + typedef typename date_type::duration_type duration_type; + duration_type wks(0); + duration_type dd(wd.as_number() - d.day_of_week().as_number()); + if(dd.days() > 0){ + wks = duration_type(7); + } + // we want a number of days, not an offset. The value returned must + // be zero or larger. + return (-dd + wks); + } + + //! Generates a date object representing the date of the following weekday from the given date + /*! Generates a date object representing the date of the following + * weekday from the given date. If the date given is 2004-May-9 + * (a Sunday) and the given weekday is Tuesday then the resulting date + * will be 2004-May-11. */ + template + inline + date_type next_weekday(const date_type& d, const weekday_type& wd) + { + return d + days_until_weekday(d, wd); + } + + //! Generates a date object representing the date of the previous weekday from the given date + /*! Generates a date object representing the date of the previous + * weekday from the given date. If the date given is 2004-May-9 + * (a Sunday) and the given weekday is Tuesday then the resulting date + * will be 2004-May-4. */ + template + inline + date_type previous_weekday(const date_type& d, const weekday_type& wd) + { + return d - days_before_weekday(d, wd); + } + +} } //namespace date_time + + + + +#endif + diff --git a/win32/include/boost/date_time/date_iterator.hpp b/win32/include/boost/date_time/date_iterator.hpp new file mode 100755 index 000000000..8b55e14f7 --- /dev/null +++ b/win32/include/boost/date_time/date_iterator.hpp @@ -0,0 +1,101 @@ +#ifndef DATE_ITERATOR_HPP___ +#define DATE_ITERATOR_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include + +namespace boost { +namespace date_time { + //! An iterator over dates with varying resolution (day, week, month, year, etc) + enum date_resolutions {day, week, months, year, decade, century, NumDateResolutions}; + + //! Base date iterator type + /*! This class provides the skeleton for the creation of iterators. + * New and interesting interators can be created by plugging in a new + * function that derives the next value from the current state. + * generation of various types of -based information. + * + * Template Parameters + * + * date_type + * + * The date_type is a concrete date_type. The date_type must + * define a duration_type and a calendar_type. + */ + template + class date_itr_base { + // works, but benefit unclear at the moment + // class date_itr_base : public std::iterator{ + public: + typedef typename date_type::duration_type duration_type; + typedef date_type value_type; + typedef std::input_iterator_tag iterator_category; + + date_itr_base(date_type d) : current_(d) {} + virtual ~date_itr_base() {}; + date_itr_base& operator++() + { + current_ = current_ + get_offset(current_); + return *this; + } + date_itr_base& operator--() + { + current_ = current_ + get_neg_offset(current_); + return *this; + } + virtual duration_type get_offset(const date_type& current) const=0; + virtual duration_type get_neg_offset(const date_type& current) const=0; + date_type operator*() {return current_;}; + date_type* operator->() {return ¤t_;}; + bool operator< (const date_type& d) {return current_ < d;} + bool operator<= (const date_type& d) {return current_ <= d;} + bool operator> (const date_type& d) {return current_ > d;} + bool operator>= (const date_type& d) {return current_ >= d;} + bool operator== (const date_type& d) {return current_ == d;} + bool operator!= (const date_type& d) {return current_ != d;} + private: + date_type current_; + }; + + //! Overrides the base date iterator providing hook for functors + /* + * offset_functor + * + * The offset functor must define a get_offset function that takes the + * current point in time and calculates and offset. + * + */ + template + class date_itr : public date_itr_base { + public: + typedef typename date_type::duration_type duration_type; + date_itr(date_type d, int factor=1) : + date_itr_base(d), + of_(factor) + {} + private: + virtual duration_type get_offset(const date_type& current) const + { + return of_.get_offset(current); + } + virtual duration_type get_neg_offset(const date_type& current) const + { + return of_.get_neg_offset(current); + } + offset_functor of_; + }; + + + +} } //namespace date_time + + +#endif diff --git a/win32/include/boost/date_time/date_names_put.hpp b/win32/include/boost/date_time/date_names_put.hpp new file mode 100755 index 000000000..f0f6a9248 --- /dev/null +++ b/win32/include/boost/date_time/date_names_put.hpp @@ -0,0 +1,320 @@ +#ifndef DATE_TIME_DATE_NAMES_PUT_HPP___ +#define DATE_TIME_DATE_NAMES_PUT_HPP___ + +/* Copyright (c) 2002-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/locale_config.hpp" // set BOOST_DATE_TIME_NO_LOCALE + +#ifndef BOOST_DATE_TIME_NO_LOCALE + +#include "boost/date_time/special_defs.hpp" +#include "boost/date_time/date_defs.hpp" +#include "boost/date_time/parse_format_base.hpp" +#include "boost/lexical_cast.hpp" +#include + + +namespace boost { +namespace date_time { + + //! Output facet base class for gregorian dates. + /*! This class is a base class for date facets used to localize the + * names of months and the names of days in the week. + * + * Requirements of Config + * - define an enumeration month_enum that enumerates the months. + * The enumeration should be '1' based eg: Jan==1 + * - define as_short_string and as_long_string + * + * (see langer & kreft p334). + * + */ + template > + class date_names_put : public std::locale::facet + { + public: + date_names_put() {}; + typedef OutputIterator iter_type; + typedef typename Config::month_type month_type; + typedef typename Config::month_enum month_enum; + typedef typename Config::weekday_enum weekday_enum; + typedef typename Config::special_value_enum special_value_enum; + //typedef typename Config::format_type format_type; + typedef std::basic_string string_type; + typedef charT char_type; + static const char_type default_special_value_names[3][17]; + static const char_type separator[2]; + + static std::locale::id id; + +#if defined (__SUNPRO_CC) && defined (_RWSTD_VER) + std::locale::id& __get_id (void) const { return id; } +#endif + + void put_special_value(iter_type& oitr, special_value_enum sv) const + { + do_put_special_value(oitr, sv); + } + void put_month_short(iter_type& oitr, month_enum moy) const + { + do_put_month_short(oitr, moy); + } + void put_month_long(iter_type& oitr, month_enum moy) const + { + do_put_month_long(oitr, moy); + } + void put_weekday_short(iter_type& oitr, weekday_enum wd) const + { + do_put_weekday_short(oitr, wd); + } + void put_weekday_long(iter_type& oitr, weekday_enum wd) const + { + do_put_weekday_long(oitr, wd); + } + bool has_date_sep_chars() const + { + return do_has_date_sep_chars(); + } + void year_sep_char(iter_type& oitr) const + { + do_year_sep_char(oitr); + } + //! char between year-month + void month_sep_char(iter_type& oitr) const + { + do_month_sep_char(oitr); + } + //! Char to separate month-day + void day_sep_char(iter_type& oitr) const + { + do_day_sep_char(oitr); + } + //! Determines the order to put the date elements + ymd_order_spec date_order() const + { + return do_date_order(); + } + //! Determines if month is displayed as integer, short or long string + month_format_spec month_format() const + { + return do_month_format(); + } + + protected: + //! Default facet implementation uses month_type defaults + virtual void do_put_month_short(iter_type& oitr, month_enum moy) const + { + month_type gm(moy); + charT c = '\0'; + put_string(oitr, gm.as_short_string(c)); + } + //! Default facet implementation uses month_type defaults + virtual void do_put_month_long(iter_type& oitr, + month_enum moy) const + { + month_type gm(moy); + charT c = '\0'; + put_string(oitr, gm.as_long_string(c)); + } + //! Default facet implementation for special value types + virtual void do_put_special_value(iter_type& oitr, special_value_enum sv) const + { + if(sv <= 2) { // only output not_a_date_time, neg_infin, or pos_infin + string_type s(default_special_value_names[sv]); + put_string(oitr, s); + } + } + virtual void do_put_weekday_short(iter_type&, weekday_enum) const + { + } + virtual void do_put_weekday_long(iter_type&, weekday_enum) const + { + } + virtual bool do_has_date_sep_chars() const + { + return true; + } + virtual void do_year_sep_char(iter_type& oitr) const + { + string_type s(separator); + put_string(oitr, s); + } + //! char between year-month + virtual void do_month_sep_char(iter_type& oitr) const + { + string_type s(separator); + put_string(oitr, s); + } + //! Char to separate month-day + virtual void do_day_sep_char(iter_type& oitr) const + { + string_type s(separator); //put in '-' + put_string(oitr, s); + } + //! Default for date order + virtual ymd_order_spec do_date_order() const + { + return ymd_order_iso; + } + //! Default month format + virtual month_format_spec do_month_format() const + { + return month_as_short_string; + } + void put_string(iter_type& oi, const charT* const s) const + { + string_type s1(boost::lexical_cast(s)); + typename string_type::iterator si,end; + for (si=s1.begin(), end=s1.end(); si!=end; si++, oi++) { + *oi = *si; + } + } + void put_string(iter_type& oi, const string_type& s1) const + { + typename string_type::const_iterator si,end; + for (si=s1.begin(), end=s1.end(); si!=end; si++, oi++) { + *oi = *si; + } + } + }; + + template + const typename date_names_put::char_type + date_names_put::default_special_value_names[3][17] = { + {'n','o','t','-','a','-','d','a','t','e','-','t','i','m','e'}, + {'-','i','n','f','i','n','i','t','y'}, + {'+','i','n','f','i','n','i','t','y'} }; + + template + const typename date_names_put::char_type + date_names_put::separator[2] = + {'-', '\0'} ; + + + //! Generate storage location for a std::locale::id + template + std::locale::id date_names_put::id; + + //! A date name output facet that takes an array of char* to define strings + template > + class all_date_names_put : public date_names_put + { + public: + all_date_names_put(const charT* const month_short_names[], + const charT* const month_long_names[], + const charT* const special_value_names[], + const charT* const weekday_short_names[], + const charT* const weekday_long_names[], + charT separator_char = '-', + ymd_order_spec order_spec = ymd_order_iso, + month_format_spec month_format = month_as_short_string) : + month_short_names_(month_short_names), + month_long_names_(month_long_names), + special_value_names_(special_value_names), + weekday_short_names_(weekday_short_names), + weekday_long_names_(weekday_long_names), + order_spec_(order_spec), + month_format_spec_(month_format) + { + separator_char_[0] = separator_char; + separator_char_[1] = '\0'; + + }; + typedef OutputIterator iter_type; + typedef typename Config::month_enum month_enum; + typedef typename Config::weekday_enum weekday_enum; + typedef typename Config::special_value_enum special_value_enum; + + const charT* const* get_short_month_names() const + { + return month_short_names_; + } + const charT* const* get_long_month_names() const + { + return month_long_names_; + } + const charT* const* get_special_value_names() const + { + return special_value_names_; + } + const charT* const* get_short_weekday_names()const + { + return weekday_short_names_; + } + const charT* const* get_long_weekday_names()const + { + return weekday_long_names_; + } + + protected: + //! Generic facet that takes array of chars + virtual void do_put_month_short(iter_type& oitr, month_enum moy) const + { + this->put_string(oitr, month_short_names_[moy-1]); + } + //! Long month names + virtual void do_put_month_long(iter_type& oitr, month_enum moy) const + { + this->put_string(oitr, month_long_names_[moy-1]); + } + //! Special values names + virtual void do_put_special_value(iter_type& oitr, special_value_enum sv) const + { + this->put_string(oitr, special_value_names_[sv]); + } + virtual void do_put_weekday_short(iter_type& oitr, weekday_enum wd) const + { + this->put_string(oitr, weekday_short_names_[wd]); + } + virtual void do_put_weekday_long(iter_type& oitr, weekday_enum wd) const + { + this->put_string(oitr, weekday_long_names_[wd]); + } + //! char between year-month + virtual void do_month_sep_char(iter_type& oitr) const + { + this->put_string(oitr, separator_char_); + } + //! Char to separate month-day + virtual void do_day_sep_char(iter_type& oitr) const + { + this->put_string(oitr, separator_char_); + } + //! Set the date ordering + virtual ymd_order_spec do_date_order() const + { + return order_spec_; + } + //! Set the date ordering + virtual month_format_spec do_month_format() const + { + return month_format_spec_; + } + + private: + const charT* const* month_short_names_; + const charT* const* month_long_names_; + const charT* const* special_value_names_; + const charT* const* weekday_short_names_; + const charT* const* weekday_long_names_; + charT separator_char_[2]; + ymd_order_spec order_spec_; + month_format_spec month_format_spec_; + }; + +} } //namespace boost::date_time + +#endif //BOOST_NO_STD_LOCALE + +#endif diff --git a/win32/include/boost/date_time/date_parsing.hpp b/win32/include/boost/date_time/date_parsing.hpp new file mode 100755 index 000000000..5db306259 --- /dev/null +++ b/win32/include/boost/date_time/date_parsing.hpp @@ -0,0 +1,299 @@ +#ifndef _DATE_TIME_DATE_PARSING_HPP___ +#define _DATE_TIME_DATE_PARSING_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/tokenizer.hpp" +#include "boost/lexical_cast.hpp" +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/parse_format_base.hpp" +#include +#include +#include + +#if defined(BOOST_NO_STD_LOCALE) +#include // ::tolower(int) +#else +#include // std::tolower(char, locale) +#endif + +namespace boost { +namespace date_time { + + //! A function to replace the std::transform( , , ,tolower) construct + /*! This function simply takes a string, and changes all the characters + * in that string to lowercase (according to the default system locale). + * In the event that a compiler does not support locales, the old + * C style tolower() is used. + */ + inline + std::string + convert_to_lower(const std::string& inp) { + std::string tmp; + unsigned i = 0; +#if defined(BOOST_NO_STD_LOCALE) + while(i < inp.length()) { + tmp += static_cast(std::tolower(inp.at(i++))); +#else + static const std::locale loc(std::locale::classic()); + while(i < inp.length()) { + // tolower and others were brought in to std for borland >= v564 + // in compiler_config.hpp + std::string::value_type c(inp.at(i++)); + tmp += std::tolower(c, loc); +#endif + + } + return tmp; + } + + //! Helper function for parse_date. + /* Used by-value parameter because we change the string and may + * want to preserve the original argument */ + template + unsigned short + month_str_to_ushort(std::string s) { + if((s.at(0) >= '0') && (s.at(0) <= '9')) { + return boost::lexical_cast(s); + } + else { + s = convert_to_lower(s); + typename month_type::month_map_ptr_type ptr = month_type::get_month_map_ptr(); + typename month_type::month_map_type::iterator iter = ptr->find(s); + if(iter != ptr->end()) { // required for STLport + return iter->second; + } + } + return 13; // intentionally out of range - name not found + } + + //! Find index of a string in either of 2 arrays + /*! find_match searches both arrays for a match to 's'. Indexing of the + * arrays is from 0 to 'limit'. The index of the match is returned. + * Ex. "Jan" returns 0, "Dec" returns 11, "Tue" returns 2. + * 'limit' can be sent in with: greg_month::max(), + * greg_weekday::max() or date_time::NumSpecialValues */ + template + short find_match(const charT* const* short_names, + const charT* const* long_names, + short limit, + const std::basic_string& s) { + for(short i = 0; i <= limit; ++i){ + if(short_names[i] == s || long_names[i] == s){ + return i; + } + } + return static_cast(limit + 1); // not-found, return a value out of range + } + + //! Generic function to parse a delimited date (eg: 2002-02-10) + /*! Accepted formats are: "2003-02-10" or " 2003-Feb-10" or + * "2003-Feburary-10" + * The order in which the Month, Day, & Year appear in the argument + * string can be accomodated by passing in the appropriate ymd_order_spec + */ + template + date_type + parse_date(const std::string& s, int order_spec = ymd_order_iso) { + std::string spec_str(""); + if(order_spec == ymd_order_iso) { + spec_str = "ymd"; + } + else if(order_spec == ymd_order_dmy) { + spec_str = "dmy"; + } + else { // (order_spec == ymd_order_us) + spec_str = "mdy"; + } + + typedef typename date_type::year_type year_type; + typedef typename date_type::month_type month_type; + unsigned pos = 0; + unsigned short year(0), month(0), day(0); + typedef typename std::basic_string::traits_type traits_type; + typedef boost::char_separator char_separator_type; + typedef boost::tokenizer::const_iterator, + std::basic_string > tokenizer; + typedef boost::tokenizer::const_iterator, + std::basic_string >::iterator tokenizer_iterator; + // may need more delimiters, these work for the regression tests + const char sep_char[] = {',','-','.',' ','/','\0'}; + char_separator_type sep(sep_char); + tokenizer tok(s,sep); + for(tokenizer_iterator beg=tok.begin(); + beg!=tok.end() && pos < spec_str.size(); + ++beg, ++pos) { + switch(spec_str.at(pos)) { + case 'y': + { + year = boost::lexical_cast(*beg); + break; + } + case 'm': + { + month = month_str_to_ushort(*beg); + break; + } + case 'd': + { + day = boost::lexical_cast(*beg); + break; + } + } //switch + } + return date_type(year, month, day); + } + + //! Generic function to parse undelimited date (eg: 20020201) + template + date_type + parse_undelimited_date(const std::string& s) { + int offsets[] = {4,2,2}; + int pos = 0; + typedef typename date_type::year_type year_type; + //typename date_type::ymd_type ymd((year_type::min)(),1,1); + unsigned short y = 0, m = 0, d = 0; + + /* The two bool arguments state that parsing will not wrap + * (only the first 8 characters will be parsed) and partial + * strings will not be parsed. + * Ex: + * "2005121" will parse 2005 & 12, but not the "1" */ + boost::offset_separator osf(offsets, offsets+3, false, false); + + typedef typename boost::tokenizer::const_iterator, + std::basic_string > tokenizer_type; + tokenizer_type tok(s, osf); + for(typename tokenizer_type::iterator ti=tok.begin(); ti!=tok.end();++ti) { + unsigned short i = boost::lexical_cast(*ti); + switch(pos) { + case 0: y = i; break; + case 1: m = i; break; + case 2: d = i; break; + } + pos++; + } + return date_type(y,m,d); + } + + //! Helper function for 'date gregorian::from_stream()' + /*! Creates a string from the iterators that reference the + * begining & end of a char[] or string. All elements are + * used in output string */ + template + inline + date_type + from_stream_type(iterator_type& beg, + iterator_type& end, + char) + { + std::stringstream ss(""); + while(beg != end) { + ss << *beg++; + } + return parse_date(ss.str()); + } + + //! Helper function for 'date gregorian::from_stream()' + /*! Returns the first string found in the stream referenced by the + * begining & end iterators */ + template + inline + date_type + from_stream_type(iterator_type& beg, + iterator_type& end, + std::string) + { + return parse_date(*beg); + } + + /* I believe the wchar stuff would be best elsewhere, perhaps in + * parse_date<>()? In the mean time this gets us started... */ + //! Helper function for 'date gregorian::from_stream()' + /*! Creates a string from the iterators that reference the + * begining & end of a wstring. All elements are + * used in output string */ + template + inline + date_type from_stream_type(iterator_type& beg, + iterator_type& end, + wchar_t) + { + std::stringstream ss(""); + while(beg != end) { +#if !defined(BOOST_DATE_TIME_NO_LOCALE) + ss << std::use_facet >(std::locale()).narrow(*beg++, 'X'); // 'X' will cause exception to be thrown +#else + ss << ss.narrow(*beg++, 'X'); +#endif + } + return parse_date(ss.str()); + } +#ifndef BOOST_NO_STD_WSTRING + //! Helper function for 'date gregorian::from_stream()' + /*! Creates a string from the first wstring found in the stream + * referenced by the begining & end iterators */ + template + inline + date_type + from_stream_type(iterator_type& beg, + iterator_type& end, + std::wstring) { + std::wstring ws = *beg; + std::stringstream ss(""); + std::wstring::iterator wsb = ws.begin(), wse = ws.end(); + while(wsb != wse) { +#if !defined(BOOST_DATE_TIME_NO_LOCALE) + ss << std::use_facet >(std::locale()).narrow(*wsb++, 'X'); // 'X' will cause exception to be thrown +#else + ss << ss.narrow(*wsb++, 'X'); // 'X' will cause exception to be thrown +#endif + } + return parse_date(ss.str()); + } +#endif // BOOST_NO_STD_WSTRING +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + // This function cannot be compiled with MSVC 6.0 due to internal compiler shorcomings +#else + //! function called by wrapper functions: date_period_from_(w)string() + template + period + from_simple_string_type(const std::basic_string& s){ + typedef typename std::basic_string::traits_type traits_type; + typedef typename boost::char_separator char_separator; + typedef typename boost::tokenizer::const_iterator, + std::basic_string > tokenizer; + const charT sep_list[4] = {'[','/',']','\0'}; + char_separator sep(sep_list); + tokenizer tokens(s, sep); + typename tokenizer::iterator tok_it = tokens.begin(); + std::basic_string date_string = *tok_it; + // get 2 string iterators and generate a date from them + typename std::basic_string::iterator date_string_start = date_string.begin(), + date_string_end = date_string.end(); + typedef typename std::iterator_traits::iterator>::value_type value_type; + date_type d1 = from_stream_type(date_string_start, date_string_end, value_type()); + date_string = *(++tok_it); // next token + date_string_start = date_string.begin(), date_string_end = date_string.end(); + date_type d2 = from_stream_type(date_string_start, date_string_end, value_type()); + return period(d1, d2); + } +#endif + +} } //namespace date_time + + + + +#endif + diff --git a/win32/include/boost/date_time/dst_rules.hpp b/win32/include/boost/date_time/dst_rules.hpp new file mode 100755 index 000000000..f837140df --- /dev/null +++ b/win32/include/boost/date_time/dst_rules.hpp @@ -0,0 +1,391 @@ +#ifndef DATE_TIME_DST_RULES_HPP__ +#define DATE_TIME_DST_RULES_HPP__ + +/* Copyright (c) 2002,2003, 2007 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! @file dst_rules.hpp + Contains template class to provide static dst rule calculations +*/ + +#include "boost/date_time/date_generators.hpp" +#include "boost/date_time/period.hpp" +#include "boost/date_time/date_defs.hpp" +#include + +namespace boost { + namespace date_time { + + enum time_is_dst_result {is_not_in_dst, is_in_dst, + ambiguous, invalid_time_label}; + + + //! Dynamic class used to caluclate dst transition information + template + class dst_calculator + { + public: + typedef time_duration_type_ time_duration_type; + typedef date_type_ date_type; + + //! Check the local time offset when on dst start day + /*! On this dst transition, the time label between + * the transition boundary and the boudary + the offset + * are invalid times. If before the boundary then still + * not in dst. + *@param time_of_day Time offset in the day for the local time + *@param dst_start_offset_minutes Local day offset for start of dst + *@param dst_length_minutes Number of minutes to adjust clock forward + *@retval status of time label w.r.t. dst + */ + static time_is_dst_result + process_local_dst_start_day(const time_duration_type& time_of_day, + unsigned int dst_start_offset_minutes, + long dst_length_minutes) + { + //std::cout << "here" << std::endl; + if (time_of_day < time_duration_type(0,dst_start_offset_minutes,0)) { + return is_not_in_dst; + } + long offset = dst_start_offset_minutes + dst_length_minutes; + if (time_of_day >= time_duration_type(0,offset,0)) { + return is_in_dst; + } + return invalid_time_label; + } + + //! Check the local time offset when on the last day of dst + /*! This is the calculation for the DST end day. On that day times + * prior to the conversion time - dst_length (1 am in US) are still + * in dst. Times between the above and the switch time are + * ambiguous. Times after the start_offset are not in dst. + *@param time_of_day Time offset in the day for the local time + *@param dst_end_offset_minutes Local time of day for end of dst + *@retval status of time label w.r.t. dst + */ + static time_is_dst_result + process_local_dst_end_day(const time_duration_type& time_of_day, + unsigned int dst_end_offset_minutes, + long dst_length_minutes) + { + //in US this will be 60 so offset in day is 1,0,0 + int offset = dst_end_offset_minutes-dst_length_minutes; + if (time_of_day < time_duration_type(0,offset,0)) { + return is_in_dst; + } + if (time_of_day >= time_duration_type(0,dst_end_offset_minutes,0)) { + return is_not_in_dst; + } + return ambiguous; + } + + //! Calculates if the given local time is dst or not + /*! Determines if the time is really in DST or not. Also checks for + * invalid and ambiguous. + * @param current_day The day to check for dst + * @param time_of_day Time offset within the day to check + * @param dst_start_day Starting day of dst for the given locality + * @param dst_start_offset Time offset within day for dst boundary + * @param dst_end_day Ending day of dst for the given locality + * @param dst_end_offset Time offset within day given in dst for dst boundary + * @param dst_length lenght of dst adjusment + * @retval The time is either ambiguous, invalid, in dst, or not in dst + */ + static time_is_dst_result + local_is_dst(const date_type& current_day, + const time_duration_type& time_of_day, + const date_type& dst_start_day, + const time_duration_type& dst_start_offset, + const date_type& dst_end_day, + const time_duration_type& dst_end_offset, + const time_duration_type& dst_length_minutes) + { + unsigned int start_minutes = + dst_start_offset.hours() * 60 + dst_start_offset.minutes(); + unsigned int end_minutes = + dst_end_offset.hours() * 60 + dst_end_offset.minutes(); + long length_minutes = + dst_length_minutes.hours() * 60 + dst_length_minutes.minutes(); + + return local_is_dst(current_day, time_of_day, + dst_start_day, start_minutes, + dst_end_day, end_minutes, + length_minutes); + } + + //! Calculates if the given local time is dst or not + /*! Determines if the time is really in DST or not. Also checks for + * invalid and ambiguous. + * @param current_day The day to check for dst + * @param time_of_day Time offset within the day to check + * @param dst_start_day Starting day of dst for the given locality + * @param dst_start_offset_minutes Offset within day for dst + * boundary (eg 120 for US which is 02:00:00) + * @param dst_end_day Ending day of dst for the given locality + * @param dst_end_offset_minutes Offset within day given in dst for dst + * boundary (eg 120 for US which is 02:00:00) + * @param dst_length_minutes Length of dst adjusment (eg: 60 for US) + * @retval The time is either ambiguous, invalid, in dst, or not in dst + */ + static time_is_dst_result + local_is_dst(const date_type& current_day, + const time_duration_type& time_of_day, + const date_type& dst_start_day, + unsigned int dst_start_offset_minutes, + const date_type& dst_end_day, + unsigned int dst_end_offset_minutes, + long dst_length_minutes) + { + //in northern hemisphere dst is in the middle of the year + if (dst_start_day < dst_end_day) { + if ((current_day > dst_start_day) && (current_day < dst_end_day)) { + return is_in_dst; + } + if ((current_day < dst_start_day) || (current_day > dst_end_day)) { + return is_not_in_dst; + } + } + else {//southern hemisphere dst is at begining /end of year + if ((current_day < dst_start_day) && (current_day > dst_end_day)) { + return is_not_in_dst; + } + if ((current_day > dst_start_day) || (current_day < dst_end_day)) { + return is_in_dst; + } + } + + if (current_day == dst_start_day) { + return process_local_dst_start_day(time_of_day, + dst_start_offset_minutes, + dst_length_minutes); + } + + if (current_day == dst_end_day) { + return process_local_dst_end_day(time_of_day, + dst_end_offset_minutes, + dst_length_minutes); + } + //you should never reach this statement + return invalid_time_label; + } + + }; + + + //! Compile-time configurable daylight savings time calculation engine + /* This template provides the ability to configure a daylight savings + * calculation at compile time covering all the cases. Unfortunately + * because of the number of dimensions related to daylight savings + * calculation the number of parameters is high. In addition, the + * start and end transition rules are complex types that specify + * an algorithm for calculation of the starting day and ending + * day of daylight savings time including the month and day + * specifications (eg: last sunday in October). + * + * @param date_type A type that represents dates, typically gregorian::date + * @param time_duration_type Used for the offset in the day calculations + * @param dst_traits A set of traits that define the rules of dst + * calculation. The dst_trait must include the following: + * start_rule_functor - Rule to calculate the starting date of a + * dst transition (eg: last_kday_of_month). + * start_day - static function that returns month of dst start for + * start_rule_functor + * start_month -static function that returns day or day of week for + * dst start of dst + * end_rule_functor - Rule to calculate the end of dst day. + * end_day - static fucntion that returns end day for end_rule_functor + * end_month - static function that returns end month for end_rule_functor + * dst_start_offset_minutes - number of minutes from start of day to transition to dst -- 120 (or 2:00 am) is typical for the U.S. and E.U. + * dst_start_offset_minutes - number of minutes from start of day to transition off of dst -- 180 (or 3:00 am) is typical for E.U. + * dst_length_minutes - number of minutes that dst shifts clock + */ + template + class dst_calc_engine + { + public: + typedef typename date_type::year_type year_type; + typedef typename date_type::calendar_type calendar_type; + typedef dst_calculator dstcalc; + + //! Calculates if the given local time is dst or not + /*! Determines if the time is really in DST or not. Also checks for + * invalid and ambiguous. + * @retval The time is either ambiguous, invalid, in dst, or not in dst + */ + static time_is_dst_result local_is_dst(const date_type& d, + const time_duration_type& td) + { + + year_type y = d.year(); + date_type dst_start = local_dst_start_day(y); + date_type dst_end = local_dst_end_day(y); + return dstcalc::local_is_dst(d,td, + dst_start, + dst_traits::dst_start_offset_minutes(), + dst_end, + dst_traits::dst_end_offset_minutes(), + dst_traits::dst_shift_length_minutes()); + + } + + static bool is_dst_boundary_day(date_type d) + { + year_type y = d.year(); + return ((d == local_dst_start_day(y)) || + (d == local_dst_end_day(y))); + } + + //! The time of day for the dst transition (eg: typically 01:00:00 or 02:00:00) + static time_duration_type dst_offset() + { + return time_duration_type(0,dst_traits::dst_shift_length_minutes(),0); + } + + static date_type local_dst_start_day(year_type year) + { + return dst_traits::local_dst_start_day(year); + } + + static date_type local_dst_end_day(year_type year) + { + return dst_traits::local_dst_end_day(year); + } + + + }; + + //! Depricated: Class to calculate dst boundaries for US time zones + /* Use dst_calc_engine instead. + * In 2007 US/Canada DST rules changed + * (http://en.wikipedia.org/wiki/Energy_Policy_Act_of_2005#Change_to_daylight_saving_time). + */ + template //1 hour == 60 min in US + class us_dst_rules + { + public: + typedef time_duration_type_ time_duration_type; + typedef date_type_ date_type; + typedef typename date_type::year_type year_type; + typedef typename date_type::calendar_type calendar_type; + typedef date_time::last_kday_of_month lkday; + typedef date_time::first_kday_of_month fkday; + typedef date_time::nth_kday_of_month nkday; + typedef dst_calculator dstcalc; + + //! Calculates if the given local time is dst or not + /*! Determines if the time is really in DST or not. Also checks for + * invalid and ambiguous. + * @retval The time is either ambiguous, invalid, in dst, or not in dst + */ + static time_is_dst_result local_is_dst(const date_type& d, + const time_duration_type& td) + { + + year_type y = d.year(); + date_type dst_start = local_dst_start_day(y); + date_type dst_end = local_dst_end_day(y); + return dstcalc::local_is_dst(d,td, + dst_start,dst_start_offset_minutes, + dst_end, dst_start_offset_minutes, + dst_length_minutes); + + } + + + static bool is_dst_boundary_day(date_type d) + { + year_type y = d.year(); + return ((d == local_dst_start_day(y)) || + (d == local_dst_end_day(y))); + } + + static date_type local_dst_start_day(year_type year) + { + if (year >= year_type(2007)) { + //second sunday in march + nkday ssim(nkday::second, Sunday, gregorian::Mar); + return ssim.get_date(year); + } else { + //first sunday in april + fkday fsia(Sunday, gregorian::Apr); + return fsia.get_date(year); + } + } + + static date_type local_dst_end_day(year_type year) + { + if (year >= year_type(2007)) { + //first sunday in november + fkday fsin(Sunday, gregorian::Nov); + return fsin.get_date(year); + } else { + //last sunday in october + lkday lsio(Sunday, gregorian::Oct); + return lsio.get_date(year); + } + } + + static time_duration_type dst_offset() + { + return time_duration_type(0,dst_length_minutes,0); + } + + private: + + + }; + + //! Used for local time adjustments in places that don't use dst + template + class null_dst_rules + { + public: + typedef time_duration_type_ time_duration_type; + typedef date_type_ date_type; + + + //! Calculates if the given local time is dst or not + /*! @retval Always is_not_in_dst since this is for zones without dst + */ + static time_is_dst_result local_is_dst(const date_type&, + const time_duration_type&) + { + return is_not_in_dst; + } + + //! Calculates if the given utc time is in dst + static time_is_dst_result utc_is_dst(const date_type&, + const time_duration_type&) + { + return is_not_in_dst; + } + + static bool is_dst_boundary_day(date_type d) + { + return false; + } + + static time_duration_type dst_offset() + { + return time_duration_type(0,0,0); + } + + }; + + + } } //namespace date_time + + + +#endif diff --git a/win32/include/boost/date_time/dst_transition_generators.hpp b/win32/include/boost/date_time/dst_transition_generators.hpp new file mode 100755 index 000000000..d58311262 --- /dev/null +++ b/win32/include/boost/date_time/dst_transition_generators.hpp @@ -0,0 +1,75 @@ +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + */ +#ifndef DATE_TIME_DATE_DST_TRANSITION_DAY_GEN_HPP__ +#define DATE_TIME_DATE_DST_TRANSITION_DAY_GEN_HPP__ + + + +namespace boost { +namespace date_time { + + //! Defines base interface for calculating start and end date of daylight savings + template + class dst_day_calc_rule + { + public: + typedef typename date_type::year_type year_type; + virtual ~dst_day_calc_rule() {}; + virtual date_type start_day(year_type y) const=0; + virtual std::string start_rule_as_string() const=0; + virtual date_type end_day(year_type y) const=0; + virtual std::string end_rule_as_string() const=0; + + }; + + //! Canonical form for a class that provides day rule calculation + /*! This class is used to generate specific sets of dst rules + * + *@param spec Provides a specifiction of the function object types used + * to generate start and end days of daylight savings as well + * as the date type. + */ + template + class day_calc_dst_rule : public dst_day_calc_rule + { + public: + typedef typename spec::date_type date_type; + typedef typename date_type::year_type year_type; + typedef typename spec::start_rule start_rule; + typedef typename spec::end_rule end_rule; + day_calc_dst_rule(start_rule dst_start, + end_rule dst_end) : + dst_start_(dst_start), + dst_end_(dst_end) + {} + virtual date_type start_day(year_type y) const + { + return dst_start_.get_date(y); + } + virtual std::string start_rule_as_string() const + { + return dst_start_.to_string(); + } + virtual date_type end_day(year_type y) const + { + return dst_end_.get_date(y); + } + virtual std::string end_rule_as_string() const + { + return dst_end_.to_string(); + } + private: + start_rule dst_start_; + end_rule dst_end_; + }; + + +} }//namespace + + + +#endif diff --git a/win32/include/boost/date_time/filetime_functions.hpp b/win32/include/boost/date_time/filetime_functions.hpp new file mode 100755 index 000000000..24178e1f5 --- /dev/null +++ b/win32/include/boost/date_time/filetime_functions.hpp @@ -0,0 +1,78 @@ +#ifndef DATE_TIME_FILETIME_FUNCTIONS_HPP__ +#define DATE_TIME_FILETIME_FUNCTIONS_HPP__ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! @file filetime_functions.hpp + * Function(s) for converting between a FILETIME structure and a + * time object. This file is only available on systems that have + * BOOST_HAS_FTIME defined. + */ + +#include +#if defined(BOOST_HAS_FTIME) // skip this file if no FILETIME +#include +#include +#include + + +namespace boost { +namespace date_time { + + + //! Create a time object from an initialized FILETIME struct. + /*! Create a time object from an initialized FILETIME struct. + * A FILETIME struct holds 100-nanosecond units (0.0000001). When + * built with microsecond resolution the FILETIME's sub second value + * will be truncated. Nanosecond resolution has no truncation. */ + template + inline + time_type time_from_ftime(const FILETIME& ft){ + typedef typename time_type::date_type date_type; + typedef typename time_type::date_duration_type date_duration_type; + typedef typename time_type::time_duration_type time_duration_type; + + /* OFFSET is difference between 1970-Jan-01 & 1601-Jan-01 + * in 100-nanosecond intervals */ + uint64_t c1 = 27111902UL; + uint64_t c2 = 3577643008UL; // issues warning without 'UL' + const uint64_t OFFSET = (c1 << 32) + c2; + const long sec_pr_day = 86400; // seconds per day + + uint64_t filetime = ft.dwHighDateTime; + filetime <<= 32; + filetime += ft.dwLowDateTime; + filetime -= OFFSET; // filetime is now 100-nanos since 1970-Jan-01 + + uint64_t sec = filetime / 10000000; +#if defined(BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG) + uint64_t sub_sec = (filetime % 10000000) * 100; // nanoseconds +#else + uint64_t sub_sec = (filetime % 10000000) / 10; // truncate to microseconds +#endif + + // split sec into usable chunks: days, hours, minutes, & seconds + long _d = sec / sec_pr_day; + long tmp = sec % sec_pr_day; + long _h = tmp / 3600; // sec_pr_hour + tmp %= 3600; + long _m = tmp / 60; // sec_pr_min + tmp %= 60; + long _s = tmp; // seconds + + date_duration_type dd(_d); + date_type d = date_type(1970, Jan, 01) + dd; + return time_type(d, time_duration_type(_h, _m, _s, sub_sec)); + } + +}} // boost::date_time + +#endif // BOOST_HAS_FTIME + +#endif // DATE_TIME_FILETIME_FUNCTIONS_HPP__ diff --git a/win32/include/boost/date_time/format_date_parser.hpp b/win32/include/boost/date_time/format_date_parser.hpp new file mode 100755 index 000000000..9e292a843 --- /dev/null +++ b/win32/include/boost/date_time/format_date_parser.hpp @@ -0,0 +1,731 @@ + +#ifndef DATE_TIME_FORMAT_DATE_PARSER_HPP__ +#define DATE_TIME_FORMAT_DATE_PARSER_HPP__ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/lexical_cast.hpp" +#include "boost/date_time/string_parse_tree.hpp" +#include "boost/date_time/strings_from_facet.hpp" +#include "boost/date_time/special_values_parser.hpp" +#include +#include + +namespace boost { namespace date_time { + +//! Helper function for parsing fixed length strings into integers +/*! Will consume 'length' number of characters from stream. Consumed + * character are transfered to parse_match_result struct. + * Returns '-1' if no number can be parsed or incorrect number of + * digits in stream. */ +template +inline +int_type +fixed_string_to_int(std::istreambuf_iterator& itr, + std::istreambuf_iterator& stream_end, + parse_match_result& mr, + unsigned int length, + const charT& fill_char) +{ + //typedef std::basic_string string_type; + unsigned int j = 0; + //string_type s; + while (j < length && itr != stream_end && + (std::isdigit(*itr) || *itr == fill_char)) { + if(*itr == fill_char) { + /* Since a fill_char can be anything, we convert it to a zero. + * lexical_cast will behave predictably when zero is used as fill. */ + mr.cache += ('0'); + } + else { + mr.cache += (*itr); + } + itr++; + j++; + } + int_type i = -1; + // mr.cache will hold leading zeros. size() tells us when input is too short. + if(mr.cache.size() < length) { + return i; + } + try { + i = boost::lexical_cast(mr.cache); + }catch(bad_lexical_cast blc){ + // we want to return -1 if the cast fails so nothing to do here + } + return i; +} + +//! Helper function for parsing fixed length strings into integers +/*! Will consume 'length' number of characters from stream. Consumed + * character are transfered to parse_match_result struct. + * Returns '-1' if no number can be parsed or incorrect number of + * digits in stream. */ +template +inline +int_type +fixed_string_to_int(std::istreambuf_iterator& itr, + std::istreambuf_iterator& stream_end, + parse_match_result& mr, + unsigned int length) +{ + return fixed_string_to_int(itr, stream_end, mr, length, '0'); +} + +//! Helper function for parsing varied length strings into integers +/*! Will consume 'max_length' characters from stream only if those + * characters are digits. Returns '-1' if no number can be parsed. + * Will not parse a number preceeded by a '+' or '-'. */ +template +inline +int_type +var_string_to_int(std::istreambuf_iterator& itr, + std::istreambuf_iterator& /* stream_end */, + unsigned int max_length) +{ + typedef std::basic_string string_type; + unsigned int j = 0; + string_type s; + while ((j < max_length) && std::isdigit(*itr)) { + s += (*itr); + itr++; + j++; + } + int_type i = -1; + if(s.length() != 0) { + i = boost::lexical_cast(s); + } + return i; +} + + +//! Class with generic date parsing using a format string +/*! The following is the set of recognized format specifiers + - %a - Short weekday name + - %A - Long weekday name + - %b - Abbreviated month name + - %B - Full month name + - %d - Day of the month as decimal 01 to 31 + - %j - Day of year as decimal from 001 to 366 + - %m - Month name as a decimal 01 to 12 + - %U - Week number 00 to 53 with first Sunday as the first day of week 1? + - %w - Weekday as decimal number 0 to 6 where Sunday == 0 + - %W - Week number 00 to 53 where Monday is first day of week 1 + - %x - facet default date representation + - %y - Year without the century - eg: 04 for 2004 + - %Y - Year with century + + The weekday specifiers (%a and %A) do not add to the date construction, + but they provide a way to skip over the weekday names for formats that + provide them. + + todo -- Another interesting feature that this approach could provide is + an option to fill in any missing fields with the current values + from the clock. So if you have %m-%d the parser would detect + the missing year value and fill it in using the clock. + + todo -- What to do with the %x. %x in the classic facet is just bad... + + */ +template +class format_date_parser +{ + public: + typedef std::basic_string string_type; + typedef std::basic_ostringstream stringstream_type; + typedef std::istreambuf_iterator stream_itr_type; + typedef typename string_type::const_iterator const_itr; + typedef typename date_type::year_type year_type; + typedef typename date_type::month_type month_type; + typedef typename date_type::day_type day_type; + typedef typename date_type::duration_type duration_type; + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::day_of_year_type day_of_year_type; + typedef string_parse_tree parse_tree_type; + typedef typename parse_tree_type::parse_match_result_type match_results; + typedef std::vector > input_collection_type; + + // TODO sv_parser uses its default constructor - write the others + + format_date_parser(const string_type& format_str, + const input_collection_type& month_short_names, + const input_collection_type& month_long_names, + const input_collection_type& weekday_short_names, + const input_collection_type& weekday_long_names) : + m_format(format_str), + m_month_short_names(month_short_names, 1), + m_month_long_names(month_long_names, 1), + m_weekday_short_names(weekday_short_names), + m_weekday_long_names(weekday_long_names) + {} + + format_date_parser(const string_type& format_str, + const std::locale& locale) : + m_format(format_str), + m_month_short_names(gather_month_strings(locale), 1), + m_month_long_names(gather_month_strings(locale, false), 1), + m_weekday_short_names(gather_weekday_strings(locale)), + m_weekday_long_names(gather_weekday_strings(locale, false)) + {} + + format_date_parser(const format_date_parser& fdp) + { + this->m_format = fdp.m_format; + this->m_month_short_names = fdp.m_month_short_names; + this->m_month_long_names = fdp.m_month_long_names; + this->m_weekday_short_names = fdp.m_weekday_short_names; + this->m_weekday_long_names = fdp.m_weekday_long_names; + } + + string_type format() const + { + return m_format; + } + + void format(string_type format_str) + { + m_format = format_str; + } + + void short_month_names(const input_collection_type& month_names) + { + m_month_short_names = parse_tree_type(month_names, 1); + } + void long_month_names(const input_collection_type& month_names) + { + m_month_long_names = parse_tree_type(month_names, 1); + } + void short_weekday_names(const input_collection_type& weekday_names) + { + m_weekday_short_names = parse_tree_type(weekday_names); + } + void long_weekday_names(const input_collection_type& weekday_names) + { + m_weekday_long_names = parse_tree_type(weekday_names); + } + + date_type + parse_date(const string_type& value, + const string_type& format_str, + const special_values_parser& sv_parser) const + { + stringstream_type ss; + ss << value; + stream_itr_type sitr(ss); + stream_itr_type stream_end; + return parse_date(sitr, stream_end, format_str, sv_parser); + } + + date_type + parse_date(std::istreambuf_iterator& sitr, + std::istreambuf_iterator& stream_end, + const special_values_parser& sv_parser) const + { + return parse_date(sitr, stream_end, m_format, sv_parser); + } + + /*! Of all the objects that the format_date_parser can parse, only a + * date can be a special value. Therefore, only parse_date checks + * for special_values. */ + date_type + parse_date(std::istreambuf_iterator& sitr, + std::istreambuf_iterator& stream_end, + string_type format_str, + const special_values_parser& sv_parser) const + { + bool use_current_char = false; + + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + charT current_char = *sitr; + + short year(0), month(0), day(0), day_of_year(0);// wkday(0); + /* Initialized the following to their minimum values. These intermediate + * objects are used so we get specific exceptions when part of the input + * is unparsable. + * Ex: "205-Jan-15" will throw a bad_year, "2005-Jsn-15"- bad_month, etc.*/ + year_type t_year(1400); + month_type t_month(1); + day_type t_day(1); + day_of_week_type wkday(0); + + + const_itr itr(format_str.begin()); + while (itr != format_str.end() && (sitr != stream_end)) { + if (*itr == '%') { + itr++; + if (*itr != '%') { + switch(*itr) { + case 'a': + { + //this value is just throw away. It could be used for + //error checking potentially, but it isn't helpful in + //actually constructing the date - we just need to get it + //out of the stream + match_results mr = m_weekday_short_names.match(sitr, stream_end); + if(mr.current_match == match_results::PARSE_ERROR) { + // check special_values + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast(mr.current_match)); + } + } + wkday = mr.current_match; + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'A': + { + //this value is just throw away. It could be used for + //error checking potentially, but it isn't helpful in + //actually constructing the date - we just need to get it + //out of the stream + match_results mr = m_weekday_long_names.match(sitr, stream_end); + if(mr.current_match == match_results::PARSE_ERROR) { + // check special_values + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast(mr.current_match)); + } + } + wkday = mr.current_match; + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'b': + { + match_results mr = m_month_short_names.match(sitr, stream_end); + if(mr.current_match == match_results::PARSE_ERROR) { + // check special_values + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast(mr.current_match)); + } + } + t_month = month_type(mr.current_match); + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'B': + { + match_results mr = m_month_long_names.match(sitr, stream_end); + if(mr.current_match == match_results::PARSE_ERROR) { + // check special_values + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast(mr.current_match)); + } + } + t_month = month_type(mr.current_match); + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'd': + { + match_results mr; + day = fixed_string_to_int(sitr, stream_end, mr, 2); + if(day == -1) { + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast(mr.current_match)); + } + } + t_day = day_type(day); + break; + } + case 'e': + { + match_results mr; + day = fixed_string_to_int(sitr, stream_end, mr, 2, ' '); + if(day == -1) { + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast(mr.current_match)); + } + } + t_day = day_type(day); + break; + } + case 'j': + { + match_results mr; + day_of_year = fixed_string_to_int(sitr, stream_end, mr, 3); + if(day_of_year == -1) { + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast(mr.current_match)); + } + } + // these next two lines are so we get an exception with bad input + day_of_year_type t_day_of_year(1); + t_day_of_year = day_of_year_type(day_of_year); + break; + } + case 'm': + { + match_results mr; + month = fixed_string_to_int(sitr, stream_end, mr, 2); + if(month == -1) { + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast(mr.current_match)); + } + } + t_month = month_type(month); + break; + } + case 'Y': + { + match_results mr; + year = fixed_string_to_int(sitr, stream_end, mr, 4); + if(year == -1) { + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast(mr.current_match)); + } + } + t_year = year_type(year); + break; + } + case 'y': + { + match_results mr; + year = fixed_string_to_int(sitr, stream_end, mr, 2); + if(year == -1) { + if(sv_parser.match(sitr, stream_end, mr)) { + return date_type(static_cast(mr.current_match)); + } + } + year += 2000; //make 2 digit years in this century + t_year = year_type(year); + break; + } + default: + {} //ignore those we don't understand + + }//switch + + } + else { // itr == '%', second consecutive + sitr++; + } + + itr++; //advance past format specifier + } + else { //skip past chars in format and in buffer + itr++; + if (use_current_char) { + use_current_char = false; + current_char = *sitr; + } + else { + sitr++; + } + } + } + + if (day_of_year > 0) { + date_type d(static_cast(year-1),12,31); //end of prior year + return d + duration_type(day_of_year); + } + + return date_type(t_year, t_month, t_day); // exceptions were thrown earlier + // if input was no good + } + + //! Throws bad_month if unable to parse + month_type + parse_month(std::istreambuf_iterator& sitr, + std::istreambuf_iterator& stream_end, + string_type format_str) const + { + match_results mr; + return parse_month(sitr, stream_end, format_str, mr); + } + + //! Throws bad_month if unable to parse + month_type + parse_month(std::istreambuf_iterator& sitr, + std::istreambuf_iterator& stream_end, + string_type format_str, + match_results& mr) const + { + bool use_current_char = false; + + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + charT current_char = *sitr; + + short month(0); + + const_itr itr(format_str.begin()); + while (itr != format_str.end() && (sitr != stream_end)) { + if (*itr == '%') { + itr++; + if (*itr != '%') { + switch(*itr) { + case 'b': + { + mr = m_month_short_names.match(sitr, stream_end); + month = mr.current_match; + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'B': + { + mr = m_month_long_names.match(sitr, stream_end); + month = mr.current_match; + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'm': + { + month = var_string_to_int(sitr, stream_end, 2); + // var_string_to_int returns -1 if parse failed. That will + // cause a bad_month exception to be thrown so we do nothing here + break; + } + default: + {} //ignore those we don't understand + + }//switch + + } + else { // itr == '%', second consecutive + sitr++; + } + + itr++; //advance past format specifier + } + else { //skip past chars in format and in buffer + itr++; + if (use_current_char) { + use_current_char = false; + current_char = *sitr; + } + else { + sitr++; + } + } + } + + return month_type(month); // throws bad_month exception when values are zero + } + + //! Expects 1 or 2 digits 1-31. Throws bad_day_of_month if unable to parse + day_type + parse_var_day_of_month(std::istreambuf_iterator& sitr, + std::istreambuf_iterator& stream_end) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + return day_type(var_string_to_int(sitr, stream_end, 2)); + } + //! Expects 2 digits 01-31. Throws bad_day_of_month if unable to parse + day_type + parse_day_of_month(std::istreambuf_iterator& sitr, + std::istreambuf_iterator& stream_end) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + //return day_type(var_string_to_int(sitr, stream_end, 2)); + match_results mr; + return day_type(fixed_string_to_int(sitr, stream_end, mr, 2)); + } + + day_of_week_type + parse_weekday(std::istreambuf_iterator& sitr, + std::istreambuf_iterator& stream_end, + string_type format_str) const + { + match_results mr; + return parse_weekday(sitr, stream_end, format_str, mr); + } + day_of_week_type + parse_weekday(std::istreambuf_iterator& sitr, + std::istreambuf_iterator& stream_end, + string_type format_str, + match_results& mr) const + { + bool use_current_char = false; + + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + charT current_char = *sitr; + + short wkday(0); + + const_itr itr(format_str.begin()); + while (itr != format_str.end() && (sitr != stream_end)) { + if (*itr == '%') { + itr++; + if (*itr != '%') { + switch(*itr) { + case 'a': + { + //this value is just throw away. It could be used for + //error checking potentially, but it isn't helpful in + //actually constructing the date - we just need to get it + //out of the stream + mr = m_weekday_short_names.match(sitr, stream_end); + wkday = mr.current_match; + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'A': + { + //this value is just throw away. It could be used for + //error checking potentially, but it isn't helpful in + //actually constructing the date - we just need to get it + //out of the stream + mr = m_weekday_long_names.match(sitr, stream_end); + wkday = mr.current_match; + if (mr.has_remaining()) { + current_char = mr.last_char(); + use_current_char = true; + } + break; + } + case 'w': + { + // weekday as number 0-6, Sunday == 0 + wkday = var_string_to_int(sitr, stream_end, 2); + break; + } + default: + {} //ignore those we don't understand + + }//switch + + } + else { // itr == '%', second consecutive + sitr++; + } + + itr++; //advance past format specifier + } + else { //skip past chars in format and in buffer + itr++; + if (use_current_char) { + use_current_char = false; + current_char = *sitr; + } + else { + sitr++; + } + } + } + + return day_of_week_type(wkday); // throws bad_day_of_month exception + // when values are zero + } + + //! throws bad_year if unable to parse + year_type + parse_year(std::istreambuf_iterator& sitr, + std::istreambuf_iterator& stream_end, + string_type format_str) const + { + match_results mr; + return parse_year(sitr, stream_end, format_str, mr); + } + + //! throws bad_year if unable to parse + year_type + parse_year(std::istreambuf_iterator& sitr, + std::istreambuf_iterator& stream_end, + string_type format_str, + match_results& mr) const + { + bool use_current_char = false; + + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + charT current_char = *sitr; + + unsigned short year(0); + + const_itr itr(format_str.begin()); + while (itr != format_str.end() && (sitr != stream_end)) { + if (*itr == '%') { + itr++; + if (*itr != '%') { + //match_results mr; + switch(*itr) { + case 'Y': + { + // year from 4 digit string + year = fixed_string_to_int(sitr, stream_end, mr, 4); + break; + } + case 'y': + { + // year from 2 digit string (no century) + year = fixed_string_to_int(sitr, stream_end, mr, 2); + year += 2000; //make 2 digit years in this century + break; + } + default: + {} //ignore those we don't understand + + }//switch + + } + else { // itr == '%', second consecutive + sitr++; + } + + itr++; //advance past format specifier + } + else { //skip past chars in format and in buffer + itr++; + if (use_current_char) { + use_current_char = false; + current_char = *sitr; + } + else { + sitr++; + } + } + } + + return year_type(year); // throws bad_year exception when values are zero + } + + + private: + string_type m_format; + parse_tree_type m_month_short_names; + parse_tree_type m_month_long_names; + parse_tree_type m_weekday_short_names; + parse_tree_type m_weekday_long_names; + +}; + +} } //namespace + +#endif + + + diff --git a/win32/include/boost/date_time/gregorian/conversion.hpp b/win32/include/boost/date_time/gregorian/conversion.hpp new file mode 100755 index 000000000..62543f2f2 --- /dev/null +++ b/win32/include/boost/date_time/gregorian/conversion.hpp @@ -0,0 +1,73 @@ +#ifndef _GREGORIAN__CONVERSION_HPP___ +#define _GREGORIAN__CONVERSION_HPP___ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/c_time.hpp" +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) +# if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) +# include "boost/date_time/gregorian/formatters_limited.hpp" +# else +# include "boost/date_time/gregorian/formatters.hpp" +# endif // BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS +#else +# include +# include "boost/date_time/gregorian/gregorian_io.hpp" +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO + +namespace boost { + +namespace gregorian { + + + //! Converts a date to a tm struct. Throws out_of_range exception if date is a special value + inline + std::tm to_tm(const date& d) + { + if(d.is_pos_infinity() || d.is_neg_infinity() || d.is_not_a_date()){ +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) + std::string s("tm unable to handle date value of " + to_simple_string(d)); + throw std::out_of_range(s); +#else + std::stringstream ss; + ss << "tm unable to handle date value of " << d; + throw std::out_of_range(ss.str()); +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO + } + std::tm datetm; + boost::gregorian::date::ymd_type ymd = d.year_month_day(); + datetm.tm_year = ymd.year-1900; + datetm.tm_mon = ymd.month-1; + datetm.tm_mday = ymd.day; + datetm.tm_wday = d.day_of_week(); + datetm.tm_yday = d.day_of_year()-1; + datetm.tm_hour = datetm.tm_min = datetm.tm_sec = 0; + datetm.tm_isdst = -1; // negative because not enough info to set tm_isdst + return datetm; + } + + //! Converts a tm structure into a date dropping the any time values. + inline + date date_from_tm(const std::tm& datetm) + { + return date(static_cast(datetm.tm_year+1900), + static_cast(datetm.tm_mon+1), + static_cast(datetm.tm_mday)); + } + + +} } //namespace boost::gregorian + + + + +#endif + diff --git a/win32/include/boost/date_time/gregorian/formatters.hpp b/win32/include/boost/date_time/gregorian/formatters.hpp new file mode 100755 index 000000000..0e14098e9 --- /dev/null +++ b/win32/include/boost/date_time/gregorian/formatters.hpp @@ -0,0 +1,162 @@ +#ifndef GREGORIAN_FORMATTERS_HPP___ +#define GREGORIAN_FORMATTERS_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/gregorian/gregorian_types.hpp" +#if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) +#include "boost/date_time/date_formatting_limited.hpp" +#else +#include "boost/date_time/date_formatting.hpp" +#endif +#include "boost/date_time/iso_format.hpp" +#include "boost/date_time/date_format_simple.hpp" + +/* NOTE: "to_*_string" code for older compilers, ones that define + * BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS, is located in + * formatters_limited.hpp + */ + +namespace boost { +namespace gregorian { + + // wrapper function for to_simple_(w)string(date) + template + inline + std::basic_string to_simple_string_type(const date& d) { + return date_time::date_formatter,charT>::date_to_string(d); + } + //! To YYYY-mmm-DD string where mmm 3 char month name. Example: 2002-Jan-01 + /*!\ingroup date_format + */ + inline std::string to_simple_string(const date& d) { + return to_simple_string_type(d); + } + + + // wrapper function for to_simple_(w)string(date_period) + template + inline std::basic_string to_simple_string_type(const date_period& d) { + typedef std::basic_string string_type; + charT b = '[', m = '/', e=']'; + + string_type d1(date_time::date_formatter,charT>::date_to_string(d.begin())); + string_type d2(date_time::date_formatter,charT>::date_to_string(d.last())); + return string_type(b + d1 + m + d2 + e); + } + //! Convert date period to simple string. Example: [2002-Jan-01/2002-Jan-02] + /*!\ingroup date_format + */ + inline std::string to_simple_string(const date_period& d) { + return to_simple_string_type(d); + } + + // wrapper function for to_iso_(w)string(date_period) + template + inline std::basic_string to_iso_string_type(const date_period& d) { + charT sep = '/'; + std::basic_string s(date_time::date_formatter,charT>::date_to_string(d.begin())); + return s + sep + date_time::date_formatter,charT>::date_to_string(d.last()); + } + //! Date period to iso standard format CCYYMMDD/CCYYMMDD. Example: 20021225/20021231 + /*!\ingroup date_format + */ + inline std::string to_iso_string(const date_period& d) { + return to_iso_string_type(d); + } + + + // wrapper function for to_iso_extended_(w)string(date) + template + inline std::basic_string to_iso_extended_string_type(const date& d) { + return date_time::date_formatter,charT>::date_to_string(d); + } + //! Convert to iso extended format string CCYY-MM-DD. Example 2002-12-31 + /*!\ingroup date_format + */ + inline std::string to_iso_extended_string(const date& d) { + return to_iso_extended_string_type(d); + } + + // wrapper function for to_iso_(w)string(date) + template + inline std::basic_string to_iso_string_type(const date& d) { + return date_time::date_formatter,charT>::date_to_string(d); + } + //! Convert to iso standard string YYYYMMDD. Example: 20021231 + /*!\ingroup date_format + */ + inline std::string to_iso_string(const date& d) { + return to_iso_string_type(d); + } + + + + + // wrapper function for to_sql_(w)string(date) + template + inline std::basic_string to_sql_string_type(const date& d) + { + date::ymd_type ymd = d.year_month_day(); + std::basic_ostringstream ss; + ss << ymd.year << "-" + << std::setw(2) << std::setfill(ss.widen('0')) + << ymd.month.as_number() //solves problem with gcc 3.1 hanging + << "-" + << std::setw(2) << std::setfill(ss.widen('0')) + << ymd.day; + return ss.str(); + } + inline std::string to_sql_string(const date& d) { + return to_sql_string_type(d); + } + + +#if !defined(BOOST_NO_STD_WSTRING) + //! Convert date period to simple string. Example: [2002-Jan-01/2002-Jan-02] + /*!\ingroup date_format + */ + inline std::wstring to_simple_wstring(const date_period& d) { + return to_simple_string_type(d); + } + //! To YYYY-mmm-DD string where mmm 3 char month name. Example: 2002-Jan-01 + /*!\ingroup date_format + */ + inline std::wstring to_simple_wstring(const date& d) { + return to_simple_string_type(d); + } + //! Date period to iso standard format CCYYMMDD/CCYYMMDD. Example: 20021225/20021231 + /*!\ingroup date_format + */ + inline std::wstring to_iso_wstring(const date_period& d) { + return to_iso_string_type(d); + } + //! Convert to iso extended format string CCYY-MM-DD. Example 2002-12-31 + /*!\ingroup date_format + */ + inline std::wstring to_iso_extended_wstring(const date& d) { + return to_iso_extended_string_type(d); + } + //! Convert to iso standard string YYYYMMDD. Example: 20021231 + /*!\ingroup date_format + */ + inline std::wstring to_iso_wstring(const date& d) { + return to_iso_string_type(d); + } + inline std::wstring to_sql_wstring(const date& d) { + return to_sql_string_type(d); + } +#endif // BOOST_NO_STD_WSTRING + +} } //namespace gregorian + + +#endif + diff --git a/win32/include/boost/date_time/gregorian/formatters_limited.hpp b/win32/include/boost/date_time/gregorian/formatters_limited.hpp new file mode 100755 index 000000000..12dc6abf9 --- /dev/null +++ b/win32/include/boost/date_time/gregorian/formatters_limited.hpp @@ -0,0 +1,81 @@ +#ifndef GREGORIAN_FORMATTERS_LIMITED_HPP___ +#define GREGORIAN_FORMATTERS_LIMITED_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/date_formatting_limited.hpp" +#include "boost/date_time/iso_format.hpp" +#include "boost/date_time/date_format_simple.hpp" +#include "boost/date_time/compiler_config.hpp" + +namespace boost { +namespace gregorian { + + //! To YYYY-mmm-DD string where mmm 3 char month name. Example: 2002-Jan-01 + /*!\ingroup date_format + */ + inline std::string to_simple_string(const date& d) { + return date_time::date_formatter >::date_to_string(d); + } + + //! Convert date period to simple string. Example: [2002-Jan-01/2002-Jan-02] + /*!\ingroup date_format + */ + inline std::string to_simple_string(const date_period& d) { + std::string s("["); + std::string d1(date_time::date_formatter >::date_to_string(d.begin())); + std::string d2(date_time::date_formatter >::date_to_string(d.last())); + return std::string("[" + d1 + "/" + d2 + "]"); + } + + //! Date period to iso standard format CCYYMMDD/CCYYMMDD. Example: 20021225/20021231 + /*!\ingroup date_format + */ + inline std::string to_iso_string(const date_period& d) { + std::string s(date_time::date_formatter >::date_to_string(d.begin())); + return s + "/" + date_time::date_formatter >::date_to_string(d.last()); + } + + + //! Convert to iso extended format string CCYY-MM-DD. Example 2002-12-31 + /*!\ingroup date_format + */ + inline std::string to_iso_extended_string(const date& d) { + return date_time::date_formatter >::date_to_string(d); + } + + //! Convert to iso standard string YYYYMMDD. Example: 20021231 + /*!\ingroup date_format + */ + inline std::string to_iso_string(const date& d) { + return date_time::date_formatter >::date_to_string(d); + } + + + + inline std::string to_sql_string(const date& d) + { + date::ymd_type ymd = d.year_month_day(); + std::ostringstream ss; + ss << ymd.year << "-" + << std::setw(2) << std::setfill('0') + << ymd.month.as_number() //solves problem with gcc 3.1 hanging + << "-" + << std::setw(2) << std::setfill('0') + << ymd.day; + return ss.str(); + } + + +} } //namespace gregorian + + +#endif + diff --git a/win32/include/boost/date_time/gregorian/greg_calendar.hpp b/win32/include/boost/date_time/gregorian/greg_calendar.hpp new file mode 100755 index 000000000..554f27b5b --- /dev/null +++ b/win32/include/boost/date_time/gregorian/greg_calendar.hpp @@ -0,0 +1,47 @@ +#ifndef GREGORIAN_GREGORIAN_CALENDAR_HPP__ +#define GREGORIAN_GREGORIAN_CALENDAR_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/greg_weekday.hpp" +#include "boost/date_time/gregorian/greg_day_of_year.hpp" +#include "boost/date_time/gregorian_calendar.hpp" +#include "boost/date_time/gregorian/greg_ymd.hpp" +#include "boost/date_time/int_adapter.hpp" + +namespace boost { +namespace gregorian { + + //!An internal date representation that includes infinities, not a date + typedef date_time::int_adapter fancy_date_rep; + + //! Gregorian calendar for this implementation, hard work in the base + class gregorian_calendar : + public date_time::gregorian_calendar_base { + public: + //! Type to hold a weekday (eg: Sunday, Monday,...) + typedef greg_weekday day_of_week_type; + //! Counter type from 1 to 366 for gregorian dates. + typedef greg_day_of_year_rep day_of_year_type; + //! Internal date representation that handles infinity, not a date + typedef fancy_date_rep date_rep_type; + //! Date rep implements the traits stuff as well + typedef fancy_date_rep date_traits_type; + + + private: + }; + +} } //namespace gregorian + + + + +#endif + diff --git a/win32/include/boost/date_time/gregorian/greg_date.hpp b/win32/include/boost/date_time/gregorian/greg_date.hpp new file mode 100755 index 000000000..f3622ab5c --- /dev/null +++ b/win32/include/boost/date_time/gregorian/greg_date.hpp @@ -0,0 +1,135 @@ +#ifndef GREG_DATE_HPP___ +#define GREG_DATE_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/date.hpp" +#include "boost/date_time/special_defs.hpp" +#include "boost/date_time/gregorian/greg_calendar.hpp" +#include "boost/date_time/gregorian/greg_duration.hpp" + +namespace boost { +namespace gregorian { + + //bring special enum values into the namespace + using date_time::special_values; + using date_time::not_special; + using date_time::neg_infin; + using date_time::pos_infin; + using date_time::not_a_date_time; + using date_time::max_date_time; + using date_time::min_date_time; + + //! A date type based on gregorian_calendar + /*! This class is the primary interface for programming with + greogorian dates. The is a lightweight type that can be + freely passed by value. All comparison operators are + supported. + \ingroup date_basics + */ + class date : public date_time::date + { + public: + typedef gregorian_calendar::year_type year_type; + typedef gregorian_calendar::month_type month_type; + typedef gregorian_calendar::day_type day_type; + typedef gregorian_calendar::day_of_year_type day_of_year_type; + typedef gregorian_calendar::ymd_type ymd_type; + typedef gregorian_calendar::date_rep_type date_rep_type; + typedef gregorian_calendar::date_int_type date_int_type; + typedef date_duration duration_type; +#if !defined(DATE_TIME_NO_DEFAULT_CONSTRUCTOR) + //! Default constructor constructs with not_a_date_time + date(): + date_time::date(date_rep_type::from_special(not_a_date_time)) + {} +#endif // DATE_TIME_NO_DEFAULT_CONSTRUCTOR + //! Main constructor with year, month, day + date(year_type y, month_type m, day_type d) + : date_time::date(y, m, d) + { + if (gregorian_calendar::end_of_month_day(y, m) < d) { + throw bad_day_of_month(std::string("Day of month is not valid for year")); + } + } + //! Constructor from a ymd_type structure + explicit date(const ymd_type& ymd) + : date_time::date(ymd) + {} + //! Needed copy constructor + explicit date(const date_int_type& rhs): + date_time::date(rhs) + {} + //! Needed copy constructor + explicit date(date_rep_type rhs): + date_time::date(rhs) + {} + //! Constructor for infinities, not a date, max and min date + explicit date(special_values sv): + date_time::date(date_rep_type::from_special(sv)) + { + if (sv == min_date_time) + { + *this = date(1400, 1, 1); + } + if (sv == max_date_time) + { + *this = date(9999, 12, 31); + } + + } + //!Return the Julian Day number for the date. + date_int_type julian_day() const + { + ymd_type ymd = year_month_day(); + return gregorian_calendar::julian_day_number(ymd); + } + //!Return the day of year 1..365 or 1..366 (for leap year) + day_of_year_type day_of_year() const + { + date start_of_year(year(), 1, 1); + unsigned short doy = static_cast((*this-start_of_year).days() + 1); + return day_of_year_type(doy); + } + //!Return the Modified Julian Day number for the date. + long modjulian_day() const + { + ymd_type ymd = year_month_day(); + return gregorian_calendar::modjulian_day_number(ymd); + } + //!Return the iso 8601 week number 1..53 + int week_number() const + { + ymd_type ymd = year_month_day(); + return gregorian_calendar::week_number(ymd); + } + //! Return the day number from the calendar + date_int_type day_number() const + { + return days_; + } + //! Return the last day of the current month + date end_of_month() const + { + ymd_type ymd = year_month_day(); + short eom_day = gregorian_calendar::end_of_month_day(ymd.year, ymd.month); + return date(ymd.year, ymd.month, eom_day); + } + + private: + + }; + + + +} } //namespace gregorian + + + +#endif diff --git a/win32/include/boost/date_time/gregorian/greg_day.hpp b/win32/include/boost/date_time/gregorian/greg_day.hpp new file mode 100755 index 000000000..fede06760 --- /dev/null +++ b/win32/include/boost/date_time/gregorian/greg_day.hpp @@ -0,0 +1,57 @@ +#ifndef GREG_DAY_HPP___ +#define GREG_DAY_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/constrained_value.hpp" +#include +#include + +namespace boost { +namespace gregorian { + + //! Exception type for gregorian day of month (1..31) + struct bad_day_of_month : public std::out_of_range + { + bad_day_of_month() : + std::out_of_range(std::string("Day of month value is out of range 1..31")) + {} + //! Allow other classes to throw with unique string for bad day like Feb 29 + bad_day_of_month(const std::string& s) : + std::out_of_range(s) + {} + }; + //! Policy class that declares error handling and day of month ranges + typedef CV::simple_exception_policy greg_day_policies; + + //! Generated represetation for gregorian day of month + typedef CV::constrained_value greg_day_rep; + + //! Represent a day of the month (range 1 - 31) + /*! This small class allows for simple conversion an integer value into + a day of the month for a standard gregorian calendar. The type + is automatically range checked so values outside of the range 1-31 + will cause a bad_day_of_month exception + */ + class greg_day : public greg_day_rep { + public: + greg_day(unsigned short day_of_month) : greg_day_rep(day_of_month) {} + unsigned short as_number() const {return value_;} + operator unsigned short() const {return value_;} + private: + + }; + + + +} } //namespace gregorian + + + +#endif diff --git a/win32/include/boost/date_time/gregorian/greg_day_of_year.hpp b/win32/include/boost/date_time/gregorian/greg_day_of_year.hpp new file mode 100755 index 000000000..b0057a3c0 --- /dev/null +++ b/win32/include/boost/date_time/gregorian/greg_day_of_year.hpp @@ -0,0 +1,38 @@ +#ifndef GREG_DAY_OF_YEAR_HPP___ +#define GREG_DAY_OF_YEAR_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/constrained_value.hpp" +#include +#include + +namespace boost { +namespace gregorian { + + //! Exception type for day of year (1..366) + struct bad_day_of_year : public std::out_of_range + { + bad_day_of_year() : + std::out_of_range(std::string("Day of year value is out of range 1..366")) + {} + }; + + //! A day of the year range (1..366) + typedef CV::simple_exception_policy greg_day_of_year_policies; + + //! Define a range representation type for the day of the year 1..366 + typedef CV::constrained_value greg_day_of_year_rep; + + +} } //namespace gregorian + + + +#endif diff --git a/win32/include/boost/date_time/gregorian/greg_duration.hpp b/win32/include/boost/date_time/gregorian/greg_duration.hpp new file mode 100755 index 000000000..2c53d1020 --- /dev/null +++ b/win32/include/boost/date_time/gregorian/greg_duration.hpp @@ -0,0 +1,38 @@ +#ifndef GREG_DURATION_HPP___ +#define GREG_DURATION_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/date_duration.hpp" +#if defined(BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES) +#include "boost/date_time/date_duration_types.hpp" +#endif +#include "boost/date_time/int_adapter.hpp" + + +namespace boost { +namespace gregorian { + + + //!An internal date representation that includes infinities, not a date + typedef boost::date_time::duration_traits_adapted date_duration_rep; + + //! Durations in days for gregorian system + /*! \ingroup date_basics + */ + typedef date_time::date_duration date_duration; + + //! Shorthand for date_duration + typedef date_duration days; + +} } //namespace gregorian + + + +#endif diff --git a/win32/include/boost/date_time/gregorian/greg_duration_types.hpp b/win32/include/boost/date_time/gregorian/greg_duration_types.hpp new file mode 100755 index 000000000..fa3654d78 --- /dev/null +++ b/win32/include/boost/date_time/gregorian/greg_duration_types.hpp @@ -0,0 +1,34 @@ +#ifndef GREG_DURATION_TYPES_HPP___ +#define GREG_DURATION_TYPES_HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Subject to Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/gregorian/greg_date.hpp" +#include "boost/date_time/int_adapter.hpp" +#include "boost/date_time/adjust_functors.hpp" +#include "boost/date_time/date_duration.hpp" +#include "boost/date_time/date_duration_types.hpp" + +namespace boost { +namespace gregorian { + + //! config struct for additional duration types (ie months_duration<> & years_duration<>) + struct greg_durations_config { + typedef date date_type; + typedef date_time::int_adapter int_rep; + typedef date_time::month_functor month_adjustor_type; + }; + + typedef date_time::months_duration months; + typedef date_time::years_duration years; + typedef date_time::weeks_duration weeks; + +}} // namespace boost::gregorian + +#endif // GREG_DURATION_TYPES_HPP___ diff --git a/win32/include/boost/date_time/gregorian/greg_facet.hpp b/win32/include/boost/date_time/gregorian/greg_facet.hpp new file mode 100755 index 000000000..daee3ad34 --- /dev/null +++ b/win32/include/boost/date_time/gregorian/greg_facet.hpp @@ -0,0 +1,351 @@ +#ifndef GREGORIAN_FACET_HPP___ +#define GREGORIAN_FACET_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/date_formatting_locales.hpp" // sets BOOST_DATE_TIME_NO_LOCALE +#include "boost/date_time/gregorian/parsers.hpp" +#include +#include + +//This file is basically commented out if locales are not supported +#ifndef BOOST_DATE_TIME_NO_LOCALE + + +namespace boost { +namespace gregorian { + + //! Configuration of the output facet template + struct greg_facet_config + { + typedef boost::gregorian::greg_month month_type; + typedef boost::date_time::special_values special_value_enum; + typedef boost::gregorian::months_of_year month_enum; + typedef boost::date_time::weekdays weekday_enum; + }; + +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) + //! Create the base facet type for gregorian::date + typedef boost::date_time::date_names_put greg_base_facet; + + //! ostream operator for gregorian::date + /*! Uses the date facet to determine various output parameters including: + * - string values for the month (eg: Jan, Feb, Mar) (default: English) + * - string values for special values (eg: not-a-date-time) (default: English) + * - selection of long, short strings, or numerical month representation (default: short string) + * - month day year order (default yyyy-mmm-dd) + */ + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const date& d) + { + typedef boost::date_time::date_names_put facet_def; + typedef boost::date_time::ostream_date_formatter greg_ostream_formatter; + greg_ostream_formatter::date_put(d, os); + return os; + } + + //! operator<< for gregorian::greg_month typically streaming: Jan, Feb, Mar... + /*! Uses the date facet to determine output string as well as selection of long or short strings. + * Default if no facet is installed is to output a 2 wide numeric value for the month + * eg: 01 == Jan, 02 == Feb, ... 12 == Dec. + */ + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const greg_month& m) + { + typedef boost::date_time::date_names_put facet_def; + typedef boost::date_time::ostream_month_formatter greg_month_formatter; + std::locale locale = os.getloc(); + if (std::has_facet(locale)) { + const facet_def& f = std::use_facet(locale); + greg_month_formatter::format_month(m, os, f); + + } + else { //default to numeric + charT fill_char = '0'; + os << std::setw(2) << std::setfill(fill_char) << m.as_number(); + } + + return os; + } + + //! operator<< for gregorian::greg_weekday typically streaming: Sun, Mon, Tue, ... + /*! Uses the date facet to determine output string as well as selection of long or short string. + * Default if no facet is installed is to output a 3 char english string for the + * day of the week. + */ + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const greg_weekday& wd) + { + typedef boost::date_time::date_names_put facet_def; + typedef boost::date_time::ostream_weekday_formatter greg_weekday_formatter; + std::locale locale = os.getloc(); + if (std::has_facet(locale)) { + const facet_def& f = std::use_facet(locale); + greg_weekday_formatter::format_weekday(wd.as_enum(), os, f, true); + } + else { //default to short English string eg: Sun, Mon, Tue, Wed... + os << wd.as_short_string(); + } + + return os; + } + + //! operator<< for gregorian::date_period typical output: [2002-Jan-01/2002-Jan-31] + /*! Uses the date facet to determine output string as well as selection of long + * or short string fr dates. + * Default if no facet is installed is to output a 3 char english string for the + * day of the week. + */ + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const date_period& dp) + { + os << '['; //TODO: facet or manipulator for periods? + os << dp.begin(); + os << '/'; //TODO: facet or manipulator for periods? + os << dp.last(); + os << ']'; + return os; + } + + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const date_duration& dd) + { + //os << dd.days(); + os << dd.get_rep(); + return os; + } + + //! operator<< for gregorian::partial_date. Output: "Jan 1" + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const partial_date& pd) + { + os << std::setw(2) << std::setfill('0') << pd.day() << ' ' + << pd.month().as_short_string() ; + return os; + } + + //! operator<< for gregorian::nth_kday_of_month. Output: "first Mon of Jun" + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, + const nth_kday_of_month& nkd) + { + os << nkd.nth_week_as_str() << ' ' + << nkd.day_of_week() << " of " + << nkd.month().as_short_string() ; + return os; + } + + //! operator<< for gregorian::first_kday_of_month. Output: "first Mon of Jun" + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, + const first_kday_of_month& fkd) + { + os << "first " << fkd.day_of_week() << " of " + << fkd.month().as_short_string() ; + return os; + } + + //! operator<< for gregorian::last_kday_of_month. Output: "last Mon of Jun" + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, + const last_kday_of_month& lkd) + { + os << "last " << lkd.day_of_week() << " of " + << lkd.month().as_short_string() ; + return os; + } + + //! operator<< for gregorian::first_kday_after. Output: "first Mon after" + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, + const first_kday_after& fka) + { + os << fka.day_of_week() << " after"; + return os; + } + + //! operator<< for gregorian::first_kday_before. Output: "first Mon before" + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, + const first_kday_before& fkb) + { + os << fkb.day_of_week() << " before"; + return os; + } +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO + /**************** Input Streaming ******************/ + +#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) + //! operator>> for gregorian::date + template + inline + std::basic_istream& operator>>(std::basic_istream& is, date& d) + { + std::istream_iterator, charT> beg(is), eos; + + typedef boost::date_time::all_date_names_put facet_def; + d = from_stream(beg, eos); + return is; + } +#endif // BOOST_NO_STD_ITERATOR_TRAITS + + //! operator>> for gregorian::date_duration + template + inline + std::basic_istream& operator>>(std::basic_istream& is, + date_duration& dd) + { + long v; + is >> v; + dd = date_duration(v); + return is; + } + + //! operator>> for gregorian::date_period + template + inline + std::basic_istream& operator>>(std::basic_istream& is, + date_period& dp) + { + std::basic_string s; + is >> s; + dp = date_time::from_simple_string_type(s); + return is; + } + + //! generates a locale with the set of gregorian name-strings of type char* + BOOST_DATE_TIME_DECL std::locale generate_locale(std::locale& loc, char type); + + //! Returns a pointer to a facet with a default set of names (English) + /* Necessary in the event an exception is thrown from op>> for + * weekday or month. See comments in those functions for more info */ + BOOST_DATE_TIME_DECL boost::date_time::all_date_names_put* create_facet_def(char type); + +#ifndef BOOST_NO_STD_WSTRING + //! generates a locale with the set of gregorian name-strings of type wchar_t* + BOOST_DATE_TIME_DECL std::locale generate_locale(std::locale& loc, wchar_t type); + //! Returns a pointer to a facet with a default set of names (English) + /* Necessary in the event an exception is thrown from op>> for + * weekday or month. See comments in those functions for more info */ + BOOST_DATE_TIME_DECL boost::date_time::all_date_names_put* create_facet_def(wchar_t type); +#endif // BOOST_NO_STD_WSTRING + + //! operator>> for gregorian::greg_month - throws exception if invalid month given + template + inline + std::basic_istream& operator>>(std::basic_istream& is,greg_month& m) + { + typedef boost::date_time::all_date_names_put facet_def; + + std::basic_string s; + is >> s; + + if(!std::has_facet(is.getloc())) { + std::locale loc = is.getloc(); + charT a = '\0'; + is.imbue(generate_locale(loc, a)); + } + + short num = 0; + + try{ + const facet_def& f = std::use_facet(is.getloc()); + num = date_time::find_match(f.get_short_month_names(), + f.get_long_month_names(), + (greg_month::max)(), s); + } + /* bad_cast will be thrown if the desired facet is not accessible + * so we can generate the facet. This has the drawback of using english + * names as a default. */ + catch(std::bad_cast bc){ + std::cout << "Month exception caught" << std::endl; + charT a = '\0'; + const facet_def* f = create_facet_def(a); + num = date_time::find_match(f->get_short_month_names(), + f->get_long_month_names(), + (greg_month::max)(), s); + delete(f); + } + + num += 1; // months numbered 1-12 + m = greg_month(num); + + return is; + } + + //! operator>> for gregorian::greg_weekday - throws exception if invalid weekday given + template + inline + std::basic_istream& operator>>(std::basic_istream& is,greg_weekday& wd) + { + typedef boost::date_time::all_date_names_put facet_def; + + std::basic_string s; + is >> s; + + if(!std::has_facet(is.getloc())) { + std::locale loc = is.getloc(); + charT a = '\0'; + is.imbue(generate_locale(loc, a)); + } + + short num = 0; + try{ + const facet_def& f = std::use_facet(is.getloc()); + num = date_time::find_match(f.get_short_weekday_names(), + f.get_long_weekday_names(), + (greg_weekday::max)(), s); + } + /* bad_cast will be thrown if the desired facet is not accessible + * so we can generate the facet. This has the drawback of using english + * names as a default. */ + catch(std::bad_cast bc){ + //std::cout << "Weekday exception caught" << std::endl; + charT a = '\0'; + const facet_def* f = create_facet_def(a); + num = date_time::find_match(f->get_short_weekday_names(), + f->get_long_weekday_names(), + (greg_weekday::max)(), s); + delete(f); + } + + wd = greg_weekday(num); // weekdays numbered 0-6 + return is; + } + +} } //namespace gregorian + +#endif + + +#endif + diff --git a/win32/include/boost/date_time/gregorian/greg_month.hpp b/win32/include/boost/date_time/gregorian/greg_month.hpp new file mode 100755 index 000000000..0a07a8d09 --- /dev/null +++ b/win32/include/boost/date_time/gregorian/greg_month.hpp @@ -0,0 +1,105 @@ +#ifndef GREG_MONTH_HPP___ +#define GREG_MONTH_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/constrained_value.hpp" +#include "boost/date_time/date_defs.hpp" +#include "boost/shared_ptr.hpp" +#include "boost/date_time/compiler_config.hpp" +#include +#include +#include +#include +#include + +namespace boost { +namespace gregorian { + + typedef date_time::months_of_year months_of_year; + + //bring enum values into the namespace + using date_time::Jan; + using date_time::Feb; + using date_time::Mar; + using date_time::Apr; + using date_time::May; + using date_time::Jun; + using date_time::Jul; + using date_time::Aug; + using date_time::Sep; + using date_time::Oct; + using date_time::Nov; + using date_time::Dec; + using date_time::NotAMonth; + using date_time::NumMonths; + + //! Exception thrown if a greg_month is constructed with a value out of range + struct bad_month : public std::out_of_range + { + bad_month() : std::out_of_range(std::string("Month number is out of range 1..12")) {} + }; + //! Build a policy class for the greg_month_rep + typedef CV::simple_exception_policy greg_month_policies; + //! A constrained range that implements the gregorian_month rules + typedef CV::constrained_value greg_month_rep; + + + //! Wrapper class to represent months in gregorian based calendar + class BOOST_DATE_TIME_DECL greg_month : public greg_month_rep { + public: + typedef date_time::months_of_year month_enum; + typedef std::map month_map_type; + typedef boost::shared_ptr month_map_ptr_type; + //! Construct a month from the months_of_year enumeration + greg_month(month_enum theMonth) : + greg_month_rep(static_cast(theMonth)) {} + //! Construct from a short value + greg_month(unsigned short theMonth) : greg_month_rep(theMonth) {} + //! Convert the value back to a short + operator unsigned short() const {return value_;} + //! Returns month as number from 1 to 12 + unsigned short as_number() const {return value_;} + month_enum as_enum() const {return static_cast(value_);} + const char* as_short_string() const; + const char* as_long_string() const; +#ifndef BOOST_NO_STD_WSTRING + const wchar_t* as_short_wstring() const; + const wchar_t* as_long_wstring() const; +#endif // BOOST_NO_STD_WSTRING + //! Shared pointer to a map of Month strings (Names & Abbrev) & numbers + static month_map_ptr_type get_month_map_ptr(); + + /* parameterized as_*_string functions are intended to be called + * from a template function: "... as_short_string(charT c='\0');" */ + const char* as_short_string(char) const + { + return as_short_string(); + } + const char* as_long_string(char) const + { + return as_long_string(); + } +#ifndef BOOST_NO_STD_WSTRING + const wchar_t* as_short_string(wchar_t) const + { + return as_short_wstring(); + } + const wchar_t* as_long_string(wchar_t) const + { + return as_long_wstring(); + } +#endif // BOOST_NO_STD_WSTRING + }; + +} } //namespace gregorian + + + +#endif diff --git a/win32/include/boost/date_time/gregorian/greg_serialize.hpp b/win32/include/boost/date_time/gregorian/greg_serialize.hpp new file mode 100755 index 000000000..6d660c909 --- /dev/null +++ b/win32/include/boost/date_time/gregorian/greg_serialize.hpp @@ -0,0 +1,489 @@ +#ifndef GREGORIAN_SERIALIZE_HPP___ +#define GREGORIAN_SERIALIZE_HPP___ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/gregorian/parsers.hpp" +#include "boost/serialization/split_free.hpp" + + +// macros to split serialize functions into save & load functions +// An expanded version is below for gregorian::date +// NOTE: these macros define template functions in the boost::serialization namespace. +// They must be expanded *outside* of any namespace +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::date_duration) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::date_duration::duration_rep) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::date_period) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::greg_month) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::greg_day) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::greg_weekday) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::partial_date) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::nth_kday_of_month) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::first_kday_of_month) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::last_kday_of_month) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::first_kday_before) +BOOST_SERIALIZATION_SPLIT_FREE(::boost::gregorian::first_kday_after) + +namespace boost { +namespace serialization { + +/*! Method that does serialization for gregorian::date -- splits to load/save + */ +template +inline void serialize(Archive & ar, + ::boost::gregorian::date & d, + const unsigned int file_version) +{ + split_free(ar, d, file_version); +} + +//! Function to save gregorian::date objects using serialization lib +/*! Dates are serialized into a string for transport and storage. + * While it would be more efficient to store the internal + * integer used to manipulate the dates, it is an unstable solution. + */ +template +void save(Archive & ar, + const ::boost::gregorian::date & d, + unsigned int /* version */) +{ + std::string ds = to_iso_string(d); + ar & make_nvp("date", ds); +} + +//! Function to load gregorian::date objects using serialization lib +/*! Dates are serialized into a string for transport and storage. + * While it would be more efficient to store the internal + * integer used to manipulate the dates, it is an unstable solution. + */ +template +void load(Archive & ar, + ::boost::gregorian::date & d, + unsigned int /*version*/) +{ + std::string ds; + ar & make_nvp("date", ds); + try{ + d = ::boost::gregorian::from_undelimited_string(ds); + }catch(bad_lexical_cast be) { + gregorian::special_values sv = gregorian::special_value_from_string(ds); + if(sv == gregorian::not_special) { + throw(be); // no match found, rethrow original exception + } + else { + d = gregorian::date(sv); + } + } +} + + +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, + ::boost::gregorian::date* dp, + const unsigned int /*file_version*/) +{ + // retrieve data from archive required to construct new + // invoke inplace constructor to initialize instance of date + ::new(dp) ::boost::gregorian::date(::boost::gregorian::not_a_date_time); +} + +/**** date_duration ****/ + +//! Function to save gregorian::date_duration objects using serialization lib +template +void save(Archive & ar, const gregorian::date_duration & dd, + unsigned int /*version*/) +{ + typename gregorian::date_duration::duration_rep dr = dd.get_rep(); + ar & make_nvp("date_duration", dr); +} +//! Function to load gregorian::date_duration objects using serialization lib +template +void load(Archive & ar, gregorian::date_duration & dd, unsigned int /*version*/) +{ + typename gregorian::date_duration::duration_rep dr(0); + ar & make_nvp("date_duration", dr); + dd = gregorian::date_duration(dr); +} +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, gregorian::date_duration* dd, + const unsigned int /*file_version*/) +{ + ::new(dd) gregorian::date_duration(gregorian::not_a_date_time); +} + +/**** date_duration::duration_rep (most likely int_adapter) ****/ + +//! helper unction to save date_duration objects using serialization lib +template +void save(Archive & ar, const gregorian::date_duration::duration_rep & dr, + unsigned int /*version*/) +{ + typename gregorian::date_duration::duration_rep::int_type it = dr.as_number(); + ar & make_nvp("date_duration_duration_rep", it); +} +//! helper function to load date_duration objects using serialization lib +template +void load(Archive & ar, gregorian::date_duration::duration_rep & dr, unsigned int /*version*/) +{ + typename gregorian::date_duration::duration_rep::int_type it(0); + ar & make_nvp("date_duration_duration_rep", it); + dr = gregorian::date_duration::duration_rep::int_type(it); +} +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, gregorian::date_duration::duration_rep* dr, + const unsigned int /*file_version*/) +{ + ::new(dr) gregorian::date_duration::duration_rep(0); +} + +/**** date_period ****/ + +//! Function to save gregorian::date_period objects using serialization lib +/*! date_period objects are broken down into 2 parts for serialization: + * the begining date object and the end date object + */ +template +void save(Archive & ar, const gregorian::date_period& dp, + unsigned int /*version*/) +{ + gregorian::date d1 = dp.begin(); + gregorian::date d2 = dp.end(); + ar & make_nvp("date_period_begin_date", d1); + ar & make_nvp("date_period_end_date", d2); +} +//! Function to load gregorian::date_period objects using serialization lib +/*! date_period objects are broken down into 2 parts for serialization: + * the begining date object and the end date object + */ +template +void load(Archive & ar, gregorian::date_period& dp, unsigned int /*version*/) +{ + gregorian::date d1(gregorian::not_a_date_time); + gregorian::date d2(gregorian::not_a_date_time); + ar & make_nvp("date_period_begin_date", d1); + ar & make_nvp("date_period_end_date", d2); + dp = gregorian::date_period(d1,d2); +} +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, gregorian::date_period* dp, + const unsigned int /*file_version*/) +{ + gregorian::date d(gregorian::not_a_date_time); + gregorian::date_duration dd(1); + ::new(dp) gregorian::date_period(d,dd); +} + +/**** greg_month ****/ + +//! Function to save gregorian::greg_month objects using serialization lib +template +void save(Archive & ar, const gregorian::greg_month& gm, + unsigned int /*version*/) +{ + unsigned short us = gm.as_number(); + ar & make_nvp("greg_month", us); +} +//! Function to load gregorian::greg_month objects using serialization lib +template +void load(Archive & ar, gregorian::greg_month& gm, unsigned int /*version*/) +{ + unsigned short us; + ar & make_nvp("greg_month", us); + gm = gregorian::greg_month(us); +} +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, gregorian::greg_month* gm, + const unsigned int /*file_version*/) +{ + ::new(gm) gregorian::greg_month(1); +} + +/**** greg_day ****/ + +//! Function to save gregorian::greg_day objects using serialization lib +template +void save(Archive & ar, const gregorian::greg_day& gd, + unsigned int /*version*/) +{ + unsigned short us = gd.as_number(); + ar & make_nvp("greg_day", us); +} +//! Function to load gregorian::greg_day objects using serialization lib +template +void load(Archive & ar, gregorian::greg_day& gd, unsigned int /*version*/) +{ + unsigned short us; + ar & make_nvp("greg_day", us); + gd = gregorian::greg_day(us); +} +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, gregorian::greg_day* gd, + const unsigned int /*file_version*/) +{ + ::new(gd) gregorian::greg_day(1); +} + +/**** greg_weekday ****/ + +//! Function to save gregorian::greg_weekday objects using serialization lib +template +void save(Archive & ar, const gregorian::greg_weekday& gd, + unsigned int /*version*/) +{ + unsigned short us = gd.as_number(); + ar & make_nvp("greg_weekday", us); +} +//! Function to load gregorian::greg_weekday objects using serialization lib +template +void load(Archive & ar, gregorian::greg_weekday& gd, unsigned int /*version*/) +{ + unsigned short us; + ar & make_nvp("greg_weekday", us); + gd = gregorian::greg_weekday(us); +} +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, gregorian::greg_weekday* gd, + const unsigned int /*file_version*/) +{ + ::new(gd) gregorian::greg_weekday(1); +} + +/**** date_generators ****/ + +/**** partial_date ****/ + +//! Function to save gregorian::partial_date objects using serialization lib +/*! partial_date objects are broken down into 2 parts for serialization: + * the day (typically greg_day) and month (typically greg_month) objects + */ +template +void save(Archive & ar, const gregorian::partial_date& pd, + unsigned int /*version*/) +{ + gregorian::greg_day gd(pd.day()); + gregorian::greg_month gm(pd.month().as_number()); + ar & make_nvp("partial_date_day", gd); + ar & make_nvp("partial_date_month", gm); +} +//! Function to load gregorian::partial_date objects using serialization lib +/*! partial_date objects are broken down into 2 parts for serialization: + * the day (greg_day) and month (greg_month) objects + */ +template +void load(Archive & ar, gregorian::partial_date& pd, unsigned int /*version*/) +{ + gregorian::greg_day gd(1); + gregorian::greg_month gm(1); + ar & make_nvp("partial_date_day", gd); + ar & make_nvp("partial_date_month", gm); + pd = gregorian::partial_date(gd,gm); +} +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, gregorian::partial_date* pd, + const unsigned int /*file_version*/) +{ + gregorian::greg_month gm(1); + gregorian::greg_day gd(1); + ::new(pd) gregorian::partial_date(gd,gm); +} + +/**** nth_kday_of_month ****/ + +//! Function to save nth_day_of_the_week_in_month objects using serialization lib +/*! nth_day_of_the_week_in_month objects are broken down into 3 parts for + * serialization: the week number, the day of the week, and the month + */ +template +void save(Archive & ar, const gregorian::nth_kday_of_month& nkd, + unsigned int /*version*/) +{ + typename gregorian::nth_kday_of_month::week_num wn(nkd.nth_week()); + typename gregorian::nth_kday_of_month::day_of_week_type d(nkd.day_of_week().as_number()); + typename gregorian::nth_kday_of_month::month_type m(nkd.month().as_number()); + ar & make_nvp("nth_kday_of_month_week_num", wn); + ar & make_nvp("nth_kday_of_month_day_of_week", d); + ar & make_nvp("nth_kday_of_month_month", m); +} +//! Function to load nth_day_of_the_week_in_month objects using serialization lib +/*! nth_day_of_the_week_in_month objects are broken down into 3 parts for + * serialization: the week number, the day of the week, and the month + */ +template +void load(Archive & ar, gregorian::nth_kday_of_month& nkd, unsigned int /*version*/) +{ + typename gregorian::nth_kday_of_month::week_num wn(gregorian::nth_kday_of_month::first); + typename gregorian::nth_kday_of_month::day_of_week_type d(gregorian::Monday); + typename gregorian::nth_kday_of_month::month_type m(gregorian::Jan); + ar & make_nvp("nth_kday_of_month_week_num", wn); + ar & make_nvp("nth_kday_of_month_day_of_week", d); + ar & make_nvp("nth_kday_of_month_month", m); + + nkd = gregorian::nth_kday_of_month(wn,d,m); +} +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, + gregorian::nth_kday_of_month* nkd, + const unsigned int /*file_version*/) +{ + // values used are not significant + ::new(nkd) gregorian::nth_kday_of_month(gregorian::nth_kday_of_month::first, + gregorian::Monday,gregorian::Jan); +} + +/**** first_kday_of_month ****/ + +//! Function to save first_day_of_the_week_in_month objects using serialization lib +/*! first_day_of_the_week_in_month objects are broken down into 2 parts for + * serialization: the day of the week, and the month + */ +template +void save(Archive & ar, const gregorian::first_kday_of_month& fkd, + unsigned int /*version*/) +{ + typename gregorian::first_kday_of_month::day_of_week_type d(fkd.day_of_week().as_number()); + typename gregorian::first_kday_of_month::month_type m(fkd.month().as_number()); + ar & make_nvp("first_kday_of_month_day_of_week", d); + ar & make_nvp("first_kday_of_month_month", m); +} +//! Function to load first_day_of_the_week_in_month objects using serialization lib +/*! first_day_of_the_week_in_month objects are broken down into 2 parts for + * serialization: the day of the week, and the month + */ +template +void load(Archive & ar, gregorian::first_kday_of_month& fkd, unsigned int /*version*/) +{ + typename gregorian::first_kday_of_month::day_of_week_type d(gregorian::Monday); + typename gregorian::first_kday_of_month::month_type m(gregorian::Jan); + ar & make_nvp("first_kday_of_month_day_of_week", d); + ar & make_nvp("first_kday_of_month_month", m); + + fkd = gregorian::first_kday_of_month(d,m); +} +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, + gregorian::first_kday_of_month* fkd, + const unsigned int /*file_version*/) +{ + // values used are not significant + ::new(fkd) gregorian::first_kday_of_month(gregorian::Monday,gregorian::Jan); +} + +/**** last_kday_of_month ****/ + +//! Function to save last_day_of_the_week_in_month objects using serialization lib +/*! last_day_of_the_week_in_month objects are broken down into 2 parts for + * serialization: the day of the week, and the month + */ +template +void save(Archive & ar, const gregorian::last_kday_of_month& lkd, + unsigned int /*version*/) +{ + typename gregorian::last_kday_of_month::day_of_week_type d(lkd.day_of_week().as_number()); + typename gregorian::last_kday_of_month::month_type m(lkd.month().as_number()); + ar & make_nvp("last_kday_of_month_day_of_week", d); + ar & make_nvp("last_kday_of_month_month", m); +} +//! Function to load last_day_of_the_week_in_month objects using serialization lib +/*! last_day_of_the_week_in_month objects are broken down into 2 parts for + * serialization: the day of the week, and the month + */ +template +void load(Archive & ar, gregorian::last_kday_of_month& lkd, unsigned int /*version*/) +{ + typename gregorian::last_kday_of_month::day_of_week_type d(gregorian::Monday); + typename gregorian::last_kday_of_month::month_type m(gregorian::Jan); + ar & make_nvp("last_kday_of_month_day_of_week", d); + ar & make_nvp("last_kday_of_month_month", m); + + lkd = gregorian::last_kday_of_month(d,m); +} +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, + gregorian::last_kday_of_month* lkd, + const unsigned int /*file_version*/) +{ + // values used are not significant + ::new(lkd) gregorian::last_kday_of_month(gregorian::Monday,gregorian::Jan); +} + +/**** first_kday_before ****/ + +//! Function to save first_day_of_the_week_before objects using serialization lib +template +void save(Archive & ar, const gregorian::first_kday_before& fkdb, + unsigned int /*version*/) +{ + typename gregorian::first_kday_before::day_of_week_type d(fkdb.day_of_week().as_number()); + ar & make_nvp("first_kday_before_day_of_week", d); +} +//! Function to load first_day_of_the_week_before objects using serialization lib +template +void load(Archive & ar, gregorian::first_kday_before& fkdb, unsigned int /*version*/) +{ + typename gregorian::first_kday_before::day_of_week_type d(gregorian::Monday); + ar & make_nvp("first_kday_before_day_of_week", d); + + fkdb = gregorian::first_kday_before(d); +} +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, + gregorian::first_kday_before* fkdb, + const unsigned int /*file_version*/) +{ + // values used are not significant + ::new(fkdb) gregorian::first_kday_before(gregorian::Monday); +} + +/**** first_kday_after ****/ + +//! Function to save first_day_of_the_week_after objects using serialization lib +template +void save(Archive & ar, const gregorian::first_kday_after& fkda, + unsigned int /*version*/) +{ + typename gregorian::first_kday_after::day_of_week_type d(fkda.day_of_week().as_number()); + ar & make_nvp("first_kday_after_day_of_week", d); +} +//! Function to load first_day_of_the_week_after objects using serialization lib +template +void load(Archive & ar, gregorian::first_kday_after& fkda, unsigned int /*version*/) +{ + typename gregorian::first_kday_after::day_of_week_type d(gregorian::Monday); + ar & make_nvp("first_kday_after_day_of_week", d); + + fkda = gregorian::first_kday_after(d); +} +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, + gregorian::first_kday_after* fkda, + const unsigned int /*file_version*/) +{ + // values used are not significant + ::new(fkda) gregorian::first_kday_after(gregorian::Monday); +} + +} // namespace serialization +} // namespace boost + +#endif diff --git a/win32/include/boost/date_time/gregorian/greg_weekday.hpp b/win32/include/boost/date_time/gregorian/greg_weekday.hpp new file mode 100755 index 000000000..01058c283 --- /dev/null +++ b/win32/include/boost/date_time/gregorian/greg_weekday.hpp @@ -0,0 +1,66 @@ +#ifndef GREG_WEEKDAY_HPP___ +#define GREG_WEEKDAY_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/constrained_value.hpp" +#include "boost/date_time/date_defs.hpp" +#include "boost/date_time/compiler_config.hpp" +#include +#include + +namespace boost { +namespace gregorian { + + //bring enum values into the namespace + using date_time::Sunday; + using date_time::Monday; + using date_time::Tuesday; + using date_time::Wednesday; + using date_time::Thursday; + using date_time::Friday; + using date_time::Saturday; + + + //! Exception that flags that a weekday number is incorrect + struct bad_weekday : public std::out_of_range + { + bad_weekday() : std::out_of_range(std::string("Weekday os out of range 0..6")) {} + }; + typedef CV::simple_exception_policy greg_weekday_policies; + typedef CV::constrained_value greg_weekday_rep; + + + //! Represent a day within a week (range 0==Sun to 6==Sat) + class BOOST_DATE_TIME_DECL greg_weekday : public greg_weekday_rep { + public: + typedef boost::date_time::weekdays weekday_enum; + greg_weekday(unsigned short day_of_week_num) : + greg_weekday_rep(day_of_week_num) + {} + + unsigned short as_number() const {return value_;} + const char* as_short_string() const; + const char* as_long_string() const; +#ifndef BOOST_NO_STD_WSTRING + const wchar_t* as_short_wstring() const; + const wchar_t* as_long_wstring() const; +#endif // BOOST_NO_STD_WSTRING + weekday_enum as_enum() const {return static_cast(value_);} + + + }; + + + +} } //namespace gregorian + + + +#endif diff --git a/win32/include/boost/date_time/gregorian/greg_year.hpp b/win32/include/boost/date_time/gregorian/greg_year.hpp new file mode 100755 index 000000000..ca028d33a --- /dev/null +++ b/win32/include/boost/date_time/gregorian/greg_year.hpp @@ -0,0 +1,53 @@ +#ifndef GREG_YEAR_HPP___ +#define GREG_YEAR_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/constrained_value.hpp" +#include +#include + +namespace boost { +namespace gregorian { + + //! Exception type for gregorian year + struct bad_year : public std::out_of_range + { + bad_year() : + std::out_of_range(std::string("Year is out of valid range: 1400..10000")) + {} + }; + //! Policy class that declares error handling gregorian year type + typedef CV::simple_exception_policy greg_year_policies; + + //! Generated representation for gregorian year + typedef CV::constrained_value greg_year_rep; + + //! Represent a day of the month (range 1900 - 10000) + /*! This small class allows for simple conversion an integer value into + a year for the gregorian calendar. This currently only allows a + range of 1900 to 10000. Both ends of the range are a bit arbitrary + at the moment, but they are the limits of current testing of the + library. As such they may be increased in the future. + */ + class greg_year : public greg_year_rep { + public: + greg_year(unsigned short year) : greg_year_rep(year) {} + operator unsigned short() const {return value_;} + private: + + }; + + + +} } //namespace gregorian + + + +#endif diff --git a/win32/include/boost/date_time/gregorian/greg_ymd.hpp b/win32/include/boost/date_time/gregorian/greg_ymd.hpp new file mode 100755 index 000000000..21d557125 --- /dev/null +++ b/win32/include/boost/date_time/gregorian/greg_ymd.hpp @@ -0,0 +1,33 @@ +#ifndef DATE_TIME_GREG_YMD_HPP__ +#define DATE_TIME_GREG_YMD_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/year_month_day.hpp" +#include "boost/date_time/special_defs.hpp" +#include "boost/date_time/gregorian/greg_day.hpp" +#include "boost/date_time/gregorian/greg_year.hpp" +#include "boost/date_time/gregorian/greg_month.hpp" + +namespace boost { +namespace gregorian { + + typedef date_time::year_month_day_base greg_year_month_day; + + + +} } //namespace gregorian + + + + +#endif + diff --git a/win32/include/boost/date_time/gregorian/gregorian.hpp b/win32/include/boost/date_time/gregorian/gregorian.hpp new file mode 100755 index 000000000..4131004a3 --- /dev/null +++ b/win32/include/boost/date_time/gregorian/gregorian.hpp @@ -0,0 +1,38 @@ +#ifndef GREGORIAN_HPP__ +#define GREGORIAN_HPP__ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! @file gregorian.hpp + Single file header that provides overall include for all elements of + the gregorian date-time system. This includes the various types + defined, but also other functions for formatting and parsing. +*/ + + +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/gregorian/conversion.hpp" +#if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) +#include "boost/date_time/gregorian/formatters_limited.hpp" +#else +#include "boost/date_time/gregorian/formatters.hpp" +#endif + +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) +#include "boost/date_time/gregorian/greg_facet.hpp" +#else +#include "boost/date_time/gregorian/gregorian_io.hpp" +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO + +#include "boost/date_time/gregorian/parsers.hpp" + + + +#endif diff --git a/win32/include/boost/date_time/gregorian/gregorian_io.hpp b/win32/include/boost/date_time/gregorian/gregorian_io.hpp new file mode 100755 index 000000000..288737c5f --- /dev/null +++ b/win32/include/boost/date_time/gregorian/gregorian_io.hpp @@ -0,0 +1,777 @@ +#ifndef DATE_TIME_GREGORIAN_IO_HPP__ +#define DATE_TIME_GREGORIAN_IO_HPP__ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/date_facet.hpp" +#include "boost/io/ios_state.hpp" +#include +#include + +namespace boost { +namespace gregorian { + + + typedef boost::date_time::period_formatter wperiod_formatter; + typedef boost::date_time::period_formatter period_formatter; + + typedef boost::date_time::date_facet wdate_facet; + typedef boost::date_time::date_facet date_facet; + + typedef boost::date_time::period_parser period_parser; + typedef boost::date_time::period_parser wperiod_parser; + + typedef boost::date_time::special_values_formatter special_values_formatter; + typedef boost::date_time::special_values_formatter wspecial_values_formatter; + + typedef boost::date_time::special_values_parser special_values_parser; + typedef boost::date_time::special_values_parser wspecial_values_parser; + + typedef boost::date_time::date_input_facet date_input_facet; + typedef boost::date_time::date_input_facet wdate_input_facet; + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::date& d) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet custom_date_facet; + std::ostreambuf_iterator output_itr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(output_itr, os, os.fill(), d); + else { + //instantiate a custom facet for dealing with dates since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every date + //if the locale did not already exist. Of course this will be overridden + //if the user imbues at some later point. With the default settings + //for the facet the resulting format will be the same as the + //std::time_facet settings. + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), d); + } + return os; + } + + //! input operator for date + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, date& d) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet date_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, d); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, d); + } + } + catch(...) { + // mask tells us what exceptions are turned on + std::ios_base::iostate exception_mask = is.exceptions(); + // if the user wants exceptions on failbit, we'll rethrow our + // date_time exception & set the failbit + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} // ignore this one + throw; // rethrow original exception + } + else { + // if the user want's to fail quietly, we simply set the failbit + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::date_duration& dd) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet custom_date_facet; + std::ostreambuf_iterator output_itr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(output_itr, os, os.fill(), dd); + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), dd); + + } + return os; + } + + //! input operator for date_duration + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, date_duration& dd) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet date_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, dd); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, dd); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::date_period& dp) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet custom_date_facet; + std::ostreambuf_iterator output_itr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(output_itr, os, os.fill(), dp); + else { + //instantiate a custom facet for dealing with date periods since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every time period + //if the local did not already exist. Of course this will be overridden + //if the user imbues at some later point. With the default settings + //for the facet the resulting format will be the same as the + //std::time_facet settings. + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), dp); + + } + return os; + } + + //! input operator for date_period + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, date_period& dp) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet date_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, dp); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, dp); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + /********** small gregorian types **********/ + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::greg_month& gm) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet custom_date_facet; + std::ostreambuf_iterator output_itr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(output_itr, os, os.fill(), gm); + else { + custom_date_facet* f = new custom_date_facet();//-> 10/1074199752/32 because year & day not initialized in put(...) + //custom_date_facet* f = new custom_date_facet("%B"); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), gm); + } + return os; + } + + //! input operator for greg_month + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, greg_month& m) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet date_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, m); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, m); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::greg_weekday& gw) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet custom_date_facet; + std::ostreambuf_iterator output_itr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(output_itr, os, os.fill(), gw); + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), gw); + } + return os; + } + + //! input operator for greg_weekday + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, greg_weekday& wd) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet date_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, wd); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, wd); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + //NOTE: output operator for greg_day was not necessary + + //! input operator for greg_day + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, greg_day& gd) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet date_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, gd); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, gd); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + //NOTE: output operator for greg_year was not necessary + + //! input operator for greg_year + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, greg_year& gy) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet date_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, gy); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, gy); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + /********** date generator types **********/ + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::partial_date& pd) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet custom_date_facet; + std::ostreambuf_iterator output_itr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(output_itr, os, os.fill(), pd); + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), pd); + } + return os; + } + + //! input operator for partial_date + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, partial_date& pd) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet date_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, pd); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, pd); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::nth_day_of_the_week_in_month& nkd) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet custom_date_facet; + std::ostreambuf_iterator output_itr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(output_itr, os, os.fill(), nkd); + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), nkd); + } + return os; + } + + //! input operator for nth_day_of_the_week_in_month + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, + nth_day_of_the_week_in_month& nday) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet date_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, nday); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, nday); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::first_day_of_the_week_in_month& fkd) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet custom_date_facet; + std::ostreambuf_iterator output_itr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(output_itr, os, os.fill(), fkd); + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), fkd); + } + return os; + } + + //! input operator for first_day_of_the_week_in_month + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, + first_day_of_the_week_in_month& fkd) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet date_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, fkd); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, fkd); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::last_day_of_the_week_in_month& lkd) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet custom_date_facet; + std::ostreambuf_iterator output_itr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(output_itr, os, os.fill(), lkd); + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), lkd); + } + return os; + } + + //! input operator for last_day_of_the_week_in_month + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, + last_day_of_the_week_in_month& lkd) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet date_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, lkd); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, lkd); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::first_day_of_the_week_after& fda) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet custom_date_facet; + std::ostreambuf_iterator output_itr(os); + if (std::has_facet(os.getloc())) { + std::use_facet(os.getloc()).put(output_itr, os, os.fill(), fda); + } + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), fda); + } + return os; + } + + //! input operator for first_day_of_the_week_after + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, + first_day_of_the_week_after& fka) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet date_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, fka); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, fka); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const boost::gregorian::first_day_of_the_week_before& fdb) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::date_facet custom_date_facet; + std::ostreambuf_iterator output_itr(os); + if (std::has_facet(os.getloc())) { + std::use_facet(os.getloc()).put(output_itr, os, os.fill(), fdb); + } + else { + custom_date_facet* f = new custom_date_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(output_itr, os, os.fill(), fdb); + } + return os; + } + + //! input operator for first_day_of_the_week_before + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, + first_day_of_the_week_before& fkb) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::date_input_facet date_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, fkb); + } + else { + date_input_facet* f = new date_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, fkb); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + +} } // namespaces + +#endif // DATE_TIME_GREGORIAN_IO_HPP__ diff --git a/win32/include/boost/date_time/gregorian/gregorian_types.hpp b/win32/include/boost/date_time/gregorian/gregorian_types.hpp new file mode 100755 index 000000000..32b6e6246 --- /dev/null +++ b/win32/include/boost/date_time/gregorian/gregorian_types.hpp @@ -0,0 +1,109 @@ +#ifndef _GREGORIAN_TYPES_HPP__ +#define _GREGORIAN_TYPES_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! @file gregorian_types.hpp + Single file header that defines most of the types for the gregorian + date-time system. +*/ + +#include "boost/date_time/date.hpp" +#include "boost/date_time/period.hpp" +#include "boost/date_time/gregorian/greg_calendar.hpp" +#include "boost/date_time/gregorian/greg_duration.hpp" +#if defined(BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES) +#include "boost/date_time/gregorian/greg_duration_types.hpp" +#endif +#include "boost/date_time/gregorian/greg_date.hpp" +#include "boost/date_time/date_generators.hpp" +#include "boost/date_time/date_clock_device.hpp" +#include "boost/date_time/date_iterator.hpp" +#include "boost/date_time/adjust_functors.hpp" + +namespace boost { + +//! Gregorian date system based on date_time components +/*! This date system defines a full complement of types including + * a date, date_duration, date_period, day_clock, and a + * day_iterator. + */ +namespace gregorian { + //! Date periods for the gregorian system + /*!\ingroup date_basics + */ + typedef date_time::period date_period; + + //! A unifying date_generator base type + /*! A unifying date_generator base type for: + * partial_date, nth_day_of_the_week_in_month, + * first_day_of_the_week_in_month, and last_day_of_the_week_in_month + */ + typedef date_time::year_based_generator year_based_generator; + + //! A date generation object type + typedef date_time::partial_date partial_date; + + typedef date_time::nth_kday_of_month nth_kday_of_month; + typedef nth_kday_of_month nth_day_of_the_week_in_month; + + typedef date_time::first_kday_of_month first_kday_of_month; + typedef first_kday_of_month first_day_of_the_week_in_month; + + typedef date_time::last_kday_of_month last_kday_of_month; + typedef last_kday_of_month last_day_of_the_week_in_month; + + typedef date_time::first_kday_after first_kday_after; + typedef first_kday_after first_day_of_the_week_after; + + typedef date_time::first_kday_before first_kday_before; + typedef first_kday_before first_day_of_the_week_before; + + //! A clock to get the current day from the local computer + /*!\ingroup date_basics + */ + typedef date_time::day_clock day_clock; + + //! Base date_iterator type for gregorian types. + /*!\ingroup date_basics + */ + typedef date_time::date_itr_base date_iterator; + + //! A day level iterator + /*!\ingroup date_basics + */ + typedef date_time::date_itr, + date> day_iterator; + //! A week level iterator + /*!\ingroup date_basics + */ + typedef date_time::date_itr, + date> week_iterator; + //! A month level iterator + /*!\ingroup date_basics + */ + typedef date_time::date_itr, + date> month_iterator; + //! A year level iterator + /*!\ingroup date_basics + */ + typedef date_time::date_itr, + date> year_iterator; + + // bring in these date_generator functions from date_time namespace + using date_time::days_until_weekday; + using date_time::days_before_weekday; + using date_time::next_weekday; + using date_time::previous_weekday; + +} } //namespace gregorian + + + +#endif diff --git a/win32/include/boost/date_time/gregorian/parsers.hpp b/win32/include/boost/date_time/gregorian/parsers.hpp new file mode 100755 index 000000000..0bf936f6a --- /dev/null +++ b/win32/include/boost/date_time/gregorian/parsers.hpp @@ -0,0 +1,91 @@ +#ifndef GREGORIAN_PARSERS_HPP___ +#define GREGORIAN_PARSERS_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/date_parsing.hpp" +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/parse_format_base.hpp" +#include +#include + +namespace boost { +namespace gregorian { + + //! Return special_value from string argument + /*! Return special_value from string argument. If argument is + * not one of the special value names (defined in src/gregorian/names.hpp), + * return 'not_special' */ + BOOST_DATE_TIME_DECL special_values special_value_from_string(const std::string& s); + + //! Deprecated: Use from_simple_string + inline date from_string(std::string s) { + return date_time::parse_date(s); + } + + //! From delimited date string where with order year-month-day eg: 2002-1-25 or 2003-Jan-25 (full month name is also accepted) + inline date from_simple_string(std::string s) { + return date_time::parse_date(s, date_time::ymd_order_iso); + } + + //! From delimited date string where with order year-month-day eg: 1-25-2003 or Jan-25-2003 (full month name is also accepted) + inline date from_us_string(std::string s) { + return date_time::parse_date(s, date_time::ymd_order_us); + } + + //! From delimited date string where with order day-month-year eg: 25-1-2002 or 25-Jan-2003 (full month name is also accepted) + inline date from_uk_string(std::string s) { + return date_time::parse_date(s, date_time::ymd_order_dmy); + } + + //! From iso type date string where with order year-month-day eg: 20020125 + inline date from_undelimited_string(std::string s) { + return date_time::parse_undelimited_date(s); + } + + //! From iso type date string where with order year-month-day eg: 20020125 + inline date date_from_iso_string(const std::string& s) { + return date_time::parse_undelimited_date(s); + } + +#if !(defined(BOOST_NO_STD_ITERATOR_TRAITS)) + //! Stream should hold a date in the form of: 2002-1-25. Month number, abbrev, or name are accepted + /* Arguments passed in by-value for convertability of char[] + * to iterator_type. Calls to from_stream_type are by-reference + * since conversion is already done */ + template + inline date from_stream(iterator_type beg, iterator_type end) { + if(beg == end) + { + return date(not_a_date_time); + } + typedef typename std::iterator_traits::value_type value_type; + return date_time::from_stream_type(beg, end, value_type()); + } +#endif //BOOST_NO_STD_ITERATOR_TRAITS + +#if (defined(_MSC_VER) && (_MSC_VER < 1300)) + // This function cannot be compiled with MSVC 6.0 due to internal compiler shorcomings +#else + //! Function to parse a date_period from a string (eg: [2003-Oct-31/2003-Dec-25]) + inline date_period date_period_from_string(const std::string& s){ + return date_time::from_simple_string_type(s); + } +# if !defined(BOOST_NO_STD_WSTRING) + //! Function to parse a date_period from a wstring (eg: [2003-Oct-31/2003-Dec-25]) + inline date_period date_period_from_wstring(const std::wstring& s){ + return date_time::from_simple_string_type(s); + } +# endif // BOOST_NO_STD_WSTRING +#endif + +} } //namespace gregorian + +#endif diff --git a/win32/include/boost/date_time/gregorian_calendar.hpp b/win32/include/boost/date_time/gregorian_calendar.hpp new file mode 100755 index 000000000..b249851f1 --- /dev/null +++ b/win32/include/boost/date_time/gregorian_calendar.hpp @@ -0,0 +1,70 @@ +#ifndef DATE_TIME_GREGORIAN_CALENDAR_HPP__ +#define DATE_TIME_GREGORIAN_CALENDAR_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +namespace boost { +namespace date_time { + + + //! An implementation of the Gregorian calendar + /*! This is a parameterized implementation of a proleptic Gregorian Calendar that + can be used in the creation of date systems or just to perform calculations. + All the methods of this class are static functions, so the intent is to + never create instances of this class. + @param ymd_type_ Struct type representing the year, month, day. The ymd_type must + define a of types for the year, month, and day. These types need to be + arithmetic types. + @param date_int_type_ Underlying type for the date count. Must be an arithmetic type. + */ + template + class gregorian_calendar_base { + public: + //! define a type a date split into components + typedef ymd_type_ ymd_type; + //! define a type for representing months + typedef typename ymd_type::month_type month_type; + //! define a type for representing days + typedef typename ymd_type::day_type day_type; + //! Type to hold a stand alone year value (eg: 2002) + typedef typename ymd_type::year_type year_type; + //! Define the integer type to use for internal calculations + typedef date_int_type_ date_int_type; + + + static unsigned short day_of_week(const ymd_type& ymd); + static int week_number(const ymd_type&ymd); + //static unsigned short day_of_year(date_int_type); + static date_int_type day_number(const ymd_type& ymd); + static date_int_type julian_day_number(const ymd_type& ymd); + static long modjulian_day_number(const ymd_type& ymd); + static ymd_type from_day_number(date_int_type); + static ymd_type from_julian_day_number(date_int_type); + static ymd_type from_modjulian_day_number(long); + static bool is_leap_year(year_type); + static unsigned short end_of_month_day(year_type y, month_type m); + static ymd_type epoch(); + static unsigned short days_in_week(); + + }; + + + +} } //namespace + +#ifndef NO_BOOST_DATE_TIME_INLINE +#include "boost/date_time/gregorian_calendar.ipp" +#endif + + + +#endif + + diff --git a/win32/include/boost/date_time/gregorian_calendar.ipp b/win32/include/boost/date_time/gregorian_calendar.ipp new file mode 100755 index 000000000..9118c4411 --- /dev/null +++ b/win32/include/boost/date_time/gregorian_calendar.ipp @@ -0,0 +1,219 @@ +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#ifndef NO_BOOST_DATE_TIME_INLINE + #undef BOOST_DATE_TIME_INLINE + #define BOOST_DATE_TIME_INLINE inline +#endif + +namespace boost { +namespace date_time { + //! Return the day of the week (0==Sunday, 1==Monday, etc) + /*! Converts a the year-month-day into a day of the week number + */ + template + BOOST_DATE_TIME_INLINE + unsigned short + gregorian_calendar_base::day_of_week(const ymd_type& ymd) { + unsigned short a = static_cast((14-ymd.month)/12); + unsigned short y = static_cast(ymd.year - a); + unsigned short m = static_cast(ymd.month + 12*a - 2); + unsigned short d = static_cast((ymd.day + y + (y/4) - (y/100) + (y/400) + (31*m)/12) % 7); + //std::cout << year << "-" << month << "-" << day << " is day: " << d << "\n"; + return d; + } + + //!Return the iso week number for the date + /*!Implements the rules associated with the iso 8601 week number. + Basically the rule is that Week 1 of the year is the week that contains + January 4th or the week that contains the first Thursday in January. + Reference for this algorithm is the Calendar FAQ by Claus Tondering, April 2000. + */ + template + BOOST_DATE_TIME_INLINE + int + gregorian_calendar_base::week_number(const ymd_type& ymd) { + unsigned long julianbegin = julian_day_number(ymd_type(ymd.year,1,1)); + unsigned long juliantoday = julian_day_number(ymd); + unsigned long day = (julianbegin + 3) % 7; + unsigned long week = (juliantoday + day - julianbegin + 4)/7; + + if ((week >= 1) && (week <= 52)) { + return week; + } + + if ((week == 53)) { + if((day==6) ||(day == 5 && is_leap_year(ymd.year))) { + return week; //under these circumstances week == 53. + } else { + return 1; //monday - wednesday is in week 1 of next year + } + } + //if the week is not in current year recalculate using the previous year as the beginning year + else if (week == 0) { + julianbegin = julian_day_number(ymd_type(static_cast(ymd.year-1),1,1)); + juliantoday = julian_day_number(ymd); + day = (julianbegin + 3) % 7; + week = (juliantoday + day - julianbegin + 4)/7; + return week; + } + + return week; //not reachable -- well except if day == 5 and is_leap_year != true + + } + + //! Convert a ymd_type into a day number + /*! The day number is an absolute number of days since the start of count + */ + template + BOOST_DATE_TIME_INLINE + date_int_type_ + gregorian_calendar_base::day_number(const ymd_type& ymd) + { + unsigned short a = static_cast((14-ymd.month)/12); + unsigned short y = static_cast(ymd.year + 4800 - a); + unsigned short m = static_cast(ymd.month + 12*a - 3); + unsigned long d = ymd.day + ((153*m + 2)/5) + 365*y + (y/4) - (y/100) + (y/400) - 32045; + return d; + } + + //! Convert a year-month-day into the julian day number + /*! Since this implementation uses julian day internally, this is the same as the day_number. + */ + template + BOOST_DATE_TIME_INLINE + date_int_type_ + gregorian_calendar_base::julian_day_number(const ymd_type& ymd) + { + return day_number(ymd); + } + + //! Convert year-month-day into a modified julian day number + /*! The day number is an absolute number of days. + * MJD 0 thus started on 17 Nov 1858(Gregorian) at 00:00:00 UTC + */ + template + BOOST_DATE_TIME_INLINE + long + gregorian_calendar_base::modjulian_day_number(const ymd_type& ymd) + { + return julian_day_number(ymd)-2400001; //prerounded + } + + //! Change a day number into a year-month-day + template + BOOST_DATE_TIME_INLINE + ymd_type_ + gregorian_calendar_base::from_day_number(date_int_type dayNumber) + { + date_int_type a = dayNumber + 32044; + date_int_type b = (4*a + 3)/146097; + date_int_type c = a-((146097*b)/4); + date_int_type d = (4*c + 3)/1461; + date_int_type e = c - (1461*d)/4; + date_int_type m = (5*e + 2)/153; + unsigned short day = static_cast(e - ((153*m + 2)/5) + 1); + unsigned short month = static_cast(m + 3 - 12 * (m/10)); + year_type year = static_cast(100*b + d - 4800 + (m/10)); + //std::cout << year << "-" << month << "-" << day << "\n"; + + return ymd_type(static_cast(year),month,day); + } + + //! Change a day number into a year-month-day + template + BOOST_DATE_TIME_INLINE + ymd_type_ + gregorian_calendar_base::from_julian_day_number(date_int_type dayNumber) + { + date_int_type a = dayNumber + 32044; + date_int_type b = (4*a+3)/146097; + date_int_type c = a - ((146097*b)/4); + date_int_type d = (4*c + 3)/1461; + date_int_type e = c - ((1461*d)/4); + date_int_type m = (5*e + 2)/153; + unsigned short day = static_cast(e - ((153*m + 2)/5) + 1); + unsigned short month = static_cast(m + 3 - 12 * (m/10)); + year_type year = static_cast(100*b + d - 4800 + (m/10)); + //std::cout << year << "-" << month << "-" << day << "\n"; + + return ymd_type(year,month,day); + } + + //! Change a modified julian day number into a year-month-day + template + BOOST_DATE_TIME_INLINE + ymd_type_ + gregorian_calendar_base::from_modjulian_day_number(long dayNumber) { + date_int_type jd = dayNumber + 2400001; //is 2400000.5 prerounded + return from_julian_day_number(jd); + } + + //! Determine if the provided year is a leap year + /*! + *@return true if year is a leap year, false otherwise + */ + template + BOOST_DATE_TIME_INLINE + bool + gregorian_calendar_base::is_leap_year(year_type year) + { + //divisible by 4, not if divisible by 100, but true if divisible by 400 + return (!(year % 4)) && ((year % 100) || (!(year % 400))); + } + + //! Calculate the last day of the month + /*! Find the day which is the end of the month given year and month + * No error checking is performed. + */ + template + BOOST_DATE_TIME_INLINE + unsigned short + gregorian_calendar_base::end_of_month_day(year_type year, + month_type month) + { + switch (month) { + case 2: + if (is_leap_year(year)) { + return 29; + } else { + return 28; + }; + case 4: + case 6: + case 9: + case 11: + return 30; + default: + return 31; + }; + + } + + //! Provide the ymd_type specification for the calandar start + template + BOOST_DATE_TIME_INLINE + ymd_type_ + gregorian_calendar_base::epoch() + { + return ymd_type(1400,1,1); + } + + //! Defines length of a week for week calculations + template + BOOST_DATE_TIME_INLINE + unsigned short + gregorian_calendar_base::days_in_week() + { + return 7; + } + + +} } //namespace gregorian + + diff --git a/win32/include/boost/date_time/int_adapter.hpp b/win32/include/boost/date_time/int_adapter.hpp new file mode 100755 index 000000000..7c9e8095e --- /dev/null +++ b/win32/include/boost/date_time/int_adapter.hpp @@ -0,0 +1,507 @@ +#ifndef _DATE_TIME_INT_ADAPTER_HPP__ +#define _DATE_TIME_INT_ADAPTER_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/config.hpp" +#include "boost/limits.hpp" //work around compilers without limits +#include "boost/date_time/special_defs.hpp" +#include "boost/date_time/locale_config.hpp" +#include + +namespace boost { +namespace date_time { + + +//! Adapter to create integer types with +-infinity, and not a value +/*! This class is used internally in counted date/time representations. + * It adds the floating point like features of infinities and + * not a number. It also provides mathmatical operations with + * consideration to special values following these rules: + *@code + * +infinity - infinity == Not A Number (NAN) + * infinity * non-zero == infinity + * infinity * zero == NAN + * +infinity * -integer == -infinity + * infinity / infinity == NAN + * infinity * infinity == infinity + *@endcode + */ +template +class int_adapter { +public: + typedef int_type_ int_type; + int_adapter(int_type v) : + value_(v) + {} + static bool has_infinity() + { + return true; + } + static const int_adapter pos_infinity() + { + return (::std::numeric_limits::max)(); + } + static const int_adapter neg_infinity() + { + return (::std::numeric_limits::min)(); + } + static const int_adapter not_a_number() + { + return (::std::numeric_limits::max)()-1; + } + static int_adapter max BOOST_PREVENT_MACRO_SUBSTITUTION () + { + return (::std::numeric_limits::max)()-2; + } + static int_adapter min BOOST_PREVENT_MACRO_SUBSTITUTION () + { + return (::std::numeric_limits::min)()+1; + } + static int_adapter from_special(special_values sv) + { + switch (sv) { + case not_a_date_time: return not_a_number(); + case neg_infin: return neg_infinity(); + case pos_infin: return pos_infinity(); + case max_date_time: return (max)(); + case min_date_time: return (min)(); + default: return not_a_number(); + } + } + static bool is_inf(int_type v) + { + return (v == neg_infinity().as_number() || + v == pos_infinity().as_number()); + } + static bool is_neg_inf(int_type v) + { + return (v == neg_infinity().as_number()); + } + static bool is_pos_inf(int_type v) + { + return (v == pos_infinity().as_number()); + } + static bool is_not_a_number(int_type v) + { + return (v == not_a_number().as_number()); + } + //! Returns either special value type or is_not_special + static special_values to_special(int_type v) + { + if (is_not_a_number(v)) return not_a_date_time; + if (is_neg_inf(v)) return neg_infin; + if (is_pos_inf(v)) return pos_infin; + return not_special; + } + + //-3 leaves room for representations of infinity and not a date + static int_type maxcount() + { + return (::std::numeric_limits::max)()-3; + } + bool is_infinity() const + { + return (value_ == neg_infinity().as_number() || + value_ == pos_infinity().as_number()); + } + bool is_pos_infinity()const + { + return(value_ == pos_infinity().as_number()); + } + bool is_neg_infinity()const + { + return(value_ == neg_infinity().as_number()); + } + bool is_nan() const + { + return (value_ == not_a_number().as_number()); + } + bool is_special() const + { + return(is_infinity() || is_nan()); + } + bool operator==(const int_adapter& rhs) const + { + return (compare(rhs) == 0); + } + bool operator==(const int& rhs) const + { + // quiets compiler warnings + bool is_signed = std::numeric_limits::is_signed; + if(!is_signed) + { + if(is_neg_inf(value_) && rhs == 0) + { + return false; + } + } + return (compare(rhs) == 0); + } + bool operator!=(const int_adapter& rhs) const + { + return (compare(rhs) != 0); + } + bool operator!=(const int& rhs) const + { + // quiets compiler warnings + bool is_signed = std::numeric_limits::is_signed; + if(!is_signed) + { + if(is_neg_inf(value_) && rhs == 0) + { + return true; + } + } + return (compare(rhs) != 0); + } + bool operator<(const int_adapter& rhs) const + { + return (compare(rhs) == -1); + } + bool operator<(const int& rhs) const + { + // quiets compiler warnings + bool is_signed = std::numeric_limits::is_signed; + if(!is_signed) + { + if(is_neg_inf(value_) && rhs == 0) + { + return true; + } + } + return (compare(rhs) == -1); + } + bool operator>(const int_adapter& rhs) const + { + return (compare(rhs) == 1); + } + int_type as_number() const + { + return value_; + } + //! Returns either special value type or is_not_special + special_values as_special() const + { + return int_adapter::to_special(value_); + } + //creates nasty ambiguities +// operator int_type() const +// { +// return value_; +// } + + /*! Operator allows for adding dissimilar int_adapter types. + * The return type will match that of the the calling object's type */ + template + inline + int_adapter operator+(const int_adapter& rhs) const + { + if(is_special() || rhs.is_special()) + { + if (is_nan() || rhs.is_nan()) + { + return int_adapter::not_a_number(); + } + if((is_pos_inf(value_) && rhs.is_neg_inf(rhs.as_number())) || + (is_neg_inf(value_) && rhs.is_pos_inf(rhs.as_number())) ) + { + return int_adapter::not_a_number(); + } + if (is_infinity()) + { + return *this; + } + if (rhs.is_pos_inf(rhs.as_number())) + { + return int_adapter::pos_infinity(); + } + if (rhs.is_neg_inf(rhs.as_number())) + { + return int_adapter::neg_infinity(); + } + } + return int_adapter(value_ + rhs.as_number()); + } + + int_adapter operator+(const int_type rhs) const + { + if(is_special()) + { + if (is_nan()) + { + return int_adapter(not_a_number()); + } + if (is_infinity()) + { + return *this; + } + } + return int_adapter(value_ + rhs); + } + + /*! Operator allows for subtracting dissimilar int_adapter types. + * The return type will match that of the the calling object's type */ + template + inline + int_adapter operator-(const int_adapter& rhs)const + { + if(is_special() || rhs.is_special()) + { + if (is_nan() || rhs.is_nan()) + { + return int_adapter::not_a_number(); + } + if((is_pos_inf(value_) && rhs.is_pos_inf(rhs.as_number())) || + (is_neg_inf(value_) && rhs.is_neg_inf(rhs.as_number())) ) + { + return int_adapter::not_a_number(); + } + if (is_infinity()) + { + return *this; + } + if (rhs.is_pos_inf(rhs.as_number())) + { + return int_adapter::neg_infinity(); + } + if (rhs.is_neg_inf(rhs.as_number())) + { + return int_adapter::pos_infinity(); + } + } + return int_adapter(value_ - rhs.as_number()); + } + int_adapter operator-(const int_type rhs) const + { + if(is_special()) + { + if (is_nan()) + { + return int_adapter(not_a_number()); + } + if (is_infinity()) + { + return *this; + } + } + return int_adapter(value_ - rhs); + } + + // should templatize this to be consistant with op +- + int_adapter operator*(const int_adapter& rhs)const + { + if(this->is_special() || rhs.is_special()) + { + return mult_div_specials(rhs); + } + return int_adapter(value_ * rhs.value_); + } + /*! Provided for cases when automatic conversion from + * 'int' to 'int_adapter' causes incorrect results. */ + int_adapter operator*(const int rhs) const + { + if(is_special()) + { + return mult_div_specials(rhs); + } + return int_adapter(value_ * rhs); + } + + // should templatize this to be consistant with op +- + int_adapter operator/(const int_adapter& rhs)const + { + if(this->is_special() || rhs.is_special()) + { + if(is_infinity() && rhs.is_infinity()) + { + return int_adapter(not_a_number()); + } + if(rhs != 0) + { + return mult_div_specials(rhs); + } + else { // let divide by zero blow itself up + return int_adapter(value_ / rhs.value_); + } + } + return int_adapter(value_ / rhs.value_); + } + /*! Provided for cases when automatic conversion from + * 'int' to 'int_adapter' causes incorrect results. */ + int_adapter operator/(const int rhs) const + { + if(is_special() && rhs != 0) + { + return mult_div_specials(rhs); + } + return int_adapter(value_ / rhs); + } + + // should templatize this to be consistant with op +- + int_adapter operator%(const int_adapter& rhs)const + { + if(this->is_special() || rhs.is_special()) + { + if(is_infinity() && rhs.is_infinity()) + { + return int_adapter(not_a_number()); + } + if(rhs != 0) + { + return mult_div_specials(rhs); + } + else { // let divide by zero blow itself up + return int_adapter(value_ % rhs.value_); + } + } + return int_adapter(value_ % rhs.value_); + } + /*! Provided for cases when automatic conversion from + * 'int' to 'int_adapter' causes incorrect results. */ + int_adapter operator%(const int rhs) const + { + if(is_special() && rhs != 0) + { + return mult_div_specials(rhs); + } + return int_adapter(value_ % rhs); + } +private: + int_type value_; + + //! returns -1, 0, 1, or 2 if 'this' is <, ==, >, or 'nan comparison' rhs + int compare(const int_adapter& rhs)const + { + if(this->is_special() || rhs.is_special()) + { + if(this->is_nan() || rhs.is_nan()) { + if(this->is_nan() && rhs.is_nan()) { + return 0; // equal + } + else { + return 2; // nan + } + } + if((is_neg_inf(value_) && !is_neg_inf(rhs.value_)) || + (is_pos_inf(rhs.value_) && !is_pos_inf(value_)) ) + { + return -1; // less than + } + if((is_pos_inf(value_) && !is_pos_inf(rhs.value_)) || + (is_neg_inf(rhs.value_) && !is_neg_inf(value_)) ) { + return 1; // greater than + } + } + if(value_ < rhs.value_) return -1; + if(value_ > rhs.value_) return 1; + // implied-> if(value_ == rhs.value_) + return 0; + } + /* When multiplying and dividing with at least 1 special value + * very simmilar rules apply. In those cases where the rules + * are different, they are handled in the respective operator + * function. */ + //! Assumes at least 'this' or 'rhs' is a special value + int_adapter mult_div_specials(const int_adapter& rhs)const + { + int min_value; + // quiets compiler warnings + bool is_signed = std::numeric_limits::is_signed; + if(is_signed) { + min_value = 0; + } + else { + min_value = 1;// there is no zero with unsigned + } + if(this->is_nan() || rhs.is_nan()) { + return int_adapter(not_a_number()); + } + if((*this > 0 && rhs > 0) || (*this < min_value && rhs < min_value)) { + return int_adapter(pos_infinity()); + } + if((*this > 0 && rhs < min_value) || (*this < min_value && rhs > 0)) { + return int_adapter(neg_infinity()); + } + //implied -> if(this->value_ == 0 || rhs.value_ == 0) + return int_adapter(not_a_number()); + } + /* Overloaded function necessary because of special + * situation where int_adapter is instantiated with + * 'unsigned' and func is called with negative int. + * It would produce incorrect results since 'unsigned' + * wraps around when initialized with a negative value */ + //! Assumes 'this' is a special value + int_adapter mult_div_specials(const int& rhs) const + { + int min_value; + // quiets compiler warnings + bool is_signed = std::numeric_limits::is_signed; + if(is_signed) { + min_value = 0; + } + else { + min_value = 1;// there is no zero with unsigned + } + if(this->is_nan()) { + return int_adapter(not_a_number()); + } + if((*this > 0 && rhs > 0) || (*this < min_value && rhs < 0)) { + return int_adapter(pos_infinity()); + } + if((*this > 0 && rhs < 0) || (*this < min_value && rhs > 0)) { + return int_adapter(neg_infinity()); + } + //implied -> if(this->value_ == 0 || rhs.value_ == 0) + return int_adapter(not_a_number()); + } + +}; + +#ifndef BOOST_DATE_TIME_NO_LOCALE + /*! Expected output is either a numeric representation + * or a special values representation.
+ * Ex. "12", "+infinity", "not-a-number", etc. */ + //template, typename int_type> + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const int_adapter& ia) + { + if(ia.is_special()) { + // switch copied from date_names_put.hpp + switch(ia.as_special()) + { + case not_a_date_time: + os << "not-a-number"; + break; + case pos_infin: + os << "+infinity"; + break; + case neg_infin: + os << "-infinity"; + break; + default: + os << ""; + } + } + else { + os << ia.as_number(); + } + return os; + } +#endif + + +} } //namespace date_time + + + +#endif diff --git a/win32/include/boost/date_time/iso_format.hpp b/win32/include/boost/date_time/iso_format.hpp new file mode 100755 index 000000000..ae01f48aa --- /dev/null +++ b/win32/include/boost/date_time/iso_format.hpp @@ -0,0 +1,303 @@ +#ifndef ISO_FORMAT_HPP___ +#define ISO_FORMAT_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/parse_format_base.hpp" + +namespace boost { +namespace date_time { + +//! Class to provide common iso formatting spec +template +class iso_format_base { +public: + //! Describe month format -- its an integer in iso format + static month_format_spec month_format() + { + return month_as_integer; + } + + //! String used printed is date is invalid + static const charT* not_a_date() + { + return "not-a-date-time"; + } + //! String used to for positive infinity value + static const charT* pos_infinity() + { + return "+infinity"; + } + //! String used to for positive infinity value + static const charT* neg_infinity() + { + return "-infinity"; + } + + //! ISO char for a year -- used in durations + static charT year_sep_char() + { + return 'Y'; + } + //! ISO char for a month + static charT month_sep_char() + { + return '-'; + } + //! ISO char for a day + static charT day_sep_char() + { + return '-'; + } + //! char for minute + static charT hour_sep_char() + { + return ':'; + } + //! char for minute + static charT minute_sep_char() + { + return ':'; + } + //! char for second + static charT second_sep_char() + { + return ':'; + } + //! ISO char for a period + static charT period_start_char() + { + return 'P'; + } + //! Used in time in mixed strings to set start of time + static charT time_start_char() + { + return 'T'; + } + + //! Used in mixed strings to identify start of a week number + static charT week_start_char() + { + return 'W'; + } + + //! Separators for periods + static charT period_sep_char() + { + return '/'; + } + //! Separator for hh:mm:ss + static charT time_sep_char() + { + return ':'; + } + //! Preferred Separator for hh:mm:ss,decimal_fraction + static charT fractional_time_sep_char() + { + return ','; + } + + static bool is_component_sep(charT sep) + { + switch(sep) { + case 'H': + case 'M': + case 'S': + case 'W': + case 'T': + case 'Y': + case 'D':return true; + default: + return false; + } + } + + static bool is_fractional_time_sep(charT sep) + { + switch(sep) { + case ',': + case '.': return true; + default: return false; + } + } + static bool is_timezone_sep(charT sep) + { + switch(sep) { + case '+': + case '-': return true; + default: return false; + } + } + static charT element_sep_char() + { + return '-'; + } + +}; + +#ifndef BOOST_NO_STD_WSTRING + +//! Class to provide common iso formatting spec +template<> +class iso_format_base { +public: + //! Describe month format -- its an integer in iso format + static month_format_spec month_format() + { + return month_as_integer; + } + + //! String used printed is date is invalid + static const wchar_t* not_a_date() + { + return L"not-a-date-time"; + } + //! String used to for positive infinity value + static const wchar_t* pos_infinity() + { + return L"+infinity"; + } + //! String used to for positive infinity value + static const wchar_t* neg_infinity() + { + return L"-infinity"; + } + + //! ISO char for a year -- used in durations + static wchar_t year_sep_char() + { + return 'Y'; + } + //! ISO char for a month + static wchar_t month_sep_char() + { + return '-'; + } + //! ISO char for a day + static wchar_t day_sep_char() + { + return '-'; + } + //! char for minute + static wchar_t hour_sep_char() + { + return ':'; + } + //! char for minute + static wchar_t minute_sep_char() + { + return ':'; + } + //! char for second + static wchar_t second_sep_char() + { + return ':'; + } + //! ISO char for a period + static wchar_t period_start_char() + { + return 'P'; + } + //! Used in time in mixed strings to set start of time + static wchar_t time_start_char() + { + return 'T'; + } + + //! Used in mixed strings to identify start of a week number + static wchar_t week_start_char() + { + return 'W'; + } + + //! Separators for periods + static wchar_t period_sep_char() + { + return '/'; + } + //! Separator for hh:mm:ss + static wchar_t time_sep_char() + { + return ':'; + } + //! Preferred Separator for hh:mm:ss,decimal_fraction + static wchar_t fractional_time_sep_char() + { + return ','; + } + + static bool is_component_sep(wchar_t sep) + { + switch(sep) { + case 'H': + case 'M': + case 'S': + case 'W': + case 'T': + case 'Y': + case 'D':return true; + default: + return false; + } + } + + static bool is_fractional_time_sep(wchar_t sep) + { + switch(sep) { + case ',': + case '.': return true; + default: return false; + } + } + static bool is_timezone_sep(wchar_t sep) + { + switch(sep) { + case '+': + case '-': return true; + default: return false; + } + } + static wchar_t element_sep_char() + { + return '-'; + } + +}; + +#endif // BOOST_NO_STD_WSTRING + +//! Format description for iso normal YYYYMMDD +template +class iso_format : public iso_format_base { +public: + //! The ios standard format doesn't use char separators + static bool has_date_sep_chars() + { + return false; + } +}; + +//! Extended format uses seperators YYYY-MM-DD +template +class iso_extended_format : public iso_format_base { +public: + //! Extended format needs char separators + static bool has_date_sep_chars() + { + return true; + } + +}; + +} } //namespace date_time + + + + +#endif diff --git a/win32/include/boost/date_time/local_time/conversion.hpp b/win32/include/boost/date_time/local_time/conversion.hpp new file mode 100755 index 000000000..afa3d0441 --- /dev/null +++ b/win32/include/boost/date_time/local_time/conversion.hpp @@ -0,0 +1,35 @@ +#ifndef DATE_TIME_LOCAL_TIME_CONVERSION_HPP__ +#define DATE_TIME_LOCAL_TIME_CONVERSION_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/posix_time/conversion.hpp" +#include "boost/date_time/c_time.hpp" +#include "boost/date_time/local_time/local_date_time.hpp" + +namespace boost { +namespace local_time { + +//! Function that creates a tm struct from a local_date_time +inline +tm to_tm(const local_date_time& lt) { + tm lt_tm; + lt_tm = posix_time::to_tm(lt.local_time()); + if(lt.is_dst()){ + lt_tm.tm_isdst = 1; + } + else{ + lt_tm.tm_isdst = 0; + } + return lt_tm; +} + + +}} // namespaces +#endif // DATE_TIME_LOCAL_TIME_CONVERSION_HPP__ diff --git a/win32/include/boost/date_time/local_time/custom_time_zone.hpp b/win32/include/boost/date_time/local_time/custom_time_zone.hpp new file mode 100755 index 000000000..7ddd876ae --- /dev/null +++ b/win32/include/boost/date_time/local_time/custom_time_zone.hpp @@ -0,0 +1,169 @@ +#ifndef LOCAL_TIME_CUSTOM_TIME_ZONE_HPP__ +#define LOCAL_TIME_CUSTOM_TIME_ZONE_HPP__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/time_zone_base.hpp" +#include "boost/date_time/time_zone_names.hpp" +#include "boost/date_time/posix_time/posix_time.hpp" +#include "boost/date_time/local_time/dst_transition_day_rules.hpp" +#include "boost/date_time/string_convert.hpp" +//#include "boost/date_time/special_defs.hpp" +#include "boost/shared_ptr.hpp" + +namespace boost { +namespace local_time { + + //typedef boost::date_time::time_zone_names time_zone_names; + typedef boost::date_time::dst_adjustment_offsets dst_adjustment_offsets; + //typedef boost::date_time::time_zone_base time_zone; + typedef boost::shared_ptr dst_calc_rule_ptr; + + //! A real time zone + template + class custom_time_zone_base : public date_time::time_zone_base { + public: + typedef boost::posix_time::time_duration time_duration_type; + typedef date_time::time_zone_base base_type; + typedef typename base_type::string_type string_type; + typedef typename base_type::stringstream_type stringstream_type; + typedef date_time::time_zone_names_base time_zone_names; + typedef CharT char_type; + + custom_time_zone_base(const time_zone_names& zone_names, + const time_duration_type& utc_offset, + const dst_adjustment_offsets& dst_shift, + boost::shared_ptr calc_rule) : + zone_names_(zone_names), + base_utc_offset_(utc_offset), + dst_offsets_(dst_shift), + dst_calc_rules_(calc_rule) + {}; + virtual ~custom_time_zone_base() {}; + virtual string_type dst_zone_abbrev() const + { + return zone_names_.dst_zone_abbrev(); + } + virtual string_type std_zone_abbrev() const + { + return zone_names_.std_zone_abbrev(); + } + virtual string_type dst_zone_name() const + { + return zone_names_.dst_zone_name(); + } + virtual string_type std_zone_name() const + { + return zone_names_.std_zone_name(); + } + //! True if zone uses daylight savings adjustments + virtual bool has_dst() const + { + return (dst_calc_rules_); //if calc_rule is set the tz has dst + } + //! Local time that DST starts -- NADT if has_dst is false + virtual posix_time::ptime dst_local_start_time(gregorian::greg_year y) const + { + gregorian::date d(gregorian::not_a_date_time); + if (dst_calc_rules_) { + d = dst_calc_rules_->start_day(y); + } + return posix_time::ptime(d, dst_offsets_.dst_start_offset_); + } + //! Local time that DST ends -- NADT if has_dst is false + virtual posix_time::ptime dst_local_end_time(gregorian::greg_year y) const + { + gregorian::date d(gregorian::not_a_date_time); + if (dst_calc_rules_) { + d = dst_calc_rules_->end_day(y); + } + return posix_time::ptime(d, dst_offsets_.dst_end_offset_); + } + //! Base offset from UTC for zone (eg: -07:30:00) + virtual time_duration_type base_utc_offset() const + { + return base_utc_offset_; + } + //! Adjustment forward or back made while DST is in effect + virtual time_duration_type dst_offset() const + { + return dst_offsets_.dst_adjust_; + } + //! Returns a POSIX time_zone string for this object + virtual string_type to_posix_string() const + { + // std offset dst [offset],start[/time],end[/time] - w/o spaces + stringstream_type ss; + ss.fill('0'); + boost::shared_ptr no_rules; + // std + ss << std_zone_abbrev(); + // offset + if(base_utc_offset().is_negative()) { + // inverting the sign guarantees we get two digits + ss << '-' << std::setw(2) << base_utc_offset().invert_sign().hours(); + } + else { + ss << '+' << std::setw(2) << base_utc_offset().hours(); + } + if(base_utc_offset().minutes() != 0 || base_utc_offset().seconds() != 0) { + ss << ':' << std::setw(2) << base_utc_offset().minutes(); + if(base_utc_offset().seconds() != 0) { + ss << ':' << std::setw(2) << base_utc_offset().seconds(); + } + } + if(dst_calc_rules_ != no_rules) { + // dst + ss << dst_zone_abbrev(); + // dst offset + if(dst_offset().is_negative()) { + // inverting the sign guarantees we get two digits + ss << '-' << std::setw(2) << dst_offset().invert_sign().hours(); + } + else { + ss << '+' << std::setw(2) << dst_offset().hours(); + } + if(dst_offset().minutes() != 0 || dst_offset().seconds() != 0) { + ss << ':' << std::setw(2) << dst_offset().minutes(); + if(dst_offset().seconds() != 0) { + ss << ':' << std::setw(2) << dst_offset().seconds(); + } + } + // start/time + ss << ',' << date_time::convert_string_type(dst_calc_rules_->start_rule_as_string()) << '/' + << std::setw(2) << dst_offsets_.dst_start_offset_.hours() << ':' + << std::setw(2) << dst_offsets_.dst_start_offset_.minutes(); + if(dst_offsets_.dst_start_offset_.seconds() != 0) { + ss << ':' << std::setw(2) << dst_offsets_.dst_start_offset_.seconds(); + } + // end/time + ss << ',' << date_time::convert_string_type(dst_calc_rules_->end_rule_as_string()) << '/' + << std::setw(2) << dst_offsets_.dst_end_offset_.hours() << ':' + << std::setw(2) << dst_offsets_.dst_end_offset_.minutes(); + if(dst_offsets_.dst_end_offset_.seconds() != 0) { + ss << ':' << std::setw(2) << dst_offsets_.dst_end_offset_.seconds(); + } + } + + return ss.str(); + } + private: + time_zone_names zone_names_; + bool has_dst_; + time_duration_type base_utc_offset_; + dst_adjustment_offsets dst_offsets_; + boost::shared_ptr dst_calc_rules_; + }; + + typedef custom_time_zone_base custom_time_zone; + +} }//namespace + + + +#endif diff --git a/win32/include/boost/date_time/local_time/date_duration_operators.hpp b/win32/include/boost/date_time/local_time/date_duration_operators.hpp new file mode 100755 index 000000000..8facb0b3a --- /dev/null +++ b/win32/include/boost/date_time/local_time/date_duration_operators.hpp @@ -0,0 +1,115 @@ +#ifndef LOCAL_TIME_DATE_DURATION_OPERATORS_HPP___ +#define LOCAL_TIME_DATE_DURATION_OPERATORS_HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or + * http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/greg_duration_types.hpp" +#include "boost/date_time/local_time/local_date_time.hpp" + +namespace boost { +namespace local_time { + + /*!@file date_duration_operators.hpp Operators for local_date_time and + * optional gregorian types. Operators use snap-to-end-of-month behavior. + * Further details on this behavior can be found in reference for + * date_time/date_duration_types.hpp and documentation for + * month and year iterators. + */ + + + /*! Adds a months object and a local_date_time. Result will be same + * day-of-month as local_date_time unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + local_date_time + operator+(const local_date_time& t, const boost::gregorian::months& m) + { + return t + m.get_offset(t.utc_time().date()); + } + + /*! Adds a months object to a local_date_time. Result will be same + * day-of-month as local_date_time unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + local_date_time + operator+=(local_date_time& t, const boost::gregorian::months& m) + { + return t += m.get_offset(t.utc_time().date()); + } + + /*! Subtracts a months object and a local_date_time. Result will be same + * day-of-month as local_date_time unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + local_date_time + operator-(const local_date_time& t, const boost::gregorian::months& m) + { + // get_neg_offset returns a negative duration, so we add + return t + m.get_neg_offset(t.utc_time().date()); + } + + /*! Subtracts a months object from a local_date_time. Result will be same + * day-of-month as local_date_time unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + local_date_time + operator-=(local_date_time& t, const boost::gregorian::months& m) + { + // get_neg_offset returns a negative duration, so we add + return t += m.get_neg_offset(t.utc_time().date()); + } + + // local_date_time & years + + /*! Adds a years object and a local_date_time. Result will be same + * month and day-of-month as local_date_time unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + local_date_time + operator+(const local_date_time& t, const boost::gregorian::years& y) + { + return t + y.get_offset(t.utc_time().date()); + } + + /*! Adds a years object to a local_date_time. Result will be same + * month and day-of-month as local_date_time unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + local_date_time + operator+=(local_date_time& t, const boost::gregorian::years& y) + { + return t += y.get_offset(t.utc_time().date()); + } + + /*! Subtracts a years object and a local_date_time. Result will be same + * month and day-of-month as local_date_time unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + local_date_time + operator-(const local_date_time& t, const boost::gregorian::years& y) + { + // get_neg_offset returns a negative duration, so we add + return t + y.get_neg_offset(t.utc_time().date()); + } + + /*! Subtracts a years object from a local_date_time. Result will be same + * month and day-of-month as local_date_time unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + local_date_time + operator-=(local_date_time& t, const boost::gregorian::years& y) + { + // get_neg_offset returns a negative duration, so we add + return t += y.get_neg_offset(t.utc_time().date()); + } + + +}} // namespaces + +#endif // LOCAL_TIME_DATE_DURATION_OPERATORS_HPP___ diff --git a/win32/include/boost/date_time/local_time/dst_transition_day_rules.hpp b/win32/include/boost/date_time/local_time/dst_transition_day_rules.hpp new file mode 100755 index 000000000..e4e25453f --- /dev/null +++ b/win32/include/boost/date_time/local_time/dst_transition_day_rules.hpp @@ -0,0 +1,77 @@ +#ifndef LOCAL_TIME_DST_TRANSITION_DAY_RULES_HPP__ +#define LOCAL_TIME_DST_TRANSITION_DAY_RULES_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/dst_transition_generators.hpp" + +namespace boost { +namespace local_time { + + //! Provides rule of the form starting Apr 30 ending Oct 21 + typedef date_time::dst_day_calc_rule dst_calc_rule; + + struct partial_date_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::partial_date start_rule; + typedef gregorian::partial_date end_rule; + }; + + //! Provides rule of the form first Sunday in April, last Saturday in Oct + typedef date_time::day_calc_dst_rule partial_date_dst_rule; + + struct first_last_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::first_kday_of_month start_rule; + typedef gregorian::last_kday_of_month end_rule; + }; + + //! Provides rule of the form first Sunday in April, last Saturday in Oct + typedef date_time::day_calc_dst_rule first_last_dst_rule; + + struct last_last_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::last_kday_of_month start_rule; + typedef gregorian::last_kday_of_month end_rule; + }; + + //! Provides rule of the form last Sunday in April, last Saturday in Oct + typedef date_time::day_calc_dst_rule last_last_dst_rule; + + struct nth_last_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::nth_kday_of_month start_rule; + typedef gregorian::last_kday_of_month end_rule; + }; + + //! Provides rule in form of [1st|2nd|3rd|4th] Sunday in April, last Sunday in Oct + typedef date_time::day_calc_dst_rule nth_last_dst_rule; + + struct nth_kday_rule_spec + { + typedef gregorian::date date_type; + typedef gregorian::nth_kday_of_month start_rule; + typedef gregorian::nth_kday_of_month end_rule; + }; + + //! Provides rule in form of [1st|2nd|3rd|4th] Sunday in April/October + typedef date_time::day_calc_dst_rule nth_kday_dst_rule; + //! Provides rule in form of [1st|2nd|3rd|4th] Sunday in April/October + typedef date_time::day_calc_dst_rule nth_day_of_the_week_in_month_dst_rule; + + +} }//namespace + + +#endif diff --git a/win32/include/boost/date_time/local_time/local_date_time.hpp b/win32/include/boost/date_time/local_time/local_date_time.hpp new file mode 100755 index 000000000..e606c2af4 --- /dev/null +++ b/win32/include/boost/date_time/local_time/local_date_time.hpp @@ -0,0 +1,525 @@ +#ifndef LOCAL_TIME_LOCAL_DATE_TIME_HPP__ +#define LOCAL_TIME_LOCAL_DATE_TIME_HPP__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/time.hpp" +#include "boost/date_time/posix_time/posix_time.hpp" //todo remove? +#include "boost/shared_ptr.hpp" +#include "boost/date_time/dst_rules.hpp" +#include "boost/date_time/time_zone_base.hpp" +#include "boost/date_time/special_defs.hpp" +#include +#include + +namespace boost { +namespace local_time { + + //! simple exception for reporting when STD or DST cannot be determined + struct ambiguous_result : public std::logic_error + { + ambiguous_result (std::string _msg="") : + std::logic_error(std::string("Daylight Savings Results are ambiguous: " + _msg)) {} + }; + //! simple exception for when time label given cannot exist + struct time_label_invalid : public std::logic_error + { + time_label_invalid (std::string _msg="") : + std::logic_error(std::string("Time label given is invalid: " + _msg)) {} + }; + struct dst_not_valid: public std::logic_error + { + dst_not_valid(std::string _msg="") : + std::logic_error(std::string("is_dst flag does not match resulting dst for time label given: " + _msg)) {} + }; + + //TODO: I think these should be in local_date_time_base and not + // necessarily brought into the namespace + using date_time::time_is_dst_result; + using date_time::is_in_dst; + using date_time::is_not_in_dst; + using date_time::ambiguous; + using date_time::invalid_time_label; + + //! Representation of "wall-clock" time in a particular time zone + /*! Representation of "wall-clock" time in a particular time zone + * Local_date_time_base holds a time value (date and time offset from 00:00) + * along with a time zone. The time value is stored as UTC and conversions + * to wall clock time are made as needed. This approach allows for + * operations between wall-clock times in different time zones, and + * daylight savings time considerations, to be made. Time zones are + * required to be in the form of a boost::shared_ptr. + */ + template > + class local_date_time_base : public date_time::base_time { + public: + typedef utc_time_ utc_time_type; + typedef typename utc_time_type::time_duration_type time_duration_type; + typedef typename utc_time_type::date_type date_type; + typedef typename date_type::duration_type date_duration_type; + typedef typename utc_time_type::time_system_type time_system_type; + /*! This constructor interprets the passed time as a UTC time. + * So, for example, if the passed timezone is UTC-5 then the + * time will be adjusted back 5 hours. The time zone allows for + * automatic calculation of whether the particular time is adjusted for + * daylight savings, etc. + * If the time zone shared pointer is null then time stays unadjusted. + *@param t A UTC time + *@param tz Timezone for to adjust the UTC time to. + */ + local_date_time_base(utc_time_type t, + boost::shared_ptr tz) : + date_time::base_time(t), + zone_(tz) + { + // param was already utc so nothing more to do + } + + /*! This constructs a local time -- the passed time information + * understood to be in the passed tz. The DST flag must be passed + * to indicate whether the time is in daylight savings or not. + * @throws -- time_label_invalid if the time passed does not exist in + * the given locale. The non-existent case occurs typically + * during the shift-back from daylight savings time. When + * the clock is shifted forward a range of times + * (2 am to 3 am in the US) is skipped and hence is invalid. + * @throws -- dst_not_valid if the DST flag is passed for a period + * where DST is not active. + */ + local_date_time_base(date_type d, + time_duration_type td, + boost::shared_ptr tz, + bool dst_flag) : //necessary for constr_adj() + date_time::base_time(construction_adjustment(utc_time_type(d, td), tz, dst_flag)), + zone_(tz) + { + if(tz != boost::shared_ptr() && tz->has_dst()){ + + // d & td are already local so we use them + time_is_dst_result result = check_dst(d, td, tz); + bool in_dst = (result == is_in_dst); // less processing than is_dst() + + // ambig occurs at end, invalid at start + if(result == invalid_time_label){ + // Ex: 2:15am local on trans-in day in nyc, dst_flag irrelevant + std::stringstream ss; + ss << "time given: " << d << ' ' << td; + throw time_label_invalid(ss.str()); + } + else if(result != ambiguous && in_dst != dst_flag){ + // is dst_flag accurate? + // Ex: false flag in NYC in June + std::stringstream ss; + ss << "flag given: " << (dst_flag ? "dst=true" : "dst=false") + << ", dst calculated: " << (in_dst ? "dst=true" : "dst=false"); + throw dst_not_valid(ss.str()); + } + + // everything checks out and conversion to utc already done + } + } + + //TODO maybe not the right set...Ignore the last 2 for now... + enum DST_CALC_OPTIONS { EXCEPTION_ON_ERROR, NOT_DATE_TIME_ON_ERROR }; + //ASSUME_DST_ON_ERROR, ASSUME_NOT_DST_ON_ERROR }; + + /*! This constructs a local time -- the passed time information + * understood to be in the passed tz. The DST flag is calculated + * according to the specified rule. + */ + local_date_time_base(date_type d, + time_duration_type td, + boost::shared_ptr tz, + DST_CALC_OPTIONS calc_option) : + // dummy value - time_ is set in constructor code + date_time::base_time(utc_time_type(d,td)), + zone_(tz) + { + time_is_dst_result result = check_dst(d, td, tz); + if(result == ambiguous) { + if(calc_option == EXCEPTION_ON_ERROR){ + std::stringstream ss; + ss << "time given: " << d << ' ' << td; + throw ambiguous_result(ss.str()); + } + else{ // NADT on error + this->time_ = posix_time::posix_time_system::get_time_rep(date_type(date_time::not_a_date_time), time_duration_type(date_time::not_a_date_time)); + } + } + else if(result == invalid_time_label){ + if(calc_option == EXCEPTION_ON_ERROR){ + std::stringstream ss; + ss << "time given: " << d << ' ' << td; + throw time_label_invalid(ss.str()); + } + else{ // NADT on error + this->time_ = posix_time::posix_time_system::get_time_rep(date_type(date_time::not_a_date_time), time_duration_type(date_time::not_a_date_time)); + } + } + else if(result == is_in_dst){ + utc_time_type t = + construction_adjustment(utc_time_type(d, td), tz, true); + this->time_ = posix_time::posix_time_system::get_time_rep(t.date(), + t.time_of_day()); + } + else{ + utc_time_type t = + construction_adjustment(utc_time_type(d, td), tz, false); + this->time_ = posix_time::posix_time_system::get_time_rep(t.date(), + t.time_of_day()); + } + } + + + //! Determines if given time label is in daylight savings for given zone + /*! Determines if given time label is in daylight savings for given zone. + * Takes a date and time_duration representing a local time, along + * with time zone, and returns a time_is_dst_result object as result. + */ + static time_is_dst_result check_dst(date_type d, + time_duration_type td, + boost::shared_ptr tz) + { + if(tz != boost::shared_ptr() && tz->has_dst()) { + typedef typename date_time::dst_calculator dst_calculator; + return dst_calculator::local_is_dst( + d, td, + tz->dst_local_start_time(d.year()).date(), + tz->dst_local_start_time(d.year()).time_of_day(), + tz->dst_local_end_time(d.year()).date(), + tz->dst_local_end_time(d.year()).time_of_day(), + tz->dst_offset() + ); + } + else{ + return is_not_in_dst; + } + } + + //! Simple destructor, releases time zone if last referrer + ~local_date_time_base() {}; + + //! Copy constructor + local_date_time_base(const local_date_time_base& rhs) : + date_time::base_time(rhs), + zone_(rhs.zone_) + {} + + //! Special values constructor + explicit local_date_time_base(const boost::date_time::special_values sv, + boost::shared_ptr tz = boost::shared_ptr()) : + date_time::base_time(utc_time_type(sv)), + zone_(tz) + {} + + //! returns time zone associated with calling instance + boost::shared_ptr zone() const + { + return zone_; + } + //! returns false is time_zone is NULL and if time value is a special_value + bool is_dst() const + { + if(zone_ != boost::shared_ptr() && zone_->has_dst() && !this->is_special()) { + // check_dst takes a local time, *this is utc + utc_time_type lt(this->time_); + lt += zone_->base_utc_offset(); + // dst_offset only needs to be considered with ambiguous time labels + // make that adjustment there + + switch(check_dst(lt.date(), lt.time_of_day(), zone_)){ + case is_not_in_dst: + return false; + case is_in_dst: + return true; + case ambiguous: + if(lt + zone_->dst_offset() < zone_->dst_local_end_time(lt.date().year())) { + return true; + } + break; + case invalid_time_label: + if(lt >= zone_->dst_local_start_time(lt.date().year())) { + return true; + } + break; + } + } + return false; + } + //! Returns object's time value as a utc representation + utc_time_type utc_time() const + { + return utc_time_type(this->time_); + } + //! Returns object's time value as a local representation + utc_time_type local_time() const + { + if(zone_ != boost::shared_ptr()){ + utc_time_type lt = this->utc_time() + zone_->base_utc_offset(); + if (is_dst()) { + lt += zone_->dst_offset(); + } + return lt; + } + return utc_time_type(this->time_); + } + //! Returns string in the form "2003-Aug-20 05:00:00 EDT" + /*! Returns string in the form "2003-Aug-20 05:00:00 EDT". If + * time_zone is NULL the time zone abbreviation will be "UTC". The time + * zone abbrev will not be included if calling object is a special_value*/ + std::string to_string() const + { + //TODO is this a temporary function ??? + std::stringstream ss; + if(this->is_special()){ + ss << utc_time(); + return ss.str(); + } + if(zone_ == boost::shared_ptr()) { + ss << utc_time() << " UTC"; + return ss.str(); + } + bool is_dst_ = is_dst(); + utc_time_type lt = this->utc_time() + zone_->base_utc_offset(); + if (is_dst_) { + lt += zone_->dst_offset(); + } + ss << local_time() << " "; + if (is_dst()) { + ss << zone_->dst_zone_abbrev(); + } + else { + ss << zone_->std_zone_abbrev(); + } + return ss.str(); + } + /*! returns a local_date_time_base in the given time zone with the + * optional time_duration added. */ + local_date_time_base local_time_in(boost::shared_ptr new_tz, + time_duration_type td=time_duration_type(0,0,0)) const + { + return local_date_time_base(utc_time_type(this->time_) + td, new_tz); + } + + //! Returns name of associated time zone or "Coordinated Universal Time". + /*! Optional bool parameter will return time zone as an offset + * (ie "+07:00" extended iso format). Empty string is returned for + * classes that do not use a time_zone */ + std::string zone_name(bool as_offset=false) const + { + if(zone_ == boost::shared_ptr()) { + if(as_offset) { + return std::string("Z"); + } + else { + return std::string("Coordinated Universal Time"); + } + } + if (is_dst()) { + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + td += zone_->dst_offset(); + return zone_as_offset(td, ":"); + } + else { + return zone_->dst_zone_name(); + } + } + else { + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + return zone_as_offset(td, ":"); + } + else { + return zone_->std_zone_name(); + } + } + } + //! Returns abbreviation of associated time zone or "UTC". + /*! Optional bool parameter will return time zone as an offset + * (ie "+0700" iso format). Empty string is returned for classes + * that do not use a time_zone */ + std::string zone_abbrev(bool as_offset=false) const + { + if(zone_ == boost::shared_ptr()) { + if(as_offset) { + return std::string("Z"); + } + else { + return std::string("UTC"); + } + } + if (is_dst()) { + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + td += zone_->dst_offset(); + return zone_as_offset(td, ""); + } + else { + return zone_->dst_zone_abbrev(); + } + } + else { + if(as_offset) { + time_duration_type td = zone_->base_utc_offset(); + return zone_as_offset(td, ""); + } + else { + return zone_->std_zone_abbrev(); + } + } + } + + //! returns a posix_time_zone string for the associated time_zone. If no time_zone, "UTC+00" is returned. + std::string zone_as_posix_string() const + { + if(zone_ == shared_ptr()) { + return std::string("UTC+00"); + } + return zone_->to_posix_string(); + } + + //! Equality comparison operator + /*bool operator==(const date_time::base_time& rhs) const + { // fails due to rhs.time_ being protected + return date_time::base_time::operator==(rhs); + //return this->time_ == rhs.time_; + }*/ + //! Equality comparison operator + bool operator==(const local_date_time_base& rhs) const + { + return time_system_type::is_equal(this->time_, rhs.time_); + } + //! Non-Equality comparison operator + bool operator!=(const local_date_time_base& rhs) const + { + return !(*this == rhs); + } + //! Less than comparison operator + bool operator<(const local_date_time_base& rhs) const + { + return time_system_type::is_less(this->time_, rhs.time_); + } + //! Less than or equal to comparison operator + bool operator<=(const local_date_time_base& rhs) const + { + return (*this < rhs || *this == rhs); + } + //! Greater than comparison operator + bool operator>(const local_date_time_base& rhs) const + { + return !(*this <= rhs); + } + //! Greater than or equal to comparison operator + bool operator>=(const local_date_time_base& rhs) const + { + return (*this > rhs || *this == rhs); + } + + //! Local_date_time + date_duration + local_date_time_base operator+(const date_duration_type& dd) const + { + return local_date_time_base(time_system_type::add_days(this->time_,dd), zone_); + } + //! Local_date_time += date_duration + local_date_time_base operator+=(const date_duration_type& dd) + { + this->time_ = time_system_type::add_days(this->time_,dd); + return *this; + } + //! Local_date_time - date_duration + local_date_time_base operator-(const date_duration_type& dd) const + { + return local_date_time_base(time_system_type::subtract_days(this->time_,dd), zone_); + } + //! Local_date_time -= date_duration + local_date_time_base operator-=(const date_duration_type& dd) + { + this->time_ = time_system_type::subtract_days(this->time_,dd); + return *this; + } + //! Local_date_time + time_duration + local_date_time_base operator+(const time_duration_type& td) const + { + return local_date_time_base(time_system_type::add_time_duration(this->time_,td), zone_); + } + //! Local_date_time += time_duration + local_date_time_base operator+=(const time_duration_type& td) + { + this->time_ = time_system_type::add_time_duration(this->time_,td); + return *this; + } + //! Local_date_time - time_duration + local_date_time_base operator-(const time_duration_type& td) const + { + return local_date_time_base(time_system_type::subtract_time_duration(this->time_,td), zone_); + } + //! Local_date_time -= time_duration + local_date_time_base operator-=(const time_duration_type& td) + { + this->time_ = time_system_type::subtract_time_duration(this->time_,td); + return *this; + } + //! local_date_time -= local_date_time --> time_duration_type + time_duration_type operator-(const local_date_time_base& rhs) const + { + return utc_time_type(this->time_) - utc_time_type(rhs.time_); + } + private: + boost::shared_ptr zone_; + //bool is_dst_; + + /*! Adjust the passed in time to UTC? + */ + utc_time_type construction_adjustment(utc_time_type t, + boost::shared_ptr z, + bool dst_flag) + { + if(z != boost::shared_ptr()) { + if(dst_flag && z->has_dst()) { + t -= z->dst_offset(); + } // else no adjust + t -= z->base_utc_offset(); + } + return t; + } + + /*! Simple formatting code -- todo remove this? + */ + std::string zone_as_offset(const time_duration_type& td, + const std::string& separator) const + { + std::stringstream ss; + if(td.is_negative()) { + // a negative duration is represented as "-[h]h:mm" + // we require two digits for the hour. A positive duration + // with the %H flag will always give two digits + ss << "-"; + } + else { + ss << "+"; + } + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.hours()) + << separator + << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.minutes()); + return ss.str(); + } + }; + + //!Use the default parameters to define local_date_time + typedef local_date_time_base<> local_date_time; + +} } + + +#endif diff --git a/win32/include/boost/date_time/local_time/local_time.hpp b/win32/include/boost/date_time/local_time/local_time.hpp new file mode 100755 index 000000000..978ea4ab2 --- /dev/null +++ b/win32/include/boost/date_time/local_time/local_time.hpp @@ -0,0 +1,24 @@ +#ifndef LOCAL_TIME_LOCAL_TIME_HPP__ +#define LOCAL_TIME_LOCAL_TIME_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/posix_time/posix_time.hpp" +#include "boost/date_time/local_time/local_date_time.hpp" +#include "boost/date_time/local_time/local_time_types.hpp" +#if !defined(USE_DATE_TIME_PRE_1_33_FACET_IO) +#include "boost/date_time/local_time/local_time_io.hpp" +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO +#include "boost/date_time/local_time/posix_time_zone.hpp" +#include "boost/date_time/local_time/custom_time_zone.hpp" +#include "boost/date_time/local_time/tz_database.hpp" +#include "boost/date_time/local_time/conversion.hpp" +#include "boost/date_time/time_zone_base.hpp" + + +#endif diff --git a/win32/include/boost/date_time/local_time/local_time_io.hpp b/win32/include/boost/date_time/local_time/local_time_io.hpp new file mode 100755 index 000000000..717def985 --- /dev/null +++ b/win32/include/boost/date_time/local_time/local_time_io.hpp @@ -0,0 +1,118 @@ +#ifndef BOOST_DATE_TIME_LOCAL_TIME_IO_HPP__ +#define BOOST_DATE_TIME_LOCAL_TIME_IO_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include +#include "boost/date_time/local_time/local_date_time.hpp" +#include "boost/date_time/local_time/posix_time_zone.hpp" +#include "boost/date_time/time_facet.hpp" +#include "boost/date_time/string_convert.hpp" +#include "boost/io/ios_state.hpp" + +namespace boost { +namespace local_time { + + typedef boost::date_time::time_facet wlocal_time_facet; + typedef boost::date_time::time_facet local_time_facet; + + typedef boost::date_time::time_input_facet wlocal_time_input_facet; + typedef boost::date_time::time_input_facet local_time_input_facet; + + //! operator<< for local_date_time - see local_time docs for formatting details + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const local_date_time& ldt) + { + boost::io::ios_flags_saver iflags(os); + typedef local_date_time time_type;//::utc_time_type typename + typedef date_time::time_facet custom_time_facet; + typedef std::time_put std_time_facet; + std::ostreambuf_iterator oitr(os); + + if(std::has_facet(os.getloc())) { + std::use_facet(os.getloc()).put(oitr, + os, + os.fill(), + ldt); + } + else { + custom_time_facet* f = new custom_time_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), ldt); + } + + return os; + } + + + //! input operator for local_date_time + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, local_date_time& ldt) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename local_date_time::utc_time_type utc_time_type; + typedef typename date_time::time_input_facet time_input_facet; + + // intermediate objects + std::basic_string tz_str; + utc_time_type pt(not_a_date_time); + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get_local_time(sit, str_end, is, pt, tz_str); + } + else { + time_input_facet* f = new time_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get_local_time(sit, str_end, is, pt, tz_str); + } + if(tz_str.empty()) { + time_zone_ptr null_ptr; + // a null time_zone_ptr creates a local_date_time that is UTC + ldt = local_date_time(pt, null_ptr); + } + else { + time_zone_ptr tz_ptr(new posix_time_zone(date_time::convert_string_type(tz_str))); + // the "date & time" constructor expects the time label to *not* be utc. + // a posix_tz_string also expects the time label to *not* be utc. + ldt = local_date_time(pt.date(), pt.time_of_day(), tz_ptr, local_date_time::EXCEPTION_ON_ERROR); + } + } + catch(...) { + // mask tells us what exceptions are turned on + std::ios_base::iostate exception_mask = is.exceptions(); + // if the user wants exceptions on failbit, we'll rethrow our + // date_time exception & set the failbit + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} // ignore this one + throw; // rethrow original exception + } + else { + // if the user want's to fail quietly, we simply set the failbit + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + +} } // namespaces + +#endif // BOOST_DATE_TIME_LOCAL_TIME_IO_HPP__ diff --git a/win32/include/boost/date_time/local_time/local_time_types.hpp b/win32/include/boost/date_time/local_time/local_time_types.hpp new file mode 100755 index 000000000..84d852f82 --- /dev/null +++ b/win32/include/boost/date_time/local_time/local_time_types.hpp @@ -0,0 +1,52 @@ +#ifndef LOCAL_TIME_LOCAL_TIME_TYPES_HPP__ +#define LOCAL_TIME_LOCAL_TIME_TYPES_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/local_time/local_date_time.hpp" +#include "boost/date_time/period.hpp" +#include "boost/date_time/time_iterator.hpp" +#include "boost/date_time/compiler_config.hpp" +#if defined(BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES) +#include "boost/date_time/local_time/date_duration_operators.hpp" +#endif //BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES +#include "boost/date_time/local_time/custom_time_zone.hpp" + +namespace boost { +namespace local_time { + + typedef boost::date_time::period local_time_period; + + typedef date_time::time_itr local_time_iterator; + + typedef date_time::second_clock local_sec_clock; + typedef date_time::microsec_clock local_microsec_clock; + + typedef date_time::time_zone_base time_zone; + typedef date_time::time_zone_base wtime_zone; + + //! Shared Pointer for custom_time_zone and posix_time_zone objects + typedef boost::shared_ptr time_zone_ptr; + typedef boost::shared_ptr wtime_zone_ptr; + + typedef date_time::time_zone_names_base time_zone_names; + typedef date_time::time_zone_names_base wtime_zone_names; + + //bring special enum values into the namespace + using date_time::special_values; + using date_time::not_special; + using date_time::neg_infin; + using date_time::pos_infin; + using date_time::not_a_date_time; + using date_time::max_date_time; + using date_time::min_date_time; + +}} // namespaces + +#endif // LOCAL_TIME_LOCAL_TIME_TYPES_HPP__ diff --git a/win32/include/boost/date_time/local_time/posix_time_zone.hpp b/win32/include/boost/date_time/local_time/posix_time_zone.hpp new file mode 100755 index 000000000..fcc56cc3e --- /dev/null +++ b/win32/include/boost/date_time/local_time/posix_time_zone.hpp @@ -0,0 +1,443 @@ +#ifndef _DATE_TIME_POSIX_TIME_ZONE__ +#define _DATE_TIME_POSIX_TIME_ZONE__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include +#include +#include "boost/date_time/gregorian/gregorian.hpp" +#include "boost/date_time/time_zone_names.hpp" +#include "boost/date_time/time_zone_base.hpp" +#include "boost/date_time/local_time/dst_transition_day_rules.hpp" +#include "boost/date_time/posix_time/posix_time.hpp" +#include "boost/date_time/string_convert.hpp" +#include "boost/date_time/time_parsing.hpp" +#include "boost/tokenizer.hpp" +#include + +namespace boost{ +namespace local_time{ + + //! simple exception for UTC and Daylight savings start/end offsets + struct bad_offset : public std::out_of_range + { + bad_offset(std::string _msg="") : std::out_of_range(std::string("Offset out of range: " + _msg)) {} + }; + //! simple exception for UTC daylight savings adjustment + struct bad_adjustment : public std::out_of_range + { + bad_adjustment(std::string _msg="") : std::out_of_range(std::string("Adjustment out of range: " + _msg)) {} + }; + + typedef boost::date_time::dst_adjustment_offsets dst_adjustment_offsets; + + //! A time zone class constructed from a POSIX time zone string + /*! A POSIX time zone string takes the form of:
+ * "std offset dst [offset],start[/time],end[/time]" (w/no spaces) + * 'std' specifies the abbrev of the time zone.
+ * 'offset' is the offset from UTC.
+ * 'dst' specifies the abbrev of the time zone during daylight savings time.
+ * The second offset is how many hours changed during DST. Default=1
+ * 'start' and'end' are the dates when DST goes into (and out of) effect.
+ * 'offset' takes the form of: [+|-]hh[:mm[:ss]] {h=0-23, m/s=0-59}
+ * 'time' and 'offset' take the same form. Time defaults=02:00:00
+ * 'start' and 'end' can be one of three forms:
+ * Mm.w.d {month=1-12, week=1-5 (5 is always last), day=0-6}
+ * Jn {n=1-365 Feb29 is never counted}
+ * n {n=0-365 Feb29 is counted in leap years}
+ * Example "PST-5PDT01:00:00,M4.1.0/02:00:00,M10.1.0/02:00:00" + *
+ * Exceptions will be thrown under these conditions:
+ * An invalid date spec (see date class)
+ * A boost::local_time::bad_offset exception will be thrown for:
+ * A DST start or end offset that is negative or more than 24 hours
+ * A UTC zone that is greater than +12 or less than -12 hours
+ * A boost::local_time::bad_adjustment exception will be thrown for:
+ * A DST adjustment that is 24 hours or more (positive or negative)
+ */ + template + class posix_time_zone_base : public date_time::time_zone_base { + public: + typedef boost::posix_time::time_duration time_duration_type; + typedef date_time::time_zone_names_base time_zone_names; + typedef date_time::time_zone_base base_type; + typedef typename base_type::string_type string_type; + typedef CharT char_type; + typedef typename base_type::stringstream_type stringstream_type; + typedef boost::char_separator > char_separator_type; + typedef boost::tokenizer tokenizer_type; + typedef typename boost::tokenizer::iterator tokenizer_iterator_type; + + //! Construct from a POSIX time zone string + posix_time_zone_base(const string_type& s) : + //zone_names_("std_name","std_abbrev","no-dst","no-dst"), + zone_names_(), + has_dst_(false), + base_utc_offset_(posix_time::hours(0)), + dst_offsets_(posix_time::hours(0),posix_time::hours(0),posix_time::hours(0)), + dst_calc_rules_() + { + const char_type sep_chars[2] = {','}; + char_separator_type sep(sep_chars); + tokenizer_type tokens(s, sep); + tokenizer_iterator_type it = tokens.begin(); + calc_zone(*it++); + if(has_dst_){ + string_type tmp_str = *it++; + calc_rules(tmp_str, *it); + } + } + virtual ~posix_time_zone_base() {}; + //!String for the zone when not in daylight savings (eg: EST) + virtual string_type std_zone_abbrev()const + { + return zone_names_.std_zone_abbrev(); + } + //!String for the timezone when in daylight savings (eg: EDT) + /*! For those time zones that have no DST, an empty string is used */ + virtual string_type dst_zone_abbrev() const + { + return zone_names_.dst_zone_abbrev(); + } + //!String for the zone when not in daylight savings (eg: Eastern Standard Time) + /*! The full STD name is not extracted from the posix time zone string. + * Therefore, the STD abbreviation is used in it's place */ + virtual string_type std_zone_name()const + { + return zone_names_.std_zone_name(); + } + //!String for the timezone when in daylight savings (eg: Eastern Daylight Time) + /*! The full DST name is not extracted from the posix time zone string. + * Therefore, the STD abbreviation is used in it's place. For time zones + * that have no DST, an empty string is used */ + virtual string_type dst_zone_name()const + { + return zone_names_.dst_zone_name(); + } + //! True if zone uses daylight savings adjustments otherwise false + virtual bool has_dst()const + { + return has_dst_; + } + //! Local time that DST starts -- NADT if has_dst is false + virtual posix_time::ptime dst_local_start_time(gregorian::greg_year y)const + { + gregorian::date d(gregorian::not_a_date_time); + if(has_dst_) + { + d = dst_calc_rules_->start_day(y); + } + return posix_time::ptime(d, dst_offsets_.dst_start_offset_); + } + //! Local time that DST ends -- NADT if has_dst is false + virtual posix_time::ptime dst_local_end_time(gregorian::greg_year y)const + { + gregorian::date d(gregorian::not_a_date_time); + if(has_dst_) + { + d = dst_calc_rules_->end_day(y); + } + return posix_time::ptime(d, dst_offsets_.dst_end_offset_); + } + //! Base offset from UTC for zone (eg: -07:30:00) + virtual time_duration_type base_utc_offset()const + { + return base_utc_offset_; + } + //! Adjustment forward or back made while DST is in effect + virtual time_duration_type dst_offset()const + { + return dst_offsets_.dst_adjust_; + } + + //! Returns a POSIX time_zone string for this object + virtual string_type to_posix_string() const + { + // std offset dst [offset],start[/time],end[/time] - w/o spaces + stringstream_type ss; + ss.fill('0'); + boost::shared_ptr no_rules; + // std + ss << std_zone_abbrev(); + // offset + if(base_utc_offset().is_negative()) { + // inverting the sign guarantees we get two digits + ss << '-' << std::setw(2) << base_utc_offset().invert_sign().hours(); + } + else { + ss << '+' << std::setw(2) << base_utc_offset().hours(); + } + if(base_utc_offset().minutes() != 0 || base_utc_offset().seconds() != 0) { + ss << ':' << std::setw(2) << base_utc_offset().minutes(); + if(base_utc_offset().seconds() != 0) { + ss << ':' << std::setw(2) << base_utc_offset().seconds(); + } + } + if(dst_calc_rules_ != no_rules) { + // dst + ss << dst_zone_abbrev(); + // dst offset + if(dst_offset().is_negative()) { + // inverting the sign guarantees we get two digits + ss << '-' << std::setw(2) << dst_offset().invert_sign().hours(); + } + else { + ss << '+' << std::setw(2) << dst_offset().hours(); + } + if(dst_offset().minutes() != 0 || dst_offset().seconds() != 0) { + ss << ':' << std::setw(2) << dst_offset().minutes(); + if(dst_offset().seconds() != 0) { + ss << ':' << std::setw(2) << dst_offset().seconds(); + } + } + // start/time + ss << ',' << date_time::convert_string_type(dst_calc_rules_->start_rule_as_string()) << '/' + << std::setw(2) << dst_offsets_.dst_start_offset_.hours() << ':' + << std::setw(2) << dst_offsets_.dst_start_offset_.minutes(); + if(dst_offsets_.dst_start_offset_.seconds() != 0) { + ss << ':' << std::setw(2) << dst_offsets_.dst_start_offset_.seconds(); + } + // end/time + ss << ',' << date_time::convert_string_type(dst_calc_rules_->end_rule_as_string()) << '/' + << std::setw(2) << dst_offsets_.dst_end_offset_.hours() << ':' + << std::setw(2) << dst_offsets_.dst_end_offset_.minutes(); + if(dst_offsets_.dst_end_offset_.seconds() != 0) { + ss << ':' << std::setw(2) << dst_offsets_.dst_end_offset_.seconds(); + } + } + + return ss.str(); + } + private: + time_zone_names zone_names_; + bool has_dst_; + time_duration_type base_utc_offset_; + dst_adjustment_offsets dst_offsets_; + boost::shared_ptr dst_calc_rules_; + + /*! Extract time zone abbreviations for STD & DST as well + * as the offsets for the time shift that occurs and how + * much of a shift. At this time full time zone names are + * NOT extracted so the abbreviations are used in their place */ + void calc_zone(const string_type& obj){ + const char_type empty_string[2] = {'\0'}; + stringstream_type ss(empty_string); + typename string_type::const_iterator sit = obj.begin(); + string_type l_std_zone_abbrev, l_dst_zone_abbrev; + + // get 'std' name/abbrev + while(std::isalpha(*sit)){ + ss << *sit++; + } + l_std_zone_abbrev = ss.str(); + ss.str(empty_string); + + // get UTC offset + if(sit != obj.end()){ + // get duration + while(sit != obj.end() && !std::isalpha(*sit)){ + ss << *sit++; + } + base_utc_offset_ = date_time::str_from_delimited_time_duration(ss.str()); + ss.str(empty_string); + + // base offset must be within range of -12 hours to +12 hours + if(base_utc_offset_ < time_duration_type(-12,0,0) || + base_utc_offset_ > time_duration_type(12,0,0)) + { + throw bad_offset(posix_time::to_simple_string(base_utc_offset_)); + } + } + + // get DST data if given + if(sit != obj.end()){ + has_dst_ = true; + + // get 'dst' name/abbrev + while(sit != obj.end() && std::isalpha(*sit)){ + ss << *sit++; + } + l_dst_zone_abbrev = ss.str(); + ss.str(empty_string); + + // get DST offset if given + if(sit != obj.end()){ + // get duration + while(sit != obj.end() && !std::isalpha(*sit)){ + ss << *sit++; + } + dst_offsets_.dst_adjust_ = date_time::str_from_delimited_time_duration(ss.str()); + ss.str(empty_string); + } + else{ // default DST offset + dst_offsets_.dst_adjust_ = posix_time::hours(1); + } + + // adjustment must be within +|- 1 day + if(dst_offsets_.dst_adjust_ <= time_duration_type(-24,0,0) || + dst_offsets_.dst_adjust_ >= time_duration_type(24,0,0)) + { + throw bad_adjustment(posix_time::to_simple_string(dst_offsets_.dst_adjust_)); + } + } + // full names not extracted so abbrevs used in their place + zone_names_ = time_zone_names(l_std_zone_abbrev, l_std_zone_abbrev, l_dst_zone_abbrev, l_dst_zone_abbrev); + } + + void calc_rules(const string_type& start, const string_type& end){ + const char_type sep_chars[2] = {'/'}; + char_separator_type sep(sep_chars); + tokenizer_type st_tok(start, sep); + tokenizer_type et_tok(end, sep); + tokenizer_iterator_type sit = st_tok.begin(); + tokenizer_iterator_type eit = et_tok.begin(); + + // generate date spec + char_type x = string_type(*sit).at(0); + if(x == 'M'){ + M_func(*sit, *eit); + } + else if(x == 'J'){ + julian_no_leap(*sit, *eit); + } + else{ + julian_day(*sit, *eit); + } + + ++sit; + ++eit; + // generate durations + // starting offset + if(sit != st_tok.end()){ + dst_offsets_.dst_start_offset_ = date_time::str_from_delimited_time_duration(*sit); + } + else{ + // default + dst_offsets_.dst_start_offset_ = posix_time::hours(2); + } + // start/end offsets must fall on given date + if(dst_offsets_.dst_start_offset_ < time_duration_type(0,0,0) || + dst_offsets_.dst_start_offset_ >= time_duration_type(24,0,0)) + { + throw bad_offset(posix_time::to_simple_string(dst_offsets_.dst_start_offset_)); + } + + // ending offset + if(eit != et_tok.end()){ + dst_offsets_.dst_end_offset_ = date_time::str_from_delimited_time_duration(*eit); + } + else{ + // default + dst_offsets_.dst_end_offset_ = posix_time::hours(2); + } + // start/end offsets must fall on given date + if(dst_offsets_.dst_end_offset_ < time_duration_type(0,0,0) || + dst_offsets_.dst_end_offset_ >= time_duration_type(24,0,0)) + { + throw bad_offset(posix_time::to_simple_string(dst_offsets_.dst_end_offset_)); + } + } + + /* Parses out a start/end date spec from a posix time zone string. + * Date specs come in three possible formats, this function handles + * the 'M' spec. Ex "M2.2.4" => 2nd month, 2nd week, 4th day . + */ + void M_func(const string_type& s, const string_type& e){ + typedef gregorian::nth_kday_of_month nkday; + unsigned short sm=0,sw=0,sd=0,em=0,ew=0,ed=0; // start/end month,week,day + const char_type sep_chars[3] = {'M','.'}; + char_separator_type sep(sep_chars); + tokenizer_type stok(s, sep), etok(e, sep); + + tokenizer_iterator_type it = stok.begin(); + sm = lexical_cast(*it++); + sw = lexical_cast(*it++); + sd = lexical_cast(*it); + + it = etok.begin(); + em = lexical_cast(*it++); + ew = lexical_cast(*it++); + ed = lexical_cast(*it); + + dst_calc_rules_ = shared_ptr( + new nth_kday_dst_rule( + nth_last_dst_rule::start_rule( + static_cast(sw),sd,sm), + nth_last_dst_rule::start_rule( + static_cast(ew),ed,em) + ) + ); + } + + //! Julian day. Feb29 is never counted, even in leap years + // expects range of 1-365 + void julian_no_leap(const string_type& s, const string_type& e){ + typedef gregorian::gregorian_calendar calendar; + const unsigned short year = 2001; // Non-leap year + unsigned short sm=1; + int sd=0; + sd = lexical_cast(s.substr(1)); // skip 'J' + while(sd >= calendar::end_of_month_day(year,sm)){ + sd -= calendar::end_of_month_day(year,sm++); + } + unsigned short em=1; + int ed=0; + ed = lexical_cast(e.substr(1)); // skip 'J' + while(ed > calendar::end_of_month_day(year,em)){ + ed -= calendar::end_of_month_day(year,em++); + } + + dst_calc_rules_ = shared_ptr( + new partial_date_dst_rule( + partial_date_dst_rule::start_rule( + sd, static_cast(sm)), + partial_date_dst_rule::end_rule( + ed, static_cast(em)) + ) + ); + } + + //! Julian day. Feb29 is always counted, but exception thrown in non-leap years + // expects range of 0-365 + void julian_day(const string_type& s, const string_type& e){ + int sd=0, ed=0; + sd = lexical_cast(s); + ed = lexical_cast(e); + dst_calc_rules_ = shared_ptr( + new partial_date_dst_rule( + partial_date_dst_rule::start_rule(++sd),// args are 0-365 + partial_date_dst_rule::end_rule(++ed) // pd expects 1-366 + ) + ); + } + + //! helper function used when throwing exceptions + static std::string td_as_string(const time_duration_type& td) + { + std::string s; +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) + s = posix_time::to_simple_string(td); +#else + std::stringstream ss; + ss << td; + s = ss.str(); +#endif + return s; + } + }; + + typedef posix_time_zone_base posix_time_zone; + +} } // namespace boost::local_time + + +#endif // _DATE_TIME_POSIX_TIME_ZONE__ diff --git a/win32/include/boost/date_time/local_time/tz_database.hpp b/win32/include/boost/date_time/local_time/tz_database.hpp new file mode 100755 index 000000000..2fe845769 --- /dev/null +++ b/win32/include/boost/date_time/local_time/tz_database.hpp @@ -0,0 +1,32 @@ +#ifndef BOOST_DATE_TIME_TZ_DATABASE_HPP__ +#define BOOST_DATE_TIME_TZ_DATABASE_HPP__ + +/* Copyright (c) 2003-2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include +#include "boost/date_time/local_time/custom_time_zone.hpp" +#include "boost/date_time/local_time/dst_transition_day_rules.hpp" +#include "boost/date_time/tz_db_base.hpp" + + +namespace boost { +namespace local_time { + + using date_time::data_not_accessible; + using date_time::bad_field_count; + + //! Object populated with boost::shared_ptr objects + /*! Object populated with boost::shared_ptr objects + * Database is populated from specs stored in external csv file. See + * date_time::tz_db_base for greater detail */ + typedef date_time::tz_db_base tz_database; + +}} // namespace + +#endif // BOOST_DATE_TIME_TZ_DATABASE_HPP__ + diff --git a/win32/include/boost/date_time/local_time_adjustor.hpp b/win32/include/boost/date_time/local_time_adjustor.hpp new file mode 100755 index 000000000..2e8e331dc --- /dev/null +++ b/win32/include/boost/date_time/local_time_adjustor.hpp @@ -0,0 +1,213 @@ +#ifndef DATE_TIME_LOCAL_TIME_ADJUSTOR_HPP__ +#define DATE_TIME_LOCAL_TIME_ADJUSTOR_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! @file local_time_adjustor.hpp + Time adjustment calculations for local times +*/ + +#include "boost/date_time/date_generators.hpp" +#include "boost/date_time/dst_rules.hpp" +#include + +namespace boost { + namespace date_time { + + + //! Provides a base offset adjustment from utc + template + class utc_adjustment + { + public: + static time_duration_type local_to_utc_base_offset() + { + time_duration_type td(hours,minutes,0); + return td.invert_sign(); + } + static time_duration_type utc_to_local_base_offset() + { + return time_duration_type(hours,minutes,0); + } + }; + + + + //! Allow sliding utc adjustment with fixed dst rules + template + class dynamic_local_time_adjustor : public dst_rules + { + public: + typedef typename time_type::time_duration_type time_duration_type; + typedef typename time_type::date_type date_type; + + dynamic_local_time_adjustor(time_duration_type utc_offset) : + utc_offset_(utc_offset) + {} + + //! Presumes local time + time_duration_type utc_offset(bool is_dst) + { + if (is_dst) { + return utc_offset_ + this->dst_offset(); + } + else { + return utc_offset_; + } + + } + private: + time_duration_type utc_offset_; + + }; + + + + //! Embed the rules for local time adjustments at compile time + template + class static_local_time_adjustor: public dst_rules, public utc_offset_rules + { + public: + typedef typename time_type::time_duration_type time_duration_type; + typedef typename time_type::date_type date_type; + + //! Calculates the offset from a utc time to local based on dst and utc offset + /*! @param t UTC time to calculate offset to local time + * This adjustment depends on the following observations about the + * workings of the DST boundary offset. Since UTC time labels are + * monotonically increasing we can determine if a given local time + * is in DST or not and therefore adjust the offset appropriately. + * + * The logic is as follows. Starting with UTC time use the offset to + * create a label for an non-dst adjusted local time. Then call + * dst_rules::local_is_dst with the non adjust local time. The + * results of this function will either unabiguously decide that + * the initial local time is in dst or return an illegal or + * ambiguous result. An illegal result only occurs at the end + * of dst (where labels are skipped) and indicates that dst has + * ended. An ambiguous result means that we need to recheck by + * making a dst adjustment and then rechecking. If the dst offset + * is added to the utc time and the recheck proves non-ambiguous + * then we are past the boundary. If it is still ambiguous then + * we are ahead of the boundary and dst is still in effect. + * + * TODO -- check if all dst offsets are positive. If not then + * the algorithm needs to check for this and reverse the + * illegal/ambiguous logic. + */ + static time_duration_type utc_to_local_offset(const time_type& t) + { + //get initial local time guess by applying utc offset + time_type initial = t + utc_offset_rules::utc_to_local_base_offset(); + time_is_dst_result dst_flag = + dst_rules::local_is_dst(initial.date(), initial.time_of_day()); + switch(dst_flag) { + case is_in_dst: return utc_offset_rules::utc_to_local_base_offset() + dst_rules::dst_offset(); + case is_not_in_dst: return utc_offset_rules::utc_to_local_base_offset(); + case invalid_time_label:return utc_offset_rules::utc_to_local_base_offset() + dst_rules::dst_offset(); + case ambiguous: { + time_type retry = initial + dst_rules::dst_offset(); + dst_flag = dst_rules::local_is_dst(retry.date(), retry.time_of_day()); + //if still ambibuous then the utc time still translates to a dst time + if (dst_flag == ambiguous) { + return utc_offset_rules::utc_to_local_base_offset() + dst_rules::dst_offset(); + } + // we are past the dst boundary + else { + return utc_offset_rules::utc_to_local_base_offset(); + } + } + }//case + //TODO better excpetion type + throw std::out_of_range("Unreachable case"); + + } + + //! Get the offset to UTC given a local time + static time_duration_type local_to_utc_offset(const time_type& t, + date_time::dst_flags dst=date_time::calculate) + { + switch (dst) { + case is_dst: + return utc_offset_rules::local_to_utc_base_offset() - dst_rules::dst_offset(); + case not_dst: + return utc_offset_rules::local_to_utc_base_offset(); + case calculate: + time_is_dst_result res = + dst_rules::local_is_dst(t.date(), t.time_of_day()); + switch(res) { + case is_in_dst: return utc_offset_rules::local_to_utc_base_offset() - dst_rules::dst_offset(); + case is_not_in_dst: return utc_offset_rules::local_to_utc_base_offset(); + case ambiguous: return utc_offset_rules::local_to_utc_base_offset(); + case invalid_time_label: throw std::out_of_range("Time label invalid"); + } + } + throw std::out_of_range("Time label invalid"); + } + + + private: + + }; + + void dummy_to_prevent_msvc6_ice(); //why ask why? + + //! Template that simplifies the creation of local time calculator + /*! Use this template to create the timezone to utc convertors as required. + * + * This class will also work for other regions that don't use dst and + * have a utc offset which is an integral number of hours. + * + * Template Parameters + * -time_type -- Time class to use + * -utc_offset -- Number hours local time is adjust from utc + * -use_dst -- true (default) if region uses dst, false otherwise + * For example: + * @code + * //eastern timezone is utc-5 + typedef date_time::local_adjustor us_eastern; + typedef date_time::local_adjustor us_central; + typedef date_time::local_adjustor us_mountain; + typedef date_time::local_adjustor us_pacific; + typedef date_time::local_adjustor us_arizona; + @endcode + + */ + template + class local_adjustor + { + public: + typedef typename time_type::time_duration_type time_duration_type; + typedef typename time_type::date_type date_type; + typedef static_local_time_adjustor > dst_adjustor; + //! Convert a utc time to local time + static time_type utc_to_local(const time_type& t) + { + time_duration_type td = dst_adjustor::utc_to_local_offset(t); + return t + td; + } + //! Convert a local time to utc + static time_type local_to_utc(const time_type& t, + date_time::dst_flags dst=date_time::calculate) + { + time_duration_type td = dst_adjustor::local_to_utc_offset(t, dst); + return t + td; + } + }; + + + } } //namespace date_time + + + +#endif diff --git a/win32/include/boost/date_time/local_timezone_defs.hpp b/win32/include/boost/date_time/local_timezone_defs.hpp new file mode 100755 index 000000000..d58197a46 --- /dev/null +++ b/win32/include/boost/date_time/local_timezone_defs.hpp @@ -0,0 +1,193 @@ +#ifndef DATE_TIME_LOCAL_TIMEZONE_DEFS_HPP__ +#define DATE_TIME_LOCAL_TIMEZONE_DEFS_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/dst_rules.hpp" + +namespace boost { + namespace date_time { + + // Configurations for common dst rules cases: + // See http://www.wharton.co.uk/Support/sup_dst.htm for more + // information on how various locales use dst rules + + //! Specification for daylight savings start rules in US + /*! This class is used to configure dst_calc_engine template typically + as follows: + @code + using namespace boost::gregorian; + using namespace boost::posix_time; + typedef us_dst_trait us_dst_traits; + typedef boost::date_time::dst_calc_engine + us_dst_calc; + //calculate the 2002 transition day of USA April 7 2002 + date dst_start = us_dst_calc::local_dst_start_day(2002); + + //calculate the 2002 transition day of USA Oct 27 2002 + date dst_end = us_dst_calc::local_dst_end_day(2002); + + //check if a local time is in dst or not -- posible answers + //are yes, no, invalid time label, ambiguous + ptime t(...some time...); + if (us_dst::local_is_dst(t.date(), t.time_of_day()) + == boost::date_time::is_not_in_dst) + { + + } + + @endcode + This generates a type suitable for the calculation of dst + transitions for the United States. Of course other templates + can be used for other locales. + + */ + + template + struct us_dst_trait + { + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::month_type month_type; + typedef typename date_type::year_type year_type; + typedef date_time::nth_kday_of_month start_rule_functor; + typedef date_time::first_kday_of_month end_rule_functor; + typedef date_time::first_kday_of_month start_rule_functor_pre2007; + typedef date_time::last_kday_of_month end_rule_functor_pre2007; + static day_of_week_type start_day(year_type) {return Sunday;} + static month_type start_month(year_type y) + { + if (y < 2007) return Apr; + return Mar; + } + static day_of_week_type end_day(year_type y) {return Sunday;} + static month_type end_month(year_type y) + { + if (y < 2007) return Oct; + return Nov; + } + static date_type local_dst_start_day(year_type year) + { + if (year < 2007) { + start_rule_functor_pre2007 start1(start_day(year), + start_month(year)); + return start1.get_date(year); + } + start_rule_functor start(start_rule_functor::second, + start_day(year), + start_month(year)); + return start.get_date(year); + + } + static date_type local_dst_end_day(year_type year) + { + if (year < 2007) { + end_rule_functor_pre2007 end_rule(end_day(year), + end_month(year)); + return end_rule.get_date(year); + } + end_rule_functor end(end_day(year), + end_month(year)); + return end.get_date(year); + } + static int dst_start_offset_minutes() { return 120;} + static int dst_end_offset_minutes() { return 120; } + static int dst_shift_length_minutes() { return 60; } + }; + + //!Rules for daylight savings start in the EU (Last Sun in Mar) + /*!These amount to the following: + - Start of dst day is last Sunday in March + - End day of dst is last Sunday in Oct + - Going forward switch time is 2:00 am (offset 120 minutes) + - Going back switch time is 3:00 am (off set 180 minutes) + - Shift duration is one hour (60 minutes) + */ + template + struct eu_dst_trait + { + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::month_type month_type; + typedef typename date_type::year_type year_type; + typedef date_time::last_kday_of_month start_rule_functor; + typedef date_time::last_kday_of_month end_rule_functor; + static day_of_week_type start_day(year_type) {return Sunday;} + static month_type start_month(year_type) {return Mar;} + static day_of_week_type end_day(year_type) {return Sunday;} + static month_type end_month(year_type) {return Oct;} + static int dst_start_offset_minutes() { return 120;} + static int dst_end_offset_minutes() { return 180; } + static int dst_shift_length_minutes() { return 60; } + static date_type local_dst_start_day(year_type year) + { + start_rule_functor start(start_day(year), + start_month(year)); + return start.get_date(year); + } + static date_type local_dst_end_day(year_type year) + { + end_rule_functor end(end_day(year), + end_month(year)); + return end.get_date(year); + } + }; + + //! Alternative dst traits for some parts of the United Kingdom + /* Several places in the UK use EU start and end rules for the + day, but different local conversion times (eg: forward change at 1:00 + am local and backward change at 2:00 am dst instead of 2:00am + forward and 3:00am back for the EU). + */ + template + struct uk_dst_trait : public eu_dst_trait + { + static int dst_start_offset_minutes() { return 60;} + static int dst_end_offset_minutes() { return 120; } + static int dst_shift_length_minutes() { return 60; } + }; + + //Rules for Adelaide Australia + template + struct acst_dst_trait + { + typedef typename date_type::day_of_week_type day_of_week_type; + typedef typename date_type::month_type month_type; + typedef typename date_type::year_type year_type; + typedef date_time::last_kday_of_month start_rule_functor; + typedef date_time::last_kday_of_month end_rule_functor; + static day_of_week_type start_day(year_type) {return Sunday;} + static month_type start_month(year_type) {return Oct;} + static day_of_week_type end_day(year_type) {return Sunday;} + static month_type end_month(year_type) {return Mar;} + static int dst_start_offset_minutes() { return 120;} + static int dst_end_offset_minutes() { return 180; } + static int dst_shift_length_minutes() { return 60; } + static date_type local_dst_start_day(year_type year) + { + start_rule_functor start(start_day(year), + start_month(year)); + return start.get_date(year); + } + static date_type local_dst_end_day(year_type year) + { + end_rule_functor end(end_day(year), + end_month(year)); + return end.get_date(year); + } + }; + + + + + + +} } //namespace boost::date_time + + +#endif diff --git a/win32/include/boost/date_time/locale_config.hpp b/win32/include/boost/date_time/locale_config.hpp new file mode 100755 index 000000000..003d841be --- /dev/null +++ b/win32/include/boost/date_time/locale_config.hpp @@ -0,0 +1,31 @@ +#ifndef DATE_TIME_LOCALE_CONFIG_HPP___ +#define DATE_TIME_LOCALE_CONFIG_HPP___ + +/* Copyright (c) 2002-2006 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +// This file configures whether the library will support locales and hence +// iostream based i/o. Even if a compiler has some support for locales, +// any failure to be compatible gets the compiler on the exclusion list. +// +// At the moment this is defined for MSVC 6 and any compiler that +// defines BOOST_NO_STD_LOCALE (gcc 2.95.x) + +#include "boost/config.hpp" //sets BOOST_NO_STD_LOCALE +#include "boost/detail/workaround.hpp" + +//This file basically becomes a noop if locales are not properly supported +#if (defined(BOOST_NO_STD_LOCALE) \ + || (BOOST_WORKAROUND( BOOST_MSVC, < 1300)) \ + || (BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x581 )) ) ) +#define BOOST_DATE_TIME_NO_LOCALE +#endif + + +#endif + diff --git a/win32/include/boost/date_time/microsec_time_clock.hpp b/win32/include/boost/date_time/microsec_time_clock.hpp new file mode 100755 index 000000000..ce2556367 --- /dev/null +++ b/win32/include/boost/date_time/microsec_time_clock.hpp @@ -0,0 +1,205 @@ +#ifndef DATE_TIME_HIGHRES_TIME_CLOCK_HPP___ +#define DATE_TIME_HIGHRES_TIME_CLOCK_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +/*! @file microsec_time_clock.hpp + This file contains a high resolution time clock implementation. +*/ + +#include +#include "boost/date_time/c_time.hpp" +#include "boost/date_time/time_clock.hpp" +#include "boost/cstdint.hpp" +#include "boost/shared_ptr.hpp" + +#ifdef BOOST_HAS_FTIME +#include +#endif + +#ifdef BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK + +namespace boost { +namespace date_time { + + + //! A clock providing microsecond level resolution + /*! A high precision clock that measures the local time + * at a resolution up to microseconds and adjusts to the + * resolution of the time system. For example, for the + * a library configuration with nano second resolution, + * the last 3 places of the fractional seconds will always + * be 000 since there are 1000 nano-seconds in a micro second. + */ + template + class microsec_clock + { + public: + typedef typename time_type::date_type date_type; + typedef typename time_type::time_duration_type time_duration_type; + typedef typename time_duration_type::rep_type resolution_traits_type; + + //! return a local time object for the given zone, based on computer clock + //JKG -- looks like we could rewrite this against universal_time + template + static time_type local_time(shared_ptr tz_ptr) { + typedef typename time_type::utc_time_type utc_time_type; + typedef second_clock second_clock; + // we'll need to know the utc_offset this machine has + // in order to get a utc_time_type set to utc + utc_time_type utc_time = second_clock::universal_time(); + time_duration_type utc_offset = second_clock::local_time() - utc_time; + // use micro clock to get a local time with sub seconds + // and adjust it to get a true utc time reading with sub seconds + utc_time = microsec_clock::local_time() - utc_offset; + return time_type(utc_time, tz_ptr); + } + + + private: + // we want this enum available for both platforms yet still private + enum TZ_FOR_CREATE { LOCAL, GMT }; + + public: + +#ifdef BOOST_HAS_GETTIMEOFDAY + //! Return the local time based on computer clock settings + static time_type local_time() { + return create_time(LOCAL); + } + + //! Get the current day in universal date as a ymd_type + static time_type universal_time() + { + return create_time(GMT); + } + + private: + static time_type create_time(TZ_FOR_CREATE tz) { + timeval tv; + gettimeofday(&tv, 0); //gettimeofday does not support TZ adjust on Linux. + std::time_t t = tv.tv_sec; + boost::uint32_t fs = tv.tv_usec; + std::tm curr, *curr_ptr = 0; + if (tz == LOCAL) { + curr_ptr = c_time::localtime(&t, &curr); + } else { + curr_ptr = c_time::gmtime(&t, &curr); + } + date_type d(curr_ptr->tm_year + 1900, + curr_ptr->tm_mon + 1, + curr_ptr->tm_mday); + //The following line will adjusts the fractional second tick in terms + //of the current time system. For example, if the time system + //doesn't support fractional seconds then res_adjust returns 0 + //and all the fractional seconds return 0. + int adjust = resolution_traits_type::res_adjust()/1000000; + + time_duration_type td(curr_ptr->tm_hour, + curr_ptr->tm_min, + curr_ptr->tm_sec, + fs*adjust); + return time_type(d,td); + + } +#endif // BOOST_HAS_GETTIMEOFDAY + +#ifdef BOOST_HAS_FTIME + //! Return the local time based on computer clock settings + static time_type local_time() { + FILETIME ft; + #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) + // Some runtime library implementations expect local times as the norm for ctime. + FILETIME ft_utc; + GetSystemTimeAsFileTime(&ft_utc); + FileTimeToLocalFileTime(&ft_utc,&ft); + #elif defined(BOOST_NO_GETSYSTEMTIMEASFILETIME) + SYSTEMTIME st; + GetSystemTime( &st ); + SystemTimeToFileTime( &st, &ft ); + #else + GetSystemTimeAsFileTime(&ft); + #endif + return create_time(ft, LOCAL); + } + + //! Return the UTC time based on computer settings + static time_type universal_time() { + FILETIME ft; + #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) + // Some runtime library implementations expect local times as the norm for ctime. + FILETIME ft_utc; + GetSystemTimeAsFileTime(&ft_utc); + FileTimeToLocalFileTime(&ft_utc,&ft); + #elif defined(BOOST_NO_GETSYSTEMTIMEASFILETIME) + SYSTEMTIME st; + GetSystemTime( &st ); + SystemTimeToFileTime( &st, &ft ); + #else + GetSystemTimeAsFileTime(&ft); + #endif + return create_time(ft, GMT); + } + + private: + static time_type create_time(FILETIME& ft, TZ_FOR_CREATE tz) { + // offset is difference (in 100-nanoseconds) from + // 1970-Jan-01 to 1601-Jan-01 + boost::uint64_t c1 = 27111902; + boost::uint64_t c2 = 3577643008UL; // 'UL' removes compiler warnings + const boost::uint64_t OFFSET = (c1 << 32) + c2; + + boost::uint64_t filetime = ft.dwHighDateTime; + filetime = filetime << 32; + filetime += ft.dwLowDateTime; + filetime -= OFFSET; + // filetime now holds 100-nanoseconds since 1970-Jan-01 + + // microseconds -- static casts supress warnings + boost::uint32_t sub_sec = static_cast((filetime % 10000000) / 10); + + std::time_t t = static_cast(filetime / 10000000); // seconds since epoch + + std::tm curr, *curr_ptr = 0; + if (tz == LOCAL) { + curr_ptr = c_time::localtime(&t, &curr); + } + else { + curr_ptr = c_time::gmtime(&t, &curr); + } + date_type d(curr_ptr->tm_year + 1900, + curr_ptr->tm_mon + 1, + curr_ptr->tm_mday); + + //The following line will adjusts the fractional second tick in terms + //of the current time system. For example, if the time system + //doesn't support fractional seconds then res_adjust returns 0 + //and all the fractional seconds return 0. + int adjust = static_cast(resolution_traits_type::res_adjust()/1000000); + + time_duration_type td(curr_ptr->tm_hour, + curr_ptr->tm_min, + curr_ptr->tm_sec, + sub_sec * adjust); + //st.wMilliseconds * adjust); + return time_type(d,td); + + } +#endif // BOOST_HAS_FTIME + }; + + +} } //namespace date_time + +#endif //BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK + + +#endif + diff --git a/win32/include/boost/date_time/parse_format_base.hpp b/win32/include/boost/date_time/parse_format_base.hpp new file mode 100755 index 000000000..317151a15 --- /dev/null +++ b/win32/include/boost/date_time/parse_format_base.hpp @@ -0,0 +1,29 @@ +#ifndef DATE_TIME_PARSE_FORMAT_BASE__ +#define DATE_TIME_PARSE_FORMAT_BASE__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +namespace boost { +namespace date_time { + + //! Enum for distinguishing parsing and formatting options + enum month_format_spec {month_as_integer, month_as_short_string, + month_as_long_string}; + + //! Enum for distinguishing the order of Month, Day, & Year. + /*! Enum for distinguishing the order in which Month, Day, & Year + * will appear in a date string */ + enum ymd_order_spec {ymd_order_iso, //order is year-month-day + ymd_order_dmy, //day-month-year + ymd_order_us}; //order is month-day-year + + +} }//namespace date_time + +#endif diff --git a/win32/include/boost/date_time/period.hpp b/win32/include/boost/date_time/period.hpp new file mode 100755 index 000000000..f54a963c1 --- /dev/null +++ b/win32/include/boost/date_time/period.hpp @@ -0,0 +1,377 @@ +#ifndef DATE_TIME_PERIOD_HPP___ +#define DATE_TIME_PERIOD_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! \file period.hpp + This file contain the implementation of the period abstraction. This is + basically the same idea as a range. Although this class is intended for + use in the time library, it is pretty close to general enough for other + numeric uses. + +*/ + +#include "boost/operators.hpp" + + +namespace boost { +namespace date_time { + //!Provides generalized period type useful in date-time systems + /*!This template uses a class to represent a time point within the period + and another class to represent a duration. As a result, this class is + not appropriate for use when the number and duration representation + are the same (eg: in the regular number domain). + + A period can be specified by providing either the begining point and + a duration or the begining point and the end point( end is NOT part + of the period but 1 unit past it. A period will be "invalid" if either + end_point <= begin_point or the given duration is <= 0. Any valid period + will return false for is_null(). + + Zero length periods are also considered invalid. Zero length periods are + periods where the begining and end points are the same, or, the given + duration is zero. For a zero length period, the last point will be one + unit less than the begining point. + + In the case that the begin and last are the same, the period has a + length of one unit. + + The best way to handle periods is usually to provide a begining point and + a duration. So, day1 + 7 days is a week period which includes all of the + first day and 6 more days (eg: Sun to Sat). + + */ + template + class period : private + boost::less_than_comparable + , boost::equality_comparable< period + > > + { + public: + typedef point_rep point_type; + typedef duration_rep duration_type; + + period(point_rep first_point, point_rep end_point); + period(point_rep first_point, duration_rep len); + point_rep begin() const; + point_rep end() const; + point_rep last() const; + duration_rep length() const; + bool is_null() const; + bool operator==(const period& rhs) const; + bool operator<(const period& rhs) const; + void shift(const duration_rep& d); + void expand(const duration_rep& d); + bool contains(const point_rep& point) const; + bool contains(const period& other) const; + bool intersects(const period& other) const; + bool is_adjacent(const period& other) const; + bool is_before(const point_rep& point) const; + bool is_after(const point_rep& point) const; + period intersection(const period& other) const; + period merge(const period& other) const; + period span(const period& other) const; + private: + point_rep begin_; + point_rep last_; + }; + + //! create a period from begin to last eg: [begin,end) + /*! If end <= begin then the period will be invalid + */ + template + inline + period::period(point_rep first_point, + point_rep end_point) : + begin_(first_point), + last_(end_point - duration_rep::unit()) + {} + + //! create a period as [begin, begin+len) + /*! If len is <= 0 then the period will be invalid + */ + template + inline + period::period(point_rep first_point, duration_rep len) : + begin_(first_point), + last_(first_point + len-duration_rep::unit()) + { } + + + //! Return the first element in the period + template + inline + point_rep period::begin() const + { + return begin_; + } + + //! Return one past the last element + template + inline + point_rep period::end() const + { + return last_ + duration_rep::unit(); + } + + //! Return the last item in the period + template + inline + point_rep period::last() const + { + return last_; + } + + //! True if period is ill formed (length is zero or less) + template + inline + bool period::is_null() const + { + return end() <= begin_; + } + + //! Return the length of the period + template + inline + duration_rep period::length() const + { + if(last_ < begin_){ // invalid period + return last_+duration_rep::unit() - begin_; + } + else{ + return end() - begin_; // normal case + } + } + + //! Equality operator + template + inline + bool period::operator==(const period& rhs) const + { + return ((begin_ == rhs.begin_) && + (last_ == rhs.last_)); + } + + //! Strict as defined by rhs.last <= lhs.last + template + inline + bool period::operator<(const period& rhs) const + { + return (last_ < rhs.begin_); + } + + + //! Shift the start and end by the specified amount + template + inline + void period::shift(const duration_rep& d) + { + begin_ = begin_ + d; + last_ = last_ + d; + } + + /** Expands the size of the period by the duration on both ends. + * + *So before expand + *@code + * + * [-------] + * ^ ^ ^ ^ ^ ^ ^ + * 1 2 3 4 5 6 7 + * + *@endcode + * After expand(2) + *@code + * + * [----------------------] + * ^ ^ ^ ^ ^ ^ ^ + * 1 2 3 4 5 6 7 + * + *@endcode + */ + template + inline + void period::expand(const duration_rep& d) + { + begin_ = begin_ - d; + last_ = last_ + d; + } + + //! True if the point is inside the period, zero length periods contain no points + template + inline + bool period::contains(const point_rep& point) const + { + return ((point >= begin_) && + (point <= last_)); + } + + + //! True if this period fully contains (or equals) the other period + template + inline + bool period::contains(const period& other) const + { + return ((begin_ <= other.begin_) && (last_ >= other.last_)); + } + + + //! True if periods are next to each other without a gap. + /* In the example below, p1 and p2 are adjacent, but p3 is not adjacent + * with either of p1 or p2. + *@code + * [-p1-) + * [-p2-) + * [-p3-) + *@endcode + */ + template + inline + bool + period::is_adjacent(const period& other) const + { + return (other.begin() == end() || + begin_ == other.end()); + } + + + //! True if all of the period is prior or t < start + /* In the example below only point 1 would evaluate to true. + *@code + * [---------]) + * ^ ^ ^ ^ ^ + * 1 2 3 4 5 + * + *@endcode + */ + template + inline + bool + period::is_after(const point_rep& t) const + { + if (is_null()) + { + return false; //null period isn't after + } + + return t < begin_; + } + + //! True if all of the period is prior to the passed point or end <= t + /* In the example below points 4 and 5 return true. + *@code + * [---------]) + * ^ ^ ^ ^ ^ + * 1 2 3 4 5 + * + *@endcode + */ + template + inline + bool + period::is_before(const point_rep& t) const + { + if (is_null()) + { + return false; //null period isn't before anything + } + + return last_ < t; + } + + + //! True if the periods overlap in any way + /* In the example below p1 intersects with p2, p4, and p6. + *@code + * [---p1---) + * [---p2---) + * [---p3---) + * [---p4---) + * [-p5-) + * [-p6-) + *@endcode + */ + template + inline + bool period::intersects(const period& other) const + { + return ( contains(other.begin_) || + other.contains(begin_) || + ((other.begin_ < begin_) && (other.last_ >= begin_))); + } + + //! Returns the period of intersection or invalid range no intersection + template + inline + period + period::intersection(const period& other) const + { + if (begin_ > other.begin_) { + if (last_ <= other.last_) { //case2 + return *this; + } + //case 1 + return period(begin_, other.end()); + } + else { + if (last_ <= other.last_) { //case3 + return period(other.begin_, this->end()); + } + //case4 + return other; + } + //unreachable + } + + //! Returns the union of intersecting periods -- or null period + /*! + */ + template + inline + period + period::merge(const period& other) const + { + if (this->intersects(other)) { + if (begin_ < other.begin_) { + return period(begin_, last_ > other.last_ ? this->end() : other.end()); + } + + return period(other.begin_, last_ > other.last_ ? this->end() : other.end()); + + } + return period(begin_,begin_); // no intersect return null + } + + //! Combine two periods with earliest start and latest end. + /*! Combines two periods and any gap between them such that + * start = min(p1.start, p2.start) + * end = max(p1.end , p2.end) + *@code + * [---p1---) + * [---p2---) + * result: + * [-----------p3----------) + *@endcode + */ + template + inline + period + period::span(const period& other) const + { + point_rep start((begin_ < other.begin_) ? begin() : other.begin()); + point_rep newend((last_ < other.last_) ? other.end() : this->end()); + return period(start, newend); + } + + +} } //namespace date_time + + + +#endif diff --git a/win32/include/boost/date_time/period_formatter.hpp b/win32/include/boost/date_time/period_formatter.hpp new file mode 100755 index 000000000..63d4bce53 --- /dev/null +++ b/win32/include/boost/date_time/period_formatter.hpp @@ -0,0 +1,196 @@ + +#ifndef DATETIME_PERIOD_FORMATTER_HPP___ +#define DATETIME_PERIOD_FORMATTER_HPP___ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + + +namespace boost { namespace date_time { + + + //! Not a facet, but a class used to specify and control period formats + /*! Provides settings for the following: + * - period_separator -- default '/' + * - period_open_start_delimeter -- default '[' + * - period_open_range_end_delimeter -- default ')' + * - period_closed_range_end_delimeter -- default ']' + * - display_as_open_range, display_as_closed_range -- default closed_range + * + * Thus the default formatting for a period is as follows: + *@code + * [period.start()/period.last()] + *@endcode + * So for a typical date_period this would be + *@code + * [2004-Jan-04/2004-Feb-01] + *@endcode + * where the date formatting is controlled by the date facet + */ + template > > + class period_formatter { + public: + typedef std::basic_string string_type; + typedef CharT char_type; + typedef typename std::basic_string::const_iterator const_itr_type; + typedef std::vector > collection_type; + + static const char_type default_period_separator[2]; + static const char_type default_period_start_delimeter[2]; + static const char_type default_period_open_range_end_delimeter[2]; + static const char_type default_period_closed_range_end_delimeter[2]; + + enum range_display_options { AS_OPEN_RANGE, AS_CLOSED_RANGE }; + + //! Constructor that sets up period formatter options -- default should suffice most cases. + period_formatter(range_display_options range_option_in = AS_CLOSED_RANGE, + const char_type* const period_separator = default_period_separator, + const char_type* const period_start_delimeter = default_period_start_delimeter, + const char_type* const period_open_range_end_delimeter = default_period_open_range_end_delimeter, + const char_type* const period_closed_range_end_delimeter = default_period_closed_range_end_delimeter) : + m_range_option(range_option_in), + m_period_separator(period_separator), + m_period_start_delimeter(period_start_delimeter), + m_open_range_end_delimeter(period_open_range_end_delimeter), + m_closed_range_end_delimeter(period_closed_range_end_delimeter) + {} + + //! Puts the characters between period elements into stream -- default is / + OutItrT put_period_separator(OutItrT& oitr) const + { + const_itr_type ci = m_period_separator.begin(); + while (ci != m_period_separator.end()) { + *oitr = *ci; + ci++; + } + return oitr; + } + + //! Puts the period start characters into stream -- default is [ + OutItrT put_period_start_delimeter(OutItrT& oitr) const + { + const_itr_type ci = m_period_start_delimeter.begin(); + while (ci != m_period_start_delimeter.end()) { + *oitr = *ci; + ci++; + } + return oitr; + } + + //! Puts the period end characters into stream as controled by open/closed range setting. + OutItrT put_period_end_delimeter(OutItrT& oitr) const + { + + const_itr_type ci, end; + if (m_range_option == AS_OPEN_RANGE) { + ci = m_open_range_end_delimeter.begin(); + end = m_open_range_end_delimeter.end(); + } + else { + ci = m_closed_range_end_delimeter.begin(); + end = m_closed_range_end_delimeter.end(); + } + while (ci != end) { + *oitr = *ci; + ci++; + } + return oitr; + } + + range_display_options range_option() const + { + return m_range_option; + } + + //! Reset the range_option control + void + range_option(range_display_options option) const + { + m_range_option = option; + } + void delimiter_strings(const string_type& separator, + const string_type& start_delim, + const string_type& open_end_delim, + const string_type& closed_end_delim) + { + m_period_separator; + m_period_start_delimeter; + m_open_range_end_delimeter; + m_closed_range_end_delimeter; + } + + + //! Generic code to output a period -- no matter the period type. + /*! This generic code will output any period using a facet to + * to output the 'elements'. For example, in the case of a date_period + * the elements will be instances of a date which will be formatted + * according the to setup in the passed facet parameter. + * + * The steps for formatting a period are always the same: + * - put the start delimiter + * - put start element + * - put the separator + * - put either last or end element depending on range settings + * - put end delimeter depending on range settings + * + * Thus for a typical date period the result might look like this: + *@code + * + * [March 01, 2004/June 07, 2004] <-- closed range + * [March 01, 2004/June 08, 2004) <-- open range + * + *@endcode + */ + template + OutItrT put_period(OutItrT next, + std::ios_base& a_ios, + char_type a_fill, + const period_type& p, + const facet_type& facet) const { + put_period_start_delimeter(next); + next = facet.put(next, a_ios, a_fill, p.begin()); + put_period_separator(next); + if (m_range_option == AS_CLOSED_RANGE) { + facet.put(next, a_ios, a_fill, p.last()); + } + else { + facet.put(next, a_ios, a_fill, p.end()); + } + put_period_end_delimeter(next); + return next; + } + + + private: + range_display_options m_range_option; + string_type m_period_separator; + string_type m_period_start_delimeter; + string_type m_open_range_end_delimeter; + string_type m_closed_range_end_delimeter; + }; + + template + const typename period_formatter::char_type + period_formatter::default_period_separator[2] = {'/'}; + + template + const typename period_formatter::char_type + period_formatter::default_period_start_delimeter[2] = {'['}; + + template + const typename period_formatter::char_type + period_formatter::default_period_open_range_end_delimeter[2] = {')'}; + + template + const typename period_formatter::char_type + period_formatter::default_period_closed_range_end_delimeter[2] = {']'}; + + } } //namespace boost::date_time + +#endif diff --git a/win32/include/boost/date_time/period_parser.hpp b/win32/include/boost/date_time/period_parser.hpp new file mode 100755 index 000000000..57623e109 --- /dev/null +++ b/win32/include/boost/date_time/period_parser.hpp @@ -0,0 +1,196 @@ + +#ifndef DATETIME_PERIOD_PARSER_HPP___ +#define DATETIME_PERIOD_PARSER_HPP___ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/string_parse_tree.hpp" +#include "boost/date_time/string_convert.hpp" + + +namespace boost { namespace date_time { + + + //! Not a facet, but a class used to specify and control period parsing + /*! Provides settings for the following: + * - period_separator -- default '/' + * - period_open_start_delimeter -- default '[' + * - period_open_range_end_delimeter -- default ')' + * - period_closed_range_end_delimeter -- default ']' + * - display_as_open_range, display_as_closed_range -- default closed_range + * + * For a typical date_period, the contents of the input stream would be + *@code + * [2004-Jan-04/2004-Feb-01] + *@endcode + * where the date format is controlled by the date facet + */ + template + class period_parser { + public: + typedef std::basic_string string_type; + typedef CharT char_type; + //typedef typename std::basic_string::const_iterator const_itr_type; + typedef std::istreambuf_iterator stream_itr_type; + typedef string_parse_tree parse_tree_type; + typedef typename parse_tree_type::parse_match_result_type match_results; + typedef std::vector > collection_type; + + static const char_type default_period_separator[2]; + static const char_type default_period_start_delimeter[2]; + static const char_type default_period_open_range_end_delimeter[2]; + static const char_type default_period_closed_range_end_delimeter[2]; + + enum period_range_option { AS_OPEN_RANGE, AS_CLOSED_RANGE }; + + //! Constructor that sets up period parser options + period_parser(period_range_option range_option = AS_CLOSED_RANGE, + const char_type* const period_separator = default_period_separator, + const char_type* const period_start_delimeter = default_period_start_delimeter, + const char_type* const period_open_range_end_delimeter = default_period_open_range_end_delimeter, + const char_type* const period_closed_range_end_delimeter = default_period_closed_range_end_delimeter) + : m_range_option(range_option) + { + delimiters.push_back(string_type(period_separator)); + delimiters.push_back(string_type(period_start_delimeter)); + delimiters.push_back(string_type(period_open_range_end_delimeter)); + delimiters.push_back(string_type(period_closed_range_end_delimeter)); + } + + period_parser(const period_parser& p_parser) + { + this->delimiters = p_parser.delimiters; + this->m_range_option = p_parser.m_range_option; + } + + period_range_option range_option() const + { + return m_range_option; + } + void range_option(period_range_option option) + { + m_range_option = option; + } + collection_type delimiter_strings() const + { + return delimiters; + } + void delimiter_strings(const string_type& separator, + const string_type& start_delim, + const string_type& open_end_delim, + const string_type& closed_end_delim) + { + delimiters.clear(); + delimiters.push_back(separator); + delimiters.push_back(start_delim); + delimiters.push_back(open_end_delim); + delimiters.push_back(closed_end_delim); + } + + //! Generic code to parse a period -- no matter the period type. + /*! This generic code will parse any period using a facet to + * to get the 'elements'. For example, in the case of a date_period + * the elements will be instances of a date which will be parsed + * according the to setup in the passed facet parameter. + * + * The steps for parsing a period are always the same: + * - consume the start delimiter + * - get start element + * - consume the separator + * - get either last or end element depending on range settings + * - consume the end delimeter depending on range settings + * + * Thus for a typical date period the contents of the input stream + * might look like this: + *@code + * + * [March 01, 2004/June 07, 2004] <-- closed range + * [March 01, 2004/June 08, 2004) <-- open range + * + *@endcode + */ + template + period_type get_period(stream_itr_type& sitr, + stream_itr_type& stream_end, + std::ios_base& a_ios, + const period_type& p, + const duration_type& dur_unit, + const facet_type& facet) const + { + // skip leading whitespace + while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } + + typedef typename period_type::point_type point_type; + point_type p1(not_a_date_time), p2(not_a_date_time); + + + consume_delim(sitr, stream_end, delimiters[START]); // start delim + facet.get(sitr, stream_end, a_ios, p1); // first point + consume_delim(sitr, stream_end, delimiters[SEPARATOR]); // separator + facet.get(sitr, stream_end, a_ios, p2); // second point + + // period construction parameters are always open range [begin, end) + if (m_range_option == AS_CLOSED_RANGE) { + consume_delim(sitr, stream_end, delimiters[CLOSED_END]);// end delim + // add 1 duration unit to p2 to make range open + p2 += dur_unit; + } + else { + consume_delim(sitr, stream_end, delimiters[OPEN_END]); // end delim + } + + return period_type(p1, p2); + } + + private: + collection_type delimiters; + period_range_option m_range_option; + + enum delim_ids { SEPARATOR, START, OPEN_END, CLOSED_END }; + + //! throws ios_base::failure if delimiter and parsed data do not match + void consume_delim(stream_itr_type& sitr, + stream_itr_type& stream_end, + const string_type& delim) const + { + /* string_parse_tree will not parse a string of punctuation characters + * without knowing exactly how many characters to process + * Ex [2000. Will not parse out the '[' string without knowing + * to process only one character. By using length of the delimiter + * string we can safely iterate past it. */ + string_type s; + for(unsigned int i = 0; i < delim.length() && sitr != stream_end; ++i) { + s += *sitr; + ++sitr; + } + if(s != delim) { + throw std::ios_base::failure("Parse failed. Expected '" + convert_string_type(delim) + "' but found '" + convert_string_type(s) + "'"); + } + } + }; + + template + const typename period_parser::char_type + period_parser::default_period_separator[2] = {'/'}; + + template + const typename period_parser::char_type + period_parser::default_period_start_delimeter[2] = {'['}; + + template + const typename period_parser::char_type + period_parser::default_period_open_range_end_delimeter[2] = {')'}; + + template + const typename period_parser::char_type + period_parser::default_period_closed_range_end_delimeter[2] = {']'}; + + } } //namespace boost::date_time + +#endif // DATETIME_PERIOD_PARSER_HPP___ diff --git a/win32/include/boost/date_time/posix_time/conversion.hpp b/win32/include/boost/date_time/posix_time/conversion.hpp new file mode 100755 index 000000000..78c329977 --- /dev/null +++ b/win32/include/boost/date_time/posix_time/conversion.hpp @@ -0,0 +1,93 @@ +#ifndef POSIX_TIME_CONVERSION_HPP___ +#define POSIX_TIME_CONVERSION_HPP___ + +/* Copyright (c) 2002-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/posix_time/ptime.hpp" +#include "boost/date_time/posix_time/posix_time_duration.hpp" +#include "boost/date_time/filetime_functions.hpp" +#include "boost/date_time/c_time.hpp" +#include "boost/date_time/gregorian/conversion.hpp" + +namespace boost { + +namespace posix_time { + + + //! Function that converts a time_t into a ptime. + inline + ptime from_time_t(std::time_t t) + { + ptime start(gregorian::date(1970,1,1)); + return start + seconds(static_cast(t)); + } + + //! Convert a time to a tm structure truncating any fractional seconds + inline + std::tm to_tm(const boost::posix_time::ptime& t) { + std::tm timetm = boost::gregorian::to_tm(t.date()); + boost::posix_time::time_duration td = t.time_of_day(); + timetm.tm_hour = td.hours(); + timetm.tm_min = td.minutes(); + timetm.tm_sec = td.seconds(); + timetm.tm_isdst = -1; // -1 used when dst info is unknown + return timetm; + } + //! Convert a time_duration to a tm structure truncating any fractional seconds and zeroing fields for date components + inline + std::tm to_tm(const boost::posix_time::time_duration& td) { + std::tm timetm; + timetm.tm_year = 0; + timetm.tm_mon = 0; + timetm.tm_mday = 0; + timetm.tm_wday = 0; + timetm.tm_yday = 0; + + timetm.tm_hour = date_time::absolute_value(td.hours()); + timetm.tm_min = date_time::absolute_value(td.minutes()); + timetm.tm_sec = date_time::absolute_value(td.seconds()); + timetm.tm_isdst = -1; // -1 used when dst info is unknown + return timetm; + } + + //! Convert a tm struct to a ptime ignoring is_dst flag + inline + ptime ptime_from_tm(const std::tm& timetm) { + boost::gregorian::date d = boost::gregorian::date_from_tm(timetm); + return ptime(d, time_duration(timetm.tm_hour, timetm.tm_min, timetm.tm_sec)); + } + + +#if defined(BOOST_HAS_FTIME) + + //! Function to create a time object from an initialized FILETIME struct. + /*! Function to create a time object from an initialized FILETIME struct. + * A FILETIME struct holds 100-nanosecond units (0.0000001). When + * built with microsecond resolution the FILETIME's sub second value + * will be truncated. Nanosecond resolution has no truncation. + * + * Note ftime is part of the Win32 API, so it is not portable to non-windows + * platforms. + */ + template + inline + time_type from_ftime(const FILETIME& ft) + { + return boost::date_time::time_from_ftime(ft); + } + +#endif // BOOST_HAS_FTIME + +} } //namespace boost::posix_time + + + + +#endif + diff --git a/win32/include/boost/date_time/posix_time/date_duration_operators.hpp b/win32/include/boost/date_time/posix_time/date_duration_operators.hpp new file mode 100755 index 000000000..24f80cf39 --- /dev/null +++ b/win32/include/boost/date_time/posix_time/date_duration_operators.hpp @@ -0,0 +1,114 @@ +#ifndef DATE_DURATION_OPERATORS_HPP___ +#define DATE_DURATION_OPERATORS_HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or + * http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/greg_duration_types.hpp" +#include "boost/date_time/posix_time/ptime.hpp" + +namespace boost { +namespace posix_time { + + /*!@file date_duration_operators.hpp Operators for ptime and + * optional gregorian types. Operators use snap-to-end-of-month behavior. + * Further details on this behavior can be found in reference for + * date_time/date_duration_types.hpp and documentation for + * month and year iterators. + */ + + + /*! Adds a months object and a ptime. Result will be same + * day-of-month as ptime unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + ptime + operator+(const ptime& t, const boost::gregorian::months& m) + { + return t + m.get_offset(t.date()); + } + + /*! Adds a months object to a ptime. Result will be same + * day-of-month as ptime unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + ptime + operator+=(ptime& t, const boost::gregorian::months& m) + { + // get_neg_offset returns a negative duration, so we add + return t += m.get_offset(t.date()); + } + + /*! Subtracts a months object and a ptime. Result will be same + * day-of-month as ptime unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + ptime + operator-(const ptime& t, const boost::gregorian::months& m) + { + // get_neg_offset returns a negative duration, so we add + return t + m.get_neg_offset(t.date()); + } + + /*! Subtracts a months object from a ptime. Result will be same + * day-of-month as ptime unless original day was the last day of month. + * see date_time::months_duration for more details */ + inline + ptime + operator-=(ptime& t, const boost::gregorian::months& m) + { + return t += m.get_neg_offset(t.date()); + } + + // ptime & years + + /*! Adds a years object and a ptime. Result will be same + * month and day-of-month as ptime unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + ptime + operator+(const ptime& t, const boost::gregorian::years& y) + { + return t + y.get_offset(t.date()); + } + + /*! Adds a years object to a ptime. Result will be same + * month and day-of-month as ptime unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + ptime + operator+=(ptime& t, const boost::gregorian::years& y) + { + return t += y.get_offset(t.date()); + } + + /*! Subtracts a years object and a ptime. Result will be same + * month and day-of-month as ptime unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + ptime + operator-(const ptime& t, const boost::gregorian::years& y) + { + // get_neg_offset returns a negative duration, so we add + return t + y.get_neg_offset(t.date()); + } + + /*! Subtracts a years object from a ptime. Result will be same + * month and day-of-month as ptime unless original day was the + * last day of month. see date_time::years_duration for more details */ + inline + ptime + operator-=(ptime& t, const boost::gregorian::years& y) + { + // get_neg_offset returns a negative duration, so we add + return t += y.get_neg_offset(t.date()); + } + +}} // namespaces + +#endif // DATE_DURATION_OPERATORS_HPP___ diff --git a/win32/include/boost/date_time/posix_time/posix_time.hpp b/win32/include/boost/date_time/posix_time/posix_time.hpp new file mode 100755 index 000000000..8e6195309 --- /dev/null +++ b/win32/include/boost/date_time/posix_time/posix_time.hpp @@ -0,0 +1,39 @@ +#ifndef POSIX_TIME_HPP___ +#define POSIX_TIME_HPP___ + +/* Copyright (c) 2002-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ +/*!@file posix_time.hpp Global header file to get all of posix time types + */ + +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/posix_time/ptime.hpp" +#if defined(BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES) +#include "boost/date_time/posix_time/date_duration_operators.hpp" +#endif + +// output functions +#if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) +#include "boost/date_time/posix_time/time_formatters_limited.hpp" +#else +#include "boost/date_time/posix_time/time_formatters.hpp" +#endif // BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS + +// streaming operators +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) +#include "boost/date_time/posix_time/posix_time_legacy_io.hpp" +#else +#include "boost/date_time/posix_time/posix_time_io.hpp" +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO + +#include "boost/date_time/posix_time/time_parsers.hpp" +#include "boost/date_time/posix_time/conversion.hpp" + + +#endif + diff --git a/win32/include/boost/date_time/posix_time/posix_time_config.hpp b/win32/include/boost/date_time/posix_time/posix_time_config.hpp new file mode 100755 index 000000000..0441ae1e6 --- /dev/null +++ b/win32/include/boost/date_time/posix_time/posix_time_config.hpp @@ -0,0 +1,178 @@ +#ifndef POSIX_TIME_CONFIG_HPP___ +#define POSIX_TIME_CONFIG_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/time_duration.hpp" +#include "boost/date_time/time_resolution_traits.hpp" +#include "boost/date_time/gregorian/gregorian_types.hpp" +#include "boost/date_time/wrapping_int.hpp" +#include "boost/limits.hpp" +#include "boost/date_time/compiler_config.hpp" +#include "boost/cstdint.hpp" +#include +#include //for MCW 7.2 std::abs(long long) + +namespace boost { +namespace posix_time { + +//Remove the following line if you want 64 bit millisecond resolution time +//#define BOOST_GDTL_POSIX_TIME_STD_CONFIG + +#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + // set up conditional test compilations +#define BOOST_DATE_TIME_HAS_MILLISECONDS +#define BOOST_DATE_TIME_HAS_MICROSECONDS +#define BOOST_DATE_TIME_HAS_NANOSECONDS + typedef date_time::time_resolution_traits time_res_traits; +#else + // set up conditional test compilations +#define BOOST_DATE_TIME_HAS_MILLISECONDS +#define BOOST_DATE_TIME_HAS_MICROSECONDS +#undef BOOST_DATE_TIME_HAS_NANOSECONDS + typedef date_time::time_resolution_traits< + boost::date_time::time_resolution_traits_adapted64_impl, boost::date_time::micro, + 1000000, 6 > time_res_traits; + + +// #undef BOOST_DATE_TIME_HAS_MILLISECONDS +// #undef BOOST_DATE_TIME_HAS_MICROSECONDS +// #undef BOOST_DATE_TIME_HAS_NANOSECONDS +// typedef date_time::time_resolution_traits time_res_traits; + +#endif + + + //! Base time duration type + /*! \ingroup time_basics + */ + class time_duration : + public date_time::time_duration + { + public: + typedef time_res_traits rep_type; + typedef time_res_traits::day_type day_type; + typedef time_res_traits::hour_type hour_type; + typedef time_res_traits::min_type min_type; + typedef time_res_traits::sec_type sec_type; + typedef time_res_traits::fractional_seconds_type fractional_seconds_type; + typedef time_res_traits::tick_type tick_type; + typedef time_res_traits::impl_type impl_type; + time_duration(hour_type hour, + min_type min, + sec_type sec, + fractional_seconds_type fs=0) : + date_time::time_duration(hour,min,sec,fs) + {} + time_duration() : + date_time::time_duration(0,0,0) + {} + //! Construct from special_values + time_duration(boost::date_time::special_values sv) : + date_time::time_duration(sv) + {} + //Give duration access to ticks constructor -- hide from users + friend class date_time::time_duration; + private: + explicit time_duration(impl_type ticks) : + date_time::time_duration(ticks) + {} + }; + +#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + + //! Simple implementation for the time rep + struct simple_time_rep + { + typedef gregorian::date date_type; + typedef time_duration time_duration_type; + simple_time_rep(date_type d, time_duration_type tod) : + day(d), + time_of_day(tod) + { + // make sure we have sane values for date & time + if(!day.is_special() && !time_of_day.is_special()){ + if(time_of_day >= time_duration_type(24,0,0)) { + while(time_of_day >= time_duration_type(24,0,0)) { + day += date_type::duration_type(1); + time_of_day -= time_duration_type(24,0,0); + } + } + else if(time_of_day.is_negative()) { + while(time_of_day.is_negative()) { + day -= date_type::duration_type(1); + time_of_day += time_duration_type(24,0,0); + } + } + } + } + date_type day; + time_duration_type time_of_day; + bool is_special()const + { + return(is_pos_infinity() || is_neg_infinity() || is_not_a_date_time()); + } + bool is_pos_infinity()const + { + return(day.is_pos_infinity() || time_of_day.is_pos_infinity()); + } + bool is_neg_infinity()const + { + return(day.is_neg_infinity() || time_of_day.is_neg_infinity()); + } + bool is_not_a_date_time()const + { + return(day.is_not_a_date() || time_of_day.is_not_a_date_time()); + } + }; + + class posix_time_system_config + { + public: + typedef simple_time_rep time_rep_type; + typedef gregorian::date date_type; + typedef gregorian::date_duration date_duration_type; + typedef time_duration time_duration_type; + typedef time_res_traits::tick_type int_type; + typedef time_res_traits resolution_traits; +#if (defined(BOOST_DATE_TIME_NO_MEMBER_INIT)) //help bad compilers +#else + BOOST_STATIC_CONSTANT(boost::int64_t, tick_per_second = 1000000000); +#endif + }; + +#else + + class millisec_posix_time_system_config + { + public: + typedef boost::int64_t time_rep_type; + //typedef time_res_traits::tick_type time_rep_type; + typedef gregorian::date date_type; + typedef gregorian::date_duration date_duration_type; + typedef time_duration time_duration_type; + typedef time_res_traits::tick_type int_type; + typedef time_res_traits::impl_type impl_type; + typedef time_res_traits resolution_traits; +#if (defined(BOOST_DATE_TIME_NO_MEMBER_INIT)) //help bad compilers +#else + BOOST_STATIC_CONSTANT(boost::int64_t, tick_per_second = 1000000); +#endif + }; + +#endif + +} }//namespace posix_time + + +#endif + + diff --git a/win32/include/boost/date_time/posix_time/posix_time_duration.hpp b/win32/include/boost/date_time/posix_time/posix_time_duration.hpp new file mode 100755 index 000000000..0ec460046 --- /dev/null +++ b/win32/include/boost/date_time/posix_time/posix_time_duration.hpp @@ -0,0 +1,82 @@ +#ifndef POSIX_TIME_DURATION_HPP___ +#define POSIX_TIME_DURATION_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/posix_time/posix_time_config.hpp" + +namespace boost { +namespace posix_time { + + //! Allows expression of durations as an hour count + /*! \ingroup time_basics + */ + class hours : public time_duration + { + public: + explicit hours(long h) : + time_duration(h,0,0) + {} + }; + + //! Allows expression of durations as a minute count + /*! \ingroup time_basics + */ + class minutes : public time_duration + { + public: + explicit minutes(long m) : + time_duration(0,m,0) + {} + }; + + //! Allows expression of durations as a seconds count + /*! \ingroup time_basics + */ + class seconds : public time_duration + { + public: + explicit seconds(long s) : + time_duration(0,0,s) + {} + }; + + + //! Allows expression of durations as milli seconds + /*! \ingroup time_basics + */ + typedef date_time::subsecond_duration millisec; + typedef date_time::subsecond_duration milliseconds; + + //! Allows expression of durations as micro seconds + /*! \ingroup time_basics + */ + typedef date_time::subsecond_duration microsec; + typedef date_time::subsecond_duration microseconds; + + //This is probably not needed anymore... +#if defined(BOOST_DATE_TIME_HAS_NANOSECONDS) + + //! Allows expression of durations as nano seconds + /*! \ingroup time_basics + */ + typedef date_time::subsecond_duration nanosec; + typedef date_time::subsecond_duration nanoseconds; + + +#endif + + + + +} }//namespace posix_time + + +#endif + diff --git a/win32/include/boost/date_time/posix_time/posix_time_io.hpp b/win32/include/boost/date_time/posix_time/posix_time_io.hpp new file mode 100755 index 000000000..5946e9e60 --- /dev/null +++ b/win32/include/boost/date_time/posix_time/posix_time_io.hpp @@ -0,0 +1,246 @@ +#ifndef DATE_TIME_POSIX_TIME_IO_HPP__ +#define DATE_TIME_POSIX_TIME_IO_HPP__ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/time_facet.hpp" +#include "boost/date_time/period_formatter.hpp" +#include "boost/date_time/posix_time/time_period.hpp" +#include "boost/date_time/posix_time/posix_time_duration.hpp" +//#include "boost/date_time/gregorian/gregorian_io.hpp" +#include "boost/io/ios_state.hpp" +#include +#include + +namespace boost { +namespace posix_time { + + + //! wptime_facet is depricated and will be phased out. use wtime_facet instead + //typedef boost::date_time::time_facet wptime_facet; + //! ptime_facet is depricated and will be phased out. use time_facet instead + //typedef boost::date_time::time_facet ptime_facet; + + //! wptime_input_facet is depricated and will be phased out. use wtime_input_facet instead + //typedef boost::date_time::time_input_facet wptime_input_facet; + //! ptime_input_facet is depricated and will be phased out. use time_input_facet instead + //typedef boost::date_time::time_input_facet ptime_input_facet; + + typedef boost::date_time::time_facet wtime_facet; + typedef boost::date_time::time_facet time_facet; + + typedef boost::date_time::time_input_facet wtime_input_facet; + typedef boost::date_time::time_input_facet time_input_facet; + + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, + const ptime& p) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::time_facet custom_ptime_facet; + typedef std::time_put std_ptime_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(oitr, os, os.fill(), p); + else { + //instantiate a custom facet for dealing with times since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every time period + //if the locale did not already exist. Of course this will be overridden + //if the user imbues as some later point. + std::ostreambuf_iterator oitr(os); + custom_ptime_facet* f = new custom_ptime_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), p); + } + return os; + } + + //! input operator for ptime + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, ptime& pt) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::time_input_facet time_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, pt); + } + else { + time_input_facet* f = new time_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, pt); + } + } + catch(...) { + // mask tells us what exceptions are turned on + std::ios_base::iostate exception_mask = is.exceptions(); + // if the user wants exceptions on failbit, we'll rethrow our + // date_time exception & set the failbit + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} // ignore this one + throw; // rethrow original exception + } + else { + // if the user want's to fail quietly, we simply set the failbit + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, + const boost::posix_time::time_period& p) { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::time_facet custom_ptime_facet; + typedef std::time_put std_time_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) { + std::use_facet(os.getloc()).put(oitr, os, os.fill(), p); + } + else { + //instantiate a custom facet for dealing with periods since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every time period + //if the local did not already exist. Of course this will be overridden + //if the user imbues as some later point. + std::ostreambuf_iterator oitr(os); + custom_ptime_facet* f = new custom_ptime_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), p); + } + return os; + } + + //! input operator for time_period + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, time_period& tp) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::time_input_facet time_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, tp); + } + else { + time_input_facet* f = new time_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, tp); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + + + //! ostream operator for posix_time::time_duration + // todo fix to use facet -- place holder for now... + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const time_duration& td) + { + boost::io::ios_flags_saver iflags(os); + typedef boost::date_time::time_facet custom_ptime_facet; + typedef std::time_put std_ptime_facet; + std::ostreambuf_iterator oitr(os); + if (std::has_facet(os.getloc())) + std::use_facet(os.getloc()).put(oitr, os, os.fill(), td); + else { + //instantiate a custom facet for dealing with times since the user + //has not put one in the stream so far. This is for efficiency + //since we would always need to reconstruct for every time period + //if the locale did not already exist. Of course this will be overridden + //if the user imbues as some later point. + std::ostreambuf_iterator oitr(os); + custom_ptime_facet* f = new custom_ptime_facet(); + std::locale l = std::locale(os.getloc(), f); + os.imbue(l); + f->put(oitr, os, os.fill(), td); + } + return os; + } + + //! input operator for time_duration + template + inline + std::basic_istream& + operator>>(std::basic_istream& is, time_duration& td) + { + boost::io::ios_flags_saver iflags(is); + typename std::basic_istream::sentry strm_sentry(is, false); + if (strm_sentry) { + try { + typedef typename date_time::time_input_facet time_input_facet; + + std::istreambuf_iterator sit(is), str_end; + if(std::has_facet(is.getloc())) { + std::use_facet(is.getloc()).get(sit, str_end, is, td); + } + else { + time_input_facet* f = new time_input_facet(); + std::locale l = std::locale(is.getloc(), f); + is.imbue(l); + f->get(sit, str_end, is, td); + } + } + catch(...) { + std::ios_base::iostate exception_mask = is.exceptions(); + if(std::ios_base::failbit & exception_mask) { + try { is.setstate(std::ios_base::failbit); } + catch(std::ios_base::failure&) {} + throw; // rethrow original exception + } + else { + is.setstate(std::ios_base::failbit); + } + + } + } + return is; + } + +} } // namespaces +#endif // DATE_TIME_POSIX_TIME_IO_HPP__ diff --git a/win32/include/boost/date_time/posix_time/posix_time_legacy_io.hpp b/win32/include/boost/date_time/posix_time/posix_time_legacy_io.hpp new file mode 100755 index 000000000..ef7187506 --- /dev/null +++ b/win32/include/boost/date_time/posix_time/posix_time_legacy_io.hpp @@ -0,0 +1,153 @@ +#ifndef POSIX_TIME_PRE133_OPERATORS_HPP___ +#define POSIX_TIME_PRE133_OPERATORS_HPP___ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! @file posix_time_pre133_operators.hpp + * These input and output operators are for use with the + * pre 1.33 version of the date_time libraries io facet code. + * The operators used in version 1.33 and later can be found + * in posix_time_io.hpp */ + +#include +#include +#include +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/gregorian/gregorian.hpp" +#include "boost/date_time/posix_time/posix_time_duration.hpp" +#include "boost/date_time/posix_time/ptime.hpp" +#include "boost/date_time/posix_time/time_period.hpp" +#include "boost/date_time/time_parsing.hpp" + +namespace boost { +namespace posix_time { + + +//The following code is removed for configurations with poor std::locale support (eg: MSVC6, gcc 2.9x) +#ifndef BOOST_DATE_TIME_NO_LOCALE +#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) + //! ostream operator for posix_time::time_duration + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const time_duration& td) + { + typedef boost::date_time::ostream_time_duration_formatter duration_formatter; + duration_formatter::duration_put(td, os); + return os; + } + + //! ostream operator for posix_time::ptime + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const ptime& t) + { + typedef boost::date_time::ostream_time_formatter time_formatter; + time_formatter::time_put(t, os); + return os; + } + + //! ostream operator for posix_time::time_period + template + inline + std::basic_ostream& + operator<<(std::basic_ostream& os, const time_period& tp) + { + typedef boost::date_time::ostream_time_period_formatter period_formatter; + period_formatter::period_put(tp, os); + return os; + } +#endif // USE_DATE_TIME_PRE_1_33_FACET_IO +/******** input streaming ********/ + template + inline + std::basic_istream& operator>>(std::basic_istream& is, time_duration& td) + { + // need to create a std::string and parse it + std::basic_string inp_s; + std::stringstream out_ss; + is >> inp_s; + typename std::basic_string::iterator b = inp_s.begin(); + // need to use both iterators because there is no requirement + // for the data held by a std::basic_string<> be terminated with + // any marker (such as '\0'). + typename std::basic_string::iterator e = inp_s.end(); + while(b != e){ + out_ss << out_ss.narrow(*b, 0); + ++b; + } + + td = date_time::parse_delimited_time_duration(out_ss.str()); + return is; + } + + template + inline + std::basic_istream& operator>>(std::basic_istream& is, ptime& pt) + { + gregorian::date d(not_a_date_time); + time_duration td(0,0,0); + is >> d >> td; + pt = ptime(d, td); + + return is; + } + + /** operator>> for time_period. time_period must be in + * "[date time_duration/date time_duration]" format. */ + template + inline + std::basic_istream& operator>>(std::basic_istream& is, time_period& tp) + { + gregorian::date d(not_a_date_time); + time_duration td(0,0,0); + ptime beg(d, td); + ptime end(beg); + std::basic_string s; + // get first date string and remove leading '[' + is >> s; + { + std::basic_stringstream ss; + ss << s.substr(s.find('[')+1); + ss >> d; + } + // get first time_duration & second date string, remove the '/' + // and split into 2 strings + is >> s; + { + std::basic_stringstream ss; + ss << s.substr(0, s.find('/')); + ss >> td; + } + beg = ptime(d, td); + { + std::basic_stringstream ss; + ss << s.substr(s.find('/')+1); + ss >> d; + } + // get last time_duration and remove the trailing ']' + is >> s; + { + std::basic_stringstream ss; + ss << s.substr(0, s.find(']')); + ss >> td; + } + end = ptime(d, td); + + tp = time_period(beg,end); + return is; + } + + +#endif //BOOST_DATE_TIME_NO_LOCALE + +} } // namespaces + +#endif // POSIX_TIME_PRE133_OPERATORS_HPP___ diff --git a/win32/include/boost/date_time/posix_time/posix_time_system.hpp b/win32/include/boost/date_time/posix_time/posix_time_system.hpp new file mode 100755 index 000000000..e0cf1e991 --- /dev/null +++ b/win32/include/boost/date_time/posix_time/posix_time_system.hpp @@ -0,0 +1,68 @@ +#ifndef POSIX_TIME_SYSTEM_HPP___ +#define POSIX_TIME_SYSTEM_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/posix_time/posix_time_config.hpp" +#include "boost/date_time/time_system_split.hpp" +#include "boost/date_time/time_system_counted.hpp" +#include "boost/date_time/compiler_config.hpp" + + +namespace boost { +namespace posix_time { + +#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG + +#if (defined(BOOST_DATE_TIME_NO_MEMBER_INIT)) //help bad compilers + typedef date_time::split_timedate_system posix_time_system; +#else + typedef date_time::split_timedate_system posix_time_system; +#endif + +#else + + typedef date_time::counted_time_rep int64_time_rep; + typedef date_time::counted_time_system posix_time_system; + +#endif + +} }//namespace posix_time + + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/win32/include/boost/date_time/posix_time/posix_time_types.hpp b/win32/include/boost/date_time/posix_time/posix_time_types.hpp new file mode 100755 index 000000000..ec1ad2eb3 --- /dev/null +++ b/win32/include/boost/date_time/posix_time/posix_time_types.hpp @@ -0,0 +1,55 @@ +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + */ +#ifndef POSIX_TIME_TYPES_HPP___ +#define POSIX_TIME_TYPES_HPP___ + +#include "boost/date_time/time_clock.hpp" +#include "boost/date_time/microsec_time_clock.hpp" +#include "boost/date_time/posix_time/ptime.hpp" +#if defined(BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES) +#include "boost/date_time/posix_time/date_duration_operators.hpp" +#endif +#include "boost/date_time/posix_time/posix_time_duration.hpp" +#include "boost/date_time/posix_time/posix_time_system.hpp" +#include "boost/date_time/posix_time/time_period.hpp" +#include "boost/date_time/time_iterator.hpp" +#include "boost/date_time/dst_rules.hpp" + +namespace boost { + +//!Defines a non-adjusted time system with nano-second resolution and stable calculation properties +namespace posix_time { + + //! Iterator over a defined time duration + /*! \ingroup time_basics + */ + typedef date_time::time_itr time_iterator; + //! A time clock that has a resolution of one second + /*! \ingroup time_basics + */ + typedef date_time::second_clock second_clock; + +#ifdef BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK + //! A time clock that has a resolution of one microsecond + /*! \ingroup time_basics + */ + typedef date_time::microsec_clock microsec_clock; +#endif + + //! Define a dst null dst rule for the posix_time system + typedef date_time::null_dst_rules no_dst; + //! Define US dst rule calculator for the posix_time system + typedef date_time::us_dst_rules us_dst; + + +} } //namespace posix_time + + + + +#endif + diff --git a/win32/include/boost/date_time/posix_time/ptime.hpp b/win32/include/boost/date_time/posix_time/ptime.hpp new file mode 100755 index 000000000..48132c99b --- /dev/null +++ b/win32/include/boost/date_time/posix_time/ptime.hpp @@ -0,0 +1,65 @@ +#ifndef POSIX_PTIME_HPP___ +#define POSIX_PTIME_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/posix_time/posix_time_system.hpp" +#include "boost/date_time/time.hpp" + +namespace boost { + +namespace posix_time { + + //bring special enum values into the namespace + using date_time::special_values; + using date_time::not_special; + using date_time::neg_infin; + using date_time::pos_infin; + using date_time::not_a_date_time; + using date_time::max_date_time; + using date_time::min_date_time; + + //! Time type with no timezone or other adjustments + /*! \ingroup time_basics + */ + class ptime : public date_time::base_time + { + public: + typedef posix_time_system time_system_type; + typedef time_system_type::time_rep_type time_rep_type; + typedef time_system_type::time_duration_type time_duration_type; + typedef ptime time_type; + //! Construct with date and offset in day + ptime(gregorian::date d,time_duration_type td) : date_time::base_time(d,td) + {} + //! Construct a time at start of the given day (midnight) + explicit ptime(gregorian::date d) : date_time::base_time(d,time_duration_type(0,0,0)) + {} + //! Copy from time_rep + ptime(const time_rep_type& rhs): + date_time::base_time(rhs) + {} + //! Construct from special value + ptime(const special_values sv) : date_time::base_time(sv) + {} +#if !defined(DATE_TIME_NO_DEFAULT_CONSTRUCTOR) + // Default constructor constructs to not_a_date_time + ptime() : date_time::base_time(gregorian::date(not_a_date_time), time_duration_type(not_a_date_time)) + {} +#endif // DATE_TIME_NO_DEFAULT_CONSTRUCTOR + + }; + + + +} }//namespace posix_time + + +#endif + diff --git a/win32/include/boost/date_time/posix_time/time_formatters.hpp b/win32/include/boost/date_time/posix_time/time_formatters.hpp new file mode 100755 index 000000000..2dfe9781d --- /dev/null +++ b/win32/include/boost/date_time/posix_time/time_formatters.hpp @@ -0,0 +1,289 @@ +#ifndef POSIXTIME_FORMATTERS_HPP___ +#define POSIXTIME_FORMATTERS_HPP___ + +/* Copyright (c) 2002-2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/gregorian.hpp" +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/iso_format.hpp" +#include "boost/date_time/date_format_simple.hpp" +#include "boost/date_time/posix_time/posix_time_types.hpp" +#include "boost/date_time/time_formatting_streams.hpp" + +#include "boost/date_time/time_parsing.hpp" + +/* NOTE: The "to_*_string" code for older compilers, ones that define + * BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS, is located in + * formatters_limited.hpp + */ + +namespace boost { + +namespace posix_time { + + // template function called by wrapper functions: + // to_*_string(time_duration) & to_*_wstring(time_duration) + template + inline std::basic_string to_simple_string_type(time_duration td) { + std::basic_ostringstream ss; + if(td.is_special()) { + /* simply using 'ss << td.get_rep()' won't work on compilers + * that don't support locales. This way does. */ + // switch copied from date_names_put.hpp + switch(td.get_rep().as_special()) + { + case not_a_date_time: + //ss << "not-a-number"; + ss << "not-a-date-time"; + break; + case pos_infin: + ss << "+infinity"; + break; + case neg_infin: + ss << "-infinity"; + break; + default: + ss << ""; + } + } + else { + charT fill_char = '0'; + if(td.is_negative()) { + ss << '-'; + } + ss << std::setw(2) << std::setfill(fill_char) + << date_time::absolute_value(td.hours()) << ":"; + ss << std::setw(2) << std::setfill(fill_char) + << date_time::absolute_value(td.minutes()) << ":"; + ss << std::setw(2) << std::setfill(fill_char) + << date_time::absolute_value(td.seconds()); + //TODO the following is totally non-generic, yelling FIXME +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + boost::int64_t frac_sec = + date_time::absolute_value(td.fractional_seconds()); + // JDG [7/6/02 VC++ compatibility] + charT buff[32]; + _i64toa(frac_sec, buff, 10); +#else + time_duration::fractional_seconds_type frac_sec = + date_time::absolute_value(td.fractional_seconds()); +#endif + if (frac_sec != 0) { + ss << "." << std::setw(time_duration::num_fractional_digits()) + << std::setfill(fill_char) + + // JDG [7/6/02 VC++ compatibility] +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + << buff; +#else + << frac_sec; +#endif + } + }// else + return ss.str(); + } + //! Time duration to string -hh::mm::ss.fffffff. Example: 10:09:03.0123456 + /*!\ingroup time_format + */ + inline std::string to_simple_string(time_duration td) { + return to_simple_string_type(td); + } + + + // template function called by wrapper functions: + // to_*_string(time_duration) & to_*_wstring(time_duration) + template + inline std::basic_string to_iso_string_type(time_duration td) + { + std::basic_ostringstream ss; + if(td.is_special()) { + /* simply using 'ss << td.get_rep()' won't work on compilers + * that don't support locales. This way does. */ + // switch copied from date_names_put.hpp + switch(td.get_rep().as_special()) { + case not_a_date_time: + //ss << "not-a-number"; + ss << "not-a-date-time"; + break; + case pos_infin: + ss << "+infinity"; + break; + case neg_infin: + ss << "-infinity"; + break; + default: + ss << ""; + } + } + else { + charT fill_char = '0'; + if(td.is_negative()) { + ss << '-'; + } + ss << std::setw(2) << std::setfill(fill_char) + << date_time::absolute_value(td.hours()); + ss << std::setw(2) << std::setfill(fill_char) + << date_time::absolute_value(td.minutes()); + ss << std::setw(2) << std::setfill(fill_char) + << date_time::absolute_value(td.seconds()); + //TODO the following is totally non-generic, yelling FIXME +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + boost::int64_t frac_sec = + date_time::absolute_value(td.fractional_seconds()); + // JDG [7/6/02 VC++ compatibility] + charT buff[32]; + _i64toa(frac_sec, buff, 10); +#else + time_duration::fractional_seconds_type frac_sec = + date_time::absolute_value(td.fractional_seconds()); +#endif + if (frac_sec != 0) { + ss << "." << std::setw(time_duration::num_fractional_digits()) + << std::setfill(fill_char) + + // JDG [7/6/02 VC++ compatibility] +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + << buff; +#else + << frac_sec; +#endif + } + }// else + return ss.str(); + } + //! Time duration in iso format -hhmmss,fffffff Example: 10:09:03,0123456 + /*!\ingroup time_format + */ + inline std::string to_iso_string(time_duration td){ + return to_iso_string_type(td); + } + + //! Time to simple format CCYY-mmm-dd hh:mm:ss.fffffff + /*!\ingroup time_format + */ + template + inline std::basic_string to_simple_string_type(ptime t) + { + // can't use this w/gcc295, no to_simple_string_type<>(td) available + std::basic_string ts = gregorian::to_simple_string_type(t.date());// + " "; + if(!t.time_of_day().is_special()) { + charT space = ' '; + return ts + space + to_simple_string_type(t.time_of_day()); + } + else { + return ts; + } + } + inline std::string to_simple_string(ptime t){ + return to_simple_string_type(t); + } + + // function called by wrapper functions to_*_string(time_period) + // & to_*_wstring(time_period) + template + inline std::basic_string to_simple_string_type(time_period tp) + { + charT beg = '[', mid = '/', end = ']'; + std::basic_string d1(to_simple_string_type(tp.begin())); + std::basic_string d2(to_simple_string_type(tp.last())); + return std::basic_string(beg + d1 + mid + d2 + end); + } + //! Convert to string of form [YYYY-mmm-DD HH:MM::SS.ffffff/YYYY-mmm-DD HH:MM::SS.fffffff] + /*!\ingroup time_format + */ + inline std::string to_simple_string(time_period tp){ + return to_simple_string_type(tp); + } + + // function called by wrapper functions to_*_string(time_period) + // & to_*_wstring(time_period) + template + inline std::basic_string to_iso_string_type(ptime t) + { + std::basic_string ts = gregorian::to_iso_string_type(t.date());// + "T"; + if(!t.time_of_day().is_special()) { + charT sep = 'T'; + return ts + sep + to_iso_string_type(t.time_of_day()); + } + else { + return ts; + } + } + //! Convert iso short form YYYYMMDDTHHMMSS where T is the date-time separator + /*!\ingroup time_format + */ + inline std::string to_iso_string(ptime t){ + return to_iso_string_type(t); + } + + + // function called by wrapper functions to_*_string(time_period) + // & to_*_wstring(time_period) + template + inline std::basic_string to_iso_extended_string_type(ptime t) + { + std::basic_string ts = gregorian::to_iso_extended_string_type(t.date());// + "T"; + if(!t.time_of_day().is_special()) { + charT sep = 'T'; + return ts + sep + to_simple_string_type(t.time_of_day()); + } + else { + return ts; + } + } + //! Convert to form YYYY-MM-DDTHH:MM:SS where T is the date-time separator + /*!\ingroup time_format + */ + inline std::string to_iso_extended_string(ptime t){ + return to_iso_extended_string_type(t); + } + +#if !defined(BOOST_NO_STD_WSTRING) + //! Time duration to wstring -hh::mm::ss.fffffff. Example: 10:09:03.0123456 + /*!\ingroup time_format + */ + inline std::wstring to_simple_wstring(time_duration td) { + return to_simple_string_type(td); + } + //! Time duration in iso format -hhmmss,fffffff Example: 10:09:03,0123456 + /*!\ingroup time_format + */ + inline std::wstring to_iso_wstring(time_duration td){ + return to_iso_string_type(td); + } + inline std::wstring to_simple_wstring(ptime t){ + return to_simple_string_type(t); + } + //! Convert to wstring of form [YYYY-mmm-DD HH:MM::SS.ffffff/YYYY-mmm-DD HH:MM::SS.fffffff] + /*!\ingroup time_format + */ + inline std::wstring to_simple_wstring(time_period tp){ + return to_simple_string_type(tp); + } + //! Convert iso short form YYYYMMDDTHHMMSS where T is the date-time separator + /*!\ingroup time_format + */ + inline std::wstring to_iso_wstring(ptime t){ + return to_iso_string_type(t); + } + //! Convert to form YYYY-MM-DDTHH:MM:SS where T is the date-time separator + /*!\ingroup time_format + */ + inline std::wstring to_iso_extended_wstring(ptime t){ + return to_iso_extended_string_type(t); + } + +#endif // BOOST_NO_STD_WSTRING + + +} } //namespace posix_time + + +#endif + diff --git a/win32/include/boost/date_time/posix_time/time_formatters_limited.hpp b/win32/include/boost/date_time/posix_time/time_formatters_limited.hpp new file mode 100755 index 000000000..0c6708080 --- /dev/null +++ b/win32/include/boost/date_time/posix_time/time_formatters_limited.hpp @@ -0,0 +1,211 @@ +#ifndef POSIXTIME_FORMATTERS_LIMITED_HPP___ +#define POSIXTIME_FORMATTERS_LIMITED_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/gregorian.hpp" +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/iso_format.hpp" +#include "boost/date_time/date_format_simple.hpp" +#include "boost/date_time/posix_time/posix_time_types.hpp" +#include "boost/date_time/time_formatting_streams.hpp" + +namespace boost { + +namespace posix_time { + + //! Time duration to string -hh::mm::ss.fffffff. Example: 10:09:03.0123456 + /*!\ingroup time_format + */ + inline std::string to_simple_string(time_duration td) { + std::ostringstream ss; + if(td.is_special()) { + /* simply using 'ss << td.get_rep()' won't work on compilers + * that don't support locales. This way does. */ + // switch copied from date_names_put.hpp + switch(td.get_rep().as_special()) + { + case not_a_date_time: + //ss << "not-a-number"; + ss << "not-a-date-time"; + break; + case pos_infin: + ss << "+infinity"; + break; + case neg_infin: + ss << "-infinity"; + break; + default: + ss << ""; + } + } + else { + if(td.is_negative()) { + ss << '-'; + } + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.hours()) << ":"; + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.minutes()) << ":"; + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.seconds()); + //TODO the following is totally non-generic, yelling FIXME +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + boost::int64_t frac_sec = + date_time::absolute_value(td.fractional_seconds()); + // JDG [7/6/02 VC++ compatibility] + char buff[32]; + _i64toa(frac_sec, buff, 10); +#else + time_duration::fractional_seconds_type frac_sec = + date_time::absolute_value(td.fractional_seconds()); +#endif + if (frac_sec != 0) { + ss << "." << std::setw(time_duration::num_fractional_digits()) + << std::setfill('0') + + // JDG [7/6/02 VC++ compatibility] +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + << buff; +#else + << frac_sec; +#endif + } + }// else + return ss.str(); + } + + //! Time duration in iso format -hhmmss,fffffff Example: 10:09:03,0123456 + /*!\ingroup time_format + */ + inline + std::string + to_iso_string(time_duration td) + { + std::ostringstream ss; + if(td.is_special()) { + /* simply using 'ss << td.get_rep()' won't work on compilers + * that don't support locales. This way does. */ + // switch copied from date_names_put.hpp + switch(td.get_rep().as_special()) { + case not_a_date_time: + //ss << "not-a-number"; + ss << "not-a-date-time"; + break; + case pos_infin: + ss << "+infinity"; + break; + case neg_infin: + ss << "-infinity"; + break; + default: + ss << ""; + } + } + else { + if(td.is_negative()) { + ss << '-'; + } + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.hours()); + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.minutes()); + ss << std::setw(2) << std::setfill('0') + << date_time::absolute_value(td.seconds()); + //TODO the following is totally non-generic, yelling FIXME +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + boost::int64_t frac_sec = + date_time::absolute_value(td.fractional_seconds()); + // JDG [7/6/02 VC++ compatibility] + char buff[32]; + _i64toa(frac_sec, buff, 10); +#else + time_duration::fractional_seconds_type frac_sec = + date_time::absolute_value(td.fractional_seconds()); +#endif + if (frac_sec != 0) { + ss << "." << std::setw(time_duration::num_fractional_digits()) + << std::setfill('0') + + // JDG [7/6/02 VC++ compatibility] +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + << buff; +#else + << frac_sec; +#endif + } + }// else + return ss.str(); + } + + //! Time to simple format CCYY-mmm-dd hh:mm:ss.fffffff + /*!\ingroup time_format + */ + inline + std::string + to_simple_string(ptime t) + { + std::string ts = gregorian::to_simple_string(t.date());// + " "; + if(!t.time_of_day().is_special()) { + return ts + " " + to_simple_string(t.time_of_day()); + } + else { + return ts; + } + } + + //! Convert to string of form [YYYY-mmm-DD HH:MM::SS.ffffff/YYYY-mmm-DD HH:MM::SS.fffffff] + /*!\ingroup time_format + */ + inline + std::string + to_simple_string(time_period tp) + { + std::string d1(to_simple_string(tp.begin())); + std::string d2(to_simple_string(tp.last())); + return std::string("[" + d1 + "/" + d2 +"]"); + } + + //! Convert iso short form YYYYMMDDTHHMMSS where T is the date-time separator + /*!\ingroup time_format + */ + inline + std::string to_iso_string(ptime t) + { + std::string ts = gregorian::to_iso_string(t.date());// + "T"; + if(!t.time_of_day().is_special()) { + return ts + "T" + to_iso_string(t.time_of_day()); + } + else { + return ts; + } + } + + //! Convert to form YYYY-MM-DDTHH:MM:SS where T is the date-time separator + /*!\ingroup time_format + */ + inline + std::string + to_iso_extended_string(ptime t) + { + std::string ts = gregorian::to_iso_extended_string(t.date());// + "T"; + if(!t.time_of_day().is_special()) { + return ts + "T" + to_simple_string(t.time_of_day()); + } + else { + return ts; + } + } + + +} } //namespace posix_time + + +#endif + diff --git a/win32/include/boost/date_time/posix_time/time_parsers.hpp b/win32/include/boost/date_time/posix_time/time_parsers.hpp new file mode 100755 index 000000000..d40270c62 --- /dev/null +++ b/win32/include/boost/date_time/posix_time/time_parsers.hpp @@ -0,0 +1,44 @@ +#ifndef POSIXTIME_PARSERS_HPP___ +#define POSIXTIME_PARSERS_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/gregorian/gregorian.hpp" +#include "boost/date_time/time_parsing.hpp" +#include "boost/date_time/posix_time/posix_time_types.hpp" + + +namespace boost { + +namespace posix_time { + + //! Creates a time_duration object from a delimited string + /*! Expected format for string is "[-]h[h][:mm][:ss][.fff]". + * A negative duration will be created if the first character in + * string is a '-', all other '-' will be treated as delimiters. + * Accepted delimiters are "-:,.". */ + inline time_duration duration_from_string(const std::string& s) { + return date_time::parse_delimited_time_duration(s); + } + + inline ptime time_from_string(const std::string& s) { + return date_time::parse_delimited_time(s, ' '); + } + + inline ptime from_iso_string(const std::string& s) { + return date_time::parse_iso_time(s, 'T'); + } + + + +} } //namespace posix_time + + +#endif + diff --git a/win32/include/boost/date_time/posix_time/time_period.hpp b/win32/include/boost/date_time/posix_time/time_period.hpp new file mode 100755 index 000000000..96ca0915a --- /dev/null +++ b/win32/include/boost/date_time/posix_time/time_period.hpp @@ -0,0 +1,29 @@ +#ifndef POSIX_TIME_PERIOD_HPP___ +#define POSIX_TIME_PERIOD_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/period.hpp" +#include "boost/date_time/posix_time/posix_time_duration.hpp" +#include "boost/date_time/posix_time/ptime.hpp" + +namespace boost { +namespace posix_time { + + //! Time period type + /*! \ingroup time_basics + */ + typedef date_time::period time_period; + + +} }//namespace posix_time + + +#endif + diff --git a/win32/include/boost/date_time/posix_time/time_serialize.hpp b/win32/include/boost/date_time/posix_time/time_serialize.hpp new file mode 100755 index 000000000..f338da17e --- /dev/null +++ b/win32/include/boost/date_time/posix_time/time_serialize.hpp @@ -0,0 +1,200 @@ +#ifndef POSIX_TIME_SERIALIZE_HPP___ +#define POSIX_TIME_SERIALIZE_HPP___ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/posix_time/posix_time.hpp" +#include "boost/date_time/gregorian/greg_serialize.hpp" +#include "boost/serialization/split_free.hpp" + + +// macros to split serialize functions into save & load functions +// NOTE: these macros define template functions in the boost::serialization namespace. +// They must be expanded *outside* of any namespace +BOOST_SERIALIZATION_SPLIT_FREE(boost::posix_time::ptime) +BOOST_SERIALIZATION_SPLIT_FREE(boost::posix_time::time_duration) +BOOST_SERIALIZATION_SPLIT_FREE(boost::posix_time::time_period) + +namespace boost { +namespace serialization { + + +/*** time_duration ***/ + +//! Function to save posix_time::time_duration objects using serialization lib +/*! time_duration objects are broken down into 4 parts for serialization: + * types are hour_type, min_type, sec_type, and fractional_seconds_type + * as defined in the time_duration class + */ +template +void save(Archive & ar, + const posix_time::time_duration& td, + unsigned int /*version*/) +{ + // serialize a bool so we know how to read this back in later + bool is_special = td.is_special(); + ar & make_nvp("is_special", is_special); + if(is_special) { + std::string s = to_simple_string(td); + ar & make_nvp("sv_time_duration", s); + } + else { + typename posix_time::time_duration::hour_type h = td.hours(); + typename posix_time::time_duration::min_type m = td.minutes(); + typename posix_time::time_duration::sec_type s = td.seconds(); + typename posix_time::time_duration::fractional_seconds_type fs = td.fractional_seconds(); + ar & make_nvp("time_duration_hours", h); + ar & make_nvp("time_duration_minutes", m); + ar & make_nvp("time_duration_seconds", s); + ar & make_nvp("time_duration_fractional_seconds", fs); + } +} + +//! Function to load posix_time::time_duration objects using serialization lib +/*! time_duration objects are broken down into 4 parts for serialization: + * types are hour_type, min_type, sec_type, and fractional_seconds_type + * as defined in the time_duration class + */ +template +void load(Archive & ar, + posix_time::time_duration & td, + unsigned int /*version*/) +{ + bool is_special = false; + ar & make_nvp("is_special", is_special); + if(is_special) { + std::string s; + ar & make_nvp("sv_time_duration", s); + posix_time::special_values sv = gregorian::special_value_from_string(s); + td = posix_time::time_duration(sv); + } + else { + typename posix_time::time_duration::hour_type h(0); + typename posix_time::time_duration::min_type m(0); + typename posix_time::time_duration::sec_type s(0); + typename posix_time::time_duration::fractional_seconds_type fs(0); + ar & make_nvp("time_duration_hours", h); + ar & make_nvp("time_duration_minutes", m); + ar & make_nvp("time_duration_seconds", s); + ar & make_nvp("time_duration_fractional_seconds", fs); + td = posix_time::time_duration(h,m,s,fs); + } +} + +// no load_construct_data function provided as time_duration provides a +// default constructor + +/*** ptime ***/ + +//! Function to save posix_time::ptime objects using serialization lib +/*! ptime objects are broken down into 2 parts for serialization: + * a date object and a time_duration onject + */ +template +void save(Archive & ar, + const posix_time::ptime& pt, + unsigned int /*version*/) +{ + // from_iso_string does not include fractional seconds + // therefore date and time_duration are used + typename posix_time::ptime::date_type d = pt.date(); + ar & make_nvp("ptime_date", d); + if(!pt.is_special()) { + typename posix_time::ptime::time_duration_type td = pt.time_of_day(); + ar & make_nvp("ptime_time_duration", td); + } +} + +//! Function to load posix_time::ptime objects using serialization lib +/*! ptime objects are broken down into 2 parts for serialization: + * a date object and a time_duration onject + */ +template +void load(Archive & ar, + posix_time::ptime & pt, + unsigned int /*version*/) +{ + // from_iso_string does not include fractional seconds + // therefore date and time_duration are used + typename posix_time::ptime::date_type d(posix_time::not_a_date_time); + typename posix_time::ptime::time_duration_type td; + ar & make_nvp("ptime_date", d); + if(!d.is_special()) { + ar & make_nvp("ptime_time_duration", td); + pt = boost::posix_time::ptime(d,td); + } + else { + pt = boost::posix_time::ptime(d.as_special()); + } + +} + +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, + posix_time::ptime* pt, + const unsigned int /*file_version*/) +{ + // retrieve data from archive required to construct new + // invoke inplace constructor to initialize instance of date + new(pt) boost::posix_time::ptime(boost::posix_time::not_a_date_time); +} + +/*** time_period ***/ + +//! Function to save posix_time::time_period objects using serialization lib +/*! time_period objects are broken down into 2 parts for serialization: + * a begining ptime object and an ending ptime object + */ +template +void save(Archive & ar, + const posix_time::time_period& tp, + unsigned int /*version*/) +{ + posix_time::ptime beg(tp.begin().date(), tp.begin().time_of_day()); + posix_time::ptime end(tp.end().date(), tp.end().time_of_day()); + ar & make_nvp("time_period_begin", beg); + ar & make_nvp("time_period_end", end); +} + +//! Function to load posix_time::time_period objects using serialization lib +/*! time_period objects are broken down into 2 parts for serialization: + * a begining ptime object and an ending ptime object + */ +template +void load(Archive & ar, + boost::posix_time::time_period & tp, + unsigned int /*version*/) +{ + posix_time::time_duration td(1,0,0); + gregorian::date d(gregorian::not_a_date_time); + posix_time::ptime beg(d,td); + posix_time::ptime end(d,td); + ar & make_nvp("time_period_begin", beg); + ar & make_nvp("time_period_end", end); + tp = boost::posix_time::time_period(beg, end); +} + +//!override needed b/c no default constructor +template +inline void load_construct_data(Archive & ar, + boost::posix_time::time_period* tp, + const unsigned int /*file_version*/) +{ + posix_time::time_duration td(1,0,0); + gregorian::date d(gregorian::not_a_date_time); + posix_time::ptime beg(d,td); + posix_time::ptime end(d,td); + new(tp) boost::posix_time::time_period(beg,end); +} + +} // namespace serialization +} // namespace boost + +#endif diff --git a/win32/include/boost/date_time/special_defs.hpp b/win32/include/boost/date_time/special_defs.hpp new file mode 100755 index 000000000..2d1c123d4 --- /dev/null +++ b/win32/include/boost/date_time/special_defs.hpp @@ -0,0 +1,25 @@ +#ifndef DATE_TIME_SPECIAL_DEFS_HPP__ +#define DATE_TIME_SPECIAL_DEFS_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +namespace boost { +namespace date_time { + + enum special_values {not_a_date_time, + neg_infin, pos_infin, + min_date_time, max_date_time, + not_special, NumSpecialValues}; + + +} } //namespace date_time + + +#endif + diff --git a/win32/include/boost/date_time/special_values_formatter.hpp b/win32/include/boost/date_time/special_values_formatter.hpp new file mode 100755 index 000000000..e3b13e57e --- /dev/null +++ b/win32/include/boost/date_time/special_values_formatter.hpp @@ -0,0 +1,96 @@ + +#ifndef DATETIME_SPECIAL_VALUE_FORMATTER_HPP___ +#define DATETIME_SPECIAL_VALUE_FORMATTER_HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include +#include +#include "boost/date_time/special_defs.hpp" + +namespace boost { namespace date_time { + + + //! Class that provides generic formmatting ostream formatting for special values + /*! This class provides for the formmating of special values to an output stream. + * In particular, it produces strings for the values of negative and positive + * infinity as well as not_a_date_time. + * + * While not a facet, this class is used by the date and time facets for formatting + * special value types. + * + */ + template > > + class special_values_formatter + { + public: + typedef std::basic_string string_type; + typedef CharT char_type; + typedef std::vector collection_type; + static const char_type default_special_value_names[3][17]; + + //! Construct special values formatter using default strings. + /*! Default strings are not-a-date-time -infinity +infinity + */ + special_values_formatter() + { + std::copy(&default_special_value_names[0], + &default_special_value_names[3], + std::back_inserter(m_special_value_names)); + } + + //! Construct special values formatter from array of strings + /*! This constructor will take pair of iterators from an array of strings + * that represent the special values and copy them for use in formatting + * special values. + *@code + * const char* const special_value_names[]={"nadt","-inf","+inf" }; + * + * special_value_formatter svf(&special_value_names[0], &special_value_names[3]); + *@endcode + */ + special_values_formatter(const char_type* const* begin, const char_type* const* end) + { + std::copy(begin, end, std::back_inserter(m_special_value_names)); + } + special_values_formatter(typename collection_type::iterator beg, typename collection_type::iterator end) + { + std::copy(beg, end, std::back_inserter(m_special_value_names)); + } + + OutItrT put_special(OutItrT next, + const boost::date_time::special_values& value) const + { + + unsigned int index = value; + if (index < m_special_value_names.size()) { + std::copy(m_special_value_names[index].begin(), + m_special_value_names[index].end(), + next); + } + return next; + } + protected: + collection_type m_special_value_names; + }; + + //! Storage for the strings used to indicate special values + /* using c_strings to initialize these worked fine in testing, however, + * a project that compiled its objects separately, then linked in a separate + * step wound up with redefinition errors for the values in this array. + * Initializing individual characters eliminated this problem */ + template + const typename special_values_formatter::char_type special_values_formatter::default_special_value_names[3][17] = { + {'n','o','t','-','a','-','d','a','t','e','-','t','i','m','e'}, + {'-','i','n','f','i','n','i','t','y'}, + {'+','i','n','f','i','n','i','t','y'} }; + + } } //namespace boost::date_time + +#endif diff --git a/win32/include/boost/date_time/special_values_parser.hpp b/win32/include/boost/date_time/special_values_parser.hpp new file mode 100755 index 000000000..7ad037554 --- /dev/null +++ b/win32/include/boost/date_time/special_values_parser.hpp @@ -0,0 +1,159 @@ + +#ifndef DATE_TIME_SPECIAL_VALUES_PARSER_HPP__ +#define DATE_TIME_SPECIAL_VALUES_PARSER_HPP__ + +/* Copyright (c) 2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: + */ + + +#include "boost/date_time/string_parse_tree.hpp" +#include "boost/date_time/special_defs.hpp" +#include +#include + +namespace boost { namespace date_time { + + //! Class for special_value parsing + /*! + * TODO: add doc-comments for which elements can be changed + * Parses input stream for strings representing special_values. + * Special values parsed are: + * - not_a_date_time + * - neg_infin + * - pod_infin + * - min_date_time + * - max_date_time + */ + template + class special_values_parser + { + public: + typedef std::basic_string string_type; + //typedef std::basic_stringstream stringstream_type; + typedef std::istreambuf_iterator stream_itr_type; + //typedef typename string_type::const_iterator const_itr; + //typedef typename date_type::year_type year_type; + //typedef typename date_type::month_type month_type; + typedef typename date_type::duration_type duration_type; + //typedef typename date_type::day_of_week_type day_of_week_type; + //typedef typename date_type::day_type day_type; + typedef string_parse_tree parse_tree_type; + typedef typename parse_tree_type::parse_match_result_type match_results; + typedef std::vector > collection_type; + + typedef charT char_type; + static const char_type nadt_string[16]; + static const char_type neg_inf_string[10]; + static const char_type pos_inf_string[10]; + static const char_type min_date_time_string[18]; + static const char_type max_date_time_string[18]; + + //! Creates a special_values_parser with the default set of "sv_strings" + special_values_parser() + { + sv_strings(string_type(nadt_string), + string_type(neg_inf_string), + string_type(pos_inf_string), + string_type(min_date_time_string), + string_type(max_date_time_string)); + } + + //! Creates a special_values_parser using a user defined set of element strings + special_values_parser(const string_type& nadt_str, + const string_type& neg_inf_str, + const string_type& pos_inf_str, + const string_type& min_dt_str, + const string_type& max_dt_str) + { + sv_strings(nadt_str, neg_inf_str, pos_inf_str, min_dt_str, max_dt_str); + } + + special_values_parser(typename collection_type::iterator beg, typename collection_type::iterator end) + { + collection_type phrases; + std::copy(beg, end, std::back_inserter(phrases)); + m_sv_strings = parse_tree_type(phrases, static_cast(not_a_date_time)); + } + + special_values_parser(const special_values_parser& svp) + { + this->m_sv_strings = svp.m_sv_strings; + } + + //! Replace special value strings + void sv_strings(const string_type& nadt_str, + const string_type& neg_inf_str, + const string_type& pos_inf_str, + const string_type& min_dt_str, + const string_type& max_dt_str) + { + collection_type phrases; + phrases.push_back(nadt_str); + phrases.push_back(neg_inf_str); + phrases.push_back(pos_inf_str); + phrases.push_back(min_dt_str); + phrases.push_back(max_dt_str); + m_sv_strings = parse_tree_type(phrases, static_cast(not_a_date_time)); + } + + /* Does not return a special_value because if the parsing fails, + * the return value will always be not_a_date_time + * (mr.current_match retains its default value of -1 on a failed + * parse and that casts to not_a_date_time). */ + //! Sets match_results.current_match to the corresponding special_value or -1 + bool match(stream_itr_type& sitr, + stream_itr_type& str_end, + match_results& mr) const + { + unsigned int level = 0; + m_sv_strings.match(sitr, str_end, mr, level); + return (mr.current_match != match_results::PARSE_ERROR); + } + /*special_values match(stream_itr_type& sitr, + stream_itr_type& str_end, + match_results& mr) const + { + unsigned int level = 0; + m_sv_strings.match(sitr, str_end, mr, level); + if(mr.current_match == match_results::PARSE_ERROR) { + throw std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'"); + } + return static_cast(mr.current_match); + }*/ + + + private: + parse_tree_type m_sv_strings; + + }; + + template + const typename special_values_parser::char_type + special_values_parser::nadt_string[16] = + {'n','o','t','-','a','-','d','a','t','e','-','t','i','m','e'}; + template + const typename special_values_parser::char_type + special_values_parser::neg_inf_string[10] = + {'-','i','n','f','i','n','i','t','y'}; + template + const typename special_values_parser::char_type + special_values_parser::pos_inf_string[10] = + {'+','i','n','f','i','n','i','t','y'}; + template + const typename special_values_parser::char_type + special_values_parser::min_date_time_string[18] = + {'m','i','n','i','m','u','m','-','d','a','t','e','-','t','i','m','e'}; + template + const typename special_values_parser::char_type + special_values_parser::max_date_time_string[18] = + {'m','a','x','i','m','u','m','-','d','a','t','e','-','t','i','m','e'}; + +} } //namespace + +#endif // DATE_TIME_SPECIAL_VALUES_PARSER_HPP__ + diff --git a/win32/include/boost/date_time/string_convert.hpp b/win32/include/boost/date_time/string_convert.hpp new file mode 100755 index 000000000..e5190a94d --- /dev/null +++ b/win32/include/boost/date_time/string_convert.hpp @@ -0,0 +1,33 @@ +#ifndef _STRING_CONVERT_HPP___ +#define _STRING_CONVERT_HPP___ + +/* Copyright (c) 2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/compiler_config.hpp" +#include + +namespace boost { +namespace date_time { + + //! Converts a string from one value_type to another + /*! Converts a wstring to a string (or a string to wstring). If both template parameters + * are of same type, a copy of the input string is returned. */ + template + inline + std::basic_string convert_string_type(const std::basic_string& inp_str) + { + typedef std::basic_string input_type; + typedef std::basic_string output_type; + output_type result; + result.insert(result.begin(), inp_str.begin(), inp_str.end()); + return result; + } + +}} // namespace boost::date_time + +#endif // _STRING_CONVERT_HPP___ diff --git a/win32/include/boost/date_time/string_parse_tree.hpp b/win32/include/boost/date_time/string_parse_tree.hpp new file mode 100755 index 000000000..fc357cfa5 --- /dev/null +++ b/win32/include/boost/date_time/string_parse_tree.hpp @@ -0,0 +1,278 @@ +#ifndef BOOST_DATE_TIME_STRING_PARSE_TREE___HPP__ +#define BOOST_DATE_TIME_STRING_PARSE_TREE___HPP__ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/lexical_cast.hpp" //error without? +#include "boost/algorithm/string/case_conv.hpp" +#include +#include +#include +#include + +namespace boost { namespace date_time { + + +template +struct parse_match_result +{ + parse_match_result() : + match_depth(0), + current_match(-1)// -1 is match_not-found value + {} + typedef std::basic_string string_type; + string_type remaining() const + { + if (match_depth == cache.size()) { + return string_type(); + } + if (current_match == -1) { + return cache; + } + //some of the cache was used return the rest + return string_type(cache, match_depth); + } + charT last_char() const + { + return cache[cache.size()-1]; + } + //! Returns true if more characters were parsed than was necessary + /*! Should be used in conjunction with last_char() + * to get the remaining character. + */ + bool has_remaining() const + { + return (cache.size() > match_depth); + } + + // cache will hold characters that have been read from the stream + string_type cache; + unsigned short match_depth; + short current_match; + enum PARSE_STATE { PARSE_ERROR= -1 }; +}; + + //for debug -- really only char streams... +template +std::basic_ostream& +operator<<(std::basic_ostream& os, parse_match_result& mr) +{ + os << "cm: " << mr.current_match + << " C: '" << mr.cache + << "' md: " << mr.match_depth + << " R: " << mr.remaining(); + return os; +} + + + +//! Recursive data structure to allow efficient parsing of various strings +/*! This class provides a quick lookup by building what amounts to a + * tree data structure. It also features a match function which can + * can handle nasty input interators by caching values as it recurses + * the tree so that it can backtrack as needed. + */ +template +struct string_parse_tree +{ +#if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581) ) + typedef std::multimap > ptree_coll; +#else + typedef std::multimap ptree_coll; +#endif + typedef typename ptree_coll::value_type value_type; + typedef typename ptree_coll::iterator iterator; + typedef typename ptree_coll::const_iterator const_iterator; + typedef std::basic_string string_type; + typedef std::vector > collection_type; + typedef parse_match_result parse_match_result_type; + + /*! Parameter "starting_point" desingates where the numbering begins. + * A starting_point of zero will start the numbering at zero + * (Sun=0, Mon=1, ...) were a starting_point of one starts the + * numbering at one (Jan=1, Feb=2, ...). The default is zero, + * negative vaules are not allowed */ + string_parse_tree(collection_type names, unsigned int starting_point=0) + { + // iterate thru all the elements and build the tree + unsigned short index = 0; + while (index != names.size() ) { + string_type s = boost::algorithm::to_lower_copy(names[index]); + insert(s, static_cast(index + starting_point)); + index++; + } + //set the last tree node = index+1 indicating a value + index++; + } + + + string_parse_tree(short value = -1) : + m_value(value) + {} + ptree_coll m_next_chars; + short m_value; + + void insert(const string_type& s, unsigned short value) + { + unsigned int i = 0; + iterator ti; + while(i < s.size()) { + if (i==0) { + if (i == (s.size()-1)) { + ti = m_next_chars.insert(value_type(s[i], + string_parse_tree(value))); + } + else { + ti = m_next_chars.insert(value_type(s[i], + string_parse_tree())); + } + } + else { + if (i == (s.size()-1)) { + ti = ti->second.m_next_chars.insert(value_type(s[i], + string_parse_tree(value))); + } + + else { + ti = ti->second.m_next_chars.insert(value_type(s[i], + string_parse_tree())); + } + + } + i++; + } + } + + + //! Recursive function that finds a matching string in the tree. + /*! Must check match_results::has_remaining() after match() is + * called. This is required so the user can determine if + * stream iterator is already pointing to the expected + * character or not (match() might advance sitr to next char in stream). + * + * A parse_match_result that has been returned from a failed match + * attempt can be sent in to the match function of a different + * string_parse_tree to attempt a match there. Use the iterators + * for the partially consumed stream, the parse_match_result object, + * and '0' for the level parameter. */ + short + match(std::istreambuf_iterator& sitr, + std::istreambuf_iterator& stream_end, + parse_match_result_type& result, + unsigned int& level) const + { + + level++; + charT c; + // if we conditionally advance sitr, we won't have + // to consume the next character past the input + bool adv_itr = true; + if (level > result.cache.size()) { + if (sitr == stream_end) return 0; //bail - input exhausted + c = static_cast(std::tolower(*sitr)); + //result.cache += c; + //sitr++; + } + else { + // if we're looking for characters from the cache, + // we don't want to increment sitr + adv_itr = false; + c = static_cast(std::tolower(result.cache[level-1])); + } + const_iterator litr = m_next_chars.lower_bound(c); + const_iterator uitr = m_next_chars.upper_bound(c); + while (litr != uitr) { // equal if not found + if(adv_itr) { + sitr++; + result.cache += c; + } + if (litr->second.m_value != -1) { // -1 is default value + if (result.match_depth < level) { + result.current_match = litr->second.m_value; + result.match_depth = static_cast(level); + } + litr->second.match(sitr, stream_end, + result, level); + level--; + } + else { + litr->second.match(sitr, stream_end, + result, level); + level--; + } + + if(level <= result.cache.size()) { + adv_itr = false; + } + + litr++; + } + return result.current_match; + + } + + /*! Must check match_results::has_remaining() after match() is + * called. This is required so the user can determine if + * stream iterator is already pointing to the expected + * character or not (match() might advance sitr to next char in stream). + */ + parse_match_result_type + match(std::istreambuf_iterator& sitr, + std::istreambuf_iterator& stream_end) const + { + // lookup to_lower of char in tree. + unsigned int level = 0; + // string_type cache; + parse_match_result_type result; + match(sitr, stream_end, result, level); + return result; + } + + void printme(std::ostream& os, int& level) + { + level++; + iterator itr = m_next_chars.begin(); + iterator end = m_next_chars.end(); + // os << "starting level: " << level << std::endl; + while (itr != end) { + os << "level: " << level + << " node: " << itr->first + << " value: " << itr->second.m_value + << std::endl; + itr->second.printme(os, level); + itr++; + } + level--; + } + + void print(std::ostream& os) + { + int level = 0; + printme(os, level); + } + + void printmatch(std::ostream& os, charT c) + { + iterator litr = m_next_chars.lower_bound(c); + iterator uitr = m_next_chars.upper_bound(c); + os << "matches for: " << c << std::endl; + while (litr != uitr) { + os << " node: " << litr->first + << " value: " << litr->second.m_value + << std::endl; + litr++; + } + } + +}; + + +} } //namespace +#endif diff --git a/win32/include/boost/date_time/strings_from_facet.hpp b/win32/include/boost/date_time/strings_from_facet.hpp new file mode 100755 index 000000000..11155d720 --- /dev/null +++ b/win32/include/boost/date_time/strings_from_facet.hpp @@ -0,0 +1,123 @@ +#ifndef DATE_TIME_STRINGS_FROM_FACET__HPP___ +#define DATE_TIME_STRINGS_FROM_FACET__HPP___ + +/* Copyright (c) 2004 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include +#include +#include +#include + +namespace boost { namespace date_time { + +//! This function gathers up all the month strings from a std::locale +/*! Using the time_put facet, this function creates a collection of + * all the month strings from a locale. This is handy when building + * custom date parsers or formatters that need to be localized. + * + *@param charT The type of char to use when gathering typically char + * or wchar_t. + *@param locale The locale to use when gathering the strings + *@param short_strings True(default) to gather short strings, + * false for long strings. + *@return A vector of strings containing the strings in order. eg: + * Jan, Feb, Mar, etc. + */ +template +std::vector > +gather_month_strings(const std::locale& locale, bool short_strings=true) +{ + typedef std::basic_string string_type; + typedef std::vector collection_type; + typedef std::basic_ostringstream ostream_type; + typedef std::ostreambuf_iterator ostream_iter_type; + typedef std::basic_ostringstream stringstream_type; + typedef std::time_put time_put_facet_type; + charT short_fmt[3] = { '%', 'b' }; + charT long_fmt[3] = { '%', 'B' }; + collection_type months; + string_type outfmt(short_fmt); + if (!short_strings) { + outfmt = long_fmt; + } + { + //grab the needed strings by using the locale to + //output each month + for (int m=0; m < 12; m++) { + tm tm_value; + tm_value.tm_mon = m; + stringstream_type ss; + ostream_iter_type oitr(ss); + std::use_facet(locale).put(oitr, ss, ss.fill(), + &tm_value, + &*outfmt.begin(), + &*outfmt.begin()+outfmt.size()); + months.push_back(ss.str()); + } + } + return months; +} + +//! This function gathers up all the weekday strings from a std::locale +/*! Using the time_put facet, this function creates a collection of + * all the weekday strings from a locale starting with the string for + * 'Sunday'. This is handy when building custom date parsers or + * formatters that need to be localized. + * + *@param charT The type of char to use when gathering typically char + * or wchar_t. + *@param locale The locale to use when gathering the strings + *@param short_strings True(default) to gather short strings, + * false for long strings. + *@return A vector of strings containing the weekdays in order. eg: + * Sun, Mon, Tue, Wed, Thu, Fri, Sat + */ +template +std::vector > +gather_weekday_strings(const std::locale& locale, bool short_strings=true) +{ + typedef std::basic_string string_type; + typedef std::vector collection_type; + typedef std::basic_ostringstream ostream_type; + typedef std::ostreambuf_iterator ostream_iter_type; + typedef std::basic_ostringstream stringstream_type; + typedef std::time_put time_put_facet_type; + charT short_fmt[3] = { '%', 'a' }; + charT long_fmt[3] = { '%', 'A' }; + + collection_type weekdays; + + + string_type outfmt(short_fmt); + if (!short_strings) { + outfmt = long_fmt; + } + { + //grab the needed strings by using the locale to + //output each month / weekday + for (int i=0; i < 7; i++) { + tm tm_value; + tm_value.tm_wday = i; + stringstream_type ss; + ostream_iter_type oitr(ss); + std::use_facet(locale).put(oitr, ss, ss.fill(), + &tm_value, + &*outfmt.begin(), + &*outfmt.begin()+outfmt.size()); + + weekdays.push_back(ss.str()); + } + } + return weekdays; +} + +} } //namespace + + +#endif diff --git a/win32/include/boost/date_time/testfrmwk.hpp b/win32/include/boost/date_time/testfrmwk.hpp new file mode 100755 index 000000000..6450ecf78 --- /dev/null +++ b/win32/include/boost/date_time/testfrmwk.hpp @@ -0,0 +1,66 @@ + +#ifndef TEST_FRMWK_HPP___ +#define TEST_FRMWK_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * $Date: 2008-03-26 17:16:15 -0400 (Wed, 26 Mar 2008) $ + */ + + +#include +#include + +//! Really simple test framework for counting and printing +class TestStats +{ +public: + static TestStats& instance() {static TestStats ts; return ts;} + void addPassingTest() {testcount_++; passcount_++;} + void addFailingTest() {testcount_++;} + unsigned int testcount() const {return testcount_;} + unsigned int passcount() const {return passcount_;} + void print(std::ostream& out = std::cout) const + { + out << testcount_ << " Tests Executed: " ; + if (passcount() != testcount()) { + out << (testcount() - passcount()) << " FAILURES"; + } + else { + out << "All Succeeded" << std::endl; + } + out << std::endl; + } +private: + TestStats() : testcount_(0), passcount_(0) {} + unsigned int testcount_; + unsigned int passcount_; +}; + + +bool check(const std::string& testname, bool testcond) +{ + TestStats& stat = TestStats::instance(); + if (testcond) { + std::cout << "Pass :: " << testname << " " << std::endl; + stat.addPassingTest(); + return true; + } + else { + stat.addFailingTest(); + std::cout << "FAIL :: " << testname << " " << std::endl; + return false; + } +} + + +int printTestStats() +{ + TestStats& stat = TestStats::instance(); + stat.print(); + return stat.testcount() - stat.passcount(); +} + +#endif diff --git a/win32/include/boost/date_time/time.hpp b/win32/include/boost/date_time/time.hpp new file mode 100755 index 000000000..512a1e5e2 --- /dev/null +++ b/win32/include/boost/date_time/time.hpp @@ -0,0 +1,190 @@ +#ifndef DATE_TIME_TIME_HPP___ +#define DATE_TIME_TIME_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +/*! @file time.hpp + This file contains the interface for the time associated classes. +*/ +#include "boost/date_time/time_defs.hpp" +#include "boost/operators.hpp" +#include + +namespace boost { +namespace date_time { + + //! Representation of a precise moment in time, including the date. + /*! + This class is a skeleton for the interface of a temporal type + with a resolution that is higher than a day. It is intended that + this class be the base class and that the actual time + class be derived using the BN pattern. In this way, the derived + class can make decisions such as 'should there be a default constructor' + and what should it set its value to, should there be optional constructors + say allowing only an time_durations that generate a time from a clock,etc. + So, in fact multiple time types can be created for a time_system with + different construction policies, and all of them can perform basic + operations by only writing a copy constructor. Finally, compiler + errors are also shorter. + + The real behavior of the time class is provided by the time_system + template parameter. This class must provide all the logic + for addition, subtraction, as well as define all the interface + types. + + */ + + template + class base_time : private + boost::less_than_comparable > + { + public: + typedef T time_type; + typedef typename time_system::time_rep_type time_rep_type; + typedef typename time_system::date_type date_type; + typedef typename time_system::date_duration_type date_duration_type; + typedef typename time_system::time_duration_type time_duration_type; + //typedef typename time_system::hms_type hms_type; + + base_time(const date_type& day, + const time_duration_type& td, + dst_flags dst=not_dst) : + time_(time_system::get_time_rep(day, td, dst)) + {} + base_time(special_values sv) : + time_(time_system::get_time_rep(sv)) + {} + base_time(const time_rep_type& rhs) : + time_(rhs) + {} + date_type date() const + { + return time_system::get_date(time_); + } + time_duration_type time_of_day() const + { + return time_system::get_time_of_day(time_); + } + /*! Optional bool parameter will return time zone as an offset + * (ie "+07:00"). Empty string is returned for classes that do + * not use a time_zone */ + std::string zone_name(bool as_offset=false) const + { + return time_system::zone_name(time_); + } + /*! Optional bool parameter will return time zone as an offset + * (ie "+07:00"). Empty string is returned for classes that do + * not use a time_zone */ + std::string zone_abbrev(bool as_offset=false) const + { + return time_system::zone_name(time_); + } + //! An empty string is returned for classes that do not use a time_zone + std::string zone_as_posix_string() const + { + return std::string(""); + } + + //! check to see if date is not a value + bool is_not_a_date_time() const + { + return time_.is_not_a_date_time(); + } + //! check to see if date is one of the infinity values + bool is_infinity() const + { + return (is_pos_infinity() || is_neg_infinity()); + } + //! check to see if date is greater than all possible dates + bool is_pos_infinity() const + { + return time_.is_pos_infinity(); + } + //! check to see if date is greater than all possible dates + bool is_neg_infinity() const + { + return time_.is_neg_infinity(); + } + //! check to see if time is a special value + bool is_special() const + { + return(is_not_a_date_time() || is_infinity()); + } + //!Equality operator -- others generated by boost::equality_comparable + bool operator==(const time_type& rhs) const + { + return time_system::is_equal(time_,rhs.time_); + } + //!Equality operator -- others generated by boost::less_than_comparable + bool operator<(const time_type& rhs) const + { + return time_system::is_less(time_,rhs.time_); + } + //! difference between two times + time_duration_type operator-(const time_type& rhs) const + { + return time_system::subtract_times(time_, rhs.time_); + } + //! add date durations + time_type operator+(const date_duration_type& dd) const + { + return time_system::add_days(time_, dd); + } + time_type operator+=(const date_duration_type& dd) + { + time_ = (time_system::get_time_rep(date() + dd, time_of_day())); + return time_type(time_); + } + //! subtract date durations + time_type operator-(const date_duration_type& dd) const + { + return time_system::subtract_days(time_, dd); + } + time_type operator-=(const date_duration_type& dd) + { + time_ = (time_system::get_time_rep(date() - dd, time_of_day())); + return time_type(time_); + } + //! add time durations + time_type operator+(const time_duration_type& td) const + { + return time_type(time_system::add_time_duration(time_, td)); + } + time_type operator+=(const time_duration_type& td) + { + time_ = (time_system::get_time_rep(date(), time_of_day() + td)); + return time_type(time_); + } + //! subtract time durations + time_type operator-(const time_duration_type& rhs) const + { + return time_system::subtract_time_duration(time_, rhs); + } + time_type operator-=(const time_duration_type& td) + { + time_ = (time_system::get_time_rep(date(), time_of_day() - td)); + return time_type(time_); + } + + protected: + time_rep_type time_; + }; + + + + + +} } //namespace date_time::boost + + +#endif + diff --git a/win32/include/boost/date_time/time_clock.hpp b/win32/include/boost/date_time/time_clock.hpp new file mode 100755 index 000000000..38f17d93f --- /dev/null +++ b/win32/include/boost/date_time/time_clock.hpp @@ -0,0 +1,83 @@ +#ifndef DATE_TIME_TIME_CLOCK_HPP___ +#define DATE_TIME_TIME_CLOCK_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +/*! @file time_clock.hpp + This file contains the interface for clock devices. +*/ + +#include "boost/date_time/c_time.hpp" +#include "boost/shared_ptr.hpp" + +namespace boost { +namespace date_time { + + + //! A clock providing time level services based on C time_t capabilities + /*! This clock provides resolution to the 1 second level + */ + template + class second_clock + { + public: + typedef typename time_type::date_type date_type; + typedef typename time_type::time_duration_type time_duration_type; + + static time_type local_time() + { + ::std::time_t t; + ::std::time(&t); + ::std::tm curr, *curr_ptr; + //curr_ptr = ::std::localtime(&t); + curr_ptr = c_time::localtime(&t, &curr); + return create_time(curr_ptr); + } + + + //! Get the current day in universal date as a ymd_type + static time_type universal_time() + { + + ::std::time_t t; + ::std::time(&t); + ::std::tm curr, *curr_ptr; + //curr_ptr = ::std::gmtime(&t); + curr_ptr = c_time::gmtime(&t, &curr); + return create_time(curr_ptr); + } + + template + static time_type local_time(boost::shared_ptr tz_ptr) + { + typedef typename time_type::utc_time_type utc_time_type; + utc_time_type utc_time = second_clock::universal_time(); + return time_type(utc_time, tz_ptr); + } + + + private: + static time_type create_time(::std::tm* current) + { + date_type d(static_cast(current->tm_year + 1900), + static_cast(current->tm_mon + 1), + static_cast(current->tm_mday)); + time_duration_type td(current->tm_hour, + current->tm_min, + current->tm_sec); + return time_type(d,td); + } + + }; + + +} } //namespace date_time + + +#endif diff --git a/win32/include/boost/date_time/time_defs.hpp b/win32/include/boost/date_time/time_defs.hpp new file mode 100755 index 000000000..f33b7e554 --- /dev/null +++ b/win32/include/boost/date_time/time_defs.hpp @@ -0,0 +1,33 @@ +#ifndef DATE_TIME_TIME_PRECISION_LIMITS_HPP +#define DATE_TIME_TIME_PRECISION_LIMITS_HPP + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + + +/*! \file time_defs.hpp + This file contains nice definitions for handling the resoluion of various time + reprsentations. +*/ + +namespace boost { +namespace date_time { + + //!Defines some nice types for handling time level resolutions + enum time_resolutions {sec, tenth, hundreth, milli, ten_thousandth, micro, nano, NumResolutions }; + + //! Flags for daylight savings or summer time + enum dst_flags {not_dst, is_dst, calculate}; + + +} } //namespace date_time + + + +#endif diff --git a/win32/include/boost/date_time/time_duration.hpp b/win32/include/boost/date_time/time_duration.hpp new file mode 100755 index 000000000..eba1ef38f --- /dev/null +++ b/win32/include/boost/date_time/time_duration.hpp @@ -0,0 +1,281 @@ +#ifndef DATE_TIME_TIME_DURATION_HPP___ +#define DATE_TIME_TIME_DURATION_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/operators.hpp" +#include "boost/date_time/time_defs.hpp" +#include "boost/date_time/special_defs.hpp" +#include "boost/date_time/compiler_config.hpp" + +namespace boost { +namespace date_time { + + + //! Represents some amount of elapsed time measure to a given resolution + /*! This class represents a standard set of capabilities for all + counted time durations. Time duration implementations should derive + from this class passing their type as the first template parameter. + This design allows the subclass duration types to provide custom + construction policies or other custom features not provided here. + + @param T The subclass type + @param rep_type The time resolution traits for this duration type. + */ + template + class time_duration : private + boost::less_than_comparable > + /* dividable, addable, and subtractable operator templates + * won't work with this class (MSVC++ 6.0). return type + * from '+=' is different than expected return type + * from '+'. multipliable probably wont work + * either (haven't tried) */ + { + public: + typedef T duration_type; //the subclass + typedef rep_type traits_type; + typedef typename rep_type::day_type day_type; + typedef typename rep_type::hour_type hour_type; + typedef typename rep_type::min_type min_type; + typedef typename rep_type::sec_type sec_type; + typedef typename rep_type::fractional_seconds_type fractional_seconds_type; + typedef typename rep_type::tick_type tick_type; + typedef typename rep_type::impl_type impl_type; + + time_duration() : ticks_(0) {} + time_duration(hour_type hours_in, + min_type minutes_in, + sec_type seconds_in=0, + fractional_seconds_type frac_sec_in = 0) : + ticks_(rep_type::to_tick_count(hours_in,minutes_in,seconds_in,frac_sec_in)) + {} + // copy constructor required for dividable<> + //! Construct from another time_duration (Copy constructor) + time_duration(const time_duration& other) + : ticks_(other.ticks_) + {} + //! Construct from special_values + time_duration(special_values sv) : ticks_(impl_type::from_special(sv)) + {} + //! Returns smallest representable duration + static duration_type unit() + { + return duration_type(0,0,0,1); + } + //! Return the number of ticks in a second + static tick_type ticks_per_second() + { + return rep_type::res_adjust(); + } + //! Provide the resolution of this duration type + static time_resolutions resolution() + { + return rep_type::resolution(); + } + //! Returns number of hours in the duration + hour_type hours() const + { + return static_cast(ticks() / (3600*ticks_per_second())); + } + //! Returns normalized number of minutes + min_type minutes() const + { + return static_cast((ticks() / (60*ticks_per_second())) % 60); + } + //! Returns normalized number of seconds (0..60) + sec_type seconds() const + { + return static_cast((ticks()/ticks_per_second()) % 60); + } + //! Returns total number of seconds truncating any fractional seconds + sec_type total_seconds() const + { + return static_cast(ticks() / ticks_per_second()); + } + //! Returns total number of milliseconds truncating any fractional seconds + tick_type total_milliseconds() const + { + if (ticks_per_second() < 1000) { + return ticks() * (static_cast(1000) / ticks_per_second()); + } + return ticks() / (ticks_per_second() / static_cast(1000)) ; + } + //! Returns total number of nanoseconds truncating any sub millisecond values + tick_type total_nanoseconds() const + { + if (ticks_per_second() < 1000000000) { + return ticks() * (static_cast(1000000000) / ticks_per_second()); + } + return ticks() / (ticks_per_second() / static_cast(1000000000)) ; + } + //! Returns total number of microseconds truncating any sub microsecond values + tick_type total_microseconds() const + { + if (ticks_per_second() < 1000000) { + return ticks() * (static_cast(1000000) / ticks_per_second()); + } + return ticks() / (ticks_per_second() / static_cast(1000000)) ; + } + //! Returns count of fractional seconds at given resolution + fractional_seconds_type fractional_seconds() const + { + return (ticks() % ticks_per_second()); + } + //! Returns number of possible digits in fractional seconds + static unsigned short num_fractional_digits() + { + return rep_type::num_fractional_digits(); + } + duration_type invert_sign() const + { + return duration_type(ticks_ * (-1)); + } + bool is_negative() const + { + return ticks_ < 0; + } + bool operator<(const time_duration& rhs) const + { + return ticks_ < rhs.ticks_; + } + bool operator==(const time_duration& rhs) const + { + return ticks_ == rhs.ticks_; + } + //! unary- Allows for time_duration td = -td1 + duration_type operator-()const + { + return duration_type(ticks_ * (-1)); + } + duration_type operator-(const duration_type& d) const + { + return duration_type(ticks_ - d.ticks_); + } + duration_type operator+(const duration_type& d) const + { + return duration_type(ticks_ + d.ticks_); + } + duration_type operator/(int divisor) const + { + return duration_type(ticks_ / divisor); + } + duration_type operator-=(const duration_type& d) + { + ticks_ = ticks_ - d.ticks_; + return duration_type(ticks_); + } + duration_type operator+=(const duration_type& d) + { + ticks_ = ticks_ + d.ticks_; + return duration_type(ticks_); + } + //! Division operations on a duration with an integer. + duration_type operator/=(int divisor) + { + ticks_ = ticks_ / divisor; + return duration_type(ticks_); + } + //! Multiplication operations an a duration with an integer + duration_type operator*(int rhs) const + { + return duration_type(ticks_ * rhs); + } + duration_type operator*=(int divisor) + { + ticks_ = ticks_ * divisor; + return duration_type(ticks_); + } + tick_type ticks() const + { + return traits_type::as_number(ticks_); + } + + //! Is ticks_ a special value? + bool is_special()const + { + if(traits_type::is_adapted()) + { + return ticks_.is_special(); + } + else{ + return false; + } + } + //! Is duration pos-infinity + bool is_pos_infinity()const + { + if(traits_type::is_adapted()) + { + return ticks_.is_pos_infinity(); + } + else{ + return false; + } + } + //! Is duration neg-infinity + bool is_neg_infinity()const + { + if(traits_type::is_adapted()) + { + return ticks_.is_neg_infinity(); + } + else{ + return false; + } + } + //! Is duration not-a-date-time + bool is_not_a_date_time()const + { + if(traits_type::is_adapted()) + { + return ticks_.is_nan(); + } + else{ + return false; + } + } + + //! Used for special_values output + impl_type get_rep()const + { + return ticks_; + } + + protected: + explicit time_duration(impl_type in) : ticks_(in) {}; + impl_type ticks_; + }; + + + + //! Template for instantiating derived adjusting durations + /* These templates are designed to work with multiples of + * 10 for frac_of_second and resoultion adjustment + */ + template + class subsecond_duration : public base_duration + { + public: + typedef typename base_duration::traits_type traits_type; + explicit subsecond_duration(boost::int64_t ss) : + base_duration(0,0,0,ss*traits_type::res_adjust()/frac_of_second) + {} + }; + + + +} } //namespace date_time + + + + +#endif + diff --git a/win32/include/boost/date_time/time_facet.hpp b/win32/include/boost/date_time/time_facet.hpp new file mode 100755 index 000000000..3ade78b4f --- /dev/null +++ b/win32/include/boost/date_time/time_facet.hpp @@ -0,0 +1,1263 @@ + +#ifndef _DATE_TIME_FACET__HPP__ +#define _DATE_TIME_FACET__HPP__ + +/* Copyright (c) 2004-2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Martin Andrian, Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/date_time/date_facet.hpp" +#include "boost/date_time/string_convert.hpp" +#include "boost/algorithm/string/erase.hpp" +#include +#include +#include + +namespace boost { +namespace date_time { + + template + struct time_formats { + public: + typedef CharT char_type; + static const char_type fractional_seconds_format[3]; // f + static const char_type fractional_seconds_or_none_format[3]; // F + static const char_type seconds_with_fractional_seconds_format[3]; // s + static const char_type seconds_format[3]; // S + static const char_type standard_format[9]; // x X + static const char_type zone_abbrev_format[3]; // z + static const char_type zone_name_format[3]; // Z + static const char_type zone_iso_format[3]; // q + static const char_type zone_iso_extended_format[3]; // Q + static const char_type posix_zone_string_format[4]; // ZP + static const char_type duration_sign_negative_only[3]; // - + static const char_type duration_sign_always[3]; // + + static const char_type duration_seperator[2]; + static const char_type negative_sign[2]; //- + static const char_type positive_sign[2]; //+ + static const char_type iso_time_format_specifier[18]; + static const char_type iso_time_format_extended_specifier[22]; + //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] + static const char_type default_time_format[23]; + // default_time_input_format uses a posix_time_zone_string instead of a time zone abbrev + static const char_type default_time_input_format[24]; + //default time_duration format is HH:MM:SS[.fff...] + static const char_type default_time_duration_format[11]; + }; + + template + const typename time_formats::char_type + time_formats::fractional_seconds_format[3] = {'%','f'}; + + template + const typename time_formats::char_type + time_formats::fractional_seconds_or_none_format[3] = {'%','F'}; + + template + const typename time_formats::char_type + time_formats::seconds_with_fractional_seconds_format[3] = + {'%','s'}; + + template + const typename time_formats::char_type + time_formats::seconds_format[3] = {'%','S'}; + + template + const typename time_formats::char_type + //time_formats::standard_format[5] = {'%','c',' ','%','z'}; + time_formats::standard_format[9] = {'%','x',' ','%','X',' ','%','z'}; + + template + const typename time_formats::char_type + time_formats::zone_abbrev_format[3] = {'%','z'}; + + template + const typename time_formats::char_type + time_formats::zone_name_format[3] = {'%','Z'}; + + template + const typename time_formats::char_type + time_formats::zone_iso_format[3] = {'%','q'}; + + template + const typename time_formats::char_type + time_formats::zone_iso_extended_format[3] ={'%','Q'}; + + template + const typename time_formats::char_type + time_formats::posix_zone_string_format[4] ={'%','Z','P'}; + + template + const typename time_formats::char_type + time_formats::duration_seperator[2] = {':'}; + + template + const typename time_formats::char_type + time_formats::negative_sign[2] = {'-'}; + + template + const typename time_formats::char_type + time_formats::positive_sign[2] = {'+'}; + + template + const typename time_formats::char_type + time_formats::duration_sign_negative_only[3] ={'%','-'}; + + template + const typename time_formats::char_type + time_formats::duration_sign_always[3] ={'%','+'}; + + template + const typename time_formats::char_type + time_formats::iso_time_format_specifier[18] = + {'%', 'Y', '%', 'm', '%', 'd', 'T', + '%', 'H', '%', 'M', '%', 'S', '%', 'F', '%','q' }; + + template + const typename time_formats::char_type + time_formats::iso_time_format_extended_specifier[22] = + {'%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', + '%', 'H', ':', '%', 'M', ':', '%', 'S', '%', 'F','%','Q'}; + + template + const typename time_formats::char_type + time_formats::default_time_format[23] = + {'%','Y','-','%','b','-','%','d',' ', + '%','H',':','%','M',':','%','S','%','F',' ','%','z'}; + + template + const typename time_formats::char_type + time_formats::default_time_input_format[24] = + {'%','Y','-','%','b','-','%','d',' ', + '%','H',':','%','M',':','%','S','%','F',' ','%','Z','P'}; + + template + const typename time_formats::char_type + time_formats::default_time_duration_format[11] = + {'%','H',':','%','M',':','%','S','%','F'}; + + + + /*! Facet used for format-based output of time types + * This class provides for the use of format strings to output times. In addition + * to the flags for formatting date elements, the following are the allowed format flags: + * - %x %X => default format - enables addition of more flags to default (ie. "%x %X %z") + * - %f => fractional seconds ".123456" + * - %F => fractional seconds or none: like frac sec but empty if frac sec == 0 + * - %s => seconds w/ fractional sec "02.123" (this is the same as "%S%f) + * - %S => seconds "02" + * - %z => abbreviated time zone "EDT" + * - %Z => full time zone name "Eastern Daylight Time" + */ + template > > + class time_facet : + public boost::date_time::date_facet { + public: + typedef typename time_type::date_type date_type; + typedef typename time_type::time_duration_type time_duration_type; + typedef boost::date_time::period period_type; + typedef boost::date_time::date_facet base_type; + typedef typename base_type::string_type string_type; + typedef typename base_type::char_type char_type; + typedef typename base_type::period_formatter_type period_formatter_type; + typedef typename base_type::special_values_formatter_type special_values_formatter_type; + typedef typename base_type::date_gen_formatter_type date_gen_formatter_type; + static const char_type* fractional_seconds_format; // %f + static const char_type* fractional_seconds_or_none_format; // %F + static const char_type* seconds_with_fractional_seconds_format; // %s + static const char_type* seconds_format; // %S + static const char_type* standard_format; // %x X + static const char_type* zone_abbrev_format; // %z + static const char_type* zone_name_format; // %Z + static const char_type* zone_iso_format; // %q + static const char_type* zone_iso_extended_format; // %Q + static const char_type* posix_zone_string_format; // %ZP + static const char_type* duration_seperator; + static const char_type* duration_sign_always; // %+ + static const char_type* duration_sign_negative_only; // %- + static const char_type* negative_sign; //- + static const char_type* positive_sign; //+ + static const char_type* iso_time_format_specifier; + static const char_type* iso_time_format_extended_specifier; + + //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] + static const char_type* default_time_format; + //default time_duration format is HH:MM:SS[.fff...] + static const char_type* default_time_duration_format; + static std::locale::id id; + +#if defined (__SUNPRO_CC) && defined (_RWSTD_VER) + std::locale::id& __get_id (void) const { return id; } +#endif + + //! sets default formats for ptime, local_date_time, and time_duration + explicit time_facet(::size_t /* a_ref */ = 0) + //: base_type(standard_format), + : base_type(default_time_format), + m_time_duration_format(string_type(duration_sign_negative_only) + default_time_duration_format) + {} + + //! Construct the facet with an explicitly specified format + explicit time_facet(const char_type* a_format, + period_formatter_type period_formatter = period_formatter_type(), + const special_values_formatter_type& special_value_formatter = special_values_formatter_type(), + date_gen_formatter_type dg_formatter = date_gen_formatter_type(), + ::size_t a_ref = 0) + : base_type(a_format, + period_formatter, + special_value_formatter, + dg_formatter, + a_ref), + m_time_duration_format(string_type(duration_sign_negative_only) + default_time_duration_format) + {} + + //! Changes format for time_duration + void time_duration_format(const char_type* const format) + { + m_time_duration_format = format; + } + + virtual void set_iso_format() + { + this->m_format = iso_time_format_specifier; + } + virtual void set_iso_extended_format() + { + this->m_format = iso_time_format_extended_specifier; + } + + OutItrT put(OutItrT a_next, + std::ios_base& a_ios, + char_type a_fill, + const time_type& a_time) const + { + if (a_time.is_special()) { + return this->do_put_special(a_next, a_ios, a_fill, + a_time.date().as_special()); + } + string_type format(this->m_format); + string_type frac_str; + if (format.find(seconds_with_fractional_seconds_format) != string_type::npos) { + // replace %s with %S.nnn + frac_str = + fractional_seconds_as_string(a_time.time_of_day(), false); + char_type sep = std::use_facet >(a_ios.getloc()).decimal_point(); + + string_type replace_string(seconds_format); + replace_string += sep; + replace_string += frac_str; + boost::algorithm::replace_all(format, + seconds_with_fractional_seconds_format, + replace_string); + } + /* NOTE: replacing posix_zone_string_format must be done BEFORE + * zone_name_format: "%ZP" & "%Z", if Z is checked first it will + * incorrectly replace a zone_name where a posix_string should go */ + if (format.find(posix_zone_string_format) != string_type::npos) { + if(a_time.zone_abbrev().empty()) { + // if zone_abbrev() returns an empty string, we want to + // erase posix_zone_string_format from format + boost::algorithm::replace_all(format, + posix_zone_string_format, + ""); + } + else{ + boost::algorithm::replace_all(format, + posix_zone_string_format, + a_time.zone_as_posix_string()); + } + } + if (format.find(zone_name_format) != string_type::npos) { + if(a_time.zone_name().empty()) { + /* TODO: this'll probably create problems if a user places + * the zone_*_format flag in the format with a ptime. This + * code removes the flag from the default formats */ + + // if zone_name() returns an empty string, we want to + // erase zone_name_format & one preceeding space + std::basic_ostringstream ss; + ss << ' ' << zone_name_format; + boost::algorithm::replace_all(format, + ss.str(), + ""); + } + else{ + boost::algorithm::replace_all(format, + zone_name_format, + a_time.zone_name()); + } + } + if (format.find(zone_abbrev_format) != string_type::npos) { + if(a_time.zone_abbrev(false).empty()) { + /* TODO: this'll probably create problems if a user places + * the zone_*_format flag in the format with a ptime. This + * code removes the flag from the default formats */ + + // if zone_abbrev() returns an empty string, we want to + // erase zone_abbrev_format & one preceeding space + std::basic_ostringstream ss; + ss << ' ' << zone_abbrev_format; + boost::algorithm::replace_all(format, + ss.str(), + ""); + } + else{ + boost::algorithm::replace_all(format, + zone_abbrev_format, + a_time.zone_abbrev(false)); + } + } + if (format.find(zone_iso_extended_format) != string_type::npos) { + if(a_time.zone_name(true).empty()) { + /* TODO: this'll probably create problems if a user places + * the zone_*_format flag in the format with a ptime. This + * code removes the flag from the default formats */ + + // if zone_name() returns an empty string, we want to + // erase zone_iso_extended_format from format + boost::algorithm::replace_all(format, + zone_iso_extended_format, + ""); + } + else{ + boost::algorithm::replace_all(format, + zone_iso_extended_format, + a_time.zone_name(true)); + } + } + + if (format.find(zone_iso_format) != string_type::npos) { + if(a_time.zone_abbrev(true).empty()) { + /* TODO: this'll probably create problems if a user places + * the zone_*_format flag in the format with a ptime. This + * code removes the flag from the default formats */ + + // if zone_abbrev() returns an empty string, we want to + // erase zone_iso_format from format + boost::algorithm::replace_all(format, + zone_iso_format, + ""); + } + else{ + boost::algorithm::replace_all(format, + zone_iso_format, + a_time.zone_abbrev(true)); + } + } + if (format.find(fractional_seconds_format) != string_type::npos) { + // replace %f with nnnnnnn + if (!frac_str.size()) { + frac_str = fractional_seconds_as_string(a_time.time_of_day(), false); + } + boost::algorithm::replace_all(format, + fractional_seconds_format, + frac_str); + } + + if (format.find(fractional_seconds_or_none_format) != string_type::npos) { + // replace %F with nnnnnnn or nothing if fs == 0 + frac_str = + fractional_seconds_as_string(a_time.time_of_day(), true); + if (frac_str.size()) { + char_type sep = std::use_facet >(a_ios.getloc()).decimal_point(); + string_type replace_string; + replace_string += sep; + replace_string += frac_str; + boost::algorithm::replace_all(format, + fractional_seconds_or_none_format, + replace_string); + } + else { + boost::algorithm::erase_all(format, + fractional_seconds_or_none_format); + } + } + + return this->do_put_tm(a_next, a_ios, a_fill, + to_tm(a_time), format); + } + + //! put function for time_duration + OutItrT put(OutItrT a_next, + std::ios_base& a_ios, + char_type a_fill, + const time_duration_type& a_time_dur) const + { + if (a_time_dur.is_special()) { + return this->do_put_special(a_next, a_ios, a_fill, + a_time_dur.get_rep().as_special()); + } + + string_type format(m_time_duration_format); + if (a_time_dur.is_negative()) { + // replace %- with minus sign. Should we use the numpunct facet? + boost::algorithm::replace_all(format, + duration_sign_negative_only, + negative_sign); + // remove all the %+ in the string with '-' + boost::algorithm::replace_all(format, + duration_sign_always, + negative_sign); + } + else { //duration is positive + // remove all the %- combos from the string + boost::algorithm::replace_all(format, + duration_sign_negative_only, + ""); + // remove all the %+ in the string with '+' + boost::algorithm::replace_all(format, + duration_sign_always, + positive_sign); + } + + string_type frac_str; + if (format.find(seconds_with_fractional_seconds_format) != string_type::npos) { + // replace %s with %S.nnn + frac_str = + fractional_seconds_as_string(a_time_dur, false); + char_type sep = std::use_facet >(a_ios.getloc()).decimal_point(); + + string_type replace_string(seconds_format); + replace_string += sep; + replace_string += frac_str; + boost::algorithm::replace_all(format, + seconds_with_fractional_seconds_format, + replace_string); + } + if (format.find(fractional_seconds_format) != string_type::npos) { + // replace %f with nnnnnnn + if (!frac_str.size()) { + frac_str = fractional_seconds_as_string(a_time_dur, false); + } + boost::algorithm::replace_all(format, + fractional_seconds_format, + frac_str); + } + + if (format.find(fractional_seconds_or_none_format) != string_type::npos) { + // replace %F with nnnnnnn or nothing if fs == 0 + frac_str = + fractional_seconds_as_string(a_time_dur, true); + if (frac_str.size()) { + char_type sep = std::use_facet >(a_ios.getloc()).decimal_point(); + string_type replace_string; + replace_string += sep; + replace_string += frac_str; + boost::algorithm::replace_all(format, + fractional_seconds_or_none_format, + replace_string); + } + else { + boost::algorithm::erase_all(format, + fractional_seconds_or_none_format); + } + } + + return this->do_put_tm(a_next, a_ios, a_fill, + to_tm(a_time_dur), format); + } + + OutItrT put(OutItrT next, std::ios_base& a_ios, + char_type fill, const period_type& p) const + { + return this->m_period_formatter.put_period(next, a_ios, fill,p,*this); + } + + + protected: + + static + string_type + fractional_seconds_as_string(const time_duration_type& a_time, + bool null_when_zero) + { + typename time_duration_type::fractional_seconds_type frac_sec = + a_time.fractional_seconds(); + + if (null_when_zero && (frac_sec == 0)) { + return string_type(); + } + + //make sure there is no sign + frac_sec = date_time::absolute_value(frac_sec); + std::basic_ostringstream ss; + ss.imbue(std::locale::classic()); // don't want any formatting + ss << std::setw(time_duration_type::num_fractional_digits()) + << std::setfill(static_cast('0')); +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + // JDG [7/6/02 VC++ compatibility] + char_type buff[34]; + ss << _i64toa(static_cast(frac_sec), buff, 10); +#else + ss << frac_sec; +#endif + return ss.str(); + } + + private: + string_type m_time_duration_format; + + }; + + template + std::locale::id time_facet::id; + + template + const typename time_facet::char_type* + time_facet::fractional_seconds_format = time_formats::fractional_seconds_format; + + template + const typename time_facet::char_type* + time_facet::fractional_seconds_or_none_format = time_formats::fractional_seconds_or_none_format; + + template + const typename time_facet::char_type* + time_facet::seconds_with_fractional_seconds_format = + time_formats::seconds_with_fractional_seconds_format; + + + template + const typename time_facet::char_type* + time_facet::zone_name_format = time_formats::zone_name_format; + + template + const typename time_facet::char_type* + time_facet::zone_abbrev_format = time_formats::zone_abbrev_format; + + template + const typename time_facet::char_type* + time_facet::zone_iso_extended_format =time_formats::zone_iso_extended_format; + + template + const typename time_facet::char_type* + time_facet::posix_zone_string_format =time_formats::posix_zone_string_format; + + template + const typename time_facet::char_type* + time_facet::zone_iso_format = time_formats::zone_iso_format; + + template + const typename time_facet::char_type* + time_facet::seconds_format = time_formats::seconds_format; + + template + const typename time_facet::char_type* + time_facet::standard_format = time_formats::standard_format; + + template + const typename time_facet::char_type* + time_facet::duration_seperator = time_formats::duration_seperator; + + template + const typename time_facet::char_type* + time_facet::negative_sign = time_formats::negative_sign; + + template + const typename time_facet::char_type* + time_facet::positive_sign = time_formats::positive_sign; + + template + const typename time_facet::char_type* + time_facet::duration_sign_negative_only = time_formats::duration_sign_negative_only; + + template + const typename time_facet::char_type* + time_facet::duration_sign_always = time_formats::duration_sign_always; + + template + const typename time_facet::char_type* + time_facet::iso_time_format_specifier = time_formats::iso_time_format_specifier; + + template + const typename time_facet::char_type* + time_facet::iso_time_format_extended_specifier = time_formats::iso_time_format_extended_specifier; + + template + const typename time_facet::char_type* + time_facet::default_time_format = + time_formats::default_time_format; + + template + const typename time_facet::char_type* + time_facet::default_time_duration_format = + time_formats::default_time_duration_format; + + + //! Facet for format-based input. + /*! + */ + template > > + class time_input_facet : + public boost::date_time::date_input_facet { + public: + typedef typename time_type::date_type date_type; + typedef typename time_type::time_duration_type time_duration_type; + typedef typename time_duration_type::fractional_seconds_type fracional_seconds_type; + typedef boost::date_time::period period_type; + typedef boost::date_time::date_input_facet base_type; + typedef typename base_type::duration_type date_duration_type; + typedef typename base_type::year_type year_type; + typedef typename base_type::month_type month_type; + typedef typename base_type::day_type day_type; + typedef typename base_type::string_type string_type; + typedef typename string_type::const_iterator const_itr; + typedef typename base_type::char_type char_type; + typedef typename base_type::format_date_parser_type format_date_parser_type; + typedef typename base_type::period_parser_type period_parser_type; + typedef typename base_type::special_values_parser_type special_values_parser_type; + typedef typename base_type::date_gen_parser_type date_gen_parser_type; + typedef typename base_type::special_values_parser_type::match_results match_results; + + static const char_type* fractional_seconds_format; // f + static const char_type* fractional_seconds_or_none_format; // F + static const char_type* seconds_with_fractional_seconds_format; // s + static const char_type* seconds_format; // S + static const char_type* standard_format; // x X + static const char_type* zone_abbrev_format; // z + static const char_type* zone_name_format; // Z + static const char_type* zone_iso_format; // q + static const char_type* zone_iso_extended_format; // Q + static const char_type* duration_seperator; + static const char_type* iso_time_format_specifier; + static const char_type* iso_time_format_extended_specifier; + static const char_type* default_time_input_format; + static const char_type* default_time_duration_format; + static std::locale::id id; + + //! Constructor that takes a format string for a ptime + explicit time_input_facet(const string_type& format, ::size_t a_ref = 0) + : base_type(format, a_ref), + m_time_duration_format(default_time_duration_format) + { } + + explicit time_input_facet(const string_type& format, + const format_date_parser_type& date_parser, + const special_values_parser_type& sv_parser, + const period_parser_type& per_parser, + const date_gen_parser_type& date_gen_parser, + ::size_t a_ref = 0) + : base_type(format, + date_parser, + sv_parser, + per_parser, + date_gen_parser, + a_ref), + m_time_duration_format(default_time_duration_format) + {} + + //! sets default formats for ptime, local_date_time, and time_duration + explicit time_input_facet(::size_t a_ref = 0) + : base_type(default_time_input_format, a_ref), + m_time_duration_format(default_time_duration_format) + { } + + //! Set the format for time_duration + void time_duration_format(const char_type* const format) { + m_time_duration_format = format; + } + virtual void set_iso_format() + { + this->m_format = iso_time_format_specifier; + } + virtual void set_iso_extended_format() + { + this->m_format = iso_time_format_extended_specifier; + } + + InItrT get(InItrT& sitr, + InItrT& stream_end, + std::ios_base& a_ios, + period_type& p) const + { + p = this->m_period_parser.get_period(sitr, + stream_end, + a_ios, + p, + time_duration_type::unit(), + *this); + return sitr; + } + + //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] + //default time_duration format is %H:%M:%S%F HH:MM:SS[.fff...] + + InItrT get(InItrT& sitr, + InItrT& stream_end, + std::ios_base& a_ios, + time_duration_type& td) const + { + // skip leading whitespace + while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } + + bool use_current_char = false; + + // num_get will consume the +/-, we may need a copy if special_value + char_type c = '\0'; + if((sitr != stream_end) && (*sitr == '-' || *sitr == '+')) { + c = *sitr; + } + + long hour = 0; + long min = 0; + long sec = 0; + typename time_duration_type::fractional_seconds_type frac(0); + + typedef std::num_get num_get; + if(!std::has_facet(a_ios.getloc())) { + num_get* ng = new num_get(); + std::locale loc = std::locale(a_ios.getloc(), ng); + a_ios.imbue(loc); + } + + const_itr itr(m_time_duration_format.begin()); + while (itr != m_time_duration_format.end() && (sitr != stream_end)) { + if (*itr == '%') { + itr++; + if (*itr != '%') { + switch(*itr) { + case 'H': + { + match_results mr; + hour = fixed_string_to_int(sitr, stream_end, mr, 2); + if(hour == -1){ + return check_special_value(sitr, stream_end, td, c); + } + break; + } + case 'M': + { + match_results mr; + min = fixed_string_to_int(sitr, stream_end, mr, 2); + if(min == -1){ + return check_special_value(sitr, stream_end, td, c); + } + break; + } + case 'S': + { + match_results mr; + sec = fixed_string_to_int(sitr, stream_end, mr, 2); + if(sec == -1){ + return check_special_value(sitr, stream_end, td, c); + } + break; + } + case 's': + { + match_results mr; + sec = fixed_string_to_int(sitr, stream_end, mr, 2); + if(sec == -1){ + return check_special_value(sitr, stream_end, td, c); + } + // %s is the same as %S%f so we drop through into %f + //break; + } + case 'f': + { + // check for decimal, check special_values if missing + if(*sitr == '.') { + ++sitr; + parse_frac_type(sitr, stream_end, frac); + // sitr will point to next expected char after this parsing + // is complete so no need to advance it + use_current_char = true; + } + else { + return check_special_value(sitr, stream_end, td, c); + } + break; + } + case 'F': + { + // check for decimal, skip if missing + if(*sitr == '.') { + ++sitr; + parse_frac_type(sitr, stream_end, frac); + // sitr will point to next expected char after this parsing + // is complete so no need to advance it + use_current_char = true; + } + else { + // nothing was parsed so we don't want to advance sitr + use_current_char = true; + } + break; + } + default: + {} // ignore what we don't understand? + }// switch + } + else { // itr == '%', second consecutive + sitr++; + } + + itr++; //advance past format specifier + } + else { //skip past chars in format and in buffer + itr++; + // set use_current_char when sitr is already + // pointing at the next character to process + if (use_current_char) { + use_current_char = false; + } + else { + sitr++; + } + } + } + + td = time_duration_type(hour, min, sec, frac); + return sitr; + } + + + //! Parses a time object from the input stream + InItrT get(InItrT& sitr, + InItrT& stream_end, + std::ios_base& a_ios, + time_type& t) const + { + string_type tz_str; + return get(sitr, stream_end, a_ios, t, tz_str, false); + } + //! Expects a time_zone in the input stream + InItrT get_local_time(InItrT& sitr, + InItrT& stream_end, + std::ios_base& a_ios, + time_type& t, + string_type& tz_str) const + { + return get(sitr, stream_end, a_ios, t, tz_str, true); + } + + protected: + + InItrT get(InItrT& sitr, + InItrT& stream_end, + std::ios_base& a_ios, + time_type& t, + string_type& tz_str, + bool time_is_local) const + { + // skip leading whitespace + while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } + + bool use_current_char = false; + bool use_current_format_char = false; // used whith two character flags + + // num_get will consume the +/-, we may need a copy if special_value + char_type c = '\0'; + if((sitr != stream_end) && (*sitr == '-' || *sitr == '+')) { + c = *sitr; + } + + // time elements + long hour = 0; + long min = 0; + long sec = 0; + typename time_duration_type::fractional_seconds_type frac(0); + // date elements + short day_of_year(0); + /* Initialized the following to their minimum values. These intermediate + * objects are used so we get specific exceptions when part of the input + * is unparsable. + * Ex: "205-Jan-15" will throw a bad_year, "2005-Jsn-15"- bad_month, etc.*/ + year_type t_year(1400); + month_type t_month(1); + day_type t_day(1); + + typedef std::num_get num_get; + if(!std::has_facet(a_ios.getloc())) { + num_get* ng = new num_get(); + std::locale loc = std::locale(a_ios.getloc(), ng); + a_ios.imbue(loc); + } + + const_itr itr(this->m_format.begin()); + while (itr != this->m_format.end() && (sitr != stream_end)) { + if (*itr == '%') { + itr++; + if (*itr != '%') { + // the cases are grouped by date & time flags - not alphabetical order + switch(*itr) { + // date flags + case 'Y': + case 'y': + { + char_type cs[3] = { '%', *itr }; + string_type s(cs); + match_results mr; + try { + t_year = this->m_parser.parse_year(sitr, stream_end, s, mr); + } + catch(std::out_of_range bad_year) { // base class for bad_year exception + if(this->m_sv_parser.match(sitr, stream_end, mr)) { + t = time_type(static_cast(mr.current_match)); + return sitr; + } + else { + throw; // rethrow bad_year + } + } + break; + } + case 'B': + case 'b': + case 'm': + { + char_type cs[3] = { '%', *itr }; + string_type s(cs); + match_results mr; + try { + t_month = this->m_parser.parse_month(sitr, stream_end, s, mr); + } + catch(std::out_of_range bad_month) { // base class for bad_month exception + if(this->m_sv_parser.match(sitr, stream_end, mr)) { + t = time_type(static_cast(mr.current_match)); + return sitr; + } + else { + throw; // rethrow bad_year + } + } + // did m_parser already advance sitr to next char? + if(mr.has_remaining()) { + use_current_char = true; + } + break; + } + case 'a': + case 'A': + case 'w': + { + // weekday is not used in construction but we need to get it out of the stream + char_type cs[3] = { '%', *itr }; + string_type s(cs); + match_results mr; + typename date_type::day_of_week_type wd(0); + try { + wd = this->m_parser.parse_weekday(sitr, stream_end, s, mr); + } + catch(std::out_of_range bad_weekday) { // base class for bad_weekday exception + if(this->m_sv_parser.match(sitr, stream_end, mr)) { + t = time_type(static_cast(mr.current_match)); + return sitr; + } + else { + throw; // rethrow bad_weekday + } + } + // did m_parser already advance sitr to next char? + if(mr.has_remaining()) { + use_current_char = true; + } + break; + } + case 'j': + { + // code that gets julian day (from format_date_parser) + match_results mr; + day_of_year = fixed_string_to_int(sitr, stream_end, mr, 3); + if(day_of_year == -1) { + if(this->m_sv_parser.match(sitr, stream_end, mr)) { + t = time_type(static_cast(mr.current_match)); + return sitr; + } + } + // these next two lines are so we get an exception with bad input + typedef typename time_type::date_type::day_of_year_type day_of_year_type; + day_of_year_type t_day_of_year(day_of_year); + break; + } + case 'd': + { + try { + t_day = this->m_parser.parse_day_of_month(sitr, stream_end); + } + catch(std::out_of_range bad_day_of_month) { // base class for exception + match_results mr; + if(this->m_sv_parser.match(sitr, stream_end, mr)) { + t = time_type(static_cast(mr.current_match)); + return sitr; + } + else { + throw; // rethrow bad_year + } + } + break; + } + // time flags + case 'H': + { + match_results mr; + hour = fixed_string_to_int(sitr, stream_end, mr, 2); + if(hour == -1){ + return check_special_value(sitr, stream_end, t, c); + } + break; + } + case 'M': + { + match_results mr; + min = fixed_string_to_int(sitr, stream_end, mr, 2); + if(min == -1){ + return check_special_value(sitr, stream_end, t, c); + } + break; + } + case 'S': + { + match_results mr; + sec = fixed_string_to_int(sitr, stream_end, mr, 2); + if(sec == -1){ + return check_special_value(sitr, stream_end, t, c); + } + break; + } + case 's': + { + match_results mr; + sec = fixed_string_to_int(sitr, stream_end, mr, 2); + if(sec == -1){ + return check_special_value(sitr, stream_end, t, c); + } + // %s is the same as %S%f so we drop through into %f + //break; + } + case 'f': + { + // check for decimal, check SV if missing + if(*sitr == '.') { + ++sitr; + parse_frac_type(sitr, stream_end, frac); + // sitr will point to next expected char after this parsing + // is complete so no need to advance it + use_current_char = true; + } + else { + return check_special_value(sitr, stream_end, t, c); + } + break; + } + case 'F': + { + // check for decimal, skip if missing + if(*sitr == '.') { + ++sitr; + parse_frac_type(sitr, stream_end, frac); + // sitr will point to next expected char after this parsing + // is complete so no need to advance it + use_current_char = true; + } + else { + // nothing was parsed so we don't want to advance sitr + use_current_char = true; + } + break; + } + // time_zone flags + //case 'q': + //case 'Q': + //case 'z': + case 'Z': + { + if(time_is_local) { // skip if 't' is a ptime + ++itr; + if(*itr == 'P') { + // skip leading whitespace + while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } + // parse zone + while((sitr != stream_end) && (!std::isspace(*sitr))) { + tz_str += *sitr; + ++sitr; + } + } + else { + use_current_format_char = true; + } + + } + else { + // nothing was parsed so we don't want to advance sitr + use_current_char = true; + } + + break; + } + default: + {} // ignore what we don't understand? + }// switch + } + else { // itr == '%', second consecutive + sitr++; + } + + if(use_current_format_char) { + use_current_format_char = false; + } + else { + itr++; //advance past format specifier + } + + } + else { //skip past chars in format and in buffer + itr++; + // set use_current_char when sitr is already + // pointing at the next character to process + if (use_current_char) { + use_current_char = false; + } + else { + sitr++; + } + } + } + + date_type d(not_a_date_time); + if (day_of_year > 0) { + d = date_type(static_cast(t_year-1),12,31) + date_duration_type(day_of_year); + } + else { + d = date_type(t_year, t_month, t_day); + } + + time_duration_type td(hour, min, sec, frac); + t = time_type(d, td); + return sitr; + } + + //! Helper function to check for special_value + /*! First character may have been consumed during original parse + * attempt. Parameter 'c' should be a copy of that character. + * Throws ios_base::failure if parse fails. */ + template + inline + InItrT check_special_value(InItrT& sitr,InItrT& stream_end, temporal_type& tt, char_type c='\0') const + { + match_results mr; + if((c == '-' || c == '+') && (*sitr != c)) { // was the first character consumed? + mr.cache += c; + } + this->m_sv_parser.match(sitr, stream_end, mr); + if(mr.current_match == match_results::PARSE_ERROR) { + std::string tmp = convert_string_type(mr.cache); + throw std::ios_base::failure("Parse failed. No match found for '" + tmp + "'"); + } + tt = temporal_type(static_cast(mr.current_match)); + return sitr; + } + + //! Helper function for parsing a fractional second type from the stream + void parse_frac_type(InItrT& sitr, + InItrT& stream_end, + fracional_seconds_type& frac) const + { + string_type cache; + while((sitr != stream_end) && std::isdigit(*sitr)) { + cache += *sitr; + ++sitr; + } + if(cache.size() > 0) { + unsigned short precision = time_duration_type::num_fractional_digits(); + // input may be only the first few decimal places + if(cache.size() < precision) { + frac = lexical_cast(cache); + frac = decimal_adjust(frac, static_cast(precision - cache.size())); + } + else { + // if input has too many decimal places, drop excess digits + frac = lexical_cast(cache.substr(0, precision)); + } + } + } + + private: + string_type m_time_duration_format; + + //! Helper function to adjust trailing zeros when parsing fractional digits + template + inline + int_type decimal_adjust(int_type val, const unsigned short places) const + { + unsigned long factor = 1; + for(int i = 0; i < places; ++i){ + factor *= 10; // shift decimal to the right + } + return val * factor; + } + + }; + +template + std::locale::id time_input_facet::id; + +template + const typename time_input_facet::char_type* + time_input_facet::fractional_seconds_format = time_formats::fractional_seconds_format; + + template + const typename time_input_facet::char_type* + time_input_facet::fractional_seconds_or_none_format = time_formats::fractional_seconds_or_none_format; + + template + const typename time_input_facet::char_type* + time_input_facet::seconds_with_fractional_seconds_format = time_formats::seconds_with_fractional_seconds_format; + + template + const typename time_input_facet::char_type* + time_input_facet::seconds_format = time_formats::seconds_format; + + template + const typename time_input_facet::char_type* + time_input_facet::standard_format = time_formats::standard_format; + + template + const typename time_input_facet::char_type* + time_input_facet::zone_abbrev_format = time_formats::zone_abbrev_format; + + template + const typename time_input_facet::char_type* + time_input_facet::zone_name_format = time_formats::zone_name_format; + + template + const typename time_input_facet::char_type* + time_input_facet::zone_iso_format = time_formats::zone_iso_format; + + template + const typename time_input_facet::char_type* + time_input_facet::zone_iso_extended_format = time_formats::zone_iso_extended_format; + + template + const typename time_input_facet::char_type* + time_input_facet::duration_seperator = time_formats::duration_seperator; + + template + const typename time_input_facet::char_type* + time_input_facet::iso_time_format_specifier = time_formats::iso_time_format_specifier; + + template + const typename time_input_facet::char_type* + time_input_facet::iso_time_format_extended_specifier = time_formats::iso_time_format_extended_specifier; + + template + const typename time_input_facet::char_type* + time_input_facet::default_time_input_format = time_formats::default_time_input_format; + + template + const typename time_input_facet::char_type* + time_input_facet::default_time_duration_format = time_formats::default_time_duration_format; + + +} } // namespaces + + +#endif + diff --git a/win32/include/boost/date_time/time_formatting_streams.hpp b/win32/include/boost/date_time/time_formatting_streams.hpp new file mode 100755 index 000000000..0595f82b8 --- /dev/null +++ b/win32/include/boost/date_time/time_formatting_streams.hpp @@ -0,0 +1,119 @@ +#ifndef DATE_TIME_TIME_FORMATTING_STREAMS_HPP___ +#define DATE_TIME_TIME_FORMATTING_STREAMS_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/date_formatting_locales.hpp" +#include "boost/date_time/time_resolution_traits.hpp" + +#ifndef BOOST_DATE_TIME_NO_LOCALE + +namespace boost { +namespace date_time { + + + //! Put a time type into a stream using appropriate facets + template + class ostream_time_duration_formatter + { + public: + typedef std::basic_ostream ostream_type; + typedef typename time_duration_type::fractional_seconds_type fractional_seconds_type; + + //! Put time into an ostream + static void duration_put(const time_duration_type& td, + ostream_type& os) + { + if(td.is_special()) { + os << td.get_rep(); + } + else { + charT fill_char = '0'; + if(td.is_negative()) { + os << '-'; + } + os << std::setw(2) << std::setfill(fill_char) + << absolute_value(td.hours()) << ":"; + os << std::setw(2) << std::setfill(fill_char) + << absolute_value(td.minutes()) << ":"; + os << std::setw(2) << std::setfill(fill_char) + << absolute_value(td.seconds()); + fractional_seconds_type frac_sec = + absolute_value(td.fractional_seconds()); + if (frac_sec != 0) { + os << "." + << std::setw(time_duration_type::num_fractional_digits()) + << std::setfill(fill_char) + << frac_sec; + } + } // else + } // duration_put + }; //class ostream_time_duration_formatter + + //! Put a time type into a stream using appropriate facets + template + class ostream_time_formatter + { + public: + typedef std::basic_ostream ostream_type; + typedef typename time_type::date_type date_type; + typedef typename time_type::time_duration_type time_duration_type; + typedef ostream_time_duration_formatter duration_formatter; + + //! Put time into an ostream + static void time_put(const time_type& t, + ostream_type& os) + { + date_type d = t.date(); + os << d; + if(!d.is_infinity() && !d.is_not_a_date()) + { + os << " "; //TODO: fix the separator here. + duration_formatter::duration_put(t.time_of_day(), os); + } + + } // time_to_ostream + }; //class ostream_time_formatter + + + //! Put a time period into a stream using appropriate facets + template + class ostream_time_period_formatter + { + public: + typedef std::basic_ostream ostream_type; + typedef typename time_period_type::point_type time_type; + typedef ostream_time_formatter time_formatter; + + //! Put time into an ostream + static void period_put(const time_period_type& tp, + ostream_type& os) + { + os << '['; //TODO: facet or manipulator for periods? + time_formatter::time_put(tp.begin(), os); + os << '/'; //TODO: facet or manipulator for periods? + time_formatter::time_put(tp.last(), os); + os << ']'; + + } // period_put + + }; //class ostream_time_period_formatter + + + +} } //namespace date_time + +#endif //BOOST_DATE_TIME_NO_LOCALE + +#endif + diff --git a/win32/include/boost/date_time/time_iterator.hpp b/win32/include/boost/date_time/time_iterator.hpp new file mode 100755 index 000000000..37f7782b1 --- /dev/null +++ b/win32/include/boost/date_time/time_iterator.hpp @@ -0,0 +1,52 @@ +#ifndef DATE_TIME_TIME_ITERATOR_HPP___ +#define DATE_TIME_TIME_ITERATOR_HPP___ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +namespace boost { +namespace date_time { + + + //! Simple time iterator skeleton class + template + class time_itr { + public: + typedef typename time_type::time_duration_type time_duration_type; + time_itr(time_type t, time_duration_type d) : current_(t), offset_(d) {}; + time_itr& operator++() + { + current_ = current_ + offset_; + return *this; + } + time_itr& operator--() + { + current_ = current_ - offset_; + return *this; + } + time_type operator*() {return current_;}; + time_type* operator->() {return ¤t_;}; + bool operator< (const time_type& t) {return current_ < t;}; + bool operator<= (const time_type& t) {return current_ <= t;}; + bool operator!= (const time_type& t) {return current_ != t;}; + bool operator== (const time_type& t) {return current_ == t;}; + bool operator> (const time_type& t) {return current_ > t;}; + bool operator>= (const time_type& t) {return current_ >= t;}; + + private: + time_type current_; + time_duration_type offset_; + }; + + + +} }//namespace date_time + + +#endif diff --git a/win32/include/boost/date_time/time_parsing.hpp b/win32/include/boost/date_time/time_parsing.hpp new file mode 100755 index 000000000..6d3954b61 --- /dev/null +++ b/win32/include/boost/date_time/time_parsing.hpp @@ -0,0 +1,321 @@ +#ifndef _DATE_TIME_TIME_PARSING_HPP___ +#define _DATE_TIME_TIME_PARSING_HPP___ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/tokenizer.hpp" +#include "boost/lexical_cast.hpp" +#include "boost/date_time/date_parsing.hpp" +#include "boost/cstdint.hpp" +#include + +namespace boost { +namespace date_time { + + //! computes exponential math like 2^8 => 256, only works with positive integers + //Not general purpose, but needed b/c std::pow is not available + //everywehere. Hasn't been tested with negatives and zeros + template + inline + int_type power(int_type base, int_type exponent) + { + int_type result = 1; + for(int i = 0; i < exponent; ++i){ + result *= base; + } + return result; + } + + //! Creates a time_duration object from a delimited string + /*! Expected format for string is "[-]h[h][:mm][:ss][.fff]". + * If the number of fractional digits provided is greater than the + * precision of the time duration type then the extra digits are + * truncated. + * + * A negative duration will be created if the first character in + * string is a '-', all other '-' will be treated as delimiters. + * Accepted delimiters are "-:,.". + */ + template + inline + time_duration + str_from_delimited_time_duration(const std::basic_string& s) + { + unsigned short min=0, sec =0; + int hour =0; + bool is_neg = (s.at(0) == '-'); + boost::int64_t fs=0; + int pos = 0; + + typedef typename std::basic_string::traits_type traits_type; + typedef boost::char_separator char_separator_type; + typedef boost::tokenizer::const_iterator, + std::basic_string > tokenizer; + typedef typename boost::tokenizer::const_iterator, + typename std::basic_string >::iterator tokenizer_iterator; + + char_type sep_chars[5] = {'-',':',',','.'}; + char_separator_type sep(sep_chars); + tokenizer tok(s,sep); + for(tokenizer_iterator beg=tok.begin(); beg!=tok.end();++beg){ + switch(pos) { + case 0: { + hour = boost::lexical_cast(*beg); + break; + } + case 1: { + min = boost::lexical_cast(*beg); + break; + } + case 2: { + sec = boost::lexical_cast(*beg); + break; + }; + case 3: { + int digits = static_cast(beg->length()); + //Works around a bug in MSVC 6 library that does not support + //operator>> thus meaning lexical_cast will fail to compile. +#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) + // msvc wouldn't compile 'time_duration::num_fractional_digits()' + // (required template argument list) as a workaround a temp + // time_duration object was used + time_duration td(hour,min,sec,fs); + int precision = td.num_fractional_digits(); + // _atoi64 is an MS specific function + if(digits >= precision) { + // drop excess digits + fs = _atoi64(beg->substr(0, precision).c_str()); + } + else { + fs = _atoi64(beg->c_str()); + } +#else + int precision = time_duration::num_fractional_digits(); + if(digits >= precision) { + // drop excess digits + fs = boost::lexical_cast(beg->substr(0, precision)); + } + else { + fs = boost::lexical_cast(*beg); + } +#endif + if(digits < precision){ + // trailing zeros get dropped from the string, + // "1:01:01.1" would yield .000001 instead of .100000 + // the power() compensates for the missing decimal places + fs *= power(10, precision - digits); + } + + break; + } + }//switch + pos++; + } + if(is_neg) { + return -time_duration(hour, min, sec, fs); + } + else { + return time_duration(hour, min, sec, fs); + } + } + + //! Creates a time_duration object from a delimited string + /*! Expected format for string is "[-]h[h][:mm][:ss][.fff]". + * If the number of fractional digits provided is greater than the + * precision of the time duration type then the extra digits are + * truncated. + * + * A negative duration will be created if the first character in + * string is a '-', all other '-' will be treated as delimiters. + * Accepted delimiters are "-:,.". + */ + template + inline + time_duration + parse_delimited_time_duration(const std::string& s) + { + return str_from_delimited_time_duration(s); + } + + //! Utility function to split appart string + inline + bool + split(const std::string& s, + char sep, + std::string& first, + std::string& second) + { + int sep_pos = static_cast(s.find(sep)); + first = s.substr(0,sep_pos); + second = s.substr(sep_pos+1); + return true; + } + + + template + inline + time_type + parse_delimited_time(const std::string& s, char sep) + { + typedef typename time_type::time_duration_type time_duration; + typedef typename time_type::date_type date_type; + + //split date/time on a unique delimiter char such as ' ' or 'T' + std::string date_string, tod_string; + split(s, sep, date_string, tod_string); + //call parse_date with first string + date_type d = parse_date(date_string); + //call parse_time_duration with remaining string + time_duration td = parse_delimited_time_duration(tod_string); + //construct a time + return time_type(d, td); + + } + + //! Parse time duration part of an iso time of form: [-]hhmmss[.fff...] (eg: 120259.123 is 12 hours, 2 min, 59 seconds, 123000 microseconds) + template + inline + time_duration + parse_undelimited_time_duration(const std::string& s) + { + int precision = 0; + { + // msvc wouldn't compile 'time_duration::num_fractional_digits()' + // (required template argument list) as a workaround, a temp + // time_duration object was used + time_duration tmp(0,0,0,1); + precision = tmp.num_fractional_digits(); + } + // 'precision+1' is so we grab all digits, plus the decimal + int offsets[] = {2,2,2, precision+1}; + int pos = 0, sign = 0; + int hours = 0; + short min=0, sec=0; + boost::int64_t fs=0; + // increment one position if the string was "signed" + if(s.at(sign) == '-') + { + ++sign; + } + // stlport choked when passing s.substr() to tokenizer + // using a new string fixed the error + std::string remain = s.substr(sign); + /* We do not want the offset_separator to wrap the offsets, we + * will never want to process more than: + * 2 char, 2 char, 2 char, frac_sec length. + * We *do* want the offset_separator to give us a partial for the + * last characters if there were not enough provided in the input string. */ + bool wrap_off = false; + bool ret_part = true; + boost::offset_separator osf(offsets, offsets+4, wrap_off, ret_part); + typedef boost::tokenizer::const_iterator, + std::basic_string > tokenizer; + typedef boost::tokenizer::const_iterator, + std::basic_string >::iterator tokenizer_iterator; + tokenizer tok(remain, osf); + for(tokenizer_iterator ti=tok.begin(); ti!=tok.end();++ti){ + switch(pos) { + case 0: + { + hours = boost::lexical_cast(*ti); + break; + } + case 1: + { + min = boost::lexical_cast(*ti); + break; + } + case 2: + { + sec = boost::lexical_cast(*ti); + break; + } + case 3: + { + std::string char_digits(ti->substr(1)); // digits w/no decimal + int digits = static_cast(char_digits.length()); + + //Works around a bug in MSVC 6 library that does not support + //operator>> thus meaning lexical_cast will fail to compile. +#if (defined(BOOST_MSVC) && (_MSC_VER <= 1200)) // 1200 == VC++ 6.0 + // _atoi64 is an MS specific function + if(digits >= precision) { + // drop excess digits + fs = _atoi64(char_digits.substr(0, precision).c_str()); + } + else if(digits == 0) { + fs = 0; // just in case _atoi64 doesn't like an empty string + } + else { + fs = _atoi64(char_digits.c_str()); + } +#else + if(digits >= precision) { + // drop excess digits + fs = boost::lexical_cast(char_digits.substr(0, precision)); + } + else if(digits == 0) { + fs = 0; // lexical_cast doesn't like empty strings + } + else { + fs = boost::lexical_cast(char_digits); + } +#endif + if(digits < precision){ + // trailing zeros get dropped from the string, + // "1:01:01.1" would yield .000001 instead of .100000 + // the power() compensates for the missing decimal places + fs *= power(10, precision - digits); + } + + break; + } + }; + pos++; + } + if(sign) { + return -time_duration(hours, min, sec, fs); + } + else { + return time_duration(hours, min, sec, fs); + } + } + + //! Parse time string of form YYYYMMDDThhmmss where T is delimeter between date and time + template + inline + time_type + parse_iso_time(const std::string& s, char sep) + { + typedef typename time_type::time_duration_type time_duration; + typedef typename time_type::date_type date_type; + + //split date/time on a unique delimiter char such as ' ' or 'T' + std::string date_string, tod_string; + split(s, sep, date_string, tod_string); + //call parse_date with first string + date_type d = parse_undelimited_date(date_string); + //call parse_time_duration with remaining string + time_duration td = parse_undelimited_time_duration(tod_string); + //construct a time + return time_type(d, td); + } + + + +} }//namespace date_time + + + + +#endif diff --git a/win32/include/boost/date_time/time_resolution_traits.hpp b/win32/include/boost/date_time/time_resolution_traits.hpp new file mode 100755 index 000000000..6e72543f1 --- /dev/null +++ b/win32/include/boost/date_time/time_resolution_traits.hpp @@ -0,0 +1,140 @@ +#ifndef DATE_TIME_TIME_RESOLUTION_TRAITS_HPP +#define DATE_TIME_TIME_RESOLUTION_TRAITS_HPP + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include "boost/date_time/time_defs.hpp" +#include "boost/date_time/int_adapter.hpp" +#include "boost/cstdint.hpp" + +namespace boost { +namespace date_time { + + //! Simple function to calculate absolute value of a numeric type + template + // JDG [7/6/02 made a template], + // moved here from time_duration.hpp 2003-Sept-4. + inline T absolute_value(T x) + { + return x < 0 ? -x : x; + } + + //! traits struct for time_resolution_traits implementation type + struct time_resolution_traits_bi32_impl { + typedef boost::int32_t int_type; + typedef boost::int32_t impl_type; + static int_type as_number(impl_type i){ return i;} + //! Used to determine if implemented type is int_adapter or int + static bool is_adapted() { return false;} + }; + //! traits struct for time_resolution_traits implementation type + struct time_resolution_traits_adapted32_impl { + typedef boost::int32_t int_type; + typedef boost::date_time::int_adapter impl_type; + static int_type as_number(impl_type i){ return i.as_number();} + //! Used to determine if implemented type is int_adapter or int + static bool is_adapted() { return true;} + }; + //! traits struct for time_resolution_traits implementation type + struct time_resolution_traits_bi64_impl { + typedef boost::int64_t int_type; + typedef boost::int64_t impl_type; + static int_type as_number(impl_type i){ return i;} + //! Used to determine if implemented type is int_adapter or int + static bool is_adapted() { return false;} + }; + //! traits struct for time_resolution_traits implementation type + struct time_resolution_traits_adapted64_impl { + typedef boost::int64_t int_type; + typedef boost::date_time::int_adapter impl_type; + static int_type as_number(impl_type i){ return i.as_number();} + //! Used to determine if implemented type is int_adapter or int + static bool is_adapted() { return true;} + }; + + template + class time_resolution_traits { + public: + typedef typename frac_sec_type::int_type fractional_seconds_type; + typedef typename frac_sec_type::int_type tick_type; + typedef typename frac_sec_type::impl_type impl_type; + typedef v_type day_type; + typedef v_type hour_type; + typedef v_type min_type; + typedef v_type sec_type; + + // bring in function from frac_sec_type traits structs + static typename frac_sec_type::int_type as_number(typename frac_sec_type::impl_type i) + { + return frac_sec_type::as_number(i); + } + static bool is_adapted() + { + return frac_sec_type::is_adapted(); + } + + //Would like this to be frac_sec_type, but some compilers complain + BOOST_STATIC_CONSTANT(int, ticks_per_second = resolution_adjust); + // static const boost::int32_t ticks_per_second = resolution_adjust; + + static time_resolutions resolution() + { + return res; + } + static unsigned short num_fractional_digits() + { + return frac_digits; + } + static fractional_seconds_type res_adjust() + { + return resolution_adjust; + } + //! Any negative argument results in a negative tick_count + static tick_type to_tick_count(hour_type hours, + min_type minutes, + sec_type seconds, + fractional_seconds_type fs) + { + if(hours < 0 || minutes < 0 || seconds < 0 || fs < 0) + { + hours = absolute_value(hours); + minutes = absolute_value(minutes); + seconds = absolute_value(seconds); + fs = absolute_value(fs); + return (((((fractional_seconds_type(hours)*3600) + + (fractional_seconds_type(minutes)*60) + + seconds)*res_adjust()) + fs) * -1); + } + + return (((fractional_seconds_type(hours)*3600) + + (fractional_seconds_type(minutes)*60) + + seconds)*res_adjust()) + fs; + } + + }; + + typedef time_resolution_traits milli_res; + typedef time_resolution_traits micro_res; + typedef time_resolution_traits nano_res; + + +} } //namespace date_time + + + +#endif diff --git a/win32/include/boost/date_time/time_system_counted.hpp b/win32/include/boost/date_time/time_system_counted.hpp new file mode 100755 index 000000000..41a34c75e --- /dev/null +++ b/win32/include/boost/date_time/time_system_counted.hpp @@ -0,0 +1,254 @@ +#ifndef DATE_TIME_TIME_SYSTEM_COUNTED_HPP +#define DATE_TIME_TIME_SYSTEM_COUNTED_HPP + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + + +#include "boost/date_time/time_defs.hpp" +#include + + +namespace boost { +namespace date_time { + + //! Time representation that uses a single integer count + template + struct counted_time_rep + { + typedef typename config::int_type int_type; + typedef typename config::date_type date_type; + typedef typename config::impl_type impl_type; + typedef typename date_type::duration_type date_duration_type; + typedef typename date_type::calendar_type calendar_type; + typedef typename date_type::ymd_type ymd_type; + typedef typename config::time_duration_type time_duration_type; + typedef typename config::resolution_traits resolution_traits; + + counted_time_rep(const date_type& d, const time_duration_type& time_of_day) + : time_count_(1) + { + if(d.is_infinity() || d.is_not_a_date() || time_of_day.is_special()) { + time_count_ = time_of_day.get_rep() + d.day_count(); + //std::cout << time_count_ << std::endl; + } + else { + time_count_ = (d.day_number() * frac_sec_per_day()) + time_of_day.ticks(); + } + } + explicit counted_time_rep(int_type count) : + time_count_(count) + {} + explicit counted_time_rep(impl_type count) : + time_count_(count) + {} + date_type date() const + { + if(time_count_.is_special()) { + return date_type(time_count_.as_special()); + } + else { + typename calendar_type::date_int_type dc = day_count(); + //std::cout << "time_rep here:" << dc << std::endl; + ymd_type ymd = calendar_type::from_day_number(dc); + return date_type(ymd); + } + } + //int_type day_count() const + unsigned long day_count() const + { + /* resolution_traits::as_number returns a boost::int64_t & + * frac_sec_per_day is also a boost::int64_t so, naturally, + * the division operation returns a boost::int64_t. + * The static_cast to an unsigned long is ok (results in no data loss) + * because frac_sec_per_day is either the number of + * microseconds per day, or the number of nanoseconds per day. + * Worst case scenario: resolution_traits::as_number returns the + * maximum value an int64_t can hold and frac_sec_per_day + * is microseconds per day (lowest possible value). + * The division operation will then return a value of 106751991 - + * easily fitting in an unsigned long. + */ + return static_cast(resolution_traits::as_number(time_count_) / frac_sec_per_day()); + } + int_type time_count() const + { + return resolution_traits::as_number(time_count_); + } + int_type tod() const + { + return resolution_traits::as_number(time_count_) % frac_sec_per_day(); + } + static int_type frac_sec_per_day() + { + int_type seconds_per_day = 60*60*24; + int_type fractional_sec_per_sec(resolution_traits::res_adjust()); + return seconds_per_day*fractional_sec_per_sec; + } + bool is_pos_infinity()const + { + return impl_type::is_pos_inf(time_count_.as_number()); + } + bool is_neg_infinity()const + { + return impl_type::is_neg_inf(time_count_.as_number()); + } + bool is_not_a_date_time()const + { + return impl_type::is_not_a_number(time_count_.as_number()); + } + bool is_special()const + { + return time_count_.is_special(); + } + impl_type get_rep()const + { + return time_count_; + } + private: + impl_type time_count_; + }; + + //! An unadjusted time system implementation. + template + class counted_time_system + { + public: + typedef time_rep time_rep_type; + typedef typename time_rep_type::impl_type impl_type; + typedef typename time_rep_type::time_duration_type time_duration_type; + typedef typename time_duration_type::fractional_seconds_type fractional_seconds_type; + typedef typename time_rep_type::date_type date_type; + typedef typename time_rep_type::date_duration_type date_duration_type; + + + template static void unused_var(const T&) {} + + static time_rep_type get_time_rep(const date_type& day, + const time_duration_type& tod, + date_time::dst_flags dst=not_dst) + { + unused_var(dst); + return time_rep_type(day, tod); + } + + static time_rep_type get_time_rep(special_values sv) + { + switch (sv) { + case not_a_date_time: + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + case pos_infin: + return time_rep_type(date_type(pos_infin), + time_duration_type(pos_infin)); + case neg_infin: + return time_rep_type(date_type(neg_infin), + time_duration_type(neg_infin)); + case max_date_time: { + time_duration_type td = time_duration_type(24,0,0,0) - time_duration_type(0,0,0,1); + return time_rep_type(date_type(max_date_time), td); + } + case min_date_time: + return time_rep_type(date_type(min_date_time), time_duration_type(0,0,0,0)); + + default: + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + + } + + } + + static date_type get_date(const time_rep_type& val) + { + return val.date(); + } + static time_duration_type get_time_of_day(const time_rep_type& val) + { + if(val.is_special()) { + return time_duration_type(val.get_rep().as_special()); + } + else{ + return time_duration_type(0,0,0,val.tod()); + } + } + static std::string zone_name(const time_rep_type&) + { + return ""; + } + static bool is_equal(const time_rep_type& lhs, const time_rep_type& rhs) + { + return (lhs.time_count() == rhs.time_count()); + } + static bool is_less(const time_rep_type& lhs, const time_rep_type& rhs) + { + return (lhs.time_count() < rhs.time_count()); + } + static time_rep_type add_days(const time_rep_type& base, + const date_duration_type& dd) + { + if(base.is_special() || dd.is_special()) { + return(time_rep_type(base.get_rep() + dd.get_rep())); + } + else { + return time_rep_type(base.time_count() + (dd.days() * time_rep_type::frac_sec_per_day())); + } + } + static time_rep_type subtract_days(const time_rep_type& base, + const date_duration_type& dd) + { + if(base.is_special() || dd.is_special()) { + return(time_rep_type(base.get_rep() - dd.get_rep())); + } + else{ + return time_rep_type(base.time_count() - (dd.days() * time_rep_type::frac_sec_per_day())); + } + } + static time_rep_type subtract_time_duration(const time_rep_type& base, + const time_duration_type& td) + { + if(base.is_special() || td.is_special()) { + return(time_rep_type(base.get_rep() - td.get_rep())); + } + else { + return time_rep_type(base.time_count() - td.ticks()); + } + } + static time_rep_type add_time_duration(const time_rep_type& base, + time_duration_type td) + { + if(base.is_special() || td.is_special()) { + return(time_rep_type(base.get_rep() + td.get_rep())); + } + else { + return time_rep_type(base.time_count() + td.ticks()); + } + } + static time_duration_type subtract_times(const time_rep_type& lhs, + const time_rep_type& rhs) + { + if(lhs.is_special() || rhs.is_special()) { + return(time_duration_type( + impl_type::to_special((lhs.get_rep() - rhs.get_rep()).as_number()))); + } + else { + fractional_seconds_type fs = lhs.time_count() - rhs.time_count(); + return time_duration_type(0,0,0,fs); + } + } + + }; + + +} } //namespace date_time + + + +#endif + diff --git a/win32/include/boost/date_time/time_system_split.hpp b/win32/include/boost/date_time/time_system_split.hpp new file mode 100755 index 000000000..608c7ba84 --- /dev/null +++ b/win32/include/boost/date_time/time_system_split.hpp @@ -0,0 +1,213 @@ +#ifndef DATE_TIME_TIME_SYSTEM_SPLIT_HPP +#define DATE_TIME_TIME_SYSTEM_SPLIT_HPP + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include +#include "boost/date_time/compiler_config.hpp" +#include "boost/date_time/special_defs.hpp" + +namespace boost { +namespace date_time { + + //! An unadjusted time system implementation. +#if (defined(BOOST_DATE_TIME_NO_MEMBER_INIT)) + template +#else + template +#endif + class split_timedate_system + { + public: + typedef typename config::time_rep_type time_rep_type; + typedef typename config::date_type date_type; + typedef typename config::time_duration_type time_duration_type; + typedef typename config::date_duration_type date_duration_type; + typedef typename config::int_type int_type; + typedef typename config::resolution_traits resolution_traits; + + //86400 is number of seconds in a day... +#if (defined(BOOST_DATE_TIME_NO_MEMBER_INIT)) + typedef date_time::wrapping_int wrap_int_type; +#else + private: + BOOST_STATIC_CONSTANT(int_type, ticks_per_day = INT64_C(86400) * config::tick_per_second); + public: +# if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0X581) ) + typedef date_time::wrapping_int< split_timedate_system::int_type, split_timedate_system::ticks_per_day> wrap_int_type; +# else + typedef date_time::wrapping_int wrap_int_type; +#endif +#endif + + static time_rep_type get_time_rep(special_values sv) + { + switch (sv) { + case not_a_date_time: + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + case pos_infin: + return time_rep_type(date_type(pos_infin), + time_duration_type(pos_infin)); + case neg_infin: + return time_rep_type(date_type(neg_infin), + time_duration_type(neg_infin)); + case max_date_time: { + time_duration_type td = time_duration_type(24,0,0,0) - time_duration_type(0,0,0,1); + return time_rep_type(date_type(max_date_time), td); + } + case min_date_time: + return time_rep_type(date_type(min_date_time), time_duration_type(0,0,0,0)); + + default: + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + + } + + } + + static time_rep_type get_time_rep(const date_type& day, + const time_duration_type& tod, + date_time::dst_flags dst=not_dst) + { + if(day.is_special() || tod.is_special()) { + if(day.is_not_a_date() || tod.is_not_a_date_time()) { + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + } + else if(day.is_pos_infinity()) { + if(tod.is_neg_infinity()) { + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + } + else { + return time_rep_type(day, time_duration_type(pos_infin)); + } + } + else if(day.is_neg_infinity()) { + if(tod.is_pos_infinity()) { + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + } + else { + return time_rep_type(day, time_duration_type(neg_infin)); + } + } + else if(tod.is_pos_infinity()) { + if(day.is_neg_infinity()) { + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + } + else { + return time_rep_type(date_type(pos_infin), tod); + } + } + else if(tod.is_neg_infinity()) { + if(day.is_pos_infinity()) { + return time_rep_type(date_type(not_a_date_time), + time_duration_type(not_a_date_time)); + } + else { + return time_rep_type(date_type(neg_infin), tod); + } + } + } + return time_rep_type(day, tod); + } + static date_type get_date(const time_rep_type& val) + { + return date_type(val.day); + } + static time_duration_type get_time_of_day(const time_rep_type& val) + { + return time_duration_type(val.time_of_day); + } + static std::string zone_name(const time_rep_type&) + { + return ""; + } + static bool is_equal(const time_rep_type& lhs, const time_rep_type& rhs) + { + return ((lhs.day == rhs.day) && (lhs.time_of_day == rhs.time_of_day)); + } + static bool is_less(const time_rep_type& lhs, const time_rep_type& rhs) + { + if (lhs.day < rhs.day) return true; + if (lhs.day > rhs.day) return false; + return (lhs.time_of_day < rhs.time_of_day); + } + static time_rep_type add_days(const time_rep_type& base, + const date_duration_type& dd) + { + return time_rep_type(base.day+dd, base.time_of_day); + } + static time_rep_type subtract_days(const time_rep_type& base, + const date_duration_type& dd) + { + return split_timedate_system::get_time_rep(base.day-dd, base.time_of_day); + } + static time_rep_type subtract_time_duration(const time_rep_type& base, + const time_duration_type& td) + { + if(base.day.is_special() || td.is_special()) + { + return split_timedate_system::get_time_rep(base.day, -td); + } + if (td.is_negative()) { + time_duration_type td1 = td.invert_sign(); + return add_time_duration(base,td1); + } + + //std::cout << td.ticks() << std::endl; + wrap_int_type day_offset(base.time_of_day.ticks()); + date_duration_type day_overflow(static_cast(day_offset.subtract(td.ticks()))); +// std::cout << "sub: " << base.time_of_day.ticks() << "|" +// << day_offset.as_int() << "|" +// << day_overflow.days() << std::endl; + return time_rep_type(base.day-day_overflow, + time_duration_type(0,0,0,day_offset.as_int())); + } + static time_rep_type add_time_duration(const time_rep_type& base, + time_duration_type td) + { + if(base.day.is_special() || td.is_special()) { + return split_timedate_system::get_time_rep(base.day, td); + } + if (td.is_negative()) { + time_duration_type td1 = td.invert_sign(); + return subtract_time_duration(base,td1); + } + wrap_int_type day_offset(base.time_of_day.ticks()); + typename date_duration_type::duration_rep_type doff = day_offset.add(td.ticks()); +// std::cout << "day overflow: " << doff << std::endl; +// std::cout << "ticks: " << td.ticks() << std::endl; + date_duration_type day_overflow(doff); +// std::cout << "base: " << to_simple_string(base.day) << std::endl; +// std::cout << "overflow " << day_overflow.days() << std::endl; + return time_rep_type(base.day+day_overflow, + time_duration_type(0,0,0,day_offset.as_int())); + } + static time_duration_type subtract_times(const time_rep_type& lhs, + const time_rep_type& rhs) + { + date_duration_type dd = lhs.day - rhs.day; + time_duration_type td(dd.days()*24,0,0); //days * 24 hours + time_duration_type td2 = lhs.time_of_day - rhs.time_of_day; + return td+td2; + // return time_rep_type(base.day-dd, base.time_of_day); + } + + }; + +} } //namespace date_time + + +#endif diff --git a/win32/include/boost/date_time/time_zone_base.hpp b/win32/include/boost/date_time/time_zone_base.hpp new file mode 100755 index 000000000..801feed1f --- /dev/null +++ b/win32/include/boost/date_time/time_zone_base.hpp @@ -0,0 +1,99 @@ +#ifndef _DATE_TIME_TIME_ZONE_BASE__ +#define _DATE_TIME_TIME_ZONE_BASE__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +#include +#include + +namespace boost { +namespace date_time { + + + + //! Interface class for dynamic time zones. + /*! This class represents the base interface for all timezone + * representations. Subclasses may provide different systems + * for identifying a particular zone. For example some may + * provide a geographical based zone construction while others + * may specify the offset from GMT. Another possible implementation + * would be to convert from POSIX timezone strings. Regardless of + * the construction technique, this is the interface that these + * time zone types must provide. + * + * Note that this class is intended to be used as a shared + * resource (hence the derivation from boost::counted_base. + */ + template + class time_zone_base { + public: + typedef CharT char_type; + typedef std::basic_string string_type; + typedef std::basic_ostringstream stringstream_type; + typedef typename time_type::date_type::year_type year_type; + typedef typename time_type::time_duration_type time_duration_type; + + time_zone_base() {}; + virtual ~time_zone_base() {}; + //!String for the timezone when in daylight savings (eg: EDT) + virtual string_type dst_zone_abbrev() const=0; + //!String for the zone when not in daylight savings (eg: EST) + virtual string_type std_zone_abbrev() const=0; + //!String for the timezone when in daylight savings (eg: Eastern Daylight Time) + virtual string_type dst_zone_name() const=0; + //!String for the zone when not in daylight savings (eg: Eastern Standard Time) + virtual string_type std_zone_name() const=0; + //! True if zone uses daylight savings adjustments otherwise false + virtual bool has_dst() const=0; + //! Local time that DST starts -- undefined if has_dst is false + virtual time_type dst_local_start_time(year_type y) const=0; + //! Local time that DST ends -- undefined if has_dst is false + virtual time_type dst_local_end_time(year_type y) const=0; + //! Base offset from UTC for zone (eg: -07:30:00) + virtual time_duration_type base_utc_offset() const=0; + //! Adjustment forward or back made while DST is in effect + virtual time_duration_type dst_offset() const=0; + //! Returns a POSIX time_zone string for this object + virtual string_type to_posix_string() const =0; + + private: + + }; + + + //! Structure which holds the time offsets associated with daylight savings time + /*! + *@param time_duration_type A type used to represent the offset + */ + template + class dst_adjustment_offsets + { + public: + dst_adjustment_offsets(const time_duration_type& dst_adjust, + const time_duration_type& dst_start_offset, + const time_duration_type& dst_end_offset) : + dst_adjust_(dst_adjust), + dst_start_offset_(dst_start_offset), + dst_end_offset_(dst_end_offset) + {} + + //! Amount DST adjusts the clock eg: plus one hour + time_duration_type dst_adjust_; + //! Time past midnight on start transition day that dst starts + time_duration_type dst_start_offset_; + //! Time past midnight on end transition day that dst ends + time_duration_type dst_end_offset_; + }; + + +} } //namespace date_time + + + +#endif diff --git a/win32/include/boost/date_time/time_zone_names.hpp b/win32/include/boost/date_time/time_zone_names.hpp new file mode 100755 index 000000000..07f83b42f --- /dev/null +++ b/win32/include/boost/date_time/time_zone_names.hpp @@ -0,0 +1,98 @@ +#ifndef DATE_TIME_TIME_ZONE_NAMES_HPP__ +#define DATE_TIME_TIME_ZONE_NAMES_HPP__ + +/* Copyright (c) 2002-2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include + +namespace boost { +namespace date_time { + + template + struct default_zone_names { + public: + typedef CharT char_type; + static const char_type standard_name[9]; + static const char_type standard_abbrev[11]; + static const char_type non_dst_identifier[7]; + }; + template + const typename default_zone_names::char_type + default_zone_names::standard_name[9] = + {'s','t','d','_','n','a','m','e'}; + + template + const typename default_zone_names::char_type + default_zone_names::standard_abbrev[11] = + {'s','t','d','_','a','b','b','r','e','v'}; + + template + const typename default_zone_names::char_type + default_zone_names::non_dst_identifier[7] = + {'n','o','-','d','s','t'}; + + //! Base type that holds various string names for timezone output. + /*! Class that holds various types of strings used for timezones. + * For example, for the western United States there is the full + * name: Pacific Standard Time and the abbreviated name: PST. + * During daylight savings there are additional names: + * Pacific Daylight Time and PDT. + *@parm CharT Allows class to support different character types + */ + template + class time_zone_names_base + { + public: + typedef std::basic_string string_type; + time_zone_names_base() : + std_zone_name_(default_zone_names::standard_name), + std_zone_abbrev_(default_zone_names::standard_abbrev), + dst_zone_name_(default_zone_names::non_dst_identifier), + dst_zone_abbrev_(default_zone_names::non_dst_identifier) + {} + time_zone_names_base(const string_type& std_zone_name_str, + const string_type& std_zone_abbrev_str, + const string_type& dst_zone_name_str, + const string_type& dst_zone_abbrev_str) : + std_zone_name_(std_zone_name_str), + std_zone_abbrev_(std_zone_abbrev_str), + dst_zone_name_(dst_zone_name_str), + dst_zone_abbrev_(dst_zone_abbrev_str) + {} + string_type dst_zone_abbrev() const + { + return dst_zone_abbrev_; + } + string_type std_zone_abbrev() const + { + return std_zone_abbrev_; + } + string_type dst_zone_name() const + { + return dst_zone_name_; + } + string_type std_zone_name() const + { + return std_zone_name_; + } + private: + string_type std_zone_name_; + string_type std_zone_abbrev_; + string_type dst_zone_name_; + string_type dst_zone_abbrev_; + + }; + + //! Specialization of timezone names for standard char. + //typedef time_zone_names_base time_zone_names; + +} } //namespace + + +#endif diff --git a/win32/include/boost/date_time/tz_db_base.hpp b/win32/include/boost/date_time/tz_db_base.hpp new file mode 100755 index 000000000..ae706890d --- /dev/null +++ b/win32/include/boost/date_time/tz_db_base.hpp @@ -0,0 +1,376 @@ +#ifndef DATE_TIME_TZ_DB_BASE_HPP__ +#define DATE_TIME_TZ_DB_BASE_HPP__ + +/* Copyright (c) 2003-2005 CrystalClear Software, Inc. + * Subject to the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +#include "boost/shared_ptr.hpp" +#include "boost/date_time/time_zone_names.hpp" +#include "boost/date_time/time_zone_base.hpp" +#include "boost/date_time/time_parsing.hpp" +#include "boost/tokenizer.hpp" +#include +#include +#include +#include +#include +#include + +namespace boost { + namespace date_time { + + //! Exception thrown when tz database cannot locate requested data file + class data_not_accessible : public std::logic_error + { + public: + data_not_accessible() : + std::logic_error(std::string("Unable to locate or access the required datafile.")) + {} + data_not_accessible(const std::string& filespec) : + std::logic_error(std::string("Unable to locate or access the required datafile. Filespec: " + filespec)) + {} + }; + + //! Exception thrown when tz database locates incorrect field structure in data file + class bad_field_count : public std::out_of_range + { + public: + bad_field_count(const std::string& s) : + std::out_of_range(s) + {} + }; + + //! Creates a database of time_zones from csv datafile + /*! The csv file containing the zone_specs used by the + * tz_db_base is intended to be customized by the + * library user. When customizing this file (or creating your own) the + * file must follow a specific format. + * + * This first line is expected to contain column headings and is therefore + * not processed by the tz_db_base. + * + * Each record (line) must have eleven fields. Some of those fields can + * be empty. Every field (even empty ones) must be enclosed in + * double-quotes. + * Ex: + * @code + * "America/Phoenix" <- string enclosed in quotes + * "" <- empty field + * @endcode + * + * Some fields represent a length of time. The format of these fields + * must be: + * @code + * "{+|-}hh:mm[:ss]" <- length-of-time format + * @endcode + * Where the plus or minus is mandatory and the seconds are optional. + * + * Since some time zones do not use daylight savings it is not always + * necessary for every field in a zone_spec to contain a value. All + * zone_specs must have at least ID and GMT offset. Zones that use + * daylight savings must have all fields filled except: + * STD ABBR, STD NAME, DST NAME. You should take note + * that DST ABBR is mandatory for zones that use daylight savings + * (see field descriptions for further details). + * + * ******* Fields and their description/details ********* + * + * ID: + * Contains the identifying string for the zone_spec. Any string will + * do as long as it's unique. No two ID's can be the same. + * + * STD ABBR: + * STD NAME: + * DST ABBR: + * DST NAME: + * These four are all the names and abbreviations used by the time + * zone being described. While any string will do in these fields, + * care should be taken. These fields hold the strings that will be + * used in the output of many of the local_time classes. + * Ex: + * @code + * time_zone nyc = tz_db.time_zone_from_region("America/New_York"); + * local_time ny_time(date(2004, Aug, 30), IS_DST, nyc); + * cout << ny_time.to_long_string() << endl; + * // 2004-Aug-30 00:00:00 Eastern Daylight Time + * cout << ny_time.to_short_string() << endl; + * // 2004-Aug-30 00:00:00 EDT + * @endcode + * + * NOTE: The exact format/function names may vary - see local_time + * documentation for further details. + * + * GMT offset: + * This is the number of hours added to utc to get the local time + * before any daylight savings adjustments are made. Some examples + * are: America/New_York offset -5 hours, & Africa/Cairo offset +2 hours. + * The format must follow the length-of-time format described above. + * + * DST adjustment: + * The amount of time added to gmt_offset when daylight savings is in + * effect. The format must follow the length-of-time format described + * above. + * + * DST Start Date rule: + * This is a specially formatted string that describes the day of year + * in which the transition take place. It holds three fields of it's own, + * separated by semicolons. + * The first field indicates the "nth" weekday of the month. The possible + * values are: 1 (first), 2 (second), 3 (third), 4 (fourth), 5 (fifth), + * and -1 (last). + * The second field indicates the day-of-week from 0-6 (Sun=0). + * The third field indicates the month from 1-12 (Jan=1). + * + * Examples are: "-1;5;9"="Last Friday of September", + * "2;1;3"="Second Monday of March" + * + * Start time: + * Start time is the number of hours past midnight, on the day of the + * start transition, the transition takes place. More simply put, the + * time of day the transition is made (in 24 hours format). The format + * must follow the length-of-time format described above with the + * exception that it must always be positive. + * + * DST End date rule: + * See DST Start date rule. The difference here is this is the day + * daylight savings ends (transition to STD). + * + * End time: + * Same as Start time. + */ + template + class tz_db_base { + public: + /* Having CharT as a template parameter created problems + * with posix_time::duration_from_string. Templatizing + * duration_from_string was not possible at this time, however, + * it should be possible in the future (when poor compilers get + * fixed or stop being used). + * Since this class was designed to use CharT as a parameter it + * is simply typedef'd here to ease converting in back to a + * parameter the future */ + typedef char char_type; + + typedef typename time_zone_type::base_type time_zone_base_type; + typedef typename time_zone_type::time_duration_type time_duration_type; + typedef time_zone_names_base time_zone_names; + typedef dst_adjustment_offsets dst_adjustment_offsets; + typedef std::basic_string string_type; + + //! Constructs an empty database + tz_db_base() {} + + //! Process csv data file, may throw exceptions + /*! May throw data_not_accessible, or bad_field_count exceptions */ + void load_from_file(const std::string& pathspec) + { + string_type in_str; + std::string buff; + + std::ifstream ifs(pathspec.c_str()); + if(!ifs){ + throw data_not_accessible(pathspec); + } + std::getline(ifs, buff); // first line is column headings + + while( std::getline(ifs, buff)) { + parse_string(buff); + } + } + + //! returns true if record successfully added to map + /*! Takes an id string in the form of "America/Phoenix", and a + * time_zone object for that region. The id string must be a unique + * name that does not already exist in the database. */ + bool add_record(const string_type& id, + boost::shared_ptr tz) + { + typename map_type::value_type p(id, tz); + return (m_zone_map.insert(p)).second; + } + + //! Returns a time_zone object built from the specs for the given region + /*! Returns a time_zone object built from the specs for the given + * region. If region does not exist a local_time::record_not_found + * exception will be thrown */ + boost::shared_ptr + time_zone_from_region(const string_type& region) const + { + // get the record + typename map_type::const_iterator record = m_zone_map.find(region); + if(record == m_zone_map.end()){ + return boost::shared_ptr(); //null pointer + } + return record->second; + } + + //! Returns a vector of strings holding the time zone regions in the database + std::vector region_list() const + { + typedef std::vector vector_type; + vector_type regions; + typename map_type::const_iterator itr = m_zone_map.begin(); + while(itr != m_zone_map.end()) { + regions.push_back(itr->first); + ++itr; + } + return regions; + } + + private: + typedef std::map > map_type; + map_type m_zone_map; + + // start and end rule are of the same type + typedef typename rule_type::start_rule::week_num week_num; + + /* TODO: mechanisms need to be put in place to handle different + * types of rule specs. parse_rules() only handles nth_kday + * rule types. */ + + //! parses rule specs for transition day rules + rule_type* parse_rules(const string_type& sr, const string_type& er) const + { + using namespace gregorian; + // start and end rule are of the same type, + // both are included here for readability + typedef typename rule_type::start_rule start_rule; + typedef typename rule_type::end_rule end_rule; + + // these are: [start|end] nth, day, month + int s_nth = 0, s_d = 0, s_m = 0; + int e_nth = 0, e_d = 0, e_m = 0; + split_rule_spec(s_nth, s_d, s_m, sr); + split_rule_spec(e_nth, e_d, e_m, er); + + typename start_rule::week_num s_wn, e_wn; + s_wn = get_week_num(s_nth); + e_wn = get_week_num(e_nth); + + + return new rule_type(start_rule(s_wn, s_d, s_m), + end_rule(e_wn, e_d, e_m)); + } + //! helper function for parse_rules() + week_num get_week_num(int nth) const + { + typedef typename rule_type::start_rule start_rule; + switch(nth){ + case 1: + return start_rule::first; + case 2: + return start_rule::second; + case 3: + return start_rule::third; + case 4: + return start_rule::fourth; + case 5: + case -1: + return start_rule::fifth; + default: + // shouldn't get here - add error handling later + break; + } + return start_rule::fifth; // silence warnings + } + + //! splits the [start|end]_date_rule string into 3 ints + void split_rule_spec(int& nth, int& d, int& m, string_type rule) const + { + typedef boost::char_separator > char_separator_type; + typedef boost::tokenizer::const_iterator, + std::basic_string > tokenizer; + typedef boost::tokenizer::const_iterator, + std::basic_string >::iterator tokenizer_iterator; + + const char_type sep_char[] = { ';', '\0'}; + char_separator_type sep(sep_char); + tokenizer tokens(rule, sep); // 3 fields + + tokenizer_iterator tok_iter = tokens.begin(); + nth = std::atoi(tok_iter->c_str()); ++tok_iter; + d = std::atoi(tok_iter->c_str()); ++tok_iter; + m = std::atoi(tok_iter->c_str()); + } + + + //! Take a line from the csv, turn it into a time_zone_type. + /*! Take a line from the csv, turn it into a time_zone_type, + * and add it to the map. Zone_specs in csv file are expected to + * have eleven fields that describe the time zone. Returns true if + * zone_spec successfully added to database */ + bool parse_string(string_type& s) + { + + std::vector result; + typedef boost::token_iterator_generator, string_type::const_iterator, string_type >::type token_iter_type; + + token_iter_type i = boost::make_token_iterator(s.begin(), s.end(),boost::escaped_list_separator()); + + token_iter_type end; + while (i != end) { + result.push_back(*i); + i++; + } + + enum db_fields { ID, STDABBR, STDNAME, DSTABBR, DSTNAME, GMTOFFSET, + DSTADJUST, START_DATE_RULE, START_TIME, END_DATE_RULE, + END_TIME, FIELD_COUNT }; + + //take a shot at fixing gcc 4.x error + const unsigned int expected_fields = static_cast(FIELD_COUNT); + if (result.size() != expected_fields) { + std::stringstream msg; + msg << "Expecting " << FIELD_COUNT << " fields, got " + << result.size() << " fields in line: " << s; + throw bad_field_count(msg.str()); + } + + // initializations + bool has_dst = true; + if(result[DSTABBR] == std::string()){ + has_dst = false; + } + + + // start building components of a time_zone + time_zone_names names(result[STDNAME], result[STDABBR], + result[DSTNAME], result[DSTABBR]); + + time_duration_type utc_offset = + str_from_delimited_time_duration(result[GMTOFFSET]); + + dst_adjustment_offsets adjust(time_duration_type(0,0,0), + time_duration_type(0,0,0), + time_duration_type(0,0,0)); + + boost::shared_ptr rules; + + if(has_dst){ + adjust = dst_adjustment_offsets( + str_from_delimited_time_duration(result[DSTADJUST]), + str_from_delimited_time_duration(result[START_TIME]), + str_from_delimited_time_duration(result[END_TIME]) + ); + + rules = + boost::shared_ptr(parse_rules(result[START_DATE_RULE], + result[END_DATE_RULE])); + } + string_type id(result[ID]); + boost::shared_ptr zone(new time_zone_type(names, utc_offset, adjust, rules)); + return (add_record(id, zone)); + + } + + }; + +} } // namespace + +#endif // DATE_TIME_TZ_DB_BASE_HPP__ diff --git a/win32/include/boost/date_time/wrapping_int.hpp b/win32/include/boost/date_time/wrapping_int.hpp new file mode 100755 index 000000000..11be318e5 --- /dev/null +++ b/win32/include/boost/date_time/wrapping_int.hpp @@ -0,0 +1,163 @@ +#ifndef _DATE_TIME_WRAPPING_INT_HPP__ +#define _DATE_TIME_WRAPPING_INT_HPP__ + +/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland, Bart Garst + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + + +namespace boost { +namespace date_time { + +//! A wrapping integer used to support time durations (WARNING: only instantiate with a signed type) +/*! In composite date and time types this type is used to + * wrap at the day boundary. + * Ex: + * A wrapping_int will roll over after nine, and + * roll under below zero. This gives a range of [0,9] + * + * NOTE: it is strongly recommended that wrapping_int2 be used + * instead of wrapping_int as wrapping_int is to be depricated + * at some point soon. + * + * Also Note that warnings will occur if instantiated with an + * unsigned type. Only a signed type should be used! + */ +template +class wrapping_int { +public: + typedef int_type_ int_type; + //typedef overflow_type_ overflow_type; + static int_type wrap_value() {return wrap_val;} + //!Add, return true if wrapped + wrapping_int(int_type v) : value_(v) {}; + //! Explicit converion method + int_type as_int() const {return value_;} + operator int_type() const {return value_;} + //!Add, return number of wraps performed + /*! The sign of the returned value will indicate which direction the + * wraps went. Ex: add a negative number and wrapping under could occur, + * this would be indicated by a negative return value. If wrapping over + * took place, a positive value would be returned */ + int_type add(int_type v) + { + int_type remainder = static_cast(v % (wrap_val)); + int_type overflow = static_cast(v / (wrap_val)); + value_ = static_cast(value_ + remainder); + return calculate_wrap(overflow); + } + //! Subtract will return '+d' if wrapping under took place ('d' is the number of wraps) + /*! The sign of the returned value will indicate which direction the + * wraps went (positive indicates wrap under, negative indicates wrap over). + * Ex: subtract a negative number and wrapping over could + * occur, this would be indicated by a negative return value. If + * wrapping under took place, a positive value would be returned. */ + int_type subtract(int_type v) + { + int_type remainder = static_cast(v % (wrap_val)); + int_type underflow = static_cast(-(v / (wrap_val))); + value_ = static_cast(value_ - remainder); + return calculate_wrap(underflow) * -1; + } +private: + int_type value_; + + int_type calculate_wrap(int_type wrap) + { + if ((value_) >= wrap_val) + { + wrap++; + value_ -= (wrap_val); + } + else if(value_ < 0) + { + wrap--; + value_ += (wrap_val); + } + return wrap; + } + +}; + + +//! A wrapping integer used to wrap around at the top (WARNING: only instantiate with a signed type) +/*! Bad name, quick impl to fix a bug -- fix later!! + * This allows the wrap to restart at a value other than 0. + */ +template +class wrapping_int2 { +public: + typedef int_type_ int_type; + static int_type wrap_value() {return wrap_max;} + static int_type min_value() {return wrap_min;} + /*! If initializing value is out of range of [wrap_min, wrap_max], + * value will be initialized to closest of min or max */ + wrapping_int2(int_type v) : value_(v) { + if(value_ < wrap_min) + { + value_ = wrap_min; + } + if(value_ > wrap_max) + { + value_ = wrap_max; + } + } + //! Explicit converion method + int_type as_int() const {return value_;} + operator int_type() const {return value_;} + //!Add, return number of wraps performed + /*! The sign of the returned value will indicate which direction the + * wraps went. Ex: add a negative number and wrapping under could occur, + * this would be indicated by a negative return value. If wrapping over + * took place, a positive value would be returned */ + int_type add(int_type v) + { + int_type remainder = static_cast(v % (wrap_max - wrap_min + 1)); + int_type overflow = static_cast(v / (wrap_max - wrap_min + 1)); + value_ = static_cast(value_ + remainder); + return calculate_wrap(overflow); + } + //! Subtract will return '-d' if wrapping under took place ('d' is the number of wraps) + /*! The sign of the returned value will indicate which direction the + * wraps went. Ex: subtract a negative number and wrapping over could + * occur, this would be indicated by a positive return value. If + * wrapping under took place, a negative value would be returned */ + int_type subtract(int_type v) + { + int_type remainder = static_cast(v % (wrap_max - wrap_min + 1)); + int_type underflow = static_cast(-(v / (wrap_max - wrap_min + 1))); + value_ = static_cast(value_ - remainder); + return calculate_wrap(underflow); + } + +private: + int_type value_; + + int_type calculate_wrap(int_type wrap) + { + if ((value_) > wrap_max) + { + wrap++; + value_ -= (wrap_max - wrap_min + 1); + } + else if((value_) < wrap_min) + { + wrap--; + value_ += (wrap_max - wrap_min + 1); + } + return wrap; + } +}; + + + +} } //namespace date_time + + + +#endif + diff --git a/win32/include/boost/date_time/year_month_day.hpp b/win32/include/boost/date_time/year_month_day.hpp new file mode 100755 index 000000000..00cdbd46a --- /dev/null +++ b/win32/include/boost/date_time/year_month_day.hpp @@ -0,0 +1,45 @@ +#ifndef YearMonthDayBase_HPP__ +#define YearMonthDayBase_HPP__ + +/* Copyright (c) 2002,2003 CrystalClear Software, Inc. + * Use, modification and distribution is subject to the + * Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + * Author: Jeff Garland + * $Date: 2008-02-27 15:00:24 -0500 (Wed, 27 Feb 2008) $ + */ + +namespace boost { +namespace date_time { + + //! Allow rapid creation of ymd triples of different types + template + struct year_month_day_base { + year_month_day_base(YearType year, + MonthType month, + DayType day); + YearType year; + MonthType month; + DayType day; + typedef YearType year_type; + typedef MonthType month_type; + typedef DayType day_type; + }; + + + //! A basic constructor + template + inline + year_month_day_base::year_month_day_base(YearType y, + MonthType m, + DayType d) : + year(y), + month(m), + day(d) + {} + +} }//namespace date_time + + +#endif + diff --git a/win32/include/boost/detail/algorithm.hpp b/win32/include/boost/detail/algorithm.hpp new file mode 100755 index 000000000..6f8fcda99 --- /dev/null +++ b/win32/include/boost/detail/algorithm.hpp @@ -0,0 +1,222 @@ +// (C) Copyright Jeremy Siek 2001. +// Distributed under the Boost Software License, Version 1.0. (See accompany- +// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef BOOST_ALGORITHM_HPP +# define BOOST_ALGORITHM_HPP +# include +// Algorithms on sequences +// +// The functions in this file have not yet gone through formal +// review, and are subject to change. This is a work in progress. +// They have been checked into the detail directory because +// there are some graph algorithms that use these functions. + +#include +#include + +namespace boost { + + template + Iter1 begin(const std::pair& p) { return p.first; } + + template + Iter2 end(const std::pair& p) { return p.second; } + + template + typename boost::detail::iterator_traits::difference_type + size(const std::pair& p) { + return std::distance(p.first, p.second); + } + +#if 0 + // These seem to interfere with the std::pair overloads :( + template + typename Container::iterator + begin(Container& c) { return c.begin(); } + + template + typename Container::const_iterator + begin(const Container& c) { return c.begin(); } + + template + typename Container::iterator + end(Container& c) { return c.end(); } + + template + typename Container::const_iterator + end(const Container& c) { return c.end(); } + + template + typename Container::size_type + size(const Container& c) { return c.size(); } +#else + template + typename std::vector::iterator + begin(std::vector& c) { return c.begin(); } + + template + typename std::vector::const_iterator + begin(const std::vector& c) { return c.begin(); } + + template + typename std::vector::iterator + end(std::vector& c) { return c.end(); } + + template + typename std::vector::const_iterator + end(const std::vector& c) { return c.end(); } + + template + typename std::vector::size_type + size(const std::vector& c) { return c.size(); } +#endif + + template + void iota(ForwardIterator first, ForwardIterator last, T value) + { + for (; first != last; ++first, ++value) + *first = value; + } + template + void iota(Container& c, const T& value) + { + iota(begin(c), end(c), value); + } + + // Also do version with 2nd container? + template + OutIter copy(const Container& c, OutIter result) { + return std::copy(begin(c), end(c), result); + } + + template + bool equal(const Container1& c1, const Container2& c2) + { + if (size(c1) != size(c2)) + return false; + return std::equal(begin(c1), end(c1), begin(c2)); + } + + template + void sort(Container& c) { std::sort(begin(c), end(c)); } + + template + void sort(Container& c, const Predicate& p) { + std::sort(begin(c), end(c), p); + } + + template + void stable_sort(Container& c) { std::stable_sort(begin(c), end(c)); } + + template + void stable_sort(Container& c, const Predicate& p) { + std::stable_sort(begin(c), end(c), p); + } + + template + bool any_if(InputIterator first, InputIterator last, Predicate p) + { + return std::find_if(first, last, p) != last; + } + template + bool any_if(const Container& c, Predicate p) + { + return any_if(begin(c), end(c), p); + } + + template + bool container_contains(InputIterator first, InputIterator last, T value) + { + return std::find(first, last, value) != last; + } + template + bool container_contains(const Container& c, const T& value) + { + return container_contains(begin(c), end(c), value); + } + + template + std::size_t count(const Container& c, const T& value) + { + return std::count(begin(c), end(c), value); + } + + template + std::size_t count_if(const Container& c, Predicate p) + { + return std::count_if(begin(c), end(c), p); + } + + template + bool is_sorted(ForwardIterator first, ForwardIterator last) + { + if (first == last) + return true; + + ForwardIterator next = first; + for (++next; next != last; first = next, ++next) { + if (*next < *first) + return false; + } + + return true; + } + + template + bool is_sorted(ForwardIterator first, ForwardIterator last, + StrictWeakOrdering comp) + { + if (first == last) + return true; + + ForwardIterator next = first; + for (++next; next != last; first = next, ++next) { + if (comp(*next, *first)) + return false; + } + + return true; + } + + template + bool is_sorted(const Container& c) + { + return is_sorted(begin(c), end(c)); + } + + template + bool is_sorted(const Container& c, StrictWeakOrdering comp) + { + return is_sorted(begin(c), end(c), comp); + } + +} // namespace boost + +#endif // BOOST_ALGORITHM_HPP diff --git a/win32/include/boost/detail/allocator_utilities.hpp b/win32/include/boost/detail/allocator_utilities.hpp new file mode 100755 index 000000000..52d31eef2 --- /dev/null +++ b/win32/include/boost/detail/allocator_utilities.hpp @@ -0,0 +1,193 @@ +/* Copyright 2003-2008 Joaquin M Lopez Munoz. + * 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) + * + * See Boost website at http://www.boost.org/ + */ + +#ifndef BOOST_DETAIL_ALLOCATOR_UTILITIES_HPP +#define BOOST_DETAIL_ALLOCATOR_UTILITIES_HPP + +#include /* keep it first to prevent nasty warns in MSVC */ +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ + +namespace detail{ + +/* Allocator adaption layer. Some stdlibs provide allocators without rebind + * and template ctors. These facilities are simulated with the external + * template class rebind_to and the aid of partial_std_allocator_wrapper. + */ + +namespace allocator{ + +/* partial_std_allocator_wrapper inherits the functionality of a std + * allocator while providing a templatized ctor and other bits missing + * in some stdlib implementation or another. + */ + +template +class partial_std_allocator_wrapper:public std::allocator +{ +public: + /* Oddly enough, STLport does not define std::allocator::value_type + * when configured to work without partial template specialization. + * No harm in supplying the definition here unconditionally. + */ + + typedef Type value_type; + + partial_std_allocator_wrapper(){}; + + template + partial_std_allocator_wrapper(const partial_std_allocator_wrapper&){} + + partial_std_allocator_wrapper(const std::allocator& x): + std::allocator(x) + { + }; + +#if defined(BOOST_DINKUMWARE_STDLIB) + /* Dinkumware guys didn't provide a means to call allocate() without + * supplying a hint, in disagreement with the standard. + */ + + Type* allocate(std::size_t n,const void* hint=0) + { + std::allocator& a=*this; + return a.allocate(n,hint); + } +#endif + +}; + +/* Detects whether a given allocator belongs to a defective stdlib not + * having the required member templates. + * Note that it does not suffice to check the Boost.Config stdlib + * macros, as the user might have passed a custom, compliant allocator. + * The checks also considers partial_std_allocator_wrapper to be + * a standard defective allocator. + */ + +#if defined(BOOST_NO_STD_ALLOCATOR)&&\ + (defined(BOOST_HAS_PARTIAL_STD_ALLOCATOR)||defined(BOOST_DINKUMWARE_STDLIB)) + +template +struct is_partial_std_allocator +{ + BOOST_STATIC_CONSTANT(bool, + value= + (is_same< + std::allocator, + Allocator + >::value)|| + (is_same< + partial_std_allocator_wrapper< + BOOST_DEDUCED_TYPENAME Allocator::value_type>, + Allocator + >::value)); +}; + +#else + +template +struct is_partial_std_allocator +{ + BOOST_STATIC_CONSTANT(bool,value=false); +}; + +#endif + +/* rebind operations for defective std allocators */ + +template +struct partial_std_allocator_rebind_to +{ + typedef partial_std_allocator_wrapper type; +}; + +/* rebind operation in all other cases */ + +#if BOOST_WORKAROUND(BOOST_MSVC,<1300) +/* Workaround for a problem in MSVC with dependent template typedefs + * when doing rebinding of allocators. + * Modeled after (thanks, Aleksey!) + */ + +template +struct rebinder +{ + template struct fake_allocator:Allocator{}; + template<> struct fake_allocator + { + template struct rebind{}; + }; + + template + struct result: + fake_allocator::value>:: + template rebind + { + }; +}; +#else +template +struct rebinder +{ + template + struct result + { + typedef typename Allocator::BOOST_NESTED_TEMPLATE + rebind::other other; + }; +}; +#endif + +template +struct compliant_allocator_rebind_to +{ + typedef typename rebinder:: + BOOST_NESTED_TEMPLATE result::other type; +}; + +/* rebind front-end */ + +template +struct rebind_to: + mpl::eval_if_c< + is_partial_std_allocator::value, + partial_std_allocator_rebind_to, + compliant_allocator_rebind_to + > +{ +}; + +/* allocator-independent versions of construct and destroy */ + +template +void construct(void* p,const Type& t) +{ + new (p) Type(t); +} + +template +void destroy(const Type* p) +{ + p->~Type(); +} + +} /* namespace boost::detail::allocator */ + +} /* namespace boost::detail */ + +} /* namespace boost */ + +#endif diff --git a/win32/include/boost/detail/atomic_count.hpp b/win32/include/boost/detail/atomic_count.hpp new file mode 100755 index 000000000..aa8527d94 --- /dev/null +++ b/win32/include/boost/detail/atomic_count.hpp @@ -0,0 +1,124 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/atomic_count.hpp - thread/SMP safe reference counter +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// 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) +// +// typedef boost::detail::atomic_count; +// +// atomic_count a(n); +// +// (n is convertible to long) +// +// Effects: Constructs an atomic_count with an initial value of n +// +// a; +// +// Returns: (long) the current value of a +// +// ++a; +// +// Effects: Atomically increments the value of a +// Returns: nothing +// +// --a; +// +// Effects: Atomically decrements the value of a +// Returns: (long) zero if the new value of a is zero, +// unspecified non-zero value otherwise (usually the new value) +// +// Important note: when --a returns zero, it must act as a +// read memory barrier (RMB); i.e. the calling thread must +// have a synchronized view of the memory +// +// On Intel IA-32 (x86) memory is always synchronized, so this +// is not a problem. +// +// On many architectures the atomic instructions already act as +// a memory barrier. +// +// This property is necessary for proper reference counting, since +// a thread can update the contents of a shared object, then +// release its reference, and another thread may immediately +// release the last reference causing object destruction. +// +// The destructor needs to have a synchronized view of the +// object to perform proper cleanup. +// +// Original example by Alexander Terekhov: +// +// Given: +// +// - a mutable shared object OBJ; +// - two threads THREAD1 and THREAD2 each holding +// a private smart_ptr object pointing to that OBJ. +// +// t1: THREAD1 updates OBJ (thread-safe via some synchronization) +// and a few cycles later (after "unlock") destroys smart_ptr; +// +// t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization +// with respect to shared mutable object OBJ; OBJ destructors +// are called driven by smart_ptr interface... +// + +#include + +#ifndef BOOST_HAS_THREADS + +namespace boost +{ + +namespace detail +{ + +typedef long atomic_count; + +} + +} + +#elif defined(BOOST_AC_USE_PTHREADS) + +# include + +#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) + +# include + +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) + +# include + +#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + +# include + +#elif defined(__GLIBCPP__) || defined(__GLIBCXX__) + +# include + +#elif defined(BOOST_HAS_PTHREADS) + +# define BOOST_AC_USE_PTHREADS +# include + +#else + +// Use #define BOOST_DISABLE_THREADS to avoid the error +#error Unrecognized threading platform + +#endif + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED diff --git a/win32/include/boost/detail/atomic_count_gcc.hpp b/win32/include/boost/detail/atomic_count_gcc.hpp new file mode 100755 index 000000000..ea1f6a453 --- /dev/null +++ b/win32/include/boost/detail/atomic_count_gcc.hpp @@ -0,0 +1,68 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED + +// +// boost/detail/atomic_count_gcc.hpp +// +// atomic_count for GNU libstdc++ v3 +// +// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2002 Lars Gullik Bjønnes +// Copyright 2003-2005 Peter Dimov +// +// 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) +// + +#include + +namespace boost +{ + +namespace detail +{ + +#if defined(__GLIBCXX__) // g++ 3.4+ + +using __gnu_cxx::__atomic_add; +using __gnu_cxx::__exchange_and_add; + +#endif + +class atomic_count +{ +public: + + explicit atomic_count(long v) : value_(v) {} + + void operator++() + { + __atomic_add(&value_, 1); + } + + long operator--() + { + return __exchange_and_add(&value_, -1) - 1; + } + + operator long() const + { + return __exchange_and_add(&value_, 0); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + mutable _Atomic_word value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED diff --git a/win32/include/boost/detail/atomic_count_gcc_x86.hpp b/win32/include/boost/detail/atomic_count_gcc_x86.hpp new file mode 100755 index 000000000..077a9045b --- /dev/null +++ b/win32/include/boost/detail/atomic_count_gcc_x86.hpp @@ -0,0 +1,84 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED + +// +// boost/detail/atomic_count_gcc_x86.hpp +// +// atomic_count for g++ on 486+/AMD64 +// +// Copyright 2007 Peter Dimov +// +// 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) +// + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( long v ) : value_( static_cast< int >( v ) ) {} + + void operator++() + { + __asm__ + ( + "lock\n\t" + "incl %0": + "+m"( value_ ): // output (%0) + : // inputs + "cc" // clobbers + ); + } + + long operator--() + { + return atomic_exchange_and_add( &value_, -1 ) - 1; + } + + operator long() const + { + return atomic_exchange_and_add( &value_, 0 ); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + mutable int value_; + +private: + + static int atomic_exchange_and_add( int * pw, int dv ) + { + // int r = *pw; + // *pw += dv; + // return r; + + int r; + + __asm__ __volatile__ + ( + "lock\n\t" + "xadd %1, %0": + "+m"( *pw ), "=r"( r ): // outputs (%0, %1) + "1"( dv ): // inputs (%2 == %1) + "memory", "cc" // clobbers + ); + + return r; + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED diff --git a/win32/include/boost/detail/atomic_count_pthreads.hpp b/win32/include/boost/detail/atomic_count_pthreads.hpp new file mode 100755 index 000000000..f3eb54d4e --- /dev/null +++ b/win32/include/boost/detail/atomic_count_pthreads.hpp @@ -0,0 +1,96 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED + +// +// boost/detail/atomic_count_pthreads.hpp +// +// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// +// 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) +// + +#include + +// +// The generic pthread_mutex-based implementation sometimes leads to +// inefficiencies. Example: a class with two atomic_count members +// can get away with a single mutex. +// +// Users can detect this situation by checking BOOST_AC_USE_PTHREADS. +// + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +private: + + class scoped_lock + { + public: + + scoped_lock(pthread_mutex_t & m): m_(m) + { + pthread_mutex_lock(&m_); + } + + ~scoped_lock() + { + pthread_mutex_unlock(&m_); + } + + private: + + pthread_mutex_t & m_; + }; + +public: + + explicit atomic_count(long v): value_(v) + { + pthread_mutex_init(&mutex_, 0); + } + + ~atomic_count() + { + pthread_mutex_destroy(&mutex_); + } + + void operator++() + { + scoped_lock lock(mutex_); + ++value_; + } + + long operator--() + { + scoped_lock lock(mutex_); + return --value_; + } + + operator long() const + { + scoped_lock lock(mutex_); + return value_; + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + mutable pthread_mutex_t mutex_; + long value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED diff --git a/win32/include/boost/detail/atomic_count_solaris.hpp b/win32/include/boost/detail/atomic_count_solaris.hpp new file mode 100755 index 000000000..99571d666 --- /dev/null +++ b/win32/include/boost/detail/atomic_count_solaris.hpp @@ -0,0 +1,59 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED + +// +// boost/detail/atomic_count_solaris.hpp +// based on: boost/detail/atomic_count_win32.hpp +// +// Copyright (c) 2001-2005 Peter Dimov +// Copyright (c) 2006 Michael van der Westhuizen +// +// 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) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( uint32_t v ): value_( v ) + { + } + + long operator++() + { + return atomic_inc_32_nv( &value_ ); + } + + long operator--() + { + return atomic_dec_32_nv( &value_ ); + } + + operator uint32_t() const + { + return static_cast( value_ ); + } + +private: + + atomic_count( atomic_count const & ); + atomic_count & operator=( atomic_count const & ); + + uint32_t value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED diff --git a/win32/include/boost/detail/atomic_count_sync.hpp b/win32/include/boost/detail/atomic_count_sync.hpp new file mode 100755 index 000000000..ed6ef403b --- /dev/null +++ b/win32/include/boost/detail/atomic_count_sync.hpp @@ -0,0 +1,57 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED + +// +// boost/detail/atomic_count_sync.hpp +// +// atomic_count for g++ 4.1+ +// +// http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html +// +// Copyright 2007 Peter Dimov +// +// 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) +// + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( long v ) : value_( v ) {} + + void operator++() + { + __sync_add_and_fetch( &value_, 1 ); + } + + long operator--() + { + return __sync_add_and_fetch( &value_, -1 ); + } + + operator long() const + { + return __sync_fetch_and_add( &value_, 0 ); + } + +private: + + atomic_count(atomic_count const &); + atomic_count & operator=(atomic_count const &); + + mutable long value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED diff --git a/win32/include/boost/detail/atomic_count_win32.hpp b/win32/include/boost/detail/atomic_count_win32.hpp new file mode 100755 index 000000000..a9ac55016 --- /dev/null +++ b/win32/include/boost/detail/atomic_count_win32.hpp @@ -0,0 +1,63 @@ +#ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED +#define BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/atomic_count_win32.hpp +// +// Copyright (c) 2001-2005 Peter Dimov +// +// 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) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class atomic_count +{ +public: + + explicit atomic_count( long v ): value_( v ) + { + } + + long operator++() + { + return BOOST_INTERLOCKED_INCREMENT( &value_ ); + } + + long operator--() + { + return BOOST_INTERLOCKED_DECREMENT( &value_ ); + } + + operator long() const + { + return static_cast( value_ ); + } + +private: + + atomic_count( atomic_count const & ); + atomic_count & operator=( atomic_count const & ); + + long value_; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED diff --git a/win32/include/boost/detail/bad_weak_ptr.hpp b/win32/include/boost/detail/bad_weak_ptr.hpp new file mode 100755 index 000000000..3bbca2b2b --- /dev/null +++ b/win32/include/boost/detail/bad_weak_ptr.hpp @@ -0,0 +1,59 @@ +#ifndef BOOST_BAD_WEAK_PTR_HPP_INCLUDED +#define BOOST_BAD_WEAK_PTR_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/bad_weak_ptr.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// +// 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) +// + +#include + +#ifdef __BORLANDC__ +# pragma warn -8026 // Functions with excep. spec. are not expanded inline +#endif + +namespace boost +{ + +// The standard library that comes with Borland C++ 5.5.1, 5.6.4 +// defines std::exception and its members as having C calling +// convention (-pc). When the definition of bad_weak_ptr +// is compiled with -ps, the compiler issues an error. +// Hence, the temporary #pragma option -pc below. + +#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564 +# pragma option push -pc +#endif + +class bad_weak_ptr: public std::exception +{ +public: + + virtual char const * what() const throw() + { + return "tr1::bad_weak_ptr"; + } +}; + +#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564 +# pragma option pop +#endif + +} // namespace boost + +#ifdef __BORLANDC__ +# pragma warn .8026 // Functions with excep. spec. are not expanded inline +#endif + +#endif // #ifndef BOOST_BAD_WEAK_PTR_HPP_INCLUDED diff --git a/win32/include/boost/detail/binary_search.hpp b/win32/include/boost/detail/binary_search.hpp new file mode 100755 index 000000000..8242b70c3 --- /dev/null +++ b/win32/include/boost/detail/binary_search.hpp @@ -0,0 +1,216 @@ +// Copyright (c) 2000 David Abrahams. +// 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) +// +// Copyright (c) 1994 +// Hewlett-Packard Company +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. Hewlett-Packard Company makes no +// representations about the suitability of this software for any +// purpose. It is provided "as is" without express or implied warranty. +// +// Copyright (c) 1996 +// Silicon Graphics Computer Systems, Inc. +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. Silicon Graphics makes no +// representations about the suitability of this software for any +// purpose. It is provided "as is" without express or implied warranty. +// +#ifndef BINARY_SEARCH_DWA_122600_H_ +# define BINARY_SEARCH_DWA_122600_H_ + +# include +# include + +namespace boost { namespace detail { + +template +ForwardIter lower_bound(ForwardIter first, ForwardIter last, + const Tp& val) +{ + typedef detail::iterator_traits traits; + + typename traits::difference_type len = boost::detail::distance(first, last); + typename traits::difference_type half; + ForwardIter middle; + + while (len > 0) { + half = len >> 1; + middle = first; + std::advance(middle, half); + if (*middle < val) { + first = middle; + ++first; + len = len - half - 1; + } + else + len = half; + } + return first; +} + +template +ForwardIter lower_bound(ForwardIter first, ForwardIter last, + const Tp& val, Compare comp) +{ + typedef detail::iterator_traits traits; + + typename traits::difference_type len = boost::detail::distance(first, last); + typename traits::difference_type half; + ForwardIter middle; + + while (len > 0) { + half = len >> 1; + middle = first; + std::advance(middle, half); + if (comp(*middle, val)) { + first = middle; + ++first; + len = len - half - 1; + } + else + len = half; + } + return first; +} + +template +ForwardIter upper_bound(ForwardIter first, ForwardIter last, + const Tp& val) +{ + typedef detail::iterator_traits traits; + + typename traits::difference_type len = boost::detail::distance(first, last); + typename traits::difference_type half; + ForwardIter middle; + + while (len > 0) { + half = len >> 1; + middle = first; + std::advance(middle, half); + if (val < *middle) + len = half; + else { + first = middle; + ++first; + len = len - half - 1; + } + } + return first; +} + +template +ForwardIter upper_bound(ForwardIter first, ForwardIter last, + const Tp& val, Compare comp) +{ + typedef detail::iterator_traits traits; + + typename traits::difference_type len = boost::detail::distance(first, last); + typename traits::difference_type half; + ForwardIter middle; + + while (len > 0) { + half = len >> 1; + middle = first; + std::advance(middle, half); + if (comp(val, *middle)) + len = half; + else { + first = middle; + ++first; + len = len - half - 1; + } + } + return first; +} + +template +std::pair +equal_range(ForwardIter first, ForwardIter last, const Tp& val) +{ + typedef detail::iterator_traits traits; + + typename traits::difference_type len = boost::detail::distance(first, last); + typename traits::difference_type half; + ForwardIter middle, left, right; + + while (len > 0) { + half = len >> 1; + middle = first; + std::advance(middle, half); + if (*middle < val) { + first = middle; + ++first; + len = len - half - 1; + } + else if (val < *middle) + len = half; + else { + left = boost::detail::lower_bound(first, middle, val); + std::advance(first, len); + right = boost::detail::upper_bound(++middle, first, val); + return std::pair(left, right); + } + } + return std::pair(first, first); +} + +template +std::pair +equal_range(ForwardIter first, ForwardIter last, const Tp& val, + Compare comp) +{ + typedef detail::iterator_traits traits; + + typename traits::difference_type len = boost::detail::distance(first, last); + typename traits::difference_type half; + ForwardIter middle, left, right; + + while (len > 0) { + half = len >> 1; + middle = first; + std::advance(middle, half); + if (comp(*middle, val)) { + first = middle; + ++first; + len = len - half - 1; + } + else if (comp(val, *middle)) + len = half; + else { + left = boost::detail::lower_bound(first, middle, val, comp); + std::advance(first, len); + right = boost::detail::upper_bound(++middle, first, val, comp); + return std::pair(left, right); + } + } + return std::pair(first, first); +} + +template +bool binary_search(ForwardIter first, ForwardIter last, + const Tp& val) { + ForwardIter i = boost::detail::lower_bound(first, last, val); + return i != last && !(val < *i); +} + +template +bool binary_search(ForwardIter first, ForwardIter last, + const Tp& val, + Compare comp) { + ForwardIter i = boost::detail::lower_bound(first, last, val, comp); + return i != last && !comp(val, *i); +} + +}} // namespace boost::detail + +#endif // BINARY_SEARCH_DWA_122600_H_ diff --git a/win32/include/boost/detail/call_traits.hpp b/win32/include/boost/detail/call_traits.hpp new file mode 100755 index 000000000..cd7dd10f3 --- /dev/null +++ b/win32/include/boost/detail/call_traits.hpp @@ -0,0 +1,164 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/utility for most recent version including documentation. + +// call_traits: defines typedefs for function usage +// (see libs/utility/call_traits.htm) + +/* Release notes: + 23rd July 2000: + Fixed array specialization. (JM) + Added Borland specific fixes for reference types + (issue raised by Steve Cleary). +*/ + +#ifndef BOOST_DETAIL_CALL_TRAITS_HPP +#define BOOST_DETAIL_CALL_TRAITS_HPP + +#ifndef BOOST_CONFIG_HPP +#include +#endif +#include + +#include +#include +#include + +namespace boost{ + +namespace detail{ + +template +struct ct_imp2 +{ + typedef const T& param_type; +}; + +template +struct ct_imp2 +{ + typedef const T param_type; +}; + +template +struct ct_imp +{ + typedef const T& param_type; +}; + +template +struct ct_imp +{ + typedef typename ct_imp2::param_type param_type; +}; + +template +struct ct_imp +{ + typedef const T param_type; +}; + +} + +template +struct call_traits +{ +public: + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + // + // C++ Builder workaround: we should be able to define a compile time + // constant and pass that as a single template parameter to ct_imp, + // however compiler bugs prevent this - instead pass three bool's to + // ct_imp and add an extra partial specialisation + // of ct_imp to handle the logic. (JM) + typedef typename boost::detail::ct_imp< + T, + ::boost::is_pointer::value, + ::boost::is_arithmetic::value + >::param_type param_type; +}; + +template +struct call_traits +{ + typedef T& value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T& param_type; // hh removed const +}; + +#if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x581 ) ) +// these are illegal specialisations; cv-qualifies applied to +// references have no effect according to [8.3.2p1], +// C++ Builder requires them though as it treats cv-qualified +// references as distinct types... +template +struct call_traits +{ + typedef T& value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T& param_type; // hh removed const +}; +template +struct call_traits +{ + typedef T& value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T& param_type; // hh removed const +}; +template +struct call_traits +{ + typedef T& value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T& param_type; // hh removed const +}; + +template +struct call_traits< T * > +{ + typedef T * value_type; + typedef T * & reference; + typedef T * const & const_reference; + typedef T * const param_type; // hh removed const +}; +#endif +#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS) +template +struct call_traits +{ +private: + typedef T array_type[N]; +public: + // degrades array to pointer: + typedef const T* value_type; + typedef array_type& reference; + typedef const array_type& const_reference; + typedef const T* const param_type; +}; + +template +struct call_traits +{ +private: + typedef const T array_type[N]; +public: + // degrades array to pointer: + typedef const T* value_type; + typedef array_type& reference; + typedef const array_type& const_reference; + typedef const T* const param_type; +}; +#endif + +} + +#endif // BOOST_DETAIL_CALL_TRAITS_HPP diff --git a/win32/include/boost/detail/catch_exceptions.hpp b/win32/include/boost/detail/catch_exceptions.hpp new file mode 100755 index 000000000..f06a11769 --- /dev/null +++ b/win32/include/boost/detail/catch_exceptions.hpp @@ -0,0 +1,146 @@ +// boost/catch_exceptions.hpp -----------------------------------------------// + +// Copyright Beman Dawes 1995-2001. 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) + +// See http://www.boost.org/libs/test for documentation. + +// Revision History +// 13 Jun 01 report_exception() made inline. (John Maddock, Jesse Jones) +// 26 Feb 01 Numerous changes suggested during formal review. (Beman) +// 25 Jan 01 catch_exceptions.hpp code factored out of cpp_main.cpp. +// 22 Jan 01 Remove test_tools dependencies to reduce coupling. +// 5 Nov 00 Initial boost version (Beman Dawes) + +#ifndef BOOST_CATCH_EXCEPTIONS_HPP +#define BOOST_CATCH_EXCEPTIONS_HPP + +// header dependencies are deliberately restricted to the standard library +// to reduce coupling to other boost libraries. +#include // for string +#include // for bad_alloc +#include // for bad_cast, bad_typeid +#include // for exception, bad_exception +#include // for std exception hierarchy +#include // for exit codes +# if __GNUC__ != 2 || __GNUC_MINOR__ > 96 +# include // for ostream +# else +# include // workaround GNU missing ostream header +# endif + +# if defined(__BORLANDC__) && (__BORLANDC__ <= 0x0551) +# define BOOST_BUILT_IN_EXCEPTIONS_MISSING_WHAT +# endif + +#if defined(MPW_CPLUS) && (MPW_CPLUS <= 0x890) +# define BOOST_BUILT_IN_EXCEPTIONS_MISSING_WHAT + namespace std { class bad_typeid { }; } +# endif + +namespace boost +{ + + namespace detail + { + // A separate reporting function was requested during formal review. + inline void report_exception( std::ostream & os, + const char * name, const char * info ) + { os << "\n** uncaught exception: " << name << " " << info << std::endl; } + } + + // catch_exceptions ------------------------------------------------------// + + template< class Generator > // Generator is function object returning int + int catch_exceptions( Generator function_object, + std::ostream & out, std::ostream & err ) + { + int result = 0; // quiet compiler warnings + bool exception_thrown = true; // avoid setting result for each excptn type + +#ifndef BOOST_NO_EXCEPTIONS + try + { +#endif + result = function_object(); + exception_thrown = false; +#ifndef BOOST_NO_EXCEPTIONS + } + + // As a result of hard experience with strangely interleaved output + // under some compilers, there is a lot of use of endl in the code below + // where a simple '\n' might appear to do. + + // The rules for catch & arguments are a bit different from function + // arguments (ISO 15.3 paragraphs 18 & 19). Apparently const isn't + // required, but it doesn't hurt and some programmers ask for it. + + catch ( const char * ex ) + { detail::report_exception( out, "", ex ); } + catch ( const std::string & ex ) + { detail::report_exception( out, "", ex.c_str() ); } + + // std:: exceptions + catch ( const std::bad_alloc & ex ) + { detail::report_exception( out, "std::bad_alloc:", ex.what() ); } + +# ifndef BOOST_BUILT_IN_EXCEPTIONS_MISSING_WHAT + catch ( const std::bad_cast & ex ) + { detail::report_exception( out, "std::bad_cast:", ex.what() ); } + catch ( const std::bad_typeid & ex ) + { detail::report_exception( out, "std::bad_typeid:", ex.what() ); } +# else + catch ( const std::bad_cast & ) + { detail::report_exception( out, "std::bad_cast", "" ); } + catch ( const std::bad_typeid & ) + { detail::report_exception( out, "std::bad_typeid", "" ); } +# endif + + catch ( const std::bad_exception & ex ) + { detail::report_exception( out, "std::bad_exception:", ex.what() ); } + catch ( const std::domain_error & ex ) + { detail::report_exception( out, "std::domain_error:", ex.what() ); } + catch ( const std::invalid_argument & ex ) + { detail::report_exception( out, "std::invalid_argument:", ex.what() ); } + catch ( const std::length_error & ex ) + { detail::report_exception( out, "std::length_error:", ex.what() ); } + catch ( const std::out_of_range & ex ) + { detail::report_exception( out, "std::out_of_range:", ex.what() ); } + catch ( const std::range_error & ex ) + { detail::report_exception( out, "std::range_error:", ex.what() ); } + catch ( const std::overflow_error & ex ) + { detail::report_exception( out, "std::overflow_error:", ex.what() ); } + catch ( const std::underflow_error & ex ) + { detail::report_exception( out, "std::underflow_error:", ex.what() ); } + catch ( const std::logic_error & ex ) + { detail::report_exception( out, "std::logic_error:", ex.what() ); } + catch ( const std::runtime_error & ex ) + { detail::report_exception( out, "std::runtime_error:", ex.what() ); } + catch ( const std::exception & ex ) + { detail::report_exception( out, "std::exception:", ex.what() ); } + + catch ( ... ) + { detail::report_exception( out, "unknown exception", "" ); } +#endif // BOOST_NO_EXCEPTIONS + + if ( exception_thrown ) result = boost::exit_exception_failure; + + if ( result != 0 && result != exit_success ) + { + out << std::endl << "**** returning with error code " + << result << std::endl; + err + << "********** errors detected; see stdout for details ***********" + << std::endl; + } +#if !defined(BOOST_NO_CPP_MAIN_SUCCESS_MESSAGE) + else { out << std::flush << "no errors detected" << std::endl; } +#endif + return result; + } // catch_exceptions + +} // boost + +#endif // BOOST_CATCH_EXCEPTIONS_HPP + diff --git a/win32/include/boost/detail/compressed_pair.hpp b/win32/include/boost/detail/compressed_pair.hpp new file mode 100755 index 000000000..7d9c51843 --- /dev/null +++ b/win32/include/boost/detail/compressed_pair.hpp @@ -0,0 +1,443 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/utility for most recent version including documentation. + +// compressed_pair: pair that "compresses" empty members +// (see libs/utility/compressed_pair.htm) +// +// JM changes 25 Jan 2004: +// For the case where T1 == T2 and both are empty, then first() and second() +// should return different objects. +// JM changes 25 Jan 2000: +// Removed default arguments from compressed_pair_switch to get +// C++ Builder 4 to accept them +// rewriten swap to get gcc and C++ builder to compile. +// added partial specialisations for case T1 == T2 to avoid duplicate constructor defs. + +#ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP +#define BOOST_DETAIL_COMPRESSED_PAIR_HPP + +#include + +#include +#include +#include +#include + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4512) +#endif +namespace boost +{ + +template +class compressed_pair; + + +// compressed_pair + +namespace details +{ + // JM altered 26 Jan 2000: + template + struct compressed_pair_switch; + + template + struct compressed_pair_switch + {static const int value = 0;}; + + template + struct compressed_pair_switch + {static const int value = 3;}; + + template + struct compressed_pair_switch + {static const int value = 1;}; + + template + struct compressed_pair_switch + {static const int value = 2;}; + + template + struct compressed_pair_switch + {static const int value = 4;}; + + template + struct compressed_pair_switch + {static const int value = 5;}; + + template class compressed_pair_imp; + +#ifdef __GNUC__ + // workaround for GCC (JM): + using std::swap; +#endif + // + // can't call unqualified swap from within classname::swap + // as Koenig lookup rules will find only the classname::swap + // member function not the global declaration, so use cp_swap + // as a forwarding function (JM): + template + inline void cp_swap(T& t1, T& t2) + { +#ifndef __GNUC__ + using std::swap; +#endif + swap(t1, t2); + } + + // 0 derive from neither + + template + class compressed_pair_imp + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : first_(x), second_(y) {} + + compressed_pair_imp(first_param_type x) + : first_(x) {} + + compressed_pair_imp(second_param_type y) + : second_(y) {} + + first_reference first() {return first_;} + first_const_reference first() const {return first_;} + + second_reference second() {return second_;} + second_const_reference second() const {return second_;} + + void swap(::boost::compressed_pair& y) + { + cp_swap(first_, y.first()); + cp_swap(second_, y.second()); + } + private: + first_type first_; + second_type second_; + }; + + // 1 derive from T1 + + template + class compressed_pair_imp + : protected ::boost::remove_cv::type + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : first_type(x), second_(y) {} + + compressed_pair_imp(first_param_type x) + : first_type(x) {} + + compressed_pair_imp(second_param_type y) + : second_(y) {} + + first_reference first() {return *this;} + first_const_reference first() const {return *this;} + + second_reference second() {return second_;} + second_const_reference second() const {return second_;} + + void swap(::boost::compressed_pair& y) + { + // no need to swap empty base class: + cp_swap(second_, y.second()); + } + private: + second_type second_; + }; + + // 2 derive from T2 + + template + class compressed_pair_imp + : protected ::boost::remove_cv::type + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : second_type(y), first_(x) {} + + compressed_pair_imp(first_param_type x) + : first_(x) {} + + compressed_pair_imp(second_param_type y) + : second_type(y) {} + + first_reference first() {return first_;} + first_const_reference first() const {return first_;} + + second_reference second() {return *this;} + second_const_reference second() const {return *this;} + + void swap(::boost::compressed_pair& y) + { + // no need to swap empty base class: + cp_swap(first_, y.first()); + } + + private: + first_type first_; + }; + + // 3 derive from T1 and T2 + + template + class compressed_pair_imp + : protected ::boost::remove_cv::type, + protected ::boost::remove_cv::type + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : first_type(x), second_type(y) {} + + compressed_pair_imp(first_param_type x) + : first_type(x) {} + + compressed_pair_imp(second_param_type y) + : second_type(y) {} + + first_reference first() {return *this;} + first_const_reference first() const {return *this;} + + second_reference second() {return *this;} + second_const_reference second() const {return *this;} + // + // no need to swap empty bases: + void swap(::boost::compressed_pair&) {} + }; + + // JM + // 4 T1 == T2, T1 and T2 both empty + // Originally this did not store an instance of T2 at all + // but that led to problems beause it meant &x.first() == &x.second() + // which is not true for any other kind of pair, so now we store an instance + // of T2 just in case the user is relying on first() and second() returning + // different objects (albeit both empty). + template + class compressed_pair_imp + : protected ::boost::remove_cv::type + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : first_type(x), m_second(y) {} + + compressed_pair_imp(first_param_type x) + : first_type(x), m_second(x) {} + + first_reference first() {return *this;} + first_const_reference first() const {return *this;} + + second_reference second() {return m_second;} + second_const_reference second() const {return m_second;} + + void swap(::boost::compressed_pair&) {} + private: + T2 m_second; + }; + + // 5 T1 == T2 and are not empty: //JM + + template + class compressed_pair_imp + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : first_(x), second_(y) {} + + compressed_pair_imp(first_param_type x) + : first_(x), second_(x) {} + + first_reference first() {return first_;} + first_const_reference first() const {return first_;} + + second_reference second() {return second_;} + second_const_reference second() const {return second_;} + + void swap(::boost::compressed_pair& y) + { + cp_swap(first_, y.first()); + cp_swap(second_, y.second()); + } + private: + first_type first_; + second_type second_; + }; + +} // details + +template +class compressed_pair + : private ::boost::details::compressed_pair_imp::type, typename remove_cv::type>::value, + ::boost::is_empty::value, + ::boost::is_empty::value>::value> +{ +private: + typedef details::compressed_pair_imp::type, typename remove_cv::type>::value, + ::boost::is_empty::value, + ::boost::is_empty::value>::value> base; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair() : base() {} + compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} + explicit compressed_pair(first_param_type x) : base(x) {} + explicit compressed_pair(second_param_type y) : base(y) {} + + first_reference first() {return base::first();} + first_const_reference first() const {return base::first();} + + second_reference second() {return base::second();} + second_const_reference second() const {return base::second();} + + void swap(compressed_pair& y) { base::swap(y); } +}; + +// JM +// Partial specialisation for case where T1 == T2: +// +template +class compressed_pair + : private details::compressed_pair_imp::type, typename remove_cv::type>::value, + ::boost::is_empty::value, + ::boost::is_empty::value>::value> +{ +private: + typedef details::compressed_pair_imp::type, typename remove_cv::type>::value, + ::boost::is_empty::value, + ::boost::is_empty::value>::value> base; +public: + typedef T first_type; + typedef T second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair() : base() {} + compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} +#if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) + explicit +#endif + compressed_pair(first_param_type x) : base(x) {} + + first_reference first() {return base::first();} + first_const_reference first() const {return base::first();} + + second_reference second() {return base::second();} + second_const_reference second() const {return base::second();} + + void swap(::boost::compressed_pair& y) { base::swap(y); } +}; + +template +inline +void +swap(compressed_pair& x, compressed_pair& y) +{ + x.swap(y); +} + +} // boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP + diff --git a/win32/include/boost/detail/dynamic_bitset.hpp b/win32/include/boost/detail/dynamic_bitset.hpp new file mode 100755 index 000000000..fc30baff3 --- /dev/null +++ b/win32/include/boost/detail/dynamic_bitset.hpp @@ -0,0 +1,176 @@ +// -------------------------------------------------- +// +// (C) Copyright Chuck Allison and Jeremy Siek 2001 - 2002. +// (C) Copyright Gennaro Prota 2003 - 2006. +// +// 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) +// +// ----------------------------------------------------------- + +// See http://www.boost.org/libs/dynamic_bitset/ for documentation. +// +// $Revision: 41316 $ $Date: 2007-11-23 12:03:14 -0500 (Fri, 23 Nov 2007) $ - $Name$ + +#ifndef BOOST_DETAIL_DYNAMIC_BITSET_HPP +#define BOOST_DETAIL_DYNAMIC_BITSET_HPP + +#include // for std::size_t +#include "boost/config.hpp" +#include "boost/detail/workaround.hpp" + + +namespace boost { + + namespace detail { + + // Gives (read-)access to the object representation + // of an object of type T (3.9p4). CANNOT be used + // on a base sub-object + // + template + inline const unsigned char * object_representation (T* p) + { + return static_cast(static_cast(p)); + } + + template + struct shifter + { + static void left_shift(T & v) { + amount >= width ? (v = 0) + : (v >>= BOOST_DYNAMIC_BITSET_WRAP_CONSTANT(amount)); + } + }; + + // ------- count function implementation -------------- + + namespace dynamic_bitset_count_impl { + + typedef unsigned char byte_type; + + enum mode { access_by_bytes, access_by_blocks }; + + template struct mode_to_type {}; + + // the table: wrapped in a class template, so + // that it is only instantiated if/when needed + // + template + struct count_table { static const byte_type table[]; }; + + template <> + struct count_table { /* no table */ }; + + + const unsigned int table_width = 8; + template + const byte_type count_table::table[] = + { + // Automatically generated by GPTableGen.exe v.1.0 + // + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 + }; + + + // overload for access by bytes + // + + template + inline std::size_t do_count(Iterator first, std::size_t length, + int /*dummy param*/, + mode_to_type* ) + { + std::size_t num = 0; + if (length) + { + const byte_type * p = object_representation(&*first); + length *= sizeof(*first); + + do { + num += count_table<>::table[*p]; + ++p; + --length; + + } while (length); + } + + return num; + } + + + // overload for access by blocks + // + template + inline std::size_t do_count(Iterator first, std::size_t length, ValueType, + mode_to_type*) + { + std::size_t num = 0; + while (length){ + + ValueType value = *first; + while (value) { + num += count_table<>::table[value & ((1u<>= table_width; + } + + ++first; + --length; + } + + return num; + } + + + } // dynamic_bitset_count_impl + // ------------------------------------------------------- + + + // Some library implementations simply return a dummy + // value such as + // + // size_type(-1) / sizeof(T) + // + // from vector<>::max_size. This tries to get out more + // meaningful info. + // + template + typename T::size_type vector_max_size_workaround(const T & v) { + + typedef typename T::allocator_type allocator_type; + + const typename allocator_type::size_type alloc_max = + v.get_allocator().max_size(); + const typename T::size_type container_max = v.max_size(); + + return alloc_max < container_max? + alloc_max : + container_max; + } + + // for static_asserts + template + struct dynamic_bitset_allowed_block_type { + enum { value = T(-1) > 0 }; // ensure T has no sign + }; + + template <> + struct dynamic_bitset_allowed_block_type { + enum { value = false }; + }; + + + } // namespace detail + +} // namespace boost + +#endif // include guard + diff --git a/win32/include/boost/detail/endian.hpp b/win32/include/boost/detail/endian.hpp new file mode 100755 index 000000000..2b99be21e --- /dev/null +++ b/win32/include/boost/detail/endian.hpp @@ -0,0 +1,73 @@ +// Copyright 2005 Caleb Epstein +// Copyright 2006 John Maddock +// Distributed under the Boost Software License, Version 1.0. (See accompany- +// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/* + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/* + * Copyright notice reproduced from , from + * which this code was originally taken. + * + * Modified by Caleb Epstein to use with GNU libc and to + * defined the BOOST_ENDIAN macro. + */ + +#ifndef BOOST_DETAIL_ENDIAN_HPP +#define BOOST_DETAIL_ENDIAN_HPP + +// GNU libc offers the helpful header which defines +// __BYTE_ORDER + +#if defined (__GLIBC__) +# include +# if (__BYTE_ORDER == __LITTLE_ENDIAN) +# define BOOST_LITTLE_ENDIAN +# elif (__BYTE_ORDER == __BIG_ENDIAN) +# define BOOST_BIG_ENDIAN +# elif (__BYTE_ORDER == __PDP_ENDIAN) +# define BOOST_PDP_ENDIAN +# else +# error Unknown machine endianness detected. +# endif +# define BOOST_BYTE_ORDER __BYTE_ORDER +#elif defined(_BIG_ENDIAN) +# define BOOST_BIG_ENDIAN +# define BOOST_BYTE_ORDER 4321 +#elif defined(_LITTLE_ENDIAN) +# define BOOST_LITTLE_ENDIAN +# define BOOST_BYTE_ORDER 1234 +#elif defined(__sparc) || defined(__sparc__) \ + || defined(_POWER) || defined(__powerpc__) \ + || defined(__ppc__) || defined(__hpux) \ + || defined(_MIPSEB) || defined(_POWER) \ + || defined(__s390__) +# define BOOST_BIG_ENDIAN +# define BOOST_BYTE_ORDER 4321 +#elif defined(__i386__) || defined(__alpha__) \ + || defined(__ia64) || defined(__ia64__) \ + || defined(_M_IX86) || defined(_M_IA64) \ + || defined(_M_ALPHA) || defined(__amd64) \ + || defined(__amd64__) || defined(_M_AMD64) \ + || defined(__x86_64) || defined(__x86_64__) \ + || defined(_M_X64) + +# define BOOST_LITTLE_ENDIAN +# define BOOST_BYTE_ORDER 1234 +#else +# error The file boost/detail/endian.hpp needs to be set up for your CPU type. +#endif + + +#endif diff --git a/win32/include/boost/detail/has_default_constructor.hpp b/win32/include/boost/detail/has_default_constructor.hpp new file mode 100755 index 000000000..911a5e5f3 --- /dev/null +++ b/win32/include/boost/detail/has_default_constructor.hpp @@ -0,0 +1,29 @@ + +// (C) Copyright Matthias Troyerk 2006. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. + +#ifndef BOOST_DETAIL_HAS_DEFAULT_CONSTRUCTOR_HPP_INCLUDED +#define BOOST_DETAIL_HAS_DEFAULT_CONSTRUCTOR_HPP_INCLUDED + +#include + +namespace boost { namespace detail { + +/// type trait to check for a default constructor +/// +/// The default implementation just checks for a trivial constructor. +/// Using some compiler magic it might be possible to provide a better default + +template +struct has_default_constructor + : public has_trivial_constructor +{}; + +} } // namespace boost::detail + + +#endif // BOOST_DETAIL_HAS_DEFAULT_CONSTRUCTOR_HPP_INCLUDED diff --git a/win32/include/boost/detail/identifier.hpp b/win32/include/boost/detail/identifier.hpp new file mode 100755 index 000000000..142a546be --- /dev/null +++ b/win32/include/boost/detail/identifier.hpp @@ -0,0 +1,89 @@ +// boost/identifier.hpp ----------------------------------------------------// + +// Copyright Beman Dawes 2006 + +// 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) + +// See documentation at http://www.boost.org/libs/utility + +#ifndef BOOST_IDENTIFIER_HPP +#define BOOST_IDENTIFIER_HPP + +#include +#include +#include + +namespace boost +{ + namespace detail + { + // class template identifier ---------------------------------------------// + + // Always used as a base class so that different instantiations result in + // different class types even if instantiated with the same value type T. + + // Expected usage is that T is often an integer type, best passed by + // value. There is no reason why T can't be a possibly larger class such as + // std::string, best passed by const reference. + + // This implementation uses pass by value, based on expected common uses. + + template + class identifier + { + public: + typedef T value_type; + + const value_type value() const { return m_value; } + void assign( value_type v ) { m_value = v; } + + bool operator==( const D & rhs ) const { return m_value == rhs.m_value; } + bool operator!=( const D & rhs ) const { return m_value != rhs.m_value; } + bool operator< ( const D & rhs ) const { return m_value < rhs.m_value; } + bool operator<=( const D & rhs ) const { return m_value <= rhs.m_value; } + bool operator> ( const D & rhs ) const { return m_value > rhs.m_value; } + bool operator>=( const D & rhs ) const { return m_value >= rhs.m_value; } + + typedef void (*unspecified_bool_type)(D); // without the D, unspecified_bool_type + static void unspecified_bool_true(D){} // conversion allows relational operators + // between different identifier types + + operator unspecified_bool_type() const { return m_value == value_type() ? 0 : unspecified_bool_true; } + bool operator!() const { return m_value == value_type(); } + + // constructors are protected so that class can only be used as a base class + protected: + identifier() {} + explicit identifier( value_type v ) : m_value(v) {} + + #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // 1300 == VC++ 7.0 bug workaround + private: + #endif + T m_value; + }; + + //#ifndef BOOST_NO_SFINAE + + // template + // typename enable_if< is_base_of< identifier< typename Id::value_type, Id >, Id >, + // Ostream & >::type operator<<( Ostream & os, const Id & id ) + // { + // return os << id.value(); + // } + + // template + // typename enable_if< is_base_of< identifier< typename Id::value_type, Id >, Id >, + // Istream & >::type operator>>( Istream & is, Id & id ) + // { + // typename Id::value_type v; + // is >> v; + // id.value( v ); + // return is; + // } + //#endif + + } // namespace detail +} // namespace boost + +#endif // BOOST_IDENTIFIER_HPP diff --git a/win32/include/boost/detail/indirect_traits.hpp b/win32/include/boost/detail/indirect_traits.hpp new file mode 100755 index 000000000..a35b7cb86 --- /dev/null +++ b/win32/include/boost/detail/indirect_traits.hpp @@ -0,0 +1,487 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef INDIRECT_TRAITS_DWA2002131_HPP +# define INDIRECT_TRAITS_DWA2002131_HPP +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# include +# include + +# include +# include +# include +# include +# include +# include + +# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# include +# endif + +namespace boost { namespace detail { + +namespace indirect_traits { + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct is_reference_to_const : mpl::false_ +{ +}; + +template +struct is_reference_to_const : mpl::true_ +{ +}; + +# if defined(BOOST_MSVC) && _MSC_FULL_VER <= 13102140 // vc7.01 alpha workaround +template +struct is_reference_to_const : mpl::true_ +{ +}; +# endif + +template +struct is_reference_to_function : mpl::false_ +{ +}; + +template +struct is_reference_to_function : is_function +{ +}; + +template +struct is_pointer_to_function : mpl::false_ +{ +}; + +// There's no such thing as a pointer-to-cv-function, so we don't need +// specializations for those +template +struct is_pointer_to_function : is_function +{ +}; + +template +struct is_reference_to_member_function_pointer_impl : mpl::false_ +{ +}; + +template +struct is_reference_to_member_function_pointer_impl + : is_member_function_pointer::type> +{ +}; + + +template +struct is_reference_to_member_function_pointer + : is_reference_to_member_function_pointer_impl +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_reference_to_member_function_pointer,(T)) +}; + +template +struct is_reference_to_function_pointer_aux + : mpl::and_< + is_reference + , is_pointer_to_function< + typename remove_cv< + typename remove_reference::type + >::type + > + > +{ + // There's no such thing as a pointer-to-cv-function, so we don't need specializations for those +}; + +template +struct is_reference_to_function_pointer + : mpl::if_< + is_reference_to_function + , mpl::false_ + , is_reference_to_function_pointer_aux + >::type +{ +}; + +template +struct is_reference_to_non_const + : mpl::and_< + is_reference + , mpl::not_< + is_reference_to_const + > + > +{ +}; + +template +struct is_reference_to_volatile : mpl::false_ +{ +}; + +template +struct is_reference_to_volatile : mpl::true_ +{ +}; + +# if defined(BOOST_MSVC) && _MSC_FULL_VER <= 13102140 // vc7.01 alpha workaround +template +struct is_reference_to_volatile : mpl::true_ +{ +}; +# endif + + +template +struct is_reference_to_pointer : mpl::false_ +{ +}; + +template +struct is_reference_to_pointer : mpl::true_ +{ +}; + +template +struct is_reference_to_pointer : mpl::true_ +{ +}; + +template +struct is_reference_to_pointer : mpl::true_ +{ +}; + +template +struct is_reference_to_pointer : mpl::true_ +{ +}; + +template +struct is_reference_to_class + : mpl::and_< + is_reference + , is_class< + typename remove_cv< + typename remove_reference::type + >::type + > + > +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_reference_to_class,(T)) +}; + +template +struct is_pointer_to_class + : mpl::and_< + is_pointer + , is_class< + typename remove_cv< + typename remove_pointer::type + >::type + > + > +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_pointer_to_class,(T)) +}; + +# else + +using namespace boost::detail::is_function_ref_tester_; + +typedef char (&inner_yes_type)[3]; +typedef char (&inner_no_type)[2]; +typedef char (&outer_no_type)[1]; + +template +struct is_const_help +{ + typedef typename mpl::if_< + is_const + , inner_yes_type + , inner_no_type + >::type type; +}; + +template +struct is_volatile_help +{ + typedef typename mpl::if_< + is_volatile + , inner_yes_type + , inner_no_type + >::type type; +}; + +template +struct is_pointer_help +{ + typedef typename mpl::if_< + is_pointer + , inner_yes_type + , inner_no_type + >::type type; +}; + +template +struct is_class_help +{ + typedef typename mpl::if_< + is_class + , inner_yes_type + , inner_no_type + >::type type; +}; + +template +struct is_reference_to_function_aux +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value = sizeof(detail::is_function_ref_tester(t,0)) == sizeof(::boost::type_traits::yes_type)); + typedef mpl::bool_ type; + }; + +template +struct is_reference_to_function + : mpl::if_, is_reference_to_function_aux, mpl::bool_ >::type +{ +}; + +template +struct is_pointer_to_function_aux +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof(::boost::type_traits::is_function_ptr_tester(t)) == sizeof(::boost::type_traits::yes_type)); + typedef mpl::bool_ type; +}; + +template +struct is_pointer_to_function + : mpl::if_, is_pointer_to_function_aux, mpl::bool_ >::type +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_pointer_to_function,(T)) +}; + +struct false_helper1 +{ + template + struct apply : mpl::false_ + { + }; +}; + +template +typename is_const_help::type reference_to_const_helper(V&); +outer_no_type +reference_to_const_helper(...); + +struct true_helper1 +{ + template + struct apply + { + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof(reference_to_const_helper(t)) == sizeof(inner_yes_type)); + typedef mpl::bool_ type; + }; +}; + +template +struct is_reference_to_const_helper1 : true_helper1 +{ +}; + +template <> +struct is_reference_to_const_helper1 : false_helper1 +{ +}; + + +template +struct is_reference_to_const + : is_reference_to_const_helper1::value>::template apply +{ +}; + + +template +struct is_reference_to_non_const_helper1 +{ + template + struct apply + { + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof(reference_to_const_helper(t)) == sizeof(inner_no_type)); + + typedef mpl::bool_ type; + }; +}; + +template <> +struct is_reference_to_non_const_helper1 : false_helper1 +{ +}; + + +template +struct is_reference_to_non_const + : is_reference_to_non_const_helper1::value>::template apply +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_reference_to_non_const,(T)) +}; + + +template +typename is_volatile_help::type reference_to_volatile_helper(V&); +outer_no_type +reference_to_volatile_helper(...); + +template +struct is_reference_to_volatile_helper1 +{ + template + struct apply + { + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof(reference_to_volatile_helper(t)) == sizeof(inner_yes_type)); + typedef mpl::bool_ type; + }; +}; + +template <> +struct is_reference_to_volatile_helper1 : false_helper1 +{ +}; + + +template +struct is_reference_to_volatile + : is_reference_to_volatile_helper1::value>::template apply +{ +}; + +template +typename is_pointer_help::type reference_to_pointer_helper(V&); +outer_no_type reference_to_pointer_helper(...); + +template +struct reference_to_pointer_impl +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = (sizeof((reference_to_pointer_helper)(t)) == sizeof(inner_yes_type)) + ); + + typedef mpl::bool_ type; +}; + +template +struct is_reference_to_pointer + : mpl::eval_if, reference_to_pointer_impl, mpl::false_>::type +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_reference_to_pointer,(T)) +}; + +template +struct is_reference_to_function_pointer + : mpl::eval_if, is_pointer_to_function_aux, mpl::false_>::type +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_reference_to_function_pointer,(T)) +}; + + +template +struct is_member_function_pointer_help + : mpl::if_, inner_yes_type, inner_no_type> +{}; + +template +typename is_member_function_pointer_help::type member_function_pointer_helper(V&); +outer_no_type member_function_pointer_helper(...); + +template +struct is_pointer_to_member_function_aux +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = sizeof((member_function_pointer_helper)(t)) == sizeof(inner_yes_type)); + typedef mpl::bool_ type; +}; + +template +struct is_reference_to_member_function_pointer + : mpl::if_< + is_reference + , is_pointer_to_member_function_aux + , mpl::bool_ + >::type +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_reference_to_member_function_pointer,(T)) +}; + +template +typename is_class_help::type reference_to_class_helper(V const volatile&); +outer_no_type reference_to_class_helper(...); + +template +struct is_reference_to_class +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = (is_reference::value + & (sizeof(reference_to_class_helper(t)) == sizeof(inner_yes_type))) + ); + typedef mpl::bool_ type; + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_reference_to_class,(T)) +}; + +template +typename is_class_help::type pointer_to_class_helper(V const volatile*); +outer_no_type pointer_to_class_helper(...); + +template +struct is_pointer_to_class +{ + static T t; + BOOST_STATIC_CONSTANT( + bool, value + = (is_pointer::value + && sizeof(pointer_to_class_helper(t)) == sizeof(inner_yes_type)) + ); + typedef mpl::bool_ type; +}; +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +} + +using namespace indirect_traits; + +}} // namespace boost::python::detail + +#endif // INDIRECT_TRAITS_DWA2002131_HPP diff --git a/win32/include/boost/detail/interlocked.hpp b/win32/include/boost/detail/interlocked.hpp new file mode 100755 index 000000000..47da18822 --- /dev/null +++ b/win32/include/boost/detail/interlocked.hpp @@ -0,0 +1,130 @@ +#ifndef BOOST_DETAIL_INTERLOCKED_HPP_INCLUDED +#define BOOST_DETAIL_INTERLOCKED_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/interlocked.hpp +// +// Copyright 2005 Peter Dimov +// +// 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) +// + +#include + +#if defined( BOOST_USE_WINDOWS_H ) + +# include + +# define BOOST_INTERLOCKED_INCREMENT InterlockedIncrement +# define BOOST_INTERLOCKED_DECREMENT InterlockedDecrement +# define BOOST_INTERLOCKED_COMPARE_EXCHANGE InterlockedCompareExchange +# define BOOST_INTERLOCKED_EXCHANGE InterlockedExchange +# define BOOST_INTERLOCKED_EXCHANGE_ADD InterlockedExchangeAdd +# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER InterlockedCompareExchangePointer +# define BOOST_INTERLOCKED_EXCHANGE_POINTER InterlockedExchangePointer + +#elif defined(_WIN32_WCE) + +// under Windows CE we still have old-style Interlocked* functions + +extern "C" long __cdecl InterlockedIncrement( long* ); +extern "C" long __cdecl InterlockedDecrement( long* ); +extern "C" long __cdecl InterlockedCompareExchange( long*, long, long ); +extern "C" long __cdecl InterlockedExchange( long*, long ); +extern "C" long __cdecl InterlockedExchangeAdd( long*, long ); + +# define BOOST_INTERLOCKED_INCREMENT InterlockedIncrement +# define BOOST_INTERLOCKED_DECREMENT InterlockedDecrement +# define BOOST_INTERLOCKED_COMPARE_EXCHANGE InterlockedCompareExchange +# define BOOST_INTERLOCKED_EXCHANGE InterlockedExchange +# define BOOST_INTERLOCKED_EXCHANGE_ADD InterlockedExchangeAdd + +# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest,exchange,compare) \ + ((void*)BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)(dest),(long)(exchange),(long)(compare))) +# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest,exchange) \ + ((void*)BOOST_INTERLOCKED_EXCHANGE((long*)(dest),(long)(exchange))) + +#elif defined( BOOST_MSVC ) || defined( BOOST_INTEL_WIN ) + +extern "C" long __cdecl _InterlockedIncrement( long volatile * ); +extern "C" long __cdecl _InterlockedDecrement( long volatile * ); +extern "C" long __cdecl _InterlockedCompareExchange( long volatile *, long, long ); +extern "C" long __cdecl _InterlockedExchange( long volatile *, long); +extern "C" long __cdecl _InterlockedExchangeAdd( long volatile *, long); + +# pragma intrinsic( _InterlockedIncrement ) +# pragma intrinsic( _InterlockedDecrement ) +# pragma intrinsic( _InterlockedCompareExchange ) +# pragma intrinsic( _InterlockedExchange ) +# pragma intrinsic( _InterlockedExchangeAdd ) + +# if defined(_M_IA64) || defined(_M_AMD64) + +extern "C" void* __cdecl _InterlockedCompareExchangePointer( void* volatile *, void*, void* ); +extern "C" void* __cdecl _InterlockedExchangePointer( void* volatile *, void* ); + +# pragma intrinsic( _InterlockedCompareExchangePointer ) +# pragma intrinsic( _InterlockedExchangePointer ) + +# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER _InterlockedCompareExchangePointer +# define BOOST_INTERLOCKED_EXCHANGE_POINTER _InterlockedExchangePointer + +# else + +# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest,exchange,compare) \ + ((void*)BOOST_INTERLOCKED_COMPARE_EXCHANGE((long volatile*)(dest),(long)(exchange),(long)(compare))) +# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest,exchange) \ + ((void*)BOOST_INTERLOCKED_EXCHANGE((long volatile*)(dest),(long)(exchange))) + +# endif + +# define BOOST_INTERLOCKED_INCREMENT _InterlockedIncrement +# define BOOST_INTERLOCKED_DECREMENT _InterlockedDecrement +# define BOOST_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange +# define BOOST_INTERLOCKED_EXCHANGE _InterlockedExchange +# define BOOST_INTERLOCKED_EXCHANGE_ADD _InterlockedExchangeAdd + +#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) + +namespace boost +{ + +namespace detail +{ + +extern "C" __declspec(dllimport) long __stdcall InterlockedIncrement( long volatile * ); +extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement( long volatile * ); +extern "C" __declspec(dllimport) long __stdcall InterlockedCompareExchange( long volatile *, long, long ); +extern "C" __declspec(dllimport) long __stdcall InterlockedExchange( long volatile *, long ); +extern "C" __declspec(dllimport) long __stdcall InterlockedExchangeAdd( long volatile *, long ); + +} // namespace detail + +} // namespace boost + +# define BOOST_INTERLOCKED_INCREMENT ::boost::detail::InterlockedIncrement +# define BOOST_INTERLOCKED_DECREMENT ::boost::detail::InterlockedDecrement +# define BOOST_INTERLOCKED_COMPARE_EXCHANGE ::boost::detail::InterlockedCompareExchange +# define BOOST_INTERLOCKED_EXCHANGE ::boost::detail::InterlockedExchange +# define BOOST_INTERLOCKED_EXCHANGE_ADD ::boost::detail::InterlockedExchangeAdd + +# define BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest,exchange,compare) \ + ((void*)BOOST_INTERLOCKED_COMPARE_EXCHANGE((long volatile*)(dest),(long)(exchange),(long)(compare))) +# define BOOST_INTERLOCKED_EXCHANGE_POINTER(dest,exchange) \ + ((void*)BOOST_INTERLOCKED_EXCHANGE((long volatile*)(dest),(long)(exchange))) + +#else + +# error "Interlocked intrinsics not available" + +#endif + +#endif // #ifndef BOOST_DETAIL_INTERLOCKED_HPP_INCLUDED diff --git a/win32/include/boost/detail/is_function_ref_tester.hpp b/win32/include/boost/detail/is_function_ref_tester.hpp new file mode 100755 index 000000000..833cdf34b --- /dev/null +++ b/win32/include/boost/detail/is_function_ref_tester.hpp @@ -0,0 +1,135 @@ + +// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, +// Aleksey Gurtovoy, Howard Hinnant & John Maddock 2000. +// 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_PP_IS_ITERATING) + +///// header body + +#ifndef BOOST_DETAIL_IS_FUNCTION_REF_TESTER_HPP_INCLUDED +#define BOOST_DETAIL_IS_FUNCTION_REF_TESTER_HPP_INCLUDED + +#include "boost/type_traits/detail/yes_no_type.hpp" +#include "boost/type_traits/config.hpp" + +#if defined(BOOST_TT_PREPROCESSING_MODE) +# include "boost/preprocessor/iterate.hpp" +# include "boost/preprocessor/enum_params.hpp" +# include "boost/preprocessor/comma_if.hpp" +#endif + +namespace boost { +namespace detail { +namespace is_function_ref_tester_ { + +template +boost::type_traits::no_type BOOST_TT_DECL is_function_ref_tester(T& ...); + +#if !defined(BOOST_TT_PREPROCESSING_MODE) +// preprocessor-generated part, don't edit by hand! + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23), int); + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24), int); + +#else + +#define BOOST_PP_ITERATION_PARAMS_1 \ + (3, (0, 25, "boost/type_traits/detail/is_function_ref_tester.hpp")) +#include BOOST_PP_ITERATE() + +#endif // BOOST_TT_PREPROCESSING_MODE + +} // namespace detail +} // namespace python +} // namespace boost + +#endif // BOOST_DETAIL_IS_FUNCTION_REF_TESTER_HPP_INCLUDED + +///// iteration + +#else +#define i BOOST_PP_FRAME_ITERATION(1) + +template +boost::type_traits::yes_type is_function_ref_tester(R (&)(BOOST_PP_ENUM_PARAMS(i,T)), int); + +#undef i +#endif // BOOST_PP_IS_ITERATING diff --git a/win32/include/boost/detail/is_incrementable.hpp b/win32/include/boost/detail/is_incrementable.hpp new file mode 100755 index 000000000..e64d2c5f2 --- /dev/null +++ b/win32/include/boost/detail/is_incrementable.hpp @@ -0,0 +1,124 @@ +// Copyright David Abrahams 2004. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef IS_INCREMENTABLE_DWA200415_HPP +# define IS_INCREMENTABLE_DWA200415_HPP + +# include +# include +# include +# include +# include + +// Must be the last include +# include + +namespace boost { namespace detail { + +// is_incrementable metafunction +// +// Requires: Given x of type T&, if the expression ++x is well-formed +// it must have complete type; otherwise, it must neither be ambiguous +// nor violate access. + +// This namespace ensures that ADL doesn't mess things up. +namespace is_incrementable_ +{ + // a type returned from operator++ when no increment is found in the + // type's own namespace + struct tag {}; + + // any soaks up implicit conversions and makes the following + // operator++ less-preferred than any other such operator that + // might be found via ADL. + struct any { template any(T const&); }; + + // This is a last-resort operator++ for when none other is found +# if BOOST_WORKAROUND(__GNUC__, == 4) && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 2 + +} + +namespace is_incrementable_2 +{ + is_incrementable_::tag operator++(is_incrementable_::any const&); + is_incrementable_::tag operator++(is_incrementable_::any const&,int); +} +using namespace is_incrementable_2; + +namespace is_incrementable_ +{ + +# else + + tag operator++(any const&); + tag operator++(any const&,int); + +# endif + +# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3202)) \ + || BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +# define BOOST_comma(a,b) (a) +# else + // In case an operator++ is found that returns void, we'll use ++x,0 + tag operator,(tag,int); +# define BOOST_comma(a,b) (a,b) +# endif + + // two check overloads help us identify which operator++ was picked + char (& check(tag) )[2]; + + template + char check(T const&); + + + template + struct impl + { + static typename boost::remove_cv::type& x; + + BOOST_STATIC_CONSTANT( + bool + , value = sizeof(is_incrementable_::check(BOOST_comma(++x,0))) == 1 + ); + }; + + template + struct postfix_impl + { + static typename boost::remove_cv::type& x; + + BOOST_STATIC_CONSTANT( + bool + , value = sizeof(is_incrementable_::check(BOOST_comma(x++,0))) == 1 + ); + }; +} + +# undef BOOST_comma + +template +struct is_incrementable +BOOST_TT_AUX_BOOL_C_BASE(::boost::detail::is_incrementable_::impl::value) +{ + BOOST_TT_AUX_BOOL_TRAIT_VALUE_DECL(::boost::detail::is_incrementable_::impl::value) + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_incrementable,(T)) +}; + +template +struct is_postfix_incrementable +BOOST_TT_AUX_BOOL_C_BASE(::boost::detail::is_incrementable_::impl::value) +{ + BOOST_TT_AUX_BOOL_TRAIT_VALUE_DECL(::boost::detail::is_incrementable_::postfix_impl::value) + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_postfix_incrementable,(T)) +}; + +} // namespace detail + +BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1, ::boost::detail::is_incrementable) +BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1, ::boost::detail::is_postfix_incrementable) + +} // namespace boost + +# include + +#endif // IS_INCREMENTABLE_DWA200415_HPP diff --git a/win32/include/boost/detail/is_xxx.hpp b/win32/include/boost/detail/is_xxx.hpp new file mode 100755 index 000000000..60fd28b72 --- /dev/null +++ b/win32/include/boost/detail/is_xxx.hpp @@ -0,0 +1,61 @@ +// Copyright David Abrahams 2005. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_DETAIL_IS_XXX_DWA20051011_HPP +# define BOOST_DETAIL_IS_XXX_DWA20051011_HPP + +# include +# include +# include + +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +# include +# include + +# define BOOST_DETAIL_IS_XXX_DEF(name, qualified_name, nargs) \ +template \ +struct is_##name \ +{ \ + typedef char yes; \ + typedef char (&no)[2]; \ + \ + static typename add_reference::type dummy; \ + \ + struct helpers \ + { \ + template < BOOST_PP_ENUM_PARAMS_Z(1, nargs, class U) > \ + static yes test( \ + qualified_name< BOOST_PP_ENUM_PARAMS_Z(1, nargs, U) >&, int \ + ); \ + \ + template \ + static no test(U&, ...); \ + }; \ + \ + BOOST_STATIC_CONSTANT( \ + bool, value \ + = !is_reference::value \ + & (sizeof(helpers::test(dummy, 0)) == sizeof(yes))); \ + \ + typedef mpl::bool_ type; \ +}; + +# else + +# define BOOST_DETAIL_IS_XXX_DEF(name, qualified_name, nargs) \ +template \ +struct is_##name : mpl::false_ \ +{ \ +}; \ + \ +template < BOOST_PP_ENUM_PARAMS_Z(1, nargs, class T) > \ +struct is_##name< \ + qualified_name< BOOST_PP_ENUM_PARAMS_Z(1, nargs, T) > \ +> \ + : mpl::true_ \ +{ \ +}; + +# endif + +#endif // BOOST_DETAIL_IS_XXX_DWA20051011_HPP diff --git a/win32/include/boost/detail/iterator.hpp b/win32/include/boost/detail/iterator.hpp new file mode 100755 index 000000000..48345e88b --- /dev/null +++ b/win32/include/boost/detail/iterator.hpp @@ -0,0 +1,494 @@ +// (C) Copyright David Abrahams 2002. +// 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) + +// Boost versions of +// +// std::iterator_traits<>::iterator_category +// std::iterator_traits<>::difference_type +// std::distance() +// +// ...for all compilers and iterators +// +// Additionally, if X is a pointer +// std::iterator_traits::pointer + +// Otherwise, if partial specialization is supported or X is not a pointer +// std::iterator_traits::value_type +// std::iterator_traits::pointer +// std::iterator_traits::reference +// +// See http://www.boost.org for most recent version including documentation. + +// Revision History +// 04 Mar 2001 - More attempted fixes for Intel C++ (David Abrahams) +// 03 Mar 2001 - Put all implementation into namespace +// boost::detail::iterator_traits_. Some progress made on fixes +// for Intel compiler. (David Abrahams) +// 02 Mar 2001 - Changed BOOST_MSVC to BOOST_MSVC_STD_ITERATOR in a few +// places. (Jeremy Siek) +// 19 Feb 2001 - Improved workarounds for stock MSVC6; use yes_type and +// no_type from type_traits.hpp; stopped trying to remove_cv +// before detecting is_pointer, in honor of the new type_traits +// semantics. (David Abrahams) +// 13 Feb 2001 - Make it work with nearly all standard-conforming iterators +// under raw VC6. The one category remaining which will fail is +// that of iterators derived from std::iterator but not +// boost::iterator and which redefine difference_type. +// 11 Feb 2001 - Clean away code which can never be used (David Abrahams) +// 09 Feb 2001 - Always have a definition for each traits member, even if it +// can't be properly deduced. These will be incomplete types in +// some cases (undefined), but it helps suppress MSVC errors +// elsewhere (David Abrahams) +// 07 Feb 2001 - Support for more of the traits members where possible, making +// this useful as a replacement for std::iterator_traits when +// used as a default template parameter. +// 06 Feb 2001 - Removed useless #includes of standard library headers +// (David Abrahams) + +#ifndef ITERATOR_DWA122600_HPP_ +# define ITERATOR_DWA122600_HPP_ + +# include +# include + +// STLPort 4.0 and betas have a bug when debugging is enabled and there is no +// partial specialization: instead of an iterator_category typedef, the standard +// container iterators have _Iterator_category. +// +// Also, whether debugging is enabled or not, there is a broken specialization +// of std::iterator which has no +// typedefs but iterator_category. +# if defined(__SGI_STL_PORT) + +# if (__SGI_STL_PORT <= 0x410) && !defined(__STL_CLASS_PARTIAL_SPECIALIZATION) && defined(__STL_DEBUG) +# define BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF +# endif + +# define BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION + +# endif // STLPort <= 4.1b4 && no partial specialization + +# if !defined(BOOST_NO_STD_ITERATOR_TRAITS) \ + && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_MSVC_STD_ITERATOR) + +namespace boost { namespace detail { + +// Define a new template so it can be specialized +template +struct iterator_traits + : std::iterator_traits +{}; +using std::distance; + +}} // namespace boost::detail + +# else + +# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_MSVC_STD_ITERATOR) + +// This is the case where everything conforms except BOOST_NO_STD_ITERATOR_TRAITS + +namespace boost { namespace detail { + +// Rogue Wave Standard Library fools itself into thinking partial +// specialization is missing on some platforms (e.g. Sun), so fails to +// supply iterator_traits! +template +struct iterator_traits +{ + typedef typename Iterator::value_type value_type; + typedef typename Iterator::reference reference; + typedef typename Iterator::pointer pointer; + typedef typename Iterator::difference_type difference_type; + typedef typename Iterator::iterator_category iterator_category; +}; + +template +struct iterator_traits +{ + typedef T value_type; + typedef T& reference; + typedef T* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; +}; + +template +struct iterator_traits +{ + typedef T value_type; + typedef T const& reference; + typedef T const* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; +}; + +}} // namespace boost::detail + +# else + +# include +# include +# include + +# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# include +# include +# endif +# ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION +# include +# endif + +# include +# include +# include + +// should be the last #include +# include "boost/type_traits/detail/bool_trait_def.hpp" + +namespace boost { namespace detail { + +BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type) +BOOST_MPL_HAS_XXX_TRAIT_DEF(reference) +BOOST_MPL_HAS_XXX_TRAIT_DEF(pointer) +BOOST_MPL_HAS_XXX_TRAIT_DEF(difference_type) +BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator_category) + +// is_mutable_iterator -- +// +// A metafunction returning true iff T is a mutable iterator type +// with a nested value_type. Will only work portably with iterators +// whose operator* returns a reference, but that seems to be OK for +// the iterators supplied by Dinkumware. Some input iterators may +// compile-time if they arrive here, and if the compiler is strict +// about not taking the address of an rvalue. + +// This one detects ordinary mutable iterators - the result of +// operator* is convertible to the value_type. +template +type_traits::yes_type is_mutable_iterator_helper(T const*, BOOST_DEDUCED_TYPENAME T::value_type*); + +// Since you can't take the address of an rvalue, the guts of +// is_mutable_iterator_impl will fail if we use &*t directly. This +// makes sure we can still work with non-lvalue iterators. +template T* mutable_iterator_lvalue_helper(T& x); +int mutable_iterator_lvalue_helper(...); + + +// This one detects output iterators such as ostream_iterator which +// return references to themselves. +template +type_traits::yes_type is_mutable_iterator_helper(T const*, T const*); + +type_traits::no_type is_mutable_iterator_helper(...); + +template +struct is_mutable_iterator_impl +{ + static T t; + + BOOST_STATIC_CONSTANT( + bool, value = sizeof( + detail::is_mutable_iterator_helper( + (T*)0 + , mutable_iterator_lvalue_helper(*t) // like &*t + )) + == sizeof(type_traits::yes_type) + ); +}; + +BOOST_TT_AUX_BOOL_TRAIT_DEF1( + is_mutable_iterator,T,::boost::detail::is_mutable_iterator_impl::value) + + +// is_full_iterator_traits -- +// +// A metafunction returning true iff T has all the requisite nested +// types to satisfy the requirements for a fully-conforming +// iterator_traits implementation. +template +struct is_full_iterator_traits_impl +{ + enum { value = + has_value_type::value + & has_reference::value + & has_pointer::value + & has_difference_type::value + & has_iterator_category::value + }; +}; + +BOOST_TT_AUX_BOOL_TRAIT_DEF1( + is_full_iterator_traits,T,::boost::detail::is_full_iterator_traits_impl::value) + + +# ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF +BOOST_MPL_HAS_XXX_TRAIT_DEF(_Iterator_category) + +// is_stlport_40_debug_iterator -- +// +// A metafunction returning true iff T has all the requisite nested +// types to satisfy the requirements of an STLPort 4.0 debug iterator +// iterator_traits implementation. +template +struct is_stlport_40_debug_iterator_impl +{ + enum { value = + has_value_type::value + & has_reference::value + & has_pointer::value + & has_difference_type::value + & has__Iterator_category::value + }; +}; + +BOOST_TT_AUX_BOOL_TRAIT_DEF1( + is_stlport_40_debug_iterator,T,::boost::detail::is_stlport_40_debug_iterator_impl::value) + +template +struct stlport_40_debug_iterator_traits +{ + typedef typename T::value_type value_type; + typedef typename T::reference reference; + typedef typename T::pointer pointer; + typedef typename T::difference_type difference_type; + typedef typename T::_Iterator_category iterator_category; +}; +# endif // BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF + +template struct pointer_iterator_traits; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct pointer_iterator_traits +{ + typedef typename remove_const::type value_type; + typedef T* pointer; + typedef T& reference; + typedef std::random_access_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; +}; +# else + +// In case of no template partial specialization, and if T is a +// pointer, iterator_traits::value_type can still be computed. For +// some basic types, remove_pointer is manually defined in +// type_traits/broken_compiler_spec.hpp. For others, do it yourself. + +template class please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee; + +template +struct pointer_value_type + : mpl::if_< + is_same::type> + , please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee

+ , typename remove_const< + typename remove_pointer

::type + >::type + > +{ +}; + + +template +struct pointer_reference + : mpl::if_< + is_same::type> + , please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee

+ , typename remove_pointer

::type& + > +{ +}; + +template +struct pointer_iterator_traits +{ + typedef T pointer; + typedef std::random_access_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + + typedef typename pointer_value_type::type value_type; + typedef typename pointer_reference::type reference; +}; + +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +// We'll sort iterator types into one of these classifications, from which we +// can determine the difference_type, pointer, reference, and value_type +template +struct standard_iterator_traits +{ + typedef typename Iterator::difference_type difference_type; + typedef typename Iterator::value_type value_type; + typedef typename Iterator::pointer pointer; + typedef typename Iterator::reference reference; + typedef typename Iterator::iterator_category iterator_category; +}; + +template +struct msvc_stdlib_mutable_traits + : std::iterator_traits +{ + typedef typename std::iterator_traits::distance_type difference_type; + typedef typename std::iterator_traits::value_type* pointer; + typedef typename std::iterator_traits::value_type& reference; +}; + +template +struct msvc_stdlib_const_traits + : std::iterator_traits +{ + typedef typename std::iterator_traits::distance_type difference_type; + typedef const typename std::iterator_traits::value_type* pointer; + typedef const typename std::iterator_traits::value_type& reference; +}; + +# ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION +template +struct is_bad_output_iterator + : is_base_and_derived< + std::iterator + , Iterator> +{ +}; + +struct bad_output_iterator_traits +{ + typedef void value_type; + typedef void difference_type; + typedef std::output_iterator_tag iterator_category; + typedef void pointer; + typedef void reference; +}; +# endif + +// If we're looking at an MSVC6 (old Dinkumware) ``standard'' +// iterator, this will generate an appropriate traits class. +template +struct msvc_stdlib_iterator_traits + : mpl::if_< + is_mutable_iterator + , msvc_stdlib_mutable_traits + , msvc_stdlib_const_traits + >::type +{}; + +template +struct non_pointer_iterator_traits + : mpl::if_< + // if the iterator contains all the right nested types... + is_full_iterator_traits + // Use a standard iterator_traits implementation + , standard_iterator_traits +# ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF + // Check for STLPort 4.0 broken _Iterator_category type + , mpl::if_< + is_stlport_40_debug_iterator + , stlport_40_debug_iterator_traits +# endif + // Otherwise, assume it's a Dinkum iterator + , msvc_stdlib_iterator_traits +# ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF + >::type +# endif + >::type +{ +}; + +template +struct iterator_traits_aux + : mpl::if_< + is_pointer + , pointer_iterator_traits + , non_pointer_iterator_traits + >::type +{ +}; + +template +struct iterator_traits +{ + // Explicit forwarding from base class needed to keep MSVC6 happy + // under some circumstances. + private: +# ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION + typedef + typename mpl::if_< + is_bad_output_iterator + , bad_output_iterator_traits + , iterator_traits_aux + >::type base; +# else + typedef iterator_traits_aux base; +# endif + public: + typedef typename base::value_type value_type; + typedef typename base::pointer pointer; + typedef typename base::reference reference; + typedef typename base::difference_type difference_type; + typedef typename base::iterator_category iterator_category; +}; + +// This specialization cuts off ETI (Early Template Instantiation) for MSVC. +template <> struct iterator_traits +{ + typedef int value_type; + typedef int pointer; + typedef int reference; + typedef int difference_type; + typedef int iterator_category; +}; + +}} // namespace boost::detail + +# endif // workarounds + +namespace boost { namespace detail { + +namespace iterator_traits_ +{ + template + struct distance_select + { + static Difference execute(Iterator i1, const Iterator i2, ...) + { + Difference result = 0; + while (i1 != i2) + { + ++i1; + ++result; + } + return result; + } + + static Difference execute(Iterator i1, const Iterator i2, std::random_access_iterator_tag*) + { + return i2 - i1; + } + }; +} // namespace boost::detail::iterator_traits_ + +template +inline typename iterator_traits::difference_type +distance(Iterator first, Iterator last) +{ + typedef typename iterator_traits::difference_type diff_t; + typedef typename ::boost::detail::iterator_traits::iterator_category iterator_category; + + return iterator_traits_::distance_select::execute( + first, last, (iterator_category*)0); +} + +}} + +# endif + + +# undef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF +# undef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION + +#endif // ITERATOR_DWA122600_HPP_ diff --git a/win32/include/boost/detail/lcast_precision.hpp b/win32/include/boost/detail/lcast_precision.hpp new file mode 100755 index 000000000..895790e79 --- /dev/null +++ b/win32/include/boost/detail/lcast_precision.hpp @@ -0,0 +1,184 @@ +// Copyright Alexander Nasonov & Paul A. Bristow 2006. + +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED +#define BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED + +#include +#include +#include + +#include +#include + +#ifndef BOOST_NO_IS_ABSTRACT +// Fix for SF:1358600 - lexical_cast & pure virtual functions & VC 8 STL +#include +#include +#endif + +#if defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || \ + (defined(BOOST_MSVC) && (BOOST_MSVC<1310)) + +#define BOOST_LCAST_NO_COMPILE_TIME_PRECISION +#endif + +#ifdef BOOST_LCAST_NO_COMPILE_TIME_PRECISION +#include +#else +#include +#endif + +namespace boost { namespace detail { + +class lcast_abstract_stub {}; + +#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION +// Calculate an argument to pass to std::ios_base::precision from +// lexical_cast. See alternative implementation for broken standard +// libraries in lcast_get_precision below. Keep them in sync, please. +template +struct lcast_precision +{ +#ifdef BOOST_NO_IS_ABSTRACT + typedef std::numeric_limits limits; // No fix for SF:1358600. +#else + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< + boost::is_abstract + , std::numeric_limits + , std::numeric_limits + >::type limits; +#endif + + BOOST_STATIC_CONSTANT(bool, use_default_precision = + !limits::is_specialized || limits::is_exact + ); + + BOOST_STATIC_CONSTANT(bool, is_specialized_bin = + !use_default_precision && + limits::radix == 2 && limits::digits > 0 + ); + + BOOST_STATIC_CONSTANT(bool, is_specialized_dec = + !use_default_precision && + limits::radix == 10 && limits::digits10 > 0 + ); + + BOOST_STATIC_CONSTANT(std::streamsize, streamsize_max = + boost::integer_traits::const_max + ); + + BOOST_STATIC_CONSTANT(unsigned int, precision_dec = limits::digits10 + 1U); + + BOOST_STATIC_ASSERT(!is_specialized_dec || + precision_dec <= streamsize_max + 0UL + ); + + BOOST_STATIC_CONSTANT(unsigned long, precision_bin = + 2UL + limits::digits * 30103UL / 100000UL + ); + + BOOST_STATIC_ASSERT(!is_specialized_bin || + (limits::digits + 0UL < ULONG_MAX / 30103UL && + precision_bin > limits::digits10 + 0UL && + precision_bin <= streamsize_max + 0UL) + ); + + BOOST_STATIC_CONSTANT(std::streamsize, value = + is_specialized_bin ? precision_bin + : is_specialized_dec ? precision_dec : 6 + ); +}; +#endif + +template +inline std::streamsize lcast_get_precision(T* = 0) +{ +#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION + return lcast_precision::value; +#else // Follow lcast_precision algorithm at run-time: + +#ifdef BOOST_NO_IS_ABSTRACT + typedef std::numeric_limits limits; // No fix for SF:1358600. +#else + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< + boost::is_abstract + , std::numeric_limits + , std::numeric_limits + >::type limits; +#endif + + bool const use_default_precision = + !limits::is_specialized || limits::is_exact; + + if(!use_default_precision) + { // Includes all built-in floating-point types, float, double ... + // and UDT types for which digits (significand bits) is defined (not zero) + + bool const is_specialized_bin = + limits::radix == 2 && limits::digits > 0; + bool const is_specialized_dec = + limits::radix == 10 && limits::digits10 > 0; + std::streamsize const streamsize_max = + (boost::integer_traits::max)(); + + if(is_specialized_bin) + { // Floating-point types with + // limits::digits defined by the specialization. + + unsigned long const digits = limits::digits; + unsigned long const precision = 2UL + digits * 30103UL / 100000UL; + // unsigned long is selected because it is at least 32-bits + // and thus ULONG_MAX / 30103UL is big enough for all types. + BOOST_ASSERT( + digits < ULONG_MAX / 30103UL && + precision > limits::digits10 + 0UL && + precision <= streamsize_max + 0UL + ); + return precision; + } + else if(is_specialized_dec) + { // Decimal Floating-point type, most likely a User Defined Type + // rather than a real floating-point hardware type. + unsigned int const precision = limits::digits10 + 1U; + BOOST_ASSERT(precision <= streamsize_max + 0UL); + return precision; + } + } + + // Integral type (for which precision has no effect) + // or type T for which limits is NOT specialized, + // so assume stream precision remains the default 6 decimal digits. + // Warning: if your User-defined Floating-point type T is NOT specialized, + // then you may lose accuracy by only using 6 decimal digits. + // To avoid this, you need to specialize T with either + // radix == 2 and digits == the number of significand bits, + // OR + // radix = 10 and digits10 == the number of decimal digits. + + return 6; +#endif +} + +template +inline void lcast_set_precision(std::ios_base& stream, T*) +{ + stream.precision(lcast_get_precision()); +} + +template +inline void lcast_set_precision(std::ios_base& stream, Source*, Target*) +{ + std::streamsize const s = lcast_get_precision((Source*)0); + std::streamsize const t = lcast_get_precision((Target*)0); + stream.precision(s > t ? s : t); +} + +}} + +#endif // BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED + diff --git a/win32/include/boost/detail/lightweight_mutex.hpp b/win32/include/boost/detail/lightweight_mutex.hpp new file mode 100755 index 000000000..a6b758464 --- /dev/null +++ b/win32/include/boost/detail/lightweight_mutex.hpp @@ -0,0 +1,42 @@ +#ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED +#define BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/lightweight_mutex.hpp - lightweight mutex +// +// Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd. +// +// 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) +// +// typedef boost::detail::lightweight_mutex; +// +// boost::detail::lightweight_mutex is a header-only implementation of +// a subset of the Mutex concept requirements: +// +// http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex +// +// It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX. +// + +#include + +#if !defined(BOOST_HAS_THREADS) +# include +#elif defined(BOOST_HAS_PTHREADS) +# include +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# include +#else +// Use #define BOOST_DISABLE_THREADS to avoid the error +# error Unrecognized threading platform +#endif + +#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED diff --git a/win32/include/boost/detail/lightweight_test.hpp b/win32/include/boost/detail/lightweight_test.hpp new file mode 100755 index 000000000..57292cbb4 --- /dev/null +++ b/win32/include/boost/detail/lightweight_test.hpp @@ -0,0 +1,75 @@ +#ifndef BOOST_DETAIL_LIGHTWEIGHT_TEST_HPP_INCLUDED +#define BOOST_DETAIL_LIGHTWEIGHT_TEST_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/lightweight_test.hpp - lightweight test library +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// 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) +// +// BOOST_TEST(expression) +// BOOST_ERROR(message) +// +// int boost::report_errors() +// + +#include +#include + +namespace boost +{ + +namespace detail +{ + +inline int & test_errors() +{ + static int x = 0; + return x; +} + +inline void test_failed_impl(char const * expr, char const * file, int line, char const * function) +{ + std::cerr << file << "(" << line << "): test '" << expr << "' failed in function '" << function << "'" << std::endl; + ++test_errors(); +} + +inline void error_impl(char const * msg, char const * file, int line, char const * function) +{ + std::cerr << file << "(" << line << "): " << msg << " in function '" << function << "'" << std::endl; + ++test_errors(); +} + +} // namespace detail + +inline int report_errors() +{ + int errors = detail::test_errors(); + + if(errors == 0) + { + std::cerr << "No errors detected." << std::endl; + return 0; + } + else + { + std::cerr << errors << " error" << (errors == 1? "": "s") << " detected." << std::endl; + return 1; + } +} + +} // namespace boost + +#define BOOST_TEST(expr) ((expr)? (void)0: ::boost::detail::test_failed_impl(#expr, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION)) +#define BOOST_ERROR(msg) ::boost::detail::error_impl(msg, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) + +#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_TEST_HPP_INCLUDED diff --git a/win32/include/boost/detail/lightweight_thread.hpp b/win32/include/boost/detail/lightweight_thread.hpp new file mode 100755 index 000000000..be5b2c017 --- /dev/null +++ b/win32/include/boost/detail/lightweight_thread.hpp @@ -0,0 +1,135 @@ +#ifndef BOOST_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED +#define BOOST_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// boost/detail/lightweight_thread.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2008 Peter Dimov +// +// 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 + +#include +#include +#include + +// pthread_create, pthread_join + +#if defined( BOOST_HAS_PTHREADS ) + +#include + +#else + +#include +#include + +typedef HANDLE pthread_t; + +int pthread_create( pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg ) +{ + HANDLE h = (HANDLE)_beginthreadex( 0, 0, start_routine, arg, 0, 0 ); + + if( h != 0 ) + { + *thread = h; + return 0; + } + else + { + return EAGAIN; + } +} + +int pthread_join( pthread_t thread, void ** /*value_ptr*/ ) +{ + ::WaitForSingleObject( thread, INFINITE ); + ::CloseHandle( thread ); + return 0; +} + +#endif + +// template int lw_thread_create( pthread_t & pt, F f ); + +namespace boost +{ + +namespace detail +{ + +class lw_abstract_thread +{ +public: + + virtual ~lw_abstract_thread() {} + virtual void run() = 0; +}; + +#if defined( BOOST_HAS_PTHREADS ) + +extern "C" void * lw_thread_routine( void * pv ) +{ + std::auto_ptr pt( static_cast( pv ) ); + + pt->run(); + + return 0; +} + +#else + +unsigned __stdcall lw_thread_routine( void * pv ) +{ + std::auto_ptr pt( static_cast( pv ) ); + + pt->run(); + + return 0; +} + +#endif + +template class lw_thread_impl: public lw_abstract_thread +{ +public: + + explicit lw_thread_impl( F f ): f_( f ) + { + } + + void run() + { + f_(); + } + +private: + + F f_; +}; + +template int lw_thread_create( pthread_t & pt, F f ) +{ + std::auto_ptr p( new lw_thread_impl( f ) ); + + int r = pthread_create( &pt, 0, lw_thread_routine, p.get() ); + + if( r == 0 ) + { + p.release(); + } + + return r; +} + +} // namespace detail +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED diff --git a/win32/include/boost/detail/limits.hpp b/win32/include/boost/detail/limits.hpp new file mode 100755 index 000000000..4fc66d65b --- /dev/null +++ b/win32/include/boost/detail/limits.hpp @@ -0,0 +1,449 @@ +// Copyright 2001 John Maddock +// Distributed under the Boost Software License, Version 1.0. (See accompany- +// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/* + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/* NOTE: This is not portable code. Parts of numeric_limits<> are + * inherently machine-dependent, and this file is written for the MIPS + * architecture and the SGI MIPSpro C++ compiler. Parts of it (in + * particular, some of the characteristics of floating-point types) + * are almost certainly incorrect for any other platform. + */ + +/* The above comment is almost certainly out of date. This file works + * on systems other than SGI MIPSpro C++ now. + */ + +/* + * Revision history: + * 21 Sep 2001: + * Only include if BOOST_NO_CWCHAR is defined. (Darin Adler) + * 10 Aug 2001: + * Added MIPS (big endian) to the big endian family. (Jens Maurer) + * 13 Apr 2001: + * Added powerpc to the big endian family. (Jeremy Siek) + * 5 Apr 2001: + * Added sparc (big endian) processor support (John Maddock). + * Initial sub: + * Modified by Jens Maurer for gcc 2.95 on x86. + */ + +#ifndef BOOST_SGI_CPP_LIMITS +#define BOOST_SGI_CPP_LIMITS + +#include +#include +#include +#include + +#ifndef BOOST_NO_CWCHAR +#include // for WCHAR_MIN and WCHAR_MAX +#endif + +namespace std { + +enum float_round_style { + round_indeterminate = -1, + round_toward_zero = 0, + round_to_nearest = 1, + round_toward_infinity = 2, + round_toward_neg_infinity = 3 +}; + +enum float_denorm_style { + denorm_indeterminate = -1, + denorm_absent = 0, + denorm_present = 1 +}; + +// The C++ standard (section 18.2.1) requires that some of the members of +// numeric_limits be static const data members that are given constant- +// initializers within the class declaration. On compilers where the +// BOOST_NO_INCLASS_MEMBER_INITIALIZATION macro is defined, it is impossible to write +// a standard-conforming numeric_limits class. +// +// There are two possible workarounds: either initialize the data +// members outside the class, or change them from data members to +// enums. Neither workaround is satisfactory: the former makes it +// impossible to use the data members in constant-expressions, and the +// latter means they have the wrong type and that it is impossible to +// take their addresses. We choose the former workaround. + +#ifdef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +# define BOOST_STL_DECLARE_LIMITS_MEMBER(__mem_type, __mem_name, __mem_value) \ + enum { __mem_name = __mem_value } +#else /* BOOST_NO_INCLASS_MEMBER_INITIALIZATION */ +# define BOOST_STL_DECLARE_LIMITS_MEMBER(__mem_type, __mem_name, __mem_value) \ + static const __mem_type __mem_name = __mem_value +#endif /* BOOST_NO_INCLASS_MEMBER_INITIALIZATION */ + +// Base class for all specializations of numeric_limits. +template +class _Numeric_limits_base { +public: + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_specialized, false); + + static __number min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return __number(); } + static __number max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return __number(); } + + BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits, 0); + BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits10, 0); + + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_signed, false); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_integer, false); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_exact, false); + + BOOST_STL_DECLARE_LIMITS_MEMBER(int, radix, 0); + + static __number epsilon() throw() { return __number(); } + static __number round_error() throw() { return __number(); } + + BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent, 0); + BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent10, 0); + BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent, 0); + BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent10, 0); + + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_infinity, false); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_quiet_NaN, false); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_signaling_NaN, false); + BOOST_STL_DECLARE_LIMITS_MEMBER(float_denorm_style, + has_denorm, + denorm_absent); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_denorm_loss, false); + + static __number infinity() throw() { return __number(); } + static __number quiet_NaN() throw() { return __number(); } + static __number signaling_NaN() throw() { return __number(); } + static __number denorm_min() throw() { return __number(); } + + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_iec559, false); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_bounded, false); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_modulo, false); + + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, traps, false); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, tinyness_before, false); + BOOST_STL_DECLARE_LIMITS_MEMBER(float_round_style, + round_style, + round_toward_zero); +}; + +// Base class for integers. + +template +class _Integer_limits : public _Numeric_limits_base<_Int> +{ +public: + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_specialized, true); + + static _Int min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return __imin; } + static _Int max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return __imax; } + + BOOST_STL_DECLARE_LIMITS_MEMBER(int, + digits, + (__idigits < 0) ? (int)(sizeof(_Int) * CHAR_BIT) + - (__imin == 0 ? 0 : 1) + : __idigits); + BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits10, (digits * 301) / 1000); + // log 2 = 0.301029995664... + + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_signed, __imin != 0); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_integer, true); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_exact, true); + BOOST_STL_DECLARE_LIMITS_MEMBER(int, radix, 2); + + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_bounded, true); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_modulo, true); +}; + +#if defined(BOOST_BIG_ENDIAN) + + template + struct float_helper{ + static Number get_word() throw() { + // sizeof(long double) == 16 + const unsigned int _S_word[4] = { Word, 0, 0, 0 }; + return *reinterpret_cast(&_S_word); + } +}; + +#else + + template + struct float_helper{ + static Number get_word() throw() { + // sizeof(long double) == 12, but only 10 bytes significant + const unsigned int _S_word[4] = { 0, 0, 0, Word }; + return *reinterpret_cast( + reinterpret_cast(&_S_word)+16- + (sizeof(Number) == 12 ? 10 : sizeof(Number))); + } +}; + +#endif + +// Base class for floating-point numbers. +template +class _Floating_limits : public _Numeric_limits_base<__number> +{ +public: + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_specialized, true); + + BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits, __Digits); + BOOST_STL_DECLARE_LIMITS_MEMBER(int, digits10, __Digits10); + + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_signed, true); + + BOOST_STL_DECLARE_LIMITS_MEMBER(int, radix, 2); + + BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent, __MinExp); + BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent, __MaxExp); + BOOST_STL_DECLARE_LIMITS_MEMBER(int, min_exponent10, __MinExp10); + BOOST_STL_DECLARE_LIMITS_MEMBER(int, max_exponent10, __MaxExp10); + + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_infinity, true); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_quiet_NaN, true); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_signaling_NaN, true); + BOOST_STL_DECLARE_LIMITS_MEMBER(float_denorm_style, + has_denorm, + denorm_indeterminate); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, has_denorm_loss, false); + + + static __number infinity() throw() { + return float_helper<__number, __InfinityWord>::get_word(); + } + static __number quiet_NaN() throw() { + return float_helper<__number,__QNaNWord>::get_word(); + } + static __number signaling_NaN() throw() { + return float_helper<__number,__SNaNWord>::get_word(); + } + + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_iec559, __IsIEC559); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, is_bounded, true); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, traps, false /* was: true */ ); + BOOST_STL_DECLARE_LIMITS_MEMBER(bool, tinyness_before, false); + + BOOST_STL_DECLARE_LIMITS_MEMBER(float_round_style, round_style, __RoundStyle); +}; + +// Class numeric_limits + +// The unspecialized class. + +template +class numeric_limits : public _Numeric_limits_base {}; + +// Specializations for all built-in integral types. + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template<> +class numeric_limits +#if !defined(WCHAR_MAX) || !defined(WCHAR_MIN) +#if defined(_WIN32) || defined(__CYGWIN__) + : public _Integer_limits +#elif defined(__hppa) +// wchar_t has "unsigned int" as the underlying type + : public _Integer_limits +#else +// assume that wchar_t has "int" as the underlying type + : public _Integer_limits +#endif +#else +// we have WCHAR_MIN and WCHAR_MAX defined, so use it + : public _Integer_limits +#endif +{}; +#endif + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +template<> +class numeric_limits + : public _Integer_limits +{}; + +#ifdef __GNUC__ + +// Some compilers have long long, but don't define the +// LONGLONG_MIN and LONGLONG_MAX macros in limits.h. This +// assumes that long long is 64 bits. +#if !defined(LONGLONG_MAX) && !defined(ULONGLONG_MAX) + +# define ULONGLONG_MAX 0xffffffffffffffffLLU +# define LONGLONG_MAX 0x7fffffffffffffffLL + +#endif + +#if !defined(LONGLONG_MIN) +# define LONGLONG_MIN (-LONGLONG_MAX - 1) +#endif + + +#if !defined(ULONGLONG_MIN) +# define ULONGLONG_MIN 0 +#endif + +#endif /* __GNUC__ */ + +// Specializations for all built-in floating-point type. + +template<> class numeric_limits + : public _Floating_limits +{ +public: + static float min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return FLT_MIN; } + static float denorm_min() throw() { return FLT_MIN; } + static float max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return FLT_MAX; } + static float epsilon() throw() { return FLT_EPSILON; } + static float round_error() throw() { return 0.5f; } // Units: ulps. +}; + +template<> class numeric_limits + : public _Floating_limits +{ +public: + static double min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return DBL_MIN; } + static double denorm_min() throw() { return DBL_MIN; } + static double max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return DBL_MAX; } + static double epsilon() throw() { return DBL_EPSILON; } + static double round_error() throw() { return 0.5; } // Units: ulps. +}; + +template<> class numeric_limits + : public _Floating_limits +{ +public: + static long double min BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return LDBL_MIN; } + static long double denorm_min() throw() { return LDBL_MIN; } + static long double max BOOST_PREVENT_MACRO_SUBSTITUTION () throw() { return LDBL_MAX; } + static long double epsilon() throw() { return LDBL_EPSILON; } + static long double round_error() throw() { return 4; } // Units: ulps. +}; + +} // namespace std + +#endif /* BOOST_SGI_CPP_LIMITS */ + +// Local Variables: +// mode:C++ +// End: + + + diff --git a/win32/include/boost/detail/lwm_nop.hpp b/win32/include/boost/detail/lwm_nop.hpp new file mode 100755 index 000000000..21f5ed039 --- /dev/null +++ b/win32/include/boost/detail/lwm_nop.hpp @@ -0,0 +1,37 @@ +#ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED +#define BOOST_DETAIL_LWM_NOP_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/lwm_nop.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// 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) +// + +namespace boost +{ + +namespace detail +{ + +class lightweight_mutex +{ +public: + + typedef lightweight_mutex scoped_lock; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED diff --git a/win32/include/boost/detail/lwm_pthreads.hpp b/win32/include/boost/detail/lwm_pthreads.hpp new file mode 100755 index 000000000..864d87226 --- /dev/null +++ b/win32/include/boost/detail/lwm_pthreads.hpp @@ -0,0 +1,86 @@ +#ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED +#define BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/lwm_pthreads.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// +// 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) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class lightweight_mutex +{ +private: + + pthread_mutex_t m_; + + lightweight_mutex(lightweight_mutex const &); + lightweight_mutex & operator=(lightweight_mutex const &); + +public: + + lightweight_mutex() + { + +// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init + +#if defined(__hpux) && defined(_DECTHREADS_) + pthread_mutex_init(&m_, pthread_mutexattr_default); +#else + pthread_mutex_init(&m_, 0); +#endif + } + + ~lightweight_mutex() + { + pthread_mutex_destroy(&m_); + } + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock + { + private: + + pthread_mutex_t & m_; + + scoped_lock(scoped_lock const &); + scoped_lock & operator=(scoped_lock const &); + + public: + + scoped_lock(lightweight_mutex & m): m_(m.m_) + { + pthread_mutex_lock(&m_); + } + + ~scoped_lock() + { + pthread_mutex_unlock(&m_); + } + }; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED diff --git a/win32/include/boost/detail/lwm_win32_cs.hpp b/win32/include/boost/detail/lwm_win32_cs.hpp new file mode 100755 index 000000000..e7e7ab38d --- /dev/null +++ b/win32/include/boost/detail/lwm_win32_cs.hpp @@ -0,0 +1,108 @@ +#ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED +#define BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/lwm_win32_cs.hpp +// +// Copyright (c) 2002, 2003 Peter Dimov +// +// 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) +// + +#ifdef BOOST_USE_WINDOWS_H +# include +#endif + +namespace boost +{ + +namespace detail +{ + +#ifndef BOOST_USE_WINDOWS_H + +struct critical_section +{ + struct critical_section_debug * DebugInfo; + long LockCount; + long RecursionCount; + void * OwningThread; + void * LockSemaphore; +#if defined(_WIN64) + unsigned __int64 SpinCount; +#else + unsigned long SpinCount; +#endif +}; + +extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(critical_section *); + +#else + +typedef ::CRITICAL_SECTION critical_section; + +#endif // #ifndef BOOST_USE_WINDOWS_H + +class lightweight_mutex +{ +private: + + critical_section cs_; + + lightweight_mutex(lightweight_mutex const &); + lightweight_mutex & operator=(lightweight_mutex const &); + +public: + + lightweight_mutex() + { + InitializeCriticalSection(&cs_); + } + + ~lightweight_mutex() + { + DeleteCriticalSection(&cs_); + } + + class scoped_lock; + friend class scoped_lock; + + class scoped_lock + { + private: + + lightweight_mutex & m_; + + scoped_lock(scoped_lock const &); + scoped_lock & operator=(scoped_lock const &); + + public: + + explicit scoped_lock(lightweight_mutex & m): m_(m) + { + EnterCriticalSection(&m_.cs_); + } + + ~scoped_lock() + { + LeaveCriticalSection(&m_.cs_); + } + }; +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED diff --git a/win32/include/boost/detail/named_template_params.hpp b/win32/include/boost/detail/named_template_params.hpp new file mode 100755 index 000000000..0c2c94739 --- /dev/null +++ b/win32/include/boost/detail/named_template_params.hpp @@ -0,0 +1,177 @@ +// (C) Copyright Jeremy Siek 2001. +// 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) + +// Revision History: + +// 04 Oct 2001 David Abrahams +// Changed name of "bind" to "select" to avoid problems with MSVC. + +#ifndef BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP +#define BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP + +#include +#include // for is_reference +#if defined(__BORLANDC__) +#include +#endif + +namespace boost { + namespace detail { + + struct default_argument { }; + + struct dummy_default_gen { + template + struct select { + typedef default_argument type; + }; + }; + + // This class template is a workaround for MSVC. + template struct default_generator { + typedef detail::dummy_default_gen type; + }; + + template struct is_default { + enum { value = false }; + typedef type_traits::no_type type; + }; + template <> struct is_default { + enum { value = true }; + typedef type_traits::yes_type type; + }; + + struct choose_default { + template + struct select { + typedef typename default_generator::type Gen; + typedef typename Gen::template select::type type; + }; + }; + struct choose_arg { + template + struct select { + typedef Arg type; + }; + }; + +#if defined(__BORLANDC__) + template + struct choose_arg_or_default { typedef choose_arg type; }; + template <> + struct choose_arg_or_default { + typedef choose_default type; + }; +#else + template + struct choose_arg_or_default { typedef choose_arg type; }; + template <> + struct choose_arg_or_default { + typedef choose_default type; + }; +#endif + + template + class resolve_default { +#if defined(__BORLANDC__) + typedef typename choose_arg_or_default::type>::type Selector; +#else + // This usually works for Borland, but I'm seeing weird errors in + // iterator_adaptor_test.cpp when using this method. + enum { is_def = is_default::value }; + typedef typename choose_arg_or_default::type Selector; +#endif + public: + typedef typename Selector + ::template select::type type; + }; + + // To differentiate an unnamed parameter from a traits generator + // we use is_convertible. + struct named_template_param_base { }; + + template + struct is_named_param_list { + enum { value = is_convertible::value }; + }; + + struct choose_named_params { + template struct select { typedef Prev type; }; + }; + struct choose_default_arg { + template struct select { + typedef detail::default_argument type; + }; + }; + + template struct choose_default_dispatch_; + template <> struct choose_default_dispatch_ { + typedef choose_named_params type; + }; + template <> struct choose_default_dispatch_ { + typedef choose_default_arg type; + }; + // The use of inheritance here is a Solaris Forte 6 workaround. + template struct choose_default_dispatch + : public choose_default_dispatch_ { }; + + template + struct choose_default_argument { + enum { is_named = is_named_param_list::value }; + typedef typename choose_default_dispatch::type Selector; + typedef typename Selector::template select::type type; + }; + + // This macro assumes that there is a class named default_##TYPE + // defined before the application of the macro. This class should + // have a single member class template named "select" with two + // template parameters: the type of the class being created (e.g., + // the iterator_adaptor type when creating iterator adaptors) and + // a traits class. The select class should have a single typedef + // named "type" that produces the default for TYPE. See + // boost/iterator_adaptors.hpp for an example usage. Also, + // applications of this macro must be placed in namespace + // boost::detail. + +#define BOOST_NAMED_TEMPLATE_PARAM(TYPE) \ + struct get_##TYPE##_from_named { \ + template \ + struct select { \ + typedef typename NamedParams::traits NamedTraits; \ + typedef typename NamedTraits::TYPE TYPE; \ + typedef typename resolve_default::type type; \ + }; \ + }; \ + struct pass_thru_##TYPE { \ + template struct select { \ + typedef typename resolve_default::type type; \ + };\ + }; \ + template \ + struct get_##TYPE##_dispatch { }; \ + template <> struct get_##TYPE##_dispatch<1> { \ + typedef get_##TYPE##_from_named type; \ + }; \ + template <> struct get_##TYPE##_dispatch<0> { \ + typedef pass_thru_##TYPE type; \ + }; \ + template \ + class get_##TYPE { \ + enum { is_named = is_named_param_list::value }; \ + typedef typename get_##TYPE##_dispatch::type Selector; \ + public: \ + typedef typename Selector::template select::type type; \ + }; \ + template <> struct default_generator { \ + typedef default_##TYPE type; \ + } + + + } // namespace detail +} // namespace boost + +#endif // BOOST_DETAIL_NAMED_TEMPLATE_PARAMS_HPP diff --git a/win32/include/boost/detail/no_exceptions_support.hpp b/win32/include/boost/detail/no_exceptions_support.hpp new file mode 100755 index 000000000..702407f3c --- /dev/null +++ b/win32/include/boost/detail/no_exceptions_support.hpp @@ -0,0 +1,87 @@ +#ifndef BOOST_DETAIL_NO_EXCEPTIONS_SUPPORT_HPP_ +#define BOOST_DETAIL_NO_EXCEPTIONS_SUPPORT_HPP_ + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +//---------------------------------------------------------------------- +// (C) Copyright 2004 Pavel Vozenilek. +// Use, modification and distribution is subject to 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) +// +// +// This file contains helper macros used when exception support may be +// disabled (as indicated by macro BOOST_NO_EXCEPTIONS). +// +// Before picking up these macros you may consider using RAII techniques +// to deal with exceptions - their syntax can be always the same with +// or without exception support enabled. +// + +/* Example of use: + +void foo() { + BOOST_TRY { + ... + } BOOST_CATCH(const std::bad_alloc&) { + ... + BOOST_RETHROW + } BOOST_CATCH(const std::exception& e) { + ... + } + BOOST_CATCH_END +} + +With exception support enabled it will expand into: + +void foo() { + { try { + ... + } catch (const std::bad_alloc&) { + ... + throw; + } catch (const std::exception& e) { + ... + } + } +} + +With exception support disabled it will expand into: + +void foo() { + { if(true) { + ... + } else if (false) { + ... + } else if (false) { + ... + } + } +} +*/ +//---------------------------------------------------------------------- + +#include +#include + +#if !(defined BOOST_NO_EXCEPTIONS) +# define BOOST_TRY { try +# define BOOST_CATCH(x) catch(x) +# define BOOST_RETHROW throw; +# define BOOST_CATCH_END } +#else +# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +# define BOOST_TRY { if ("") +# define BOOST_CATCH(x) else if (!"") +# else +# define BOOST_TRY { if (true) +# define BOOST_CATCH(x) else if (false) +# endif +# define BOOST_RETHROW +# define BOOST_CATCH_END } +#endif + + +#endif diff --git a/win32/include/boost/detail/none_t.hpp b/win32/include/boost/detail/none_t.hpp new file mode 100755 index 000000000..e48bd3605 --- /dev/null +++ b/win32/include/boost/detail/none_t.hpp @@ -0,0 +1,28 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#ifndef BOOST_DETAIL_NONE_T_17SEP2003_HPP +#define BOOST_DETAIL_NONE_T_17SEP2003_HPP + +namespace boost { + +namespace detail { + +struct none_helper{}; + +typedef int none_helper::*none_t ; + +} // namespace detail + +} // namespace boost + +#endif + diff --git a/win32/include/boost/detail/numeric_traits.hpp b/win32/include/boost/detail/numeric_traits.hpp new file mode 100755 index 000000000..a44db9e5f --- /dev/null +++ b/win32/include/boost/detail/numeric_traits.hpp @@ -0,0 +1,191 @@ +// (C) Copyright David Abrahams 2001, Howard Hinnant 2001. +// +// 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) +// +// Template class numeric_traits -- +// +// Supplies: +// +// typedef difference_type -- a type used to represent the difference +// between any two values of Number. +// +// Support: +// 1. Not all specializations are supplied +// +// 2. Use of specializations that are not supplied will cause a +// compile-time error +// +// 3. Users are free to specialize numeric_traits for any type. +// +// 4. Right now, specializations are only supplied for integer types. +// +// 5. On implementations which do not supply compile-time constants in +// std::numeric_limits<>, only specializations for built-in integer types +// are supplied. +// +// 6. Handling of numbers whose range of representation is at least as +// great as boost::intmax_t can cause some differences to be +// unrepresentable in difference_type: +// +// Number difference_type +// ------ --------------- +// signed Number +// unsigned intmax_t +// +// template typename numeric_traits::difference_type +// numeric_distance(Number x, Number y) +// computes (y - x), attempting to avoid overflows. +// + +// See http://www.boost.org for most recent version including documentation. + +// Revision History +// 11 Feb 2001 - Use BOOST_STATIC_CONSTANT (David Abrahams) +// 11 Feb 2001 - Rolled back ineffective Borland-specific code +// (David Abrahams) +// 10 Feb 2001 - Rolled in supposed Borland fixes from John Maddock, but +// not seeing any improvement yet (David Abrahams) +// 06 Feb 2001 - Factored if_true out into boost/detail/select_type.hpp +// (David Abrahams) +// 23 Jan 2001 - Fixed logic of difference_type selection, which was +// completely wack. In the process, added digit_traits<> +// to compute the number of digits in intmax_t even when +// not supplied by numeric_limits<>. (David Abrahams) +// 21 Jan 2001 - Created (David Abrahams) + +#ifndef BOOST_NUMERIC_TRAITS_HPP_DWA20001901 +# define BOOST_NUMERIC_TRAITS_HPP_DWA20001901 + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace detail { + + // Template class is_signed -- determine whether a numeric type is signed + // Requires that T is constructable from the literals -1 and 0. Compile-time + // error results if that requirement is not met (and thus signedness is not + // likely to have meaning for that type). + template + struct is_signed + { +#if defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_MSVC) && BOOST_MSVC <= 1300 + BOOST_STATIC_CONSTANT(bool, value = (Number(-1) < Number(0))); +#else + BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_signed); +#endif + }; + +# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + // digit_traits - compute the number of digits in a built-in integer + // type. Needed for implementations on which numeric_limits is not specialized + // for intmax_t (e.g. VC6). + template struct digit_traits_select; + + // numeric_limits is specialized; just select that version of digits + template <> struct digit_traits_select + { + template struct traits + { + BOOST_STATIC_CONSTANT(int, digits = std::numeric_limits::digits); + }; + }; + + // numeric_limits is not specialized; compute digits from sizeof(T) + template <> struct digit_traits_select + { + template struct traits + { + BOOST_STATIC_CONSTANT(int, digits = ( + sizeof(T) * std::numeric_limits::digits + - (is_signed::value ? 1 : 0)) + ); + }; + }; + + // here's the "usable" template + template struct digit_traits + { + typedef digit_traits_select< + ::std::numeric_limits::is_specialized> selector; + typedef typename selector::template traits traits; + BOOST_STATIC_CONSTANT(int, digits = traits::digits); + }; +#endif + + // Template class integer_traits -- traits of various integer types + // This should probably be rolled into boost::integer_traits one day, but I + // need it to work without + template + struct integer_traits + { +# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + private: + typedef Integer integer_type; + typedef std::numeric_limits x; +# if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 + // for some reason, MSVC asserts when it shouldn't unless we make these + // local definitions + BOOST_STATIC_CONSTANT(bool, is_integer = x::is_integer); + BOOST_STATIC_CONSTANT(bool, is_specialized = x::is_specialized); + + BOOST_STATIC_ASSERT(is_integer); + BOOST_STATIC_ASSERT(is_specialized); +# endif + public: + typedef typename + if_true<(int(x::is_signed) + && (!int(x::is_bounded) + // digits is the number of no-sign bits + || (int(x::digits) + 1 >= digit_traits::digits)))>::template then< + Integer, + + typename if_true<(int(x::digits) + 1 < digit_traits::digits)>::template then< + signed int, + + typename if_true<(int(x::digits) + 1 < digit_traits::digits)>::template then< + signed long, + + // else + intmax_t + >::type>::type>::type difference_type; +#else + BOOST_STATIC_ASSERT(boost::is_integral::value); + + typedef typename + if_true<(sizeof(Integer) >= sizeof(intmax_t))>::template then< + + typename if_true<(is_signed::value)>::template then< + Integer, + intmax_t + >::type, + + typename if_true<(sizeof(Integer) < sizeof(std::ptrdiff_t))>::template then< + std::ptrdiff_t, + intmax_t + >::type + >::type difference_type; +# endif + }; + + // Right now, only supports integers, but should be expanded. + template + struct numeric_traits + { + typedef typename integer_traits::difference_type difference_type; + }; + + template + typename numeric_traits::difference_type numeric_distance(Number x, Number y) + { + typedef typename numeric_traits::difference_type difference_type; + return difference_type(y) - difference_type(x); + } +}} + +#endif // BOOST_NUMERIC_TRAITS_HPP_DWA20001901 diff --git a/win32/include/boost/detail/ob_call_traits.hpp b/win32/include/boost/detail/ob_call_traits.hpp new file mode 100755 index 000000000..eaf9cbeb0 --- /dev/null +++ b/win32/include/boost/detail/ob_call_traits.hpp @@ -0,0 +1,168 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/utility for most recent version including documentation. +// +// Crippled version for crippled compilers: +// see libs/utility/call_traits.htm +// + +/* Release notes: + 01st October 2000: + Fixed call_traits on VC6, using "poor man's partial specialisation", + using ideas taken from "Generative programming" by Krzysztof Czarnecki + & Ulrich Eisenecker. +*/ + +#ifndef BOOST_OB_CALL_TRAITS_HPP +#define BOOST_OB_CALL_TRAITS_HPP + +#ifndef BOOST_CONFIG_HPP +#include +#endif + +#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP +#include +#endif +#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP +#include +#endif + +namespace boost{ + +#ifdef BOOST_MSVC6_MEMBER_TEMPLATES +// +// use member templates to emulate +// partial specialisation: +// +namespace detail{ + +template +struct standard_call_traits +{ + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef const T& param_type; +}; +template +struct simple_call_traits +{ + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef const T param_type; +}; +template +struct reference_call_traits +{ + typedef T value_type; + typedef T reference; + typedef T const_reference; + typedef T param_type; +}; + +template +struct call_traits_chooser +{ + template + struct rebind + { + typedef standard_call_traits type; + }; +}; + +template <> +struct call_traits_chooser +{ + template + struct rebind + { + typedef simple_call_traits type; + }; +}; + +template <> +struct call_traits_chooser +{ + template + struct rebind + { + typedef reference_call_traits type; + }; +}; + +template +struct call_traits_sizeof_chooser2 +{ + template + struct small_rebind + { + typedef simple_call_traits small_type; + }; +}; + +template<> +struct call_traits_sizeof_chooser2 +{ + template + struct small_rebind + { + typedef standard_call_traits small_type; + }; +}; + +template <> +struct call_traits_chooser +{ + template + struct rebind + { + enum { sizeof_choice = (sizeof(T) <= sizeof(void*)) }; + typedef call_traits_sizeof_chooser2<(sizeof(T) <= sizeof(void*))> chooser; + typedef typename chooser::template small_rebind bound_type; + typedef typename bound_type::small_type type; + }; +}; + +} // namespace detail +template +struct call_traits +{ +private: + typedef detail::call_traits_chooser< + ::boost::is_pointer::value, + ::boost::is_arithmetic::value, + ::boost::is_reference::value + > chooser; + typedef typename chooser::template rebind bound_type; + typedef typename bound_type::type call_traits_type; +public: + typedef typename call_traits_type::value_type value_type; + typedef typename call_traits_type::reference reference; + typedef typename call_traits_type::const_reference const_reference; + typedef typename call_traits_type::param_type param_type; +}; + +#else +// +// sorry call_traits is completely non-functional +// blame your broken compiler: +// + +template +struct call_traits +{ + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef const T& param_type; +}; + +#endif // member templates + +} + +#endif // BOOST_OB_CALL_TRAITS_HPP diff --git a/win32/include/boost/detail/ob_compressed_pair.hpp b/win32/include/boost/detail/ob_compressed_pair.hpp new file mode 100755 index 000000000..51346f775 --- /dev/null +++ b/win32/include/boost/detail/ob_compressed_pair.hpp @@ -0,0 +1,510 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/utility for most recent version including documentation. +// see libs/utility/compressed_pair.hpp +// +/* Release notes: + 20 Jan 2001: + Fixed obvious bugs (David Abrahams) + 07 Oct 2000: + Added better single argument constructor support. + 03 Oct 2000: + Added VC6 support (JM). + 23rd July 2000: + Additional comments added. (JM) + Jan 2000: + Original version: this version crippled for use with crippled compilers + - John Maddock Jan 2000. +*/ + + +#ifndef BOOST_OB_COMPRESSED_PAIR_HPP +#define BOOST_OB_COMPRESSED_PAIR_HPP + +#include +#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP +#include +#endif +#ifndef BOOST_SAME_TRAITS_HPP +#include +#endif +#ifndef BOOST_CALL_TRAITS_HPP +#include +#endif + +namespace boost +{ +#ifdef BOOST_MSVC6_MEMBER_TEMPLATES +// +// use member templates to emulate +// partial specialisation. Note that due to +// problems with overload resolution with VC6 +// each of the compressed_pair versions that follow +// have one template single-argument constructor +// in place of two specific constructors: +// + +template +class compressed_pair; + +namespace detail{ + +template +struct best_conversion_traits +{ + typedef char one; + typedef char (&two)[2]; + static A a; + static one test(T1); + static two test(T2); + + enum { value = sizeof(test(a)) }; +}; + +template +struct init_one; + +template <> +struct init_one<1> +{ + template + static void init(const A& a, T1* p1, T2*) + { + *p1 = a; + } +}; + +template <> +struct init_one<2> +{ + template + static void init(const A& a, T1*, T2* p2) + { + *p2 = a; + } +}; + + +// T1 != T2, both non-empty +template +class compressed_pair_0 +{ +private: + T1 _first; + T2 _second; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_0() : _first(), _second() {} + compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {} + template + explicit compressed_pair_0(const A& val) + { + init_one::value>::init(val, &_first, &_second); + } + compressed_pair_0(const ::boost::compressed_pair& x) + : _first(x.first()), _second(x.second()) {} + +#if 0 + compressed_pair_0& operator=(const compressed_pair_0& x) { + cout << "assigning compressed pair 0" << endl; + _first = x._first; + _second = x._second; + cout << "finished assigning compressed pair 0" << endl; + return *this; + } +#endif + + first_reference first() { return _first; } + first_const_reference first() const { return _first; } + + second_reference second() { return _second; } + second_const_reference second() const { return _second; } + + void swap(compressed_pair_0& y) + { + using std::swap; + swap(_first, y._first); + swap(_second, y._second); + } +}; + +// T1 != T2, T2 empty +template +class compressed_pair_1 : T2 +{ +private: + T1 _first; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_1() : T2(), _first() {} + compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {} + + template + explicit compressed_pair_1(const A& val) + { + init_one::value>::init(val, &_first, static_cast(this)); + } + + compressed_pair_1(const ::boost::compressed_pair& x) + : T2(x.second()), _first(x.first()) {} + +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 + // Total weirdness. If the assignment to _first is moved after + // the call to the inherited operator=, then this breaks graph/test/graph.cpp + // by way of iterator_adaptor. + compressed_pair_1& operator=(const compressed_pair_1& x) { + _first = x._first; + T2::operator=(x); + return *this; + } +#endif + + first_reference first() { return _first; } + first_const_reference first() const { return _first; } + + second_reference second() { return *this; } + second_const_reference second() const { return *this; } + + void swap(compressed_pair_1& y) + { + // no need to swap empty base class: + using std::swap; + swap(_first, y._first); + } +}; + +// T1 != T2, T1 empty +template +class compressed_pair_2 : T1 +{ +private: + T2 _second; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_2() : T1(), _second() {} + compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {} + template + explicit compressed_pair_2(const A& val) + { + init_one::value>::init(val, static_cast(this), &_second); + } + compressed_pair_2(const ::boost::compressed_pair& x) + : T1(x.first()), _second(x.second()) {} + +#if 0 + compressed_pair_2& operator=(const compressed_pair_2& x) { + cout << "assigning compressed pair 2" << endl; + T1::operator=(x); + _second = x._second; + cout << "finished assigning compressed pair 2" << endl; + return *this; + } +#endif + first_reference first() { return *this; } + first_const_reference first() const { return *this; } + + second_reference second() { return _second; } + second_const_reference second() const { return _second; } + + void swap(compressed_pair_2& y) + { + // no need to swap empty base class: + using std::swap; + swap(_second, y._second); + } +}; + +// T1 != T2, both empty +template +class compressed_pair_3 : T1, T2 +{ +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_3() : T1(), T2() {} + compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {} + template + explicit compressed_pair_3(const A& val) + { + init_one::value>::init(val, static_cast(this), static_cast(this)); + } + compressed_pair_3(const ::boost::compressed_pair& x) + : T1(x.first()), T2(x.second()) {} + + first_reference first() { return *this; } + first_const_reference first() const { return *this; } + + second_reference second() { return *this; } + second_const_reference second() const { return *this; } + + void swap(compressed_pair_3& y) + { + // no need to swap empty base classes: + } +}; + +// T1 == T2, and empty +template +class compressed_pair_4 : T1 +{ +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_4() : T1() {} + compressed_pair_4(first_param_type x, second_param_type y) : T1(x), m_second(y) {} + // only one single argument constructor since T1 == T2 + explicit compressed_pair_4(first_param_type x) : T1(x), m_second(x) {} + compressed_pair_4(const ::boost::compressed_pair& x) + : T1(x.first()), m_second(x.second()) {} + + first_reference first() { return *this; } + first_const_reference first() const { return *this; } + + second_reference second() { return m_second; } + second_const_reference second() const { return m_second; } + + void swap(compressed_pair_4& y) + { + // no need to swap empty base classes: + } +private: + T2 m_second; +}; + +// T1 == T2, not empty +template +class compressed_pair_5 +{ +private: + T1 _first; + T2 _second; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_5() : _first(), _second() {} + compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {} + // only one single argument constructor since T1 == T2 + explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {} + compressed_pair_5(const ::boost::compressed_pair& c) + : _first(c.first()), _second(c.second()) {} + + first_reference first() { return _first; } + first_const_reference first() const { return _first; } + + second_reference second() { return _second; } + second_const_reference second() const { return _second; } + + void swap(compressed_pair_5& y) + { + using std::swap; + swap(_first, y._first); + swap(_second, y._second); + } +}; + +template +struct compressed_pair_chooser +{ + template + struct rebind + { + typedef compressed_pair_0 type; + }; +}; + +template <> +struct compressed_pair_chooser +{ + template + struct rebind + { + typedef compressed_pair_1 type; + }; +}; + +template <> +struct compressed_pair_chooser +{ + template + struct rebind + { + typedef compressed_pair_2 type; + }; +}; + +template <> +struct compressed_pair_chooser +{ + template + struct rebind + { + typedef compressed_pair_3 type; + }; +}; + +template <> +struct compressed_pair_chooser +{ + template + struct rebind + { + typedef compressed_pair_4 type; + }; +}; + +template <> +struct compressed_pair_chooser +{ + template + struct rebind + { + typedef compressed_pair_5 type; + }; +}; + +template +struct compressed_pair_traits +{ +private: + typedef compressed_pair_chooser::value, is_empty::value, is_same::value> chooser; + typedef typename chooser::template rebind bound_type; +public: + typedef typename bound_type::type type; +}; + +} // namespace detail + +template +class compressed_pair : public detail::compressed_pair_traits::type +{ +private: + typedef typename detail::compressed_pair_traits::type base_type; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair() : base_type() {} + compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {} + template + explicit compressed_pair(const A& x) : base_type(x){} + + first_reference first() { return base_type::first(); } + first_const_reference first() const { return base_type::first(); } + + second_reference second() { return base_type::second(); } + second_const_reference second() const { return base_type::second(); } +}; + +template +inline void swap(compressed_pair& x, compressed_pair& y) +{ + x.swap(y); +} + +#else +// no partial specialisation, no member templates: + +template +class compressed_pair +{ +private: + T1 _first; + T2 _second; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair() : _first(), _second() {} + compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {} + explicit compressed_pair(first_param_type x) : _first(x), _second() {} + // can't define this in case T1 == T2: + // explicit compressed_pair(second_param_type y) : _first(), _second(y) {} + + first_reference first() { return _first; } + first_const_reference first() const { return _first; } + + second_reference second() { return _second; } + second_const_reference second() const { return _second; } + + void swap(compressed_pair& y) + { + using std::swap; + swap(_first, y._first); + swap(_second, y._second); + } +}; + +template +inline void swap(compressed_pair& x, compressed_pair& y) +{ + x.swap(y); +} + +#endif + +} // boost + +#endif // BOOST_OB_COMPRESSED_PAIR_HPP + + + diff --git a/win32/include/boost/detail/quick_allocator.hpp b/win32/include/boost/detail/quick_allocator.hpp new file mode 100755 index 000000000..de653a62b --- /dev/null +++ b/win32/include/boost/detail/quick_allocator.hpp @@ -0,0 +1,198 @@ +#ifndef BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED +#define BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/quick_allocator.hpp +// +// Copyright (c) 2003 David Abrahams +// Copyright (c) 2003 Peter Dimov +// +// 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) +// + +#include + +#include +#include +#include + +#include // ::operator new, ::operator delete +#include // std::size_t + +namespace boost +{ + +namespace detail +{ + +template union freeblock +{ + typedef typename boost::type_with_alignment::type aligner_type; + aligner_type aligner; + char bytes[size]; + freeblock * next; +}; + +template struct allocator_impl +{ + typedef freeblock block; + + // It may seem odd to use such small pages. + // + // However, on a typical Windows implementation that uses + // the OS allocator, "normal size" pages interact with the + // "ordinary" operator new, slowing it down dramatically. + // + // 512 byte pages are handled by the small object allocator, + // and don't interfere with ::new. + // + // The other alternative is to use much bigger pages (1M.) + // + // It is surprisingly easy to hit pathological behavior by + // varying the page size. g++ 2.96 on Red Hat Linux 7.2, + // for example, passionately dislikes 496. 512 seems OK. + +#if defined(BOOST_QA_PAGE_SIZE) + + enum { items_per_page = BOOST_QA_PAGE_SIZE / size }; + +#else + + enum { items_per_page = 512 / size }; // 1048560 / size + +#endif + +#ifdef BOOST_HAS_THREADS + + static lightweight_mutex & mutex() + { + static lightweight_mutex m; + return m; + } + + static lightweight_mutex * mutex_init; + +#endif + + static block * free; + static block * page; + static unsigned last; + + static inline void * alloc() + { +#ifdef BOOST_HAS_THREADS + lightweight_mutex::scoped_lock lock( mutex() ); +#endif + if(block * x = free) + { + free = x->next; + return x; + } + else + { + if(last == items_per_page) + { + // "Listen to me carefully: there is no memory leak" + // -- Scott Meyers, Eff C++ 2nd Ed Item 10 + page = ::new block[items_per_page]; + last = 0; + } + + return &page[last++]; + } + } + + static inline void * alloc(std::size_t n) + { + if(n != size) // class-specific new called for a derived object + { + return ::operator new(n); + } + else + { +#ifdef BOOST_HAS_THREADS + lightweight_mutex::scoped_lock lock( mutex() ); +#endif + if(block * x = free) + { + free = x->next; + return x; + } + else + { + if(last == items_per_page) + { + page = ::new block[items_per_page]; + last = 0; + } + + return &page[last++]; + } + } + } + + static inline void dealloc(void * pv) + { + if(pv != 0) // 18.4.1.1/13 + { +#ifdef BOOST_HAS_THREADS + lightweight_mutex::scoped_lock lock( mutex() ); +#endif + block * pb = static_cast(pv); + pb->next = free; + free = pb; + } + } + + static inline void dealloc(void * pv, std::size_t n) + { + if(n != size) // class-specific delete called for a derived object + { + ::operator delete(pv); + } + else if(pv != 0) // 18.4.1.1/13 + { +#ifdef BOOST_HAS_THREADS + lightweight_mutex::scoped_lock lock( mutex() ); +#endif + block * pb = static_cast(pv); + pb->next = free; + free = pb; + } + } +}; + +#ifdef BOOST_HAS_THREADS + +template + lightweight_mutex * allocator_impl::mutex_init = &allocator_impl::mutex(); + +#endif + +template + freeblock * allocator_impl::free = 0; + +template + freeblock * allocator_impl::page = 0; + +template + unsigned allocator_impl::last = allocator_impl::items_per_page; + +template +struct quick_allocator: public allocator_impl< sizeof(T), boost::alignment_of::value > +{ +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED diff --git a/win32/include/boost/detail/reference_content.hpp b/win32/include/boost/detail/reference_content.hpp new file mode 100755 index 000000000..eae9f047d --- /dev/null +++ b/win32/include/boost/detail/reference_content.hpp @@ -0,0 +1,141 @@ +//----------------------------------------------------------------------------- +// boost detail/reference_content.hpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_DETAIL_REFERENCE_CONTENT_HPP +#define BOOST_DETAIL_REFERENCE_CONTENT_HPP + +#include "boost/config.hpp" + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +# include "boost/mpl/bool.hpp" +# include "boost/type_traits/has_nothrow_copy.hpp" +#else +# include "boost/mpl/if.hpp" +# include "boost/type_traits/is_reference.hpp" +#endif + +#include "boost/mpl/void.hpp" + +namespace boost { + +namespace detail { + +/////////////////////////////////////////////////////////////////////////////// +// (detail) class template reference_content +// +// Non-Assignable wrapper for references. +// +template +class reference_content +{ +private: // representation + + RefT content_; + +public: // structors + + ~reference_content() + { + } + + reference_content(RefT r) + : content_( r ) + { + } + + reference_content(const reference_content& operand) + : content_( operand.content_ ) + { + } + +private: // non-Assignable + + reference_content& operator=(const reference_content&); + +public: // queries + + RefT get() const + { + return content_; + } + +}; + +/////////////////////////////////////////////////////////////////////////////// +// (detail) metafunction make_reference_content +// +// Wraps with reference_content if specified type is reference. +// + +template struct make_reference_content; + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template +struct make_reference_content +{ + typedef T type; +}; + +template +struct make_reference_content< T& > +{ + typedef reference_content type; +}; + +#else // defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template +struct make_reference_content + : mpl::if_< + is_reference + , reference_content + , T + > +{ +}; + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION workaround + +template <> +struct make_reference_content< mpl::void_ > +{ + template + struct apply + : make_reference_content + { + }; + + typedef mpl::void_ type; +}; + +} // namespace detail + +/////////////////////////////////////////////////////////////////////////////// +// reference_content type traits specializations +// + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template +struct has_nothrow_copy< + ::boost::detail::reference_content< T& > + > + : mpl::true_ +{ +}; + +#endif // !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +} // namespace boost + +#endif // BOOST_DETAIL_REFERENCE_CONTENT_HPP diff --git a/win32/include/boost/detail/select_type.hpp b/win32/include/boost/detail/select_type.hpp new file mode 100755 index 000000000..01c943649 --- /dev/null +++ b/win32/include/boost/detail/select_type.hpp @@ -0,0 +1,36 @@ +// (C) Copyright David Abrahams 2001. +// 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) +// +// See http://www.boost.org for most recent version including documentation. + +// Revision History +// 09 Feb 01 Applied John Maddock's Borland patch Moving +// specialization to unspecialized template (David Abrahams) +// 06 Feb 01 Created (David Abrahams) + +#ifndef SELECT_TYPE_DWA20010206_HPP +# define SELECT_TYPE_DWA20010206_HPP + +namespace boost { namespace detail { + + // Template class if_true -- select among 2 types based on a bool constant expression + // Usage: + // typename if_true<(bool_const_expression)>::template then::type + + // HP aCC cannot deal with missing names for template value parameters + template struct if_true + { + template + struct then { typedef T type; }; + }; + + template <> + struct if_true + { + template + struct then { typedef F type; }; + }; +}} +#endif // SELECT_TYPE_DWA20010206_HPP diff --git a/win32/include/boost/detail/shared_array_nmt.hpp b/win32/include/boost/detail/shared_array_nmt.hpp new file mode 100755 index 000000000..3a8093241 --- /dev/null +++ b/win32/include/boost/detail/shared_array_nmt.hpp @@ -0,0 +1,151 @@ +#ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED +#define BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED + +// +// detail/shared_array_nmt.hpp - shared_array.hpp without member templates +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// 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) +// +// See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation. +// + +#include +#include +#include +#include + +#include // for std::ptrdiff_t +#include // for std::swap +#include // for std::less +#include // for std::bad_alloc + +namespace boost +{ + +template class shared_array +{ +private: + + typedef detail::atomic_count count_type; + +public: + + typedef T element_type; + + explicit shared_array(T * p = 0): px(p) + { +#ifndef BOOST_NO_EXCEPTIONS + + try // prevent leak if new throws + { + pn = new count_type(1); + } + catch(...) + { + boost::checked_array_delete(p); + throw; + } + +#else + + pn = new count_type(1); + + if(pn == 0) + { + boost::checked_array_delete(p); + boost::throw_exception(std::bad_alloc()); + } + +#endif + } + + ~shared_array() + { + if(--*pn == 0) + { + boost::checked_array_delete(px); + delete pn; + } + } + + shared_array(shared_array const & r) : px(r.px) // never throws + { + pn = r.pn; + ++*pn; + } + + shared_array & operator=(shared_array const & r) + { + shared_array(r).swap(*this); + return *this; + } + + void reset(T * p = 0) + { + BOOST_ASSERT(p == 0 || p != px); + shared_array(p).swap(*this); + } + + T * get() const // never throws + { + return px; + } + + T & operator[](std::ptrdiff_t i) const // never throws + { + BOOST_ASSERT(px != 0); + BOOST_ASSERT(i >= 0); + return px[i]; + } + + long use_count() const // never throws + { + return *pn; + } + + bool unique() const // never throws + { + return *pn == 1; + } + + void swap(shared_array & other) // never throws + { + std::swap(px, other.px); + std::swap(pn, other.pn); + } + +private: + + T * px; // contained pointer + count_type * pn; // ptr to reference counter + +}; // shared_array + +template inline bool operator==(shared_array const & a, shared_array const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(shared_array const & a, shared_array const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator<(shared_array const & a, shared_array const & b) +{ + return std::less()(a.get(), b.get()); +} + +template void swap(shared_array & a, shared_array & b) +{ + a.swap(b); +} + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED diff --git a/win32/include/boost/detail/shared_count.hpp b/win32/include/boost/detail/shared_count.hpp new file mode 100755 index 000000000..54ccc5d3c --- /dev/null +++ b/win32/include/boost/detail/shared_count.hpp @@ -0,0 +1,412 @@ +#ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED +#define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/shared_count.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// +// 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) +// + +#ifdef __BORLANDC__ +# pragma warn -8027 // Functions containing try are not expanded inline +#endif + +#include +#include +#include +#include +#include +#include +// In order to avoid circular dependencies with Boost.TR1 +// we make sure that our include of doesn't try to +// pull in the TR1 headers: that's why we use this header +// rather than including directly: +#include // std::auto_ptr +#include // std::less +#include // std::bad_alloc + +namespace boost +{ + +namespace detail +{ + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +int const shared_count_id = 0x2C35F101; +int const weak_count_id = 0x298C38A4; + +#endif + +struct sp_nothrow_tag {}; + +class weak_count; + +class shared_count +{ +private: + + sp_counted_base * pi_; + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + int id_; +#endif + + friend class weak_count; + +public: + + shared_count(): pi_(0) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + } + + template explicit shared_count( Y * p ): pi_( 0 ) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { +#ifndef BOOST_NO_EXCEPTIONS + + try + { + pi_ = new sp_counted_impl_p( p ); + } + catch(...) + { + boost::checked_delete( p ); + throw; + } + +#else + + pi_ = new sp_counted_impl_p( p ); + + if( pi_ == 0 ) + { + boost::checked_delete( p ); + boost::throw_exception( std::bad_alloc() ); + } + +#endif + } + +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) + template shared_count( Y * p, D d ): pi_(0) +#else + template shared_count( P p, D d ): pi_(0) +#endif +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) + typedef Y* P; +#endif +#ifndef BOOST_NO_EXCEPTIONS + + try + { + pi_ = new sp_counted_impl_pd(p, d); + } + catch(...) + { + d(p); // delete p + throw; + } + +#else + + pi_ = new sp_counted_impl_pd(p, d); + + if(pi_ == 0) + { + d(p); // delete p + boost::throw_exception(std::bad_alloc()); + } + +#endif + } + + template shared_count( P p, D d, A a ): pi_( 0 ) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + typedef sp_counted_impl_pda impl_type; + typedef typename A::template rebind< impl_type >::other A2; + + A2 a2( a ); + +#ifndef BOOST_NO_EXCEPTIONS + + try + { + pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); + new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); + } + catch(...) + { + d( p ); + + if( pi_ != 0 ) + { + a2.deallocate( static_cast< impl_type* >( pi_ ), 1 ); + } + + throw; + } + +#else + + pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); + + if( pi_ != 0 ) + { + new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); + } + else + { + d( p ); + boost::throw_exception( std::bad_alloc() ); + } + +#endif + } + +#ifndef BOOST_NO_AUTO_PTR + + // auto_ptr is special cased to provide the strong guarantee + + template + explicit shared_count( std::auto_ptr & r ): pi_( new sp_counted_impl_p( r.get() ) ) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { +#ifdef BOOST_NO_EXCEPTIONS + + if( pi_ == 0 ) + { + boost::throw_exception(std::bad_alloc()); + } + +#endif + + r.release(); + } + +#endif + + ~shared_count() // nothrow + { + if( pi_ != 0 ) pi_->release(); +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + id_ = 0; +#endif + } + + shared_count(shared_count const & r): pi_(r.pi_) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + if( pi_ != 0 ) pi_->add_ref_copy(); + } + + explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 + shared_count( weak_count const & r, sp_nothrow_tag ); // constructs an empty *this when r.use_count() == 0 + + shared_count & operator= (shared_count const & r) // nothrow + { + sp_counted_base * tmp = r.pi_; + + if( tmp != pi_ ) + { + if( tmp != 0 ) tmp->add_ref_copy(); + if( pi_ != 0 ) pi_->release(); + pi_ = tmp; + } + + return *this; + } + + void swap(shared_count & r) // nothrow + { + sp_counted_base * tmp = r.pi_; + r.pi_ = pi_; + pi_ = tmp; + } + + long use_count() const // nothrow + { + return pi_ != 0? pi_->use_count(): 0; + } + + bool unique() const // nothrow + { + return use_count() == 1; + } + + bool empty() const // nothrow + { + return pi_ == 0; + } + + friend inline bool operator==(shared_count const & a, shared_count const & b) + { + return a.pi_ == b.pi_; + } + + friend inline bool operator<(shared_count const & a, shared_count const & b) + { + return std::less()( a.pi_, b.pi_ ); + } + + void * get_deleter( sp_typeinfo const & ti ) const + { + return pi_? pi_->get_deleter( ti ): 0; + } +}; + + +class weak_count +{ +private: + + sp_counted_base * pi_; + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + int id_; +#endif + + friend class shared_count; + +public: + + weak_count(): pi_(0) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(weak_count_id) +#endif + { + } + + weak_count(shared_count const & r): pi_(r.pi_) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + if(pi_ != 0) pi_->weak_add_ref(); + } + + weak_count(weak_count const & r): pi_(r.pi_) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + if(pi_ != 0) pi_->weak_add_ref(); + } + + ~weak_count() // nothrow + { + if(pi_ != 0) pi_->weak_release(); +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + id_ = 0; +#endif + } + + weak_count & operator= (shared_count const & r) // nothrow + { + sp_counted_base * tmp = r.pi_; + + if( tmp != pi_ ) + { + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); + pi_ = tmp; + } + + return *this; + } + + weak_count & operator= (weak_count const & r) // nothrow + { + sp_counted_base * tmp = r.pi_; + + if( tmp != pi_ ) + { + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); + pi_ = tmp; + } + + return *this; + } + + void swap(weak_count & r) // nothrow + { + sp_counted_base * tmp = r.pi_; + r.pi_ = pi_; + pi_ = tmp; + } + + long use_count() const // nothrow + { + return pi_ != 0? pi_->use_count(): 0; + } + + friend inline bool operator==(weak_count const & a, weak_count const & b) + { + return a.pi_ == b.pi_; + } + + friend inline bool operator<(weak_count const & a, weak_count const & b) + { + return std::less()(a.pi_, b.pi_); + } +}; + +inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ ) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif +{ + if( pi_ == 0 || !pi_->add_ref_lock() ) + { + boost::throw_exception( boost::bad_weak_ptr() ); + } +} + +inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ ) +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif +{ + if( pi_ != 0 && !pi_->add_ref_lock() ) + { + pi_ = 0; + } +} + +} // namespace detail + +} // namespace boost + +#ifdef __BORLANDC__ +# pragma warn .8027 // Functions containing try are not expanded inline +#endif + +#endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED diff --git a/win32/include/boost/detail/shared_ptr_nmt.hpp b/win32/include/boost/detail/shared_ptr_nmt.hpp new file mode 100755 index 000000000..8907d6188 --- /dev/null +++ b/win32/include/boost/detail/shared_ptr_nmt.hpp @@ -0,0 +1,182 @@ +#ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED +#define BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED + +// +// detail/shared_ptr_nmt.hpp - shared_ptr.hpp without member templates +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// 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) +// +// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. +// + +#include +#include +#include +#include + +#ifndef BOOST_NO_AUTO_PTR +# include // for std::auto_ptr +#endif + +#include // for std::swap +#include // for std::less +#include // for std::bad_alloc + +namespace boost +{ + +template class shared_ptr +{ +private: + + typedef detail::atomic_count count_type; + +public: + + typedef T element_type; + typedef T value_type; + + explicit shared_ptr(T * p = 0): px(p) + { +#ifndef BOOST_NO_EXCEPTIONS + + try // prevent leak if new throws + { + pn = new count_type(1); + } + catch(...) + { + boost::checked_delete(p); + throw; + } + +#else + + pn = new count_type(1); + + if(pn == 0) + { + boost::checked_delete(p); + boost::throw_exception(std::bad_alloc()); + } + +#endif + } + + ~shared_ptr() + { + if(--*pn == 0) + { + boost::checked_delete(px); + delete pn; + } + } + + shared_ptr(shared_ptr const & r): px(r.px) // never throws + { + pn = r.pn; + ++*pn; + } + + shared_ptr & operator=(shared_ptr const & r) + { + shared_ptr(r).swap(*this); + return *this; + } + +#ifndef BOOST_NO_AUTO_PTR + + explicit shared_ptr(std::auto_ptr & r) + { + pn = new count_type(1); // may throw + px = r.release(); // fix: moved here to stop leak if new throws + } + + shared_ptr & operator=(std::auto_ptr & r) + { + shared_ptr(r).swap(*this); + return *this; + } + +#endif + + void reset(T * p = 0) + { + BOOST_ASSERT(p == 0 || p != px); + shared_ptr(p).swap(*this); + } + + T & operator*() const // never throws + { + BOOST_ASSERT(px != 0); + return *px; + } + + T * operator->() const // never throws + { + BOOST_ASSERT(px != 0); + return px; + } + + T * get() const // never throws + { + return px; + } + + long use_count() const // never throws + { + return *pn; + } + + bool unique() const // never throws + { + return *pn == 1; + } + + void swap(shared_ptr & other) // never throws + { + std::swap(px, other.px); + std::swap(pn, other.pn); + } + +private: + + T * px; // contained pointer + count_type * pn; // ptr to reference counter +}; + +template inline bool operator==(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator<(shared_ptr const & a, shared_ptr const & b) +{ + return std::less()(a.get(), b.get()); +} + +template void swap(shared_ptr & a, shared_ptr & b) +{ + a.swap(b); +} + +// get_pointer() enables boost::mem_fn to recognize shared_ptr + +template inline T * get_pointer(shared_ptr const & p) +{ + return p.get(); +} + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_convertible.hpp b/win32/include/boost/detail/sp_convertible.hpp new file mode 100755 index 000000000..451a35b70 --- /dev/null +++ b/win32/include/boost/detail/sp_convertible.hpp @@ -0,0 +1,76 @@ +#ifndef BOOST_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED +#define BOOST_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_convertible.hpp +// +// Copyright 2008 Peter Dimov +// +// 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 + +#include + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( BOOST_NO_SFINAE ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ < 303 ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x600 ) +# define BOOST_SP_NO_SP_CONVERTIBLE +#endif + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + +namespace boost +{ + +namespace detail +{ + +template< class Y, class T > struct sp_convertible +{ + typedef char (&yes) [1]; + typedef char (&no) [2]; + + static yes f( T* ); + static no f( ... ); + + enum _vt { value = sizeof( f( (Y*)0 ) ) == sizeof(yes) }; +}; + +struct sp_empty +{ +}; + +template< bool > struct sp_enable_if_convertible_impl; + +template<> struct sp_enable_if_convertible_impl +{ + typedef sp_empty type; +}; + +template<> struct sp_enable_if_convertible_impl +{ +}; + +template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_if_convertible_impl< sp_convertible< Y, T >::value > +{ +}; + +} // namespace detail + +} // namespace boost + +#endif // !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + +#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_base.hpp b/win32/include/boost/detail/sp_counted_base.hpp new file mode 100755 index 000000000..aeffd092e --- /dev/null +++ b/win32/include/boost/detail/sp_counted_base.hpp @@ -0,0 +1,66 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base.hpp +// +// Copyright 2005, 2006 Peter Dimov +// +// 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) +// + +#include + +#if defined( BOOST_SP_DISABLE_THREADS ) +# include + +#elif defined( BOOST_SP_USE_SPINLOCK ) +# include + +#elif defined( BOOST_SP_USE_PTHREADS ) +# include + +#elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 ) +# include + +#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) +# include + +#elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER ) +# include + +#elif defined(__HP_aCC) && defined(__ia64) +# include + +#elif defined( __MWERKS__ ) && defined( __POWERPC__ ) +# include + +#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) +# include + +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __arm__ ) && !defined( __hppa ) +# include + +#elif defined(__GNUC__) && ( defined( __sparcv8 ) || defined( __sparcv9 ) ) +# include + +#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) +# include + +#elif !defined( BOOST_HAS_THREADS ) +# include + +#else +# include + +#endif + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_base_acc_ia64.hpp b/win32/include/boost/detail/sp_counted_base_acc_ia64.hpp new file mode 100755 index 000000000..9a89300cc --- /dev/null +++ b/win32/include/boost/detail/sp_counted_base_acc_ia64.hpp @@ -0,0 +1,150 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED + +// +// detail/sp_counted_base_acc_ia64.hpp - aC++ on HP-UX IA64 +// +// Copyright 2007 Baruch Zilber +// Copyright 2007 Boris Gubenko +// +// 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) +// +// +// Lock-free algorithm by Alexander Terekhov +// + +#include +#include + +namespace boost +{ + +namespace detail +{ + +inline void atomic_increment( int * pw ) +{ + // ++*pw; + + _Asm_fetchadd(_FASZ_W, _SEM_REL, pw, +1, _LDHINT_NONE); +} + +inline int atomic_decrement( int * pw ) +{ + // return --*pw; + + int r = static_cast(_Asm_fetchadd(_FASZ_W, _SEM_REL, pw, -1, _LDHINT_NONE)); + if (1 == r) + { + _Asm_mf(); + } + + return r - 1; +} + +inline int atomic_conditional_increment( int * pw ) +{ + // if( *pw != 0 ) ++*pw; + // return *pw; + + int v = *pw; + + for (;;) + { + if (0 == v) + { + return 0; + } + + _Asm_mov_to_ar(_AREG_CCV, + v, + (_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE)); + int r = static_cast(_Asm_cmpxchg(_SZ_W, _SEM_ACQ, pw, v + 1, _LDHINT_NONE)); + if (r == v) + { + return r + 1; + } + + v = r; + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); // TODO use ld.acq here + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_base_cw_ppc.hpp b/win32/include/boost/detail/sp_counted_base_cw_ppc.hpp new file mode 100755 index 000000000..2513482f6 --- /dev/null +++ b/win32/include/boost/detail/sp_counted_base_cw_ppc.hpp @@ -0,0 +1,170 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_cw_ppc.hpp - CodeWarrior on PowerPC +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// +// 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) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include + +namespace boost +{ + +namespace detail +{ + +inline void atomic_increment( register long * pw ) +{ + register int a; + + asm + { +loop: + + lwarx a, 0, pw + addi a, a, 1 + stwcx. a, 0, pw + bne- loop + } +} + +inline long atomic_decrement( register long * pw ) +{ + register int a; + + asm + { + sync + +loop: + + lwarx a, 0, pw + addi a, a, -1 + stwcx. a, 0, pw + bne- loop + + isync + } + + return a; +} + +inline long atomic_conditional_increment( register long * pw ) +{ + register int a; + + asm + { +loop: + + lwarx a, 0, pw + cmpwi a, 0 + beq store + + addi a, a, 1 + +store: + + stwcx. a, 0, pw + bne- loop + } + + return a; +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + long use_count_; // #shared + long weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_base_cw_x86.hpp b/win32/include/boost/detail/sp_counted_base_cw_x86.hpp new file mode 100755 index 000000000..741c961be --- /dev/null +++ b/win32/include/boost/detail/sp_counted_base_cw_x86.hpp @@ -0,0 +1,158 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_cw_x86.hpp - CodeWarrion on 486+ +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// Copyright 2005 Rene Rivera +// +// 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) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include + +namespace boost +{ + +namespace detail +{ + +inline int atomic_exchange_and_add( int * pw, int dv ) +{ + // int r = *pw; + // *pw += dv; + // return r; + + asm + { + mov esi, [pw] + mov eax, dv + lock xadd dword ptr [esi], eax + } +} + +inline void atomic_increment( int * pw ) +{ + //atomic_exchange_and_add( pw, 1 ); + + asm + { + mov esi, [pw] + lock inc dword ptr [esi] + } +} + +inline int atomic_conditional_increment( int * pw ) +{ + // int rv = *pw; + // if( rv != 0 ) ++*pw; + // return rv; + + asm + { + mov esi, [pw] + mov eax, dword ptr [esi] + L0: + test eax, eax + je L1 + mov ebx, eax + inc ebx + lock cmpxchg dword ptr [esi], ebx + jne L0 + L1: + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_exchange_and_add( &use_count_, -1 ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_base_gcc_ia64.hpp b/win32/include/boost/detail/sp_counted_base_gcc_ia64.hpp new file mode 100755 index 000000000..fa31eb73b --- /dev/null +++ b/win32/include/boost/detail/sp_counted_base_gcc_ia64.hpp @@ -0,0 +1,157 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED + +// +// detail/sp_counted_base_gcc_ia64.hpp - g++ on IA64 +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2006 Peter Dimov +// Copyright 2005 Ben Hutchings +// +// 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) +// +// +// Lock-free algorithm by Alexander Terekhov +// + +#include + +namespace boost +{ + +namespace detail +{ + +inline void atomic_increment( int * pw ) +{ + // ++*pw; + + int tmp; + + // No barrier is required here but fetchadd always has an acquire or + // release barrier associated with it. We choose release as it should be + // cheaper. + __asm__ ("fetchadd4.rel %0=%1,1" : + "=r"(tmp), "=m"(*pw) : + "m"( *pw )); +} + +inline int atomic_decrement( int * pw ) +{ + // return --*pw; + + int rv; + + __asm__ (" fetchadd4.rel %0=%1,-1 ;; \n" + " cmp.eq p7,p0=1,%0 ;; \n" + "(p7) ld4.acq %0=%1 " : + "=&r"(rv), "=m"(*pw) : + "m"( *pw ) : + "p7"); + + return rv; +} + +inline int atomic_conditional_increment( int * pw ) +{ + // if( *pw != 0 ) ++*pw; + // return *pw; + + int rv, tmp, tmp2; + + __asm__ ("0: ld4 %0=%3 ;; \n" + " cmp.eq p7,p0=0,%0 ;; \n" + "(p7) br.cond.spnt 1f \n" + " mov ar.ccv=%0 \n" + " add %1=1,%0 ;; \n" + " cmpxchg4.acq %2=%3,%1,ar.ccv ;; \n" + " cmp.ne p7,p0=%0,%2 ;; \n" + "(p7) br.cond.spnt 0b \n" + " mov %0=%1 ;; \n" + "1:" : + "=&r"(rv), "=&r"(tmp), "=&r"(tmp2), "=m"(*pw) : + "m"( *pw ) : + "ar.ccv", "p7"); + + return rv; +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); // TODO use ld.acq here + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_base_gcc_ppc.hpp b/win32/include/boost/detail/sp_counted_base_gcc_ppc.hpp new file mode 100755 index 000000000..dfa95332b --- /dev/null +++ b/win32/include/boost/detail/sp_counted_base_gcc_ppc.hpp @@ -0,0 +1,181 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_gcc_ppc.hpp - g++ on PowerPC +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// +// 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) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include + +namespace boost +{ + +namespace detail +{ + +inline void atomic_increment( int * pw ) +{ + // ++*pw; + + int tmp; + + __asm__ + ( + "0:\n\t" + "lwarx %1, 0, %2\n\t" + "addi %1, %1, 1\n\t" + "stwcx. %1, 0, %2\n\t" + "bne- 0b": + + "=m"( *pw ), "=&b"( tmp ): + "r"( pw ), "m"( *pw ): + "cc" + ); +} + +inline int atomic_decrement( int * pw ) +{ + // return --*pw; + + int rv; + + __asm__ __volatile__ + ( + "sync\n\t" + "0:\n\t" + "lwarx %1, 0, %2\n\t" + "addi %1, %1, -1\n\t" + "stwcx. %1, 0, %2\n\t" + "bne- 0b\n\t" + "isync": + + "=m"( *pw ), "=&b"( rv ): + "r"( pw ), "m"( *pw ): + "memory", "cc" + ); + + return rv; +} + +inline int atomic_conditional_increment( int * pw ) +{ + // if( *pw != 0 ) ++*pw; + // return *pw; + + int rv; + + __asm__ + ( + "0:\n\t" + "lwarx %1, 0, %2\n\t" + "cmpwi %1, 0\n\t" + "beq 1f\n\t" + "addi %1, %1, 1\n\t" + "1:\n\t" + "stwcx. %1, 0, %2\n\t" + "bne- 0b": + + "=m"( *pw ), "=&b"( rv ): + "r"( pw ), "m"( *pw ): + "cc" + ); + + return rv; +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_base_gcc_sparc.hpp b/win32/include/boost/detail/sp_counted_base_gcc_sparc.hpp new file mode 100755 index 000000000..a53dc76ec --- /dev/null +++ b/win32/include/boost/detail/sp_counted_base_gcc_sparc.hpp @@ -0,0 +1,166 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_counted_base_gcc_sparc.hpp - g++ on Sparc V8+ +// +// Copyright (c) 2006 Piotr Wyderski +// Copyright (c) 2006 Tomas Puverle +// Copyright (c) 2006 Peter Dimov +// +// 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 +// +// Thanks to Michael van der Westhuizen + +#include +#include // int32_t + +namespace boost +{ + +namespace detail +{ + +inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ ) +{ + __asm__ __volatile__( "cas %0, %2, %1" + : "+m" (*dest_), "+r" (swap_) + : "r" (compare_) + : "memory" ); + + return swap_; +} + +inline int32_t atomic_fetch_and_add( int32_t * pw, int32_t dv ) +{ + // long r = *pw; + // *pw += dv; + // return r; + + for( ;; ) + { + int32_t r = *pw; + + if( __builtin_expect((compare_and_swap(pw, r, r + dv) == r), 1) ) + { + return r; + } + } +} + +inline void atomic_increment( int32_t * pw ) +{ + atomic_fetch_and_add( pw, 1 ); +} + +inline int32_t atomic_decrement( int32_t * pw ) +{ + return atomic_fetch_and_add( pw, -1 ); +} + +inline int32_t atomic_conditional_increment( int32_t * pw ) +{ + // long r = *pw; + // if( r != 0 ) ++*pw; + // return r; + + for( ;; ) + { + int32_t r = *pw; + + if( r == 0 ) + { + return r; + } + + if( __builtin_expect( ( compare_and_swap( pw, r, r + 1 ) == r ), 1 ) ) + { + return r; + } + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int32_t use_count_; // #shared + int32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return const_cast< int32_t const volatile & >( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_base_gcc_x86.hpp b/win32/include/boost/detail/sp_counted_base_gcc_x86.hpp new file mode 100755 index 000000000..d13b8edcf --- /dev/null +++ b/win32/include/boost/detail/sp_counted_base_gcc_x86.hpp @@ -0,0 +1,173 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_gcc_x86.hpp - g++ on 486+ or AMD64 +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// +// 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) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include + +namespace boost +{ + +namespace detail +{ + +inline int atomic_exchange_and_add( int * pw, int dv ) +{ + // int r = *pw; + // *pw += dv; + // return r; + + int r; + + __asm__ __volatile__ + ( + "lock\n\t" + "xadd %1, %0": + "=m"( *pw ), "=r"( r ): // outputs (%0, %1) + "m"( *pw ), "1"( dv ): // inputs (%2, %3 == %1) + "memory", "cc" // clobbers + ); + + return r; +} + +inline void atomic_increment( int * pw ) +{ + //atomic_exchange_and_add( pw, 1 ); + + __asm__ + ( + "lock\n\t" + "incl %0": + "=m"( *pw ): // output (%0) + "m"( *pw ): // input (%1) + "cc" // clobbers + ); +} + +inline int atomic_conditional_increment( int * pw ) +{ + // int rv = *pw; + // if( rv != 0 ) ++*pw; + // return rv; + + int rv, tmp; + + __asm__ + ( + "movl %0, %%eax\n\t" + "0:\n\t" + "test %%eax, %%eax\n\t" + "je 1f\n\t" + "movl %%eax, %2\n\t" + "incl %2\n\t" + "lock\n\t" + "cmpxchgl %2, %0\n\t" + "jne 0b\n\t" + "1:": + "=m"( *pw ), "=&a"( rv ), "=&r"( tmp ): // outputs (%0, %1, %2) + "m"( *pw ): // input (%3) + "cc" // clobbers + ); + + return rv; +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_exchange_and_add( &use_count_, -1 ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_base_nt.hpp b/win32/include/boost/detail/sp_counted_base_nt.hpp new file mode 100755 index 000000000..bc0cf9544 --- /dev/null +++ b/win32/include/boost/detail/sp_counted_base_nt.hpp @@ -0,0 +1,107 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_nt.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// +// 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) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + long use_count_; // #shared + long weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + ++use_count_; + } + + bool add_ref_lock() // true on success + { + if( use_count_ == 0 ) return false; + ++use_count_; + return true; + } + + void release() // nothrow + { + if( --use_count_ == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + ++weak_count_; + } + + void weak_release() // nothrow + { + if( --weak_count_ == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return use_count_; + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_base_pt.hpp b/win32/include/boost/detail/sp_counted_base_pt.hpp new file mode 100755 index 000000000..32e874a71 --- /dev/null +++ b/win32/include/boost/detail/sp_counted_base_pt.hpp @@ -0,0 +1,135 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_pt.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// +// 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) +// + +#include +#include + +namespace boost +{ + +namespace detail +{ + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + long use_count_; // #shared + long weak_count_; // #weak + (#shared != 0) + + mutable pthread_mutex_t m_; + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { +// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init + +#if defined(__hpux) && defined(_DECTHREADS_) + pthread_mutex_init( &m_, pthread_mutexattr_default ); +#else + pthread_mutex_init( &m_, 0 ); +#endif + } + + virtual ~sp_counted_base() // nothrow + { + pthread_mutex_destroy( &m_ ); + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + pthread_mutex_lock( &m_ ); + ++use_count_; + pthread_mutex_unlock( &m_ ); + } + + bool add_ref_lock() // true on success + { + pthread_mutex_lock( &m_ ); + bool r = use_count_ == 0? false: ( ++use_count_, true ); + pthread_mutex_unlock( &m_ ); + return r; + } + + void release() // nothrow + { + pthread_mutex_lock( &m_ ); + long new_use_count = --use_count_; + pthread_mutex_unlock( &m_ ); + + if( new_use_count == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + pthread_mutex_lock( &m_ ); + ++weak_count_; + pthread_mutex_unlock( &m_ ); + } + + void weak_release() // nothrow + { + pthread_mutex_lock( &m_ ); + long new_weak_count = --weak_count_; + pthread_mutex_unlock( &m_ ); + + if( new_weak_count == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + pthread_mutex_lock( &m_ ); + long r = use_count_; + pthread_mutex_unlock( &m_ ); + + return r; + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_base_solaris.hpp b/win32/include/boost/detail/sp_counted_base_solaris.hpp new file mode 100755 index 000000000..85f3d29bc --- /dev/null +++ b/win32/include/boost/detail/sp_counted_base_solaris.hpp @@ -0,0 +1,113 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED + +// +// detail/sp_counted_base_solaris.hpp +// based on: detail/sp_counted_base_w32.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// Copyright 2006 Michael van der Westhuizen +// +// 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) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include +#include + +namespace boost +{ + +namespace detail +{ + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + uint32_t use_count_; // #shared + uint32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_inc_32( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + for( ;; ) + { + uint32_t tmp = static_cast< uint32_t const volatile& >( use_count_ ); + if( tmp == 0 ) return false; + if( atomic_cas_32( &use_count_, tmp, tmp + 1 ) == tmp ) return true; + } + } + + void release() // nothrow + { + if( atomic_dec_32_nv( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_inc_32( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_dec_32_nv( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_base_spin.hpp b/win32/include/boost/detail/sp_counted_base_spin.hpp new file mode 100755 index 000000000..867c47e20 --- /dev/null +++ b/win32/include/boost/detail/sp_counted_base_spin.hpp @@ -0,0 +1,131 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_spin.hpp - spinlock pool atomic emulation +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2008 Peter Dimov +// +// 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) +// + +#include +#include + +namespace boost +{ + +namespace detail +{ + +inline int atomic_exchange_and_add( int * pw, int dv ) +{ + spinlock_pool<1>::scoped_lock lock( pw ); + + int r = *pw; + *pw += dv; + return r; +} + +inline void atomic_increment( int * pw ) +{ + spinlock_pool<1>::scoped_lock lock( pw ); + ++*pw; +} + +inline int atomic_conditional_increment( int * pw ) +{ + spinlock_pool<1>::scoped_lock lock( pw ); + + int rv = *pw; + if( rv != 0 ) ++*pw; + return rv; +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + int use_count_; // #shared + int weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_exchange_and_add( &use_count_, -1 ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + spinlock_pool<1>::scoped_lock lock( &use_count_ ); + return use_count_; + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_base_sync.hpp b/win32/include/boost/detail/sp_counted_base_sync.hpp new file mode 100755 index 000000000..fc4086a26 --- /dev/null +++ b/win32/include/boost/detail/sp_counted_base_sync.hpp @@ -0,0 +1,155 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_counted_base_sync.hpp - g++ 4.1+ __sync intrinsics +// +// Copyright (c) 2007 Peter Dimov +// +// 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 + +#include +#include + +#if defined( __ia64__ ) && defined( __INTEL_COMPILER ) +# include +#endif + +namespace boost +{ + +namespace detail +{ + +#if INT_MAX >= 2147483647 + +typedef int sp_int32_t; + +#else + +typedef long sp_int32_t; + +#endif + +inline void atomic_increment( sp_int32_t * pw ) +{ + __sync_fetch_and_add( pw, 1 ); +} + +inline sp_int32_t atomic_decrement( sp_int32_t * pw ) +{ + return __sync_fetch_and_add( pw, -1 ); +} + +inline sp_int32_t atomic_conditional_increment( sp_int32_t * pw ) +{ + // long r = *pw; + // if( r != 0 ) ++*pw; + // return r; + + sp_int32_t r = *pw; + + for( ;; ) + { + if( r == 0 ) + { + return r; + } + + sp_int32_t r2 = __sync_val_compare_and_swap( pw, r, r + 1 ); + + if( r2 == r ) + { + return r; + } + else + { + r = r2; + } + } +} + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + sp_int32_t use_count_; // #shared + sp_int32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + atomic_increment( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + return atomic_conditional_increment( &use_count_ ) != 0; + } + + void release() // nothrow + { + if( atomic_decrement( &use_count_ ) == 1 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + atomic_increment( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( atomic_decrement( &weak_count_ ) == 1 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return const_cast< sp_int32_t const volatile & >( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_base_w32.hpp b/win32/include/boost/detail/sp_counted_base_w32.hpp new file mode 100755 index 000000000..0e9921475 --- /dev/null +++ b/win32/include/boost/detail/sp_counted_base_w32.hpp @@ -0,0 +1,130 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_base_w32.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// +// 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) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include +#include +#include + +namespace boost +{ + +namespace detail +{ + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + long use_count_; // #shared + long weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + { + } + + virtual ~sp_counted_base() // nothrow + { + } + + // dispose() is called when use_count_ drops to zero, to release + // the resources managed by *this. + + virtual void dispose() = 0; // nothrow + + // destroy() is called when weak_count_ drops to zero. + + virtual void destroy() // nothrow + { + delete this; + } + + virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + + void add_ref_copy() + { + BOOST_INTERLOCKED_INCREMENT( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + for( ;; ) + { + long tmp = static_cast< long const volatile& >( use_count_ ); + if( tmp == 0 ) return false; + +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1200 ) + + // work around a code generation bug + + long tmp2 = tmp + 1; + if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true; + +#else + + if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true; + +#endif + } + } + + void release() // nothrow + { + if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 ) + { + dispose(); + weak_release(); + } + } + + void weak_add_ref() // nothrow + { + BOOST_INTERLOCKED_INCREMENT( &weak_count_ ); + } + + void weak_release() // nothrow + { + if( BOOST_INTERLOCKED_DECREMENT( &weak_count_ ) == 0 ) + { + destroy(); + } + } + + long use_count() const // nothrow + { + return static_cast( use_count_ ); + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_counted_impl.hpp b/win32/include/boost/detail/sp_counted_impl.hpp new file mode 100755 index 000000000..c3519a3a2 --- /dev/null +++ b/win32/include/boost/detail/sp_counted_impl.hpp @@ -0,0 +1,231 @@ +#ifndef BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED +#define BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/sp_counted_impl.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// +// 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) +// + +#include + +#if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR) +# error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible. +#endif + +#include +#include + +#if defined(BOOST_SP_USE_QUICK_ALLOCATOR) +#include +#endif + +#if defined(BOOST_SP_USE_STD_ALLOCATOR) +#include // std::allocator +#endif + +#include // std::size_t + +namespace boost +{ + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +void sp_scalar_constructor_hook( void * px, std::size_t size, void * pn ); +void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn ); + +#endif + +namespace detail +{ + +template class sp_counted_impl_p: public sp_counted_base +{ +private: + + X * px_; + + sp_counted_impl_p( sp_counted_impl_p const & ); + sp_counted_impl_p & operator= ( sp_counted_impl_p const & ); + + typedef sp_counted_impl_p this_type; + +public: + + explicit sp_counted_impl_p( X * px ): px_( px ) + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_constructor_hook( px, sizeof(X), this ); +#endif + } + + virtual void dispose() // nothrow + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_destructor_hook( px_, sizeof(X), this ); +#endif + boost::checked_delete( px_ ); + } + + virtual void * get_deleter( detail::sp_typeinfo const & ) + { + return 0; + } + +#if defined(BOOST_SP_USE_STD_ALLOCATOR) + + void * operator new( std::size_t ) + { + return std::allocator().allocate( 1, static_cast(0) ); + } + + void operator delete( void * p ) + { + std::allocator().deallocate( static_cast(p), 1 ); + } + +#endif + +#if defined(BOOST_SP_USE_QUICK_ALLOCATOR) + + void * operator new( std::size_t ) + { + return quick_allocator::alloc(); + } + + void operator delete( void * p ) + { + quick_allocator::dealloc( p ); + } + +#endif +}; + +// +// Borland's Codeguard trips up over the -Vx- option here: +// +#ifdef __CODEGUARD__ +# pragma option push -Vx- +#endif + +template class sp_counted_impl_pd: public sp_counted_base +{ +private: + + P ptr; // copy constructor must not throw + D del; // copy constructor must not throw + + sp_counted_impl_pd( sp_counted_impl_pd const & ); + sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & ); + + typedef sp_counted_impl_pd this_type; + +public: + + // pre: d(p) must not throw + + sp_counted_impl_pd( P p, D d ): ptr(p), del(d) + { + } + + virtual void dispose() // nothrow + { + del( ptr ); + } + + virtual void * get_deleter( detail::sp_typeinfo const & ti ) + { + return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast( del ): 0; + } + +#if defined(BOOST_SP_USE_STD_ALLOCATOR) + + void * operator new( std::size_t ) + { + return std::allocator().allocate( 1, static_cast(0) ); + } + + void operator delete( void * p ) + { + std::allocator().deallocate( static_cast(p), 1 ); + } + +#endif + +#if defined(BOOST_SP_USE_QUICK_ALLOCATOR) + + void * operator new( std::size_t ) + { + return quick_allocator::alloc(); + } + + void operator delete( void * p ) + { + quick_allocator::dealloc( p ); + } + +#endif +}; + +template class sp_counted_impl_pda: public sp_counted_base +{ +private: + + P p_; // copy constructor must not throw + D d_; // copy constructor must not throw + A a_; // copy constructor must not throw + + sp_counted_impl_pda( sp_counted_impl_pda const & ); + sp_counted_impl_pda & operator= ( sp_counted_impl_pda const & ); + + typedef sp_counted_impl_pda this_type; + +public: + + // pre: d( p ) must not throw + + sp_counted_impl_pda( P p, D d, A a ): p_( p ), d_( d ), a_( a ) + { + } + + virtual void dispose() // nothrow + { + d_( p_ ); + } + + virtual void destroy() // nothrow + { + typedef typename A::template rebind< this_type >::other A2; + + A2 a2( a_ ); + + this->~this_type(); + a2.deallocate( this, 1 ); + } + + virtual void * get_deleter( detail::sp_typeinfo const & ti ) + { + return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast( d_ ): 0; + } +}; + +#ifdef __CODEGUARD__ +# pragma option pop +#endif + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED diff --git a/win32/include/boost/detail/sp_typeinfo.hpp b/win32/include/boost/detail/sp_typeinfo.hpp new file mode 100755 index 000000000..1db461425 --- /dev/null +++ b/win32/include/boost/detail/sp_typeinfo.hpp @@ -0,0 +1,83 @@ +#ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED +#define BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/sp_typeinfo.hpp +// +// Copyright 2007 Peter Dimov +// +// 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) + +#include + +#if defined( BOOST_NO_TYPEID ) + +namespace boost +{ + +namespace detail +{ + +typedef void* sp_typeinfo; + +template struct sp_typeid_ +{ + static char v_; +}; + +template char sp_typeid_< T >::v_; + +template struct sp_typeid_< T const >: sp_typeid_< T > +{ +}; + +template struct sp_typeid_< T volatile >: sp_typeid_< T > +{ +}; + +template struct sp_typeid_< T const volatile >: sp_typeid_< T > +{ +}; + +} // namespace detail + +} // namespace boost + +#define BOOST_SP_TYPEID(T) (&boost::detail::sp_typeid_::v_) + +#else + +#include + +namespace boost +{ + +namespace detail +{ + +#if defined( BOOST_NO_STD_TYPEINFO ) + +typedef ::type_info sp_typeinfo; + +#else + +typedef std::type_info sp_typeinfo; + +#endif + +} // namespace detail + +} // namespace boost + +#define BOOST_SP_TYPEID(T) typeid(T) + +#endif + +#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED diff --git a/win32/include/boost/detail/spinlock.hpp b/win32/include/boost/detail/spinlock.hpp new file mode 100755 index 000000000..4d37c2294 --- /dev/null +++ b/win32/include/boost/detail/spinlock.hpp @@ -0,0 +1,47 @@ +#ifndef BOOST_DETAIL_SPINLOCK_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/spinlock.hpp +// +// Copyright (c) 2008 Peter Dimov +// +// 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) +// +// struct spinlock +// { +// void lock(); +// bool try_lock(); +// void unlock(); +// +// class scoped_lock; +// }; +// +// #define BOOST_DETAIL_SPINLOCK_INIT +// + +#include + +#if defined(__GNUC__) && defined( __arm__ ) +# include +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) +# include +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# include +#elif defined(BOOST_HAS_PTHREADS) +# include +#elif !defined(BOOST_HAS_THREADS) +# include +#else +# error Unrecognized threading platform +#endif + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_HPP_INCLUDED diff --git a/win32/include/boost/detail/spinlock_gcc_arm.hpp b/win32/include/boost/detail/spinlock_gcc_arm.hpp new file mode 100755 index 000000000..d9ec56d99 --- /dev/null +++ b/win32/include/boost/detail/spinlock_gcc_arm.hpp @@ -0,0 +1,85 @@ +#ifndef BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED + +// +// Copyright (c) 2008 Peter Dimov +// +// 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) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + int v_; + +public: + + bool try_lock() + { + int r; + + __asm__ __volatile__( + "swp %0, %1, [%2]": + "=&r"( r ): // outputs + "r"( 1 ), "r"( &v_ ): // inputs + "memory", "cc" ); + + return r == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + __asm__ __volatile__( "" ::: "memory" ); + *const_cast< int volatile* >( &v_ ) = 0; + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {0} + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED diff --git a/win32/include/boost/detail/spinlock_nt.hpp b/win32/include/boost/detail/spinlock_nt.hpp new file mode 100755 index 000000000..05d9d516b --- /dev/null +++ b/win32/include/boost/detail/spinlock_nt.hpp @@ -0,0 +1,89 @@ +#ifndef BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 Peter Dimov +// +// 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) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + bool locked_; + +public: + + inline bool try_lock() + { + if( locked_ ) + { + return false; + } + else + { + locked_ = true; + return true; + } + } + + inline void lock() + { + BOOST_ASSERT( !locked_ ); + locked_ = true; + } + + inline void unlock() + { + BOOST_ASSERT( locked_ ); + locked_ = false; + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT { false } + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_NT_HPP_INCLUDED diff --git a/win32/include/boost/detail/spinlock_pool.hpp b/win32/include/boost/detail/spinlock_pool.hpp new file mode 100755 index 000000000..1e45d8bd3 --- /dev/null +++ b/win32/include/boost/detail/spinlock_pool.hpp @@ -0,0 +1,87 @@ +#ifndef BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/spinlock_pool.hpp +// +// Copyright (c) 2008 Peter Dimov +// +// 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) +// +// spinlock_pool<0> is reserved for atomic<>, when/if it arrives +// spinlock_pool<1> is reserved for shared_ptr reference counts +// spinlock_pool<2> is reserved for shared_ptr atomic access +// + +#include +#include +#include + +namespace boost +{ + +namespace detail +{ + +template< int I > class spinlock_pool +{ +private: + + static spinlock pool_[ 41 ]; + +public: + + static spinlock & spinlock_for( void const * pv ) + { + std::size_t i = reinterpret_cast< std::size_t >( pv ) % 41; + return pool_[ i ]; + } + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( void const * pv ): sp_( spinlock_for( pv ) ) + { + sp_.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +template< int I > spinlock spinlock_pool< I >::pool_[ 41 ] = +{ + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, + BOOST_DETAIL_SPINLOCK_INIT +}; + +} // namespace detail +} // namespace boost + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_POOL_HPP_INCLUDED diff --git a/win32/include/boost/detail/spinlock_pt.hpp b/win32/include/boost/detail/spinlock_pt.hpp new file mode 100755 index 000000000..6cd3d2523 --- /dev/null +++ b/win32/include/boost/detail/spinlock_pt.hpp @@ -0,0 +1,79 @@ +#ifndef BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 Peter Dimov +// +// 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) +// + +#include + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + pthread_mutex_t v_; + +public: + + bool try_lock() + { + return pthread_mutex_trylock( &v_ ) == 0; + } + + void lock() + { + pthread_mutex_lock( &v_ ); + } + + void unlock() + { + pthread_mutex_unlock( &v_ ); + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT { PTHREAD_MUTEX_INITIALIZER } + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_PT_HPP_INCLUDED diff --git a/win32/include/boost/detail/spinlock_sync.hpp b/win32/include/boost/detail/spinlock_sync.hpp new file mode 100755 index 000000000..20faa7023 --- /dev/null +++ b/win32/include/boost/detail/spinlock_sync.hpp @@ -0,0 +1,87 @@ +#ifndef BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 Peter Dimov +// +// 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) +// + +#include + +#if defined( __ia64__ ) && defined( __INTEL_COMPILER ) +# include +#endif + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + int v_; + +public: + + bool try_lock() + { + int r = __sync_lock_test_and_set( &v_, 1 ); + return r == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + __sync_lock_release( &v_ ); + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {0} + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED diff --git a/win32/include/boost/detail/spinlock_w32.hpp b/win32/include/boost/detail/spinlock_w32.hpp new file mode 100755 index 000000000..d12c91282 --- /dev/null +++ b/win32/include/boost/detail/spinlock_w32.hpp @@ -0,0 +1,113 @@ +#ifndef BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED +#define BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2008 Peter Dimov +// +// 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) +// + +#include +#include + +// BOOST_COMPILER_FENCE + +#if defined(__INTEL_COMPILER) + +#define BOOST_COMPILER_FENCE __memory_barrier(); + +#elif defined( _MSC_VER ) && _MSC_VER >= 1310 + +extern "C" void _ReadWriteBarrier(); +#pragma intrinsic( _ReadWriteBarrier ) + +#define BOOST_COMPILER_FENCE _ReadWriteBarrier(); + +#elif defined(__GNUC__) + +#define BOOST_COMPILER_FENCE __asm__ __volatile__( "" : : : "memory" ); + +#else + +#define BOOST_COMPILER_FENCE + +#endif + +// + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + long v_; + +public: + + bool try_lock() + { + long r = BOOST_INTERLOCKED_EXCHANGE( &v_, 1 ); + + BOOST_COMPILER_FENCE + + return r == 0; + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + BOOST_COMPILER_FENCE + *const_cast< long volatile* >( &v_ ) = 0; + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT {0} + +#endif // #ifndef BOOST_DETAIL_SPINLOCK_W32_HPP_INCLUDED diff --git a/win32/include/boost/detail/templated_streams.hpp b/win32/include/boost/detail/templated_streams.hpp new file mode 100755 index 000000000..a0527fe88 --- /dev/null +++ b/win32/include/boost/detail/templated_streams.hpp @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// boost detail/templated_streams.hpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2003 +// Eric Friedman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_DETAIL_TEMPLATED_STREAMS_HPP +#define BOOST_DETAIL_TEMPLATED_STREAMS_HPP + +#include "boost/config.hpp" + +/////////////////////////////////////////////////////////////////////////////// +// (detail) BOOST_TEMPLATED_STREAM_* macros +// +// Provides workaround platforms without stream class templates. +// + +#if !defined(BOOST_NO_STD_LOCALE) + +#define BOOST_TEMPLATED_STREAM_TEMPLATE(E,T) \ + template < typename E , typename T > + +#define BOOST_TEMPLATED_STREAM_TEMPLATE_ALLOC(E,T,A) \ + template < typename E , typename T , typename A > + +#define BOOST_TEMPLATED_STREAM_ARGS(E,T) \ + typename E , typename T + +#define BOOST_TEMPLATED_STREAM_ARGS_ALLOC(E,T,A) \ + typename E , typename T , typename A + +#define BOOST_TEMPLATED_STREAM_COMMA , + +#define BOOST_TEMPLATED_STREAM_ELEM(E) E +#define BOOST_TEMPLATED_STREAM_TRAITS(T) T +#define BOOST_TEMPLATED_STREAM_ALLOC(A) A + +#define BOOST_TEMPLATED_STREAM(X,E,T) \ + BOOST_JOIN(std::basic_,X)< E , T > + +#define BOOST_TEMPLATED_STREAM_WITH_ALLOC(X,E,T,A) \ + BOOST_JOIN(std::basic_,X)< E , T , A > + +#else // defined(BOOST_NO_STD_LOCALE) + +#define BOOST_TEMPLATED_STREAM_TEMPLATE(E,T) /**/ + +#define BOOST_TEMPLATED_STREAM_TEMPLATE_ALLOC(E,T,A) /**/ + +#define BOOST_TEMPLATED_STREAM_ARGS(E,T) /**/ + +#define BOOST_TEMPLATED_STREAM_ARGS_ALLOC(E,T,A) /**/ + +#define BOOST_TEMPLATED_STREAM_COMMA /**/ + +#define BOOST_TEMPLATED_STREAM_ELEM(E) char +#define BOOST_TEMPLATED_STREAM_TRAITS(T) std::char_traits +#define BOOST_TEMPLATED_STREAM_ALLOC(A) std::allocator + +#define BOOST_TEMPLATED_STREAM(X,E,T) \ + std::X + +#define BOOST_TEMPLATED_STREAM_WITH_ALLOC(X,E,T,A) \ + std::X + +#endif // BOOST_NO_STD_LOCALE + +#endif // BOOST_DETAIL_TEMPLATED_STREAMS_HPP diff --git a/win32/include/boost/detail/utf8_codecvt_facet.hpp b/win32/include/boost/detail/utf8_codecvt_facet.hpp new file mode 100755 index 000000000..e6e62c7e6 --- /dev/null +++ b/win32/include/boost/detail/utf8_codecvt_facet.hpp @@ -0,0 +1,197 @@ +// Copyright © 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu) +// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu). +// Distributed under the Boost Software License, Version 1.0. (See accompany- +// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_UTF8_CODECVT_FACET_HPP +#define BOOST_UTF8_CODECVT_FACET_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// utf8_codecvt_facet.hpp + +// This header defines class utf8_codecvt_facet, derived fro +// std::codecvt, which can be used to convert utf8 data in +// files into wchar_t strings in the application. +// +// The header is NOT STANDALONE, and is not to be included by the USER. +// There are at least two libraries which want to use this functionality, and +// we want to avoid code duplication. It would be possible to create utf8 +// library, but: +// - this requires review process first +// - in the case, when linking the a library which uses utf8 +// (say 'program_options'), user should also link to the utf8 library. +// This seems inconvenient, and asking a user to link to an unrevieved +// library is strange. +// Until the above points are fixed, a library which wants to use utf8 must: +// - include this header from one of it's headers or sources +// - include the corresponding .cpp file from one of the sources +// - before including either file, the library must define +// - BOOST_UTF8_BEGIN_NAMESPACE to the namespace declaration that must be used +// - BOOST_UTF8_END_NAMESPACE to the code to close the previous namespace +// - declaration. +// - BOOST_UTF8_DECL -- to the code which must be used for all 'exportable' +// symbols. +// +// For example, program_options library might contain: +// #define BOOST_UTF8_BEGIN_NAMESPACE +// namespace boost { namespace program_options { +// #define BOOST_UTF8_END_NAMESPACE }} +// #define BOOST_UTF8_DECL BOOST_PROGRAM_OPTIONS_DECL +// #include "../../detail/utf8/utf8_codecvt.cpp" +// +// Essentially, each library will have its own copy of utf8 code, in +// different namespaces. + +// Note:(Robert Ramey). I have made the following alterations in the original +// code. +// a) Rendered utf8_codecvt with using templates +// b) Move longer functions outside class definition to prevent inlining +// and make code smaller +// c) added on a derived class to permit translation to/from current +// locale to utf8 + +// See http://www.boost.org for updates, documentation, and revision history. + +// archives stored as text - note these ar templated on the basic +// stream templates to accommodate wide (and other?) kind of characters +// +// note the fact that on libraries without wide characters, ostream is +// is not a specialization of basic_ostream which in fact is not defined +// in such cases. So we can't use basic_ostream but rather +// use two template parameters +// +// utf8_codecvt_facet +// This is an implementation of a std::codecvt facet for translating +// from UTF-8 externally to UCS-4. Note that this is not tied to +// any specific types in order to allow customization on platforms +// where wchar_t is not big enough. +// +// NOTES: The current implementation jumps through some unpleasant hoops in +// order to deal with signed character types. As a std::codecvt_base::result, +// it is necessary for the ExternType to be convertible to unsigned char. +// I chose not to tie the extern_type explicitly to char. But if any combination +// of types other than is used, then std::codecvt must be +// specialized on those types for this to work. + +#include +// for mbstate_t +#include +// for std::size_t +#include + +#include +#include + +namespace std { + #if defined(__LIBCOMO__) + using ::mbstate_t; + #elif defined(BOOST_DINKUMWARE_STDLIB) && !defined(__BORLANDC__) + using ::mbstate_t; + #elif defined(__SGI_STL_PORT) + #elif defined(BOOST_NO_STDC_NAMESPACE) + using ::mbstate_t; + using ::codecvt; + #endif +} // namespace std + +#if !defined(__MSL_CPP__) && !defined(__LIBCOMO__) + #define BOOST_CODECVT_DO_LENGTH_CONST const +#else + #define BOOST_CODECVT_DO_LENGTH_CONST +#endif + +// maximum lenght of a multibyte string +#define MB_LENGTH_MAX 8 + +BOOST_UTF8_BEGIN_NAMESPACE + +struct BOOST_UTF8_DECL utf8_codecvt_facet : + public std::codecvt +{ +public: + explicit utf8_codecvt_facet(std::size_t no_locale_manage=0) + : std::codecvt(no_locale_manage) + {} +protected: + virtual std::codecvt_base::result do_in( + std::mbstate_t& state, + const char * from, + const char * from_end, + const char * & from_next, + wchar_t * to, + wchar_t * to_end, + wchar_t*& to_next + ) const; + + virtual std::codecvt_base::result do_out( + std::mbstate_t & state, const wchar_t * from, + const wchar_t * from_end, const wchar_t* & from_next, + char * to, char * to_end, char * & to_next + ) const; + + bool invalid_continuing_octet(unsigned char octet_1) const { + return (octet_1 < 0x80|| 0xbf< octet_1); + } + + bool invalid_leading_octet(unsigned char octet_1) const { + return (0x7f < octet_1 && octet_1 < 0xc0) || + (octet_1 > 0xfd); + } + + // continuing octets = octets except for the leading octet + static unsigned int get_cont_octet_count(unsigned char lead_octet) { + return get_octet_count(lead_octet) - 1; + } + + static unsigned int get_octet_count(unsigned char lead_octet); + + // How many "continuing octets" will be needed for this word + // == total octets - 1. + int get_cont_octet_out_count(wchar_t word) const ; + + virtual bool do_always_noconv() const throw() { return false; } + + // UTF-8 isn't really stateful since we rewind on partial conversions + virtual std::codecvt_base::result do_unshift( + std::mbstate_t&, + char * from, + char * /*to*/, + char * & next + ) const + { + next = from; + return ok; + } + + virtual int do_encoding() const throw() { + const int variable_byte_external_encoding=0; + return variable_byte_external_encoding; + } + + // How many char objects can I process to get <= max_limit + // wchar_t objects? + virtual int do_length( + BOOST_CODECVT_DO_LENGTH_CONST std::mbstate_t &, + const char * from, + const char * from_end, + std::size_t max_limit +#if BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) + ) const throw(); +#else + ) const; +#endif + + // Largest possible value do_length(state,from,from_end,1) could return. + virtual int do_max_length() const throw () { + return 6; // largest UTF-8 encoding of a UCS-4 character + } +}; + +BOOST_UTF8_END_NAMESPACE + +#endif // BOOST_UTF8_CODECVT_FACET_HPP diff --git a/win32/include/boost/detail/workaround.hpp b/win32/include/boost/detail/workaround.hpp new file mode 100755 index 000000000..91df358f4 --- /dev/null +++ b/win32/include/boost/detail/workaround.hpp @@ -0,0 +1,202 @@ +// Copyright David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef WORKAROUND_DWA2002126_HPP +# define WORKAROUND_DWA2002126_HPP + +// Compiler/library version workaround macro +// +// Usage: +// +// #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +// // workaround for eVC4 and VC6 +// ... // workaround code here +// #endif +// +// When BOOST_STRICT_CONFIG is defined, expands to 0. Otherwise, the +// first argument must be undefined or expand to a numeric +// value. The above expands to: +// +// (BOOST_MSVC) != 0 && (BOOST_MSVC) < 1300 +// +// When used for workarounds that apply to the latest known version +// and all earlier versions of a compiler, the following convention +// should be observed: +// +// #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1301)) +// +// The version number in this case corresponds to the last version in +// which the workaround was known to have been required. When +// BOOST_DETECT_OUTDATED_WORKAROUNDS is not the defined, the macro +// BOOST_TESTED_AT(x) expands to "!= 0", which effectively activates +// the workaround for any version of the compiler. When +// BOOST_DETECT_OUTDATED_WORKAROUNDS is defined, a compiler warning or +// error will be issued if the compiler version exceeds the argument +// to BOOST_TESTED_AT(). This can be used to locate workarounds which +// may be obsoleted by newer versions. + +# ifndef BOOST_STRICT_CONFIG + +#include + +#ifndef __BORLANDC__ +#define __BORLANDC___WORKAROUND_GUARD 1 +#else +#define __BORLANDC___WORKAROUND_GUARD 0 +#endif +#ifndef __MSC_VER +#define __MSC_VER_WORKAROUND_GUARD 1 +#else +#define __MSC_VER_WORKAROUND_GUARD 0 +#endif +#ifndef _MSC_FULL_VER +#define _MSC_FULL_VER_WORKAROUND_GUARD 1 +#else +#define _MSC_FULL_VER_WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_MSVC +#define BOOST_MSVC_WORKAROUND_GUARD 1 +#else +#define BOOST_MSVC_WORKAROUND_GUARD 0 +#endif +#ifndef __GNUC__ +#define __GNUC___WORKAROUND_GUARD 1 +#else +#define __GNUC___WORKAROUND_GUARD 0 +#endif +#ifndef __GNUC_MINOR__ +#define __GNUC_MINOR___WORKAROUND_GUARD 1 +#else +#define __GNUC_MINOR___WORKAROUND_GUARD 0 +#endif +#ifndef __GNUC_PATCHLEVEL__ +#define __GNUC_PATCHLEVEL___WORKAROUND_GUARD 1 +#else +#define __GNUC_PATCHLEVEL___WORKAROUND_GUARD 0 +#endif +#ifndef __IBMCPP__ +#define __IBMCPP___WORKAROUND_GUARD 1 +#else +#define __IBMCPP___WORKAROUND_GUARD 0 +#endif +#ifndef __SUNPRO_CC +#define __SUNPRO_CC_WORKAROUND_GUARD 1 +#else +#define __SUNPRO_CC_WORKAROUND_GUARD 0 +#endif +#ifndef __DECCXX_VER +#define __DECCXX_VER_WORKAROUND_GUARD 1 +#else +#define __DECCXX_VER_WORKAROUND_GUARD 0 +#endif +#ifndef __MWERKS__ +#define __MWERKS___WORKAROUND_GUARD 1 +#else +#define __MWERKS___WORKAROUND_GUARD 0 +#endif +#ifndef __EDG_VERSION__ +#define __EDG_VERSION___WORKAROUND_GUARD 1 +#else +#define __EDG_VERSION___WORKAROUND_GUARD 0 +#endif +#ifndef __HP_aCC +#define __HP_aCC_WORKAROUND_GUARD 1 +#else +#define __HP_aCC_WORKAROUND_GUARD 0 +#endif +#ifndef _CRAYC +#define _CRAYC_WORKAROUND_GUARD 1 +#else +#define _CRAYC_WORKAROUND_GUARD 0 +#endif +#ifndef __DMC__ +#define __DMC___WORKAROUND_GUARD 1 +#else +#define __DMC___WORKAROUND_GUARD 0 +#endif +#ifndef MPW_CPLUS +#define MPW_CPLUS_WORKAROUND_GUARD 1 +#else +#define MPW_CPLUS_WORKAROUND_GUARD 0 +#endif + +#ifndef _RWSTD_VER +#define _RWSTD_VER_WORKAROUND_GUARD 1 +#else +#define _RWSTD_VER_WORKAROUND_GUARD 0 +#endif +#ifndef _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC +#define _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC_WORKAROUND_GUARD 1 +#else +#define _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC_WORKAROUND_GUARD 0 +#endif +#ifndef __SGI_STL_PORT +#define __SGI_STL_PORT_WORKAROUND_GUARD 1 +#else +#define __SGI_STL_PORT_WORKAROUND_GUARD 0 +#endif +#ifndef _STLPORT_VERSION +#define _STLPORT_VERSION_WORKAROUND_GUARD 1 +#else +#define _STLPORT_VERSION_WORKAROUND_GUARD 0 +#endif + +#ifndef BOOST_INTEL_CXX_VERSION +#define BOOST_INTEL_CXX_VERSION_WORKAROUND_GUARD 1 +#else +#define BOOST_INTEL_CXX_VERSION_WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_INTEL_WIN +#define BOOST_INTEL_WIN_WORKAROUND_GUARD 1 +#else +#define BOOST_INTEL_WIN_WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_DINKUMWARE_STDLIB +#define BOOST_DINKUMWARE_STDLIB_WORKAROUND_GUARD 1 +#else +#define BOOST_DINKUMWARE_STDLIB_WORKAROUND_GUARD 0 +#endif +#ifndef BOOST_INTEL +#define BOOST_INTEL_WORKAROUND_GUARD 1 +#else +#define BOOST_INTEL_WORKAROUND_GUARD 0 +#endif +// Always define to zero, if it's used it'll be defined my MPL: +#define BOOST_MPL_CFG_GCC_WORKAROUND_GUARD 0 + +# define BOOST_WORKAROUND(symbol, test) \ + ((symbol ## _WORKAROUND_GUARD + 0 == 0) && \ + (symbol != 0) && (1 % (( (symbol test) ) + 1))) +// ^ ^ ^ ^ +// The extra level of parenthesis nesting above, along with the +// BOOST_OPEN_PAREN indirection below, is required to satisfy the +// broken preprocessor in MWCW 8.3 and earlier. +// +// The basic mechanism works as follows: +// (symbol test) + 1 => if (symbol test) then 2 else 1 +// 1 % ((symbol test) + 1) => if (symbol test) then 1 else 0 +// +// The complication with % is for cooperation with BOOST_TESTED_AT(). +// When "test" is BOOST_TESTED_AT(x) and +// BOOST_DETECT_OUTDATED_WORKAROUNDS is #defined, +// +// symbol test => if (symbol <= x) then 1 else -1 +// (symbol test) + 1 => if (symbol <= x) then 2 else 0 +// 1 % ((symbol test) + 1) => if (symbol <= x) then 1 else divide-by-zero +// + +# ifdef BOOST_DETECT_OUTDATED_WORKAROUNDS +# define BOOST_OPEN_PAREN ( +# define BOOST_TESTED_AT(value) > value) ?(-1): BOOST_OPEN_PAREN 1 +# else +# define BOOST_TESTED_AT(value) != ((value)-(value)) +# endif + +# else + +# define BOOST_WORKAROUND(symbol, test) 0 + +# endif + +#endif // WORKAROUND_DWA2002126_HPP diff --git a/win32/include/boost/detail/yield_k.hpp b/win32/include/boost/detail/yield_k.hpp new file mode 100755 index 000000000..4bf3d0240 --- /dev/null +++ b/win32/include/boost/detail/yield_k.hpp @@ -0,0 +1,149 @@ +#ifndef BOOST_DETAIL_YIELD_K_HPP_INCLUDED +#define BOOST_DETAIL_YIELD_K_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/yield_k.hpp +// +// Copyright (c) 2008 Peter Dimov +// +// void yield( unsigned k ); +// +// Typical use: +// +// for( unsigned k = 0; !try_lock(); ++k ) yield( k ); +// +// 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 +// + +#include + +// BOOST_SMT_PAUSE + +#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) + +extern "C" void _mm_pause(); +#pragma intrinsic( _mm_pause ) + +#define BOOST_SMT_PAUSE _mm_pause(); + +#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) + +#define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" ); + +#endif + +// + +#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) + +#if defined( BOOST_USE_WINDOWS_H ) +# include +#endif + +namespace boost +{ + +namespace detail +{ + +#if !defined( BOOST_USE_WINDOWS_H ) + extern "C" void __stdcall Sleep( unsigned ms ); +#endif + +inline void yield( unsigned k ) +{ + if( k < 4 ) + { + } +#if defined( BOOST_SMT_PAUSE ) + else if( k < 16 ) + { + BOOST_SMT_PAUSE + } +#endif + else if( k < 32 ) + { + Sleep( 0 ); + } + else + { + Sleep( 1 ); + } +} + +} // namespace detail + +} // namespace boost + +#elif defined( BOOST_HAS_PTHREADS ) + +#include +#include + +namespace boost +{ + +namespace detail +{ + +inline void yield( unsigned k ) +{ + if( k < 4 ) + { + } +#if defined( BOOST_SMT_PAUSE ) + else if( k < 16 ) + { + BOOST_SMT_PAUSE + } +#endif + else if( k < 32 || k & 1 ) + { + sched_yield(); + } + else + { + // g++ -Wextra warns on {} or {0} + struct timespec rqtp = { 0, 0 }; + + // POSIX says that timespec has tv_sec and tv_nsec + // But it doesn't guarantee order or placement + + rqtp.tv_sec = 0; + rqtp.tv_nsec = 1000; + + nanosleep( &rqtp, 0 ); + } +} + +} // namespace detail + +} // namespace boost + +#else + +namespace boost +{ + +namespace detail +{ + +inline void yield( unsigned ) +{ +} + +} // namespace detail + +} // namespace boost + +#endif + +#endif // #ifndef BOOST_DETAIL_YIELD_K_HPP_INCLUDED diff --git a/win32/include/boost/dynamic_bitset.hpp b/win32/include/boost/dynamic_bitset.hpp new file mode 100755 index 000000000..7c8caaaa7 --- /dev/null +++ b/win32/include/boost/dynamic_bitset.hpp @@ -0,0 +1,21 @@ +// -------------------------------------------------- +// +// (C) Copyright Chuck Allison and Jeremy Siek 2001 - 2002. +// (C) Copyright Gennaro Prota 2003 - 2004. +// +// 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) +// +// ----------------------------------------------------------- + +// See http://www.boost.org/libs/dynamic_bitset/ for documentation. +// +// $Revision: 41369 $ $Date: 2007-11-25 13:07:19 -0500 (Sun, 25 Nov 2007) $ - $Name$ + +#ifndef BOOST_DYNAMIC_BITSET_HPP +#define BOOST_DYNAMIC_BITSET_HPP + +#include "boost/dynamic_bitset/dynamic_bitset.hpp" + +#endif // include guard diff --git a/win32/include/boost/dynamic_bitset/config.hpp b/win32/include/boost/dynamic_bitset/config.hpp new file mode 100755 index 000000000..f710c697b --- /dev/null +++ b/win32/include/boost/dynamic_bitset/config.hpp @@ -0,0 +1,82 @@ +// -------------------------------------------------- +// +// (C) Copyright Chuck Allison and Jeremy Siek 2001 - 2002. +// (C) Copyright Gennaro Prota 2003 - 2006. +// +// 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) +// +// ----------------------------------------------------------- + +// See http://www.boost.org/libs/dynamic_bitset/ for documentation. +// +// $Revision: 41369 $ $Date: 2007-11-25 13:07:19 -0500 (Sun, 25 Nov 2007) $ - $Name$ + +#ifndef BOOST_DYNAMIC_BITSET_CONFIG_HPP_GP_20040424 +#define BOOST_DYNAMIC_BITSET_CONFIG_HPP_GP_20040424 + +#include "boost/config.hpp" +#include "boost/detail/workaround.hpp" + +// support for pre 3.0 libstdc++ - thanks Phil Edwards! +#if defined (__STL_CONFIG_H) && !defined (__STL_USE_NEW_IOSTREAMS) +# define BOOST_OLD_IOSTREAMS +#endif + +// this should be in the config system some day +// see http://lists.boost.org/MailArchives/boost/msg62291.php +#define BOOST_DYNAMIC_BITSET_GNUC_VERSION ( __GNUC__ * 100 * 100 \ + + __GNUC_MINOR__ * 100) + +// no-op function to workaround gcc bug c++/8419 +// +namespace boost { namespace detail { + template T make_non_const(T t) { return t; } +}} + +#if defined(__GNUC__) && BOOST_WORKAROUND(BOOST_DYNAMIC_BITSET_GNUC_VERSION, \ + BOOST_TESTED_AT(30300)) +# define BOOST_DYNAMIC_BITSET_WRAP_CONSTANT(expr) \ + (boost::detail::make_non_const(expr)) +#else +# define BOOST_DYNAMIC_BITSET_WRAP_CONSTANT(expr) (expr) +#endif + +// +#if (defined __BORLANDC__ && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))) \ + || (defined BOOST_NO_MEMBER_TEMPLATE_FRIENDS) +#define BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS +#endif + +// if we can't use friends then we simply expose private members +// +#if defined(BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS) +#define BOOST_DYNAMIC_BITSET_PRIVATE public +#else +#define BOOST_DYNAMIC_BITSET_PRIVATE private +#endif + +// A couple of macros to cope with libraries without locale +// support. The first macro must be used to declare a reference +// to a ctype facet. The second one to widen a char by using +// that ctype object. If facets and locales aren't available +// the first macro is a no-op and the second one just expands +// to its parameter c. +// +#if defined (BOOST_USE_FACET) + +#define BOOST_DYNAMIC_BITSET_CTYPE_FACET(ch, name, loc) \ + const std::ctype & name = \ + BOOST_USE_FACET(std::ctype, loc) /**/ + +#define BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, c) \ + (fac.widen(c)) +#else + +#define BOOST_DYNAMIC_BITSET_CTYPE_FACET(ch, name, loc) /**/ +#define BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, c) c + +#endif + +#endif // include guard diff --git a/win32/include/boost/dynamic_bitset/dynamic_bitset.hpp b/win32/include/boost/dynamic_bitset/dynamic_bitset.hpp new file mode 100755 index 000000000..b2223fe67 --- /dev/null +++ b/win32/include/boost/dynamic_bitset/dynamic_bitset.hpp @@ -0,0 +1,1731 @@ +// -------------------------------------------------- +// +// (C) Copyright Chuck Allison and Jeremy Siek 2001 - 2002. +// (C) Copyright Gennaro Prota 2003 - 2006. +// +// 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) +// +// ----------------------------------------------------------- + +// See http://www.boost.org/libs/dynamic_bitset/ for documentation. +// +// $Revision: 47666 $ $Date: 2008-07-21 19:46:39 -0400 (Mon, 21 Jul 2008) $ - $Name$ + + +#ifndef BOOST_DYNAMIC_BITSET_DYNAMIC_BITSET_HPP +#define BOOST_DYNAMIC_BITSET_DYNAMIC_BITSET_HPP + +#include +#include +#include // for std::overflow_error +#include // for std::swap, min, copy, fill +#include +#include // for CHAR_BIT + +#include "boost/dynamic_bitset/config.hpp" + +#ifndef BOOST_NO_STD_LOCALE +# include +#endif + +#if defined(BOOST_OLD_IOSTREAMS) +# include +# include // for isspace +#else +# include +# include +#endif + +#include "boost/dynamic_bitset_fwd.hpp" +#include "boost/detail/dynamic_bitset.hpp" +#include "boost/detail/iterator.hpp" // used to implement append(Iter, Iter) +#include "boost/static_assert.hpp" +#include "boost/limits.hpp" +#include "boost/pending/lowest_bit.hpp" // used by find_first/next + + +namespace boost { + +template + +#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // 1300 == VC++ 7.0 + // VC++ (up to 7.0) wants the default arguments again + > +# else + +# endif + +class dynamic_bitset +{ + // Portability note: member function templates are defined inside + // this class definition to avoid problems with VC++. Similarly, + // with the member functions of nested classes. + + BOOST_STATIC_ASSERT(detail::dynamic_bitset_allowed_block_type::value); + +public: + typedef Block block_type; + typedef Allocator allocator_type; + typedef std::size_t size_type; + typedef int block_width_type; + + BOOST_STATIC_CONSTANT(block_width_type, bits_per_block = (std::numeric_limits::digits)); + BOOST_STATIC_CONSTANT(size_type, npos = static_cast(-1)); + + +public: + + // A proxy class to simulate lvalues of bit type. + // + class reference + { + friend class dynamic_bitset; + + + // the one and only non-copy ctor + reference(block_type & b, int pos) + :m_block(b), m_mask(block_type(1) << pos) + { assert(pos >= 0 && pos < bits_per_block); } + + void operator&(); // left undefined + + public: + + // copy constructor: compiler generated + + operator bool() const { return (m_block & m_mask) != 0; } + bool operator~() const { return (m_block & m_mask) == 0; } + + reference& flip() { do_flip(); return *this; } + + reference& operator=(bool x) { do_assign(x); return *this; } // for b[i] = x + reference& operator=(const reference& rhs) { do_assign(rhs); return *this; } // for b[i] = b[j] + + reference& operator|=(bool x) { if (x) do_set(); return *this; } + reference& operator&=(bool x) { if (!x) do_reset(); return *this; } + reference& operator^=(bool x) { if (x) do_flip(); return *this; } + reference& operator-=(bool x) { if (x) do_reset(); return *this; } + + private: + block_type & m_block; + const block_type m_mask; + + void do_set() { m_block |= m_mask; } + void do_reset() { m_block &= ~m_mask; } + void do_flip() { m_block ^= m_mask; } + void do_assign(bool x) { x? do_set() : do_reset(); } + }; + + typedef bool const_reference; + + // constructors, etc. + explicit + dynamic_bitset(const Allocator& alloc = Allocator()); + + explicit + dynamic_bitset(size_type num_bits, unsigned long value = 0, + const Allocator& alloc = Allocator()); + + + // WARNING: you should avoid using this constructor. + // + // A conversion from string is, in most cases, formatting, + // and should be performed by using operator>>. + // + // NOTE: + // Leave the parentheses around std::basic_string::npos. + // g++ 3.2 requires them and probably the standard will - see core issue 325 + // NOTE 2: + // split into two constructors because of bugs in MSVC 6.0sp5 with STLport + + template + dynamic_bitset(const std::basic_string& s, + typename std::basic_string::size_type pos, + typename std::basic_string::size_type n, + size_type num_bits = npos, + const Allocator& alloc = Allocator()) + + :m_bits(alloc), + m_num_bits(0) + { + init_from_string(s, pos, n, num_bits); + } + + template + explicit + dynamic_bitset(const std::basic_string& s, + typename std::basic_string::size_type pos = 0) + + :m_bits(Allocator()), + m_num_bits(0) + { + init_from_string(s, pos, (std::basic_string::npos), + npos); + } + + // The first bit in *first is the least significant bit, and the + // last bit in the block just before *last is the most significant bit. + template + dynamic_bitset(BlockInputIterator first, BlockInputIterator last, + const Allocator& alloc = Allocator()) + + :m_bits(first, last, alloc), + m_num_bits(m_bits.size() * bits_per_block) + {} + + + // copy constructor + dynamic_bitset(const dynamic_bitset& b); + + ~dynamic_bitset(); + + void swap(dynamic_bitset& b); + dynamic_bitset& operator=(const dynamic_bitset& b); + + allocator_type get_allocator() const; + + // size changing operations + void resize(size_type num_bits, bool value = false); + void clear(); + void push_back(bool bit); + void append(Block block); + + template + void m_append(BlockInputIterator first, BlockInputIterator last, std::input_iterator_tag) + { + std::vector v(first, last); + m_append(v.begin(), v.end(), std::random_access_iterator_tag()); + } + template + void m_append(BlockInputIterator first, BlockInputIterator last, std::forward_iterator_tag) + { + assert(first != last); + block_width_type r = count_extra_bits(); + std::size_t d = boost::detail::distance(first, last); + m_bits.reserve(num_blocks() + d); + if (r == 0) { + for( ; first != last; ++first) + m_bits.push_back(*first); // could use vector<>::insert() + } + else { + m_highest_block() |= (*first << r); + do { + Block b = *first >> (bits_per_block - r); + ++first; + m_bits.push_back(b | (first==last? 0 : *first << r)); + } while (first != last); + } + m_num_bits += bits_per_block * d; + } + template + void append(BlockInputIterator first, BlockInputIterator last) // strong guarantee + { + if (first != last) { + typename detail::iterator_traits::iterator_category cat; + m_append(first, last, cat); + } + } + + + // bitset operations + dynamic_bitset& operator&=(const dynamic_bitset& b); + dynamic_bitset& operator|=(const dynamic_bitset& b); + dynamic_bitset& operator^=(const dynamic_bitset& b); + dynamic_bitset& operator-=(const dynamic_bitset& b); + dynamic_bitset& operator<<=(size_type n); + dynamic_bitset& operator>>=(size_type n); + dynamic_bitset operator<<(size_type n) const; + dynamic_bitset operator>>(size_type n) const; + + // basic bit operations + dynamic_bitset& set(size_type n, bool val = true); + dynamic_bitset& set(); + dynamic_bitset& reset(size_type n); + dynamic_bitset& reset(); + dynamic_bitset& flip(size_type n); + dynamic_bitset& flip(); + bool test(size_type n) const; + bool any() const; + bool none() const; + dynamic_bitset operator~() const; + size_type count() const; + + // subscript + reference operator[](size_type pos) { + return reference(m_bits[block_index(pos)], bit_index(pos)); + } + bool operator[](size_type pos) const { return test(pos); } + + unsigned long to_ulong() const; + + size_type size() const; + size_type num_blocks() const; + size_type max_size() const; + bool empty() const; + + bool is_subset_of(const dynamic_bitset& a) const; + bool is_proper_subset_of(const dynamic_bitset& a) const; + bool intersects(const dynamic_bitset & a) const; + + // lookup + size_type find_first() const; + size_type find_next(size_type pos) const; + + +#if !defined BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS + // lexicographical comparison + template + friend bool operator==(const dynamic_bitset& a, + const dynamic_bitset& b); + + template + friend bool operator<(const dynamic_bitset& a, + const dynamic_bitset& b); + + + template + friend void to_block_range(const dynamic_bitset& b, + BlockOutputIterator result); + + template + friend void from_block_range(BlockIterator first, BlockIterator last, + dynamic_bitset& result); + + + template + friend std::basic_istream& operator>>(std::basic_istream& is, + dynamic_bitset& b); + + template + friend void to_string_helper(const dynamic_bitset & b, stringT & s, bool dump_all); + + +#endif + + +private: + BOOST_STATIC_CONSTANT(block_width_type, ulong_width = std::numeric_limits::digits); + typedef std::vector buffer_type; + + void m_zero_unused_bits(); + bool m_check_invariants() const; + + size_type m_do_find_from(size_type first_block) const; + + block_width_type count_extra_bits() const { return bit_index(size()); } + static size_type block_index(size_type pos) { return pos / bits_per_block; } + static block_width_type bit_index(size_type pos) { return static_cast(pos % bits_per_block); } + static Block bit_mask(size_type pos) { return Block(1) << bit_index(pos); } + + template + void init_from_string(const std::basic_string& s, + typename std::basic_string::size_type pos, + typename std::basic_string::size_type n, + size_type num_bits) + { + assert(pos <= s.size()); + + typedef typename std::basic_string StrT; + typedef typename StrT::traits_type Tr; + + const typename StrT::size_type rlen = (std::min)(n, s.size() - pos); + const size_type sz = ( num_bits != npos? num_bits : rlen); + m_bits.resize(calc_num_blocks(sz)); + m_num_bits = sz; + + + BOOST_DYNAMIC_BITSET_CTYPE_FACET(CharT, fac, std::locale()); + const CharT one = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1'); + + const size_type m = num_bits < rlen ? num_bits : rlen; + typename StrT::size_type i = 0; + for( ; i < m; ++i) { + + const CharT c = s[(pos + m - 1) - i]; + + assert( Tr::eq(c, one) + || Tr::eq(c, BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0')) ); + + if (Tr::eq(c, one)) + set(i); + + } + + } + +BOOST_DYNAMIC_BITSET_PRIVATE: + + bool m_unchecked_test(size_type pos) const; + static size_type calc_num_blocks(size_type num_bits); + + Block& m_highest_block(); + const Block& m_highest_block() const; + + buffer_type m_bits; + size_type m_num_bits; + + + class bit_appender; + friend class bit_appender; + class bit_appender { + // helper for stream >> + // Supplies to the lack of an efficient append at the less + // significant end: bits are actually appended "at left" but + // rearranged in the destructor. From the perspective of + // client code everything works *as if* dynamic_bitset<> had + // an append_at_right() function (eventually throwing the same + // exceptions as push_back) except that the function is in fact + // called bit_appender::do_append(). + // + dynamic_bitset & bs; + size_type n; + Block mask; + Block * current; + public: + bit_appender(dynamic_bitset & r) : bs(r), n(0), mask(0), current(0) {} + ~bit_appender() { + // reverse the order of blocks, shift + // if needed, and then resize + // + std::reverse(bs.m_bits.begin(), bs.m_bits.end()); + const block_width_type offs = bit_index(n); + if (offs) + bs >>= (bits_per_block - offs); + bs.resize(n); // doesn't enlarge, so can't throw + assert(bs.m_check_invariants()); + } + inline void do_append(bool value) { + + if (mask == 0) { + bs.append(Block(0)); + current = &bs.m_highest_block(); + mask = Block(1) << (bits_per_block - 1); + } + + if(value) + *current |= mask; + + mask /= 2; + ++n; + } + size_type get_count() const { return n; } + }; + +}; + +#if defined(__IBMCPP__) && BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) + +// Workaround for IBM's AIX platform. +// See http://comments.gmane.org/gmane.comp.lib.boost.user/15331 +// +// NOTE: +// The compiler is actually right, until core issue 454 will be settled: +// http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#454 +// +// It's arguable whether we want to mark this with BOOST_WORKAROUND or not. + + +template +dynamic_bitset::block_width_type const +dynamic_bitset::bits_per_block; + +template +dynamic_bitset::block_width_type const +dynamic_bitset::ulong_width; + +#endif + +// Global Functions: + +// comparison +template +bool operator!=(const dynamic_bitset& a, + const dynamic_bitset& b); + +template +bool operator<=(const dynamic_bitset& a, + const dynamic_bitset& b); + +template +bool operator>(const dynamic_bitset& a, + const dynamic_bitset& b); + +template +bool operator>=(const dynamic_bitset& a, + const dynamic_bitset& b); + +// stream operators +#ifdef BOOST_OLD_IOSTREAMS +template +std::ostream& operator<<(std::ostream& os, + const dynamic_bitset& b); + +template +std::istream& operator>>(std::istream& is, dynamic_bitset& b); +#else +template +std::basic_ostream& +operator<<(std::basic_ostream& os, + const dynamic_bitset& b); + +template +std::basic_istream& +operator>>(std::basic_istream& is, + dynamic_bitset& b); +#endif + +// bitset operations +template +dynamic_bitset +operator&(const dynamic_bitset& b1, + const dynamic_bitset& b2); + +template +dynamic_bitset +operator|(const dynamic_bitset& b1, + const dynamic_bitset& b2); + +template +dynamic_bitset +operator^(const dynamic_bitset& b1, + const dynamic_bitset& b2); + +template +dynamic_bitset +operator-(const dynamic_bitset& b1, + const dynamic_bitset& b2); + +// namespace scope swap +template +void swap(dynamic_bitset& b1, + dynamic_bitset& b2); + + +template +void +to_string(const dynamic_bitset& b, stringT & s); + +template +void +to_block_range(const dynamic_bitset& b, + BlockOutputIterator result); + + +template +inline void +from_block_range(BlockIterator first, BlockIterator last, + dynamic_bitset& result) +{ + // PRE: distance(first, last) <= numblocks() + std::copy (first, last, result.m_bits.begin()); +} + +//============================================================================= +// dynamic_bitset implementation + + +//----------------------------------------------------------------------------- +// constructors, etc. + +template +dynamic_bitset::dynamic_bitset(const Allocator& alloc) + : m_bits(alloc), m_num_bits(0) +{ + +} + +template +dynamic_bitset:: +dynamic_bitset(size_type num_bits, unsigned long value, const Allocator& alloc) + : m_bits(calc_num_blocks(num_bits), Block(0), alloc), + m_num_bits(num_bits) +{ + + typedef unsigned long num_type; + typedef boost::detail::shifter shifter; + + //if (num_bits == 0) + // return; + + // zero out all bits at pos >= num_bits, if any; + // note that: num_bits == 0 implies value == 0 + if (num_bits < static_cast(ulong_width)) { + const num_type mask = (num_type(1) << num_bits) - 1; + value &= mask; + } + + typename buffer_type::iterator it = m_bits.begin(); + for( ; value; shifter::left_shift(value), ++it) { + *it = static_cast(value); + } + +} + +// copy constructor +template +inline dynamic_bitset:: +dynamic_bitset(const dynamic_bitset& b) + : m_bits(b.m_bits), m_num_bits(b.m_num_bits) +{ + +} + +template +inline dynamic_bitset:: +~dynamic_bitset() +{ + assert(m_check_invariants()); +} + +template +inline void dynamic_bitset:: +swap(dynamic_bitset& b) // no throw +{ + std::swap(m_bits, b.m_bits); + std::swap(m_num_bits, b.m_num_bits); +} + +template +dynamic_bitset& dynamic_bitset:: +operator=(const dynamic_bitset& b) +{ + m_bits = b.m_bits; + m_num_bits = b.m_num_bits; + return *this; +} + +template +inline typename dynamic_bitset::allocator_type +dynamic_bitset::get_allocator() const +{ + return m_bits.get_allocator(); +} + +//----------------------------------------------------------------------------- +// size changing operations + +template +void dynamic_bitset:: +resize(size_type num_bits, bool value) // strong guarantee +{ + + const size_type old_num_blocks = num_blocks(); + const size_type required_blocks = calc_num_blocks(num_bits); + + const block_type v = value? ~Block(0) : Block(0); + + if (required_blocks != old_num_blocks) { + m_bits.resize(required_blocks, v); // s.g. (copy) + } + + + // At this point: + // + // - if the buffer was shrunk, we have nothing more to do, + // except a call to m_zero_unused_bits() + // + // - if it was enlarged, all the (used) bits in the new blocks have + // the correct value, but we have not yet touched those bits, if + // any, that were 'unused bits' before enlarging: if value == true, + // they must be set. + + if (value && (num_bits > m_num_bits)) { + + const size_type extra_bits = count_extra_bits(); + if (extra_bits) { + assert(old_num_blocks >= 1 && old_num_blocks <= m_bits.size()); + + // Set them. + m_bits[old_num_blocks - 1] |= (v << extra_bits); + } + + } + + m_num_bits = num_bits; + m_zero_unused_bits(); + +} + +template +void dynamic_bitset:: +clear() // no throw +{ + m_bits.clear(); + m_num_bits = 0; +} + + +template +void dynamic_bitset:: +push_back(bool bit) +{ + const size_type sz = size(); + resize(sz + 1); + set(sz, bit); +} + +template +void dynamic_bitset:: +append(Block value) // strong guarantee +{ + const block_width_type r = count_extra_bits(); + + if (r == 0) { + // the buffer is empty, or all blocks are filled + m_bits.push_back(value); + } + else { + m_bits.push_back(value >> (bits_per_block - r)); + m_bits[m_bits.size() - 2] |= (value << r); // m_bits.size() >= 2 + } + + m_num_bits += bits_per_block; + assert(m_check_invariants()); + +} + + +//----------------------------------------------------------------------------- +// bitset operations +template +dynamic_bitset& +dynamic_bitset::operator&=(const dynamic_bitset& rhs) +{ + assert(size() == rhs.size()); + for (size_type i = 0; i < num_blocks(); ++i) + m_bits[i] &= rhs.m_bits[i]; + return *this; +} + +template +dynamic_bitset& +dynamic_bitset::operator|=(const dynamic_bitset& rhs) +{ + assert(size() == rhs.size()); + for (size_type i = 0; i < num_blocks(); ++i) + m_bits[i] |= rhs.m_bits[i]; + //m_zero_unused_bits(); + return *this; +} + +template +dynamic_bitset& +dynamic_bitset::operator^=(const dynamic_bitset& rhs) +{ + assert(size() == rhs.size()); + for (size_type i = 0; i < this->num_blocks(); ++i) + m_bits[i] ^= rhs.m_bits[i]; + //m_zero_unused_bits(); + return *this; +} + +template +dynamic_bitset& +dynamic_bitset::operator-=(const dynamic_bitset& rhs) +{ + assert(size() == rhs.size()); + for (size_type i = 0; i < num_blocks(); ++i) + m_bits[i] &= ~rhs.m_bits[i]; + //m_zero_unused_bits(); + return *this; +} + +// +// NOTE: +// Note that the 'if (r != 0)' is crucial to avoid undefined +// behavior when the left hand operand of >> isn't promoted to a +// wider type (because rs would be too large). +// +template +dynamic_bitset& +dynamic_bitset::operator<<=(size_type n) +{ + if (n >= m_num_bits) + return reset(); + //else + if (n > 0) { + + size_type const last = num_blocks() - 1; // num_blocks() is >= 1 + size_type const div = n / bits_per_block; // div is <= last + block_width_type const r = bit_index(n); + block_type * const b = &m_bits[0]; + + if (r != 0) { + + block_width_type const rs = bits_per_block - r; + + for (size_type i = last-div; i>0; --i) { + b[i+div] = (b[i] << r) | (b[i-1] >> rs); + } + b[div] = b[0] << r; + + } + else { + for (size_type i = last-div; i>0; --i) { + b[i+div] = b[i]; + } + b[div] = b[0]; + } + + // disable std::fill_n deprecated warning in MSVC++ 8.0 (warning C4996) + // This will only work in MSVC++ 8.0 SP1, which brings up the warning + // in the line of user code; otherwise, the warning will come up + // in the line in the header itself, so if the user includes stdlib + // headers before dynamic_bitset, he will still get the warning. +#if defined(_MSC_VER) && _MSC_VER >= 1400 +#pragma warning(push) +#pragma warning(disable:4996) +#endif + + // zero out div blocks at the less significant end + std::fill_n(b, div, static_cast(0)); + +#if defined(_MSC_VER) && _MSC_VER >= 1400 +#pragma warning(pop) +#endif + + // zero out any 1 bit that flowed into the unused part + m_zero_unused_bits(); // thanks to Lester Gong + + + } + + return *this; + + +} + + +// +// NOTE: +// see the comments to operator <<= +// +template +dynamic_bitset & dynamic_bitset::operator>>=(size_type n) { + if (n >= m_num_bits) { + return reset(); + } + //else + if (n>0) { + + size_type const last = num_blocks() - 1; // num_blocks() is >= 1 + size_type const div = n / bits_per_block; // div is <= last + block_width_type const r = bit_index(n); + block_type * const b = &m_bits[0]; + + + if (r != 0) { + + block_width_type const ls = bits_per_block - r; + + for (size_type i = div; i < last; ++i) { + b[i-div] = (b[i] >> r) | (b[i+1] << ls); + } + // r bits go to zero + b[last-div] = b[last] >> r; + } + + else { + for (size_type i = div; i <= last; ++i) { + b[i-div] = b[i]; + } + // note the '<=': the last iteration 'absorbs' + // b[last-div] = b[last] >> 0; + } + + + + // div blocks are zero filled at the most significant end + std::fill_n(b + (num_blocks()-div), div, static_cast(0)); + } + + return *this; +} + + +template +dynamic_bitset +dynamic_bitset::operator<<(size_type n) const +{ + dynamic_bitset r(*this); + return r <<= n; +} + +template +dynamic_bitset +dynamic_bitset::operator>>(size_type n) const +{ + dynamic_bitset r(*this); + return r >>= n; +} + + +//----------------------------------------------------------------------------- +// basic bit operations + +template +dynamic_bitset& +dynamic_bitset::set(size_type pos, bool val) +{ + assert(pos < m_num_bits); + + if (val) + m_bits[block_index(pos)] |= bit_mask(pos); + else + reset(pos); + + return *this; +} + +template +dynamic_bitset& +dynamic_bitset::set() +{ + std::fill(m_bits.begin(), m_bits.end(), ~Block(0)); + m_zero_unused_bits(); + return *this; +} + +template +dynamic_bitset& +dynamic_bitset::reset(size_type pos) +{ + assert(pos < m_num_bits); +#if defined __MWERKS__ && BOOST_WORKAROUND(__MWERKS__, <= 0x3003) // 8.x + // CodeWarrior 8 generates incorrect code when the &=~ is compiled, + // use the |^ variation instead.. + m_bits[block_index(pos)] |= bit_mask(pos); + m_bits[block_index(pos)] ^= bit_mask(pos); +#else + m_bits[block_index(pos)] &= ~bit_mask(pos); +#endif + return *this; +} + +template +dynamic_bitset& +dynamic_bitset::reset() +{ + std::fill(m_bits.begin(), m_bits.end(), Block(0)); + return *this; +} + +template +dynamic_bitset& +dynamic_bitset::flip(size_type pos) +{ + assert(pos < m_num_bits); + m_bits[block_index(pos)] ^= bit_mask(pos); + return *this; +} + +template +dynamic_bitset& +dynamic_bitset::flip() +{ + for (size_type i = 0; i < num_blocks(); ++i) + m_bits[i] = ~m_bits[i]; + m_zero_unused_bits(); + return *this; +} + +template +bool dynamic_bitset::m_unchecked_test(size_type pos) const +{ + return (m_bits[block_index(pos)] & bit_mask(pos)) != 0; +} + +template +bool dynamic_bitset::test(size_type pos) const +{ + assert(pos < m_num_bits); + return m_unchecked_test(pos); +} + +template +bool dynamic_bitset::any() const +{ + for (size_type i = 0; i < num_blocks(); ++i) + if (m_bits[i]) + return true; + return false; +} + +template +inline bool dynamic_bitset::none() const +{ + return !any(); +} + +template +dynamic_bitset +dynamic_bitset::operator~() const +{ + dynamic_bitset b(*this); + b.flip(); + return b; +} + + +template +typename dynamic_bitset::size_type +dynamic_bitset::count() const +{ + using namespace detail::dynamic_bitset_count_impl; + + const bool no_padding = bits_per_block == CHAR_BIT * sizeof(Block); + const bool enough_table_width = table_width >= CHAR_BIT; + + typedef mode_to_type< (no_padding && enough_table_width ? + access_by_bytes : access_by_blocks) > m; + + return do_count(m_bits.begin(), num_blocks(), Block(0), static_cast(0)); + +} + + +//----------------------------------------------------------------------------- +// conversions + + +template +void to_string_helper(const dynamic_bitset & b, stringT & s, + bool dump_all) +{ + typedef typename stringT::traits_type Tr; + typedef typename stringT::value_type Ch; + + BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch, fac, std::locale()); + const Ch zero = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0'); + const Ch one = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1'); + + // Note that this function may access (when + // dump_all == true) bits beyond position size() - 1 + + typedef typename dynamic_bitset::size_type size_type; + + const size_type len = dump_all? + dynamic_bitset::bits_per_block * b.num_blocks(): + b.size(); + s.assign (len, zero); + + for (size_type i = 0; i < len; ++i) { + if (b.m_unchecked_test(i)) + Tr::assign(s[len - 1 - i], one); + + } + +} + + +// A comment similar to the one about the constructor from +// basic_string can be done here. Thanks to James Kanze for +// making me (Gennaro) realize this important separation of +// concerns issue, as well as many things about i18n. +// +template +inline void +to_string(const dynamic_bitset& b, stringT& s) +{ + to_string_helper(b, s, false); +} + + +// Differently from to_string this function dumps out +// every bit of the internal representation (may be +// useful for debugging purposes) +// +template +inline void +dump_to_string(const dynamic_bitset& b, stringT& s) +{ + to_string_helper(b, s, true /* =dump_all*/); +} + +template +inline void +to_block_range(const dynamic_bitset& b, + BlockOutputIterator result) +{ + // note how this copies *all* bits, including the + // unused ones in the last block (which are zero) + std::copy(b.m_bits.begin(), b.m_bits.end(), result); +} + +template +unsigned long dynamic_bitset:: +to_ulong() const +{ + + if (m_num_bits == 0) + return 0; // convention + + // Check for overflows. This may be a performance burden on very + // large bitsets but is required by the specification, sorry + if (find_next(ulong_width - 1) != npos) + throw std::overflow_error("boost::dynamic_bitset::to_ulong overflow"); + + + // Ok, from now on we can be sure there's no "on" bit + // beyond the "allowed" positions + typedef unsigned long result_type; + + /* + if find_next() did its job correctly we don't need the if + below, because all bits we care about are in the first block + + if (bits_per_block >= ulong_width) + return static_cast(m_bits[0]); + */ + + size_type last_block = block_index( + (std::min)( m_num_bits, (size_type)ulong_width ) - 1 ); + result_type result = 0; + for (size_type i = 0; i <= last_block; ++i) { + + assert((size_type)bits_per_block * i < (size_type)ulong_width); + + unsigned long piece = m_bits[i]; + result |= (piece << (bits_per_block * i)); + } + + return result; +} + + +template +inline typename dynamic_bitset::size_type +dynamic_bitset::size() const +{ + return m_num_bits; +} + +template +inline typename dynamic_bitset::size_type +dynamic_bitset::num_blocks() const +{ + return m_bits.size(); +} + +template +inline typename dynamic_bitset::size_type +dynamic_bitset::max_size() const +{ + // Semantics of vector<>::max_size() aren't very clear + // (see lib issue 197) and many library implementations + // simply return dummy values, _unrelated_ to the underlying + // allocator. + // + // Given these problems, I was tempted to not provide this + // function at all but the user could need it if he provides + // his own allocator. + // + + const size_type m = detail::vector_max_size_workaround(m_bits); + + return m <= (size_type(-1)/bits_per_block) ? + m * bits_per_block : + size_type(-1); +} + +template +inline bool dynamic_bitset::empty() const +{ + return size() == 0; +} + +template +bool dynamic_bitset:: +is_subset_of(const dynamic_bitset& a) const +{ + assert(size() == a.size()); + for (size_type i = 0; i < num_blocks(); ++i) + if (m_bits[i] & ~a.m_bits[i]) + return false; + return true; +} + +template +bool dynamic_bitset:: +is_proper_subset_of(const dynamic_bitset& a) const +{ + assert(size() == a.size()); + assert(num_blocks() == a.num_blocks()); + + bool proper = false; + for (size_type i = 0; i < num_blocks(); ++i) { + const Block & bt = m_bits[i]; + const Block & ba = a.m_bits[i]; + + if (bt & ~ba) + return false; // not a subset at all + if (ba & ~bt) + proper = true; + } + return proper; +} + +template +bool dynamic_bitset::intersects(const dynamic_bitset & b) const +{ + size_type common_blocks = num_blocks() < b.num_blocks() + ? num_blocks() : b.num_blocks(); + + for(size_type i = 0; i < common_blocks; ++i) { + if(m_bits[i] & b.m_bits[i]) + return true; + } + return false; +} + +// -------------------------------- +// lookup + + +// look for the first bit "on", starting +// from the block with index first_block +// +template +typename dynamic_bitset::size_type +dynamic_bitset::m_do_find_from(size_type first_block) const +{ + size_type i = first_block; + + // skip null blocks + while (i < num_blocks() && m_bits[i] == 0) + ++i; + + if (i >= num_blocks()) + return npos; // not found + + return i * bits_per_block + boost::lowest_bit(m_bits[i]); + +} + + +template +typename dynamic_bitset::size_type +dynamic_bitset::find_first() const +{ + return m_do_find_from(0); +} + + +template +typename dynamic_bitset::size_type +dynamic_bitset::find_next(size_type pos) const +{ + + const size_type sz = size(); + if (pos >= (sz-1) || sz == 0) + return npos; + + ++pos; + + const size_type blk = block_index(pos); + const block_width_type ind = bit_index(pos); + + // mask out bits before pos + const Block fore = m_bits[blk] & ( ~Block(0) << ind ); + + return fore? + blk * bits_per_block + lowest_bit(fore) + : + m_do_find_from(blk + 1); + +} + + + +//----------------------------------------------------------------------------- +// comparison + +template +bool operator==(const dynamic_bitset& a, + const dynamic_bitset& b) +{ + return (a.m_num_bits == b.m_num_bits) + && (a.m_bits == b.m_bits); +} + +template +inline bool operator!=(const dynamic_bitset& a, + const dynamic_bitset& b) +{ + return !(a == b); +} + +template +bool operator<(const dynamic_bitset& a, + const dynamic_bitset& b) +{ + assert(a.size() == b.size()); + typedef typename dynamic_bitset::size_type size_type; + + //if (a.size() == 0) + // return false; + + // Since we are storing the most significant bit + // at pos == size() - 1, we need to do the comparisons in reverse. + // + for (size_type ii = a.num_blocks(); ii > 0; --ii) { + size_type i = ii-1; + if (a.m_bits[i] < b.m_bits[i]) + return true; + else if (a.m_bits[i] > b.m_bits[i]) + return false; + } + return false; +} + +template +inline bool operator<=(const dynamic_bitset& a, + const dynamic_bitset& b) +{ + return !(a > b); +} + +template +inline bool operator>(const dynamic_bitset& a, + const dynamic_bitset& b) +{ + return b < a; +} + +template +inline bool operator>=(const dynamic_bitset& a, + const dynamic_bitset& b) +{ + return !(a < b); +} + +//----------------------------------------------------------------------------- +// stream operations + +#ifdef BOOST_OLD_IOSTREAMS +template < typename Block, typename Alloc> +std::ostream& +operator<<(std::ostream& os, const dynamic_bitset& b) +{ + // NOTE: since this is aimed at "classic" iostreams, exception + // masks on the stream are not supported. The library that + // ships with gcc 2.95 has an exceptions() member function but + // nothing is actually implemented; not even the class ios::failure. + + using namespace std; + + const ios::iostate ok = ios::goodbit; + ios::iostate err = ok; + + if (os.opfx()) { + + //try + typedef typename dynamic_bitset::size_type bitsetsize_type; + + const bitsetsize_type sz = b.size(); + std::streambuf * buf = os.rdbuf(); + size_t npad = os.width() <= 0 // careful: os.width() is signed (and can be < 0) + || (bitsetsize_type) os.width() <= sz? 0 : os.width() - sz; + + const char fill_char = os.fill(); + const ios::fmtflags adjustfield = os.flags() & ios::adjustfield; + + // if needed fill at left; pad is decresed along the way + if (adjustfield != ios::left) { + for (; 0 < npad; --npad) + if (fill_char != buf->sputc(fill_char)) { + err |= ios::failbit; + break; + } + } + + if (err == ok) { + // output the bitset + for (bitsetsize_type i = b.size(); 0 < i; --i) { + const char dig = b.test(i-1)? '1' : '0'; + if (EOF == buf->sputc(dig)) { + err |= ios::failbit; + break; + } + } + } + + if (err == ok) { + // if needed fill at right + for (; 0 < npad; --npad) { + if (fill_char != buf->sputc(fill_char)) { + err |= ios::failbit; + break; + } + } + } + + os.osfx(); + os.width(0); + + } // if opfx + + if(err != ok) + os.setstate(err); // assume this does NOT throw + return os; + +} +#else + +template +std::basic_ostream& +operator<<(std::basic_ostream& os, + const dynamic_bitset& b) +{ + + using namespace std; + + const ios_base::iostate ok = ios_base::goodbit; + ios_base::iostate err = ok; + + typename basic_ostream::sentry cerberos(os); + if (cerberos) { + + BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch, fac, os.getloc()); + const Ch zero = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0'); + const Ch one = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1'); + + try { + + typedef typename dynamic_bitset::size_type bitsetsize_type; + typedef basic_streambuf buffer_type; + + buffer_type * buf = os.rdbuf(); + size_t npad = os.width() <= 0 // careful: os.width() is signed (and can be < 0) + || (bitsetsize_type) os.width() <= b.size()? 0 : os.width() - b.size(); + + const Ch fill_char = os.fill(); + const ios_base::fmtflags adjustfield = os.flags() & ios_base::adjustfield; + + // if needed fill at left; pad is decresed along the way + if (adjustfield != ios_base::left) { + for (; 0 < npad; --npad) + if (Tr::eq_int_type(Tr::eof(), buf->sputc(fill_char))) { + err |= ios_base::failbit; + break; + } + } + + if (err == ok) { + // output the bitset + for (bitsetsize_type i = b.size(); 0 < i; --i) { + typename buffer_type::int_type + ret = buf->sputc(b.test(i-1)? one : zero); + if (Tr::eq_int_type(Tr::eof(), ret)) { + err |= ios_base::failbit; + break; + } + } + } + + if (err == ok) { + // if needed fill at right + for (; 0 < npad; --npad) { + if (Tr::eq_int_type(Tr::eof(), buf->sputc(fill_char))) { + err |= ios_base::failbit; + break; + } + } + } + + + os.width(0); + + } catch (...) { // see std 27.6.1.1/4 + bool rethrow = false; + try { os.setstate(ios_base::failbit); } catch (...) { rethrow = true; } + + if (rethrow) + throw; + } + } + + if(err != ok) + os.setstate(err); // may throw exception + return os; + +} +#endif + + +#ifdef BOOST_OLD_IOSTREAMS + + // A sentry-like class that calls isfx in its destructor. + // "Necessary" because bit_appender::do_append may throw. + class pseudo_sentry { + std::istream & m_r; + const bool m_ok; + public: + explicit pseudo_sentry(std::istream & r) : m_r(r), m_ok(r.ipfx(0)) { } + ~pseudo_sentry() { m_r.isfx(); } + operator bool() const { return m_ok; } + }; + +template +std::istream& +operator>>(std::istream& is, dynamic_bitset& b) +{ + +// Extractor for classic IO streams (libstdc++ < 3.0) +// ----------------------------------------------------// +// It's assumed that the stream buffer functions, and +// the stream's setstate() _cannot_ throw. + + + typedef dynamic_bitset bitset_type; + typedef typename bitset_type::size_type size_type; + + std::ios::iostate err = std::ios::goodbit; + pseudo_sentry cerberos(is); // skips whitespaces + if(cerberos) { + + b.clear(); + + const std::streamsize w = is.width(); + const size_type limit = w > 0 && static_cast(w) < b.max_size() + ? w : b.max_size(); + typename bitset_type::bit_appender appender(b); + std::streambuf * buf = is.rdbuf(); + for(int c = buf->sgetc(); appender.get_count() < limit; c = buf->snextc() ) { + + if (c == EOF) { + err |= std::ios::eofbit; + break; + } + else if (char(c) != '0' && char(c) != '1') + break; // non digit character + + else { + try { + appender.do_append(char(c) == '1'); + } + catch(...) { + is.setstate(std::ios::failbit); // assume this can't throw + throw; + } + } + + } // for + } + + is.width(0); + if (b.size() == 0) + err |= std::ios::failbit; + if (err != std::ios::goodbit) + is.setstate (err); // may throw + + return is; +} + +#else // BOOST_OLD_IOSTREAMS + +template +std::basic_istream& +operator>>(std::basic_istream& is, dynamic_bitset& b) +{ + + using namespace std; + + typedef dynamic_bitset bitset_type; + typedef typename bitset_type::size_type size_type; + + const streamsize w = is.width(); + const size_type limit = 0 < w && static_cast(w) < b.max_size()? + w : b.max_size(); + + ios_base::iostate err = ios_base::goodbit; + typename basic_istream::sentry cerberos(is); // skips whitespaces + if(cerberos) { + + // in accordance with prop. resol. of lib DR 303 [last checked 4 Feb 2004] + BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch, fac, is.getloc()); + const Ch zero = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0'); + const Ch one = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1'); + + b.clear(); + try { + typename bitset_type::bit_appender appender(b); + basic_streambuf * buf = is.rdbuf(); + typename Tr::int_type c = buf->sgetc(); + for( ; appender.get_count() < limit; c = buf->snextc() ) { + + if (Tr::eq_int_type(Tr::eof(), c)) { + err |= ios_base::eofbit; + break; + } + else { + const Ch to_c = Tr::to_char_type(c); + const bool is_one = Tr::eq(to_c, one); + + if (!is_one && !Tr::eq(to_c, zero)) + break; // non digit character + + appender.do_append(is_one); + + } + + } // for + } + catch (...) { + // catches from stream buf, or from vector: + // + // bits_stored bits have been extracted and stored, and + // either no further character is extractable or we can't + // append to the underlying vector (out of memory) + + bool rethrow = false; // see std 27.6.1.1/4 + try { is.setstate(ios_base::badbit); } + catch(...) { rethrow = true; } + + if (rethrow) + throw; + + } + } + + is.width(0); + if (b.size() == 0 /*|| !cerberos*/) + err |= ios_base::failbit; + if (err != ios_base::goodbit) + is.setstate (err); // may throw + + return is; + +} + + +#endif + + +//----------------------------------------------------------------------------- +// bitset operations + +template +dynamic_bitset +operator&(const dynamic_bitset& x, + const dynamic_bitset& y) +{ + dynamic_bitset b(x); + return b &= y; +} + +template +dynamic_bitset +operator|(const dynamic_bitset& x, + const dynamic_bitset& y) +{ + dynamic_bitset b(x); + return b |= y; +} + +template +dynamic_bitset +operator^(const dynamic_bitset& x, + const dynamic_bitset& y) +{ + dynamic_bitset b(x); + return b ^= y; +} + +template +dynamic_bitset +operator-(const dynamic_bitset& x, + const dynamic_bitset& y) +{ + dynamic_bitset b(x); + return b -= y; +} + +//----------------------------------------------------------------------------- +// namespace scope swap + +template +inline void +swap(dynamic_bitset& left, + dynamic_bitset& right) // no throw +{ + left.swap(right); +} + + +//----------------------------------------------------------------------------- +// private (on conforming compilers) member functions + + +template +inline typename dynamic_bitset::size_type +dynamic_bitset::calc_num_blocks(size_type num_bits) +{ + return num_bits / bits_per_block + + static_cast( num_bits % bits_per_block != 0 ); +} + +// gives a reference to the highest block +// +template +inline Block& dynamic_bitset::m_highest_block() +{ + return const_cast + (static_cast(this)->m_highest_block()); +} + +// gives a const-reference to the highest block +// +template +inline const Block& dynamic_bitset::m_highest_block() const +{ + assert(size() > 0 && num_blocks() > 0); + return m_bits.back(); +} + + +// If size() is not a multiple of bits_per_block +// then not all the bits in the last block are used. +// This function resets the unused bits (convenient +// for the implementation of many member functions) +// +template +inline void dynamic_bitset::m_zero_unused_bits() +{ + assert (num_blocks() == calc_num_blocks(m_num_bits)); + + // if != 0 this is the number of bits used in the last block + const block_width_type extra_bits = count_extra_bits(); + + if (extra_bits != 0) + m_highest_block() &= ~(~static_cast(0) << extra_bits); + +} + +// check class invariants +template +bool dynamic_bitset::m_check_invariants() const +{ + const block_width_type extra_bits = count_extra_bits(); + if (extra_bits > 0) { + block_type const mask = (~static_cast(0) << extra_bits); + if ((m_highest_block() & mask) != 0) + return false; + } + if (m_bits.size() > m_bits.capacity() || num_blocks() != calc_num_blocks(size())) + return false; + + return true; + +} + + +} // namespace boost + + +#undef BOOST_BITSET_CHAR + +#endif // include guard + diff --git a/win32/include/boost/dynamic_bitset_fwd.hpp b/win32/include/boost/dynamic_bitset_fwd.hpp new file mode 100755 index 000000000..5735876d4 --- /dev/null +++ b/win32/include/boost/dynamic_bitset_fwd.hpp @@ -0,0 +1,29 @@ +// -------------------------------------------------- +// +// (C) Copyright Chuck Allison and Jeremy Siek 2001 - 2002. +// (C) Copyright Gennaro Prota 2003 - 2004. +// +// 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) +// +// ----------------------------------------------------------- + +// See http://www.boost.org/libs/dynamic_bitset/ for documentation. +// +// $Revision: 41369 $ $Date: 2007-11-25 13:07:19 -0500 (Sun, 25 Nov 2007) $ - $Name$ + +#ifndef BOOST_DYNAMIC_BITSET_FWD_HPP +#define BOOST_DYNAMIC_BITSET_FWD_HPP + +#include + +namespace boost { + +template > +class dynamic_bitset; + +} // namespace boost + +#endif // include guard diff --git a/win32/include/boost/dynamic_property_map.hpp b/win32/include/boost/dynamic_property_map.hpp new file mode 100755 index 000000000..021691e15 --- /dev/null +++ b/win32/include/boost/dynamic_property_map.hpp @@ -0,0 +1,370 @@ +#ifndef DYNAMIC_PROPERTY_MAP_RG09302004_HPP +#define DYNAMIC_PROPERTY_MAP_RG09302004_HPP + +// Copyright 2004-5 The Trustees of Indiana University. + +// Use, modification and distribution is subject to 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) + +// dynamic_property_map.hpp - +// Support for runtime-polymorphic property maps. This header is factored +// out of Doug Gregor's routines for reading GraphML files for use in reading +// GraphViz graph files. + +// Authors: Doug Gregor +// Ronald Garcia +// + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + +namespace detail { + + // read_value - + // A wrapper around lexical_cast, which does not behave as + // desired for std::string types. + template + inline Value read_value(const std::string& value) + { return boost::lexical_cast(value); } + + template<> + inline std::string read_value(const std::string& value) + { return value; } + +} + + +// dynamic_property_map - +// This interface supports polymorphic manipulation of property maps. +class dynamic_property_map +{ +public: + virtual ~dynamic_property_map() { } + + virtual boost::any get(const any& key) = 0; + virtual std::string get_string(const any& key) = 0; + virtual void put(const any& key, const any& value) = 0; + virtual const std::type_info& key() const = 0; + virtual const std::type_info& value() const = 0; +}; + + +////////////////////////////////////////////////////////////////////// +// Property map exceptions +////////////////////////////////////////////////////////////////////// + +struct dynamic_property_exception : public std::exception { + virtual ~dynamic_property_exception() throw() {} + virtual const char* what() const throw() = 0; +}; + +struct property_not_found : public dynamic_property_exception { + std::string property; + mutable std::string statement; + property_not_found(const std::string& property) : property(property) {} + virtual ~property_not_found() throw() {} + + const char* what() const throw() { + if(statement.empty()) + statement = + std::string("Property not found: ") + property + "."; + + return statement.c_str(); + } +}; + +struct dynamic_get_failure : public dynamic_property_exception { + std::string property; + mutable std::string statement; + dynamic_get_failure(const std::string& property) : property(property) {} + virtual ~dynamic_get_failure() throw() {} + + const char* what() const throw() { + if(statement.empty()) + statement = + std::string( + "dynamic property get cannot retrieve value for property: ") + + property + "."; + + return statement.c_str(); + } +}; + +struct dynamic_const_put_error : public dynamic_property_exception { + virtual ~dynamic_const_put_error() throw() {} + + const char* what() const throw() { + return "Attempt to put a value into a const property map: "; + } +}; + + +namespace detail { + +// +// dynamic_property_map_adaptor - +// property-map adaptor to support runtime polymorphism. +template +class dynamic_property_map_adaptor : public dynamic_property_map +{ + typedef typename property_traits::key_type key_type; + typedef typename property_traits::value_type value_type; + typedef typename property_traits::category category; + + // do_put - overloaded dispatches from the put() member function. + // Attempts to "put" to a property map that does not model + // WritablePropertyMap result in a runtime exception. + + // in_value must either hold an object of value_type or a string that + // can be converted to value_type via iostreams. + void do_put(const any& in_key, const any& in_value, mpl::bool_) + { +#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 95)) + using boost::put; +#endif + + key_type key = any_cast(in_key); + if (in_value.type() == typeid(value_type)) { +#if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 95) + boost::put(property_map, key, any_cast(in_value)); +#else + put(property_map, key, any_cast(in_value)); +#endif + } else { + // if in_value is an empty string, put a default constructed value_type. + std::string v = any_cast(in_value); + if (v.empty()) { +#if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 95) + boost::put(property_map, key, value_type()); +#else + put(property_map, key, value_type()); +#endif + } else { +#if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 95) + boost::put(property_map, key, detail::read_value(v)); +#else + put(property_map, key, detail::read_value(v)); +#endif + } + } + } + + void do_put(const any&, const any&, mpl::bool_) + { + throw dynamic_const_put_error(); + } + +public: + explicit dynamic_property_map_adaptor(const PropertyMap& property_map) + : property_map(property_map) { } + + virtual boost::any get(const any& key) + { +#if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 95) + return boost::get(property_map, any_cast(key)); +#else + using boost::get; + + return get(property_map, any_cast(key)); +#endif + } + + virtual std::string get_string(const any& key) + { +#if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 95) + std::ostringstream out; + out << boost::get(property_map, any_cast(key)); + return out.str(); +#else + using boost::get; + + std::ostringstream out; + out << get(property_map, any_cast(key)); + return out.str(); +#endif + } + + virtual void put(const any& in_key, const any& in_value) + { + do_put(in_key, in_value, + mpl::bool_<(is_convertible::value)>()); + } + + virtual const std::type_info& key() const { return typeid(key_type); } + virtual const std::type_info& value() const { return typeid(value_type); } + + PropertyMap& base() { return property_map; } + const PropertyMap& base() const { return property_map; } + +private: + PropertyMap property_map; +}; + +} // namespace detail + +// +// dynamic_properties - +// container for dynamic property maps +// +struct dynamic_properties +{ + typedef std::multimap + property_maps_type; + typedef boost::function3, + const std::string&, + const boost::any&, + const boost::any&> generate_fn_type; +public: + + typedef property_maps_type::iterator iterator; + typedef property_maps_type::const_iterator const_iterator; + + dynamic_properties() : generate_fn() { } + dynamic_properties(const generate_fn_type& g) : generate_fn(g) {} + + ~dynamic_properties() + { + for (property_maps_type::iterator i = property_maps.begin(); + i != property_maps.end(); ++i) { + delete i->second; + } + } + + template + dynamic_properties& + property(const std::string& name, PropertyMap property_map) + { + // Tbd: exception safety + std::auto_ptr pm( + new detail::dynamic_property_map_adaptor(property_map)); + property_maps_type::iterator i = + property_maps.insert(property_maps_type::value_type(name, 0)); + i->second = pm.release(); + + return *this; + } + + iterator begin() { return property_maps.begin(); } + const_iterator begin() const { return property_maps.begin(); } + iterator end() { return property_maps.end(); } + const_iterator end() const { return property_maps.end(); } + + iterator lower_bound(const std::string& name) + { return property_maps.lower_bound(name); } + + const_iterator lower_bound(const std::string& name) const + { return property_maps.lower_bound(name); } + + void + insert(const std::string& name, std::auto_ptr pm) + { + property_maps.insert(property_maps_type::value_type(name, pm.release())); + } + + template + std::auto_ptr + generate(const std::string& name, const Key& key, const Value& value) + { + if(!generate_fn) { + throw property_not_found(name); + } else { + return generate_fn(name,key,value); + } + } + +private: + property_maps_type property_maps; + generate_fn_type generate_fn; +}; + +template +bool +put(const std::string& name, dynamic_properties& dp, const Key& key, + const Value& value) +{ + for (dynamic_properties::iterator i = dp.lower_bound(name); + i != dp.end() && i->first == name; ++i) { + if (i->second->key() == typeid(key)) { + i->second->put(key, value); + return true; + } + } + + std::auto_ptr new_map = dp.generate(name, key, value); + if (new_map.get()) { + new_map->put(key, value); + dp.insert(name, new_map); + return true; + } else { + return false; + } +} + +#ifndef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS +template +Value +get(const std::string& name, const dynamic_properties& dp, const Key& key) +{ + for (dynamic_properties::const_iterator i = dp.lower_bound(name); + i != dp.end() && i->first == name; ++i) { + if (i->second->key() == typeid(key)) + return any_cast(i->second->get(key)); + } + + throw dynamic_get_failure(name); +} +#endif + +template +Value +get(const std::string& name, const dynamic_properties& dp, const Key& key, type) +{ + for (dynamic_properties::const_iterator i = dp.lower_bound(name); + i != dp.end() && i->first == name; ++i) { + if (i->second->key() == typeid(key)) + return any_cast(i->second->get(key)); + } + + throw dynamic_get_failure(name); +} + +template +std::string +get(const std::string& name, const dynamic_properties& dp, const Key& key) +{ + for (dynamic_properties::const_iterator i = dp.lower_bound(name); + i != dp.end() && i->first == name; ++i) { + if (i->second->key() == typeid(key)) + return i->second->get_string(key); + } + + throw dynamic_get_failure(name); +} + +// The easy way to ignore properties. +inline +std::auto_ptr +ignore_other_properties(const std::string&, + const boost::any&, + const boost::any&) { + return std::auto_ptr(0); +} + +} // namespace boost + +#endif // DYNAMIC_PROPERTY_MAP_RG09302004_HPP diff --git a/win32/include/boost/enable_shared_from_this.hpp b/win32/include/boost/enable_shared_from_this.hpp new file mode 100755 index 000000000..28042c886 --- /dev/null +++ b/win32/include/boost/enable_shared_from_this.hpp @@ -0,0 +1,73 @@ +#ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED +#define BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED + +// +// enable_shared_from_this.hpp +// +// Copyright (c) 2002 Peter Dimov +// +// 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) +// +// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html +// + +#include +#include +#include +#include + +namespace boost +{ + +template class enable_shared_from_this +{ +protected: + + enable_shared_from_this() + { + } + + enable_shared_from_this(enable_shared_from_this const &) + { + } + + enable_shared_from_this & operator=(enable_shared_from_this const &) + { + return *this; + } + + ~enable_shared_from_this() + { + } + +public: + + shared_ptr shared_from_this() + { + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(p.get() == this); + return p; + } + + shared_ptr shared_from_this() const + { + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(p.get() == this); + return p; + } + +// Note: No, you don't need to initialize _internal_weak_this +// +// Please read the documentation, not the code +// +// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html + + typedef T _internal_element_type; // for bcc 5.5.1 + mutable weak_ptr<_internal_element_type> _internal_weak_this; +}; + +} // namespace boost + +#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED diff --git a/win32/include/boost/exception.hpp b/win32/include/boost/exception.hpp new file mode 100755 index 000000000..f869fc725 --- /dev/null +++ b/win32/include/boost/exception.hpp @@ -0,0 +1,19 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_1D94A7C6054E11DB9804B622A1EF5492 +#define UUID_1D94A7C6054E11DB9804B622A1EF5492 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/exception/detail/cloning_base.hpp b/win32/include/boost/exception/detail/cloning_base.hpp new file mode 100755 index 000000000..4fd676366 --- /dev/null +++ b/win32/include/boost/exception/detail/cloning_base.hpp @@ -0,0 +1,38 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_F7D5662CCB0F11DCA353CAC656D89593 +#define UUID_F7D5662CCB0F11DCA353CAC656D89593 + +#include + +namespace +boost + { + namespace + exception_detail + { + class clone_base; + + class + cloning_base + { + public: + + virtual clone_base const * clone() const = 0; + + protected: + +#if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT(4) ) +virtual //Disable bogus GCC warning. +#endif + ~cloning_base() throw() + { + } + }; + } + } + +#endif diff --git a/win32/include/boost/exception/detail/counted_base.hpp b/win32/include/boost/exception/detail/counted_base.hpp new file mode 100755 index 000000000..bc562dbf8 --- /dev/null +++ b/win32/include/boost/exception/detail/counted_base.hpp @@ -0,0 +1,49 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_DBA0D90C930911DCBA7B675A56D89593 +#define UUID_DBA0D90C930911DCBA7B675A56D89593 + +#include + +namespace +boost + { + namespace + exception_detail + { + class + counted_base + { + friend + void + intrusive_ptr_add_ref( counted_base const * c ) + { + c->add_ref(); + } + + friend + void + intrusive_ptr_release( counted_base const * c ) + { + c->release(); + } + + virtual void add_ref() const=0; + virtual void release() const=0; + + protected: + +#if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT(4) ) +virtual //Disable bogus GCC warning. +#endif + ~counted_base() throw() + { + } + }; + } + } + +#endif diff --git a/win32/include/boost/exception/detail/is_output_streamable.hpp b/win32/include/boost/exception/detail/is_output_streamable.hpp new file mode 100755 index 000000000..77582a2a1 --- /dev/null +++ b/win32/include/boost/exception/detail/is_output_streamable.hpp @@ -0,0 +1,38 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_898984B4076411DD973EDFA055D89593 +#define UUID_898984B4076411DD973EDFA055D89593 + +#include + +namespace +boost + { + namespace + to_string_detail + { + template + char operator<<( std::basic_ostream &, T const & ); + + template + struct + is_output_streamable_impl + { + static std::basic_ostream & f(); + static T const & g(); + enum e { value=1!=(sizeof(f()< > + struct + is_output_streamable + { + enum e { value=to_string_detail::is_output_streamable_impl::value }; + }; + } + +#endif diff --git a/win32/include/boost/exception/detail/object_hex_dump.hpp b/win32/include/boost/exception/detail/object_hex_dump.hpp new file mode 100755 index 000000000..cad8a6499 --- /dev/null +++ b/win32/include/boost/exception/detail/object_hex_dump.hpp @@ -0,0 +1,40 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_6F463AC838DF11DDA3E6909F56D89593 +#define UUID_6F463AC838DF11DDA3E6909F56D89593 + +#include +#include +#include +#include +#include + +namespace +boost + { + namespace + exception_detail + { + template + inline + std::string + object_hex_dump( T const & x, size_t max_size=16 ) + { + std::ostringstream s; + s << "type: " << typeid(x).name() << ", size: " << sizeof(T) << ", dump: "; + size_t n=sizeof(T)>max_size?max_size:sizeof(T); + s.fill('0'); + s.width(2); + unsigned char const * b=reinterpret_cast(&x); + s << std::setw(2) << std::hex << (unsigned int)*b; + for( unsigned char const * e=b+n; ++b!=e; ) + s << " " << std::setw(2) << std::hex << (unsigned int)*b; + return s.str(); + } + } + } + +#endif diff --git a/win32/include/boost/exception/diagnostic_information.hpp b/win32/include/boost/exception/diagnostic_information.hpp new file mode 100755 index 000000000..574fa982f --- /dev/null +++ b/win32/include/boost/exception/diagnostic_information.hpp @@ -0,0 +1,27 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_0552D49838DD11DD90146B8956D89593 +#define UUID_0552D49838DD11DD90146B8956D89593 + +#include +#include +#include + +namespace +boost + { + inline + std::string + diagnostic_information( std::exception const & x ) + { + if( exception const * be = dynamic_cast(&x) ) + return be->diagnostic_information(); + else + return std::string("[ what: ") + x.what() + ", type: " + typeid(x).name() + " ]"; + } + } + +#endif diff --git a/win32/include/boost/exception/enable_current_exception.hpp b/win32/include/boost/exception/enable_current_exception.hpp new file mode 100755 index 000000000..a888d4ae1 --- /dev/null +++ b/win32/include/boost/exception/enable_current_exception.hpp @@ -0,0 +1,156 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_78CC85B2914F11DC8F47B48E55D89593 +#define UUID_78CC85B2914F11DC8F47B48E55D89593 + +#include +#include +#include +#include +#include + +namespace +boost + { + namespace + exception_detail + { + class + clone_base: + public counted_base + { + public: + + virtual void rethrow() const=0; + }; + + struct + bad_alloc_impl: + public clone_base, + public std::bad_alloc + { + void + add_ref() const + { + } + + void + release() const + { + } + + void + rethrow() const + { + throw *this; + } + }; + + template + clone_base * make_clone( T const & ); + + template + class + clone_impl: + public T, + public cloning_base + { + public: + + explicit + clone_impl( T const & x ): + T(x) + { + if( boost::exception * be1=dynamic_cast(this) ) + if( boost::exception const * be2=dynamic_cast(&x) ) + *be1 = *be2; + } + + private: + + clone_base const * + clone() const + { + return make_clone(*this); + } + }; + + template + class + exception_clone: + public T, + public clone_base + { + public: + + explicit + exception_clone( T const & x ): + T(x), + count_(0) + { + if( boost::exception * be1=dynamic_cast(this) ) + if( boost::exception const * be2=dynamic_cast(&x) ) + *be1 = *be2; + } + + private: + + detail::atomic_count mutable count_; + + void + add_ref() const + { + ++count_; + } + + void + release() const + { + if( !--count_ ) + delete this; + } + + void + rethrow() const + { + throw clone_impl(*this); + } + }; + + template + inline + clone_base * + make_clone( T const & x ) + { + try + { + return new exception_clone(x); + } + catch( + std::bad_alloc & ) + { + static bad_alloc_impl bad_alloc; + return &bad_alloc; + } + catch( + ... ) + { + BOOST_ASSERT(0); + return 0; + } + } + } + + template + inline + exception_detail::clone_impl + enable_current_exception( T const & x ) + { + return exception_detail::clone_impl(x); + } + } + +#endif diff --git a/win32/include/boost/exception/enable_error_info.hpp b/win32/include/boost/exception/enable_error_info.hpp new file mode 100755 index 000000000..7616922ac --- /dev/null +++ b/win32/include/boost/exception/enable_error_info.hpp @@ -0,0 +1,106 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_0C5D492E909711DCB658AD4556D89593 +#define UUID_0C5D492E909711DCB658AD4556D89593 + +#include +#include +#include +#include + +namespace +boost + { + namespace + exception_detail + { + template + struct + error_info_injector: + public T, + public exception + { + explicit + error_info_injector( T const & x ): + T(x) + { + } + + ~error_info_injector() throw() + { + } + + char const * + diagnostic_information() const throw() + { + return boost::exception::_diagnostic_information(T::what()); + } + }; + + struct large_size { char c[256]; }; + large_size dispatch( exception * ); + + struct small_size { }; + small_size dispatch( void * ); + + template + struct enable_error_info_helper; + + template + struct + enable_error_info_helper + { + typedef T type; + }; + + template + struct + enable_error_info_helper + { + typedef error_info_injector type; + }; + +#if BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x582)) + template + struct + sizeof_dispatch + { + BOOST_STATIC_CONSTANT(int, value = sizeof(dispatch((T*)0)) ); + }; + + template + struct + enable_error_info_return_type + { + typedef typename enable_error_info_helper::value>::type type; + }; +#else + template + struct + enable_error_info_return_type + { + typedef typename enable_error_info_helper::type type; + }; +#endif + } + + template + inline +#if !BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x582)) + typename +#endif + exception_detail::enable_error_info_return_type::type + enable_error_info( T const & x ) + { + return +#if !BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x582)) + typename +#endif + exception_detail::enable_error_info_return_type::type(x); + } + } + +#endif diff --git a/win32/include/boost/exception/error_info.hpp b/win32/include/boost/exception/error_info.hpp new file mode 100755 index 000000000..bf4eacc1e --- /dev/null +++ b/win32/include/boost/exception/error_info.hpp @@ -0,0 +1,16 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_0E57632CCA3011DCB876FD9955D89593 +#define UUID_0E57632CCA3011DCB876FD9955D89593 + +namespace +boost + { + template + class error_info; + } + +#endif diff --git a/win32/include/boost/exception/exception.hpp b/win32/include/boost/exception/exception.hpp new file mode 100755 index 000000000..719ac88dc --- /dev/null +++ b/win32/include/boost/exception/exception.hpp @@ -0,0 +1,120 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_274DA366004E11DCB1DDFE2E56D89593 +#define UUID_274DA366004E11DCB1DDFE2E56D89593 + +#include +#include +#include +#include +#include + +namespace +boost + { + template + class shared_ptr; + + namespace + exception_detail + { + class error_info_base; + + struct + error_info_container: + public exception_detail::counted_base + { + virtual char const * diagnostic_information( char const *, std::type_info const & ) const = 0; + virtual shared_ptr get( std::type_info const & ) const = 0; + virtual void set( shared_ptr const & ) = 0; + }; + } + + template + class error_info; + + template + E const & operator<<( E const &, error_info const & ); + + template + shared_ptr get_error_info( E const & ); + + class + exception + { + public: + + virtual + char const * + diagnostic_information() const throw() + { + return _diagnostic_information(0); + } + + protected: + + exception() + { + } + + exception( exception const & e ): + data_(e.data_) + { + } + + char const * + _diagnostic_information( char const * std_what ) const throw() + { + if( data_ ) + try + { + char const * w = data_->diagnostic_information(std_what,typeid(*this)); + BOOST_ASSERT(0!=w); + return w; + } + catch(...) + { + } + return std_what ? std_what : typeid(*this).name(); + } + +#if BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1500) ) + //Force class exception to be abstract. + //Otherwise, MSVC bug allows throw exception(), even though the copy constructor is protected. + virtual ~exception() throw()=0; +#else +#if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT(4) ) + virtual //Disable bogus GCC warning. +#endif + ~exception() throw() + { + } +#endif + + private: + + shared_ptr get( std::type_info const & ) const; + void set( shared_ptr const & ) const; + + template + friend E const & operator<<( E const &, error_info const & ); + + template + friend shared_ptr get_error_info( E const & ); + + intrusive_ptr mutable data_; + }; + +#if BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1500) ) //See above. + inline + exception:: + ~exception() throw() + { + } +#endif + } + +#endif diff --git a/win32/include/boost/exception/info.hpp b/win32/include/boost/exception/info.hpp new file mode 100755 index 000000000..c43e93588 --- /dev/null +++ b/win32/include/boost/exception/info.hpp @@ -0,0 +1,244 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_8D22C4CA9CC811DCAA9133D256D89593 +#define UUID_8D22C4CA9CC811DCAA9133D256D89593 + +#include +#include +#include +#include +#include +#include +#include + +#define BOOST_ERROR_INFO\ + ::boost::throw_function(BOOST_CURRENT_FUNCTION) <<\ + ::boost::throw_file(__FILE__) <<\ + ::boost::throw_line((int)__LINE__) + +namespace +boost + { + typedef error_info throw_function; + typedef error_info throw_file; + typedef error_info throw_line; + + namespace + exception_detail + { + class + error_info_base + { + public: + + virtual std::type_info const & tag_typeid() const = 0; + virtual std::string value_as_string() const = 0; + + protected: + +#if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT(4) ) +virtual //Disable bogus GCC warning. +#endif + ~error_info_base() + { + } + }; + } + + template + class + error_info: + public exception_detail::error_info_base + { + public: + + typedef T value_type; + + error_info( value_type const & value ): + value_(value) + { + } + + value_type const & + value() const + { + return value_; + } + + private: + + std::type_info const & + tag_typeid() const + { + return typeid(type); + } + + std::string + value_as_string() const + { + return to_string_stub(value_); + } + + value_type const value_; + }; + + template + inline + E const & + operator<<( E const & x, error_info const & v ) + { + shared_ptr< error_info > p( new error_info(v) ); + x.set(p); + return x; + } + + template + inline + shared_ptr + get_error_info( E const & some_exception ) + { + if( exception const * x = dynamic_cast(&some_exception) ) + if( shared_ptr eib = x->get(typeid(ErrorInfo)) ) + { + BOOST_ASSERT( 0!=dynamic_cast(eib.get()) ); + ErrorInfo const * w = static_cast(eib.get()); + return shared_ptr(eib,&w->value()); + } + return shared_ptr(); + } + + namespace + exception_detail + { + class + error_info_container_impl: + public error_info_container + { + public: + + error_info_container_impl(): + count_(0) + { + } + + ~error_info_container_impl() throw() + { + } + + shared_ptr + get( std::type_info const & ti ) const + { + error_info_map::const_iterator i=info_.find(typeinfo(ti)); + if( info_.end()!=i ) + { + shared_ptr const & p = i->second; + BOOST_ASSERT( typeid(*p)==ti ); + return p; + } + return shared_ptr(); + } + + void + set( shared_ptr const & x ) + { + BOOST_ASSERT(x); + info_[typeinfo(typeid(*x))] = x; + what_.clear(); + } + + char const * + diagnostic_information( char const * std_what, std::type_info const & exception_type ) const + { + if( what_.empty() ) + { + std::string tmp; + if( std_what ) + { + tmp += std_what; + tmp += '\n'; + } + tmp += "Dynamic exception type: "; + tmp += exception_type.name(); + tmp += '\n'; + for( error_info_map::const_iterator i=info_.begin(),end=info_.end(); i!=end; ++i ) + { + shared_ptr const & x = i->second; + tmp += '['; + tmp += x->tag_typeid().name(); + tmp += "] = "; + tmp += x->value_as_string(); + tmp += '\n'; + } + what_.swap(tmp); + } + return what_.c_str(); + } + + private: + + friend class exception; + + struct + typeinfo + { + std::type_info const * type; + + explicit + typeinfo( std::type_info const & t ): + type(&t) + { + } + + bool + operator<( typeinfo const & b ) const + { + return 0!=(type->before(*b.type)); + } + }; + + typedef std::map< typeinfo, shared_ptr > error_info_map; + error_info_map info_; + std::string mutable what_; + int mutable count_; + + void + add_ref() const + { + ++count_; + } + + void + release() const + { + if( !--count_ ) + delete this; + } + }; + } + + inline + void + exception:: + set( shared_ptr const & x ) const + { + if( !data_ ) + data_ = intrusive_ptr(new exception_detail::error_info_container_impl); + data_->set(x); + } + + inline + shared_ptr + exception:: + get( std::type_info const & ti ) const + { + if( data_ ) + return data_->get(ti); + else + return shared_ptr(); + } + } + +#endif diff --git a/win32/include/boost/exception/info_tuple.hpp b/win32/include/boost/exception/info_tuple.hpp new file mode 100755 index 000000000..4bb9e5039 --- /dev/null +++ b/win32/include/boost/exception/info_tuple.hpp @@ -0,0 +1,67 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_63EE924290FB11DC87BB856555D89593 +#define UUID_63EE924290FB11DC87BB856555D89593 + +#include +#include + +namespace +boost + { + template < + class E, + class Tag1,class T1, + class Tag2,class T2 > + inline + E const & + operator<<( + E const & x, + tuple< + error_info, + error_info > const & v ) + { + return x << v.template get<0>() << v.template get<1>(); + } + + template < + class E, + class Tag1,class T1, + class Tag2,class T2, + class Tag3,class T3 > + inline + E const & + operator<<( + E const & x, + tuple< + error_info, + error_info, + error_info > const & v ) + { + return x << v.template get<0>() << v.template get<1>() << v.template get<2>(); + } + + template < + class E, + class Tag1,class T1, + class Tag2,class T2, + class Tag3,class T3, + class Tag4,class T4 > + inline + E const & + operator<<( + E const & x, + tuple< + error_info, + error_info, + error_info, + error_info > const & v ) + { + return x << v.template get<0>() << v.template get<1>() << v.template get<2>() << v.template get<3>(); + } + } + +#endif diff --git a/win32/include/boost/exception/to_string.hpp b/win32/include/boost/exception/to_string.hpp new file mode 100755 index 000000000..53d109a12 --- /dev/null +++ b/win32/include/boost/exception/to_string.hpp @@ -0,0 +1,74 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_7E48761AD92811DC9011477D56D89593 +#define UUID_7E48761AD92811DC9011477D56D89593 + +#include +#include +#include + +namespace +boost + { + namespace + to_string_detail + { + template + typename disable_if,char>::type to_string( T const & ); + + template + struct has_to_string_impl; + + template + struct + has_to_string_impl + { + enum e { value=1 }; + }; + + template + struct + has_to_string_impl + { + static T const & f(); + enum e { value=1!=sizeof(to_string(f())) }; + }; + } + + template + inline + typename enable_if,std::string>::type + to_string( T const & x ) + { + std::ostringstream out; + out << x; + return out.str(); + } + + template + struct + has_to_string + { + enum e { value=to_string_detail::has_to_string_impl::value>::value }; + }; + + template + inline + std::string + to_string( std::pair const & x ) + { + return std::string("(") + to_string(x.first) + ',' + to_string(x.second) + ')'; + } + + inline + std::string + to_string( std::exception const & x ) + { + return x.what(); + } + } + +#endif diff --git a/win32/include/boost/exception/to_string_stub.hpp b/win32/include/boost/exception/to_string_stub.hpp new file mode 100755 index 000000000..b371b00bf --- /dev/null +++ b/win32/include/boost/exception/to_string_stub.hpp @@ -0,0 +1,100 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_E788439ED9F011DCB181F25B55D89593 +#define UUID_E788439ED9F011DCB181F25B55D89593 + +#include +#include +#include + +namespace +boost + { + namespace + exception_detail + { + template + struct + to_string_dispatcher + { + template + static + std::string + convert( T const & x, Stub ) + { + return to_string(x); + } + }; + + template <> + struct + to_string_dispatcher + { + template + static + std::string + convert( T const & x, Stub s ) + { + return s(x); + } + + template + static + std::string + convert( T const & x, std::string s ) + { + return s; + } + + template + static + std::string + convert( T const & x, char const * s ) + { + BOOST_ASSERT(s!=0); + return s; + } + }; + + namespace + to_string_dispatch + { + template + inline + std::string + dispatch( T const & x, Stub s ) + { + return to_string_dispatcher::value>::convert(x,s); + } + } + + template + inline + std::string + string_stub_dump( T const & x ) + { + return "[ " + exception_detail::object_hex_dump(x) + " ]"; + } + } + + template + inline + std::string + to_string_stub( T const & x ) + { + return exception_detail::to_string_dispatch::dispatch(x,&exception_detail::string_stub_dump); + } + + template + inline + std::string + to_string_stub( T const & x, Stub s ) + { + return exception_detail::to_string_dispatch::dispatch(x,s); + } + } + +#endif diff --git a/win32/include/boost/exception_ptr.hpp b/win32/include/boost/exception_ptr.hpp new file mode 100755 index 000000000..d40f56bc8 --- /dev/null +++ b/win32/include/boost/exception_ptr.hpp @@ -0,0 +1,196 @@ +//Copyright (c) 2006-2008 Emil Dotchevski and Reverge Studios, Inc. + +//Distributed under the Boost Software License, Version 1.0. (See accompanying +//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef UUID_FA5836A2CADA11DC8CD47C8555D89593 +#define UUID_FA5836A2CADA11DC8CD47C8555D89593 + +#include +#include +#include +#include +#include + +namespace +boost + { + class + unknown_exception: + public exception, + public std::exception + { + public: + + unknown_exception() + { + } + + explicit + unknown_exception( boost::exception const & e ): + boost::exception(e) + { + } + + ~unknown_exception() throw() + { + } + }; + + typedef intrusive_ptr exception_ptr; + + namespace + exception_detail + { + template + class + current_exception_std_exception_wrapper: + public T, + public boost::exception + { + public: + + explicit + current_exception_std_exception_wrapper( T const & e1 ): + T(e1) + { + } + + current_exception_std_exception_wrapper( T const & e1, boost::exception const & e2 ): + T(e1), + boost::exception(e2) + { + } + + ~current_exception_std_exception_wrapper() throw() + { + } + }; + + template + inline + exception_ptr + current_exception_std_exception( T const & e1 ) + { + if( boost::exception const * e2 = dynamic_cast(&e1) ) + return exception_ptr(exception_detail::make_clone(current_exception_std_exception_wrapper(e1,*e2))); + else + return exception_ptr(exception_detail::make_clone(current_exception_std_exception_wrapper(e1))); + } + + inline + exception_ptr + current_exception_unknown_exception() + { + return exception_ptr(exception_detail::make_clone(unknown_exception())); + } + + inline + exception_ptr + current_exception_unknown_std_exception( std::exception const & e ) + { + if( boost::exception const * be = dynamic_cast(&e) ) + return exception_ptr(exception_detail::make_clone(unknown_exception(*be))); + else + return current_exception_unknown_exception(); + } + + inline + exception_ptr + current_exception_unknown_boost_exception( boost::exception const & e ) + { + return exception_ptr(exception_detail::make_clone(unknown_exception(e))); + } + } + + inline + exception_ptr + current_exception() + { + try + { + throw; + } + catch( + exception_detail::cloning_base & e ) + { + exception_detail::clone_base const * c = e.clone(); + BOOST_ASSERT(c!=0); + return exception_ptr(c); + } + catch( + std::invalid_argument & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::out_of_range & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::logic_error & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::bad_alloc & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::bad_cast & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::bad_typeid & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::bad_exception & e ) + { + return exception_detail::current_exception_std_exception(e); + } + catch( + std::exception & e ) + { + return exception_detail::current_exception_unknown_std_exception(e); + } + catch( + boost::exception & e ) + { + return exception_detail::current_exception_unknown_boost_exception(e); + } + catch( + ... ) + { + return exception_detail::current_exception_unknown_exception(); + } + } + + template + inline + exception_ptr + copy_exception( T const & e ) + { + try + { + throw enable_current_exception(e); + } + catch( ... ) + { + return current_exception(); + } + } + + inline + void + rethrow_exception( exception_ptr const & p ) + { + p->rethrow(); + } + } + +#endif diff --git a/win32/include/boost/filesystem.hpp b/win32/include/boost/filesystem.hpp new file mode 100755 index 000000000..d89914a68 --- /dev/null +++ b/win32/include/boost/filesystem.hpp @@ -0,0 +1,20 @@ +// boost/filesystem/filesystem.hpp -----------------------------------------// + +// Copyright Beman Dawes 2005 + +// Use, modification, and distribution is subject to 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) + +// See library home page at http://www.boost.org/libs/filesystem + +//----------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_FILESYSTEM_HPP +#define BOOST_FILESYSTEM_FILESYSTEM_HPP + +#include // includes path.hpp +#include + +#endif + diff --git a/win32/include/boost/filesystem/config.hpp b/win32/include/boost/filesystem/config.hpp new file mode 100755 index 000000000..b845cf13e --- /dev/null +++ b/win32/include/boost/filesystem/config.hpp @@ -0,0 +1,113 @@ +// boost/filesystem/config.hpp ---------------------------------------------// + +// Copyright Beman Dawes 2003 + +// 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) + +// See library home page at http://www.boost.org/libs/filesystem + +//----------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_CONFIG_HPP +#define BOOST_FILESYSTEM_CONFIG_HPP + +#define BOOST_FILESYSTEM_I18N // aid users wishing to compile several versions + +// ability to change namespace aids path_table.cpp ------------------------// +#ifndef BOOST_FILESYSTEM_NAMESPACE +# define BOOST_FILESYSTEM_NAMESPACE filesystem +#endif + +// This header implements separate compilation features as described in +// http://www.boost.org/more/separate_compilation.html + +#include +#include + +// determine platform ------------------------------------------------------// + +// BOOST_CYGWIN_PATH implies BOOST_WINDOWS_PATH and BOOST_POSIX_API + +# if defined(BOOST_CYGWIN_PATH) +# if defined(BOOST_POSIX_PATH) +# error BOOST_POSIX_PATH is invalid when BOOST_CYGWIN_PATH is defined +# endif +# if defined(BOOST_WINDOWS_API) +# error BOOST_WINDOWS_API is invalid when BOOST_CYGWIN_PATH is defined +# endif +# define BOOST_WINDOWS_PATH +# define BOOST_POSIX_API +# endif + +// BOOST_POSIX_API or BOOST_WINDOWS_API specify which API to use + +# if defined( BOOST_WINDOWS_API ) && defined( BOOST_POSIX_API ) +# error both BOOST_WINDOWS_API and BOOST_POSIX_API are defined +# elif !defined( BOOST_WINDOWS_API ) && !defined( BOOST_POSIX_API ) +# if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__) +# define BOOST_WINDOWS_API +# else +# define BOOST_POSIX_API +# endif +# endif + +// BOOST_WINDOWS_PATH enables Windows path syntax recognition + +# if !defined(BOOST_POSIX_PATH) && (defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +# define BOOST_WINDOWS_PATH +# endif + +// narrow support only for badly broken compilers or libraries -------------// + +# if defined(BOOST_NO_STD_WSTRING) || defined(BOOST_NO_SFINAE) || defined(BOOST_NO_STD_LOCALE) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) +# define BOOST_FILESYSTEM_NARROW_ONLY +# endif + +// enable dynamic linking on Windows ---------------------------------------// + +# if (defined(BOOST_ALL_DYN_LINK) || defined(BOOST_FILESYSTEM_DYN_LINK)) && defined(__BORLANDC__) && defined(__WIN32__) +# error Dynamic linking Boost.Filesystem does not work for Borland; use static linking instead +# endif + +#ifdef BOOST_HAS_DECLSPEC // defined in config system +// we need to import/export our code only if the user has specifically +// asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost +// libraries to be dynamically linked, or BOOST_FILESYSTEM_DYN_LINK +// if they want just this one to be dynamically liked: +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_FILESYSTEM_DYN_LINK) +// export if this is our own source, otherwise import: +#ifdef BOOST_FILESYSTEM_SOURCE +# define BOOST_FILESYSTEM_DECL __declspec(dllexport) +#else +# define BOOST_FILESYSTEM_DECL __declspec(dllimport) +#endif // BOOST_FILESYSTEM_SOURCE +#endif // DYN_LINK +#endif // BOOST_HAS_DECLSPEC +// +// if BOOST_FILESYSTEM_DECL isn't defined yet define it now: +#ifndef BOOST_FILESYSTEM_DECL +#define BOOST_FILESYSTEM_DECL +#endif + +// enable automatic library variant selection ------------------------------// + +#if !defined(BOOST_FILESYSTEM_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_FILESYSTEM_NO_LIB) +// +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it: +// +#define BOOST_LIB_NAME boost_filesystem +// +// If we're importing code from a dll, then tell auto_link.hpp about it: +// +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_FILESYSTEM_DYN_LINK) +# define BOOST_DYN_LINK +#endif +// +// And include the header that does the work: +// +#include +#endif // auto-linking disabled + +#endif // BOOST_FILESYSTEM_CONFIG_HPP diff --git a/win32/include/boost/filesystem/convenience.hpp b/win32/include/boost/filesystem/convenience.hpp new file mode 100755 index 000000000..98eec941f --- /dev/null +++ b/win32/include/boost/filesystem/convenience.hpp @@ -0,0 +1,291 @@ +// boost/filesystem/convenience.hpp ----------------------------------------// + +// Copyright Beman Dawes, 2002-2005 +// Copyright Vladimir Prus, 2002 +// Use, modification, and distribution is subject to 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) + +// See library home page at http://www.boost.org/libs/filesystem + +//----------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_CONVENIENCE_HPP +#define BOOST_FILESYSTEM_CONVENIENCE_HPP + +#include +#include +#include +#include + +#include // must be the last #include + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY +# define BOOST_FS_FUNC(BOOST_FS_TYPE) \ + template typename boost::enable_if, \ + BOOST_FS_TYPE>::type +# define BOOST_FS_FUNC_STRING BOOST_FS_FUNC(typename Path::string_type) +# define BOOST_FS_TYPENAME typename +# else +# define BOOST_FS_FUNC(BOOST_FS_TYPE) inline BOOST_FS_TYPE + typedef boost::filesystem::path Path; +# define BOOST_FS_FUNC_STRING inline std::string +# define BOOST_FS_TYPENAME +# endif + +namespace boost +{ + namespace filesystem + { + + BOOST_FS_FUNC(bool) create_directories(const Path& ph) + { + if (ph.empty() || exists(ph)) + { + if ( !ph.empty() && !is_directory(ph) ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::create_directories", ph, + make_error_code( boost::system::posix::file_exists ) ) ); + return false; + } + + // First create branch, by calling ourself recursively + create_directories(ph.parent_path()); + // Now that parent's path exists, create the directory + create_directory(ph); + return true; + } + +# ifndef BOOST_FILESYSTEM_NO_DEPRECATED + + BOOST_FS_FUNC_STRING extension(const Path& ph) + { + typedef BOOST_FS_TYPENAME Path::string_type string_type; + string_type filename = ph.filename(); + + BOOST_FS_TYPENAME string_type::size_type n = filename.rfind('.'); + if (n != string_type::npos) + return filename.substr(n); + else + return string_type(); + } + + BOOST_FS_FUNC_STRING basename(const Path& ph) + { + typedef BOOST_FS_TYPENAME Path::string_type string_type; + string_type filename = ph.filename(); + BOOST_FS_TYPENAME string_type::size_type n = filename.rfind('.'); + return filename.substr(0, n); + } + + + BOOST_FS_FUNC(Path) change_extension( const Path & ph, + const BOOST_FS_TYPENAME Path::string_type & new_extension ) + { return ph.parent_path() / (basename(ph) + new_extension); } + +# endif + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + + // "do-the-right-thing" overloads ---------------------------------------// + + inline bool create_directories(const path& ph) + { return create_directories(ph); } + inline bool create_directories(const wpath& ph) + { return create_directories(ph); } + + inline std::string extension(const path& ph) + { return extension(ph); } + inline std::wstring extension(const wpath& ph) + { return extension(ph); } + + inline std::string basename(const path& ph) + { return basename( ph ); } + inline std::wstring basename(const wpath& ph) + { return basename( ph ); } + + inline path change_extension( const path & ph, const std::string& new_ex ) + { return change_extension( ph, new_ex ); } + inline wpath change_extension( const wpath & ph, const std::wstring& new_ex ) + { return change_extension( ph, new_ex ); } + +# endif + + + // basic_recursive_directory_iterator helpers --------------------------// + + namespace detail + { + template< class Path > + struct recur_dir_itr_imp + { + typedef basic_directory_iterator< Path > element_type; + std::stack< element_type, std::vector< element_type > > m_stack; + int m_level; + bool m_no_push; + bool m_no_throw; + + recur_dir_itr_imp() : m_level(0), m_no_push(false), m_no_throw(false) {} + }; + + } // namespace detail + + // basic_recursive_directory_iterator ----------------------------------// + + template< class Path > + class basic_recursive_directory_iterator + : public boost::iterator_facade< + basic_recursive_directory_iterator, + basic_directory_entry, + boost::single_pass_traversal_tag > + { + public: + typedef Path path_type; + + basic_recursive_directory_iterator(){} // creates the "end" iterator + + explicit basic_recursive_directory_iterator( const Path & dir_path ); + basic_recursive_directory_iterator( const Path & dir_path, + system::error_code & ec ); + + int level() const { return m_imp->m_level; } + + void pop(); + void no_push() + { + BOOST_ASSERT( m_imp.get() && "attempt to no_push() on end iterator" ); + m_imp->m_no_push = true; + } + + file_status status() const + { + BOOST_ASSERT( m_imp.get() + && "attempt to call status() on end recursive_iterator" ); + return m_imp->m_stack.top()->status(); + } + + file_status symlink_status() const + { + BOOST_ASSERT( m_imp.get() + && "attempt to call symlink_status() on end recursive_iterator" ); + return m_imp->m_stack.top()->symlink_status(); + } + + private: + + // shared_ptr provides shallow-copy semantics required for InputIterators. + // m_imp.get()==0 indicates the end iterator. + boost::shared_ptr< detail::recur_dir_itr_imp< Path > > m_imp; + + friend class boost::iterator_core_access; + + typename boost::iterator_facade< + basic_recursive_directory_iterator, + basic_directory_entry, + boost::single_pass_traversal_tag >::reference + dereference() const + { + BOOST_ASSERT( m_imp.get() && "attempt to dereference end iterator" ); + return *m_imp->m_stack.top(); + } + + void increment(); + + bool equal( const basic_recursive_directory_iterator & rhs ) const + { return m_imp == rhs.m_imp; } + + }; + + typedef basic_recursive_directory_iterator recursive_directory_iterator; +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + typedef basic_recursive_directory_iterator wrecursive_directory_iterator; +# endif + + // basic_recursive_directory_iterator implementation -------------------// + + // constructors + template + basic_recursive_directory_iterator:: + basic_recursive_directory_iterator( const Path & dir_path ) + : m_imp( new detail::recur_dir_itr_imp ) + { + m_imp->m_stack.push( basic_directory_iterator( dir_path ) ); + if ( m_imp->m_stack.top () == basic_directory_iterator() ) + { m_imp.reset (); } + } + + template + basic_recursive_directory_iterator:: + basic_recursive_directory_iterator( const Path & dir_path, + system::error_code & ec ) + : m_imp( new detail::recur_dir_itr_imp ) + { + m_imp->m_no_throw = true; + m_imp->m_stack.push( basic_directory_iterator( dir_path, ec ) ); + if ( m_imp->m_stack.top () == basic_directory_iterator() ) + { m_imp.reset (); } + } + + // increment + template + void basic_recursive_directory_iterator::increment() + { + BOOST_ASSERT( m_imp.get() && "increment on end iterator" ); + + static const basic_directory_iterator end_itr; + + if ( m_imp->m_no_push ) + { m_imp->m_no_push = false; } + else if ( is_directory( m_imp->m_stack.top()->status() ) ) + { + system::error_code ec; + m_imp->m_stack.push( + m_imp->m_no_throw + ? basic_directory_iterator( *m_imp->m_stack.top(), ec ) + : basic_directory_iterator( *m_imp->m_stack.top() ) ); + if ( m_imp->m_stack.top() != end_itr ) + { + ++m_imp->m_level; + return; + } + m_imp->m_stack.pop(); + } + + while ( !m_imp->m_stack.empty() + && ++m_imp->m_stack.top() == end_itr ) + { + m_imp->m_stack.pop(); + --m_imp->m_level; + } + + if ( m_imp->m_stack.empty() ) m_imp.reset(); // done, so make end iterator + } + + // pop + template + void basic_recursive_directory_iterator::pop() + { + BOOST_ASSERT( m_imp.get() && "pop on end iterator" ); + BOOST_ASSERT( m_imp->m_level > 0 && "pop with level < 1" ); + + static const basic_directory_iterator end_itr; + + do + { + m_imp->m_stack.pop(); + --m_imp->m_level; + } + while ( !m_imp->m_stack.empty() + && ++m_imp->m_stack.top() == end_itr ); + + if ( m_imp->m_stack.empty() ) m_imp.reset(); // done, so make end iterator + } + + } // namespace filesystem +} // namespace boost + +#undef BOOST_FS_FUNC_STRING +#undef BOOST_FS_FUNC + +#include // pops abi_prefix.hpp pragmas +#endif // BOOST_FILESYSTEM_CONVENIENCE_HPP diff --git a/win32/include/boost/filesystem/exception.hpp b/win32/include/boost/filesystem/exception.hpp new file mode 100755 index 000000000..0d7d38358 --- /dev/null +++ b/win32/include/boost/filesystem/exception.hpp @@ -0,0 +1,9 @@ +// boost/filesystem/exception.hpp -------------------------------------------// + +// Copyright Beman Dawes 2003 +// Use, modification, and distribution is subject to 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) + +// This header is no long used. The contents have been moved to path.hpp. +// It is provided so that user code #includes do not have to be changed. diff --git a/win32/include/boost/filesystem/fstream.hpp b/win32/include/boost/filesystem/fstream.hpp new file mode 100755 index 000000000..642f7336e --- /dev/null +++ b/win32/include/boost/filesystem/fstream.hpp @@ -0,0 +1,584 @@ +// boost/filesystem/fstream.hpp --------------------------------------------// + +// Copyright Beman Dawes 2002. +// Use, modification, and distribution is subject to 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) + +// See library home page at http://www.boost.org/libs/filesystem + +//----------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_FSTREAM_HPP +#define BOOST_FILESYSTEM_FSTREAM_HPP + +#include // for 8.3 hack (see below) +#include +#include + +#include +#include + +#include // must be the last #include + +// NOTE: fstream.hpp for Boost 1.32.0 and earlier supplied workarounds for +// various compiler problems. They have been removed to ease development of the +// basic i18n functionality. Once the new interface is stable, the workarounds +// will be reinstated for any compilers that otherwise can support the rest of +// the library after internationalization. + +namespace boost +{ + namespace filesystem + { + namespace detail + { +# if defined(BOOST_WINDOWS_API) && !defined(BOOST_FILESYSTEM_NARROW_ONLY) +# if !defined(BOOST_DINKUMWARE_STDLIB) || BOOST_DINKUMWARE_STDLIB < 405 + // The 8.3 hack: + // C++98 does not supply a wchar_t open, so try to get an equivalent + // narrow char name based on the short, so-called 8.3, name. + // Not needed for Dinkumware 405 and later as they do supply wchar_t open. + BOOST_FILESYSTEM_DECL bool create_file_api( const std::wstring & ph, + std::ios_base::openmode mode ); // true if succeeds + BOOST_FILESYSTEM_DECL std::string narrow_path_api( + const std::wstring & ph ); // return is empty if fails + + inline std::string path_proxy( const std::wstring & file_ph, + std::ios_base::openmode mode ) + // Return a non-existant path if cannot supply narrow short path. + // An empty path doesn't work because some Dinkumware versions + // assert the path is non-empty. + { + std::string narrow_ph; + bool created_file( false ); + if ( !exists( file_ph ) + && (mode & std::ios_base::out) != 0 + && create_file_api( file_ph, mode ) ) + { + created_file = true; + } + narrow_ph = narrow_path_api( file_ph ); + if ( narrow_ph.empty() ) + { + if ( created_file ) remove_api( file_ph ); + narrow_ph = "\x01"; + } + return narrow_ph; + } +# else + // Dinkumware 405 and later does supply wchar_t functions + inline const std::wstring & path_proxy( const std::wstring & file_ph, + std::ios_base::openmode ) + { return file_ph; } +# endif +# endif + + inline const std::string & path_proxy( const std::string & file_ph, + std::ios_base::openmode ) + { return file_ph; } + + } // namespace detail + + template < class charT, class traits = std::char_traits > + class basic_filebuf : public std::basic_filebuf + { + private: // disallow copying + basic_filebuf( const basic_filebuf & ); + const basic_filebuf & operator=( const basic_filebuf & ); + public: + basic_filebuf() {} + virtual ~basic_filebuf() {} + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + template + typename boost::enable_if, + basic_filebuf *>::type + open( const Path & file_ph, std::ios_base::openmode mode ); + + basic_filebuf * + open( const wpath & file_ph, std::ios_base::openmode mode ); +# endif + +# if !BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) // VC++ 6.0 can't handle this + basic_filebuf * + open( const path & file_ph, std::ios_base::openmode mode ); +# endif + }; + + template < class charT, class traits = std::char_traits > + class basic_ifstream : public std::basic_ifstream + { + private: // disallow copying + basic_ifstream( const basic_ifstream & ); + const basic_ifstream & operator=( const basic_ifstream & ); + public: + basic_ifstream() {} + + // use two signatures, rather than one signature with default second + // argument, to workaround VC++ 7.1 bug (ID VSWhidbey 38416) + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + template + explicit basic_ifstream( const Path & file_ph, + typename boost::enable_if >::type* dummy = 0 ); + + template + basic_ifstream( const Path & file_ph, std::ios_base::openmode mode, + typename boost::enable_if >::type* dummy = 0 ); + + template + typename boost::enable_if, void>::type + open( const Path & file_ph ); + + template + typename boost::enable_if, void>::type + open( const Path & file_ph, std::ios_base::openmode mode ); + + explicit basic_ifstream( const wpath & file_ph ); + basic_ifstream( const wpath & file_ph, std::ios_base::openmode mode ); + void open( const wpath & file_ph ); + void open( const wpath & file_ph, std::ios_base::openmode mode ); +# endif + + explicit basic_ifstream( const path & file_ph ); + basic_ifstream( const path & file_ph, std::ios_base::openmode mode ); +# if !BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) // VC++ 6.0 can't handle this + void open( const path & file_ph ); + void open( const path & file_ph, std::ios_base::openmode mode ); +# endif + virtual ~basic_ifstream() {} + }; + + template < class charT, class traits = std::char_traits > + class basic_ofstream : public std::basic_ofstream + { + private: // disallow copying + basic_ofstream( const basic_ofstream & ); + const basic_ofstream & operator=( const basic_ofstream & ); + public: + basic_ofstream() {} + + // use two signatures, rather than one signature with default second + // argument, to workaround VC++ 7.1 bug (ID VSWhidbey 38416) + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + + template + explicit basic_ofstream( const Path & file_ph, + typename boost::enable_if >::type* dummy = 0 ); + explicit basic_ofstream( const wpath & file_ph ); + + template + basic_ofstream( const Path & file_ph, std::ios_base::openmode mode, + typename boost::enable_if >::type* dummy = 0 ); + basic_ofstream( const wpath & file_ph, std::ios_base::openmode mode ); + + template + typename boost::enable_if, void>::type + open( const Path & file_ph ); + void open( const wpath & file_ph ); + + template + typename boost::enable_if, void>::type + open( const Path & file_ph, std::ios_base::openmode mode ); + void open( const wpath & file_ph, std::ios_base::openmode mode ); + +# endif + + explicit basic_ofstream( const path & file_ph ); + basic_ofstream( const path & file_ph, std::ios_base::openmode mode ); +# if !BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) // VC++ 6.0 can't handle this + void open( const path & file_ph ); + void open( const path & file_ph, std::ios_base::openmode mode ); +# endif + virtual ~basic_ofstream() {} + }; + + template < class charT, class traits = std::char_traits > + class basic_fstream : public std::basic_fstream + { + private: // disallow copying + basic_fstream( const basic_fstream & ); + const basic_fstream & operator=( const basic_fstream & ); + public: + basic_fstream() {} + + // use two signatures, rather than one signature with default second + // argument, to workaround VC++ 7.1 bug (ID VSWhidbey 38416) + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + + template + explicit basic_fstream( const Path & file_ph, + typename boost::enable_if >::type* dummy = 0 ); + explicit basic_fstream( const wpath & file_ph ); + + template + basic_fstream( const Path & file_ph, std::ios_base::openmode mode, + typename boost::enable_if >::type* dummy = 0 ); + basic_fstream( const wpath & file_ph, std::ios_base::openmode mode ); + + template + typename boost::enable_if, void>::type + open( const Path & file_ph ); + void open( const wpath & file_ph ); + + template + typename boost::enable_if, void>::type + open( const Path & file_ph, std::ios_base::openmode mode ); + void open( const wpath & file_ph, std::ios_base::openmode mode ); + +# endif + + explicit basic_fstream( const path & file_ph ); + basic_fstream( const path & file_ph, std::ios_base::openmode mode ); +# if !BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) // VC++ 6.0 can't handle this + void open( const path & file_ph ); + void open( const path & file_ph, std::ios_base::openmode mode ); +# endif + virtual ~basic_fstream() {} + + }; + + typedef basic_filebuf filebuf; + typedef basic_ifstream ifstream; + typedef basic_ofstream ofstream; + typedef basic_fstream fstream; + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + typedef basic_filebuf wfilebuf; + typedef basic_ifstream wifstream; + typedef basic_fstream wfstream; + typedef basic_ofstream wofstream; +# endif + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + +// basic_filebuf definitions -----------------------------------------------// + + template + template + typename boost::enable_if, + basic_filebuf *>::type + basic_filebuf::open( const Path & file_ph, + std::ios_base::openmode mode ) + { + return (std::basic_filebuf::open( detail::path_proxy( + file_ph.external_file_string(), mode ).c_str(), mode ) + == 0) ? 0 : this; + } + + template + basic_filebuf * + basic_filebuf::open( const wpath & file_ph, + std::ios_base::openmode mode ) + { + return this->BOOST_NESTED_TEMPLATE open( file_ph, mode ); + } + +// basic_ifstream definitions ----------------------------------------------// + + template template + basic_ifstream::basic_ifstream(const Path & file_ph, + typename boost::enable_if >::type* ) + : std::basic_ifstream( + detail::path_proxy( file_ph.external_file_string(), + std::ios_base::in ).c_str(), std::ios_base::in ) {} + + template + basic_ifstream::basic_ifstream( const wpath & file_ph ) + : std::basic_ifstream( + detail::path_proxy( file_ph.external_file_string(), + std::ios_base::in ).c_str(), std::ios_base::in ) {} + + template template + basic_ifstream::basic_ifstream( const Path & file_ph, + std::ios_base::openmode mode, + typename boost::enable_if >::type* ) + : std::basic_ifstream( + detail::path_proxy( file_ph.external_file_string(), + mode ).c_str(), mode | std::ios_base::in ) {} + + template + basic_ifstream::basic_ifstream( const wpath & file_ph, + std::ios_base::openmode mode ) + : std::basic_ifstream( + detail::path_proxy( file_ph.external_file_string(), + mode ).c_str(), mode | std::ios_base::in ) {} + + template template + typename boost::enable_if, void>::type + basic_ifstream::open( const Path & file_ph ) + { + std::basic_ifstream::open( + detail::path_proxy( file_ph.external_file_string(), + std::ios_base::in ).c_str(), std::ios_base::in ); + } + + template + void basic_ifstream::open( const wpath & file_ph ) + { + std::basic_ifstream::open( + detail::path_proxy( file_ph.external_file_string(), + std::ios_base::in ).c_str(), std::ios_base::in ); + } + + template template + typename boost::enable_if, void>::type + basic_ifstream::open( const Path & file_ph, + std::ios_base::openmode mode ) + { + std::basic_ifstream::open( + detail::path_proxy( file_ph.external_file_string(), + mode ).c_str(), mode | std::ios_base::in ); + } + + template + void basic_ifstream::open( const wpath & file_ph, + std::ios_base::openmode mode ) + { + std::basic_ifstream::open( + detail::path_proxy( file_ph.external_file_string(), + mode ).c_str(), mode | std::ios_base::in ); + } + +// basic_ofstream definitions ----------------------------------------------// + + template template + basic_ofstream::basic_ofstream(const Path & file_ph, + typename boost::enable_if >::type* ) + : std::basic_ofstream( + detail::path_proxy( file_ph.external_file_string(), + std::ios_base::out ).c_str(), std::ios_base::out ) {} + + template + basic_ofstream::basic_ofstream( const wpath & file_ph ) + : std::basic_ofstream( + detail::path_proxy( file_ph.external_file_string(), + std::ios_base::out ).c_str(), std::ios_base::out ) {} + + template template + basic_ofstream::basic_ofstream( const Path & file_ph, + std::ios_base::openmode mode, + typename boost::enable_if >::type* ) + : std::basic_ofstream( + detail::path_proxy( file_ph.external_file_string(), + mode ).c_str(), mode | std::ios_base::out ) {} + + template + basic_ofstream::basic_ofstream( const wpath & file_ph, + std::ios_base::openmode mode ) + : std::basic_ofstream( + detail::path_proxy( file_ph.external_file_string(), + mode ).c_str(), mode | std::ios_base::out ) {} + + template template + typename boost::enable_if, void>::type + basic_ofstream::open( const Path & file_ph ) + { + std::basic_ofstream::open( + detail::path_proxy( file_ph.external_file_string(), + std::ios_base::out ).c_str(), std::ios_base::out ); + } + + template + void basic_ofstream::open( const wpath & file_ph ) + { + std::basic_ofstream::open( + detail::path_proxy( file_ph.external_file_string(), + std::ios_base::out ).c_str(), std::ios_base::out ); + } + + template template + typename boost::enable_if, void>::type + basic_ofstream::open( const Path & file_ph, + std::ios_base::openmode mode ) + { + std::basic_ofstream::open( + detail::path_proxy( file_ph.external_file_string(), + mode ).c_str(), mode | std::ios_base::out ); + } + + template + void basic_ofstream::open( const wpath & file_ph, + std::ios_base::openmode mode ) + { + std::basic_ofstream::open( + detail::path_proxy( file_ph.external_file_string(), + mode ).c_str(), mode | std::ios_base::out ); + } + +// basic_fstream definitions -----------------------------------------------// + + template template + basic_fstream::basic_fstream(const Path & file_ph, + typename boost::enable_if >::type* ) + : std::basic_fstream( + detail::path_proxy( file_ph.external_file_string(), + std::ios_base::in|std::ios_base::out ).c_str(), + std::ios_base::in|std::ios_base::out ) {} + + template + basic_fstream::basic_fstream( const wpath & file_ph ) + : std::basic_fstream( + detail::path_proxy( file_ph.external_file_string(), + std::ios_base::in|std::ios_base::out ).c_str(), + std::ios_base::in|std::ios_base::out ) {} + + template template + basic_fstream::basic_fstream( const Path & file_ph, + std::ios_base::openmode mode, + typename boost::enable_if >::type* ) + : std::basic_fstream( + detail::path_proxy( file_ph.external_file_string(), + mode ).c_str(), mode | std::ios_base::in | std::ios_base::out ) {} + + template + basic_fstream::basic_fstream( const wpath & file_ph, + std::ios_base::openmode mode ) + : std::basic_fstream( + detail::path_proxy( file_ph.external_file_string(), + mode ).c_str(), mode | std::ios_base::in | std::ios_base::out ) {} + + template template + typename boost::enable_if, void>::type + basic_fstream::open( const Path & file_ph ) + { + std::basic_fstream::open( + detail::path_proxy( file_ph.external_file_string(), + std::ios_base::in|std::ios_base::out ).c_str(), + std::ios_base::in|std::ios_base::out ); + } + + template + void basic_fstream::open( const wpath & file_ph ) + { + std::basic_fstream::open( + detail::path_proxy( file_ph.external_file_string(), + std::ios_base::in|std::ios_base::out ).c_str(), + std::ios_base::in|std::ios_base::out ); + } + + template template + typename boost::enable_if, void>::type + basic_fstream::open( const Path & file_ph, + std::ios_base::openmode mode ) + { + std::basic_fstream::open( + detail::path_proxy( file_ph.external_file_string(), + mode ).c_str(), mode | std::ios_base::in | std::ios_base::out ); + } + + template + void basic_fstream::open( const wpath & file_ph, + std::ios_base::openmode mode ) + { + std::basic_fstream::open( + detail::path_proxy( file_ph.external_file_string(), + mode ).c_str(), mode | std::ios_base::in | std::ios_base::out ); + } + +# endif + +# if !BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) // VC++ 6.0 can't handle this + template + basic_filebuf * + basic_filebuf::open( const path & file_ph, + std::ios_base::openmode mode ) + { + return std::basic_filebuf::open( + file_ph.file_string().c_str(), mode ) == 0 ? 0 : this; + } +# endif + + template + basic_ifstream::basic_ifstream( const path & file_ph ) + : std::basic_ifstream( + file_ph.file_string().c_str(), std::ios_base::in ) {} + + template + basic_ifstream::basic_ifstream( const path & file_ph, + std::ios_base::openmode mode ) + : std::basic_ifstream( + file_ph.file_string().c_str(), mode ) {} + +# if !BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) // VC++ 6.0 can't handle this + template + void basic_ifstream::open( const path & file_ph ) + { + std::basic_ifstream::open( + file_ph.file_string().c_str(), std::ios_base::in ); + } + + template + void basic_ifstream::open( const path & file_ph, + std::ios_base::openmode mode ) + { + std::basic_ifstream::open( + file_ph.file_string().c_str(), mode ); + } +# endif + + template + basic_ofstream::basic_ofstream( const path & file_ph ) + : std::basic_ofstream( + file_ph.file_string().c_str(), std::ios_base::out ) {} + + template + basic_ofstream::basic_ofstream( const path & file_ph, + std::ios_base::openmode mode ) + : std::basic_ofstream( + file_ph.file_string().c_str(), mode ) {} + +# if !BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) // VC++ 6.0 can't handle this + template + void basic_ofstream::open( const path & file_ph ) + { + std::basic_ofstream::open( + file_ph.file_string().c_str(), std::ios_base::out ); + } + + template + void basic_ofstream::open( const path & file_ph, + std::ios_base::openmode mode ) + { + std::basic_ofstream::open( + file_ph.file_string().c_str(), mode ); + } +# endif + + template + basic_fstream::basic_fstream( const path & file_ph ) + : std::basic_fstream( + file_ph.file_string().c_str(), + std::ios_base::in|std::ios_base::out ) {} + + + template + basic_fstream::basic_fstream( const path & file_ph, + std::ios_base::openmode mode ) + : std::basic_fstream( + file_ph.file_string().c_str(), mode ) {} + +# if !BOOST_WORKAROUND( BOOST_MSVC, <= 1200 ) // VC++ 6.0 can't handle this + template + void basic_fstream::open( const path & file_ph ) + { + std::basic_fstream::open( + file_ph.file_string().c_str(), std::ios_base::in|std::ios_base::out ); + } + + template + void basic_fstream::open( const path & file_ph, + std::ios_base::openmode mode ) + { + std::basic_fstream::open( + file_ph.file_string().c_str(), mode ); + } +# endif + } // namespace filesystem +} // namespace boost + +#include // pops abi_prefix.hpp pragmas +#endif // BOOST_FILESYSTEM_FSTREAM_HPP diff --git a/win32/include/boost/filesystem/operations.hpp b/win32/include/boost/filesystem/operations.hpp new file mode 100755 index 000000000..46afeb305 --- /dev/null +++ b/win32/include/boost/filesystem/operations.hpp @@ -0,0 +1,1136 @@ +// boost/filesystem/operations.hpp -----------------------------------------// + +// Copyright 2002-2005 Beman Dawes +// Copyright 2002 Jan Langer +// Copyright 2001 Dietmar Kuehl +// +// 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) + +// See library home page at http://www.boost.org/libs/filesystem + +//----------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_OPERATIONS_HPP +#define BOOST_FILESYSTEM_OPERATIONS_HPP + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include // for pair +#include + +#ifdef BOOST_WINDOWS_API +# include +# if !defined(_WIN32_WINNT) || _WIN32_WINNT >= 0x0500 +# define BOOST_FS_HARD_LINK // Default for Windows 2K or later +# endif +#endif + +#include // must be the last #include + +# ifdef BOOST_NO_STDC_NAMESPACE + namespace std { using ::time_t; } +# endif + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY +# define BOOST_FS_FUNC(BOOST_FS_TYPE) \ + template typename boost::enable_if, \ + BOOST_FS_TYPE>::type +# define BOOST_INLINE_FS_FUNC(BOOST_FS_TYPE) \ + template inline typename boost::enable_if, \ + BOOST_FS_TYPE>::type +# define BOOST_FS_TYPENAME typename +# else +# define BOOST_FS_FUNC(BOOST_FS_TYPE) inline BOOST_FS_TYPE +# define BOOST_INLINE_FS_FUNC(BOOST_FS_TYPE) inline BOOST_FS_TYPE + typedef boost::filesystem::path Path; +# define BOOST_FS_TYPENAME +# endif + +//----------------------------------------------------------------------------// + +namespace boost +{ + namespace filesystem + { + template class basic_directory_iterator; + + // BOOST_FILESYSTEM_NARROW_ONLY needs this: + typedef basic_directory_iterator directory_iterator; + + template class basic_directory_entry; + + enum file_type + { + status_unknown, + file_not_found, + regular_file, + directory_file, + // the following will never be reported by some operating or file systems + symlink_file, + block_file, + character_file, + fifo_file, + socket_file, + type_unknown // file does exist, but isn't one of the above types or + // we don't have strong enough permission to find its type + }; + + class file_status + { + public: + explicit file_status( file_type v = status_unknown ) : m_value(v) {} + + void type( file_type v ) { m_value = v; } + file_type type() const { return m_value; } + + private: + // the internal representation is unspecified so that additional state + // information such as permissions can be added in the future; this + // implementation just uses status_type as the internal representation + + file_type m_value; + }; + + inline bool status_known( file_status f ) { return f.type() != status_unknown; } + inline bool exists( file_status f ) { return f.type() != status_unknown && f.type() != file_not_found; } + inline bool is_regular_file(file_status f){ return f.type() == regular_file; } + inline bool is_directory( file_status f ) { return f.type() == directory_file; } + inline bool is_symlink( file_status f ) { return f.type() == symlink_file; } + inline bool is_other( file_status f ) { return exists(f) && !is_regular_file(f) && !is_directory(f) && !is_symlink(f); } + +# ifndef BOOST_FILESYSTEM_NO_DEPRECATED + inline bool is_regular( file_status f ) { return f.type() == regular_file; } +# endif + + struct space_info + { + // all values are byte counts + boost::uintmax_t capacity; + boost::uintmax_t free; // <= capacity + boost::uintmax_t available; // <= free + }; + + namespace detail + { + // singular object used only as a tag; thus initialization and + // thread-safety are not issues + BOOST_FILESYSTEM_DECL extern system::error_code throws; + + typedef std::pair< system::error_code, bool > + query_pair; + + typedef std::pair< system::error_code, boost::uintmax_t > + uintmax_pair; + + typedef std::pair< system::error_code, std::time_t > + time_pair; + + typedef std::pair< system::error_code, space_info > + space_pair; + + template< class Path > + struct directory_pair + { + typedef std::pair< system::error_code, + typename Path::external_string_type > type; + }; + +# ifndef BOOST_FILESYSTEM_NO_DEPRECATED + BOOST_FILESYSTEM_DECL bool + symbolic_link_exists_api( const std::string & ); // deprecated +# endif + + BOOST_FILESYSTEM_DECL file_status + status_api( const std::string & ph, system::error_code & ec ); +# ifndef BOOST_WINDOWS_API + BOOST_FILESYSTEM_DECL file_status + symlink_status_api( const std::string & ph, system::error_code & ec ); +# endif + BOOST_FILESYSTEM_DECL query_pair + is_empty_api( const std::string & ph ); + BOOST_FILESYSTEM_DECL query_pair + equivalent_api( const std::string & ph1, const std::string & ph2 ); + BOOST_FILESYSTEM_DECL uintmax_pair + file_size_api( const std::string & ph ); + BOOST_FILESYSTEM_DECL space_pair + space_api( const std::string & ph ); + BOOST_FILESYSTEM_DECL time_pair + last_write_time_api( const std::string & ph ); + BOOST_FILESYSTEM_DECL system::error_code + last_write_time_api( const std::string & ph, std::time_t new_value ); + BOOST_FILESYSTEM_DECL system::error_code + get_current_path_api( std::string & ph ); + BOOST_FILESYSTEM_DECL system::error_code + set_current_path_api( const std::string & ph ); + BOOST_FILESYSTEM_DECL query_pair + create_directory_api( const std::string & ph ); + BOOST_FILESYSTEM_DECL system::error_code + create_hard_link_api( const std::string & to_ph, + const std::string & from_ph ); + BOOST_FILESYSTEM_DECL system::error_code + create_symlink_api( const std::string & to_ph, + const std::string & from_ph ); + BOOST_FILESYSTEM_DECL system::error_code + remove_api( const std::string & ph ); + BOOST_FILESYSTEM_DECL system::error_code + rename_api( const std::string & from, const std::string & to ); + BOOST_FILESYSTEM_DECL system::error_code + copy_file_api( const std::string & from, const std::string & to ); + +# if defined(BOOST_WINDOWS_API) + + BOOST_FILESYSTEM_DECL system::error_code + get_full_path_name_api( const std::string & ph, std::string & target ); + +# if !defined(BOOST_FILESYSTEM_NARROW_ONLY) + + BOOST_FILESYSTEM_DECL boost::filesystem::file_status + status_api( const std::wstring & ph, system::error_code & ec ); + BOOST_FILESYSTEM_DECL query_pair + is_empty_api( const std::wstring & ph ); + BOOST_FILESYSTEM_DECL query_pair + equivalent_api( const std::wstring & ph1, const std::wstring & ph2 ); + BOOST_FILESYSTEM_DECL uintmax_pair + file_size_api( const std::wstring & ph ); + BOOST_FILESYSTEM_DECL space_pair + space_api( const std::wstring & ph ); + BOOST_FILESYSTEM_DECL system::error_code + get_full_path_name_api( const std::wstring & ph, std::wstring & target ); + BOOST_FILESYSTEM_DECL time_pair + last_write_time_api( const std::wstring & ph ); + BOOST_FILESYSTEM_DECL system::error_code + last_write_time_api( const std::wstring & ph, std::time_t new_value ); + BOOST_FILESYSTEM_DECL system::error_code + get_current_path_api( std::wstring & ph ); + BOOST_FILESYSTEM_DECL system::error_code + set_current_path_api( const std::wstring & ph ); + BOOST_FILESYSTEM_DECL query_pair + create_directory_api( const std::wstring & ph ); +# ifdef BOOST_FS_HARD_LINK + BOOST_FILESYSTEM_DECL system::error_code + create_hard_link_api( const std::wstring & existing_ph, + const std::wstring & new_ph ); +# endif + BOOST_FILESYSTEM_DECL system::error_code + create_symlink_api( const std::wstring & to_ph, + const std::wstring & from_ph ); + BOOST_FILESYSTEM_DECL system::error_code + remove_api( const std::wstring & ph ); + BOOST_FILESYSTEM_DECL system::error_code + rename_api( const std::wstring & from, const std::wstring & to ); + BOOST_FILESYSTEM_DECL system::error_code + copy_file_api( const std::wstring & from, const std::wstring & to ); + +# endif +# endif + + template + unsigned long remove_all_aux( const Path & ph ); + + } // namespace detail + +// operations functions ----------------------------------------------------// + + // The non-template overloads enable automatic conversion from std and + // C-style strings. See basic_path constructors. The enable_if for the + // templates implements the famous "do-the-right-thing" rule. + +// query functions ---------------------------------------------------------// + + BOOST_INLINE_FS_FUNC(file_status) + status( const Path & ph, system::error_code & ec ) + { return detail::status_api( ph.external_file_string(), ec ); } + + BOOST_FS_FUNC(file_status) + status( const Path & ph ) + { + system::error_code ec; + file_status result( detail::status_api( ph.external_file_string(), ec ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::status", ph, ec ) ); + return result; + } + + BOOST_INLINE_FS_FUNC(file_status) + symlink_status( const Path & ph, system::error_code & ec ) +# ifdef BOOST_WINDOWS_API + { return detail::status_api( ph.external_file_string(), ec ); } +# else + { return detail::symlink_status_api( ph.external_file_string(), ec ); } +# endif + + BOOST_FS_FUNC(file_status) + symlink_status( const Path & ph ) + { + system::error_code ec; + file_status result( symlink_status( ph, ec ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::symlink_status", ph, ec ) ); + return result; + } + +# ifndef BOOST_FILESYSTEM_NO_DEPRECATED + inline bool symbolic_link_exists( const path & ph ) + { return is_symlink( symlink_status(ph) ); } +# endif + + BOOST_FS_FUNC(bool) exists( const Path & ph ) + { + system::error_code ec; + file_status result( detail::status_api( ph.external_file_string(), ec ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::exists", ph, ec ) ); + return exists( result ); + } + + BOOST_FS_FUNC(bool) is_directory( const Path & ph ) + { + system::error_code ec; + file_status result( detail::status_api( ph.external_file_string(), ec ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::is_directory", ph, ec ) ); + return is_directory( result ); + } + + BOOST_FS_FUNC(bool) is_regular_file( const Path & ph ) + { + system::error_code ec; + file_status result( detail::status_api( ph.external_file_string(), ec ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::is_regular_file", ph, ec ) ); + return is_regular_file( result ); + } + +# ifndef BOOST_FILESYSTEM_NO_DEPRECATED + BOOST_FS_FUNC(bool) is_regular( const Path & ph ) + { + system::error_code ec; + file_status result( detail::status_api( ph.external_file_string(), ec ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::is_regular", ph, ec ) ); + return is_regular( result ); + } +# endif + + BOOST_FS_FUNC(bool) is_other( const Path & ph ) + { + system::error_code ec; + file_status result( detail::status_api( ph.external_file_string(), ec ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::is_other", ph, ec ) ); + return is_other( result ); + } + + BOOST_FS_FUNC(bool) is_symlink( +# ifdef BOOST_WINDOWS_API + const Path & ) + { + return false; +# else + const Path & ph) + { + system::error_code ec; + file_status result( detail::symlink_status_api( ph.external_file_string(), ec ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::is_symlink", ph, ec ) ); + return is_symlink( result ); +# endif + } + + // VC++ 7.0 and earlier has a serious namespace bug that causes a clash + // between boost::filesystem::is_empty and the unrelated type trait + // boost::is_empty. + +# if !defined( BOOST_MSVC ) || BOOST_MSVC > 1300 + BOOST_FS_FUNC(bool) is_empty( const Path & ph ) +# else + BOOST_FS_FUNC(bool) _is_empty( const Path & ph ) +# endif + { + detail::query_pair result( + detail::is_empty_api( ph.external_file_string() ) ); + if ( result.first ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::is_empty", ph, result.first ) ); + return result.second; + } + + BOOST_FS_FUNC(bool) equivalent( const Path & ph1, const Path & ph2 ) + { + detail::query_pair result( detail::equivalent_api( + ph1.external_file_string(), ph2.external_file_string() ) ); + if ( result.first ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::equivalent", ph1, ph2, result.first ) ); + return result.second; + } + + BOOST_FS_FUNC(boost::uintmax_t) file_size( const Path & ph ) + { + detail::uintmax_pair result + ( detail::file_size_api( ph.external_file_string() ) ); + if ( result.first ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::file_size", ph, result.first ) ); + return result.second; + } + + BOOST_FS_FUNC(space_info) space( const Path & ph ) + { + detail::space_pair result + ( detail::space_api( ph.external_file_string() ) ); + if ( result.first ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::space", ph, result.first ) ); + return result.second; + } + + BOOST_FS_FUNC(std::time_t) last_write_time( const Path & ph ) + { + detail::time_pair result + ( detail::last_write_time_api( ph.external_file_string() ) ); + if ( result.first ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::last_write_time", ph, result.first ) ); + return result.second; + } + + +// operations --------------------------------------------------------------// + + BOOST_FS_FUNC(bool) create_directory( const Path & dir_ph ) + { + detail::query_pair result( + detail::create_directory_api( dir_ph.external_directory_string() ) ); + if ( result.first ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::create_directory", + dir_ph, result.first ) ); + return result.second; + } + +#if !defined(BOOST_WINDOWS_API) || defined(BOOST_FS_HARD_LINK) + BOOST_FS_FUNC(void) + create_hard_link( const Path & to_ph, const Path & from_ph ) + { + system::error_code ec( + detail::create_hard_link_api( + to_ph.external_file_string(), + from_ph.external_file_string() ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::create_hard_link", + to_ph, from_ph, ec ) ); + } + + BOOST_FS_FUNC(system::error_code) + create_hard_link( const Path & to_ph, const Path & from_ph, + system::error_code & ec ) + { + ec = detail::create_hard_link_api( + to_ph.external_file_string(), + from_ph.external_file_string() ); + return ec; + } +#endif + + BOOST_FS_FUNC(void) + create_symlink( const Path & to_ph, const Path & from_ph ) + { + system::error_code ec( + detail::create_symlink_api( + to_ph.external_file_string(), + from_ph.external_file_string() ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::create_symlink", + to_ph, from_ph, ec ) ); + } + + BOOST_FS_FUNC(system::error_code) + create_symlink( const Path & to_ph, const Path & from_ph, + system::error_code & ec ) + { + ec = detail::create_symlink_api( + to_ph.external_file_string(), + from_ph.external_file_string() ); + return ec; + } + + BOOST_FS_FUNC(void) remove( const Path & ph, system::error_code & ec = detail::throws ) + { + system::error_code error( detail::remove_api(ph.external_file_string()) ); + if ( error && &ec == &detail::throws ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::remove", ph, error ) ); + ec = error; + } + + BOOST_FS_FUNC(unsigned long) remove_all( const Path & ph ) + { + return exists( ph )|| is_symlink( ph ) + ? detail::remove_all_aux( ph ) : 0; + } + + BOOST_FS_FUNC(void) rename( const Path & from_path, const Path & to_path ) + { + system::error_code ec( detail::rename_api( + from_path.external_directory_string(), + to_path.external_directory_string() ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::rename", + from_path, to_path, ec ) ); + } + + BOOST_FS_FUNC(void) copy_file( const Path & from_path, const Path & to_path ) + { + system::error_code ec( detail::copy_file_api( + from_path.external_directory_string(), + to_path.external_directory_string() ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::copy_file", + from_path, to_path, ec ) ); + } + + template< class Path > + Path current_path() + { + typename Path::external_string_type ph; + system::error_code ec( detail::get_current_path_api( ph ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::current_path", ec ) ); + return Path( Path::traits_type::to_internal( ph ) ); + } + + BOOST_FS_FUNC(void) current_path( const Path & ph ) + { + system::error_code ec( detail::set_current_path_api( + ph.external_directory_string() ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::current_path", ph, ec ) ); + } + + template< class Path > + const Path & initial_path() + { + static Path init_path; + if ( init_path.empty() ) init_path = current_path(); + return init_path; + } + +# ifndef BOOST_FILESYSTEM_NO_DEPRECATED + // legacy support + inline path current_path() // overload supports pre-i18n apps + { return current_path(); } + inline const path & initial_path() // overload supports pre-i18n apps + { return initial_path(); } +# endif + + BOOST_FS_FUNC(Path) system_complete( const Path & ph ) + { +# ifdef BOOST_WINDOWS_API + if ( ph.empty() ) return ph; + BOOST_FS_TYPENAME Path::external_string_type sys_ph; + system::error_code ec( detail::get_full_path_name_api( ph.external_file_string(), + sys_ph ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::system_complete", ph, ec ) ); + return Path( Path::traits_type::to_internal( sys_ph ) ); +# else + return (ph.empty() || ph.is_complete()) + ? ph : current_path() / ph; +# endif + } + + BOOST_FS_FUNC(Path) + complete( const Path & ph, + const Path & base/* = initial_path() */) + { + BOOST_ASSERT( base.is_complete() + && (ph.is_complete() || !ph.has_root_name()) + && "boost::filesystem::complete() precondition not met" ); +# ifdef BOOST_WINDOWS_PATH + if (ph.empty() || ph.is_complete()) return ph; + if ( !ph.has_root_name() ) + return ph.has_root_directory() + ? Path( base.root_name() ) / ph + : base / ph; + return base / ph; +# else + return (ph.empty() || ph.is_complete()) ? ph : base / ph; +# endif + } + + // VC++ 7.1 had trouble with default arguments, so separate one argument + // signatures are provided as workarounds; the effect is the same. + BOOST_FS_FUNC(Path) complete( const Path & ph ) + { return complete( ph, initial_path() ); } + + BOOST_FS_FUNC(void) + last_write_time( const Path & ph, const std::time_t new_time ) + { + system::error_code ec( detail::last_write_time_api( ph.external_file_string(), + new_time ) ); + if ( ec ) + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::last_write_time", ph, ec ) ); + } + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + + // "do-the-right-thing" overloads ---------------------------------------// + + inline file_status status( const path & ph ) + { return status( ph ); } + inline file_status status( const wpath & ph ) + { return status( ph ); } + + inline file_status status( const path & ph, system::error_code & ec ) + { return status( ph, ec ); } + inline file_status status( const wpath & ph, system::error_code & ec ) + { return status( ph, ec ); } + + inline file_status symlink_status( const path & ph ) + { return symlink_status( ph ); } + inline file_status symlink_status( const wpath & ph ) + { return symlink_status( ph ); } + + inline file_status symlink_status( const path & ph, system::error_code & ec ) + { return symlink_status( ph, ec ); } + inline file_status symlink_status( const wpath & ph, system::error_code & ec ) + { return symlink_status( ph, ec ); } + + inline bool exists( const path & ph ) { return exists( ph ); } + inline bool exists( const wpath & ph ) { return exists( ph ); } + + inline bool is_directory( const path & ph ) + { return is_directory( ph ); } + inline bool is_directory( const wpath & ph ) + { return is_directory( ph ); } + + inline bool is_regular_file( const path & ph ) + { return is_regular_file( ph ); } + inline bool is_regular_file( const wpath & ph ) + { return is_regular_file( ph ); } + +# ifndef BOOST_FILESYSTEM_NO_DEPRECATED + inline bool is_regular( const path & ph ) + { return is_regular( ph ); } + inline bool is_regular( const wpath & ph ) + { return is_regular( ph ); } +# endif + + inline bool is_other( const path & ph ) + { return is_other( ph ); } + inline bool is_other( const wpath & ph ) + { return is_other( ph ); } + + inline bool is_symlink( const path & ph ) + { return is_symlink( ph ); } + inline bool is_symlink( const wpath & ph ) + { return is_symlink( ph ); } + + inline bool is_empty( const path & ph ) + { return is_empty( ph ); } + inline bool is_empty( const wpath & ph ) + { return is_empty( ph ); } + + inline bool equivalent( const path & ph1, const path & ph2 ) + { return equivalent( ph1, ph2 ); } + inline bool equivalent( const wpath & ph1, const wpath & ph2 ) + { return equivalent( ph1, ph2 ); } + + inline boost::uintmax_t file_size( const path & ph ) + { return file_size( ph ); } + inline boost::uintmax_t file_size( const wpath & ph ) + { return file_size( ph ); } + + inline space_info space( const path & ph ) + { return space( ph ); } + inline space_info space( const wpath & ph ) + { return space( ph ); } + + inline std::time_t last_write_time( const path & ph ) + { return last_write_time( ph ); } + inline std::time_t last_write_time( const wpath & ph ) + { return last_write_time( ph ); } + + inline bool create_directory( const path & dir_ph ) + { return create_directory( dir_ph ); } + inline bool create_directory( const wpath & dir_ph ) + { return create_directory( dir_ph ); } + +#if !defined(BOOST_WINDOWS_API) || defined(BOOST_FS_HARD_LINK) + inline void create_hard_link( const path & to_ph, + const path & from_ph ) + { return create_hard_link( to_ph, from_ph ); } + inline void create_hard_link( const wpath & to_ph, + const wpath & from_ph ) + { return create_hard_link( to_ph, from_ph ); } + + inline system::error_code create_hard_link( const path & to_ph, + const path & from_ph, system::error_code & ec ) + { return create_hard_link( to_ph, from_ph, ec ); } + inline system::error_code create_hard_link( const wpath & to_ph, + const wpath & from_ph, system::error_code & ec ) + { return create_hard_link( to_ph, from_ph, ec ); } +#endif + + inline void create_symlink( const path & to_ph, + const path & from_ph ) + { return create_symlink( to_ph, from_ph ); } + inline void create_symlink( const wpath & to_ph, + const wpath & from_ph ) + { return create_symlink( to_ph, from_ph ); } + + inline system::error_code create_symlink( const path & to_ph, + const path & from_ph, system::error_code & ec ) + { return create_symlink( to_ph, from_ph, ec ); } + inline system::error_code create_symlink( const wpath & to_ph, + const wpath & from_ph, system::error_code & ec ) + { return create_symlink( to_ph, from_ph, ec ); } + + inline void remove( const path & ph ) { remove( ph ); } + inline void remove( const wpath & ph ) { remove( ph ); } + + inline unsigned long remove_all( const path & ph ) + { return remove_all( ph ); } + inline unsigned long remove_all( const wpath & ph ) + { return remove_all( ph ); } + + inline void rename( const path & from_path, const path & to_path ) + { return rename( from_path, to_path ); } + inline void rename( const wpath & from_path, const wpath & to_path ) + { return rename( from_path, to_path ); } + + inline void copy_file( const path & from_path, const path & to_path ) + { return copy_file( from_path, to_path ); } + inline void copy_file( const wpath & from_path, const wpath & to_path ) + { return copy_file( from_path, to_path ); } + + inline path system_complete( const path & ph ) + { return system_complete( ph ); } + inline wpath system_complete( const wpath & ph ) + { return system_complete( ph ); } + + inline path complete( const path & ph, + const path & base/* = initial_path()*/ ) + { return complete( ph, base ); } + inline wpath complete( const wpath & ph, + const wpath & base/* = initial_path()*/ ) + { return complete( ph, base ); } + + inline path complete( const path & ph ) + { return complete( ph, initial_path() ); } + inline wpath complete( const wpath & ph ) + { return complete( ph, initial_path() ); } + + inline void last_write_time( const path & ph, const std::time_t new_time ) + { last_write_time( ph, new_time ); } + inline void last_write_time( const wpath & ph, const std::time_t new_time ) + { last_write_time( ph, new_time ); } + + inline void current_path( const path & ph ) + { current_path( ph ); } + inline void current_path( const wpath & ph ) + { current_path( ph ); } + +# endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY + + namespace detail + { + template + unsigned long remove_all_aux( const Path & ph ) + { + static const boost::filesystem::basic_directory_iterator end_itr; + unsigned long count = 1; + if ( !boost::filesystem::is_symlink( ph ) // don't recurse symbolic links + && boost::filesystem::is_directory( ph ) ) + { + for ( boost::filesystem::basic_directory_iterator itr( ph ); + itr != end_itr; ++itr ) + { + count += remove_all_aux( itr->path() ); + } + } + boost::filesystem::remove( ph ); + return count; + } + +// test helper -------------------------------------------------------------// + + // not part of the documented interface because false positives are possible; + // there is no law that says that an OS that has large stat.st_size + // actually supports large file sizes. + BOOST_FILESYSTEM_DECL bool possible_large_file_size_support(); + +// directory_iterator helpers ----------------------------------------------// + +// forwarding functions avoid need for BOOST_FILESYSTEM_DECL for class +// basic_directory_iterator, and so avoid iterator_facade DLL template +// problems. They also overload to the proper external path character type. + + BOOST_FILESYSTEM_DECL system::error_code + dir_itr_first( void *& handle, +#if defined(BOOST_POSIX_API) + void *& buffer, +#endif + const std::string & dir_path, + std::string & target, file_status & fs, file_status & symlink_fs ); + // eof: return==0 && handle==0 + + BOOST_FILESYSTEM_DECL system::error_code + dir_itr_increment( void *& handle, +#if defined(BOOST_POSIX_API) + void *& buffer, +#endif + std::string & target, file_status & fs, file_status & symlink_fs ); + // eof: return==0 && handle==0 + + BOOST_FILESYSTEM_DECL system::error_code + dir_itr_close( void *& handle +#if defined(BOOST_POSIX_API) + , void *& buffer +#endif + ); + // Effects: none if handle==0, otherwise close handle, set handle=0 + +# if defined(BOOST_WINDOWS_API) && !defined(BOOST_FILESYSTEM_NARROW_ONLY) + BOOST_FILESYSTEM_DECL system::error_code + dir_itr_first( void *& handle, const std::wstring & ph, + std::wstring & target, file_status & fs, file_status & symlink_fs ); + BOOST_FILESYSTEM_DECL system::error_code + dir_itr_increment( void *& handle, std::wstring & target, + file_status & fs, file_status & symlink_fs ); +# endif + + template< class Path > + class dir_itr_imp + { + public: + basic_directory_entry m_directory_entry; + void * m_handle; +# ifdef BOOST_POSIX_API + void * m_buffer; // see dir_itr_increment implementation +# endif + dir_itr_imp() : m_handle(0) +# ifdef BOOST_POSIX_API + , m_buffer(0) +# endif + {} + + ~dir_itr_imp() { dir_itr_close( m_handle +#if defined(BOOST_POSIX_API) + , m_buffer +#endif + ); } + }; + + BOOST_FILESYSTEM_DECL system::error_code not_found_error(); + + } // namespace detail + +// basic_directory_iterator ------------------------------------------------// + + template< class Path > + class basic_directory_iterator + : public boost::iterator_facade< + basic_directory_iterator, + basic_directory_entry, + boost::single_pass_traversal_tag > + { + public: + typedef Path path_type; + + basic_directory_iterator(){} // creates the "end" iterator + + explicit basic_directory_iterator( const Path & dir_path ); + basic_directory_iterator( const Path & dir_path, system::error_code & ec ); + + private: + + // shared_ptr provides shallow-copy semantics required for InputIterators. + // m_imp.get()==0 indicates the end iterator. + boost::shared_ptr< detail::dir_itr_imp< Path > > m_imp; + + friend class boost::iterator_core_access; + + typename boost::iterator_facade< + basic_directory_iterator, + basic_directory_entry, + boost::single_pass_traversal_tag >::reference dereference() const + { + BOOST_ASSERT( m_imp.get() && "attempt to dereference end iterator" ); + return m_imp->m_directory_entry; + } + + void increment(); + + bool equal( const basic_directory_iterator & rhs ) const + { return m_imp == rhs.m_imp; } + + system::error_code m_init( const Path & dir_path ); + }; + + typedef basic_directory_iterator< path > directory_iterator; +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + typedef basic_directory_iterator< wpath > wdirectory_iterator; +# endif + + // basic_directory_iterator implementation ---------------------------// + + template + system::error_code basic_directory_iterator::m_init( + const Path & dir_path ) + { + if ( dir_path.empty() ) + { + m_imp.reset(); + return detail::not_found_error(); + } + typename Path::external_string_type name; + file_status fs, symlink_fs; + system::error_code ec( detail::dir_itr_first( m_imp->m_handle, +#if defined(BOOST_POSIX_API) + m_imp->m_buffer, +#endif + dir_path.external_directory_string(), + name, fs, symlink_fs ) ); + + if ( ec ) + { + m_imp.reset(); + return ec; + } + + if ( m_imp->m_handle == 0 ) m_imp.reset(); // eof, so make end iterator + else // not eof + { + m_imp->m_directory_entry.assign( dir_path + / Path::traits_type::to_internal( name ), fs, symlink_fs ); + if ( name[0] == dot::value // dot or dot-dot + && (name.size() == 1 + || (name[1] == dot::value + && name.size() == 2)) ) + { increment(); } + } + return boost::system::error_code(); + } + + template + basic_directory_iterator::basic_directory_iterator( + const Path & dir_path ) + : m_imp( new detail::dir_itr_imp ) + { + system::error_code ec( m_init(dir_path) ); + if ( ec ) + { + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::basic_directory_iterator constructor", + dir_path, ec ) ); + } + } + + template + basic_directory_iterator::basic_directory_iterator( + const Path & dir_path, system::error_code & ec ) + : m_imp( new detail::dir_itr_imp ) + { + ec = m_init(dir_path); + } + + template + void basic_directory_iterator::increment() + { + BOOST_ASSERT( m_imp.get() && "attempt to increment end iterator" ); + BOOST_ASSERT( m_imp->m_handle != 0 && "internal program error" ); + + typename Path::external_string_type name; + file_status fs, symlink_fs; + system::error_code ec; + + for (;;) + { + ec = detail::dir_itr_increment( m_imp->m_handle, +#if defined(BOOST_POSIX_API) + m_imp->m_buffer, +#endif + name, fs, symlink_fs ); + if ( ec ) + { + boost::throw_exception( basic_filesystem_error( + "boost::filesystem::basic_directory_iterator increment", + m_imp->m_directory_entry.path().parent_path(), ec ) ); + } + if ( m_imp->m_handle == 0 ) { m_imp.reset(); return; } // eof, make end + if ( !(name[0] == dot::value // !(dot or dot-dot) + && (name.size() == 1 + || (name[1] == dot::value + && name.size() == 2))) ) + { + m_imp->m_directory_entry.replace_filename( + Path::traits_type::to_internal( name ), fs, symlink_fs ); + return; + } + } + } + + // basic_directory_entry -----------------------------------------------// + + template + class basic_directory_entry + { + public: + typedef Path path_type; + typedef typename Path::string_type string_type; + + // compiler generated copy-ctor, copy assignment, and destructor apply + + basic_directory_entry() {} + explicit basic_directory_entry( const path_type & p, + file_status st = file_status(), file_status symlink_st=file_status() ) + : m_path(p), m_status(st), m_symlink_status(symlink_st) + {} + + void assign( const path_type & p, + file_status st, file_status symlink_st ) + { m_path = p; m_status = st; m_symlink_status = symlink_st; } + + void replace_filename( const string_type & s, + file_status st, file_status symlink_st ) + { + m_path.remove_filename(); + m_path /= s; + m_status = st; + m_symlink_status = symlink_st; + } + + const Path & path() const { return m_path; } + file_status status() const; + file_status status( system::error_code & ec ) const; + file_status symlink_status() const; + file_status symlink_status( system::error_code & ec ) const; + + // conversion simplifies the most common use of basic_directory_entry + operator const path_type &() const { return m_path; } + +# ifndef BOOST_FILESYSTEM_NO_DEPRECATED + // deprecated functions preserve common use cases in legacy code + typename Path::string_type filename() const + { + return path().filename(); + } + typename Path::string_type string() const + { + return path().string(); + } +# endif + + private: + path_type m_path; + mutable file_status m_status; // stat()-like + mutable file_status m_symlink_status; // lstat()-like + // note: m_symlink_status is not used by Windows implementation + + }; // basic_directory_status + + typedef basic_directory_entry directory_entry; +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + typedef basic_directory_entry wdirectory_entry; +# endif + + // basic_directory_entry implementation --------------------------------// + + template + file_status + basic_directory_entry::status() const + { + if ( !status_known( m_status ) ) + { +# ifndef BOOST_WINDOWS_API + if ( status_known( m_symlink_status ) + && !is_symlink( m_symlink_status ) ) + { m_status = m_symlink_status; } + else { m_status = boost::filesystem::status( m_path ); } +# else + m_status = boost::filesystem::status( m_path ); +# endif + } + return m_status; + } + + template + file_status + basic_directory_entry::status( system::error_code & ec ) const + { + if ( !status_known( m_status ) ) + { +# ifndef BOOST_WINDOWS_API + if ( status_known( m_symlink_status ) + && !is_symlink( m_symlink_status ) ) + { ec = boost::system::error_code();; m_status = m_symlink_status; } + else { m_status = boost::filesystem::status( m_path, ec ); } +# else + m_status = boost::filesystem::status( m_path, ec ); +# endif + } + else ec = boost::system::error_code();; + return m_status; + } + + template + file_status + basic_directory_entry::symlink_status() const + { +# ifndef BOOST_WINDOWS_API + if ( !status_known( m_symlink_status ) ) + { m_symlink_status = boost::filesystem::symlink_status( m_path ); } + return m_symlink_status; +# else + return status(); +# endif + } + + template + file_status + basic_directory_entry::symlink_status( system::error_code & ec ) const + { +# ifndef BOOST_WINDOWS_API + if ( !status_known( m_symlink_status ) ) + { m_symlink_status = boost::filesystem::symlink_status( m_path, ec ); } + else ec = boost::system::error_code();; + return m_symlink_status; +# else + return status( ec ); +# endif + } + } // namespace filesystem +} // namespace boost + +#undef BOOST_FS_FUNC + + +#include // pops abi_prefix.hpp pragmas +#endif // BOOST_FILESYSTEM_OPERATIONS_HPP diff --git a/win32/include/boost/filesystem/path.hpp b/win32/include/boost/filesystem/path.hpp new file mode 100755 index 000000000..92dc131e7 --- /dev/null +++ b/win32/include/boost/filesystem/path.hpp @@ -0,0 +1,1486 @@ +// boost/filesystem/path.hpp -----------------------------------------------// + +// Copyright Beman Dawes 2002-2005 +// Copyright Vladimir Prus 2002 + +// 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) + +// See library home page at http://www.boost.org/libs/filesystem + +// basic_path's stem(), extension(), and replace_extension() are based on +// basename(), extension(), and change_extension() from the original +// filesystem/convenience.hpp header by Vladimir Prus. + +//----------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_PATH_HPP +#define BOOST_FILESYSTEM_PATH_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include +#include // for lexicographical_compare +#include // needed by basic_path inserter and extractor +#include +#include + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY +# include +# endif + +#include // must be the last #include + +//----------------------------------------------------------------------------// + +namespace boost +{ + namespace BOOST_FILESYSTEM_NAMESPACE + { + template class basic_path; + + struct path_traits; + typedef basic_path< std::string, path_traits > path; + + struct path_traits + { + typedef std::string internal_string_type; + typedef std::string external_string_type; + static external_string_type to_external( const path &, + const internal_string_type & src ) { return src; } + static internal_string_type to_internal( + const external_string_type & src ) { return src; } + }; + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + + struct BOOST_FILESYSTEM_DECL wpath_traits; + + typedef basic_path< std::wstring, wpath_traits > wpath; + + struct BOOST_FILESYSTEM_DECL wpath_traits + { + typedef std::wstring internal_string_type; +# ifdef BOOST_WINDOWS_API + typedef std::wstring external_string_type; + static external_string_type to_external( const wpath &, + const internal_string_type & src ) { return src; } + static internal_string_type to_internal( + const external_string_type & src ) { return src; } +# else + typedef std::string external_string_type; + static external_string_type to_external( const wpath & ph, + const internal_string_type & src ); + static internal_string_type to_internal( + const external_string_type & src ); +# endif + static void imbue( const std::locale & loc ); + static bool imbue( const std::locale & loc, const std::nothrow_t & ); + }; + +# endif // ifndef BOOST_FILESYSTEM_NARROW_ONLY + + // path traits ---------------------------------------------------------// + + template struct is_basic_path + { BOOST_STATIC_CONSTANT( bool, value = false ); }; + template<> struct is_basic_path + { BOOST_STATIC_CONSTANT( bool, value = true ); }; +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + template<> struct is_basic_path + { BOOST_STATIC_CONSTANT( bool, value = true ); }; +# endif + + // these only have to be specialized if Path::string_type::value_type + // is not convertible from char + template struct slash + { BOOST_STATIC_CONSTANT( char, value = '/' ); }; + + template struct dot + { BOOST_STATIC_CONSTANT( char, value = '.' ); }; + + template struct colon + { BOOST_STATIC_CONSTANT( char, value = ':' ); }; + +# ifdef BOOST_WINDOWS_PATH + template struct path_alt_separator + { BOOST_STATIC_CONSTANT( char, value = '\\' ); }; +# endif + + // workaround for VC++ 7.0 and earlier issues with nested classes + namespace detail + { + template + class iterator_helper + { + public: + typedef typename Path::iterator iterator; + static void do_increment( iterator & ph ); + static void do_decrement( iterator & ph ); + }; + } + + // basic_path ----------------------------------------------------------// + + template + class basic_path + { + // invariant: m_path valid according to the portable generic path grammar + + // validate template arguments +// TODO: get these working +// BOOST_STATIC_ASSERT( ::boost::is_same::value ); +// BOOST_STATIC_ASSERT( ::boost::is_same::value || ::boost::is_same::value ); + + public: + // compiler generates copy constructor and copy assignment + + typedef basic_path path_type; + typedef String string_type; + typedef typename String::value_type value_type; + typedef Traits traits_type; + typedef typename Traits::external_string_type external_string_type; + + // constructors/destructor + basic_path() {} + basic_path( const string_type & s ) { operator/=( s ); } + basic_path( const value_type * s ) { operator/=( s ); } +# ifndef BOOST_NO_MEMBER_TEMPLATES + template + basic_path( InputIterator first, InputIterator last ) + { append( first, last ); } +# endif + ~basic_path() {} + + // assignments + basic_path & operator=( const string_type & s ) + { +# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, >= 310) + m_path.clear(); +# else + m_path.erase( m_path.begin(), m_path.end() ); +# endif + operator/=( s ); + return *this; + } + basic_path & operator=( const value_type * s ) + { +# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, >= 310) + m_path.clear(); +# else + m_path.erase( m_path.begin(), m_path.end() ); +# endif + operator/=( s ); + return *this; + } +# ifndef BOOST_NO_MEMBER_TEMPLATES + template + basic_path & assign( InputIterator first, InputIterator last ) + { m_path.clear(); append( first, last ); return *this; } +# endif + + // modifiers + basic_path & operator/=( const basic_path & rhs ) { return operator /=( rhs.string().c_str() ); } + basic_path & operator/=( const string_type & rhs ) { return operator /=( rhs.c_str() ); } + basic_path & operator/=( const value_type * s ); +# ifndef BOOST_NO_MEMBER_TEMPLATES + template + basic_path & append( InputIterator first, InputIterator last ); +# endif + + void swap( basic_path & rhs ) + { + m_path.swap( rhs.m_path ); +# ifdef BOOST_CYGWIN_PATH + std::swap( m_cygwin_root, rhs.m_cygwin_root ); +# endif + } + + basic_path & remove_filename(); + basic_path & replace_extension( const string_type & new_extension = "" ); + +# ifndef BOOST_FILESYSTEM_NO_DEPRECATED + basic_path & remove_leaf() { return remove_filename(); } +# endif + + // observers + const string_type & string() const { return m_path; } + const string_type file_string() const; + const string_type directory_string() const { return file_string(); } + + const external_string_type external_file_string() const { return Traits::to_external( *this, file_string() ); } + const external_string_type external_directory_string() const { return Traits::to_external( *this, directory_string() ); } + + basic_path root_path() const; + string_type root_name() const; + string_type root_directory() const; + basic_path relative_path() const; + basic_path parent_path() const; + string_type filename() const; + string_type stem() const; + string_type extension() const; + +# ifndef BOOST_FILESYSTEM_NO_DEPRECATED + string_type leaf() const { return filename(); } + basic_path branch_path() const { return parent_path(); } +# endif + + bool empty() const { return m_path.empty(); } // name consistent with std containers + bool is_complete() const; + bool has_root_path() const; + bool has_root_name() const; + bool has_root_directory() const; + bool has_relative_path() const { return !relative_path().empty(); } + bool has_filename() const { return !m_path.empty(); } + bool has_parent_path() const { return !parent_path().empty(); } + + // iterators + class iterator : public boost::iterator_facade< + iterator, + string_type const, + boost::bidirectional_traversal_tag > + { + private: + friend class boost::iterator_core_access; + friend class boost::BOOST_FILESYSTEM_NAMESPACE::basic_path; + + const string_type & dereference() const + { return m_name; } + bool equal( const iterator & rhs ) const + { return m_path_ptr == rhs.m_path_ptr && m_pos == rhs.m_pos; } + + friend class boost::BOOST_FILESYSTEM_NAMESPACE::detail::iterator_helper; + + void increment() + { + boost::BOOST_FILESYSTEM_NAMESPACE::detail::iterator_helper::do_increment( + *this ); + } + void decrement() + { + boost::BOOST_FILESYSTEM_NAMESPACE::detail::iterator_helper::do_decrement( + *this ); + } + + string_type m_name; // current element + const basic_path * m_path_ptr; // path being iterated over + typename string_type::size_type m_pos; // position of name in + // path_ptr->string(). The + // end() iterator is indicated by + // pos == path_ptr->m_path.size() + }; // iterator + + typedef iterator const_iterator; + + iterator begin() const; + iterator end() const; + + private: + // Note: This is an implementation for POSIX and Windows, where there + // are only minor differences between generic and native path grammars. + // Private members might be quite different in other implementations, + // particularly where there were wide differences between portable and + // native path formats, or between file_string() and + // directory_string() formats, or simply that the implementation + // was willing expend additional memory to achieve greater speed for + // some operations at the expense of other operations. + + string_type m_path; // invariant: portable path grammar + // on Windows, backslashes converted to slashes + +# ifdef BOOST_CYGWIN_PATH + bool m_cygwin_root; // if present, m_path[0] was slash. note: initialization + // done by append +# endif + + void m_append_separator_if_needed(); + void m_append( value_type value ); // converts Windows alt_separator + + // Was qualified; como433beta8 reports: + // warning #427-D: qualified name is not allowed in member declaration + friend class iterator; + friend class boost::BOOST_FILESYSTEM_NAMESPACE::detail::iterator_helper; + + // Deprecated features ease transition for existing code. Don't use these + // in new code. +# ifndef BOOST_FILESYSTEM_NO_DEPRECATED + public: + typedef bool (*name_check)( const std::string & name ); + basic_path( const string_type & str, name_check ) { operator/=( str ); } + basic_path( const typename string_type::value_type * s, name_check ) + { operator/=( s );} + string_type native_file_string() const { return file_string(); } + string_type native_directory_string() const { return directory_string(); } + static bool default_name_check_writable() { return false; } + static void default_name_check( name_check ) {} + static name_check default_name_check() { return 0; } + basic_path & canonize(); + basic_path & normalize(); +# endif + }; + + // basic_path non-member functions ---------------------------------------// + + template< class String, class Traits > + inline void swap( basic_path & lhs, + basic_path & rhs ) { lhs.swap( rhs ); } + + template< class String, class Traits > + bool operator<( const basic_path & lhs, const basic_path & rhs ) + { + return std::lexicographical_compare( + lhs.begin(), lhs.end(), rhs.begin(), rhs.end() ); + } + + template< class String, class Traits > + bool operator<( const typename basic_path::string_type::value_type * lhs, + const basic_path & rhs ) + { + basic_path tmp( lhs ); + return std::lexicographical_compare( + tmp.begin(), tmp.end(), rhs.begin(), rhs.end() ); + } + + template< class String, class Traits > + bool operator<( const typename basic_path::string_type & lhs, + const basic_path & rhs ) + { + basic_path tmp( lhs ); + return std::lexicographical_compare( + tmp.begin(), tmp.end(), rhs.begin(), rhs.end() ); + } + + template< class String, class Traits > + bool operator<( const basic_path & lhs, + const typename basic_path::string_type::value_type * rhs ) + { + basic_path tmp( rhs ); + return std::lexicographical_compare( + lhs.begin(), lhs.end(), tmp.begin(), tmp.end() ); + } + + template< class String, class Traits > + bool operator<( const basic_path & lhs, + const typename basic_path::string_type & rhs ) + { + basic_path tmp( rhs ); + return std::lexicographical_compare( + lhs.begin(), lhs.end(), tmp.begin(), tmp.end() ); + } + + template< class String, class Traits > + inline bool operator==( const basic_path & lhs, const basic_path & rhs ) + { + return !(lhs < rhs) && !(rhs < lhs); + } + + template< class String, class Traits > + inline bool operator==( const typename basic_path::string_type::value_type * lhs, + const basic_path & rhs ) + { + basic_path tmp( lhs ); + return !(tmp < rhs) && !(rhs < tmp); + } + + template< class String, class Traits > + inline bool operator==( const typename basic_path::string_type & lhs, + const basic_path & rhs ) + { + basic_path tmp( lhs ); + return !(tmp < rhs) && !(rhs < tmp); + } + + template< class String, class Traits > + inline bool operator==( const basic_path & lhs, + const typename basic_path::string_type::value_type * rhs ) + { + basic_path tmp( rhs ); + return !(lhs < tmp) && !(tmp < lhs); + } + + template< class String, class Traits > + inline bool operator==( const basic_path & lhs, + const typename basic_path::string_type & rhs ) + { + basic_path tmp( rhs ); + return !(lhs < tmp) && !(tmp < lhs); + } + + template< class String, class Traits > + inline bool operator!=( const basic_path & lhs, const basic_path & rhs ) { return !(lhs == rhs); } + + template< class String, class Traits > + inline bool operator!=( const typename basic_path::string_type::value_type * lhs, + const basic_path & rhs ) { return !(basic_path(lhs) == rhs); } + + template< class String, class Traits > + inline bool operator!=( const typename basic_path::string_type & lhs, + const basic_path & rhs ) { return !(basic_path(lhs) == rhs); } + + template< class String, class Traits > + inline bool operator!=( const basic_path & lhs, + const typename basic_path::string_type::value_type * rhs ) + { return !(lhs == basic_path(rhs)); } + + template< class String, class Traits > + inline bool operator!=( const basic_path & lhs, + const typename basic_path::string_type & rhs ) + { return !(lhs == basic_path(rhs)); } + + template< class String, class Traits > + inline bool operator>( const basic_path & lhs, const basic_path & rhs ) { return rhs < lhs; } + + template< class String, class Traits > + inline bool operator>( const typename basic_path::string_type::value_type * lhs, + const basic_path & rhs ) { return rhs < basic_path(lhs); } + + template< class String, class Traits > + inline bool operator>( const typename basic_path::string_type & lhs, + const basic_path & rhs ) { return rhs < basic_path(lhs); } + + template< class String, class Traits > + inline bool operator>( const basic_path & lhs, + const typename basic_path::string_type::value_type * rhs ) + { return basic_path(rhs) < lhs; } + + template< class String, class Traits > + inline bool operator>( const basic_path & lhs, + const typename basic_path::string_type & rhs ) + { return basic_path(rhs) < lhs; } + + template< class String, class Traits > + inline bool operator<=( const basic_path & lhs, const basic_path & rhs ) { return !(rhs < lhs); } + + template< class String, class Traits > + inline bool operator<=( const typename basic_path::string_type::value_type * lhs, + const basic_path & rhs ) { return !(rhs < basic_path(lhs)); } + + template< class String, class Traits > + inline bool operator<=( const typename basic_path::string_type & lhs, + const basic_path & rhs ) { return !(rhs < basic_path(lhs)); } + + template< class String, class Traits > + inline bool operator<=( const basic_path & lhs, + const typename basic_path::string_type::value_type * rhs ) + { return !(basic_path(rhs) < lhs); } + + template< class String, class Traits > + inline bool operator<=( const basic_path & lhs, + const typename basic_path::string_type & rhs ) + { return !(basic_path(rhs) < lhs); } + + template< class String, class Traits > + inline bool operator>=( const basic_path & lhs, const basic_path & rhs ) { return !(lhs < rhs); } + + template< class String, class Traits > + inline bool operator>=( const typename basic_path::string_type::value_type * lhs, + const basic_path & rhs ) { return !(lhs < basic_path(rhs)); } + + template< class String, class Traits > + inline bool operator>=( const typename basic_path::string_type & lhs, + const basic_path & rhs ) { return !(lhs < basic_path(rhs)); } + + template< class String, class Traits > + inline bool operator>=( const basic_path & lhs, + const typename basic_path::string_type::value_type * rhs ) + { return !(basic_path(lhs) < rhs); } + + template< class String, class Traits > + inline bool operator>=( const basic_path & lhs, + const typename basic_path::string_type & rhs ) + { return !(basic_path(lhs) < rhs); } + + // operator / + + template< class String, class Traits > + inline basic_path operator/( + const basic_path & lhs, + const basic_path & rhs ) + { return basic_path( lhs ) /= rhs; } + + template< class String, class Traits > + inline basic_path operator/( + const basic_path & lhs, + const typename String::value_type * rhs ) + { return basic_path( lhs ) /= + basic_path( rhs ); } + + template< class String, class Traits > + inline basic_path operator/( + const basic_path & lhs, const String & rhs ) + { return basic_path( lhs ) /= + basic_path( rhs ); } + + template< class String, class Traits > + inline basic_path operator/( + const typename String::value_type * lhs, + const basic_path & rhs ) + { return basic_path( lhs ) /= rhs; } + + template< class String, class Traits > + inline basic_path operator/( + const String & lhs, const basic_path & rhs ) + { return basic_path( lhs ) /= rhs; } + + // inserters and extractors --------------------------------------------// + +// bypass VC++ 7.0 and earlier, and broken Borland compilers +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + template< class Path > + std::basic_ostream< typename Path::string_type::value_type, + typename Path::string_type::traits_type > & + operator<< + ( std::basic_ostream< typename Path::string_type::value_type, + typename Path::string_type::traits_type >& os, const Path & ph ) + { + os << ph.string(); + return os; + } + + template< class Path > + std::basic_istream< typename Path::string_type::value_type, + typename Path::string_type::traits_type > & + operator>> + ( std::basic_istream< typename Path::string_type::value_type, + typename Path::string_type::traits_type >& is, Path & ph ) + { + typename Path::string_type str; + is >> str; + ph = str; + return is; + } +# elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + template< class String, class Traits > + std::basic_ostream< BOOST_DEDUCED_TYPENAME String::value_type, + BOOST_DEDUCED_TYPENAME String::traits_type > & + operator<< + ( std::basic_ostream< BOOST_DEDUCED_TYPENAME String::value_type, + BOOST_DEDUCED_TYPENAME String::traits_type >& os, + const basic_path< String, Traits > & ph ) + { + os << ph.string(); + return os; + } + + template< class String, class Traits > + std::basic_istream< BOOST_DEDUCED_TYPENAME String::value_type, + BOOST_DEDUCED_TYPENAME String::traits_type > & + operator>> + ( std::basic_istream< BOOST_DEDUCED_TYPENAME String::value_type, + BOOST_DEDUCED_TYPENAME String::traits_type> & is, + basic_path< String, Traits > & ph ) + { + String str; + is >> str; + ph = str; + return is; + } +# endif + + // basic_filesystem_error helpers --------------------------------------// + + // Originally choice of implementation was done via specialization of + // basic_filesystem_error::what(). Several compilers (GCC, aCC, etc.) + // couldn't handle that, so the choice is now accomplished by overloading. + + namespace detail + { + // BOOST_FILESYSTEM_DECL version works for VC++ but not GCC. Go figure! + inline + const char * what( const char * sys_err_what, + const path & path1, const path & path2, std::string & target ) + { + try + { + if ( target.empty() ) + { + target = sys_err_what; + if ( !path1.empty() ) + { + target += ": \""; + target += path1.file_string(); + target += "\""; + } + if ( !path2.empty() ) + { + target += ", \""; + target += path2.file_string(); + target += "\""; + } + } + return target.c_str(); + } + catch (...) + { + return sys_err_what; + } + } + + template + const char * what( const char * sys_err_what, + const Path & /*path1*/, const Path & /*path2*/, std::string & /*target*/ ) + { + return sys_err_what; + } + } + + // basic_filesystem_error ----------------------------------------------// + + template + class basic_filesystem_error : public system::system_error + { + // see http://www.boost.org/more/error_handling.html for design rationale + public: + // compiler generates copy constructor and copy assignment + + typedef Path path_type; + + basic_filesystem_error( const std::string & what_arg, + system::error_code ec ); + + basic_filesystem_error( const std::string & what_arg, + const path_type & path1_arg, system::error_code ec ); + + basic_filesystem_error( const std::string & what_arg, const path_type & path1_arg, + const path_type & path2_arg, system::error_code ec ); + + ~basic_filesystem_error() throw() {} + + const path_type & path1() const + { + static const path_type empty_path; + return m_imp_ptr.get() ? m_imp_ptr->m_path1 : empty_path ; + } + const path_type & path2() const + { + static const path_type empty_path; + return m_imp_ptr.get() ? m_imp_ptr->m_path2 : empty_path ; + } + + const char * what() const throw() + { + if ( !m_imp_ptr.get() ) + return system::system_error::what(); + return detail::what( system::system_error::what(), m_imp_ptr->m_path1, + m_imp_ptr->m_path2, m_imp_ptr->m_what ); + } + + private: + struct m_imp + { + path_type m_path1; // may be empty() + path_type m_path2; // may be empty() + std::string m_what; // not built until needed + }; + boost::shared_ptr m_imp_ptr; + }; + + typedef basic_filesystem_error filesystem_error; + +# ifndef BOOST_FILESYSTEM_NARROW_ONLY + typedef basic_filesystem_error wfilesystem_error; +# endif + + // path::name_checks -----------------------------------------------------// + + BOOST_FILESYSTEM_DECL bool portable_posix_name( const std::string & name ); + BOOST_FILESYSTEM_DECL bool windows_name( const std::string & name ); + BOOST_FILESYSTEM_DECL bool portable_name( const std::string & name ); + BOOST_FILESYSTEM_DECL bool portable_directory_name( const std::string & name ); + BOOST_FILESYSTEM_DECL bool portable_file_name( const std::string & name ); + BOOST_FILESYSTEM_DECL bool native( const std::string & name ); + inline bool no_check( const std::string & ) + { return true; } + +// implementation -----------------------------------------------------------// + + namespace detail + { + + // is_separator helper ------------------------------------------------// + + template + inline bool is_separator( typename Path::string_type::value_type c ) + { + return c == slash::value +# ifdef BOOST_WINDOWS_PATH + || c == path_alt_separator::value +# endif + ; + } + + // filename_pos helper ----------------------------------------------------// + + template + typename String::size_type filename_pos( + const String & str, // precondition: portable generic path grammar + typename String::size_type end_pos ) // end_pos is past-the-end position + // return 0 if str itself is filename (or empty) + { + typedef typename + boost::BOOST_FILESYSTEM_NAMESPACE::basic_path path_type; + + // case: "//" + if ( end_pos == 2 + && str[0] == slash::value + && str[1] == slash::value ) return 0; + + // case: ends in "/" + if ( end_pos && str[end_pos-1] == slash::value ) + return end_pos-1; + + // set pos to start of last element + typename String::size_type pos( + str.find_last_of( slash::value, end_pos-1 ) ); +# ifdef BOOST_WINDOWS_PATH + if ( pos == String::npos ) + pos = str.find_last_of( path_alt_separator::value, end_pos-1 ); + if ( pos == String::npos ) + pos = str.find_last_of( colon::value, end_pos-2 ); +# endif + + return ( pos == String::npos // path itself must be a filename (or empty) + || (pos == 1 && str[0] == slash::value) ) // or net + ? 0 // so filename is entire string + : pos + 1; // or starts after delimiter + } + + // first_element helper -----------------------------------------------// + // sets pos and len of first element, excluding extra separators + // if src.empty(), sets pos,len, to 0,0. + + template + void first_element( + const String & src, // precondition: portable generic path grammar + typename String::size_type & element_pos, + typename String::size_type & element_size, +# if !BOOST_WORKAROUND( BOOST_MSVC, <= 1310 ) // VC++ 7.1 + typename String::size_type size = String::npos +# else + typename String::size_type size = -1 +# endif + ) + { + if ( size == String::npos ) size = src.size(); + element_pos = 0; + element_size = 0; + if ( src.empty() ) return; + + typedef typename boost::BOOST_FILESYSTEM_NAMESPACE::basic_path path_type; + + typename String::size_type cur(0); + + // deal with // [network] + if ( size >= 2 && src[0] == slash::value + && src[1] == slash::value + && (size == 2 + || src[2] != slash::value) ) + { + cur += 2; + element_size += 2; + } + + // leading (not non-network) separator + else if ( src[0] == slash::value ) + { + ++element_size; + // bypass extra leading separators + while ( cur+1 < size + && src[cur+1] == slash::value ) + { + ++cur; + ++element_pos; + } + return; + } + + // at this point, we have either a plain name, a network name, + // or (on Windows only) a device name + + // find the end + while ( cur < size +# ifdef BOOST_WINDOWS_PATH + && src[cur] != colon::value +# endif + && src[cur] != slash::value ) + { + ++cur; + ++element_size; + } + +# ifdef BOOST_WINDOWS_PATH + if ( cur == size ) return; + // include device delimiter + if ( src[cur] == colon::value ) + { ++element_size; } +# endif + + return; + } + + // root_directory_start helper ----------------------------------------// + + template + typename String::size_type root_directory_start( + const String & s, // precondition: portable generic path grammar + typename String::size_type size ) + // return npos if no root_directory found + { + typedef typename boost::BOOST_FILESYSTEM_NAMESPACE::basic_path path_type; + +# ifdef BOOST_WINDOWS_PATH + // case "c:/" + if ( size > 2 + && s[1] == colon::value + && s[2] == slash::value ) return 2; +# endif + + // case "//" + if ( size == 2 + && s[0] == slash::value + && s[1] == slash::value ) return String::npos; + + // case "//net {/}" + if ( size > 3 + && s[0] == slash::value + && s[1] == slash::value + && s[2] != slash::value ) + { + typename String::size_type pos( + s.find( slash::value, 2 ) ); + return pos < size ? pos : String::npos; + } + + // case "/" + if ( size > 0 && s[0] == slash::value ) return 0; + + return String::npos; + } + + // is_non_root_slash helper -------------------------------------------// + + template + bool is_non_root_slash( const String & str, + typename String::size_type pos ) // pos is position of the slash + { + typedef typename + boost::BOOST_FILESYSTEM_NAMESPACE::basic_path + path_type; + + assert( !str.empty() && str[pos] == slash::value + && "precondition violation" ); + + // subsequent logic expects pos to be for leftmost slash of a set + while ( pos > 0 && str[pos-1] == slash::value ) + --pos; + + return pos != 0 + && (pos <= 2 || str[1] != slash::value + || str.find( slash::value, 2 ) != pos) +# ifdef BOOST_WINDOWS_PATH + && (pos !=2 || str[1] != colon::value) +# endif + ; + } + } // namespace detail + + // decomposition functions ----------------------------------------------// + + template + String basic_path::filename() const + { + typename String::size_type end_pos( + detail::filename_pos( m_path, m_path.size() ) ); + return (m_path.size() + && end_pos + && m_path[end_pos] == slash::value + && detail::is_non_root_slash< String, Traits >(m_path, end_pos)) + ? String( 1, dot::value ) + : m_path.substr( end_pos ); + } + + template + String basic_path::stem() const + { + string_type name = filename(); + typename string_type::size_type n = name.rfind('.'); + return name.substr(0, n); + } + + template + String basic_path::extension() const + { + string_type name = filename(); + typename string_type::size_type n = name.rfind('.'); + if (n != string_type::npos) + return name.substr(n); + else + return string_type(); + } + + template + basic_path basic_path::parent_path() const + { + typename String::size_type end_pos( + detail::filename_pos( m_path, m_path.size() ) ); + + bool filename_was_separator( m_path.size() + && m_path[end_pos] == slash::value ); + + // skip separators unless root directory + typename string_type::size_type root_dir_pos( detail::root_directory_start + ( m_path, end_pos ) ); + for ( ; + end_pos > 0 + && (end_pos-1) != root_dir_pos + && m_path[end_pos-1] == slash::value + ; + --end_pos ) {} + + return (end_pos == 1 && root_dir_pos == 0 && filename_was_separator) + ? path_type() + : path_type( m_path.substr( 0, end_pos ) ); + } + + template + basic_path basic_path::relative_path() const + { + iterator itr( begin() ); + for ( ; itr.m_pos != m_path.size() + && (itr.m_name[0] == slash::value +# ifdef BOOST_WINDOWS_PATH + || itr.m_name[itr.m_name.size()-1] + == colon::value +# endif + ); ++itr ) {} + + return basic_path( m_path.substr( itr.m_pos ) ); + } + + template + String basic_path::root_name() const + { + iterator itr( begin() ); + + return ( itr.m_pos != m_path.size() + && ( + ( itr.m_name.size() > 1 + && itr.m_name[0] == slash::value + && itr.m_name[1] == slash::value + ) +# ifdef BOOST_WINDOWS_PATH + || itr.m_name[itr.m_name.size()-1] + == colon::value +# endif + ) ) + ? *itr + : String(); + } + + template + String basic_path::root_directory() const + { + typename string_type::size_type start( + detail::root_directory_start( m_path, m_path.size() ) ); + + return start == string_type::npos + ? string_type() + : m_path.substr( start, 1 ); + } + + template + basic_path basic_path::root_path() const + { + // even on POSIX, root_name() is non-empty() on network paths + return basic_path( root_name() ) /= root_directory(); + } + + // path query functions -------------------------------------------------// + + template + inline bool basic_path::is_complete() const + { +# ifdef BOOST_WINDOWS_PATH + return has_root_name() && has_root_directory(); +# else + return has_root_directory(); +# endif + } + + template + inline bool basic_path::has_root_path() const + { + return !root_path().empty(); + } + + template + inline bool basic_path::has_root_name() const + { + return !root_name().empty(); + } + + template + inline bool basic_path::has_root_directory() const + { + return !root_directory().empty(); + } + + // append ---------------------------------------------------------------// + + template + void basic_path::m_append_separator_if_needed() + // requires: !empty() + { + if ( +# ifdef BOOST_WINDOWS_PATH + *(m_path.end()-1) != colon::value && +# endif + *(m_path.end()-1) != slash::value ) + { + m_path += slash::value; + } + } + + template + void basic_path::m_append( value_type value ) + { +# ifdef BOOST_CYGWIN_PATH + if ( m_path.empty() ) m_cygwin_root = (value == slash::value); +# endif + +# ifdef BOOST_WINDOWS_PATH + // for BOOST_WINDOWS_PATH, convert alt_separator ('\') to separator ('/') + m_path += ( value == path_alt_separator::value + ? slash::value + : value ); +# else + m_path += value; +# endif + } + + // except that it wouldn't work for BOOST_NO_MEMBER_TEMPLATES compilers, + // the append() member template could replace this code. + template + basic_path & basic_path::operator /= + ( const value_type * next_p ) + { + // ignore escape sequence on POSIX or Windows + if ( *next_p == slash::value + && *(next_p+1) == slash::value + && *(next_p+2) == colon::value ) next_p += 3; + + // append slash::value if needed + if ( !empty() && *next_p != 0 + && !detail::is_separator( *next_p ) ) + { m_append_separator_if_needed(); } + + for ( ; *next_p != 0; ++next_p ) m_append( *next_p ); + return *this; + } + +# ifndef BOOST_NO_MEMBER_TEMPLATES + template template + basic_path & basic_path::append( + InputIterator first, InputIterator last ) + { + // append slash::value if needed + if ( !empty() && first != last + && !detail::is_separator( *first ) ) + { m_append_separator_if_needed(); } + + // song-and-dance to avoid violating InputIterator requirements + // (which prohibit lookahead) in detecting a possible escape sequence + // (escape sequences are simply ignored on POSIX and Windows) + bool was_escape_sequence(true); + std::size_t append_count(0); + typename String::size_type initial_pos( m_path.size() ); + + for ( ; first != last && *first; ++first ) + { + if ( append_count == 0 && *first != slash::value ) + was_escape_sequence = false; + if ( append_count == 1 && *first != slash::value ) + was_escape_sequence = false; + if ( append_count == 2 && *first != colon::value ) + was_escape_sequence = false; + m_append( *first ); + ++append_count; + } + + // erase escape sequence if any + if ( was_escape_sequence && append_count >= 3 ) + m_path.erase( initial_pos, 3 ); + + return *this; + } +# endif + +# ifndef BOOST_FILESYSTEM_NO_DEPRECATED + + // canonize ------------------------------------------------------------// + + template + basic_path & basic_path::canonize() + { + static const typename string_type::value_type dot_str[] + = { dot::value, 0 }; + + if ( m_path.empty() ) return *this; + + path_type temp; + + for ( iterator itr( begin() ); itr != end(); ++itr ) + { + temp /= *itr; + }; + + if ( temp.empty() ) temp /= dot_str; + m_path = temp.m_path; + return *this; + } + + // normalize ------------------------------------------------------------// + + template + basic_path & basic_path::normalize() + { + static const typename string_type::value_type dot_str[] + = { dot::value, 0 }; + + if ( m_path.empty() ) return *this; + + path_type temp; + iterator start( begin() ); + iterator last( end() ); + iterator stop( last-- ); + for ( iterator itr( start ); itr != stop; ++itr ) + { + // ignore "." except at start and last + if ( itr->size() == 1 + && (*itr)[0] == dot::value + && itr != start + && itr != last ) continue; + + // ignore a name and following ".." + if ( !temp.empty() + && itr->size() == 2 + && (*itr)[0] == dot::value + && (*itr)[1] == dot::value ) // dot dot + { + string_type lf( temp.filename() ); + if ( lf.size() > 0 + && (lf.size() != 1 + || (lf[0] != dot::value + && lf[0] != slash::value)) + && (lf.size() != 2 + || (lf[0] != dot::value + && lf[1] != dot::value +# ifdef BOOST_WINDOWS_PATH + && lf[1] != colon::value +# endif + ) + ) + ) + { + temp.remove_filename(); + // if not root directory, must also remove "/" if any + if ( temp.m_path.size() > 0 + && temp.m_path[temp.m_path.size()-1] + == slash::value ) + { + typename string_type::size_type rds( + detail::root_directory_start( temp.m_path, + temp.m_path.size() ) ); + if ( rds == string_type::npos + || rds != temp.m_path.size()-1 ) + { temp.m_path.erase( temp.m_path.size()-1 ); } + } + + iterator next( itr ); + if ( temp.empty() && ++next != stop + && next == last && *last == dot_str ) temp /= dot_str; + continue; + } + } + + temp /= *itr; + }; + + if ( temp.empty() ) temp /= dot_str; + m_path = temp.m_path; + return *this; + } + +# endif + + // modifiers ------------------------------------------------------------// + + template + basic_path & basic_path::remove_filename() + { + m_path.erase( + detail::filename_pos( m_path, m_path.size() ) ); + return *this; + } + + template + basic_path & + basic_path::replace_extension( const string_type & new_ext ) + { + // erase existing extension if any + string_type old_ext = extension(); + if ( !old_ext.empty() ) + m_path.erase( m_path.size() - old_ext.size() ); + + if ( !new_ext.empty() && new_ext[0] != dot::value ) + m_path += dot::value; + + m_path += new_ext; + + return *this; + } + + + // path conversion functions --------------------------------------------// + + template + const String + basic_path::file_string() const + { +# ifdef BOOST_WINDOWS_PATH + // for Windows, use the alternate separator, and bypass extra + // root separators + + typename string_type::size_type root_dir_start( + detail::root_directory_start( m_path, m_path.size() ) ); + bool in_root( root_dir_start != string_type::npos ); + String s; + for ( typename string_type::size_type pos( 0 ); + pos != m_path.size(); ++pos ) + { + // special case // [net] + if ( pos == 0 && m_path.size() > 1 + && m_path[0] == slash::value + && m_path[1] == slash::value + && ( m_path.size() == 2 + || !detail::is_separator( m_path[2] ) + ) ) + { + ++pos; + s += path_alt_separator::value; + s += path_alt_separator::value; + continue; + } + + // bypass extra root separators + if ( in_root ) + { + if ( s.size() > 0 + && s[s.size()-1] == path_alt_separator::value + && m_path[pos] == slash::value + ) continue; + } + + if ( m_path[pos] == slash::value ) + s += path_alt_separator::value; + else + s += m_path[pos]; + + if ( pos > root_dir_start + && m_path[pos] == slash::value ) + { in_root = false; } + } +# ifdef BOOST_CYGWIN_PATH + if ( m_cygwin_root ) s[0] = slash::value; +# endif + return s; +# else + return m_path; +# endif + } + + // iterator functions ---------------------------------------------------// + + template + typename basic_path::iterator basic_path::begin() const + { + iterator itr; + itr.m_path_ptr = this; + typename string_type::size_type element_size; + detail::first_element( m_path, itr.m_pos, element_size ); + itr.m_name = m_path.substr( itr.m_pos, element_size ); + return itr; + } + + template + typename basic_path::iterator basic_path::end() const + { + iterator itr; + itr.m_path_ptr = this; + itr.m_pos = m_path.size(); + return itr; + } + + namespace detail + { + // do_increment ------------------------------------------------------// + + template + void iterator_helper::do_increment( iterator & itr ) + { + typedef typename Path::string_type string_type; + typedef typename Path::traits_type traits_type; + + assert( itr.m_pos < itr.m_path_ptr->m_path.size() && "basic_path::iterator increment past end()" ); + + bool was_net( itr.m_name.size() > 2 + && itr.m_name[0] == slash::value + && itr.m_name[1] == slash::value + && itr.m_name[2] != slash::value ); + + // increment to position past current element + itr.m_pos += itr.m_name.size(); + + // if end reached, create end iterator + if ( itr.m_pos == itr.m_path_ptr->m_path.size() ) + { + itr.m_name.erase( itr.m_name.begin(), itr.m_name.end() ); // VC++ 6.0 lib didn't supply clear() + return; + } + + // process separator (Windows drive spec is only case not a separator) + if ( itr.m_path_ptr->m_path[itr.m_pos] == slash::value ) + { + // detect root directory + if ( was_net + # ifdef BOOST_WINDOWS_PATH + // case "c:/" + || itr.m_name[itr.m_name.size()-1] == colon::value + # endif + ) + { + itr.m_name = slash::value; + return; + } + + // bypass separators + while ( itr.m_pos != itr.m_path_ptr->m_path.size() + && itr.m_path_ptr->m_path[itr.m_pos] == slash::value ) + { ++itr.m_pos; } + + // detect trailing separator, and treat it as ".", per POSIX spec + if ( itr.m_pos == itr.m_path_ptr->m_path.size() + && detail::is_non_root_slash< string_type, traits_type >( + itr.m_path_ptr->m_path, itr.m_pos-1 ) ) + { + --itr.m_pos; + itr.m_name = dot::value; + return; + } + } + + // get next element + typename string_type::size_type end_pos( + itr.m_path_ptr->m_path.find( slash::value, itr.m_pos ) ); + itr.m_name = itr.m_path_ptr->m_path.substr( itr.m_pos, end_pos - itr.m_pos ); + } + + // do_decrement ------------------------------------------------------// + + template + void iterator_helper::do_decrement( iterator & itr ) + { + assert( itr.m_pos && "basic_path::iterator decrement past begin()" ); + + typedef typename Path::string_type string_type; + typedef typename Path::traits_type traits_type; + + typename string_type::size_type end_pos( itr.m_pos ); + + typename string_type::size_type root_dir_pos( + detail::root_directory_start( + itr.m_path_ptr->m_path, end_pos ) ); + + // if at end and there was a trailing non-root '/', return "." + if ( itr.m_pos == itr.m_path_ptr->m_path.size() + && itr.m_path_ptr->m_path.size() > 1 + && itr.m_path_ptr->m_path[itr.m_pos-1] == slash::value + && detail::is_non_root_slash< string_type, traits_type >( + itr.m_path_ptr->m_path, itr.m_pos-1 ) + ) + { + --itr.m_pos; + itr.m_name = dot::value; + return; + } + + // skip separators unless root directory + for ( + ; + end_pos > 0 + && (end_pos-1) != root_dir_pos + && itr.m_path_ptr->m_path[end_pos-1] == slash::value + ; + --end_pos ) {} + + itr.m_pos = detail::filename_pos + ( itr.m_path_ptr->m_path, end_pos ); + itr.m_name = itr.m_path_ptr->m_path.substr( itr.m_pos, end_pos - itr.m_pos ); + } + } // namespace detail + + // basic_filesystem_error implementation --------------------------------// + + template + basic_filesystem_error::basic_filesystem_error( + const std::string & what_arg, system::error_code ec ) + : system::system_error(ec, what_arg) + { + try + { + m_imp_ptr.reset( new m_imp ); + } + catch (...) { m_imp_ptr.reset(); } + } + + template + basic_filesystem_error::basic_filesystem_error( + const std::string & what_arg, const path_type & path1_arg, + system::error_code ec ) + : system::system_error(ec, what_arg) + { + try + { + m_imp_ptr.reset( new m_imp ); + m_imp_ptr->m_path1 = path1_arg; + } + catch (...) { m_imp_ptr.reset(); } + } + + template + basic_filesystem_error::basic_filesystem_error( + const std::string & what_arg, const path_type & path1_arg, + const path_type & path2_arg, system::error_code ec ) + : system::system_error(ec, what_arg) + { + try + { + m_imp_ptr.reset( new m_imp ); + m_imp_ptr->m_path1 = path1_arg; + m_imp_ptr->m_path2 = path2_arg; + } + catch (...) { m_imp_ptr.reset(); } + } + + } // namespace BOOST_FILESYSTEM_NAMESPACE +} // namespace boost + +#include // pops abi_prefix.hpp pragmas + +#endif // BOOST_FILESYSTEM_PATH_HPP diff --git a/win32/include/boost/foreach.hpp b/win32/include/boost/foreach.hpp new file mode 100755 index 000000000..f773f3336 --- /dev/null +++ b/win32/include/boost/foreach.hpp @@ -0,0 +1,1087 @@ +/////////////////////////////////////////////////////////////////////////////// +// foreach.hpp header file +// +// Copyright 2004 Eric Niebler. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// See http://www.boost.org/libs/foreach for documentation +// +// Credits: +// Anson Tsao - for the initial inspiration and several good suggestions. +// Thorsten Ottosen - for Boost.Range, and for suggesting a way to detect +// const-qualified rvalues at compile time on VC7.1+ +// Russell Hind - For help porting to Borland +// Alisdair Meredith - For help porting to Borland +// Stefan Slapeta - For help porting to Intel +// David Jenkins - For help finding a Microsoft Code Analysis bug + +#ifndef BOOST_FOREACH + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include // for std::pair + +#include +#include + +// Some compilers let us detect even const-qualified rvalues at compile-time +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1310) && !defined(_PREFAST_) \ + || (BOOST_WORKAROUND(__GNUC__, >= 4) && !defined(BOOST_INTEL)) \ + || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ >= 4) && !defined(BOOST_INTEL)) +# define BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION +#else +// Some compilers allow temporaries to be bound to non-const references. +// These compilers make it impossible to for BOOST_FOREACH to detect +// temporaries and avoid reevaluation of the collection expression. +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) \ + || (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER)) \ + || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x570)) \ + || BOOST_WORKAROUND(__DECCXX_VER, <= 60590042) +# define BOOST_FOREACH_NO_RVALUE_DETECTION +# endif +// Some compilers do not correctly implement the lvalue/rvalue conversion +// rules of the ternary conditional operator. +# if defined(BOOST_FOREACH_NO_RVALUE_DETECTION) \ + || defined(BOOST_NO_SFINAE) \ + || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \ + || BOOST_WORKAROUND(BOOST_INTEL_WIN, <= 810) \ + || BOOST_WORKAROUND(__GNUC__, < 3) \ + || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ <= 2)) \ + || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ <= 3) && defined(__APPLE_CC__)) \ + || BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) \ + || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) +# define BOOST_FOREACH_NO_CONST_RVALUE_DETECTION +# else +# define BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION +# endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION +# include +# include +# include +# include +#endif + +// This must be at global scope, hence the uglified name +enum boost_foreach_argument_dependent_lookup_hack +{ + boost_foreach_argument_dependent_lookup_hack_value +}; + +namespace boost +{ + +// forward declarations for iterator_range +template +class iterator_range; + +// forward declarations for sub_range +template +class sub_range; + +namespace foreach +{ + /////////////////////////////////////////////////////////////////////////////// + // in_range + // + template + inline std::pair in_range(T begin, T end) + { + return std::make_pair(begin, end); + } + + /////////////////////////////////////////////////////////////////////////////// + // boost::foreach::tag + // + typedef boost_foreach_argument_dependent_lookup_hack tag; + + /////////////////////////////////////////////////////////////////////////////// + // boost::foreach::is_lightweight_proxy + // Specialize this for user-defined collection types if they are inexpensive to copy. + // This tells BOOST_FOREACH it can avoid the rvalue/lvalue detection stuff. + template + struct is_lightweight_proxy + : boost::mpl::false_ + { + }; + + /////////////////////////////////////////////////////////////////////////////// + // boost::foreach::is_noncopyable + // Specialize this for user-defined collection types if they cannot be copied. + // This also tells BOOST_FOREACH to avoid the rvalue/lvalue detection stuff. + template + struct is_noncopyable + #if !defined(BOOST_BROKEN_IS_BASE_AND_DERIVED) && !defined(BOOST_NO_IS_ABSTRACT) + : boost::mpl::or_< + boost::is_abstract + , boost::is_base_and_derived + > + #elif !defined(BOOST_BROKEN_IS_BASE_AND_DERIVED) + : boost::is_base_and_derived + #elif !defined(BOOST_NO_IS_ABSTRACT) + : boost::is_abstract + #else + : boost::mpl::false_ + #endif + { + }; + +} // namespace foreach + +} // namespace boost + +// vc6/7 needs help ordering the following overloads +#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +# define BOOST_FOREACH_TAG_DEFAULT ... +#else +# define BOOST_FOREACH_TAG_DEFAULT boost::foreach::tag +#endif + +/////////////////////////////////////////////////////////////////////////////// +// boost_foreach_is_lightweight_proxy +// Another customization point for the is_lightweight_proxy optimization, +// this one works on legacy compilers. Overload boost_foreach_is_lightweight_proxy +// at the global namespace for your type. +template +inline boost::foreach::is_lightweight_proxy * +boost_foreach_is_lightweight_proxy(T *&, BOOST_FOREACH_TAG_DEFAULT) { return 0; } + +template +inline boost::mpl::true_ * +boost_foreach_is_lightweight_proxy(std::pair *&, boost::foreach::tag) { return 0; } + +template +inline boost::mpl::true_ * +boost_foreach_is_lightweight_proxy(boost::iterator_range *&, boost::foreach::tag) { return 0; } + +template +inline boost::mpl::true_ * +boost_foreach_is_lightweight_proxy(boost::sub_range *&, boost::foreach::tag) { return 0; } + +template +inline boost::mpl::true_ * +boost_foreach_is_lightweight_proxy(T **&, boost::foreach::tag) { return 0; } + +/////////////////////////////////////////////////////////////////////////////// +// boost_foreach_is_noncopyable +// Another customization point for the is_noncopyable trait, +// this one works on legacy compilers. Overload boost_foreach_is_noncopyable +// at the global namespace for your type. +template +inline boost::foreach::is_noncopyable * +boost_foreach_is_noncopyable(T *&, BOOST_FOREACH_TAG_DEFAULT) { return 0; } + +namespace boost +{ + +namespace foreach_detail_ +{ + +/////////////////////////////////////////////////////////////////////////////// +// Define some utilities for assessing the properties of expressions +// +template +inline boost::mpl::and_ *and_(Bool1 *, Bool2 *) { return 0; } + +template +inline boost::mpl::and_ *and_(Bool1 *, Bool2 *, Bool3 *) { return 0; } + +template +inline boost::mpl::or_ *or_(Bool1 *, Bool2 *) { return 0; } + +template +inline boost::mpl::or_ *or_(Bool1 *, Bool2 *, Bool3 *) { return 0; } + +template +inline boost::mpl::not_ *not_(Bool *) { return 0; } + +template +inline boost::mpl::false_ *is_rvalue_(T &, int) { return 0; } + +template +inline boost::mpl::true_ *is_rvalue_(T const &, ...) { return 0; } + +template +inline boost::is_array *is_array_(T const &) { return 0; } + +template +inline boost::is_const *is_const_(T &) { return 0; } + +#ifndef BOOST_FOREACH_NO_RVALUE_DETECTION +template +inline boost::mpl::true_ *is_const_(T const &) { return 0; } +#endif + +/////////////////////////////////////////////////////////////////////////////// +// auto_any_t/auto_any +// General utility for putting an object of any type into automatic storage +struct auto_any_base +{ + // auto_any_base must evaluate to false in boolean context so that + // they can be declared in if() statements. + operator bool() const + { + return false; + } +}; + +template +struct auto_any : auto_any_base +{ + auto_any(T const &t) + : item(t) + { + } + + // temporaries of type auto_any will be bound to const auto_any_base + // references, but we still want to be able to mutate the stored + // data, so declare it as mutable. + mutable T item; +}; + +typedef auto_any_base const &auto_any_t; + +template +inline BOOST_DEDUCED_TYPENAME boost::mpl::if_::type &auto_any_cast(auto_any_t a) +{ + return static_cast const &>(a).item; +} + +typedef boost::mpl::true_ const_; + +/////////////////////////////////////////////////////////////////////////////// +// type2type +// +template +struct type2type + : boost::mpl::if_ +{ +}; + +template +struct wrap_cstr +{ + typedef T type; +}; + +template<> +struct wrap_cstr +{ + typedef wrap_cstr type; + typedef char *iterator; + typedef char *const_iterator; +}; + +template<> +struct wrap_cstr +{ + typedef wrap_cstr type; + typedef char const *iterator; + typedef char const *const_iterator; +}; + +template<> +struct wrap_cstr +{ + typedef wrap_cstr type; + typedef wchar_t *iterator; + typedef wchar_t *const_iterator; +}; + +template<> +struct wrap_cstr +{ + typedef wrap_cstr type; + typedef wchar_t const *iterator; + typedef wchar_t const *const_iterator; +}; + +template +struct is_char_array + : mpl::and_< + is_array + , mpl::or_< + is_convertible + , is_convertible + > + > +{}; + +template +struct foreach_iterator +{ + // **** READ THIS IF YOUR COMPILE BREAKS HERE **** + // + // There is an ambiguity about how to iterate over arrays of char and wchar_t. + // Should the last array element be treated as a null terminator to be skipped, or + // is it just like any other element in the array? To fix the problem, you must + // say which behavior you want. + // + // To treat the container as a null-terminated string, merely cast it to a + // char const *, as in BOOST_FOREACH( char ch, (char const *)"hello" ) ... + // + // To treat the container as an array, use boost::as_array() in , + // as in BOOST_FOREACH( char ch, boost::as_array("hello") ) ... + #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + BOOST_MPL_ASSERT_MSG( (!is_char_array::value), IS_THIS_AN_ARRAY_OR_A_NULL_TERMINATED_STRING, (T&) ); + #endif + + // If the type is a pointer to a null terminated string (as opposed + // to an array type), there is no ambiguity. + typedef BOOST_DEDUCED_TYPENAME wrap_cstr::type container; + + typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if< + C + , range_const_iterator + , range_mutable_iterator + >::type type; +}; + + +template +struct foreach_reverse_iterator +{ + // **** READ THIS IF YOUR COMPILE BREAKS HERE **** + // + // There is an ambiguity about how to iterate over arrays of char and wchar_t. + // Should the last array element be treated as a null terminator to be skipped, or + // is it just like any other element in the array? To fix the problem, you must + // say which behavior you want. + // + // To treat the container as a null-terminated string, merely cast it to a + // char const *, as in BOOST_FOREACH( char ch, (char const *)"hello" ) ... + // + // To treat the container as an array, use boost::as_array() in , + // as in BOOST_FOREACH( char ch, boost::as_array("hello") ) ... + #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + BOOST_MPL_ASSERT_MSG( (!is_char_array::value), IS_THIS_AN_ARRAY_OR_A_NULL_TERMINATED_STRING, (T&) ); + #endif + + // If the type is a pointer to a null terminated string (as opposed + // to an array type), there is no ambiguity. + typedef BOOST_DEDUCED_TYPENAME wrap_cstr::type container; + + typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if< + C + , range_reverse_iterator + , range_reverse_iterator + >::type type; +}; + +template +struct foreach_reference + : iterator_reference::type> +{ +}; + +/////////////////////////////////////////////////////////////////////////////// +// encode_type +// +template +inline type2type *encode_type(T &, boost::mpl::false_ *) { return 0; } + +template +inline type2type *encode_type(T const &, boost::mpl::true_ *) { return 0; } + +/////////////////////////////////////////////////////////////////////////////// +// set_false +// +inline bool set_false(bool &b) +{ + b = false; + return false; +} + +/////////////////////////////////////////////////////////////////////////////// +// to_ptr +// +template +inline T *&to_ptr(T const &) +{ + static T *t = 0; + return t; +} + +// Borland needs a little extra help with arrays +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +template +inline T (*&to_ptr(T (&)[N]))[N] +{ + static T (*t)[N] = 0; + return t; +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// derefof +// +template +inline T &derefof(T *t) +{ + // This is a work-around for a compiler bug in Borland. If T* is a pointer to array type U(*)[N], + // then dereferencing it results in a U* instead of U(&)[N]. The cast forces the issue. + return reinterpret_cast( + *const_cast( + reinterpret_cast(t) + ) + ); +} + +#ifdef BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION +/////////////////////////////////////////////////////////////////////////////// +// Detect at compile-time whether an expression yields an rvalue or +// an lvalue. This is rather non-standard, but some popular compilers +// accept it. +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// rvalue_probe +// +template +struct rvalue_probe +{ + struct private_type_ {}; + // can't ever return an array by value + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< + boost::mpl::or_, boost::is_array >, private_type_, T + >::type value_type; + operator value_type() { return *reinterpret_cast(this); } // never called + operator T &() const { return *reinterpret_cast(const_cast(this)); } // never called +}; + +template +rvalue_probe const make_probe(T const &) +{ + return rvalue_probe(); +} + +# define BOOST_FOREACH_IS_RVALUE(COL) \ + boost::foreach_detail_::and_( \ + boost::foreach_detail_::not_(boost::foreach_detail_::is_array_(COL)) \ + , (true ? 0 : boost::foreach_detail_::is_rvalue_( \ + (true ? boost::foreach_detail_::make_probe(COL) : (COL)), 0))) + +#elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION) +/////////////////////////////////////////////////////////////////////////////// +// Detect at run-time whether an expression yields an rvalue +// or an lvalue. This is 100% standard C++, but not all compilers +// accept it. Also, it causes FOREACH to break when used with non- +// copyable collection types. +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// rvalue_probe +// +template +struct rvalue_probe +{ + rvalue_probe(T &t, bool &b) + : value(t) + , is_rvalue(b) + { + } + + struct private_type_ {}; + // can't ever return an array or an abstract type by value + #ifdef BOOST_NO_IS_ABSTRACT + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< + boost::is_array, private_type_, T + >::type value_type; + #else + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< + boost::mpl::or_, boost::is_array >, private_type_, T + >::type value_type; + #endif + + operator value_type() + { + this->is_rvalue = true; + return this->value; + } + + operator T &() const + { + return this->value; + } + +private: + T &value; + bool &is_rvalue; +}; + +template +rvalue_probe make_probe(T &t, bool &b) { return rvalue_probe(t, b); } + +template +rvalue_probe make_probe(T const &t, bool &b) { return rvalue_probe(t, b); } + +/////////////////////////////////////////////////////////////////////////////// +// simple_variant +// holds either a T or a T const* +template +struct simple_variant +{ + simple_variant(T const *t) + : is_rvalue(false) + { + *static_cast(this->data.address()) = t; + } + + simple_variant(T const &t) + : is_rvalue(true) + { + ::new(this->data.address()) T(t); + } + + simple_variant(simple_variant const &that) + : is_rvalue(that.is_rvalue) + { + if(this->is_rvalue) + ::new(this->data.address()) T(*that.get()); + else + *static_cast(this->data.address()) = that.get(); + } + + ~simple_variant() + { + if(this->is_rvalue) + this->get()->~T(); + } + + T const *get() const + { + if(this->is_rvalue) + return static_cast(this->data.address()); + else + return *static_cast(this->data.address()); + } + +private: + enum size_type { size = sizeof(T) > sizeof(T*) ? sizeof(T) : sizeof(T*) }; + simple_variant &operator =(simple_variant const &); + bool const is_rvalue; + aligned_storage data; +}; + +// If the collection is an array or is noncopyable, it must be an lvalue. +// If the collection is a lightweight proxy, treat it as an rvalue +// BUGBUG what about a noncopyable proxy? +template +inline BOOST_DEDUCED_TYPENAME boost::enable_if, IsProxy>::type * +should_copy_impl(LValue *, IsProxy *, bool *) +{ + return 0; +} + +// Otherwise, we must determine at runtime whether it's an lvalue or rvalue +inline bool * +should_copy_impl(boost::mpl::false_ *, boost::mpl::false_ *, bool *is_rvalue) +{ + return is_rvalue; +} + +#endif + +/////////////////////////////////////////////////////////////////////////////// +// contain +// +template +inline auto_any contain(T const &t, boost::mpl::true_ *) // rvalue +{ + return t; +} + +template +inline auto_any contain(T &t, boost::mpl::false_ *) // lvalue +{ + // Cannot seem to get sunpro to handle addressof() with array types. + #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x570)) + return &t; + #else + return boost::addressof(t); + #endif +} + +#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION +template +auto_any > +contain(T const &t, bool *rvalue) +{ + return *rvalue ? simple_variant(t) : simple_variant(&t); +} +#endif + +///////////////////////////////////////////////////////////////////////////// +// begin +// +template +inline auto_any::type> +begin(auto_any_t col, type2type *, boost::mpl::true_ *) // rvalue +{ + return boost::begin(auto_any_cast(col)); +} + +template +inline auto_any::type> +begin(auto_any_t col, type2type *, boost::mpl::false_ *) // lvalue +{ + typedef BOOST_DEDUCED_TYPENAME type2type::type type; + typedef BOOST_DEDUCED_TYPENAME foreach_iterator::type iterator; + return iterator(boost::begin(derefof(auto_any_cast(col)))); +} + +#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION +template +auto_any::type> +begin(auto_any_t col, type2type *, bool *) +{ + return boost::begin(*auto_any_cast, boost::mpl::false_>(col).get()); +} +#endif + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +template +inline auto_any +begin(auto_any_t col, type2type *, boost::mpl::true_ *) // null-terminated C-style strings +{ + return auto_any_cast(col); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// end +// +template +inline auto_any::type> +end(auto_any_t col, type2type *, boost::mpl::true_ *) // rvalue +{ + return boost::end(auto_any_cast(col)); +} + +template +inline auto_any::type> +end(auto_any_t col, type2type *, boost::mpl::false_ *) // lvalue +{ + typedef BOOST_DEDUCED_TYPENAME type2type::type type; + typedef BOOST_DEDUCED_TYPENAME foreach_iterator::type iterator; + return iterator(boost::end(derefof(auto_any_cast(col)))); +} + +#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION +template +auto_any::type> +end(auto_any_t col, type2type *, bool *) +{ + return boost::end(*auto_any_cast, boost::mpl::false_>(col).get()); +} +#endif + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +template +inline auto_any +end(auto_any_t col, type2type *, boost::mpl::true_ *) // null-terminated C-style strings +{ + return 0; // not used +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// done +// +template +inline bool done(auto_any_t cur, auto_any_t end, type2type *) +{ + typedef BOOST_DEDUCED_TYPENAME foreach_iterator::type iter_t; + return auto_any_cast(cur) == auto_any_cast(end); +} + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +template +inline bool done(auto_any_t cur, auto_any_t, type2type *) // null-terminated C-style strings +{ + return ! *auto_any_cast(cur); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// next +// +template +inline void next(auto_any_t cur, type2type *) +{ + typedef BOOST_DEDUCED_TYPENAME foreach_iterator::type iter_t; + ++auto_any_cast(cur); +} + +/////////////////////////////////////////////////////////////////////////////// +// deref +// +template +inline BOOST_DEDUCED_TYPENAME foreach_reference::type +deref(auto_any_t cur, type2type *) +{ + typedef BOOST_DEDUCED_TYPENAME foreach_iterator::type iter_t; + return *auto_any_cast(cur); +} + +///////////////////////////////////////////////////////////////////////////// +// rbegin +// +template +inline auto_any::type> +rbegin(auto_any_t col, type2type *, boost::mpl::true_ *) // rvalue +{ + return boost::rbegin(auto_any_cast(col)); +} + +template +inline auto_any::type> +rbegin(auto_any_t col, type2type *, boost::mpl::false_ *) // lvalue +{ + typedef BOOST_DEDUCED_TYPENAME type2type::type type; + typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator::type iterator; + return iterator(boost::rbegin(derefof(auto_any_cast(col)))); +} + +#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION +template +auto_any::type> +rbegin(auto_any_t col, type2type *, bool *) +{ + return boost::rbegin(*auto_any_cast, boost::mpl::false_>(col).get()); +} +#endif + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +template +inline auto_any > +rbegin(auto_any_t col, type2type *, boost::mpl::true_ *) // null-terminated C-style strings +{ + T *p = auto_any_cast(col); + while(0 != *p) + ++p; + return reverse_iterator(p); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// rend +// +template +inline auto_any::type> +rend(auto_any_t col, type2type *, boost::mpl::true_ *) // rvalue +{ + return boost::rend(auto_any_cast(col)); +} + +template +inline auto_any::type> +rend(auto_any_t col, type2type *, boost::mpl::false_ *) // lvalue +{ + typedef BOOST_DEDUCED_TYPENAME type2type::type type; + typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator::type iterator; + return iterator(boost::rend(derefof(auto_any_cast(col)))); +} + +#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION +template +auto_any::type> +rend(auto_any_t col, type2type *, bool *) +{ + return boost::rend(*auto_any_cast, boost::mpl::false_>(col).get()); +} +#endif + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +template +inline auto_any > +rend(auto_any_t col, type2type *, boost::mpl::true_ *) // null-terminated C-style strings +{ + return reverse_iterator(auto_any_cast(col)); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// rdone +// +template +inline bool rdone(auto_any_t cur, auto_any_t end, type2type *) +{ + typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator::type iter_t; + return auto_any_cast(cur) == auto_any_cast(end); +} + +/////////////////////////////////////////////////////////////////////////////// +// rnext +// +template +inline void rnext(auto_any_t cur, type2type *) +{ + typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator::type iter_t; + ++auto_any_cast(cur); +} + +/////////////////////////////////////////////////////////////////////////////// +// rderef +// +template +inline BOOST_DEDUCED_TYPENAME foreach_reference::type +rderef(auto_any_t cur, type2type *) +{ + typedef BOOST_DEDUCED_TYPENAME foreach_reverse_iterator::type iter_t; + return *auto_any_cast(cur); +} + +} // namespace foreach_detail_ +} // namespace boost + +// Suppress a bogus code analysis warning on vc8+ +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# define BOOST_FOREACH_SUPPRESS_WARNINGS() __pragma(warning(suppress:6001)) +#else +# define BOOST_FOREACH_SUPPRESS_WARNINGS() +#endif + +// A sneaky way to get the type of the collection without evaluating the expression +#define BOOST_FOREACH_TYPEOF(COL) \ + (true ? 0 : boost::foreach_detail_::encode_type(COL, boost::foreach_detail_::is_const_(COL))) + +// returns true_* if the type is noncopyable +#define BOOST_FOREACH_IS_NONCOPYABLE(COL) \ + boost_foreach_is_noncopyable( \ + boost::foreach_detail_::to_ptr(COL) \ + , boost_foreach_argument_dependent_lookup_hack_value) + +// returns true_* if the type is a lightweight proxy (and is not noncopyable) +#define BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL) \ + boost::foreach_detail_::and_( \ + boost::foreach_detail_::not_(BOOST_FOREACH_IS_NONCOPYABLE(COL)) \ + , boost_foreach_is_lightweight_proxy( \ + boost::foreach_detail_::to_ptr(COL) \ + , boost_foreach_argument_dependent_lookup_hack_value)) + +#ifdef BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION +/////////////////////////////////////////////////////////////////////////////// +// R-values and const R-values supported here with zero runtime overhead +/////////////////////////////////////////////////////////////////////////////// + +// No variable is needed to track the rvalue-ness of the collection expression +# define BOOST_FOREACH_PREAMBLE() \ + BOOST_FOREACH_SUPPRESS_WARNINGS() + +// Evaluate the collection expression +# define BOOST_FOREACH_EVALUATE(COL) \ + (COL) + +# define BOOST_FOREACH_SHOULD_COPY(COL) \ + (true ? 0 : boost::foreach_detail_::or_( \ + BOOST_FOREACH_IS_RVALUE(COL) \ + , BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL))) + +#elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION) +/////////////////////////////////////////////////////////////////////////////// +// R-values and const R-values supported here +/////////////////////////////////////////////////////////////////////////////// + +// Declare a variable to track the rvalue-ness of the collection expression +# define BOOST_FOREACH_PREAMBLE() \ + BOOST_FOREACH_SUPPRESS_WARNINGS() \ + if (bool _foreach_is_rvalue = false) {} else + +// Evaluate the collection expression, and detect if it is an lvalue or and rvalue +# define BOOST_FOREACH_EVALUATE(COL) \ + (true ? boost::foreach_detail_::make_probe((COL), _foreach_is_rvalue) : (COL)) + +// The rvalue/lvalue-ness of the collection expression is determined dynamically, unless +// type type is an array or is noncopyable or is non-const, in which case we know it's an lvalue. +// If the type happens to be a lightweight proxy, always make a copy. +# define BOOST_FOREACH_SHOULD_COPY(COL) \ + (boost::foreach_detail_::should_copy_impl( \ + true ? 0 : boost::foreach_detail_::or_( \ + boost::foreach_detail_::is_array_(COL) \ + , BOOST_FOREACH_IS_NONCOPYABLE(COL) \ + , boost::foreach_detail_::not_(boost::foreach_detail_::is_const_(COL))) \ + , true ? 0 : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL) \ + , &_foreach_is_rvalue)) + +#elif !defined(BOOST_FOREACH_NO_RVALUE_DETECTION) +/////////////////////////////////////////////////////////////////////////////// +// R-values supported here, const R-values NOT supported here +/////////////////////////////////////////////////////////////////////////////// + +// No variable is needed to track the rvalue-ness of the collection expression +# define BOOST_FOREACH_PREAMBLE() \ + BOOST_FOREACH_SUPPRESS_WARNINGS() + +// Evaluate the collection expression +# define BOOST_FOREACH_EVALUATE(COL) \ + (COL) + +// Determine whether the collection expression is an lvalue or an rvalue. +// NOTE: this gets the answer wrong for const rvalues. +# define BOOST_FOREACH_SHOULD_COPY(COL) \ + (true ? 0 : boost::foreach_detail_::or_( \ + boost::foreach_detail_::is_rvalue_((COL), 0) \ + , BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL))) + +#else +/////////////////////////////////////////////////////////////////////////////// +// R-values NOT supported here +/////////////////////////////////////////////////////////////////////////////// + +// No variable is needed to track the rvalue-ness of the collection expression +# define BOOST_FOREACH_PREAMBLE() \ + BOOST_FOREACH_SUPPRESS_WARNINGS() + +// Evaluate the collection expression +# define BOOST_FOREACH_EVALUATE(COL) \ + (COL) + +// Can't use rvalues with BOOST_FOREACH (unless they are lightweight proxies) +# define BOOST_FOREACH_SHOULD_COPY(COL) \ + (true ? 0 : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)) + +#endif + +#define BOOST_FOREACH_CONTAIN(COL) \ + boost::foreach_detail_::contain( \ + BOOST_FOREACH_EVALUATE(COL) \ + , BOOST_FOREACH_SHOULD_COPY(COL)) + +#define BOOST_FOREACH_BEGIN(COL) \ + boost::foreach_detail_::begin( \ + _foreach_col \ + , BOOST_FOREACH_TYPEOF(COL) \ + , BOOST_FOREACH_SHOULD_COPY(COL)) + +#define BOOST_FOREACH_END(COL) \ + boost::foreach_detail_::end( \ + _foreach_col \ + , BOOST_FOREACH_TYPEOF(COL) \ + , BOOST_FOREACH_SHOULD_COPY(COL)) + +#define BOOST_FOREACH_DONE(COL) \ + boost::foreach_detail_::done( \ + _foreach_cur \ + , _foreach_end \ + , BOOST_FOREACH_TYPEOF(COL)) + +#define BOOST_FOREACH_NEXT(COL) \ + boost::foreach_detail_::next( \ + _foreach_cur \ + , BOOST_FOREACH_TYPEOF(COL)) + +#define BOOST_FOREACH_DEREF(COL) \ + boost::foreach_detail_::deref( \ + _foreach_cur \ + , BOOST_FOREACH_TYPEOF(COL)) + +#define BOOST_FOREACH_RBEGIN(COL) \ + boost::foreach_detail_::rbegin( \ + _foreach_col \ + , BOOST_FOREACH_TYPEOF(COL) \ + , BOOST_FOREACH_SHOULD_COPY(COL)) + +#define BOOST_FOREACH_REND(COL) \ + boost::foreach_detail_::rend( \ + _foreach_col \ + , BOOST_FOREACH_TYPEOF(COL) \ + , BOOST_FOREACH_SHOULD_COPY(COL)) + +#define BOOST_FOREACH_RDONE(COL) \ + boost::foreach_detail_::rdone( \ + _foreach_cur \ + , _foreach_end \ + , BOOST_FOREACH_TYPEOF(COL)) + +#define BOOST_FOREACH_RNEXT(COL) \ + boost::foreach_detail_::rnext( \ + _foreach_cur \ + , BOOST_FOREACH_TYPEOF(COL)) + +#define BOOST_FOREACH_RDEREF(COL) \ + boost::foreach_detail_::rderef( \ + _foreach_cur \ + , BOOST_FOREACH_TYPEOF(COL)) + +/////////////////////////////////////////////////////////////////////////////// +// BOOST_FOREACH +// +// For iterating over collections. Collections can be +// arrays, null-terminated strings, or STL containers. +// The loop variable can be a value or reference. For +// example: +// +// std::list int_list(/*stuff*/); +// BOOST_FOREACH(int &i, int_list) +// { +// /* +// * loop body goes here. +// * i is a reference to the int in int_list. +// */ +// } +// +// Alternately, you can declare the loop variable first, +// so you can access it after the loop finishes. Obviously, +// if you do it this way, then the loop variable cannot be +// a reference. +// +// int i; +// BOOST_FOREACH(i, int_list) +// { ... } +// +#define BOOST_FOREACH(VAR, COL) \ + BOOST_FOREACH_PREAMBLE() \ + if (boost::foreach_detail_::auto_any_t _foreach_col = BOOST_FOREACH_CONTAIN(COL)) {} else \ + if (boost::foreach_detail_::auto_any_t _foreach_cur = BOOST_FOREACH_BEGIN(COL)) {} else \ + if (boost::foreach_detail_::auto_any_t _foreach_end = BOOST_FOREACH_END(COL)) {} else \ + for (bool _foreach_continue = true; \ + _foreach_continue && !BOOST_FOREACH_DONE(COL); \ + _foreach_continue ? BOOST_FOREACH_NEXT(COL) : (void)0) \ + if (boost::foreach_detail_::set_false(_foreach_continue)) {} else \ + for (VAR = BOOST_FOREACH_DEREF(COL); !_foreach_continue; _foreach_continue = true) + +/////////////////////////////////////////////////////////////////////////////// +// BOOST_REVERSE_FOREACH +// +// For iterating over collections in reverse order. In +// all other respects, BOOST_REVERSE_FOREACH is like +// BOOST_FOREACH. +// +#define BOOST_REVERSE_FOREACH(VAR, COL) \ + BOOST_FOREACH_PREAMBLE() \ + if (boost::foreach_detail_::auto_any_t _foreach_col = BOOST_FOREACH_CONTAIN(COL)) {} else \ + if (boost::foreach_detail_::auto_any_t _foreach_cur = BOOST_FOREACH_RBEGIN(COL)) {} else \ + if (boost::foreach_detail_::auto_any_t _foreach_end = BOOST_FOREACH_REND(COL)) {} else \ + for (bool _foreach_continue = true; \ + _foreach_continue && !BOOST_FOREACH_RDONE(COL); \ + _foreach_continue ? BOOST_FOREACH_RNEXT(COL) : (void)0) \ + if (boost::foreach_detail_::set_false(_foreach_continue)) {} else \ + for (VAR = BOOST_FOREACH_RDEREF(COL); !_foreach_continue; _foreach_continue = true) + +#endif diff --git a/win32/include/boost/format.hpp b/win32/include/boost/format.hpp new file mode 100755 index 000000000..13516b406 --- /dev/null +++ b/win32/include/boost/format.hpp @@ -0,0 +1,59 @@ +// ---------------------------------------------------------------------------- +// format.hpp : primary header +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// See http://www.boost.org/libs/format for library home page + + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_FORMAT_HPP +#define BOOST_FORMAT_HPP + +#include +#include +#include +#include + +#ifndef BOOST_NO_STD_LOCALE +#include +#endif + +// *** Compatibility framework +#include + +#ifdef BOOST_NO_LOCALE_ISIDIGIT +#include // we'll use the non-locale 's std::isdigit(int) +#endif + +// **** Forward declarations ---------------------------------- +#include // basic_format, and other frontends +#include // misc forward declarations for internal use + +// **** Auxiliary structs (stream_format_state , and format_item ) +#include + +// **** Format class interface -------------------------------- +#include + +// **** Exceptions ----------------------------------------------- +#include + +// **** Implementation ------------------------------------------- +#include // member functions +#include // class for grouping arguments +#include // argument-feeding functions +#include // format-string parsing (member-)functions + +// **** Implementation of the free functions ---------------------- +#include + + +// *** Undefine 'local' macros : +#include + +#endif // BOOST_FORMAT_HPP diff --git a/win32/include/boost/format/alt_sstream.hpp b/win32/include/boost/format/alt_sstream.hpp new file mode 100755 index 000000000..7574d54c7 --- /dev/null +++ b/win32/include/boost/format/alt_sstream.hpp @@ -0,0 +1,176 @@ +// ---------------------------------------------------------------------------- +// alt_sstream.hpp : alternative stringstream +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// See http://www.boost.org/libs/format for library home page + +// ---------------------------------------------------------------------------- + + + +#ifndef BOOST_SK_ALT_SSTREAM_HPP +#define BOOST_SK_ALT_SSTREAM_HPP + +#include +#include +#include +#include +#include + +namespace boost { + namespace io { + + template, + class Alloc=::std::allocator > + class basic_altstringbuf; + + template, + class Alloc=::std::allocator > + class basic_oaltstringstream; + + + template + class basic_altstringbuf + : public ::std::basic_streambuf + { + typedef ::std::basic_streambuf streambuf_t; + typedef typename CompatAlloc::compatible_type compat_allocator_type; + typedef typename CompatTraits::compatible_type compat_traits_type; + public: + typedef Ch char_type; + typedef Tr traits_type; + typedef typename compat_traits_type::int_type int_type; + typedef typename compat_traits_type::pos_type pos_type; + typedef typename compat_traits_type::off_type off_type; + typedef Alloc allocator_type; + typedef ::std::basic_string string_type; + typedef typename string_type::size_type size_type; + + typedef ::std::streamsize streamsize; + + + explicit basic_altstringbuf(std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + : putend_(NULL), is_allocated_(false), mode_(mode) + {} + explicit basic_altstringbuf(const string_type& s, + ::std::ios_base::openmode mode + = ::std::ios_base::in | ::std::ios_base::out) + : putend_(NULL), is_allocated_(false), mode_(mode) + { dealloc(); str(s); } + virtual ~basic_altstringbuf() + { dealloc(); } + using streambuf_t::pbase; + using streambuf_t::pptr; + using streambuf_t::epptr; + using streambuf_t::eback; + using streambuf_t::gptr; + using streambuf_t::egptr; + + void clear_buffer(); + void str(const string_type& s); + + // 0-copy access : + Ch * begin() const; + size_type size() const; + size_type cur_size() const; // stop at current pointer + Ch * pend() const // the highest position reached by pptr() since creation + { return ((putend_ < pptr()) ? pptr() : putend_); } + size_type pcount() const + { return static_cast( pptr() - pbase()) ;} + + // copy buffer to string : + string_type str() const + { return string_type(begin(), size()); } + string_type cur_str() const + { return string_type(begin(), cur_size()); } + protected: + explicit basic_altstringbuf (basic_altstringbuf * s, + ::std::ios_base::openmode mode + = ::std::ios_base::in | ::std::ios_base::out) + : putend_(NULL), is_allocated_(false), mode_(mode) + { dealloc(); str(s); } + + virtual pos_type seekoff(off_type off, ::std::ios_base::seekdir way, + ::std::ios_base::openmode which + = ::std::ios_base::in | ::std::ios_base::out); + virtual pos_type seekpos (pos_type pos, + ::std::ios_base::openmode which + = ::std::ios_base::in | ::std::ios_base::out); + virtual int_type underflow(); + virtual int_type pbackfail(int_type meta = compat_traits_type::eof()); + virtual int_type overflow(int_type meta = compat_traits_type::eof()); + void dealloc(); + private: + enum { alloc_min = 256}; // minimum size of allocations + + Ch *putend_; // remembers (over seeks) the highest value of pptr() + bool is_allocated_; + ::std::ios_base::openmode mode_; + compat_allocator_type alloc_; // the allocator object + }; + + +// --- class basic_oaltstringstream ---------------------------------------- + template + class basic_oaltstringstream + : private base_from_member< shared_ptr< basic_altstringbuf< Ch, Tr, Alloc> > >, + public ::std::basic_ostream + { + class No_Op { + // used as no-op deleter for (not-owner) shared_pointers + public: + template + const T & operator()(const T & arg) { return arg; } + }; + typedef ::std::basic_ostream stream_t; + typedef boost::base_from_member > > + pbase_type; + typedef ::std::basic_string string_type; + typedef typename string_type::size_type size_type; + typedef basic_altstringbuf stringbuf_t; + public: + typedef Alloc allocator_type; + basic_oaltstringstream() + : pbase_type(new stringbuf_t), stream_t(rdbuf()) + { } + basic_oaltstringstream(::boost::shared_ptr buf) + : pbase_type(buf), stream_t(rdbuf()) + { } + basic_oaltstringstream(stringbuf_t * buf) + : pbase_type(buf, No_Op() ), stream_t(rdbuf()) + { } + stringbuf_t * rdbuf() const + { return pbase_type::member.get(); } + void clear_buffer() + { rdbuf()->clear_buffer(); } + + // 0-copy access : + Ch * begin() const + { return rdbuf()->begin(); } + size_type size() const + { return rdbuf()->size(); } + size_type cur_size() const // stops at current position + { return rdbuf()->cur_size(); } + + // copy buffer to string : + string_type str() const // [pbase, epptr[ + { return rdbuf()->str(); } + string_type cur_str() const // [pbase, pptr[ + { return rdbuf()->cur_str(); } + void str(const string_type& s) + { rdbuf()->str(s); } + }; + + } // N.S. io +} // N.S. boost + +#include + +#endif // include guard + diff --git a/win32/include/boost/format/alt_sstream_impl.hpp b/win32/include/boost/format/alt_sstream_impl.hpp new file mode 100755 index 000000000..ca7ffd1d0 --- /dev/null +++ b/win32/include/boost/format/alt_sstream_impl.hpp @@ -0,0 +1,303 @@ +// ---------------------------------------------------------------------------- +// alt_sstream_impl.hpp : alternative stringstream, templates implementation +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// See http://www.boost.org/libs/format for library home page + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_SK_ALT_SSTREAM_IMPL_HPP +#define BOOST_SK_ALT_SSTREAM_IMPL_HPP + +namespace boost { + namespace io { +// --- Implementation ------------------------------------------------------// + + template + void basic_altstringbuf:: + clear_buffer () { + const Ch * p = pptr(); + const Ch * b = pbase(); + if(p != NULL && p != b) { + seekpos(0, ::std::ios_base::out); + } + p = gptr(); + b = eback(); + if(p != NULL && p != b) { + seekpos(0, ::std::ios_base::in); + } + } + + template + void basic_altstringbuf:: + str (const string_type& s) { + size_type sz=s.size(); + if(sz != 0 && mode_ & (::std::ios_base::in | ::std::ios_base::out) ) { + Ch *new_ptr = alloc_.allocate(sz, is_allocated_? eback() : 0); + // if this didnt throw, we're safe, update the buffer + dealloc(); + sz = s.copy(new_ptr, sz); + putend_ = new_ptr + sz; + if(mode_ & ::std::ios_base::in) + streambuf_t::setg(new_ptr, new_ptr, new_ptr + sz); + if(mode_ & ::std::ios_base::out) { + streambuf_t::setp(new_ptr, new_ptr + sz); + if(mode_ & (::std::ios_base::app | ::std::ios_base::ate)) + streambuf_t::pbump(static_cast(sz)); + if(gptr() == NULL) + streambuf_t::setg(new_ptr, NULL, new_ptr); + } + is_allocated_ = true; + } + else + dealloc(); + } + template + Ch* basic_altstringbuf:: + begin () const { + if(mode_ & ::std::ios_base::out && pptr() != NULL) + return pbase(); + else if(mode_ & ::std::ios_base::in && gptr() != NULL) + return eback(); + return NULL; + } + + template + typename std::basic_string::size_type + basic_altstringbuf:: + size () const { + if(mode_ & ::std::ios_base::out && pptr()) + return static_cast(pend() - pbase()); + else if(mode_ & ::std::ios_base::in && gptr()) + return static_cast(egptr() - eback()); + else + return 0; + } + + template + typename std::basic_string::size_type + basic_altstringbuf:: + cur_size () const { + if(mode_ & ::std::ios_base::out && pptr()) + return static_cast( pptr() - pbase()); + else if(mode_ & ::std::ios_base::in && gptr()) + return static_cast( gptr() - eback()); + else + return 0; + } + + template + typename basic_altstringbuf::pos_type + basic_altstringbuf:: + seekoff (off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) { + if(pptr() != NULL && putend_ < pptr()) + putend_ = pptr(); + if(which & ::std::ios_base::in && gptr() != NULL) { + // get area + if(way == ::std::ios_base::end) + off += static_cast(putend_ - gptr()); + else if(way == ::std::ios_base::beg) + off += static_cast(eback() - gptr()); + else if(way != ::std::ios_base::cur || (which & ::std::ios_base::out) ) + // (altering in&out is only supported if way is beg or end, not cur) + return pos_type(off_type(-1)); + if(eback() <= off+gptr() && off+gptr() <= putend_ ) { + // set gptr + streambuf_t::gbump(static_cast(off)); + if(which & ::std::ios_base::out && pptr() != NULL) + // update pptr to match gptr + streambuf_t::pbump(static_cast(gptr()-pptr())); + } + else + off = off_type(-1); + } + else if(which & ::std::ios_base::out && pptr() != NULL) { + // put area + if(way == ::std::ios_base::end) + off += static_cast(putend_ - pptr()); + else if(way == ::std::ios_base::beg) + off += static_cast(pbase() - pptr()); + else if(way != ::std::ios_base::beg) + return pos_type(off_type(-1)); + if(pbase() <= off+pptr() && off+pptr() <= putend_) + // set pptr + streambuf_t::pbump(static_cast(off)); + else + off = off_type(-1); + } + else // neither in nor out + off = off_type(-1); + return (pos_type(off)); + } + //- end seekoff(..) + + + template + typename basic_altstringbuf::pos_type + basic_altstringbuf:: + seekpos (pos_type pos, ::std::ios_base::openmode which) { + off_type off = off_type(pos); // operation guaranteed by §27.4.3.2 table 88 + if(pptr() != NULL && putend_ < pptr()) + putend_ = pptr(); + if(off != off_type(-1)) { + if(which & ::std::ios_base::in && gptr() != NULL) { + // get area + if(0 <= off && off <= putend_ - eback()) { + streambuf_t::gbump(static_cast(eback() - gptr() + off)); + if(which & ::std::ios_base::out && pptr() != NULL) { + // update pptr to match gptr + streambuf_t::pbump(static_cast(gptr()-pptr())); + } + } + else + off = off_type(-1); + } + else if(which & ::std::ios_base::out && pptr() != NULL) { + // put area + if(0 <= off && off <= putend_ - eback()) + streambuf_t::pbump(static_cast(eback() - pptr() + off)); + else + off = off_type(-1); + } + else // neither in nor out + off = off_type(-1); + return (pos_type(off)); + } + else { + BOOST_ASSERT(0); // §27.4.3.2 allows undefined-behaviour here + return pos_type(off_type(-1)); + } + } + // -end seekpos(..) + + + template + typename basic_altstringbuf::int_type + basic_altstringbuf:: + underflow () { + if(gptr() == NULL) // no get area -> nothing to get. + return (compat_traits_type::eof()); + else if(gptr() < egptr()) // ok, in buffer + return (compat_traits_type::to_int_type(*gptr())); + else if(mode_ & ::std::ios_base::in && pptr() != NULL + && (gptr() < pptr() || gptr() < putend_) ) + { // expand get area + if(putend_ < pptr()) + putend_ = pptr(); // remember pptr reached this far + streambuf_t::setg(eback(), gptr(), putend_); + return (compat_traits_type::to_int_type(*gptr())); + } + else // couldnt get anything. EOF. + return (compat_traits_type::eof()); + } + // -end underflow(..) + + + template + typename basic_altstringbuf::int_type + basic_altstringbuf:: + pbackfail (int_type meta) { + if(gptr() != NULL && (eback() < gptr()) + && (mode_ & (::std::ios_base::out) + || compat_traits_type::eq_int_type(compat_traits_type::eof(), meta) + || compat_traits_type::eq(compat_traits_type::to_char_type(meta), gptr()[-1]) ) ) { + streambuf_t::gbump(-1); // back one character + if(!compat_traits_type::eq_int_type(compat_traits_type::eof(), meta)) + // put-back meta into get area + *gptr() = compat_traits_type::to_char_type(meta); + return (compat_traits_type::not_eof(meta)); + } + else + return (compat_traits_type::eof()); // failed putback + } + // -end pbackfail(..) + + + template + typename basic_altstringbuf::int_type + basic_altstringbuf:: + overflow (int_type meta) { +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4996) +#endif + if(compat_traits_type::eq_int_type(compat_traits_type::eof(), meta)) + return compat_traits_type::not_eof(meta); // nothing to do + else if(pptr() != NULL && pptr() < epptr()) { + streambuf_t::sputc(compat_traits_type::to_char_type(meta)); + return meta; + } + else if(! (mode_ & ::std::ios_base::out)) + // no write position, and cant make one + return compat_traits_type::eof(); + else { // make a write position available + std::size_t prev_size = pptr() == NULL ? 0 : epptr() - eback(); + std::size_t new_size = prev_size; + // exponential growth : size *= 1.5 + std::size_t add_size = new_size / 2; + if(add_size < alloc_min) + add_size = alloc_min; + Ch * newptr = NULL, *oldptr = eback(); + + // make sure adding add_size wont overflow size_t + while (0 < add_size && ((std::numeric_limits::max)() + - add_size < new_size) ) + add_size /= 2; + if(0 < add_size) { + new_size += add_size; + newptr = alloc_.allocate(new_size, is_allocated_? oldptr : 0); + } + + if(0 < prev_size) + compat_traits_type::copy(newptr, oldptr, prev_size); + if(is_allocated_) + alloc_.deallocate(oldptr, prev_size); + is_allocated_=true; + + if(prev_size == 0) { // first allocation + putend_ = newptr; + streambuf_t::setp(newptr, newptr + new_size); + if(mode_ & ::std::ios_base::in) + streambuf_t::setg(newptr, newptr, newptr + 1); + else + streambuf_t::setg(newptr, 0, newptr); + } + else { // update pointers + putend_ = putend_ - oldptr + newptr; + int pptr_count = static_cast(pptr()-pbase()); + int gptr_count = static_cast(gptr()-eback()); + streambuf_t::setp(pbase() - oldptr + newptr, newptr + new_size); + streambuf_t::pbump(pptr_count); + if(mode_ & ::std::ios_base::in) + streambuf_t::setg(newptr, newptr + gptr_count, pptr() + 1); + else + streambuf_t::setg(newptr, 0, newptr); + } + streambuf_t::sputc(compat_traits_type::to_char_type(meta)); + return meta; + } +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + } + // -end overflow(..) + + template + void basic_altstringbuf:: dealloc() { + if(is_allocated_) + alloc_.deallocate(eback(), (pptr() != NULL ? epptr() : egptr()) - eback()); + is_allocated_ = false; + streambuf_t::setg(0, 0, 0); + streambuf_t::setp(0, 0); + putend_ = NULL; + } + + }// N.S. io +} // N.S. boost + +#endif // include guard + diff --git a/win32/include/boost/format/detail/compat_workarounds.hpp b/win32/include/boost/format/detail/compat_workarounds.hpp new file mode 100755 index 000000000..898ef3076 --- /dev/null +++ b/win32/include/boost/format/detail/compat_workarounds.hpp @@ -0,0 +1,86 @@ +// ---------------------------------------------------------------------------- +// compat_workarounds : general framework for non-conformance workarounds +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// see http://www.boost.org/libs/format for library home page + +// ---------------------------------------------------------------------------- + + +// this file defines wrapper classes to hide non-conforming +// std::char_traits<> and std::allocator<> traits +// and Includes : config_macros.hpp (defines config macros +// and compiler-specific switches) + +// Non-conformant Std-libs fail to supply conformant traits (std::char_traits, +// std::allocator) and/or the std::string doesnt support them. +// We don't want to have hundreds of #ifdef workarounds, so we define +// replacement traits. +// But both char_traits and allocator traits are visible in the interface, +// (inside the final string type), thus we need to keep both +// the replacement type (typedefed to 'compatible_type') for real use, +// and the original stdlib type (typedef to 'type_for_string') for interface +// visibility. This is what Compat* classes do (as well as be transparent +// when good allocator and char traits are present) + +#ifndef BOOST_FORMAT_COMPAT_WORKAROUNDS_HPP +#define BOOST_FORMAT_COMPAT_WORKAROUNDS_HPP + +namespace boost { + namespace io { + + // gcc-2.95 char traits (non-conformantly named string_char_traits) + // lack several functions so we extend them in a replacement class. + template + class CompatTraits; + + // std::allocator in gcc-2.95 is ok, but basic_string only works + // with plain 'std::alloc' still, alt_stringbuf requires a functionnal + // alloc template argument, so we need a replacement allocator + template + class CompatAlloc; + } // N.S. io +}// N.S. boost + + +#include + // sets-up macros and load compiler-specific workarounds headers. + +#if !defined(BOOST_FORMAT_STREAMBUF_DEFINED) +// workarounds-gcc-2.95 might have defined own streambuf +#include +#endif + +#if !defined(BOOST_FORMAT_OSTREAM_DEFINED) +// workarounds-gcc-2.95 might already have included +#include +#endif + + + +namespace boost { + namespace io { + + // **** CompatTraits general definitions : ---------------------------- + template + class CompatTraits + { // general case : be transparent + public: + typedef Tr compatible_type; + }; + + // **** CompatAlloc general definitions : ----------------------------- + template + class CompatAlloc + { // general case : be transparent + public: + typedef Alloc compatible_type; + }; + + } //N.S. io +} // N.S. boost +#endif // include guard diff --git a/win32/include/boost/format/detail/config_macros.hpp b/win32/include/boost/format/detail/config_macros.hpp new file mode 100755 index 000000000..cccb463dd --- /dev/null +++ b/win32/include/boost/format/detail/config_macros.hpp @@ -0,0 +1,97 @@ +// -*- C++ -*- +// ---------------------------------------------------------------------------- +// config_macros.hpp : configuration macros for the format library +// only BOOST_IO_STD is absolutely needed (it should be 'std::' in general) +// others are compiler-specific workaround macros used in #ifdef switches +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// see http://www.boost.org/libs/format for library home page + + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_FORMAT_CONFIG_MACROS_HPP +#define BOOST_FORMAT_CONFIG_MACROS_HPP + +#include +#include + +// make sure our local macros wont override something : +#if defined(BOOST_NO_LOCALE_ISDIGIT) || defined(BOOST_OVERLOAD_FOR_NON_CONST) \ + || defined(BOOST_IO_STD) || defined( BOOST_IO_NEEDS_USING_DECLARATION ) \ + || defined(BOOST_NO_TEMPLATE_STD_STREAM) \ + || defined(BOOST_FORMAT_STREAMBUF_DEFINED) || defined(BOOST_FORMAT_OSTREAM_DEFINED) +#error "boost::format uses a local macro that is already defined." +#endif + +// specific workarounds. each header can define BOOS_IO_STD if it +// needs. (e.g. because of IO_NEEDS_USING_DECLARATION) +#include +#include + +#ifndef BOOST_IO_STD +# define BOOST_IO_STD ::std:: +#endif + +#if defined(BOOST_NO_STD_LOCALE) || \ + ( BOOST_WORKAROUND(__BORLANDC__, <= 0x564) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT( 0x570 ) ) ) +// some future __BORLANDC__ >0x564 versions might not need this +// 0x570 is Borland's kylix branch +#define BOOST_NO_LOCALE_ISDIGIT +#endif + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570) ) || BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1300)) +#define BOOST_NO_OVERLOAD_FOR_NON_CONST +#endif + +// gcc-2.95's native stringstream is not usable +#if BOOST_WORKAROUND(__GNUC__, < 3) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) +#define BOOST_FORMAT_IGNORE_STRINGSTREAM +#endif + + +// **** Workaround for io streams, stlport and msvc. +#ifdef BOOST_IO_NEEDS_USING_DECLARATION +namespace boost { + using std::char_traits; + using std::basic_ostream; + namespace io { + using std::basic_ostream; + namespace detail { + using std::basic_ios; + using std::basic_ostream; + } + } +#if ! defined(BOOST_NO_STD_LOCALE) + using std::locale; + namespace io { + using std::locale; + namespace detail { + using std::locale; + } + } +#endif // locale +} + // -end N.S. boost +#endif // needs_using_declaration + + +// *** hide std::locale if it doesnt exist. +// this typedef is either std::locale or int, avoids placing ifdefs everywhere +namespace boost { namespace io { namespace detail { +#if ! defined(BOOST_NO_STD_LOCALE) + typedef BOOST_IO_STD locale locale_t; +#else + typedef int locale_t; +#endif +} } } + + +// ---------------------------------------------------------------------------- + +#endif // BOOST_FORMAT_MACROS_DEFAULT_HPP diff --git a/win32/include/boost/format/detail/msvc_disambiguater.hpp b/win32/include/boost/format/detail/msvc_disambiguater.hpp new file mode 100755 index 000000000..9170db9a2 --- /dev/null +++ b/win32/include/boost/format/detail/msvc_disambiguater.hpp @@ -0,0 +1,56 @@ +// ---------------------------------------------------------------------------- +// msvc_disambiguater.hpp : msvc workarounds. (for put_{head|last} overloads) +// the trick was described in boost's list by Aleksey Gurtovoy +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// see http://www.boost.org/libs/format for library home page + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_MSVC_DISAMBIGUATER_HPP +#define BOOST_MSVC_DISAMBIGUATER_HPP + +#if BOOST_WORKAROUND( BOOST_MSVC, <= 1300) || \ + BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) + // this whole header is specifically for msvc up to 7.0 + +#include +#include + +namespace boost { +namespace io { +namespace detail { + +template< class Ch, class Tr, class T > +struct disambiguater +{ + template< typename U > + static void put_head(BOOST_IO_STD basic_ostream& os, group1 const& x, long) + { + os << group_head(x.a1_); + } + static void put_head(BOOST_IO_STD basic_ostream& os, T const& x, int) + { + } + template< typename U > + static void put_last(BOOST_IO_STD basic_ostream& os, group1 const& x, long) + { + os << group_last(x.a1_); + } + static void put_last(BOOST_IO_STD basic_ostream& os, T const& x, int) + { + os << x; + } +}; + +} // namespace detail +} // namespace io +} // namespace boost + +#endif // -BOOST_MSVC + +#endif // -BOOST_MSVC_DISAMBIGUATER_HPP diff --git a/win32/include/boost/format/detail/unset_macros.hpp b/win32/include/boost/format/detail/unset_macros.hpp new file mode 100755 index 000000000..20226f0ec --- /dev/null +++ b/win32/include/boost/format/detail/unset_macros.hpp @@ -0,0 +1,34 @@ +// ---------------------------------------------------------------------------- +// unset_macros.hpp +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// See http://www.boost.org/libs/format for library home page + +// ---------------------------------------------------------------------------- + +// *** Undefine 'local' macros : +#ifdef BOOST_NO_OVERLOAD_FOR_NON_CONST +#undef BOOST_NO_OVERLOAD_FOR_NON_CONST +#endif +#ifdef BOOST_NO_LOCALE_ISDIGIT +#undef BOOST_NO_LOCALE_ISDIGIT +#endif +#ifdef BOOST_IO_STD +#undef BOOST_IO_STD +#endif +#ifdef BOOST_IO_NEEDS_USING_DECLARATION +#undef BOOST_IO_NEEDS_USING_DECLARATION +#endif +#ifdef BOOST_NO_TEMPLATE_STD_STREAM +#undef BOOST_NO_TEMPLATE_STD_STREAM +#endif +#ifdef BOOST_FORMAT_STREAMBUF_DEFINED +#undef BOOST_FORMAT_STREAMBUF_DEFINED +#endif +#ifdef BOOST_FORMAT_OSTREAM_DEFINED +#undef BOOST_FORMAT_OSTREAM_DEFINED +#endif diff --git a/win32/include/boost/format/detail/workarounds_gcc-2_95.hpp b/win32/include/boost/format/detail/workarounds_gcc-2_95.hpp new file mode 100755 index 000000000..86608c96c --- /dev/null +++ b/win32/include/boost/format/detail/workarounds_gcc-2_95.hpp @@ -0,0 +1,162 @@ +// ---------------------------------------------------------------------------- +// workarounds for gcc < 3.0. +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// See http://www.boost.org/libs/format for library home page + + +// ---------------------------------------------------------------------------- + +// There's a lot to do, the stdlib shipped with gcc prior to 3.x +// was terribly non-conforming. +// . defines macros switches +// . supplies template classes basic_foo where gcc only supplies foo. +// i.e : +// - basic_ios from ios +// - basic_ostream from ostream +// - basic_srteambuf from streambuf +// these can be used transparently. (it obviously does not work for wchar_t) +// . specialise CompatAlloc and CompatTraits to wrap gcc-2.95's +// string_char_traits and std::alloc + +#if BOOST_WORKAROUND(__GNUC__, < 3) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) + // only for gcc-2.95's native stdlib + +#ifndef BOOST_FORMAT_WORKAROUNDS_GCC295_H +#define BOOST_FORMAT_WORKAROUNDS_GCC295_H + +// SGI STL doesnt have and others, so we need iostream. +#include +#define BOOST_FORMAT_OSTREAM_DEFINED + +#include +#define BOOST_FORMAT_STREAMBUF_DEFINED + +#define BOOST_NO_TEMPLATE_STD_STREAM + +#ifndef BOOST_IO_STD +# define BOOST_IO_STD std:: +#endif + + + +// *** +// gcc's simple classes turned into standard-like template classes : + +namespace std { + + + // gcc has string_char_traits, it's incomplete. + // we declare a std::char_traits, and specialize CompatTraits<..> on it + // to do what is required + template + class char_traits; // no definition here, we will just use it as a tag. + + template + class basic_streambuf; + + template + class basic_streambuf : public streambuf { + }; + + template > + class basic_ios; + + template + class basic_ios : public ostream { + public: + basic_ios(streambuf * p) : ostream(p) {}; + char fill() const { return ios::fill(); } // gcc returns wchar.. + char fill(char c) { return ios::fill(c); } // gcc takes wchar.. + char widen(char c) { return c; } + char narrow(char c, char def) { return c; } + basic_ios& copyfmt(const ios& right) { + fill(right.fill()); + flags(right.flags() ); + exceptions(right.exceptions()); + width(right.width()); + precision(right.precision()); + return *this; + } + }; + + + typedef ios ios_base; + + template + class basic_ostream; + + template + class basic_ostream : public basic_ios + { + public: + basic_ostream(streambuf * p) : basic_ios (p) {} + }; + +} // namespace std + + +namespace boost { + namespace io { + + + // ** CompatTraits gcc2.95 specialisations ---------------------------- + template + class CompatTraits< ::std::string_char_traits > + : public ::std::string_char_traits + { + public: + typedef CompatTraits compatible_type; + + typedef Ch char_type; + typedef int int_type; + typedef ::std::streampos pos_type; + typedef ::std::streamoff off_type; + + static char_type + to_char_type(const int_type& meta) { + return static_cast(meta); } + static int_type + to_int_type(const char_type& ch) { + return static_cast(static_cast(ch) );} + static bool + eq_int_type(const int_type& left, const int_type& right) { + return left == right; } + static int_type + eof() { + return static_cast(EOF); + } + static int_type + not_eof(const int_type& meta) { + return (meta == eof()) ? 0 : meta; + } + }; + + template + class CompatTraits< ::std::char_traits > { + public: + typedef CompatTraits< ::std::string_char_traits > compatible_type; + }; + + // ** CompatAlloc gcc-2.95 specialisations --------------------------- + template<> + class CompatAlloc< ::std::alloc> + { + public: + typedef ::std::allocator compatible_type; + }; + + } // N.S. io +} // N.S. boost + + + + + +#endif // include guard + +#endif // if workaround diff --git a/win32/include/boost/format/detail/workarounds_stlport.hpp b/win32/include/boost/format/detail/workarounds_stlport.hpp new file mode 100755 index 000000000..92b8cb3a6 --- /dev/null +++ b/win32/include/boost/format/detail/workarounds_stlport.hpp @@ -0,0 +1,42 @@ +// ---------------------------------------------------------------------------- +// workarounds_stlport.hpp : workaround STLport issues +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// see http://www.boost.org/libs/format for library home page + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_MACROS_STLPORT_HPP +#define BOOST_MACROS_STLPORT_HPP + +#if defined(_STLPORT_VERSION) && BOOST_WORKAROUND( BOOST_MSVC, <= 1300) +// msvc-6-stlport fails to find basic_string::append( iterator, iterator) when linking +// might affect other MSwindows compilers +#define BOOST_NO_STRING_APPEND +#endif + +// *** This should go to "boost/config/stdlib/stlport.hpp". + +// If the streams are not native and there are problems with using templates +// accross namespaces, we define some macros to enable a workaround for this. + +// STLport 4.5 +#if !defined(_STLP_OWN_IOSTREAMS) && defined(_STLP_USE_NAMESPACES) && defined(BOOST_NO_USING_TEMPLATE) +# define BOOST_IO_STD +# define BOOST_IO_NEEDS_USING_DECLARATION +#endif + +// STLport 4.0 +#if !defined(__SGI_STL_OWN_IOSTREAMS) && defined(__STL_USE_OWN_NAMESPACE) && defined(BOOST_NO_USING_TEMPLATE) +# define BOOST_IO_STD +# define BOOST_IO_NEEDS_USING_DECLARATION +#endif + + +// ---------------------------------------------------------------------------- + +#endif // BOOST_MACROS_STLPORT_HPP diff --git a/win32/include/boost/format/exceptions.hpp b/win32/include/boost/format/exceptions.hpp new file mode 100755 index 000000000..54b409800 --- /dev/null +++ b/win32/include/boost/format/exceptions.hpp @@ -0,0 +1,103 @@ +// ---------------------------------------------------------------------------- +// boost/format/exceptions.hpp +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. +// +// 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) +// +// +// See http://www.boost.org/libs/format/ for library home page + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_FORMAT_EXCEPTIONS_HPP +#define BOOST_FORMAT_EXCEPTIONS_HPP + + +#include + + +namespace boost { + + namespace io { + +// **** exceptions ----------------------------------------------- + + class format_error : public std::exception + { + public: + format_error() {} + virtual const char *what() const throw() { + return "boost::format_error: " + "format generic failure"; + } + }; + + class bad_format_string : public format_error + { + std::size_t pos_, next_; + public: + bad_format_string(std::size_t pos, std::size_t size) + : pos_(pos), next_(size) {} + std::size_t get_pos() const { return pos_; } + std::size_t get_next() const { return next_; } + virtual const char *what() const throw() { + return "boost::bad_format_string: format-string is ill-formed"; + } + }; + + class too_few_args : public format_error + { + std::size_t cur_, expected_; + public: + too_few_args(std::size_t cur, std::size_t expected) + : cur_(cur), expected_(expected) {} + std::size_t get_cur() const { return cur_; } + std::size_t get_expected() const { return expected_; } + virtual const char *what() const throw() { + return "boost::too_few_args: " + "format-string referred to more arguments than were passed"; + } + }; + + class too_many_args : public format_error + { + std::size_t cur_, expected_; + public: + too_many_args(std::size_t cur, std::size_t expected) + : cur_(cur), expected_(expected) {} + std::size_t get_cur() const { return cur_; } + std::size_t get_expected() const { return expected_; } + virtual const char *what() const throw() { + return "boost::too_many_args: " + "format-string referred to less arguments than were passed"; + } + }; + + + class out_of_range : public format_error + { + int index_, beg_, end_; // range is [ beg, end [ + public: + out_of_range(int index, int beg, int end) + : index_(index), beg_(beg), end_(end) {} + int get_index() const { return index_; } + int get_beg() const { return beg_; } + int get_end() const { return end_; } + virtual const char *what() const throw() { + return "boost::out_of_range: " + "tried to refer to an argument (or item) number which" + " is out of range, according to the format string"; + } + }; + + + } // namespace io + +} // namespace boost + + +#endif // BOOST_FORMAT_EXCEPTIONS_HPP diff --git a/win32/include/boost/format/feed_args.hpp b/win32/include/boost/format/feed_args.hpp new file mode 100755 index 000000000..5146e1464 --- /dev/null +++ b/win32/include/boost/format/feed_args.hpp @@ -0,0 +1,277 @@ +// ---------------------------------------------------------------------------- +// feed_args.hpp : functions for processing each argument +// (feed, feed_manip, and distribute) +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// See http://www.boost.org/libs/format for library home page + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_FORMAT_FEED_ARGS_HPP +#define BOOST_FORMAT_FEED_ARGS_HPP + +#include +#include +#include + +#include +#include +#include + +namespace boost { +namespace io { +namespace detail { + + template + void mk_str( std::basic_string & res, + const Ch * beg, + typename std::basic_string::size_type size, + std::streamsize w, + const Ch fill_char, + std::ios_base::fmtflags f, + const Ch prefix_space, // 0 if no space-padding + bool center) + // applies centered/left/right padding to the string [beg, beg+size[ + // Effects : the result is placed in res. + { + typedef typename std::basic_string::size_type size_type; + res.resize(0); + if(w<=0 || static_cast(w) <=size) { + // no need to pad. + res.reserve(size + !!prefix_space); + if(prefix_space) + res.append(1, prefix_space); + if (size) + res.append(beg, size); + } + else { + std::streamsize n=static_cast(w-size-!!prefix_space); + std::streamsize n_after = 0, n_before = 0; + res.reserve(static_cast(w)); // allocate once for the 2 inserts + if(center) + n_after = n/2, n_before = n - n_after; + else + if(f & std::ios_base::left) + n_after = n; + else + n_before = n; + // now make the res string : + if(n_before) res.append(static_cast(n_before), fill_char); + if(prefix_space) + res.append(1, prefix_space); + if (size) + res.append(beg, size); + if(n_after) res.append(static_cast(n_after), fill_char); + } + } // -mk_str(..) + + +#if BOOST_WORKAROUND( BOOST_MSVC, <= 1300) || \ + BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) +// MSVC needs to be tricked to disambiguate this simple overload.. +// the trick is in "boost/format/msvc_disambiguater.hpp" + + template< class Ch, class Tr, class T> inline + void put_head (BOOST_IO_STD basic_ostream & os, const T& x ) { + disambiguater::put_head(os, x, 1L); + } + template< class Ch, class Tr, class T> inline + void put_last (BOOST_IO_STD basic_ostream & os, const T& x ) { + disambiguater::put_last(os, x, 1L); + } + +#else + + template< class Ch, class Tr, class T> inline + void put_head (BOOST_IO_STD basic_ostream &, const T& ) { + } + + template< class Ch, class Tr, class T> inline + void put_head( BOOST_IO_STD basic_ostream & os, const group1& x ) { + os << group_head(x.a1_); // send the first N-1 items, not the last + } + + template< class Ch, class Tr, class T> inline + void put_last( BOOST_IO_STD basic_ostream & os, const T& x ) { + os << x ; + } + + template< class Ch, class Tr, class T> inline + void put_last( BOOST_IO_STD basic_ostream & os, const group1& x ) { + os << group_last(x.a1_); // this selects the last element + } + +#ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST + template< class Ch, class Tr, class T> inline + void put_head( BOOST_IO_STD basic_ostream &, T& ) { + } + + template< class Ch, class Tr, class T> inline + void put_last( BOOST_IO_STD basic_ostream & os, T& x) { + os << x ; + } +#endif +#endif // -msvc workaround + + + template< class Ch, class Tr, class Alloc, class T> + void put( T x, + const format_item& specs, + typename basic_format::string_type& res, + typename basic_format::internal_streambuf_t & buf, + io::detail::locale_t *loc_p = NULL) + { +#ifdef BOOST_MSVC + // If std::min or std::max are already instantiated + // at this point then we get a blizzard of warning messages when we call + // those templates with std::size_t as arguments. Weird and very annoyning... +#pragma warning(push) +#pragma warning(disable:4267) +#endif + // does the actual conversion of x, with given params, into a string + // using the supplied stringbuf. + + typedef typename basic_format::string_type string_type; + typedef typename basic_format::format_item_t format_item_t; + typedef typename string_type::size_type size_type; + + basic_oaltstringstream oss( &buf); + specs.fmtstate_.apply_on(oss, loc_p); + + // the stream format state can be modified by manipulators in the argument : + put_head( oss, x ); + // in case x is a group, apply the manip part of it, + // in order to find width + + const std::ios_base::fmtflags fl=oss.flags(); + const bool internal = (fl & std::ios_base::internal) != 0; + const std::streamsize w = oss.width(); + const bool two_stepped_padding= internal && (w!=0); + + res.resize(0); + if(! two_stepped_padding) { + if(w>0) // handle padding via mk_str, not natively in stream + oss.width(0); + put_last( oss, x); + const Ch * res_beg = buf.pbase(); + Ch prefix_space = 0; + if(specs.pad_scheme_ & format_item_t::spacepad) + if(buf.pcount()== 0 || + (res_beg[0] !=oss.widen('+') && res_beg[0] !=oss.widen('-') )) + prefix_space = oss.widen(' '); + size_type res_size = (std::min)( + static_cast(specs.truncate_ - !!prefix_space), + buf.pcount() ); + mk_str(res, res_beg, res_size, w, oss.fill(), fl, + prefix_space, (specs.pad_scheme_ & format_item_t::centered) !=0 ); + } + else { // 2-stepped padding + // internal can be implied by zeropad, or user-set. + // left, right, and centered alignment overrule internal, + // but spacepad or truncate might be mixed with internal (using manipulator) + put_last( oss, x); // may pad + const Ch * res_beg = buf.pbase(); + size_type res_size = buf.pcount(); + bool prefix_space=false; + if(specs.pad_scheme_ & format_item_t::spacepad) + if(buf.pcount()== 0 || + (res_beg[0] !=oss.widen('+') && res_beg[0] !=oss.widen('-') )) + prefix_space = true; + if(res_size == static_cast(w) && w<=specs.truncate_ && !prefix_space) { + // okay, only one thing was printed and padded, so res is fine + res.assign(res_beg, res_size); + } + else { // length w exceeded + // either it was multi-output with first output padding up all width.. + // either it was one big arg and we are fine. + // Note that res_size oss2( &buf); + specs.fmtstate_.apply_on(oss2, loc_p); + put_head( oss2, x ); + + oss2.width(0); + if(prefix_space) + oss2 << ' '; + put_last(oss2, x ); + if(buf.pcount()==0 && specs.pad_scheme_ & format_item_t::spacepad) { + prefix_space =true; + oss2 << ' '; + } + // we now have the minimal-length output + const Ch * tmp_beg = buf.pbase(); + size_type tmp_size = (std::min)(static_cast(specs.truncate_), + buf.pcount() ); + + + if(static_cast(w) <= tmp_size) { + // minimal length is already >= w, so no padding (cool!) + res.assign(tmp_beg, tmp_size); + } + else { // hum.. we need to pad (multi_output, or spacepad present) + //find where we should pad + size_type sz = (std::min)(res_size + (prefix_space ? 1 : 0), tmp_size); + size_type i = prefix_space; + for(; i=tmp_size) i=prefix_space; + res.assign(tmp_beg, i); + std::streamsize d = w - static_cast(tmp_size); + BOOST_ASSERT(d>0); + res.append(static_cast( d ), oss2.fill()); + res.append(tmp_beg+i, tmp_size-i); + BOOST_ASSERT(i+(tmp_size-i)+(std::max)(d,(std::streamsize)0) + == static_cast(w)); + BOOST_ASSERT(res.size() == static_cast(w)); + } + } + } + buf.clear_buffer(); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + } // end- put(..) + + + template< class Ch, class Tr, class Alloc, class T> + void distribute (basic_format& self, T x) { + // call put(x, ..) on every occurence of the current argument : + if(self.cur_arg_ >= self.num_args_) { + if( self.exceptions() & too_many_args_bit ) + boost::throw_exception(too_many_args(self.cur_arg_, self.num_args_)); + else return; + } + for(unsigned long i=0; i < self.items_.size(); ++i) { + if(self.items_[i].argN_ == self.cur_arg_) { + put (x, self.items_[i], self.items_[i].res_, + self.buf_, boost::get_pointer(self.loc_) ); + } + } + } + + template + basic_format& + feed (basic_format& self, T x) { + if(self.dumped_) self.clear(); + distribute (self, x); + ++self.cur_arg_; + if(self.bound_.size() != 0) { + while( self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_] ) + ++self.cur_arg_; + } + return self; + } + +} // namespace detail +} // namespace io +} // namespace boost + + +#endif // BOOST_FORMAT_FEED_ARGS_HPP diff --git a/win32/include/boost/format/format_class.hpp b/win32/include/boost/format/format_class.hpp new file mode 100755 index 000000000..32ae447e2 --- /dev/null +++ b/win32/include/boost/format/format_class.hpp @@ -0,0 +1,143 @@ +// ---------------------------------------------------------------------------- +// format_class.hpp : class interface +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// See http://www.boost.org/libs/format for library home page + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_FORMAT_CLASS_HPP +#define BOOST_FORMAT_CLASS_HPP + + +#include +#include + +#include // to store locale when needed + +#include +#include +#include +#include + +namespace boost { + + template + class basic_format + { + typedef typename io::CompatTraits::compatible_type compat_traits; + public: + typedef Ch CharT; // borland fails in operator% if we use Ch and Tr directly + typedef std::basic_string string_type; + typedef typename string_type::size_type size_type; + typedef io::detail::format_item format_item_t; + typedef io::basic_altstringbuf internal_streambuf_t; + + + explicit basic_format(const Ch* str=NULL); + explicit basic_format(const string_type& s); + basic_format(const basic_format& x); + basic_format& operator= (const basic_format& x); + void swap(basic_format& x); + +#if !defined(BOOST_NO_STD_LOCALE) + explicit basic_format(const Ch* str, const std::locale & loc); + explicit basic_format(const string_type& s, const std::locale & loc); +#endif + io::detail::locale_t getloc() const; + + basic_format& clear(); // empty all converted string buffers (except bound items) + basic_format& clear_binds(); // unbind all bound items, and call clear() + basic_format& parse(const string_type&); // resets buffers and parse a new format string + + // ** formatted result ** // + size_type size() const; // sum of the current string pieces sizes + string_type str() const; // final string + + // ** arguments passing ** // + template + basic_format& operator%(const T& x) + { return io::detail::feed(*this,x); } + +#ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST + template basic_format& operator%(T& x) + { return io::detail::feed(*this,x); } +#endif + + // ** object modifying **// + template + basic_format& bind_arg(int argN, const T& val) + { return io::detail::bind_arg_body(*this, argN, val); } + basic_format& clear_bind(int argN); + template + basic_format& modify_item(int itemN, T manipulator) + { return io::detail::modify_item_body (*this, itemN, manipulator);} + + // Choosing which errors will throw exceptions : + unsigned char exceptions() const; + unsigned char exceptions(unsigned char newexcept); + +#if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) \ + && !BOOST_WORKAROUND(__BORLANDC__, <= 0x570) \ + && !BOOST_WORKAROUND( _CRAYC, != 0) \ + && !BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) + // use friend templates and private members only if supported + +#ifndef BOOST_NO_TEMPLATE_STD_STREAM + template + friend std::basic_ostream & + operator<<( std::basic_ostream & , + const basic_format& ); +#else + template + friend std::ostream & + operator<<( std::ostream & , + const basic_format& ); +#endif + + template + friend basic_format& + io::detail::feed (basic_format&, T); + + template friend + void io::detail::distribute (basic_format&, T); + + template friend + basic_format& + io::detail::modify_item_body (basic_format&, int, T); + + template friend + basic_format& + io::detail::bind_arg_body (basic_format&, int, const T&); + + private: +#endif + typedef io::detail::stream_format_state stream_format_state; + // flag bits, used for style_ + enum style_values { ordered = 1, // set only if all directives are positional + special_needs = 4 }; + + void make_or_reuse_data(std::size_t nbitems);// used for (re-)initialisation + + // member data --------------------------------------------// + std::vector items_; // each '%..' directive leads to a format_item + std::vector bound_; // stores which arguments were bound. size() == 0 || num_args + + int style_; // style of format-string : positional or not, etc + int cur_arg_; // keep track of wich argument is current + int num_args_; // number of expected arguments + mutable bool dumped_; // true only after call to str() or << + string_type prefix_; // piece of string to insert before first item + unsigned char exceptions_; + internal_streambuf_t buf_; // the internal stream buffer. + boost::optional loc_; + }; // class basic_format + +} // namespace boost + + +#endif // BOOST_FORMAT_CLASS_HPP diff --git a/win32/include/boost/format/format_fwd.hpp b/win32/include/boost/format/format_fwd.hpp new file mode 100755 index 000000000..60e36bbd8 --- /dev/null +++ b/win32/include/boost/format/format_fwd.hpp @@ -0,0 +1,49 @@ +// ---------------------------------------------------------------------------- +// format_fwd.hpp : forward declarations +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// See http://www.boost.org/libs/format for library home page + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_FORMAT_FWD_HPP +#define BOOST_FORMAT_FWD_HPP + +#include +#include + +#include + +namespace boost { + + template , class Alloc = std::allocator > +#else + class Tr = std::string_char_traits, class Alloc = std::alloc > +#endif + class basic_format; + + typedef basic_format format; + +#if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_STD_WSTREAMBUF) \ + && !defined(BOOST_FORMAT_IGNORE_STRINGSTREAM) + typedef basic_format wformat; +#endif + + namespace io { + enum format_error_bits { bad_format_string_bit = 1, + too_few_args_bit = 2, too_many_args_bit = 4, + out_of_range_bit = 8, + all_error_bits = 255, no_error_bits=0 }; + + } // namespace io + +} // namespace boost + +#endif // BOOST_FORMAT_FWD_HPP diff --git a/win32/include/boost/format/format_implementation.hpp b/win32/include/boost/format/format_implementation.hpp new file mode 100755 index 000000000..6c6505b73 --- /dev/null +++ b/win32/include/boost/format/format_implementation.hpp @@ -0,0 +1,288 @@ +// ---------------------------------------------------------------------------- +// format_implementation.hpp Implementation of the basic_format class +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// See http://www.boost.org/libs/format for library home page + + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_FORMAT_IMPLEMENTATION_HPP +#define BOOST_FORMAT_IMPLEMENTATION_HPP + +#include +#include +#include +#include +#include // std::swap + +namespace boost { + +// --- basic_format implementation -----------------------------------------// + + template< class Ch, class Tr, class Alloc> + basic_format:: basic_format(const Ch* s) + : style_(0), cur_arg_(0), num_args_(0), dumped_(false), + exceptions_(io::all_error_bits) + { + if( s) + parse( s ); + } + +#if !defined(BOOST_NO_STD_LOCALE) + template< class Ch, class Tr, class Alloc> + basic_format:: basic_format(const Ch* s, const std::locale & loc) + : style_(0), cur_arg_(0), num_args_(0), dumped_(false), + loc_(loc), exceptions_(io::all_error_bits) + { + if(s) parse( s ); + } + + template< class Ch, class Tr, class Alloc> + basic_format:: basic_format(const string_type& s, const std::locale & loc) + : style_(0), cur_arg_(0), num_args_(0), dumped_(false), + loc_(loc), exceptions_(io::all_error_bits) + { + parse(s); + } +#endif // ! BOOST_NO_STD_LOCALE + template< class Ch, class Tr, class Alloc> + io::detail::locale_t basic_format:: + getloc() const { + return loc_ ? loc_.get() : io::detail::locale_t(); + } + + template< class Ch, class Tr, class Alloc> + basic_format:: basic_format(const string_type& s) + : style_(0), cur_arg_(0), num_args_(0), dumped_(false), + exceptions_(io::all_error_bits) + { + parse(s); + } + + template< class Ch, class Tr, class Alloc> // just don't copy the buf_ member + basic_format:: basic_format(const basic_format& x) + : items_(x.items_), bound_(x.bound_), style_(x.style_), + cur_arg_(x.cur_arg_), num_args_(x.num_args_), dumped_(false), + prefix_(x.prefix_), exceptions_(x.exceptions_), loc_(x.loc_) + { + } + + template< class Ch, class Tr, class Alloc> // just don't copy the buf_ member + basic_format& basic_format:: + operator= (const basic_format& x) { + if(this == &x) + return *this; + (basic_format(x)).swap(*this); + return *this; + } + template< class Ch, class Tr, class Alloc> + void basic_format:: + swap (basic_format & x) { + std::swap(exceptions_, x.exceptions_); + std::swap(style_, x.style_); + std::swap(cur_arg_, x.cur_arg_); + std::swap(num_args_, x.num_args_); + std::swap(dumped_, x.dumped_); + + items_.swap(x.items_); + prefix_.swap(x.prefix_); + bound_.swap(x.bound_); + } + + template< class Ch, class Tr, class Alloc> + unsigned char basic_format:: exceptions() const { + return exceptions_; + } + + template< class Ch, class Tr, class Alloc> + unsigned char basic_format:: exceptions(unsigned char newexcept) { + unsigned char swp = exceptions_; + exceptions_ = newexcept; + return swp; + } + + template + void basic_format:: + make_or_reuse_data (std::size_t nbitems) { +#if !defined(BOOST_NO_STD_LOCALE) + Ch fill = ( BOOST_USE_FACET(std::ctype, getloc()) ). widen(' '); +#else + Ch fill = ' '; +#endif + if(items_.size() == 0) + items_.assign( nbitems, format_item_t(fill) ); + else { + if(nbitems>items_.size()) + items_.resize(nbitems, format_item_t(fill)); + bound_.resize(0); + for(std::size_t i=0; i < nbitems; ++i) + items_[i].reset(fill); // strings are resized, instead of reallocated + } + prefix_.resize(0); + } + + template< class Ch, class Tr, class Alloc> + basic_format& basic_format:: + clear () { + // empty the string buffers (except bound arguments) + // and make the format object ready for formatting a new set of arguments + + BOOST_ASSERT( bound_.size()==0 || num_args_ == static_cast(bound_.size()) ); + + for(unsigned long i=0; i + basic_format& basic_format:: + clear_binds () { + // remove all binds, then clear() + bound_.resize(0); + clear(); + return *this; + } + + template< class Ch, class Tr, class Alloc> + basic_format& basic_format:: + clear_bind (int argN) { + // remove the bind of ONE argument then clear() + if(argN<1 || argN > num_args_ || bound_.size()==0 || !bound_[argN-1] ) { + if( exceptions() & io::out_of_range_bit) + boost::throw_exception(io::out_of_range(argN, 1, num_args_+1 ) ); + else return *this; + } + bound_[argN-1]=false; + clear(); + return *this; + } + + template< class Ch, class Tr, class Alloc> + typename basic_format::string_type + basic_format:: + str () const { + if(items_.size()==0) + return prefix_; + if( cur_arg_ < num_args_) + if( exceptions() & io::too_few_args_bit ) + // not enough variables supplied + boost::throw_exception(io::too_few_args(cur_arg_, num_args_)); + + unsigned long i; + string_type res; + res.reserve(size()); + res += prefix_; + for(i=0; i < items_.size(); ++i) { + const format_item_t& item = items_[i]; + res += item.res_; + if( item.argN_ == format_item_t::argN_tabulation) { + BOOST_ASSERT( item.pad_scheme_ & format_item_t::tabulation); + if( static_cast(item.fmtstate_.width_) > res.size() ) + res.append( static_cast(item.fmtstate_.width_) - res.size(), + item.fmtstate_.fill_ ); + } + res += item.appendix_; + } + dumped_=true; + return res; + } + template< class Ch, class Tr, class Alloc> + typename std::basic_string::size_type basic_format:: + size () const { +#ifdef BOOST_MSVC + // If std::min or std::max are already instantiated + // at this point then we get a blizzard of warning messages when we call + // those templates with std::size_t as arguments. Weird and very annoyning... +#pragma warning(push) +#pragma warning(disable:4267) +#endif + BOOST_USING_STD_MAX(); + size_type sz = prefix_.size(); + unsigned long i; + for(i=0; i < items_.size(); ++i) { + const format_item_t& item = items_[i]; + sz += item.res_.size(); + if( item.argN_ == format_item_t::argN_tabulation) + sz = max BOOST_PREVENT_MACRO_SUBSTITUTION (sz, + static_cast(item.fmtstate_.width_) ); + sz += item.appendix_.size(); + } + return sz; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + } + +namespace io { +namespace detail { + + template + basic_format& + bind_arg_body (basic_format& self, int argN, const T& val) { + // bind one argument to a fixed value + // this is persistent over clear() calls, thus also over str() and << + if(self.dumped_) + self.clear(); // needed because we will modify cur_arg_ + if(argN<1 || argN > self.num_args_) { + if( self.exceptions() & io::out_of_range_bit ) + boost::throw_exception(io::out_of_range(argN, 1, self.num_args_+1 ) ); + else return self; + } + if(self.bound_.size()==0) + self.bound_.assign(self.num_args_,false); + else + BOOST_ASSERT( self.num_args_ == static_cast(self.bound_.size()) ); + int o_cur_arg = self.cur_arg_; + self.cur_arg_ = argN-1; // arrays begin at 0 + + self.bound_[self.cur_arg_]=false; // if already set, we unset and re-sets.. + self.operator%(val); // put val at the right place, because cur_arg is set + + + // Now re-position cur_arg before leaving : + self.cur_arg_ = o_cur_arg; + self.bound_[argN-1]=true; + if(self.cur_arg_ == argN-1 ) { + // hum, now this arg is bound, so move to next free arg + while(self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_]) + ++self.cur_arg_; + } + // In any case, we either have all args, or are on a non-binded arg : + BOOST_ASSERT( self.cur_arg_ >= self.num_args_ || ! self.bound_[self.cur_arg_]); + return self; + } + + template basic_format& + modify_item_body (basic_format& self, int itemN, T manipulator) { + // applies a manipulator to the format_item describing a given directive. + // this is a permanent change, clear or reset won't cancel that. + if(itemN<1 || itemN > static_cast(self.items_.size() )) { + if( self.exceptions() & io::out_of_range_bit ) + boost::throw_exception(io::out_of_range(itemN, 1, static_cast(self.items_.size()) )); + else return self; + } + self.items_[itemN-1].fmtstate_. template apply_manip ( manipulator ); + return self; + } + +} // namespace detail +} // namespace io +} // namespace boost + + + +#endif // BOOST_FORMAT_IMPLEMENTATION_HPP diff --git a/win32/include/boost/format/free_funcs.hpp b/win32/include/boost/format/free_funcs.hpp new file mode 100755 index 000000000..76b592a84 --- /dev/null +++ b/win32/include/boost/format/free_funcs.hpp @@ -0,0 +1,70 @@ +// ---------------------------------------------------------------------------- +// free_funcs.hpp : implementation of the free functions of boost::format +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// See http://www.boost.org/libs/format for library home page + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_FORMAT_FUNCS_HPP +#define BOOST_FORMAT_FUNCS_HPP + +#include +#include + +namespace boost { + + template inline + std::basic_string str(const basic_format& f) { + // adds up all pieces of strings and converted items, and return the formatted string + return f.str(); + } + namespace io { + using ::boost::str; // keep compatibility with when it was defined in this N.S. + } // - namespace io + +#ifndef BOOST_NO_TEMPLATE_STD_STREAM + template + std::basic_ostream & + operator<<( std::basic_ostream & os, + const basic_format& f) +#else + template + std::ostream & + operator<<( std::ostream & os, + const basic_format& f) +#endif + // effect: "return os << str(f);" but we can do it faster + { + typedef boost::basic_format format_t; + if(f.items_.size()==0) + os << f.prefix_; + else { + if(f.cur_arg_ < f.num_args_) + if( f.exceptions() & io::too_few_args_bit ) + // not enough variables supplied + boost::throw_exception(io::too_few_args(f.cur_arg_, f.num_args_)); + if(f.style_ & format_t::special_needs) + os << f.str(); + else { + // else we dont have to count chars output, so we dump directly to os : + os << f.prefix_; + for(unsigned long i=0; i + + +namespace boost { +namespace io { + + +namespace detail { + + +// empty group, but useful even though. +struct group0 +{ + group0() {} +}; + +template +inline +BOOST_IO_STD basic_ostream& +operator << ( BOOST_IO_STD basic_ostream& os, + const group0& ) +{ + return os; +} + +template +struct group1 +{ + T1 a1_; + group1(T1 a1) + : a1_(a1) + {} +private: + group1& operator=(const group1&); +}; + +template +inline +BOOST_IO_STD basic_ostream& +operator << (BOOST_IO_STD basic_ostream& os, + const group1& x) +{ + os << x.a1_; + return os; +} + + + + +template +struct group2 +{ + T1 a1_; + T2 a2_; + group2(T1 a1,T2 a2) + : a1_(a1),a2_(a2) + {} +private: + group2& operator=(const group2&); +}; + +template +inline +BOOST_IO_STD basic_ostream& +operator << (BOOST_IO_STD basic_ostream& os, + const group2& x) +{ + os << x.a1_<< x.a2_; + return os; +} + +template +struct group3 +{ + T1 a1_; + T2 a2_; + T3 a3_; + group3(T1 a1,T2 a2,T3 a3) + : a1_(a1),a2_(a2),a3_(a3) + {} +private: + group3& operator=(const group3&); +}; + +template +inline +BOOST_IO_STD basic_ostream& +operator << (BOOST_IO_STD basic_ostream& os, + const group3& x) +{ + os << x.a1_<< x.a2_<< x.a3_; + return os; +} + +template +struct group4 +{ + T1 a1_; + T2 a2_; + T3 a3_; + T4 a4_; + group4(T1 a1,T2 a2,T3 a3,T4 a4) + : a1_(a1),a2_(a2),a3_(a3),a4_(a4) + {} +private: + group4& operator=(const group4&); +}; + +template +inline +BOOST_IO_STD basic_ostream& +operator << (BOOST_IO_STD basic_ostream& os, + const group4& x) +{ + os << x.a1_<< x.a2_<< x.a3_<< x.a4_; + return os; +} + +template +struct group5 +{ + T1 a1_; + T2 a2_; + T3 a3_; + T4 a4_; + T5 a5_; + group5(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) + : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5) + {} +}; + +template +inline +BOOST_IO_STD basic_ostream& +operator << (BOOST_IO_STD basic_ostream& os, + const group5& x) +{ + os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_; + return os; +} + +template +struct group6 +{ + T1 a1_; + T2 a2_; + T3 a3_; + T4 a4_; + T5 a5_; + T6 a6_; + group6(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6) + : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6) + {} +}; + +template +inline +BOOST_IO_STD basic_ostream& +operator << (BOOST_IO_STD basic_ostream& os, + const group6& x) +{ + os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_; + return os; +} + +template +struct group7 +{ + T1 a1_; + T2 a2_; + T3 a3_; + T4 a4_; + T5 a5_; + T6 a6_; + T7 a7_; + group7(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7) + : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7) + {} +}; + +template +inline +BOOST_IO_STD basic_ostream& +operator << (BOOST_IO_STD basic_ostream& os, + const group7& x) +{ + os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_; + return os; +} + +template +struct group8 +{ + T1 a1_; + T2 a2_; + T3 a3_; + T4 a4_; + T5 a5_; + T6 a6_; + T7 a7_; + T8 a8_; + group8(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8) + : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8) + {} +}; + +template +inline +BOOST_IO_STD basic_ostream& +operator << (BOOST_IO_STD basic_ostream& os, + const group8& x) +{ + os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_; + return os; +} + +template +struct group9 +{ + T1 a1_; + T2 a2_; + T3 a3_; + T4 a4_; + T5 a5_; + T6 a6_; + T7 a7_; + T8 a8_; + T9 a9_; + group9(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9) + : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8),a9_(a9) + {} +}; + +template +inline +BOOST_IO_STD basic_ostream& +operator << (BOOST_IO_STD basic_ostream& os, + const group9& x) +{ + os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_<< x.a9_; + return os; +} + +template +struct group10 +{ + T1 a1_; + T2 a2_; + T3 a3_; + T4 a4_; + T5 a5_; + T6 a6_; + T7 a7_; + T8 a8_; + T9 a9_; + T10 a10_; + group10(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9,T10 a10) + : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8),a9_(a9),a10_(a10) + {} +}; + +template +inline +BOOST_IO_STD basic_ostream& +operator << (BOOST_IO_STD basic_ostream& os, + const group10& x) +{ + os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_<< x.a9_<< x.a10_; + return os; +} + + + + +template +inline +group1 +group_head( group2 const& x) +{ + return group1 (x.a1_); +} + +template +inline +group1 +group_last( group2 const& x) +{ + return group1 (x.a2_); +} + + + +template +inline +group2 +group_head( group3 const& x) +{ + return group2 (x.a1_,x.a2_); +} + +template +inline +group1 +group_last( group3 const& x) +{ + return group1 (x.a3_); +} + + + +template +inline +group3 +group_head( group4 const& x) +{ + return group3 (x.a1_,x.a2_,x.a3_); +} + +template +inline +group1 +group_last( group4 const& x) +{ + return group1 (x.a4_); +} + + + +template +inline +group4 +group_head( group5 const& x) +{ + return group4 (x.a1_,x.a2_,x.a3_,x.a4_); +} + +template +inline +group1 +group_last( group5 const& x) +{ + return group1 (x.a5_); +} + + + +template +inline +group5 +group_head( group6 const& x) +{ + return group5 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_); +} + +template +inline +group1 +group_last( group6 const& x) +{ + return group1 (x.a6_); +} + + + +template +inline +group6 +group_head( group7 const& x) +{ + return group6 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_); +} + +template +inline +group1 +group_last( group7 const& x) +{ + return group1 (x.a7_); +} + + + +template +inline +group7 +group_head( group8 const& x) +{ + return group7 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_); +} + +template +inline +group1 +group_last( group8 const& x) +{ + return group1 (x.a8_); +} + + + +template +inline +group8 +group_head( group9 const& x) +{ + return group8 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_,x.a8_); +} + +template +inline +group1 +group_last( group9 const& x) +{ + return group1 (x.a9_); +} + + + +template +inline +group9 +group_head( group10 const& x) +{ + return group9 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_,x.a8_,x.a9_); +} + +template +inline +group1 +group_last( group10 const& x) +{ + return group1 (x.a10_); +} + + + + + +} // namespace detail + + + +// helper functions + + +inline detail::group1< detail::group0 > +group() { return detail::group1< detail::group0 > ( detail::group0() ); } + +template +inline +detail::group1< detail::group2 > + group(T1 a1, Var const& var) +{ + return detail::group1< detail::group2 > + ( detail::group2 + (a1, var) + ); +} + +template +inline +detail::group1< detail::group3 > + group(T1 a1,T2 a2, Var const& var) +{ + return detail::group1< detail::group3 > + ( detail::group3 + (a1,a2, var) + ); +} + +template +inline +detail::group1< detail::group4 > + group(T1 a1,T2 a2,T3 a3, Var const& var) +{ + return detail::group1< detail::group4 > + ( detail::group4 + (a1,a2,a3, var) + ); +} + +template +inline +detail::group1< detail::group5 > + group(T1 a1,T2 a2,T3 a3,T4 a4, Var const& var) +{ + return detail::group1< detail::group5 > + ( detail::group5 + (a1,a2,a3,a4, var) + ); +} + +template +inline +detail::group1< detail::group6 > + group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5, Var const& var) +{ + return detail::group1< detail::group6 > + ( detail::group6 + (a1,a2,a3,a4,a5, var) + ); +} + +template +inline +detail::group1< detail::group7 > + group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6, Var const& var) +{ + return detail::group1< detail::group7 > + ( detail::group7 + (a1,a2,a3,a4,a5,a6, var) + ); +} + +template +inline +detail::group1< detail::group8 > + group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7, Var const& var) +{ + return detail::group1< detail::group8 > + ( detail::group8 + (a1,a2,a3,a4,a5,a6,a7, var) + ); +} + +template +inline +detail::group1< detail::group9 > + group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8, Var const& var) +{ + return detail::group1< detail::group9 > + ( detail::group9 + (a1,a2,a3,a4,a5,a6,a7,a8, var) + ); +} + +template +inline +detail::group1< detail::group10 > + group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9, Var const& var) +{ + return detail::group1< detail::group10 > + ( detail::group10 + (a1,a2,a3,a4,a5,a6,a7,a8,a9, var) + ); +} + + +#ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST + +template +inline +detail::group1< detail::group2 > + group(T1 a1, Var& var) +{ + return detail::group1< detail::group2 > + ( detail::group2 + (a1, var) + ); +} + +template +inline +detail::group1< detail::group3 > + group(T1 a1,T2 a2, Var& var) +{ + return detail::group1< detail::group3 > + ( detail::group3 + (a1,a2, var) + ); +} + +template +inline +detail::group1< detail::group4 > + group(T1 a1,T2 a2,T3 a3, Var& var) +{ + return detail::group1< detail::group4 > + ( detail::group4 + (a1,a2,a3, var) + ); +} + +template +inline +detail::group1< detail::group5 > + group(T1 a1,T2 a2,T3 a3,T4 a4, Var& var) +{ + return detail::group1< detail::group5 > + ( detail::group5 + (a1,a2,a3,a4, var) + ); +} + +template +inline +detail::group1< detail::group6 > + group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5, Var& var) +{ + return detail::group1< detail::group6 > + ( detail::group6 + (a1,a2,a3,a4,a5, var) + ); +} + +template +inline +detail::group1< detail::group7 > + group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6, Var& var) +{ + return detail::group1< detail::group7 > + ( detail::group7 + (a1,a2,a3,a4,a5,a6, var) + ); +} + +template +inline +detail::group1< detail::group8 > + group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7, Var& var) +{ + return detail::group1< detail::group8 > + ( detail::group8 + (a1,a2,a3,a4,a5,a6,a7, var) + ); +} + +template +inline +detail::group1< detail::group9 > + group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8, Var& var) +{ + return detail::group1< detail::group9 > + ( detail::group9 + (a1,a2,a3,a4,a5,a6,a7,a8, var) + ); +} + +template +inline +detail::group1< detail::group10 > + group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9, Var& var) +{ + return detail::group1< detail::group10 > + ( detail::group10 + (a1,a2,a3,a4,a5,a6,a7,a8,a9, var) + ); +} + + +#endif // - BOOST_NO_OVERLOAD_FOR_NON_CONST + + +} // namespace io + +} // namespace boost + + +#endif // BOOST_FORMAT_GROUP_HPP diff --git a/win32/include/boost/format/internals.hpp b/win32/include/boost/format/internals.hpp new file mode 100755 index 000000000..9455e0b0a --- /dev/null +++ b/win32/include/boost/format/internals.hpp @@ -0,0 +1,201 @@ +// ---------------------------------------------------------------------------- +// internals.hpp : internal structs : stream_format_state, format_item. +// included by format.hpp +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// See http://www.boost.org/libs/format for library home page + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_FORMAT_INTERNALS_HPP +#define BOOST_FORMAT_INTERNALS_HPP + + +#include +#include +#include +#include +#include +#include // used as a dummy stream + +namespace boost { +namespace io { +namespace detail { + + +//---- stream_format_state --------------------------------------------------// + +// set of params that define the format state of a stream + template + struct stream_format_state + { + typedef BOOST_IO_STD basic_ios basic_ios; + + stream_format_state(Ch fill) { reset(fill); } +// stream_format_state(const basic_ios& os) { set_by_stream(os); } + + void reset(Ch fill); //- sets to default state. + void set_by_stream(const basic_ios& os); //- sets to os's state. + void apply_on(basic_ios & os, //- applies format_state to the stream + boost::io::detail::locale_t * loc_default = 0) const; + template + void apply_manip(T manipulator) //- modifies state by applying manipulator + { apply_manip_body( *this, manipulator) ; } + + // --- data --- + std::streamsize width_; + std::streamsize precision_; + Ch fill_; + std::ios_base::fmtflags flags_; + std::ios_base::iostate rdstate_; + std::ios_base::iostate exceptions_; + boost::optional loc_; + }; + + +//---- format_item ---------------------------------------------------------// + +// stores all parameters that can be specified in format strings + template + struct format_item + { + enum pad_values { zeropad = 1, spacepad =2, centered=4, tabulation = 8 }; + // 1. if zeropad is set, all other bits are not, + // 2. if tabulation is set, all others are not. + // centered and spacepad can be mixed freely. + enum arg_values { argN_no_posit = -1, // non-positional directive. will set argN later + argN_tabulation = -2, // tabulation directive. (no argument read) + argN_ignored = -3 // ignored directive. (no argument read) + }; + typedef BOOST_IO_STD basic_ios basic_ios; + typedef detail::stream_format_state stream_format_state; + typedef ::std::basic_string string_type; + + format_item(Ch fill) :argN_(argN_no_posit), fmtstate_(fill), + truncate_(max_streamsize()), pad_scheme_(0) {} + void reset(Ch fill); + void compute_states(); // sets states according to truncate and pad_scheme. + + static std::streamsize max_streamsize() { + return (std::numeric_limits::max)(); + } + + // --- data --- + int argN_; //- argument number (starts at 0, eg : %1 => argN=0) + // negative values for items that don't process an argument + string_type res_; //- result of the formatting of this item + string_type appendix_; //- piece of string between this item and the next + + stream_format_state fmtstate_;// set by parsing, is only affected by modify_item + + std::streamsize truncate_;//- is set for directives like %.5s that ask truncation + unsigned int pad_scheme_;//- several possible padding schemes can mix. see pad_values + }; + + + +//--- Definitions ------------------------------------------------------------ + +// - stream_format_state:: ------------------------------------------------- + template + void stream_format_state:: apply_on (basic_ios & os, + boost::io::detail::locale_t * loc_default) const { + // set the state of this stream according to our params + if(width_ != -1) + os.width(width_); + if(precision_ != -1) + os.precision(precision_); + if(fill_ != 0) + os.fill(fill_); + os.flags(flags_); + os.clear(rdstate_); + os.exceptions(exceptions_); +#if !defined(BOOST_NO_STD_LOCALE) + if(loc_) + os.imbue(loc_.get()); + else if(loc_default) + os.imbue(*loc_default); +#else + (void) loc_default; // keep compiler quiet if we don't support locales +#endif + } + + template + void stream_format_state:: set_by_stream(const basic_ios& os) { + // set our params according to the state of this stream + flags_ = os.flags(); + width_ = os.width(); + precision_ = os.precision(); + fill_ = os.fill(); + rdstate_ = os.rdstate(); + exceptions_ = os.exceptions(); + } + + + template + void apply_manip_body( stream_format_state& self, + T manipulator) { + // modify our params according to the manipulator + basic_oaltstringstream ss; + self.apply_on( ss ); + ss << manipulator; + self.set_by_stream( ss ); + } + + template inline + void stream_format_state:: reset(Ch fill) { + // set our params to standard's default state. cf § 27.4.4.1 of the C++ norm + width_=0; precision_=6; + fill_=fill; // default is widen(' '), but we cant compute it without the locale + flags_ = std::ios_base::dec | std::ios_base::skipws; + // the adjust_field part is left equal to 0, which means right. + exceptions_ = std::ios_base::goodbit; + rdstate_ = std::ios_base::goodbit; + } + + +// --- format_item:: -------------------------------------------------------- + + template + void format_item:: + reset (Ch fill) { + argN_=argN_no_posit; truncate_ = max_streamsize(); pad_scheme_ =0; + res_.resize(0); appendix_.resize(0); + fmtstate_.reset(fill); + } + + template + void format_item:: + compute_states() { + // reflect pad_scheme_ on fmt_state_ + // because some pad_schemes has complex consequences on several state params. + if(pad_scheme_ & zeropad) { + // ignore zeropad in left alignment : + if(fmtstate_.flags_ & std::ios_base::left) { + BOOST_ASSERT(!(fmtstate_.flags_ &(std::ios_base::adjustfield ^std::ios_base::left))); + // only left bit might be set. (not right, nor internal) + pad_scheme_ = pad_scheme_ & (~zeropad); + } + else { + pad_scheme_ &= ~spacepad; // printf ignores spacepad when zeropadding + fmtstate_.fill_='0'; + fmtstate_.flags_ = (fmtstate_.flags_ & ~std::ios_base::adjustfield) + | std::ios_base::internal; + // removes all adjustfield bits, and adds internal. + } + } + if(pad_scheme_ & spacepad) { + if(fmtstate_.flags_ & std::ios_base::showpos) + pad_scheme_ &= ~spacepad; + } + } + + +} } } // namespaces boost :: io :: detail + + +#endif // BOOST_FORMAT_INTERNALS_HPP diff --git a/win32/include/boost/format/internals_fwd.hpp b/win32/include/boost/format/internals_fwd.hpp new file mode 100755 index 000000000..684d32a6f --- /dev/null +++ b/win32/include/boost/format/internals_fwd.hpp @@ -0,0 +1,60 @@ +// ---------------------------------------------------------------------------- +// internals_fwd.hpp : forward declarations, for internal headers +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// See http://www.boost.org/libs/format for library home page + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_FORMAT_INTERNAL_FWD_HPP +#define BOOST_FORMAT_INTERNAL_FWD_HPP + +#include +#include + + +namespace boost { +namespace io { + +namespace detail { + template struct stream_format_state; + template struct format_item; + + + // these functions were intended as methods, + // but MSVC have problems with template member functions : + // defined in format_implementation.hpp : + template + basic_format& + modify_item_body (basic_format& self, + int itemN, T manipulator); + + template + basic_format& + bind_arg_body (basic_format& self, + int argN, const T& val); + + // in internals.hpp : + template + void apply_manip_body (stream_format_state& self, + T manipulator); + + // argument feeding (defined in feed_args.hpp ) : + template + void distribute (basic_format& self, T x); + + template + basic_format& + feed (basic_format& self, T x); + +} // namespace detail + +} // namespace io +} // namespace boost + + +#endif // BOOST_FORMAT_INTERNAL_FWD_HPP diff --git a/win32/include/boost/format/parsing.hpp b/win32/include/boost/format/parsing.hpp new file mode 100755 index 000000000..a42f92461 --- /dev/null +++ b/win32/include/boost/format/parsing.hpp @@ -0,0 +1,503 @@ +// ---------------------------------------------------------------------------- +// parsing.hpp : implementation of the parsing member functions +// ( parse, parse_printf_directive) +// ---------------------------------------------------------------------------- + +// Copyright Samuel Krempp 2003. Use, modification, and distribution are +// subject to 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) + +// see http://www.boost.org/libs/format for library home page + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_FORMAT_PARSING_HPP +#define BOOST_FORMAT_PARSING_HPP + + +#include +#include +#include +#include + + +namespace boost { +namespace io { +namespace detail { + +#if defined(BOOST_NO_STD_LOCALE) + // streams will be used for narrow / widen. but these methods are not const + template + T& const_or_not(const T& x) { + return const_cast (x); + } +#else + template + const T& const_or_not(const T& x) { + return x; + } +#endif + + template inline + char wrap_narrow(const Facet& fac, Ch c, char deflt) { + return const_or_not(fac).narrow(c, deflt); + } + + template inline + bool wrap_isdigit(const Facet& fac, Ch c) { +#if ! defined( BOOST_NO_LOCALE_ISDIGIT ) + return fac.is(std::ctype::digit, c); +# else + using namespace std; + return isdigit(c); +#endif + } + + template + Iter wrap_scan_notdigit(const Facet & fac, Iter beg, Iter end) { + using namespace std; + for( ; beg!=end && wrap_isdigit(fac, *beg); ++beg) ; + return beg; + } + + + // Input : [start, last) iterators range and a + // a Facet to use its widen/narrow member function + // Effects : read sequence and convert digits into integral n, of type Res + // Returns : n + template + Iter str2int (const Iter & start, const Iter & last, Res & res, + const Facet& fac) + { + using namespace std; + Iter it; + res=0; + for(it=start; it != last && wrap_isdigit(fac, *it); ++it ) { + char cur_ch = wrap_narrow(fac, *it, 0); // cant fail. + res *= 10; + res += cur_ch - '0'; // 22.2.1.1.2.13 of the C++ standard + } + return it; + } + + // skip printf's "asterisk-fields" directives in the format-string buf + // Input : char string, with starting index *pos_p + // a Facet merely to use its widen/narrow member function + // Effects : advance *pos_p by skipping printf's asterisk fields. + // Returns : nothing + template + Iter skip_asterisk(Iter start, Iter last, const Facet& fac) + { + using namespace std; + ++ start; + start = wrap_scan_notdigit(fac, start, last); + if(start!=last && *start== const_or_not(fac).widen( '$') ) + ++start; + return start; + } + + + // auxiliary func called by parse_printf_directive + // for centralising error handling + // it either throws if user sets the corresponding flag, or does nothing. + inline void maybe_throw_exception(unsigned char exceptions, + std::size_t pos, std::size_t size) + { + if(exceptions & io::bad_format_string_bit) + boost::throw_exception(io::bad_format_string(pos, size) ); + } + + + // Input: the position of a printf-directive in the format-string + // a basic_ios& merely to use its widen/narrow member function + // a bitset'exceptions' telling whether to throw exceptions on errors. + // Returns: + // true if parse succeeded (ignore some errors if exceptions disabled) + // false if it failed so bad that the directive should be printed verbatim + // Effects: + // start is incremented so that *start is the first char after + // this directive + // *fpar is set with the parameters read in the directive + template + bool parse_printf_directive(Iter & start, const Iter& last, + detail::format_item * fpar, + const Facet& fac, + std::size_t offset, unsigned char exceptions) + { + typedef typename basic_format::format_item_t format_item_t; + + fpar->argN_ = format_item_t::argN_no_posit; // if no positional-directive + bool precision_set = false; + bool in_brackets=false; + Iter start0 = start; + std::size_t fstring_size = last-start0+offset; + + if(start>= last) { // empty directive : this is a trailing % + maybe_throw_exception(exceptions, start-start0 + offset, fstring_size); + return false; + } + + if(*start== const_or_not(fac).widen( '|')) { + in_brackets=true; + if( ++start >= last ) { + maybe_throw_exception(exceptions, start-start0 + offset, fstring_size); + return false; + } + } + + // the flag '0' would be picked as a digit for argument order, but here it's a flag : + if(*start== const_or_not(fac).widen( '0')) + goto parse_flags; + + // handle argument order (%2$d) or possibly width specification: %2d + if(wrap_isdigit(fac, *start)) { + int n; + start = str2int(start, last, n, fac); + if( start >= last ) { + maybe_throw_exception(exceptions, start-start0+offset, fstring_size); + return false; + } + + // %N% case : this is already the end of the directive + if( *start == const_or_not(fac).widen( '%') ) { + fpar->argN_ = n-1; + ++start; + if( in_brackets) + maybe_throw_exception(exceptions, start-start0+offset, fstring_size); + // but don't return. maybe "%" was used in lieu of '$', so we go on. + else + return true; + } + + if ( *start== const_or_not(fac).widen( '$') ) { + fpar->argN_ = n-1; + ++start; + } + else { + // non-positionnal directive + fpar->fmtstate_.width_ = n; + fpar->argN_ = format_item_t::argN_no_posit; + goto parse_precision; + } + } + + parse_flags: + // handle flags + while ( start != last) { // as long as char is one of + - = _ # 0 l h or ' ' + // misc switches + switch ( wrap_narrow(fac, *start, 0)) { + case '\'' : break; // no effect yet. (painful to implement) + case 'l': + case 'h': // short/long modifier : for printf-comaptibility (no action needed) + break; + case '-': + fpar->fmtstate_.flags_ |= std::ios_base::left; + break; + case '=': + fpar->pad_scheme_ |= format_item_t::centered; + break; + case '_': + fpar->fmtstate_.flags_ |= std::ios_base::internal; + break; + case ' ': + fpar->pad_scheme_ |= format_item_t::spacepad; + break; + case '+': + fpar->fmtstate_.flags_ |= std::ios_base::showpos; + break; + case '0': + fpar->pad_scheme_ |= format_item_t::zeropad; + // need to know alignment before really setting flags, + // so just add 'zeropad' flag for now, it will be processed later. + break; + case '#': + fpar->fmtstate_.flags_ |= std::ios_base::showpoint | std::ios_base::showbase; + break; + default: + goto parse_width; + } + ++start; + } // loop on flag. + + if( start>=last) { + maybe_throw_exception(exceptions, start-start0+offset, fstring_size); + return true; + } + parse_width: + // handle width spec + // first skip 'asterisk fields' : *, or *N$ + if(*start == const_or_not(fac).widen( '*') ) + start = skip_asterisk(start, last, fac); + if(start!=last && wrap_isdigit(fac, *start)) + start = str2int(start, last, fpar->fmtstate_.width_, fac); + + parse_precision: + if( start>= last) { + maybe_throw_exception(exceptions, start-start0+offset, fstring_size); + return true; + } + // handle precision spec + if (*start== const_or_not(fac).widen( '.')) { + ++start; + if(start != last && *start == const_or_not(fac).widen( '*') ) + start = skip_asterisk(start, last, fac); + if(start != last && wrap_isdigit(fac, *start)) { + start = str2int(start, last, fpar->fmtstate_.precision_, fac); + precision_set = true; + } + else + fpar->fmtstate_.precision_ =0; + } + + // handle formatting-type flags : + while( start != last && ( *start== const_or_not(fac).widen( 'l') + || *start== const_or_not(fac).widen( 'L') + || *start== const_or_not(fac).widen( 'h')) ) + ++start; + if( start>=last) { + maybe_throw_exception(exceptions, start-start0+offset, fstring_size); + return true; + } + + if( in_brackets && *start== const_or_not(fac).widen( '|') ) { + ++start; + return true; + } + switch ( wrap_narrow(fac, *start, 0) ) { + case 'X': + fpar->fmtstate_.flags_ |= std::ios_base::uppercase; + case 'p': // pointer => set hex. + case 'x': + fpar->fmtstate_.flags_ &= ~std::ios_base::basefield; + fpar->fmtstate_.flags_ |= std::ios_base::hex; + break; + + case 'o': + fpar->fmtstate_.flags_ &= ~std::ios_base::basefield; + fpar->fmtstate_.flags_ |= std::ios_base::oct; + break; + + case 'E': + fpar->fmtstate_.flags_ |= std::ios_base::uppercase; + case 'e': + fpar->fmtstate_.flags_ &= ~std::ios_base::floatfield; + fpar->fmtstate_.flags_ |= std::ios_base::scientific; + + fpar->fmtstate_.flags_ &= ~std::ios_base::basefield; + fpar->fmtstate_.flags_ |= std::ios_base::dec; + break; + + case 'f': + fpar->fmtstate_.flags_ &= ~std::ios_base::floatfield; + fpar->fmtstate_.flags_ |= std::ios_base::fixed; + case 'u': + case 'd': + case 'i': + fpar->fmtstate_.flags_ &= ~std::ios_base::basefield; + fpar->fmtstate_.flags_ |= std::ios_base::dec; + break; + + case 'T': + ++start; + if( start >= last) + maybe_throw_exception(exceptions, start-start0+offset, fstring_size); + else + fpar->fmtstate_.fill_ = *start; + fpar->pad_scheme_ |= format_item_t::tabulation; + fpar->argN_ = format_item_t::argN_tabulation; + break; + case 't': + fpar->fmtstate_.fill_ = const_or_not(fac).widen( ' '); + fpar->pad_scheme_ |= format_item_t::tabulation; + fpar->argN_ = format_item_t::argN_tabulation; + break; + + case 'G': + fpar->fmtstate_.flags_ |= std::ios_base::uppercase; + break; + case 'g': // 'g' conversion is default for floats. + fpar->fmtstate_.flags_ &= ~std::ios_base::basefield; + fpar->fmtstate_.flags_ |= std::ios_base::dec; + + // CLEAR all floatield flags, so stream will CHOOSE + fpar->fmtstate_.flags_ &= ~std::ios_base::floatfield; + break; + + case 'C': + case 'c': + fpar->truncate_ = 1; + break; + case 'S': + case 's': + if(precision_set) // handle truncation manually, with own parameter. + fpar->truncate_ = fpar->fmtstate_.precision_; + fpar->fmtstate_.precision_ = 6; // default stream precision. + break; + case 'n' : + fpar->argN_ = format_item_t::argN_ignored; + break; + default: + maybe_throw_exception(exceptions, start-start0+offset, fstring_size); + } + ++start; + + if( in_brackets ) { + if( start != last && *start== const_or_not(fac).widen( '|') ) { + ++start; + return true; + } + else maybe_throw_exception(exceptions, start-start0+offset, fstring_size); + } + return true; + } + // -end parse_printf_directive() + + template + int upper_bound_from_fstring(const String& buf, + const typename String::value_type arg_mark, + const Facet& fac, + unsigned char exceptions) + { + // quick-parsing of the format-string to count arguments mark (arg_mark, '%') + // returns : upper bound on the number of format items in the format strings + using namespace boost::io; + typename String::size_type i1=0; + int num_items=0; + while( (i1=buf.find(arg_mark,i1)) != String::npos ) { + if( i1+1 >= buf.size() ) { + if(exceptions & bad_format_string_bit) + boost::throw_exception(bad_format_string(i1, buf.size() )); // must not end in ".. %" + else { + ++num_items; + break; + } + } + if(buf[i1+1] == buf[i1] ) {// escaped "%%" + i1+=2; continue; + } + + ++i1; + // in case of %N% directives, dont count it double (wastes allocations..) : + i1 = detail::wrap_scan_notdigit(fac, buf.begin()+i1, buf.end()) - buf.begin(); + if( i1 < buf.size() && buf[i1] == arg_mark ) + ++i1; + ++num_items; + } + return num_items; + } + template inline + void append_string(String& dst, const String& src, + const typename String::size_type beg, + const typename String::size_type end) { +#if !defined(BOOST_NO_STRING_APPEND) + dst.append(src.begin()+beg, src.begin()+end); +#else + dst += src.substr(beg, end-beg); +#endif + } + +} // detail namespace +} // io namespace + + + +// ----------------------------------------------- +// format :: parse(..) + + template + basic_format& basic_format:: + parse (const string_type& buf) { + // parse the format-string + using namespace std; +#if !defined(BOOST_NO_STD_LOCALE) + const std::ctype & fac = BOOST_USE_FACET( std::ctype, getloc()); +#else + io::basic_oaltstringstream fac; + //has widen and narrow even on compilers without locale +#endif + + const Ch arg_mark = io::detail::const_or_not(fac).widen( '%'); + bool ordered_args=true; + int max_argN=-1; + + // A: find upper_bound on num_items and allocates arrays + int num_items = io::detail::upper_bound_from_fstring(buf, arg_mark, fac, exceptions()); + make_or_reuse_data(num_items); + + // B: Now the real parsing of the format string : + num_items=0; + typename string_type::size_type i0=0, i1=0; + typename string_type::const_iterator it; + bool special_things=false; + int cur_item=0; + while( (i1=buf.find(arg_mark,i1)) != string_type::npos ) { + string_type & piece = (cur_item==0) ? prefix_ : items_[cur_item-1].appendix_; + if( buf[i1+1] == buf[i1] ) { // escaped mark, '%%' + io::detail::append_string(piece, buf, i0, i1+1); + i1+=2; i0=i1; + continue; + } + BOOST_ASSERT( static_cast(cur_item) < items_.size() || cur_item==0); + + if(i1!=i0) { + io::detail::append_string(piece, buf, i0, i1); + i0=i1; + } + ++i1; + it = buf.begin()+i1; + bool parse_ok = io::detail::parse_printf_directive( + it, buf.end(), &items_[cur_item], fac, i1, exceptions()); + i1 = it - buf.begin(); + if( ! parse_ok ) // the directive will be printed verbatim + continue; + i0=i1; + items_[cur_item].compute_states(); // process complex options, like zeropad, into params + + int argN=items_[cur_item].argN_; + if(argN == format_item_t::argN_ignored) + continue; + if(argN ==format_item_t::argN_no_posit) + ordered_args=false; + else if(argN == format_item_t::argN_tabulation) special_things=true; + else if(argN > max_argN) max_argN = argN; + ++num_items; + ++cur_item; + } // loop on %'s + BOOST_ASSERT(cur_item == num_items); + + // store the final piece of string + { + string_type & piece = (cur_item==0) ? prefix_ : items_[cur_item-1].appendix_; + io::detail::append_string(piece, buf, i0, buf.size()); + } + + if( !ordered_args) { + if(max_argN >= 0 ) { // dont mix positional with non-positionnal directives + if(exceptions() & io::bad_format_string_bit) + boost::throw_exception(io::bad_format_string(max_argN, 0)); + // else do nothing. => positionnal arguments are processed as non-positionnal + } + // set things like it would have been with positional directives : + int non_ordered_items = 0; + for(int i=0; i< num_items; ++i) + if(items_[i].argN_ == format_item_t::argN_no_posit) { + items_[i].argN_ = non_ordered_items; + ++non_ordered_items; + } + max_argN = non_ordered_items-1; + } + + // C: set some member data : + items_.resize(num_items, format_item_t(io::detail::const_or_not(fac).widen( ' ')) ); + + if(special_things) style_ |= special_needs; + num_args_ = max_argN + 1; + if(ordered_args) style_ |= ordered; + else style_ &= ~ordered; + return *this; + } + +} // namespace boost + + +#endif // BOOST_FORMAT_PARSING_HPP diff --git a/win32/include/boost/function.hpp b/win32/include/boost/function.hpp new file mode 100755 index 000000000..944ff8395 --- /dev/null +++ b/win32/include/boost/function.hpp @@ -0,0 +1,66 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2001-2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org/libs/function + +// William Kempf, Jesse Jones and Karl Nelson were all very helpful in the +// design of this library. + +#include // unary_function, binary_function + +#include +#include + +#ifndef BOOST_FUNCTION_MAX_ARGS +# define BOOST_FUNCTION_MAX_ARGS 10 +#endif // BOOST_FUNCTION_MAX_ARGS + +// Include the prologue here so that the use of file-level iteration +// in anything that may be included by function_template.hpp doesn't break +#include + +// Visual Age C++ doesn't handle the file iteration well +#if BOOST_WORKAROUND(__IBMCPP__, >= 500) +# if BOOST_FUNCTION_MAX_ARGS >= 0 +# include +# endif +# if BOOST_FUNCTION_MAX_ARGS >= 1 +# include +# endif +# if BOOST_FUNCTION_MAX_ARGS >= 2 +# include +# endif +# if BOOST_FUNCTION_MAX_ARGS >= 3 +# include +# endif +# if BOOST_FUNCTION_MAX_ARGS >= 4 +# include +# endif +# if BOOST_FUNCTION_MAX_ARGS >= 5 +# include +# endif +# if BOOST_FUNCTION_MAX_ARGS >= 6 +# include +# endif +# if BOOST_FUNCTION_MAX_ARGS >= 7 +# include +# endif +# if BOOST_FUNCTION_MAX_ARGS >= 8 +# include +# endif +# if BOOST_FUNCTION_MAX_ARGS >= 9 +# include +# endif +# if BOOST_FUNCTION_MAX_ARGS >= 10 +# include +# endif +#else +// What is the '3' for? +# define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_FUNCTION_MAX_ARGS,)) +# include BOOST_PP_ITERATE() +# undef BOOST_PP_ITERATION_PARAMS_1 +#endif diff --git a/win32/include/boost/function/detail/function_iterate.hpp b/win32/include/boost/function/detail/function_iterate.hpp new file mode 100755 index 000000000..d068cb7ed --- /dev/null +++ b/win32/include/boost/function/detail/function_iterate.hpp @@ -0,0 +1,16 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org +#if !defined(BOOST_PP_IS_ITERATING) +# error Boost.Function - do not include this file! +#endif + +#define BOOST_FUNCTION_NUM_ARGS BOOST_PP_ITERATION() +#include +#undef BOOST_FUNCTION_NUM_ARGS + diff --git a/win32/include/boost/function/detail/gen_maybe_include.pl b/win32/include/boost/function/detail/gen_maybe_include.pl new file mode 100755 index 000000000..1bfaab780 --- /dev/null +++ b/win32/include/boost/function/detail/gen_maybe_include.pl @@ -0,0 +1,37 @@ +#!/usr/bin/perl -w +# +# Boost.Function library +# +# Copyright (C) 2001-2003 Douglas Gregor (gregod@cs.rpi.edu) +# +# Permission to copy, use, sell and distribute this software is granted +# provided this copyright notice appears in all copies. +# Permission to modify the code and to distribute modified code is granted +# provided this copyright notice appears in all copies, and a notice +# that the code was modified is included with the copyright notice. +# +# This software is provided "as is" without express or implied warranty, +# and with no claim as to its suitability for any purpose. +# +# For more information, see http://www.boost.org +use English; + +$max_args = $ARGV[0]; + +open (OUT, ">maybe_include.hpp") or die("Cannot write to maybe_include.hpp"); +for($on_arg = 0; $on_arg <= $max_args; ++$on_arg) { + if ($on_arg == 0) { + print OUT "#if"; + } + else { + print OUT "#elif"; + } + print OUT " BOOST_FUNCTION_NUM_ARGS == $on_arg\n"; + print OUT "# ifndef BOOST_FUNCTION_$on_arg\n"; + print OUT "# define BOOST_FUNCTION_$on_arg\n"; + print OUT "# include \n"; + print OUT "# endif\n"; +} +print OUT "#else\n"; +print OUT "# error Cannot handle Boost.Function objects that accept more than $max_args arguments!\n"; +print OUT "#endif\n"; diff --git a/win32/include/boost/function/detail/maybe_include.hpp b/win32/include/boost/function/detail/maybe_include.hpp new file mode 100755 index 000000000..10beac8df --- /dev/null +++ b/win32/include/boost/function/detail/maybe_include.hpp @@ -0,0 +1,267 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org + +#if BOOST_FUNCTION_NUM_ARGS == 0 +# ifndef BOOST_FUNCTION_0 +# define BOOST_FUNCTION_0 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 1 +# ifndef BOOST_FUNCTION_1 +# define BOOST_FUNCTION_1 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 2 +# ifndef BOOST_FUNCTION_2 +# define BOOST_FUNCTION_2 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 3 +# ifndef BOOST_FUNCTION_3 +# define BOOST_FUNCTION_3 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 4 +# ifndef BOOST_FUNCTION_4 +# define BOOST_FUNCTION_4 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 5 +# ifndef BOOST_FUNCTION_5 +# define BOOST_FUNCTION_5 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 6 +# ifndef BOOST_FUNCTION_6 +# define BOOST_FUNCTION_6 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 7 +# ifndef BOOST_FUNCTION_7 +# define BOOST_FUNCTION_7 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 8 +# ifndef BOOST_FUNCTION_8 +# define BOOST_FUNCTION_8 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 9 +# ifndef BOOST_FUNCTION_9 +# define BOOST_FUNCTION_9 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 10 +# ifndef BOOST_FUNCTION_10 +# define BOOST_FUNCTION_10 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 11 +# ifndef BOOST_FUNCTION_11 +# define BOOST_FUNCTION_11 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 12 +# ifndef BOOST_FUNCTION_12 +# define BOOST_FUNCTION_12 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 13 +# ifndef BOOST_FUNCTION_13 +# define BOOST_FUNCTION_13 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 14 +# ifndef BOOST_FUNCTION_14 +# define BOOST_FUNCTION_14 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 15 +# ifndef BOOST_FUNCTION_15 +# define BOOST_FUNCTION_15 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 16 +# ifndef BOOST_FUNCTION_16 +# define BOOST_FUNCTION_16 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 17 +# ifndef BOOST_FUNCTION_17 +# define BOOST_FUNCTION_17 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 18 +# ifndef BOOST_FUNCTION_18 +# define BOOST_FUNCTION_18 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 19 +# ifndef BOOST_FUNCTION_19 +# define BOOST_FUNCTION_19 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 20 +# ifndef BOOST_FUNCTION_20 +# define BOOST_FUNCTION_20 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 21 +# ifndef BOOST_FUNCTION_21 +# define BOOST_FUNCTION_21 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 22 +# ifndef BOOST_FUNCTION_22 +# define BOOST_FUNCTION_22 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 23 +# ifndef BOOST_FUNCTION_23 +# define BOOST_FUNCTION_23 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 24 +# ifndef BOOST_FUNCTION_24 +# define BOOST_FUNCTION_24 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 25 +# ifndef BOOST_FUNCTION_25 +# define BOOST_FUNCTION_25 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 26 +# ifndef BOOST_FUNCTION_26 +# define BOOST_FUNCTION_26 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 27 +# ifndef BOOST_FUNCTION_27 +# define BOOST_FUNCTION_27 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 28 +# ifndef BOOST_FUNCTION_28 +# define BOOST_FUNCTION_28 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 29 +# ifndef BOOST_FUNCTION_29 +# define BOOST_FUNCTION_29 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 30 +# ifndef BOOST_FUNCTION_30 +# define BOOST_FUNCTION_30 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 31 +# ifndef BOOST_FUNCTION_31 +# define BOOST_FUNCTION_31 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 32 +# ifndef BOOST_FUNCTION_32 +# define BOOST_FUNCTION_32 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 33 +# ifndef BOOST_FUNCTION_33 +# define BOOST_FUNCTION_33 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 34 +# ifndef BOOST_FUNCTION_34 +# define BOOST_FUNCTION_34 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 35 +# ifndef BOOST_FUNCTION_35 +# define BOOST_FUNCTION_35 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 36 +# ifndef BOOST_FUNCTION_36 +# define BOOST_FUNCTION_36 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 37 +# ifndef BOOST_FUNCTION_37 +# define BOOST_FUNCTION_37 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 38 +# ifndef BOOST_FUNCTION_38 +# define BOOST_FUNCTION_38 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 39 +# ifndef BOOST_FUNCTION_39 +# define BOOST_FUNCTION_39 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 40 +# ifndef BOOST_FUNCTION_40 +# define BOOST_FUNCTION_40 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 41 +# ifndef BOOST_FUNCTION_41 +# define BOOST_FUNCTION_41 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 42 +# ifndef BOOST_FUNCTION_42 +# define BOOST_FUNCTION_42 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 43 +# ifndef BOOST_FUNCTION_43 +# define BOOST_FUNCTION_43 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 44 +# ifndef BOOST_FUNCTION_44 +# define BOOST_FUNCTION_44 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 45 +# ifndef BOOST_FUNCTION_45 +# define BOOST_FUNCTION_45 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 46 +# ifndef BOOST_FUNCTION_46 +# define BOOST_FUNCTION_46 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 47 +# ifndef BOOST_FUNCTION_47 +# define BOOST_FUNCTION_47 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 48 +# ifndef BOOST_FUNCTION_48 +# define BOOST_FUNCTION_48 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 49 +# ifndef BOOST_FUNCTION_49 +# define BOOST_FUNCTION_49 +# include +# endif +#elif BOOST_FUNCTION_NUM_ARGS == 50 +# ifndef BOOST_FUNCTION_50 +# define BOOST_FUNCTION_50 +# include +# endif +#else +# error Cannot handle Boost.Function objects that accept more than 50 arguments! +#endif diff --git a/win32/include/boost/function/detail/prologue.hpp b/win32/include/boost/function/detail/prologue.hpp new file mode 100755 index 000000000..ba1ce88c0 --- /dev/null +++ b/win32/include/boost/function/detail/prologue.hpp @@ -0,0 +1,26 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2002-2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org + +#ifndef BOOST_FUNCTION_PROLOGUE_HPP +#define BOOST_FUNCTION_PROLOGUE_HPP +# include +# include +# include // unary_function, binary_function +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif // BOOST_FUNCTION_PROLOGUE_HPP diff --git a/win32/include/boost/function/function0.hpp b/win32/include/boost/function/function0.hpp new file mode 100755 index 000000000..e510889f4 --- /dev/null +++ b/win32/include/boost/function/function0.hpp @@ -0,0 +1,12 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2002-2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org + +#define BOOST_FUNCTION_NUM_ARGS 0 +#include +#undef BOOST_FUNCTION_NUM_ARGS diff --git a/win32/include/boost/function/function1.hpp b/win32/include/boost/function/function1.hpp new file mode 100755 index 000000000..3109f50e7 --- /dev/null +++ b/win32/include/boost/function/function1.hpp @@ -0,0 +1,12 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2002-2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org + +#define BOOST_FUNCTION_NUM_ARGS 1 +#include +#undef BOOST_FUNCTION_NUM_ARGS diff --git a/win32/include/boost/function/function10.hpp b/win32/include/boost/function/function10.hpp new file mode 100755 index 000000000..0818f67ea --- /dev/null +++ b/win32/include/boost/function/function10.hpp @@ -0,0 +1,12 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2002-2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org + +#define BOOST_FUNCTION_NUM_ARGS 10 +#include +#undef BOOST_FUNCTION_NUM_ARGS diff --git a/win32/include/boost/function/function2.hpp b/win32/include/boost/function/function2.hpp new file mode 100755 index 000000000..76e3b8c80 --- /dev/null +++ b/win32/include/boost/function/function2.hpp @@ -0,0 +1,12 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2002-2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org + +#define BOOST_FUNCTION_NUM_ARGS 2 +#include +#undef BOOST_FUNCTION_NUM_ARGS diff --git a/win32/include/boost/function/function3.hpp b/win32/include/boost/function/function3.hpp new file mode 100755 index 000000000..dd4f8cff5 --- /dev/null +++ b/win32/include/boost/function/function3.hpp @@ -0,0 +1,12 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2002-2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org + +#define BOOST_FUNCTION_NUM_ARGS 3 +#include +#undef BOOST_FUNCTION_NUM_ARGS diff --git a/win32/include/boost/function/function4.hpp b/win32/include/boost/function/function4.hpp new file mode 100755 index 000000000..32357e710 --- /dev/null +++ b/win32/include/boost/function/function4.hpp @@ -0,0 +1,12 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2002-2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org + +#define BOOST_FUNCTION_NUM_ARGS 4 +#include +#undef BOOST_FUNCTION_NUM_ARGS diff --git a/win32/include/boost/function/function5.hpp b/win32/include/boost/function/function5.hpp new file mode 100755 index 000000000..72f147905 --- /dev/null +++ b/win32/include/boost/function/function5.hpp @@ -0,0 +1,12 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2002-2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org + +#define BOOST_FUNCTION_NUM_ARGS 5 +#include +#undef BOOST_FUNCTION_NUM_ARGS diff --git a/win32/include/boost/function/function6.hpp b/win32/include/boost/function/function6.hpp new file mode 100755 index 000000000..1f8252812 --- /dev/null +++ b/win32/include/boost/function/function6.hpp @@ -0,0 +1,12 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2002-2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org + +#define BOOST_FUNCTION_NUM_ARGS 6 +#include +#undef BOOST_FUNCTION_NUM_ARGS diff --git a/win32/include/boost/function/function7.hpp b/win32/include/boost/function/function7.hpp new file mode 100755 index 000000000..bf827b32f --- /dev/null +++ b/win32/include/boost/function/function7.hpp @@ -0,0 +1,12 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2002-2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org + +#define BOOST_FUNCTION_NUM_ARGS 7 +#include +#undef BOOST_FUNCTION_NUM_ARGS diff --git a/win32/include/boost/function/function8.hpp b/win32/include/boost/function/function8.hpp new file mode 100755 index 000000000..4511bc43c --- /dev/null +++ b/win32/include/boost/function/function8.hpp @@ -0,0 +1,12 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2002-2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org + +#define BOOST_FUNCTION_NUM_ARGS 8 +#include +#undef BOOST_FUNCTION_NUM_ARGS diff --git a/win32/include/boost/function/function9.hpp b/win32/include/boost/function/function9.hpp new file mode 100755 index 000000000..05725d533 --- /dev/null +++ b/win32/include/boost/function/function9.hpp @@ -0,0 +1,12 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2002-2003. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org + +#define BOOST_FUNCTION_NUM_ARGS 9 +#include +#undef BOOST_FUNCTION_NUM_ARGS diff --git a/win32/include/boost/function/function_base.hpp b/win32/include/boost/function/function_base.hpp new file mode 100755 index 000000000..eb3b8e872 --- /dev/null +++ b/win32/include/boost/function/function_base.hpp @@ -0,0 +1,836 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2001-2006 +// Copyright Emil Dotchevski 2007 +// Use, modification and distribution is subject to 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) + +// For more information, see http://www.boost.org + +#ifndef BOOST_FUNCTION_BASE_HEADER +#define BOOST_FUNCTION_BASE_HEADER + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef BOOST_NO_SFINAE +# include "boost/utility/enable_if.hpp" +#else +# include "boost/mpl/bool.hpp" +#endif +#include + +#if defined(BOOST_MSVC) +# pragma warning( push ) +# pragma warning( disable : 4793 ) // complaint about native code generation +# pragma warning( disable : 4127 ) // "conditional expression is constant" +#endif + +// Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info. +#ifdef BOOST_NO_EXCEPTION_STD_NAMESPACE +// Embedded VC++ does not have type_info in namespace std +# define BOOST_FUNCTION_STD_NS +#else +# define BOOST_FUNCTION_STD_NS std +#endif + +// Borrowed from Boost.Python library: determines the cases where we +// need to use std::type_info::name to compare instead of operator==. +# if (defined(__GNUC__) && __GNUC__ >= 3) \ + || defined(_AIX) \ + || ( defined(__sgi) && defined(__host_mips)) +# include +# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \ + (std::strcmp((X).name(),(Y).name()) == 0) +# else +# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y)) +#endif + +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG) +# define BOOST_FUNCTION_TARGET_FIX(x) x +#else +# define BOOST_FUNCTION_TARGET_FIX(x) +#endif // not MSVC + +#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG) +// Work around a compiler bug. +// boost::python::objects::function has to be seen by the compiler before the +// boost::function class template. +namespace boost { namespace python { namespace objects { + class function; +}}} +#endif + +#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + || defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \ + || !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540) +# define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX +#endif + +#if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) +# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \ + typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \ + (::boost::is_integral::value)>::value), \ + Type>::type +#else +// BCC doesn't recognize this depends on a template argument and complains +// about the use of 'typename' +# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \ + ::boost::enable_if_c<(::boost::type_traits::ice_not< \ + (::boost::is_integral::value)>::value), \ + Type>::type +#endif + +#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) +namespace boost { + +template +class function; + +template +inline void swap(function& f1, + function& f2) +{ + f1.swap(f2); +} + +} // end namespace boost +#endif // have partial specialization + +namespace boost { + namespace detail { + namespace function { + class X; + + /** + * A buffer used to store small function objects in + * boost::function. It is a union containing function pointers, + * object pointers, and a structure that resembles a bound + * member function pointer. + */ + union function_buffer + { + // For pointers to function objects + void* obj_ptr; + + // For pointers to std::type_info objects + // (get_functor_type_tag, check_functor_type_tag). + const void* const_obj_ptr; + + // For function pointers of all kinds + mutable void (*func_ptr)(); + + // For bound member pointers + struct bound_memfunc_ptr_t { + void (X::*memfunc_ptr)(int); + void* obj_ptr; + } bound_memfunc_ptr; + + // To relax aliasing constraints + mutable char data; + }; + + /** + * The unusable class is a placeholder for unused function arguments + * It is also completely unusable except that it constructable from + * anything. This helps compilers without partial specialization to + * handle Boost.Function objects returning void. + */ + struct unusable + { + unusable() {} + template unusable(const T&) {} + }; + + /* Determine the return type. This supports compilers that do not support + * void returns or partial specialization by silently changing the return + * type to "unusable". + */ + template struct function_return_type { typedef T type; }; + + template<> + struct function_return_type + { + typedef unusable type; + }; + + // The operation type to perform on the given functor/function pointer + enum functor_manager_operation_type { + clone_functor_tag, + destroy_functor_tag, + check_functor_type_tag, + get_functor_type_tag + }; + + // Tags used to decide between different types of functions + struct function_ptr_tag {}; + struct function_obj_tag {}; + struct member_ptr_tag {}; + struct function_obj_ref_tag {}; + + template + class get_function_tag + { + typedef typename mpl::if_c<(is_pointer::value), + function_ptr_tag, + function_obj_tag>::type ptr_or_obj_tag; + + typedef typename mpl::if_c<(is_member_pointer::value), + member_ptr_tag, + ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag; + + typedef typename mpl::if_c<(is_reference_wrapper::value), + function_obj_ref_tag, + ptr_or_obj_or_mem_tag>::type or_ref_tag; + + public: + typedef or_ref_tag type; + }; + + // The trivial manager does nothing but return the same pointer (if we + // are cloning) or return the null pointer (if we are deleting). + template + struct reference_manager + { + static inline void + get(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op) + { + switch (op) { + case clone_functor_tag: + out_buffer.obj_ptr = in_buffer.obj_ptr; + return; + + case destroy_functor_tag: + out_buffer.obj_ptr = 0; + return; + + case check_functor_type_tag: + { + // DPG TBD: Since we're only storing a pointer, it's + // possible that the user could ask for a base class or + // derived class. Is that okay? + const BOOST_FUNCTION_STD_NS::type_info& check_type = + *static_cast(out_buffer.const_obj_ptr); + if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F))) + out_buffer.obj_ptr = in_buffer.obj_ptr; + else + out_buffer.obj_ptr = 0; + } + return; + + case get_functor_type_tag: + out_buffer.const_obj_ptr = &typeid(F); + return; + } + } + }; + + /** + * Determine if boost::function can use the small-object + * optimization with the function object type F. + */ + template + struct function_allows_small_object_optimization + { + BOOST_STATIC_CONSTANT + (bool, + value = ((sizeof(F) <= sizeof(function_buffer) && + (alignment_of::value + % alignment_of::value == 0)))); + }; + + template + struct functor_wrapper: public F, public A + { + functor_wrapper( F f, A a ): + F(f), + A(a) + { + } + }; + + /** + * The functor_manager class contains a static function "manage" which + * can clone or destroy the given function/function object pointer. + */ + template + struct functor_manager_common + { + typedef Functor functor_type; + + // Function pointers + static inline void + manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op) + { + if (op == clone_functor_tag) + out_buffer.func_ptr = in_buffer.func_ptr; + else if (op == destroy_functor_tag) + out_buffer.func_ptr = 0; + else /* op == check_functor_type_tag */ { + const BOOST_FUNCTION_STD_NS::type_info& check_type = + *static_cast(out_buffer.const_obj_ptr); + if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor))) + out_buffer.obj_ptr = &in_buffer.func_ptr; + else + out_buffer.obj_ptr = 0; + } + } + + // Function objects that fit in the small-object buffer. + static inline void + manage_small(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op) + { + if (op == clone_functor_tag) { + const functor_type* in_functor = + reinterpret_cast(&in_buffer.data); + new ((void*)&out_buffer.data) functor_type(*in_functor); + } else if (op == destroy_functor_tag) { + // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type. + reinterpret_cast(&out_buffer.data)->~Functor(); + } else /* op == check_functor_type_tag */ { + const BOOST_FUNCTION_STD_NS::type_info& check_type = + *static_cast(out_buffer.const_obj_ptr); + if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor))) + out_buffer.obj_ptr = &in_buffer.data; + else + out_buffer.obj_ptr = 0; + } + } + }; + + template + struct functor_manager + { + private: + typedef Functor functor_type; + + // Function pointers + static inline void + manager(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op, function_ptr_tag) + { + functor_manager_common::manage_ptr(in_buffer,out_buffer,op); + } + + // Function objects that fit in the small-object buffer. + static inline void + manager(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op, mpl::true_) + { + functor_manager_common::manage_small(in_buffer,out_buffer,op); + } + + // Function objects that require heap allocation + static inline void + manager(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op, mpl::false_) + { + if (op == clone_functor_tag) { + // Clone the functor + // GCC 2.95.3 gets the CV qualifiers wrong here, so we + // can't do the static_cast that we should do. + const functor_type* f = + (const functor_type*)(in_buffer.obj_ptr); + functor_type* new_f = new functor_type(*f); + out_buffer.obj_ptr = new_f; + } else if (op == destroy_functor_tag) { + /* Cast from the void pointer to the functor pointer type */ + functor_type* f = + static_cast(out_buffer.obj_ptr); + delete f; + out_buffer.obj_ptr = 0; + } else /* op == check_functor_type_tag */ { + const BOOST_FUNCTION_STD_NS::type_info& check_type = + *static_cast(out_buffer.const_obj_ptr); + if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor))) + out_buffer.obj_ptr = in_buffer.obj_ptr; + else + out_buffer.obj_ptr = 0; + } + } + + // For function objects, we determine whether the function + // object can use the small-object optimization buffer or + // whether we need to allocate it on the heap. + static inline void + manager(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op, function_obj_tag) + { + manager(in_buffer, out_buffer, op, + mpl::bool_<(function_allows_small_object_optimization::value)>()); + } + + public: + /* Dispatch to an appropriate manager based on whether we have a + function pointer or a function object pointer. */ + static inline void + manage(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op) + { + typedef typename get_function_tag::type tag_type; + switch (op) { + case get_functor_type_tag: + out_buffer.const_obj_ptr = &typeid(functor_type); + return; + + default: + manager(in_buffer, out_buffer, op, tag_type()); + return; + } + } + }; + + template + struct functor_manager_a + { + private: + typedef Functor functor_type; + + // Function pointers + static inline void + manager(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op, function_ptr_tag) + { + functor_manager_common::manage_ptr(in_buffer,out_buffer,op); + } + + // Function objects that fit in the small-object buffer. + static inline void + manager(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op, mpl::true_) + { + functor_manager_common::manage_small(in_buffer,out_buffer,op); + } + + // Function objects that require heap allocation + static inline void + manager(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op, mpl::false_) + { + typedef functor_wrapper functor_wrapper_type; + typedef typename Allocator::template rebind::other + wrapper_allocator_type; + typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type; + + if (op == clone_functor_tag) { + // Clone the functor + // GCC 2.95.3 gets the CV qualifiers wrong here, so we + // can't do the static_cast that we should do. + const functor_wrapper_type* f = + (const functor_wrapper_type*)(in_buffer.obj_ptr); + wrapper_allocator_type wrapper_allocator(static_cast(*f)); + wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); + wrapper_allocator.construct(copy, *f); + + // Get back to the original pointer type + functor_wrapper_type* new_f = static_cast(copy); + out_buffer.obj_ptr = new_f; + } else if (op == destroy_functor_tag) { + /* Cast from the void pointer to the functor_wrapper_type */ + functor_wrapper_type* victim = + static_cast(in_buffer.obj_ptr); + wrapper_allocator_type wrapper_allocator(static_cast(*victim)); + wrapper_allocator.destroy(victim); + wrapper_allocator.deallocate(victim,1); + out_buffer.obj_ptr = 0; + } else /* op == check_functor_type_tag */ { + const BOOST_FUNCTION_STD_NS::type_info& check_type = + *static_cast(out_buffer.const_obj_ptr); + if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor))) + out_buffer.obj_ptr = in_buffer.obj_ptr; + else + out_buffer.obj_ptr = 0; + } + } + + // For function objects, we determine whether the function + // object can use the small-object optimization buffer or + // whether we need to allocate it on the heap. + static inline void + manager(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op, function_obj_tag) + { + manager(in_buffer, out_buffer, op, + mpl::bool_<(function_allows_small_object_optimization::value)>()); + } + + public: + /* Dispatch to an appropriate manager based on whether we have a + function pointer or a function object pointer. */ + static inline void + manage(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op) + { + typedef typename get_function_tag::type tag_type; + switch (op) { + case get_functor_type_tag: + out_buffer.const_obj_ptr = &typeid(functor_type); + return; + + default: + manager(in_buffer, out_buffer, op, tag_type()); + return; + } + } + }; + + // A type that is only used for comparisons against zero + struct useless_clear_type {}; + +#ifdef BOOST_NO_SFINAE + // These routines perform comparisons between a Boost.Function + // object and an arbitrary function object (when the last + // parameter is mpl::bool_) or against zero (when the + // last parameter is mpl::bool_). They are only necessary + // for compilers that don't support SFINAE. + template + bool + compare_equal(const Function& f, const Functor&, int, mpl::bool_) + { return f.empty(); } + + template + bool + compare_not_equal(const Function& f, const Functor&, int, + mpl::bool_) + { return !f.empty(); } + + template + bool + compare_equal(const Function& f, const Functor& g, long, + mpl::bool_) + { + if (const Functor* fp = f.template target()) + return function_equal(*fp, g); + else return false; + } + + template + bool + compare_equal(const Function& f, const reference_wrapper& g, + int, mpl::bool_) + { + if (const Functor* fp = f.template target()) + return fp == g.get_pointer(); + else return false; + } + + template + bool + compare_not_equal(const Function& f, const Functor& g, long, + mpl::bool_) + { + if (const Functor* fp = f.template target()) + return !function_equal(*fp, g); + else return true; + } + + template + bool + compare_not_equal(const Function& f, + const reference_wrapper& g, int, + mpl::bool_) + { + if (const Functor* fp = f.template target()) + return fp != g.get_pointer(); + else return true; + } +#endif // BOOST_NO_SFINAE + + /** + * Stores the "manager" portion of the vtable for a + * boost::function object. + */ + struct vtable_base + { + vtable_base() : manager(0) { } + void (*manager)(const function_buffer& in_buffer, + function_buffer& out_buffer, + functor_manager_operation_type op); + }; + } // end namespace function + } // end namespace detail + +/** + * The function_base class contains the basic elements needed for the + * function1, function2, function3, etc. classes. It is common to all + * functions (and as such can be used to tell if we have one of the + * functionN objects). + */ +class function_base +{ +public: + function_base() : vtable(0) { } + + /** Determine if the function is empty (i.e., has no target). */ + bool empty() const { return !vtable; } + + /** Retrieve the type of the stored function object, or typeid(void) + if this is empty. */ + const BOOST_FUNCTION_STD_NS::type_info& target_type() const + { + if (!vtable) return typeid(void); + + detail::function::function_buffer type; + vtable->manager(functor, type, detail::function::get_functor_type_tag); + return *static_cast(type.const_obj_ptr); + } + + template + Functor* target() + { + if (!vtable) return 0; + + detail::function::function_buffer type_result; + type_result.const_obj_ptr = &typeid(Functor); + vtable->manager(functor, type_result, + detail::function::check_functor_type_tag); + return static_cast(type_result.obj_ptr); + } + + template +#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300) + const Functor* target( Functor * = 0 ) const +#else + const Functor* target() const +#endif + { + if (!vtable) return 0; + + detail::function::function_buffer type_result; + type_result.const_obj_ptr = &typeid(Functor); + vtable->manager(functor, type_result, + detail::function::check_functor_type_tag); + // GCC 2.95.3 gets the CV qualifiers wrong here, so we + // can't do the static_cast that we should do. + return (const Functor*)(type_result.obj_ptr); + } + + template + bool contains(const F& f) const + { +#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300) + if (const F* fp = this->target( (F*)0 )) +#else + if (const F* fp = this->template target()) +#endif + { + return function_equal(*fp, f); + } else { + return false; + } + } + +#if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3 + // GCC 3.3 and newer cannot copy with the global operator==, due to + // problems with instantiation of function return types before it + // has been verified that the argument types match up. + template + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) + operator==(Functor g) const + { + if (const Functor* fp = target()) + return function_equal(*fp, g); + else return false; + } + + template + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) + operator!=(Functor g) const + { + if (const Functor* fp = target()) + return !function_equal(*fp, g); + else return true; + } +#endif + +public: // should be protected, but GCC 2.95.3 will fail to allow access + detail::function::vtable_base* vtable; + mutable detail::function::function_buffer functor; +}; + +/** + * The bad_function_call exception class is thrown when a boost::function + * object is invoked + */ +class bad_function_call : public std::runtime_error +{ +public: + bad_function_call() : std::runtime_error("call to empty boost::function") {} +}; + +#ifndef BOOST_NO_SFINAE +inline bool operator==(const function_base& f, + detail::function::useless_clear_type*) +{ + return f.empty(); +} + +inline bool operator!=(const function_base& f, + detail::function::useless_clear_type*) +{ + return !f.empty(); +} + +inline bool operator==(detail::function::useless_clear_type*, + const function_base& f) +{ + return f.empty(); +} + +inline bool operator!=(detail::function::useless_clear_type*, + const function_base& f) +{ + return !f.empty(); +} +#endif + +#ifdef BOOST_NO_SFINAE +// Comparisons between boost::function objects and arbitrary function objects +template + inline bool operator==(const function_base& f, Functor g) + { + typedef mpl::bool_<(is_integral::value)> integral; + return detail::function::compare_equal(f, g, 0, integral()); + } + +template + inline bool operator==(Functor g, const function_base& f) + { + typedef mpl::bool_<(is_integral::value)> integral; + return detail::function::compare_equal(f, g, 0, integral()); + } + +template + inline bool operator!=(const function_base& f, Functor g) + { + typedef mpl::bool_<(is_integral::value)> integral; + return detail::function::compare_not_equal(f, g, 0, integral()); + } + +template + inline bool operator!=(Functor g, const function_base& f) + { + typedef mpl::bool_<(is_integral::value)> integral; + return detail::function::compare_not_equal(f, g, 0, integral()); + } +#else + +# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) +// Comparisons between boost::function objects and arbitrary function +// objects. GCC 3.3 and before has an obnoxious bug that prevents this +// from working. +template + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) + operator==(const function_base& f, Functor g) + { + if (const Functor* fp = f.template target()) + return function_equal(*fp, g); + else return false; + } + +template + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) + operator==(Functor g, const function_base& f) + { + if (const Functor* fp = f.template target()) + return function_equal(g, *fp); + else return false; + } + +template + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) + operator!=(const function_base& f, Functor g) + { + if (const Functor* fp = f.template target()) + return !function_equal(*fp, g); + else return true; + } + +template + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) + operator!=(Functor g, const function_base& f) + { + if (const Functor* fp = f.template target()) + return !function_equal(g, *fp); + else return true; + } +# endif + +template + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) + operator==(const function_base& f, reference_wrapper g) + { + if (const Functor* fp = f.template target()) + return fp == g.get_pointer(); + else return false; + } + +template + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) + operator==(reference_wrapper g, const function_base& f) + { + if (const Functor* fp = f.template target()) + return g.get_pointer() == fp; + else return false; + } + +template + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) + operator!=(const function_base& f, reference_wrapper g) + { + if (const Functor* fp = f.template target()) + return fp != g.get_pointer(); + else return true; + } + +template + BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) + operator!=(reference_wrapper g, const function_base& f) + { + if (const Functor* fp = f.template target()) + return g.get_pointer() != fp; + else return true; + } + +#endif // Compiler supporting SFINAE + +namespace detail { + namespace function { + inline bool has_empty_target(const function_base* f) + { + return f->empty(); + } + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310) + inline bool has_empty_target(const void*) + { + return false; + } +#else + inline bool has_empty_target(...) + { + return false; + } +#endif + } // end namespace function +} // end namespace detail +} // end namespace boost + +#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL +#undef BOOST_FUNCTION_COMPARE_TYPE_ID + +#endif // BOOST_FUNCTION_BASE_HEADER diff --git a/win32/include/boost/function/function_template.hpp b/win32/include/boost/function/function_template.hpp new file mode 100755 index 000000000..e8cb693bc --- /dev/null +++ b/win32/include/boost/function/function_template.hpp @@ -0,0 +1,957 @@ +// Boost.Function library + +// Copyright Douglas Gregor 2001-2006 +// Copyright Emil Dotchevski 2007 +// Use, modification and distribution is subject to 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) + +// For more information, see http://www.boost.org + +// Note: this header is a header template and must NOT have multiple-inclusion +// protection. +#include + +#if defined(BOOST_MSVC) +# pragma warning( push ) +# pragma warning( disable : 4127 ) // "conditional expression is constant" +#endif + +#define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T) + +#define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T) + +#define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I) + +#define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY) + +#define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a) + +#define BOOST_FUNCTION_ARG_TYPE(J,I,D) \ + typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type); + +#define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY) + +// Comma if nonzero number of arguments +#if BOOST_FUNCTION_NUM_ARGS == 0 +# define BOOST_FUNCTION_COMMA +#else +# define BOOST_FUNCTION_COMMA , +#endif // BOOST_FUNCTION_NUM_ARGS > 0 + +// Class names used in this version of the code +#define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_FUNCTION_INVOKER \ + BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \ + BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \ + BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \ + BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_FUNCTION_REF_INVOKER \ + BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \ + BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_GET_FUNCTION_INVOKER \ + BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \ + BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \ + BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS) + +#ifndef BOOST_NO_VOID_RETURNS +# define BOOST_FUNCTION_VOID_RETURN_TYPE void +# define BOOST_FUNCTION_RETURN(X) X +#else +# define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable +# define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE () +#endif + +namespace boost { + namespace detail { + namespace function { + template< + typename FunctionPtr, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_FUNCTION_INVOKER + { + static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA + BOOST_FUNCTION_PARMS) + { + FunctionPtr f = reinterpret_cast(function_ptr.func_ptr); + return f(BOOST_FUNCTION_ARGS); + } + }; + + template< + typename FunctionPtr, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER + { + static BOOST_FUNCTION_VOID_RETURN_TYPE + invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA + BOOST_FUNCTION_PARMS) + + { + FunctionPtr f = reinterpret_cast(function_ptr.func_ptr); + BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS)); + } + }; + + template< + typename FunctionObj, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER + { + static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA + BOOST_FUNCTION_PARMS) + + { + FunctionObj* f; + if (function_allows_small_object_optimization::value) + f = reinterpret_cast(&function_obj_ptr.data); + else + f = reinterpret_cast(function_obj_ptr.obj_ptr); + return (*f)(BOOST_FUNCTION_ARGS); + } + }; + + template< + typename FunctionObj, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER + { + static BOOST_FUNCTION_VOID_RETURN_TYPE + invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA + BOOST_FUNCTION_PARMS) + + { + FunctionObj* f; + if (function_allows_small_object_optimization::value) + f = reinterpret_cast(&function_obj_ptr.data); + else + f = reinterpret_cast(function_obj_ptr.obj_ptr); + BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); + } + }; + + template< + typename FunctionObj, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_FUNCTION_REF_INVOKER + { + static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA + BOOST_FUNCTION_PARMS) + + { + FunctionObj* f = + reinterpret_cast(function_obj_ptr.obj_ptr); + return (*f)(BOOST_FUNCTION_ARGS); + } + }; + + template< + typename FunctionObj, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER + { + static BOOST_FUNCTION_VOID_RETURN_TYPE + invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA + BOOST_FUNCTION_PARMS) + + { + FunctionObj* f = + reinterpret_cast(function_obj_ptr.obj_ptr); + BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); + } + }; + + template< + typename FunctionPtr, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_GET_FUNCTION_INVOKER + { + typedef typename mpl::if_c<(is_void::value), + BOOST_FUNCTION_VOID_FUNCTION_INVOKER< + FunctionPtr, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >, + BOOST_FUNCTION_FUNCTION_INVOKER< + FunctionPtr, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + > + >::type type; + }; + + template< + typename FunctionObj, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER + { + typedef typename mpl::if_c<(is_void::value), + BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER< + FunctionObj, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >, + BOOST_FUNCTION_FUNCTION_OBJ_INVOKER< + FunctionObj, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + > + >::type type; + }; + + template< + typename FunctionObj, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER + { + typedef typename mpl::if_c<(is_void::value), + BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER< + FunctionObj, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >, + BOOST_FUNCTION_FUNCTION_REF_INVOKER< + FunctionObj, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + > + >::type type; + }; + + /** + * vtable for a specific boost::function instance. + */ + template + struct BOOST_FUNCTION_VTABLE : vtable_base + { +#ifndef BOOST_NO_VOID_RETURNS + typedef R result_type; +#else + typedef typename function_return_type::type result_type; +#endif // BOOST_NO_VOID_RETURNS + + typedef result_type (*invoker_type)(function_buffer& + BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS); + + template + BOOST_FUNCTION_VTABLE(F f) : vtable_base(), invoker(0) + { + init(f); + } + template + BOOST_FUNCTION_VTABLE(F f, Allocator) : vtable_base(), invoker(0) + { + init_a(f); + } + + template + bool assign_to(F f, function_buffer& functor) + { + typedef typename get_function_tag::type tag; + return assign_to(f, functor, tag()); + } + template + bool assign_to_a(F f, function_buffer& functor, Allocator a) + { + typedef typename get_function_tag::type tag; + return assign_to_a(f, functor, a, tag()); + } + + void clear(function_buffer& functor) + { + if (manager) + manager(functor, functor, destroy_functor_tag); + } + + private: + template + void init(F f) + { + typedef typename get_function_tag::type tag; + init(f, tag()); + } + template + void init_a(F f) + { + typedef typename get_function_tag::type tag; + init_a(f, tag()); + } + + // Function pointers + template + void init(FunctionPtr /*f*/, function_ptr_tag) + { + typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER< + FunctionPtr, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >::type + actual_invoker_type; + + invoker = &actual_invoker_type::invoke; + manager = &functor_manager::manage; + } + template + void init_a(FunctionPtr f, function_ptr_tag) + { + typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER< + FunctionPtr, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >::type + actual_invoker_type; + + invoker = &actual_invoker_type::invoke; + manager = &functor_manager_a::manage; + } + + template + bool + assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) + { + this->clear(functor); + if (f) { + // should be a reinterpret cast, but some compilers insist + // on giving cv-qualifiers to free functions + functor.func_ptr = (void (*)())(f); + return true; + } else { + return false; + } + } + template + bool + assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) + { + return assign_to(f,functor,function_ptr_tag()); + } + + // Member pointers +#if BOOST_FUNCTION_NUM_ARGS > 0 + template + void init(MemberPtr f, member_ptr_tag) + { + // DPG TBD: Add explicit support for member function + // objects, so we invoke through mem_fn() but we retain the + // right target_type() values. + this->init(mem_fn(f)); + } + template + void init_a(MemberPtr f, member_ptr_tag) + { + // DPG TBD: Add explicit support for member function + // objects, so we invoke through mem_fn() but we retain the + // right target_type() values. + this->init_a(mem_fn(f)); + } + + template + bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) + { + // DPG TBD: Add explicit support for member function + // objects, so we invoke through mem_fn() but we retain the + // right target_type() values. + if (f) { + this->assign_to(mem_fn(f), functor); + return true; + } else { + return false; + } + } + template + bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag) + { + // DPG TBD: Add explicit support for member function + // objects, so we invoke through mem_fn() but we retain the + // right target_type() values. + if (f) { + this->assign_to_a(mem_fn(f), functor, a); + return true; + } else { + return false; + } + } +#endif // BOOST_FUNCTION_NUM_ARGS > 0 + + // Function objects + template + void init(FunctionObj /*f*/, function_obj_tag) + { + typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< + FunctionObj, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >::type + actual_invoker_type; + + invoker = &actual_invoker_type::invoke; + manager = &functor_manager::manage; + } + template + void init_a(FunctionObj /*f*/, function_obj_tag) + { + typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< + FunctionObj, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >::type + actual_invoker_type; + + invoker = &actual_invoker_type::invoke; + manager = &functor_manager_a::manage; + } + + // Assign to a function object using the small object optimization + template + void + assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) + { + new ((void*)&functor.data) FunctionObj(f); + } + template + void + assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) + { + assign_functor(f,functor,mpl::true_()); + } + + // Assign to a function object allocated on the heap. + template + void + assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) + { + functor.obj_ptr = new FunctionObj(f); + } + template + void + assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) + { + typedef functor_wrapper functor_wrapper_type; + typedef typename Allocator::template rebind::other + wrapper_allocator_type; + typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type; + wrapper_allocator_type wrapper_allocator(a); + wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); + wrapper_allocator.construct(copy, functor_wrapper_type(f,a)); + functor_wrapper_type* new_f = static_cast(copy); + functor.obj_ptr = new_f; + } + + template + bool + assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) + { + if (!boost::detail::function::has_empty_target(boost::addressof(f))) { + assign_functor(f, functor, + mpl::bool_<(function_allows_small_object_optimization::value)>()); + return true; + } else { + return false; + } + } + template + bool + assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) + { + if (!boost::detail::function::has_empty_target(boost::addressof(f))) { + assign_functor_a(f, functor, a, + mpl::bool_<(function_allows_small_object_optimization::value)>()); + return true; + } else { + return false; + } + } + + // Reference to a function object + template + void + init(const reference_wrapper& /*f*/, function_obj_ref_tag) + { + typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER< + FunctionObj, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >::type + actual_invoker_type; + + invoker = &actual_invoker_type::invoke; + manager = &reference_manager::get; + } + template + void + init_a(const reference_wrapper& f, function_obj_ref_tag) + { + init(f,function_obj_ref_tag()); + } + + template + bool + assign_to(const reference_wrapper& f, + function_buffer& functor, function_obj_ref_tag) + { + if (!boost::detail::function::has_empty_target(f.get_pointer())) { + // DPG TBD: We might need to detect constness of + // FunctionObj to assign into obj_ptr or const_obj_ptr to + // be truly legit, but no platform in existence makes + // const void* different from void*. + functor.const_obj_ptr = f.get_pointer(); + return true; + } else { + return false; + } + } + template + bool + assign_to_a(const reference_wrapper& f, + function_buffer& functor, Allocator, function_obj_ref_tag) + { + return assign_to(f,functor,function_obj_ref_tag()); + } + + public: + invoker_type invoker; + }; + } // end namespace function + } // end namespace detail + + template< + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + class BOOST_FUNCTION_FUNCTION : public function_base + +#if BOOST_FUNCTION_NUM_ARGS == 1 + + , public std::unary_function + +#elif BOOST_FUNCTION_NUM_ARGS == 2 + + , public std::binary_function + +#endif + + { + public: +#ifndef BOOST_NO_VOID_RETURNS + typedef R result_type; +#else + typedef typename boost::detail::function::function_return_type::type + result_type; +#endif // BOOST_NO_VOID_RETURNS + + private: + typedef boost::detail::function::BOOST_FUNCTION_VTABLE< + R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> + vtable_type; + + struct clear_type {}; + + public: + BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS); + + // add signature for boost::lambda + template + struct sig + { + typedef result_type type; + }; + +#if BOOST_FUNCTION_NUM_ARGS == 1 + typedef T0 argument_type; +#elif BOOST_FUNCTION_NUM_ARGS == 2 + typedef T0 first_argument_type; + typedef T1 second_argument_type; +#endif + + BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS); + BOOST_FUNCTION_ARG_TYPES + + typedef BOOST_FUNCTION_FUNCTION self_type; + + BOOST_FUNCTION_FUNCTION() : function_base() { } + + // MSVC chokes if the following two constructors are collapsed into + // one with a default parameter. + template + BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f +#ifndef BOOST_NO_SFINAE + ,typename enable_if_c< + (boost::type_traits::ice_not< + (is_integral::value)>::value), + int>::type = 0 +#endif // BOOST_NO_SFINAE + ) : + function_base() + { + this->assign_to(f); + } + template + BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a +#ifndef BOOST_NO_SFINAE + ,typename enable_if_c< + (boost::type_traits::ice_not< + (is_integral::value)>::value), + int>::type = 0 +#endif // BOOST_NO_SFINAE + ) : + function_base() + { + this->assign_to_a(f,a); + } + +#ifndef BOOST_NO_SFINAE + BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { } +#else + BOOST_FUNCTION_FUNCTION(int zero) : function_base() + { + BOOST_ASSERT(zero == 0); + } +#endif + + BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base() + { + this->assign_to_own(f); + } + + ~BOOST_FUNCTION_FUNCTION() { clear(); } + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + // MSVC 6.0 and prior require all definitions to be inline, but + // these definitions can become very costly. + result_type operator()(BOOST_FUNCTION_PARMS) const + { + if (this->empty()) + boost::throw_exception(bad_function_call()); + + return static_cast(vtable)->invoker + (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); + } +#else + result_type operator()(BOOST_FUNCTION_PARMS) const; +#endif + + // The distinction between when to use BOOST_FUNCTION_FUNCTION and + // when to use self_type is obnoxious. MSVC cannot handle self_type as + // the return type of these assignment operators, but Borland C++ cannot + // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to + // construct. + template +#ifndef BOOST_NO_SFINAE + typename enable_if_c< + (boost::type_traits::ice_not< + (is_integral::value)>::value), + BOOST_FUNCTION_FUNCTION&>::type +#else + BOOST_FUNCTION_FUNCTION& +#endif + operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) + { + this->clear(); + try { + this->assign_to(f); + } catch (...) { + vtable = 0; + throw; + } + return *this; + } + template + void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a) + { + this->clear(); + try { + this->assign_to_a(f,a); + } catch (...) { + vtable = 0; + throw; + } + } + +#ifndef BOOST_NO_SFINAE + BOOST_FUNCTION_FUNCTION& operator=(clear_type*) + { + this->clear(); + return *this; + } +#else + BOOST_FUNCTION_FUNCTION& operator=(int zero) + { + BOOST_ASSERT(zero == 0); + this->clear(); + return *this; + } +#endif + + // Assignment from another BOOST_FUNCTION_FUNCTION + BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f) + { + if (&f == this) + return *this; + + this->clear(); + try { + this->assign_to_own(f); + } catch (...) { + vtable = 0; + throw; + } + return *this; + } + + void swap(BOOST_FUNCTION_FUNCTION& other) + { + if (&other == this) + return; + + BOOST_FUNCTION_FUNCTION tmp = *this; + *this = other; + other = tmp; + } + + // Clear out a target, if there is one + void clear() + { + if (vtable) { + static_cast(vtable)->clear(this->functor); + vtable = 0; + } + } + +#if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG) + // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it + operator bool () const { return !this->empty(); } +#else + private: + struct dummy { + void nonnull() {}; + }; + + typedef void (dummy::*safe_bool)(); + + public: + operator safe_bool () const + { return (this->empty())? 0 : &dummy::nonnull; } + + bool operator!() const + { return this->empty(); } +#endif + + private: + void assign_to_own(const BOOST_FUNCTION_FUNCTION& f) + { + if (!f.empty()) { + this->vtable = f.vtable; + f.vtable->manager(f.functor, this->functor, + boost::detail::function::clone_functor_tag); + } + } + + template + void assign_to(Functor f) + { + static vtable_type stored_vtable(f); + if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable; + else vtable = 0; + } + template + void assign_to_a(Functor f,Allocator a) + { + static vtable_type stored_vtable(f,a); + if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable; + else vtable = 0; + } + }; + + template + inline void swap(BOOST_FUNCTION_FUNCTION< + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >& f1, + BOOST_FUNCTION_FUNCTION< + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >& f2) + { + f1.swap(f2); + } + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + template + typename BOOST_FUNCTION_FUNCTION< + R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type + BOOST_FUNCTION_FUNCTION + ::operator()(BOOST_FUNCTION_PARMS) const + { + if (this->empty()) + boost::throw_exception(bad_function_call()); + + return static_cast(vtable)->invoker + (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); + } +#endif + +// Poison comparisons between boost::function objects of the same type. +template + void operator==(const BOOST_FUNCTION_FUNCTION< + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS>&, + const BOOST_FUNCTION_FUNCTION< + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS>&); +template + void operator!=(const BOOST_FUNCTION_FUNCTION< + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS>&, + const BOOST_FUNCTION_FUNCTION< + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS>& ); + +#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) + +#if BOOST_FUNCTION_NUM_ARGS == 0 +#define BOOST_FUNCTION_PARTIAL_SPEC R (void) +#else +#define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T)) +#endif + +template +class function + : public BOOST_FUNCTION_FUNCTION +{ + typedef BOOST_FUNCTION_FUNCTION base_type; + typedef function self_type; + + struct clear_type {}; + +public: + + function() : base_type() {} + + template + function(Functor f +#ifndef BOOST_NO_SFINAE + ,typename enable_if_c< + (boost::type_traits::ice_not< + (is_integral::value)>::value), + int>::type = 0 +#endif + ) : + base_type(f) + { + } + template + function(Functor f, Allocator a +#ifndef BOOST_NO_SFINAE + ,typename enable_if_c< + (boost::type_traits::ice_not< + (is_integral::value)>::value), + int>::type = 0 +#endif + ) : + base_type(f,a) + { + } + +#ifndef BOOST_NO_SFINAE + function(clear_type*) : base_type() {} +#endif + + function(const self_type& f) : base_type(static_cast(f)){} + + function(const base_type& f) : base_type(static_cast(f)){} + + self_type& operator=(const self_type& f) + { + self_type(f).swap(*this); + return *this; + } + + template +#ifndef BOOST_NO_SFINAE + typename enable_if_c< + (boost::type_traits::ice_not< + (is_integral::value)>::value), + self_type&>::type +#else + self_type& +#endif + operator=(Functor f) + { + self_type(f).swap(*this); + return *this; + } + +#ifndef BOOST_NO_SFINAE + self_type& operator=(clear_type*) + { + this->clear(); + return *this; + } +#endif + + self_type& operator=(const base_type& f) + { + self_type(f).swap(*this); + return *this; + } +}; + +#undef BOOST_FUNCTION_PARTIAL_SPEC +#endif // have partial specialization + +} // end namespace boost + +// Cleanup after ourselves... +#undef BOOST_FUNCTION_VTABLE +#undef BOOST_FUNCTION_COMMA +#undef BOOST_FUNCTION_FUNCTION +#undef BOOST_FUNCTION_FUNCTION_INVOKER +#undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER +#undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER +#undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER +#undef BOOST_FUNCTION_FUNCTION_REF_INVOKER +#undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER +#undef BOOST_FUNCTION_GET_FUNCTION_INVOKER +#undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER +#undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER +#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER +#undef BOOST_FUNCTION_TEMPLATE_PARMS +#undef BOOST_FUNCTION_TEMPLATE_ARGS +#undef BOOST_FUNCTION_PARMS +#undef BOOST_FUNCTION_PARM +#undef BOOST_FUNCTION_ARGS +#undef BOOST_FUNCTION_ARG_TYPE +#undef BOOST_FUNCTION_ARG_TYPES +#undef BOOST_FUNCTION_VOID_RETURN_TYPE +#undef BOOST_FUNCTION_RETURN + +#if defined(BOOST_MSVC) +# pragma warning( pop ) +#endif diff --git a/win32/include/boost/function/gen_function_N.pl b/win32/include/boost/function/gen_function_N.pl new file mode 100755 index 000000000..6d1ca2f92 --- /dev/null +++ b/win32/include/boost/function/gen_function_N.pl @@ -0,0 +1,26 @@ +#!/usr/bin/perl -w +# +# Boost.Function library +# +# Copyright Douglas Gregor 2001-2003. Use, modification and +# distribution is subject to 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) +# +# For more information, see http://www.boost.org +use English; + +if ($#ARGV < 0) { + print "Usage: perl gen_function_N \n"; + exit; +} + + +$totalNumArgs = $ARGV[0]; +for ($numArgs = 0; $numArgs <= $totalNumArgs; ++$numArgs) { + open OUT, ">function$numArgs.hpp"; + print OUT "#define BOOST_FUNCTION_NUM_ARGS $numArgs\n"; + print OUT "#include \n"; + print OUT "#undef BOOST_FUNCTION_NUM_ARGS\n"; + close OUT; +} diff --git a/win32/include/boost/function_equal.hpp b/win32/include/boost/function_equal.hpp new file mode 100755 index 000000000..35e66421a --- /dev/null +++ b/win32/include/boost/function_equal.hpp @@ -0,0 +1,28 @@ +// Copyright Douglas Gregor 2004. +// Copyright 2005 Peter Dimov + +// Use, modification and distribution is subject to +// 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) + +// For more information, see http://www.boost.org +#ifndef BOOST_FUNCTION_EQUAL_HPP +#define BOOST_FUNCTION_EQUAL_HPP + +namespace boost { + +template + bool function_equal_impl(const F& f, const G& g, long) + { return f == g; } + +// function_equal_impl needs to be unqualified to pick +// user overloads on two-phase compilers + +template + bool function_equal(const F& f, const G& g) + { return function_equal_impl(f, g, 0); } + +} // end namespace boost + +#endif // BOOST_FUNCTION_EQUAL_HPP diff --git a/win32/include/boost/function_output_iterator.hpp b/win32/include/boost/function_output_iterator.hpp new file mode 100755 index 000000000..8227cbb53 --- /dev/null +++ b/win32/include/boost/function_output_iterator.hpp @@ -0,0 +1,56 @@ +// (C) Copyright Jeremy Siek 2001. +// 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) + +// Revision History: + +// 27 Feb 2001 Jeremy Siek +// Initial checkin. + +#ifndef BOOST_FUNCTION_OUTPUT_ITERATOR_HPP +#define BOOST_FUNCTION_OUTPUT_ITERATOR_HPP + +#include + +namespace boost { + + template + class function_output_iterator { + typedef function_output_iterator self; + public: + typedef std::output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + explicit function_output_iterator() {} + + explicit function_output_iterator(const UnaryFunction& f) + : m_f(f) {} + + struct output_proxy { + output_proxy(UnaryFunction& f) : m_f(f) { } + template output_proxy& operator=(const T& value) { + m_f(value); + return *this; + } + UnaryFunction& m_f; + }; + output_proxy operator*() { return output_proxy(m_f); } + self& operator++() { return *this; } + self& operator++(int) { return *this; } + private: + UnaryFunction m_f; + }; + + template + inline function_output_iterator + make_function_output_iterator(const UnaryFunction& f = UnaryFunction()) { + return function_output_iterator(f); + } + +} // namespace boost + +#endif // BOOST_FUNCTION_OUTPUT_ITERATOR_HPP diff --git a/win32/include/boost/function_types/components.hpp b/win32/include/boost/function_types/components.hpp new file mode 100755 index 000000000..6963d006a --- /dev/null +++ b/win32/include/boost/function_types/components.hpp @@ -0,0 +1,431 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_COMPONENTS_HPP_INCLUDED +#define BOOST_FT_COMPONENTS_HPP_INCLUDED + +#include + +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x656)) +# include + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# include +#endif + +#ifndef BOOST_FT_NO_CV_FUNC_SUPPORT +# include +#endif + +#include + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# if BOOST_FT_MAX_ARITY < 10 +# include +# elif BOOST_FT_MAX_ARITY < 20 +# include +# elif BOOST_FT_MAX_ARITY < 30 +# include +# elif BOOST_FT_MAX_ARITY < 40 +# include +# elif BOOST_FT_MAX_ARITY < 50 +# include +# endif +#else +# include +#endif + +#include +#include + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +namespace boost +{ + namespace function_types + { + + using mpl::placeholders::_; + + template< typename T, typename ClassTypeTransform = add_reference<_> > + struct components; + + namespace detail + { + template struct components_impl; +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x565)) + template struct components_bcc; +#endif + } + + template + struct components +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x565)) + : detail::components_impl +#else + : detail::components_bcc::type,T, + ClassTypeTransform> +#endif + { + typedef components type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,components,(T,ClassTypeTransform)) + }; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + namespace detail { + + struct components_mpl_sequence_tag; + + struct components_non_func_base + { + typedef mpl::vector0<> types; + typedef void function_arity; + + typedef detail::constant<0> bits; + typedef detail::constant<0> mask; + + typedef components_mpl_sequence_tag tag; + }; + + template + < typename Components + , typename IfTagged + , typename ThenTag + , typename DefaultBase = components_non_func_base + > + struct retagged_if + : mpl::if_ + < detail::represents_impl + , detail::changed_tag + , DefaultBase + >::type + { }; + + // We detect plain function types and function references as function + // pointers by recursive instantiation of components_impl. + // The third specialization of components_impl makes sure the recursion + // terminates (when adding pointers). + template + struct components_impl + : detail::retagged_if + < detail::components_impl + , pointer_tag, /* --> */ function_tag > + { }; + template + struct components_impl + : detail::retagged_if + < detail::components_impl + , pointer_tag, /* --> */ reference_tag > + { }; + +#if !BOOST_FT_NO_CV_FUNC_SUPPORT + // Retry the type with a member pointer attached to detect cv functions + class a_class; + + template + struct cv_func_base + : detail::retagged_if + { + typedef typename + mpl::remove + < typename Base::types + , typename detail::class_transform::type>::type + types; + }; + + template + struct components_impl + : mpl::if_ + < detail::represents_impl< detail::components_impl + , member_pointer_tag > + , detail::cv_func_base< detail::components_impl, T, L> + , components_non_func_base + >::type + { }; + + template + struct components_impl + : components_non_func_base + { }; +#else + template + struct components_impl + : components_non_func_base + { }; +#endif + + template + struct components_impl + : components_impl + { }; + + template + struct components_impl + : components_impl + { }; + + template + struct components_impl + : components_impl + { }; + + template + struct components_impl + : components_impl + { }; + + template + struct components_impl + : components_impl + { }; + + template + struct components_impl + : components_impl + { }; + + + template + struct member_obj_ptr_result + { typedef T & type; }; + + template + struct member_obj_ptr_result + { typedef T const & type; }; + + template + struct member_obj_ptr_result + { typedef T volatile & type; }; + + template + struct member_obj_ptr_result + { typedef T const volatile & type; }; + + template + struct member_obj_ptr_result + { typedef T & type; }; + + template + struct member_obj_ptr_result + { typedef T & type; }; + + template + struct member_obj_ptr_result + { typedef T & type; }; + + template + struct member_obj_ptr_result + { typedef T & type; }; + + template + struct member_obj_ptr_components + : member_object_pointer_base + { + typedef function_types::components type; + typedef components_mpl_sequence_tag tag; + + typedef mpl::integral_c function_arity; + + typedef mpl::vector2< typename detail::member_obj_ptr_result::type, + typename detail::class_transform::type > types; + }; + +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x565)) +# define BOOST_FT_variations BOOST_FT_pointer|BOOST_FT_member_pointer + + template + struct components_impl + : member_obj_ptr_components + { }; + +#else +# define BOOST_FT_variations BOOST_FT_pointer + + // This workaround removes the member pointer from the type to allow + // detection of member function pointers with BCC. + template + struct components_impl + : detail::retagged_if + < detail::components_impl::type *, L> + , pointer_tag, /* --> */ member_function_pointer_tag + , member_obj_ptr_components > + { }; + + // BCC lets us test the cv-qualification of a function type by template + // partial specialization - so we use this bug feature to find out the + // member function's cv-qualification (unfortunately there are some + // invisible modifiers that impose some limitations on these types even if + // we remove the qualifiers, So we cannot exploit the same bug to make the + // library work for cv-qualified function types). + template struct encode_cv + { typedef char (& type)[1]; BOOST_STATIC_CONSTANT(std::size_t, value = 1); }; + template struct encode_cv + { typedef char (& type)[2]; BOOST_STATIC_CONSTANT(std::size_t, value = 2); }; + template struct encode_cv + { typedef char (& type)[3]; BOOST_STATIC_CONSTANT(std::size_t, value = 3); }; + template struct encode_cv + { typedef char (& type)[4]; BOOST_STATIC_CONSTANT(std::size_t, value = 4); }; + + // For member function pointers we have to use a function template (partial + // template specialization for a member pointer drops the cv qualification + // of the function type). + template + typename encode_cv::type mfp_cv_tester(T C::*); + + template struct encode_mfp_cv + { + BOOST_STATIC_CONSTANT(std::size_t, value = + sizeof(detail::mfp_cv_tester((T)0L))); + }; + + // Associate bits with the CV codes above. + template struct cv_tag_mfp_impl; + + template struct cv_tag_mfp + : detail::cv_tag_mfp_impl + < ::boost::function_types::detail::encode_mfp_cv::value > + { }; + + template<> struct cv_tag_mfp_impl<1> : non_cv { }; + template<> struct cv_tag_mfp_impl<2> : const_non_volatile { }; + template<> struct cv_tag_mfp_impl<3> : volatile_non_const { }; + template<> struct cv_tag_mfp_impl<4> : cv_qualified { }; + + // Metafunction to decode the cv code and apply it to a type. + // We add a pointer, because otherwise cv-qualifiers won't stick (another bug). + template struct decode_cv; + + template struct decode_cv : mpl::identity {}; + template struct decode_cv : mpl::identity {}; + template struct decode_cv : mpl::identity {}; + template struct decode_cv + : mpl::identity {}; + + // The class type transformation comes after adding cv-qualifiers. We have + // wrap it to remove the pointer added in decode_cv_impl. + template struct bcc_class_transform_impl; + template struct bcc_class_transform_impl + : class_transform + { }; + + template struct bcc_class_transform + : bcc_class_transform_impl + < typename decode_cv + < T + , ::boost::function_types::detail::encode_mfp_cv::value + >::type + , L + > + { }; + + // After extracting the member pointee from the type the class type is still + // in the type (somewhere -- you won't see with RTTI, that is) and that type + // is flagged unusable and *not* identical to the nonmember function type. + // We can, however, decompose this type via components_impl but surprisingly + // a pointer to the const qualified class type pops up again as the first + // parameter type. + // We have to replace this type with the properly cv-qualified and + // transformed class type, integrate the cv qualification into the bits. + template + struct mfp_components; + + + template + struct mfp_components + { + private: + typedef typename mpl::front::type result_type; + typedef typename detail::bcc_class_transform::type class_type; + + typedef mpl::vector2 result_and_class_type; + + typedef typename + mpl::advance + < typename mpl::begin::type + , typename mpl::if_ + < mpl::equal_to< typename detail::classifier::function_arity + , typename Base::function_arity > + , mpl::integral_c , mpl::integral_c + >::type + >::type + from; + typedef typename mpl::end::type to; + + typedef mpl::iterator_range param_types; + + typedef mpl::joint_view< result_and_class_type, param_types> types_view; + public: + + typedef typename + mpl::reverse_copy > >::type + types; + + typedef typename + function_types::tag< Base, detail::cv_tag_mfp >::bits + bits; + + typedef typename Base::mask mask; + + typedef typename detail::classifier::function_arity function_arity; + + typedef components_mpl_sequence_tag tag; + }; + + // Now put it all together: detect cv-qualification of function types and do + // the weird transformations above for member function pointers. + template + struct components_bcc + : mpl::if_ + < detail::represents_impl< detail::components_impl + , member_function_pointer_tag> + , detail::mfp_components,T,OrigT,L> + , detail::components_impl + >::type + { }; + +#endif // end of BORLAND WORKAROUND + +#define BOOST_FT_al_path boost/function_types/detail/components_impl +#include + + } } // namespace function_types::detail + + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::components) + +} // namespace ::boost + +#include +#include + +#endif + diff --git a/win32/include/boost/function_types/config/cc_names.hpp b/win32/include/boost/function_types/config/cc_names.hpp new file mode 100755 index 000000000..135321916 --- /dev/null +++ b/win32/include/boost/function_types/config/cc_names.hpp @@ -0,0 +1,31 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_CONFIG_CC_NAMES_HPP_INCLUDED +#define BOOST_FT_CONFIG_CC_NAMES_HPP_INCLUDED + +#define BOOST_FT_BUILTIN_CC_NAMES \ + (( IMPLICIT , implicit_cc , BOOST_PP_EMPTY ))\ + (( CDECL , cdecl_cc , BOOST_PP_IDENTITY(__cdecl ) ))\ + (( STDCALL , stdcall_cc , BOOST_PP_IDENTITY(__stdcall ) ))\ + (( PASCAL , pascal_cc , BOOST_PP_IDENTITY(pascal ) ))\ + (( FASTCALL , fastcall_cc , BOOST_PP_IDENTITY(__fastcall) ))\ + (( CLRCALL , clrcall_cc , BOOST_PP_IDENTITY(__clrcall ) ))\ + (( THISCALL , thiscall_cc , BOOST_PP_IDENTITY(__thiscall) ))\ + (( IMPLICIT_THISCALL , thiscall_cc , BOOST_PP_EMPTY )) + +// append user-defined cc names to builtin ones +#ifdef BOOST_FT_CC_NAMES +# define BOOST_FT_CC_NAMES_SEQ BOOST_FT_BUILTIN_CC_NAMES BOOST_FT_CC_NAMES +# define BOOST_FT_CC_PREPROCESSING 1 +#else +# define BOOST_FT_CC_NAMES_SEQ BOOST_FT_BUILTIN_CC_NAMES +#endif + +#endif + diff --git a/win32/include/boost/function_types/config/compiler.hpp b/win32/include/boost/function_types/config/compiler.hpp new file mode 100755 index 000000000..c4d66a3e1 --- /dev/null +++ b/win32/include/boost/function_types/config/compiler.hpp @@ -0,0 +1,116 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_CONFIG_COMPILER_HPP_INCLUDED +#define BOOST_FT_CONFIG_COMPILER_HPP_INCLUDED + +#include +#include + +#if defined(BOOST_MSVC) + +# if BOOST_MSVC < 1310 +# error "unsupported compiler version" +# endif + +# ifdef BOOST_FT_AUTODETECT_CALLING_CONVENTIONS + + // enable clrcall calling covention (call to .NET managed code) when + // compiling with /clr +# if BOOST_MSVC >= 1400 && defined(__cplusplus_cli) +# ifndef BOOST_FT_CC_CLRCALL +# define BOOST_FT_CC_CLRCALL callable_builtin +# endif +# endif + + // Intel x86 architecture specific calling conventions +# ifdef _M_IX86 +# define BOOST_FT_COMMON_X86_CCs callable_builtin +# if BOOST_MSVC < 1400 + // version 7.1 is missing a keyword to specify the thiscall cc ... +# ifndef BOOST_FT_CC_IMPLICIT_THISCALL +# define BOOST_FT_CC_IMPLICIT_THISCALL non_variadic|member|callable_builtin +# ifndef BOOST_FT_CONFIG_OK +# pragma message("INFO| /Gd /Gr /Gz will compiler options will cause") +# pragma message("INFO| a compile error.") +# pragma message("INFO| Reconfigure Boost.FunctionTypes in this case.") +# pragma message("INFO| This message can be suppressed by defining") +# pragma message("INFO| BOOST_FT_CONFIG_OK.") +# endif +# endif +# else + // ...introduced in version 8 +# ifndef BOOST_FT_CC_THISCALL +# define BOOST_FT_CC_THISCALL non_variadic|member|callable_builtin +# endif +# endif +# endif +# endif + +#elif defined(__GNUC__) && !defined(BOOST_INTEL_LINUX) + +# if __GNUC__ < 3 +# error "unsupported compiler version" +# endif + +# ifdef BOOST_FT_AUTODETECT_CALLING_CONVENTIONS + +# if defined(__i386__) +# // see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20439 +# // see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29328 +# if BOOST_WORKAROUND(__GNUC__,BOOST_TESTED_AT(4)) +# ifndef BOOST_FT_CC_IMPLICIT +# define BOOST_FT_CC_IMPLICIT member|callable_builtin +# endif +# define BOOST_FT_COMMON_X86_CCs non_member|callable_builtin +# else +# define BOOST_FT_COMMON_X86_CCs callable_builtin +# endif +# else +# ifndef BOOST_FT_CC_IMPLICIT +# define BOOST_FT_CC_IMPLICIT callable_builtin +# endif +# endif +# endif + +# if (defined(BOOST_FT_CC_CDECL) || defined(BOOST_FT_COMMON_X86_CCs)) \ + && !defined(__cdecl) +# define __cdecl __attribute__((__cdecl__)) +# endif +# if (defined(BOOST_FT_CC_STDCALL) || defined(BOOST_FT_COMMON_X86_CCs)) \ + && !defined(__stdcall) +# define __stdcall __attribute__((__stdcall__)) +# endif +# if (defined(BOOST_FT_CC_FASTCALL) || defined(BOOST_FT_COMMON_X86_CCs)) \ + && !defined(__fastcall) +# define __fastcall __attribute__((__fastcall__)) +# endif + +#elif defined(__BORLANDC__) + +# if __BORLANDC__ < 0x550 +# error "unsupported compiler version" +# elif __BORLANDC__ > 0x565 +# pragma message("WARNING: library untested with this compiler version") +# endif + +# ifdef BOOST_FT_AUTODETECT_CALLING_CONVENTIONS +# define BOOST_FT_COMMON_X86_CCs callable_builtin +# endif + + // syntactic specialities of cc specifier +# define BOOST_FT_SYNTAX(result,lparen,cc_spec,type_mod,name,rparen) \ + result() cc_spec() lparen() type_mod() name() rparen() +#else + // only enable default calling convention +# define BOOST_FT_CC_IMPLICIT callable_builtin +#endif + + +#endif + diff --git a/win32/include/boost/function_types/config/config.hpp b/win32/include/boost/function_types/config/config.hpp new file mode 100755 index 000000000..49f0019ed --- /dev/null +++ b/win32/include/boost/function_types/config/config.hpp @@ -0,0 +1,59 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_CONFIG_HPP_INCLUDED +#define BOOST_FT_CONFIG_HPP_INCLUDED + +#include +#include + +// maximum allowed arity +#ifndef BOOST_FT_MAX_ARITY +#define BOOST_FT_MAX_ARITY 20 +#endif + +// the most common calling conventions for x86 architecture can be enabled at +// once in the compiler config +#ifdef BOOST_FT_COMMON_X86_CCs +# ifndef BOOST_FT_CC_CDECL +# define BOOST_FT_CC_CDECL BOOST_FT_COMMON_X86_CCs +# endif +# ifndef BOOST_FT_CC_STDCALL +# define BOOST_FT_CC_STDCALL non_variadic|BOOST_FT_COMMON_X86_CCs +# endif +# ifndef BOOST_FT_CC_FASTCALL +# define BOOST_FT_CC_FASTCALL non_variadic|BOOST_FT_COMMON_X86_CCs +# endif +#endif + +// where to place the cc specifier (the common way) +#ifndef BOOST_FT_SYNTAX +# define BOOST_FT_SYNTAX(result,lparen,cc_spec,type_mod,name,rparen) \ + result() lparen() cc_spec() type_mod() name() rparen() +#endif + +// param for nullary functions +// set to "void" for compilers that require nullary functions to read +// "R (void)" in template partial specialization +#ifndef BOOST_FT_NULLARY_PARAM +#define BOOST_FT_NULLARY_PARAM +#endif + +// there is a pending defect report on cv qualified function types, so support +// for these types is disabled, unless for compilers where it's known to work +#ifndef BOOST_FT_NO_CV_FUNC_SUPPORT +#define BOOST_FT_NO_CV_FUNC_SUPPORT 1 +#endif + +// full preprocessing implies preprocessing of the ccs +#if defined(BOOST_FT_PREPROCESSING_MODE) && !defined(BOOST_FT_CC_PREPROCESSING) +# define BOOST_FT_CC_PREPROCESSING 1 +#endif + +#endif + diff --git a/win32/include/boost/function_types/detail/class_transform.hpp b/win32/include/boost/function_types/detail/class_transform.hpp new file mode 100755 index 000000000..c354aa012 --- /dev/null +++ b/win32/include/boost/function_types/detail/class_transform.hpp @@ -0,0 +1,62 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_DETAIL_CLASS_TRANSFORM_HPP_INCLUDED +#define BOOST_FT_DETAIL_CLASS_TRANSFORM_HPP_INCLUDED + +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { namespace function_types { namespace detail { + +using mpl::placeholders::_; + +// Transformation metafunction for the class type of member function pointers. +template +struct class_transform +{ typedef typename mpl::apply1::type type; }; + + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +// We can short-circuit the mechanism implemented in the primary template for +// the most common lambda expression and save both the "un-lambdaing" and the +// type traits invocation (we know that T can only be a class type). + +template struct class_transform< T, mpl::identity<_> > +{ typedef T type; }; + +template struct class_transform< T, add_reference<_> > +{ typedef T & type; }; + +template struct class_transform< T, add_pointer<_> > +{ typedef T * type; }; + +template struct class_transform< T, remove_cv<_> > +{ typedef typename boost::remove_cv::type type; }; + +template struct class_transform< T, add_reference< remove_cv<_> > > +{ typedef typename boost::remove_cv::type & type; }; + +template struct class_transform< T, add_pointer< remove_cv<_> > > +{ typedef typename boost::remove_cv::type * type; }; + +template struct class_transform< T, mpl::always > +{ typedef U type; }; +#endif + + +} } } // namespace ::boost::function_types::detail + +#endif + diff --git a/win32/include/boost/function_types/detail/classifier.hpp b/win32/include/boost/function_types/detail/classifier.hpp new file mode 100755 index 000000000..401e7f842 --- /dev/null +++ b/win32/include/boost/function_types/detail/classifier.hpp @@ -0,0 +1,82 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_DETAIL_CLASSIFIER_HPP_INCLUDED +#define BOOST_FT_DETAIL_CLASSIFIER_HPP_INCLUDED + +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { namespace function_types { namespace detail { + +template struct classifier; + +template struct char_array { typedef char (&type)[S]; }; + +template struct encode_charr +{ + typedef typename char_array< + ::boost::function_types::detail::encode_charr_impl::value + >::type type; +}; + +char BOOST_TT_DECL classifier_impl(...); + +#define BOOST_FT_variations BOOST_FT_function|BOOST_FT_pointer|\ + BOOST_FT_member_pointer + +#define BOOST_FT_type_function(cc,name) BOOST_FT_SYNTAX( \ + R BOOST_PP_EMPTY,BOOST_PP_LPAREN,cc,* BOOST_PP_EMPTY,name,BOOST_PP_RPAREN) + +#define BOOST_FT_type_function_pointer(cc,name) BOOST_FT_SYNTAX( \ + R BOOST_PP_EMPTY,BOOST_PP_LPAREN,cc,** BOOST_PP_EMPTY,name,BOOST_PP_RPAREN) + +#define BOOST_FT_type_member_function_pointer(cc,name) BOOST_FT_SYNTAX( \ + R BOOST_PP_EMPTY,BOOST_PP_LPAREN,cc,T0::** BOOST_PP_EMPTY,name,BOOST_PP_RPAREN) + +#define BOOST_FT_al_path boost/function_types/detail/classifier_impl +#include + +template struct classifier_bits +{ + static typename boost::add_reference::type tester; + + BOOST_STATIC_CONSTANT(bits_t,value = (bits_t)sizeof( + boost::function_types::detail::classifier_impl(& tester) + )-1); +}; + +template struct classifier +{ + typedef detail::constant< + ::boost::function_types::detail::decode_bits< + ::boost::function_types::detail::classifier_bits::value + >::tag_bits > + bits; + + typedef detail::full_mask mask; + + typedef detail::constant< + ::boost::function_types::detail::decode_bits< + ::boost::function_types::detail::classifier_bits::value + >::arity > + function_arity; +}; + + + +} } } // namespace ::boost::function_types::detail + +#endif + diff --git a/win32/include/boost/function_types/detail/classifier_impl/arity10_0.hpp b/win32/include/boost/function_types/detail/classifier_impl/arity10_0.hpp new file mode 100755 index 000000000..bc3913215 --- /dev/null +++ b/win32/include/boost/function_types/detail/classifier_impl/arity10_0.hpp @@ -0,0 +1,55 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +template< typename R > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (BOOST_FT_nullary_param BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 BOOST_FT_ell) BOOST_FT_cv); + diff --git a/win32/include/boost/function_types/detail/classifier_impl/arity10_1.hpp b/win32/include/boost/function_types/detail/classifier_impl/arity10_1.hpp new file mode 100755 index 000000000..e9f5f8127 --- /dev/null +++ b/win32/include/boost/function_types/detail/classifier_impl/arity10_1.hpp @@ -0,0 +1,52 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +template< typename R , typename T0 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) ( BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 BOOST_FT_ell) BOOST_FT_cv); + diff --git a/win32/include/boost/function_types/detail/classifier_impl/arity20_0.hpp b/win32/include/boost/function_types/detail/classifier_impl/arity20_0.hpp new file mode 100755 index 000000000..589ca5883 --- /dev/null +++ b/win32/include/boost/function_types/detail/classifier_impl/arity20_0.hpp @@ -0,0 +1,53 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 BOOST_FT_ell) BOOST_FT_cv); + diff --git a/win32/include/boost/function_types/detail/classifier_impl/arity20_1.hpp b/win32/include/boost/function_types/detail/classifier_impl/arity20_1.hpp new file mode 100755 index 000000000..35aedeba2 --- /dev/null +++ b/win32/include/boost/function_types/detail/classifier_impl/arity20_1.hpp @@ -0,0 +1,53 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 BOOST_FT_ell) BOOST_FT_cv); + diff --git a/win32/include/boost/function_types/detail/classifier_impl/arity30_0.hpp b/win32/include/boost/function_types/detail/classifier_impl/arity30_0.hpp new file mode 100755 index 000000000..928966c94 --- /dev/null +++ b/win32/include/boost/function_types/detail/classifier_impl/arity30_0.hpp @@ -0,0 +1,53 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 BOOST_FT_ell) BOOST_FT_cv); + diff --git a/win32/include/boost/function_types/detail/classifier_impl/arity30_1.hpp b/win32/include/boost/function_types/detail/classifier_impl/arity30_1.hpp new file mode 100755 index 000000000..792d750ec --- /dev/null +++ b/win32/include/boost/function_types/detail/classifier_impl/arity30_1.hpp @@ -0,0 +1,53 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 BOOST_FT_ell) BOOST_FT_cv); + diff --git a/win32/include/boost/function_types/detail/classifier_impl/arity40_0.hpp b/win32/include/boost/function_types/detail/classifier_impl/arity40_0.hpp new file mode 100755 index 000000000..42695617f --- /dev/null +++ b/win32/include/boost/function_types/detail/classifier_impl/arity40_0.hpp @@ -0,0 +1,53 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 BOOST_FT_ell) BOOST_FT_cv); + diff --git a/win32/include/boost/function_types/detail/classifier_impl/arity40_1.hpp b/win32/include/boost/function_types/detail/classifier_impl/arity40_1.hpp new file mode 100755 index 000000000..b312bcfb8 --- /dev/null +++ b/win32/include/boost/function_types/detail/classifier_impl/arity40_1.hpp @@ -0,0 +1,53 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 BOOST_FT_ell) BOOST_FT_cv); + diff --git a/win32/include/boost/function_types/detail/classifier_impl/arity50_0.hpp b/win32/include/boost/function_types/detail/classifier_impl/arity50_0.hpp new file mode 100755 index 000000000..dee818f8a --- /dev/null +++ b/win32/include/boost/function_types/detail/classifier_impl/arity50_0.hpp @@ -0,0 +1,53 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 , typename T48 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 , T48 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 , typename T48 , typename T49 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 , T48 , T49 BOOST_FT_ell) BOOST_FT_cv); + diff --git a/win32/include/boost/function_types/detail/classifier_impl/arity50_1.hpp b/win32/include/boost/function_types/detail/classifier_impl/arity50_1.hpp new file mode 100755 index 000000000..ac6ed1a4e --- /dev/null +++ b/win32/include/boost/function_types/detail/classifier_impl/arity50_1.hpp @@ -0,0 +1,52 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 , typename T48 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 , T48 BOOST_FT_ell) BOOST_FT_cv); +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 , typename T48 , typename T49 > +typename encode_charr ::type +classifier_impl(BOOST_FT_syntax(BOOST_FT_cc, BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 , T48 , T49 BOOST_FT_ell) BOOST_FT_cv); diff --git a/win32/include/boost/function_types/detail/classifier_impl/master.hpp b/win32/include/boost/function_types/detail/classifier_impl/master.hpp new file mode 100755 index 000000000..0a2491123 --- /dev/null +++ b/win32/include/boost/function_types/detail/classifier_impl/master.hpp @@ -0,0 +1,33 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +#if BOOST_FT_ARITY_LOOP_PREFIX + +# ifndef BOOST_FT_DETAIL_CLASSIFIER_IMPL_MASTER_HPP_INCLUDED +# define BOOST_FT_DETAIL_CLASSIFIER_IMPL_MASTER_HPP_INCLUDED +# include +# endif + +# define BOOST_FT_type_name + +#elif BOOST_FT_ARITY_LOOP_IS_ITERATING + +template< BOOST_FT_tplargs(BOOST_PP_IDENTITY(typename)) > +typename encode_charr::type +classifier_impl(BOOST_FT_type); + +#elif BOOST_FT_ARITY_LOOP_SUFFIX + +# undef BOOST_FT_type_name + +#else +# error "attempt to use arity loop master file without loop" +#endif + diff --git a/win32/include/boost/function_types/detail/components_as_mpl_sequence.hpp b/win32/include/boost/function_types/detail/components_as_mpl_sequence.hpp new file mode 100755 index 000000000..feefef00d --- /dev/null +++ b/win32/include/boost/function_types/detail/components_as_mpl_sequence.hpp @@ -0,0 +1,138 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_DETAIL_COMPONENTS_AS_MPL_SEQUENCE_HPP_INCLUDED +#define BOOST_FT_DETAIL_COMPONENTS_AS_MPL_SEQUENCE_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +template<> struct size_impl +< function_types::detail::components_mpl_sequence_tag > +{ + template< typename S > struct apply + : mpl::size + { }; +}; +template<> struct empty_impl +< function_types::detail::components_mpl_sequence_tag > +{ + template< typename S > struct apply + : mpl::empty + { }; +}; +template<> struct front_impl +< function_types::detail::components_mpl_sequence_tag > +{ + template< typename S > struct apply + : mpl::front + { }; +}; +template<> struct back_impl +< function_types::detail::components_mpl_sequence_tag > +{ + template< typename S > struct apply + : mpl::back + { }; +}; +template<> struct at_impl +< function_types::detail::components_mpl_sequence_tag > +{ + template< typename S, typename N > struct apply + : mpl::at + { }; +}; +template<> struct begin_impl +< function_types::detail::components_mpl_sequence_tag > +{ + template< typename S > struct apply + : mpl::begin + { }; +}; +template<> struct end_impl +< function_types::detail::components_mpl_sequence_tag > +{ + template< typename S > struct apply + : mpl::end + { }; +}; +template<> struct clear_impl +< function_types::detail::components_mpl_sequence_tag > +{ + template< typename S > + struct apply + : S + { + typedef apply type; + typedef typename mpl::clear< typename S::types >::type types; + }; +}; +template<> +struct push_front_impl +< function_types::detail::components_mpl_sequence_tag > +{ + template< typename S, typename T > + struct apply + : S + { + typedef apply type; + typedef typename mpl::push_front< typename S::types, T >::type types; + }; +}; +template<> +struct pop_front_impl +< function_types::detail::components_mpl_sequence_tag > +{ + template< typename S > + struct apply + : S + { + typedef apply type; + typedef typename mpl::pop_front< typename S::types >::type types; + }; +}; +template<> +struct push_back_impl +< function_types::detail::components_mpl_sequence_tag > +{ + template< typename S, typename T > + struct apply + : S + { + typedef apply type; + typedef typename mpl::push_back< typename S::types, T >::type types; + }; +}; +template<> +struct pop_back_impl +< function_types::detail::components_mpl_sequence_tag > +{ + template< typename S > + struct apply + : S + { + typedef apply type; + typedef typename mpl::pop_back< typename S::types >::type types; + }; +}; + +} } // namespace ::boost::mpl + +#endif + diff --git a/win32/include/boost/function_types/detail/components_impl/arity10_0.hpp b/win32/include/boost/function_types/detail/components_impl/arity10_0.hpp new file mode 100755 index 000000000..6cbd0db65 --- /dev/null +++ b/win32/include/boost/function_types/detail/components_impl/arity10_0.hpp @@ -0,0 +1,132 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +template< typename R, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector1< R BOOST_FT_nullary_param > types; +}; +template< typename R , typename T0, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector2< R , T0 > types; +}; +template< typename R , typename T0 , typename T1, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector3< R , T0 , T1 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector4< R , T0 , T1 , T2 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector5< R , T0 , T1 , T2 , T3 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector6< R , T0 , T1 , T2 , T3 , T4 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector7< R , T0 , T1 , T2 , T3 , T4 , T5 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector8< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector9< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector10< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector11< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 > types; +}; + diff --git a/win32/include/boost/function_types/detail/components_impl/arity10_1.hpp b/win32/include/boost/function_types/detail/components_impl/arity10_1.hpp new file mode 100755 index 000000000..a0a35dea2 --- /dev/null +++ b/win32/include/boost/function_types/detail/components_impl/arity10_1.hpp @@ -0,0 +1,122 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +template< typename R , typename T0, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector2< R, typename class_transform ::type > types; +}; +template< typename R , typename T0 , typename T1, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector3< R, typename class_transform ::type , T1 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector4< R, typename class_transform ::type , T1 , T2 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector5< R, typename class_transform ::type , T1 , T2 , T3 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector6< R, typename class_transform ::type , T1 , T2 , T3 , T4 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector7< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector8< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector9< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector10< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector11< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 > types; +}; + diff --git a/win32/include/boost/function_types/detail/components_impl/arity20_0.hpp b/win32/include/boost/function_types/detail/components_impl/arity20_0.hpp new file mode 100755 index 000000000..224403f4f --- /dev/null +++ b/win32/include/boost/function_types/detail/components_impl/arity20_0.hpp @@ -0,0 +1,123 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector12< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector13< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector14< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector15< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector16< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector17< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector18< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector19< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector20< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector21< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 > types; +}; + diff --git a/win32/include/boost/function_types/detail/components_impl/arity20_1.hpp b/win32/include/boost/function_types/detail/components_impl/arity20_1.hpp new file mode 100755 index 000000000..fb51b6301 --- /dev/null +++ b/win32/include/boost/function_types/detail/components_impl/arity20_1.hpp @@ -0,0 +1,123 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector12< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector13< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector14< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector15< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector16< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector17< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector18< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector19< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector20< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector21< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 > types; +}; + diff --git a/win32/include/boost/function_types/detail/components_impl/arity30_0.hpp b/win32/include/boost/function_types/detail/components_impl/arity30_0.hpp new file mode 100755 index 000000000..56ba414a5 --- /dev/null +++ b/win32/include/boost/function_types/detail/components_impl/arity30_0.hpp @@ -0,0 +1,123 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector22< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector23< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector24< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector25< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector26< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector27< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector28< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector29< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector30< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector31< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 > types; +}; + diff --git a/win32/include/boost/function_types/detail/components_impl/arity30_1.hpp b/win32/include/boost/function_types/detail/components_impl/arity30_1.hpp new file mode 100755 index 000000000..583a8cdd7 --- /dev/null +++ b/win32/include/boost/function_types/detail/components_impl/arity30_1.hpp @@ -0,0 +1,123 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector22< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector23< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector24< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector25< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector26< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector27< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector28< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector29< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector30< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector31< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 > types; +}; + diff --git a/win32/include/boost/function_types/detail/components_impl/arity40_0.hpp b/win32/include/boost/function_types/detail/components_impl/arity40_0.hpp new file mode 100755 index 000000000..9c43fc1fe --- /dev/null +++ b/win32/include/boost/function_types/detail/components_impl/arity40_0.hpp @@ -0,0 +1,123 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector32< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector33< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector34< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector35< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector36< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector37< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector38< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector39< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector40< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector41< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 > types; +}; + diff --git a/win32/include/boost/function_types/detail/components_impl/arity40_1.hpp b/win32/include/boost/function_types/detail/components_impl/arity40_1.hpp new file mode 100755 index 000000000..739abdd5e --- /dev/null +++ b/win32/include/boost/function_types/detail/components_impl/arity40_1.hpp @@ -0,0 +1,123 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector32< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector33< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector34< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector35< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector36< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector37< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector38< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector39< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector40< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector41< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 > types; +}; + diff --git a/win32/include/boost/function_types/detail/components_impl/arity50_0.hpp b/win32/include/boost/function_types/detail/components_impl/arity50_0.hpp new file mode 100755 index 000000000..335e41250 --- /dev/null +++ b/win32/include/boost/function_types/detail/components_impl/arity50_0.hpp @@ -0,0 +1,123 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector42< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector43< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector44< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector45< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector46< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector47< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector48< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector49< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 , typename T48, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector50< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 , T48 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 , typename T48 , typename T49, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector51< R , T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 , T48 , T49 > types; +}; + diff --git a/win32/include/boost/function_types/detail/components_impl/arity50_1.hpp b/win32/include/boost/function_types/detail/components_impl/arity50_1.hpp new file mode 100755 index 000000000..b064ef74a --- /dev/null +++ b/win32/include/boost/function_types/detail/components_impl/arity50_1.hpp @@ -0,0 +1,123 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector42< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector43< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector44< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector45< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector46< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector47< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector48< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector49< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 , typename T48, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector50< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 , T48 > types; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 , typename T48 , typename T49, typename L> +struct components_impl +{ +typedef encode_bits bits; +typedef constant mask; +typedef function_types::components type; +typedef components_mpl_sequence_tag tag; +typedef mpl::integral_c function_arity; +typedef mpl::vector51< R, typename class_transform ::type , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 , T48 , T49 > types; +}; + diff --git a/win32/include/boost/function_types/detail/components_impl/master.hpp b/win32/include/boost/function_types/detail/components_impl/master.hpp new file mode 100755 index 000000000..dba84670d --- /dev/null +++ b/win32/include/boost/function_types/detail/components_impl/master.hpp @@ -0,0 +1,61 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +#if BOOST_FT_ARITY_LOOP_PREFIX + +# ifndef BOOST_FT_DETAIL_COMPONENTS_IMPL_MASTER_HPP_INCLUDED +# define BOOST_FT_DETAIL_COMPONENTS_IMPL_MASTER_HPP_INCLUDED +# include +# include +# include +# include +# include +# endif + +# define BOOST_FT_type_name + +# if !BOOST_FT_mfp + +# define BOOST_FT_types \ + R BOOST_PP_COMMA_IF(BOOST_FT_arity) BOOST_FT_params(BOOST_PP_EMPTY) +# else + +# define BOOST_FT_types \ + R, typename class_transform::type \ + BOOST_PP_COMMA_IF(BOOST_PP_DEC(BOOST_FT_arity)) \ + BOOST_FT_params(BOOST_PP_EMPTY) + +# endif + +#elif BOOST_FT_ARITY_LOOP_IS_ITERATING + +template< BOOST_FT_tplargs(BOOST_PP_IDENTITY(typename)), typename L> +struct components_impl +{ + typedef encode_bits bits; + typedef constant mask; + + typedef function_types::components type; + typedef components_mpl_sequence_tag tag; + + typedef mpl::integral_c function_arity; + + typedef BOOST_PP_CAT(mpl::vector,BOOST_FT_n)< BOOST_FT_types > types; +}; + +#elif BOOST_FT_ARITY_LOOP_SUFFIX + +# undef BOOST_FT_types +# undef BOOST_FT_type_name + +#else +# error "attempt to use arity loop master file without loop" +#endif + diff --git a/win32/include/boost/function_types/detail/cv_traits.hpp b/win32/include/boost/function_types/detail/cv_traits.hpp new file mode 100755 index 000000000..8381d8c0e --- /dev/null +++ b/win32/include/boost/function_types/detail/cv_traits.hpp @@ -0,0 +1,134 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_DETAIL_CV_TRAITS_HPP_INCLUDED +#define BOOST_FT_DETAIL_CV_TRAITS_HPP_INCLUDED + +#include +#include + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + || BOOST_WORKAROUND(__BORLANDC__, <= 0x582) +# include +# include +# include +#endif + +#include + +namespace boost { namespace function_types { namespace detail { + +#if ! (defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + || BOOST_WORKAROUND(__BORLANDC__, <= 0x582)) + +template struct cv_traits +{ typedef non_cv tag; typedef T type; }; +template struct cv_traits +{ typedef non_cv tag; typedef T type; }; +template struct cv_traits +{ typedef non_cv tag; typedef T type; }; +template struct cv_traits +{ typedef non_cv tag; typedef T type; }; +template struct cv_traits +{ typedef non_cv tag; typedef T type; }; +template struct cv_traits +{ typedef non_cv tag; typedef T type; }; + +template struct cv_traits +{ typedef const_non_volatile tag; typedef T type; }; +template struct cv_traits +{ typedef const_non_volatile tag; typedef T type; }; +template struct cv_traits +{ typedef const_non_volatile tag; typedef T type; }; +template struct cv_traits +{ typedef const_non_volatile tag; typedef T type; }; +template struct cv_traits +{ typedef const_non_volatile tag; typedef T type; }; +template struct cv_traits +{ typedef const_non_volatile tag; typedef T type; }; + +template struct cv_traits +{ typedef volatile_non_const tag; typedef T type; }; +template struct cv_traits +{ typedef volatile_non_const tag; typedef T type; }; +template struct cv_traits +{ typedef volatile_non_const tag; typedef T type; }; +template struct cv_traits +{ typedef volatile_non_const tag; typedef T type; }; +template struct cv_traits +{ typedef volatile_non_const tag; typedef T type; }; +template struct cv_traits +{ typedef volatile_non_const tag; typedef T type; }; + +template struct cv_traits +{ typedef cv_qualified tag; typedef T type; }; +template struct cv_traits +{ typedef cv_qualified tag; typedef T type; }; +template struct cv_traits +{ typedef cv_qualified tag; typedef T type; }; +template struct cv_traits +{ typedef cv_qualified tag; typedef T type; }; +template struct cv_traits +{ typedef cv_qualified tag; typedef T type; }; +template struct cv_traits +{ typedef cv_qualified tag; typedef T type; }; + +#else +template struct cv_tag_impl; + +template<> struct cv_tag_impl<1> { typedef non_cv type;}; +template<> struct cv_tag_impl<2> { typedef const_non_volatile type; }; +template<> struct cv_tag_impl<3> { typedef volatile_non_const type; }; +template<> struct cv_tag_impl<4> { typedef cv_qualified type; }; + +typedef char (& case_1)[1]; +typedef char (& case_2)[2]; +typedef char (& case_3)[3]; +typedef char (& case_4)[4]; + +template case_1 switch_cv(T *); +template case_2 switch_cv(T const *); +template case_3 switch_cv(T volatile *); +template case_4 switch_cv(T const volatile *); + +template T * ref_to_ptr(T &); +template T const * ref_to_ptr(T const &); +template T volatile * ref_to_ptr(T volatile &); +template T const volatile * ref_to_ptr(T const volatile &); + +template T * ref_to_ptr(T * const volatile &); + +template +struct cv_code +{ + static T _t; + BOOST_STATIC_CONSTANT(std::size_t, value = + sizeof(::boost::function_types::detail::switch_cv( + ::boost::function_types::detail::ref_to_ptr(_t) ) )); +}; + +template struct cv_traits +{ + typedef typename boost::function_types::detail::cv_tag_impl< + ::boost::function_types::detail::cv_code::value >::type + tag; + + // may require Boost.TypeTraits broken compiler specializations + // to work + typedef typename boost::remove_cv< + typename boost::remove_pointer< + typename boost::remove_reference::type + >::type + >::type type; +}; +#endif + +} } } // namespace boost::function_types::detail + +#endif + diff --git a/win32/include/boost/function_types/detail/encoding/aliases_def.hpp b/win32/include/boost/function_types/detail/encoding/aliases_def.hpp new file mode 100755 index 000000000..2cf2379a8 --- /dev/null +++ b/win32/include/boost/function_types/detail/encoding/aliases_def.hpp @@ -0,0 +1,16 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusions + +#define callable_builtin BOOST_FT_callable_builtin +#define member BOOST_FT_member_pointer +#define non_member BOOST_FT_non_member +#define variadic BOOST_FT_variadic +#define non_variadic BOOST_FT_non_variadic + diff --git a/win32/include/boost/function_types/detail/encoding/aliases_undef.hpp b/win32/include/boost/function_types/detail/encoding/aliases_undef.hpp new file mode 100755 index 000000000..f5f1c093f --- /dev/null +++ b/win32/include/boost/function_types/detail/encoding/aliases_undef.hpp @@ -0,0 +1,16 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusions + +#undef callable_builtin +#undef member +#undef non_member +#undef variadic +#undef non_variadic + diff --git a/win32/include/boost/function_types/detail/encoding/def.hpp b/win32/include/boost/function_types/detail/encoding/def.hpp new file mode 100755 index 000000000..20e19d765 --- /dev/null +++ b/win32/include/boost/function_types/detail/encoding/def.hpp @@ -0,0 +1,51 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusions + +// Type encoding: +// +// bit 0: callable builtin +// bit 1: non member +// bit 2: naked function +// bit 3: pointer +// bit 4: reference +// bit 5: member pointer +// bit 6: member function pointer +// bit 7: member object pointer + +#define BOOST_FT_type_mask 0x000000ff // 1111 1111 +#define BOOST_FT_callable_builtin 0x00000001 // 0000 0001 +#define BOOST_FT_non_member 0x00000002 // 0000 0010 +#define BOOST_FT_function 0x00000007 // 0000 0111 +#define BOOST_FT_pointer 0x0000000b // 0000 1011 +#define BOOST_FT_reference 0x00000013 // 0001 0011 +#define BOOST_FT_non_member_callable_builtin 0x00000003 // 0000 0011 +#define BOOST_FT_member_pointer 0x00000020 // 0010 0000 +#define BOOST_FT_member_function_pointer 0x00000061 // 0110 0001 +#define BOOST_FT_member_object_pointer 0x000000a3 // 1010 0001 +#define BOOST_FT_member_object_pointer_flags 0x000002a3 + +#define BOOST_FT_variadic 0x00000100 +#define BOOST_FT_non_variadic 0x00000200 +#define BOOST_FT_variadic_mask 0x00000300 + +#define BOOST_FT_const 0x00000400 +#define BOOST_FT_volatile 0x00000800 + +#define BOOST_FT_default_cc 0x00008000 +#define BOOST_FT_cc_mask 0x00ff8000 + +#define BOOST_FT_kind_mask 0x000000fc + +#define BOOST_FT_flags_mask 0x00000fff +#define BOOST_FT_full_mask 0x00ff0fff + +#define BOOST_FT_arity_shift 24 +#define BOOST_FT_arity_mask 0x7f000000 + diff --git a/win32/include/boost/function_types/detail/encoding/undef.hpp b/win32/include/boost/function_types/detail/encoding/undef.hpp new file mode 100755 index 000000000..c87a86ece --- /dev/null +++ b/win32/include/boost/function_types/detail/encoding/undef.hpp @@ -0,0 +1,38 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +#undef BOOST_FT_type_mask +#undef BOOST_FT_kind_mask +#undef BOOST_FT_callable_builtin +#undef BOOST_FT_non_member +#undef BOOST_FT_function +#undef BOOST_FT_pointer +#undef BOOST_FT_reference +#undef BOOST_FT_non_member_callable_builtin +#undef BOOST_FT_member_pointer +#undef BOOST_FT_member_function_pointer +#undef BOOST_FT_member_object_pointer +#undef BOOST_FT_member_object_pointer_flags + +#undef BOOST_FT_variadic +#undef BOOST_FT_non_variadic +#undef BOOST_FT_variadic_mask + +#undef BOOST_FT_const +#undef BOOST_FT_volatile + +#undef BOOST_FT_default_cc +#undef BOOST_FT_cc_mask + +#undef BOOST_FT_flags_mask +#undef BOOST_FT_full_mask + +#undef BOOST_FT_arity_mask + diff --git a/win32/include/boost/function_types/detail/pp_arity_loop.hpp b/win32/include/boost/function_types/detail/pp_arity_loop.hpp new file mode 100755 index 000000000..079476521 --- /dev/null +++ b/win32/include/boost/function_types/detail/pp_arity_loop.hpp @@ -0,0 +1,149 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +#ifndef BOOST_FT_PREPROCESSING_MODE +// input: BOOST_FT_mfp 0 or 1 <=> member function pointer? +// input: BOOST_FT_type_name BOOST_FT_type --> "R (* ..._type_name)()" (pass2) +#endif +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +#ifdef __WAVE__ +# pragma wave option(preserve: 0) +#endif + +#ifndef BOOST_FT_ARITY_LOOP_IS_ITERATING + +# define BOOST_FT_AL_PREPROCESSED \ + BOOST_FT_AL_FILE(BOOST_FT_al_path,BOOST_FT_FROM_ARITY,BOOST_FT_mfp) + +# define BOOST_FT_AL_FILE(base_path,max_arity,mfp) \ + BOOST_FT_AL_FILE_I(base_path,max_arity,mfp) +# define BOOST_FT_AL_FILE_I(base_path,max_arity,mfp) \ + + +# if !defined(BOOST_FT_PREPROCESSING_MODE) + +# if BOOST_FT_MAX_ARITY < 10 +# define BOOST_FT_FROM_ARITY 0 +# elif BOOST_FT_MAX_ARITY < 20 +# define BOOST_FT_FROM_ARITY 10 +# elif BOOST_FT_MAX_ARITY < 30 +# define BOOST_FT_FROM_ARITY 20 +# elif BOOST_FT_MAX_ARITY < 40 +# define BOOST_FT_FROM_ARITY 30 +# endif + +# if BOOST_FT_FROM_ARITY +# include BOOST_FT_AL_PREPROCESSED +# endif + +# elif !defined(BOOST_FT_FROM_ARITY) // single pass preprocessing +# define BOOST_FT_FROM_ARITY 0 + +# elif BOOST_FT_FROM_ARITY > 0 // arity20 includes arity10 +BOOST_PP_EXPAND(#) include BOOST_FT_AL_PREPROCESSED +# endif + +# undef BOOST_FT_AL_PREPROCESSED + +# undef BOOST_FT_AL_FILE +# undef BOOST_FT_AL_FILE_I + +# if BOOST_FT_MAX_ARITY > BOOST_FT_FROM_ARITY + +# ifndef BOOST_FT_DETAIL_ARITY_LOOP_HPP_INCLUDED +# define BOOST_FT_DETAIL_ARITY_LOOP_HPP_INCLUDED +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# endif + +# define BOOST_FT_AL_INCLUDE_FILE + +# define BOOST_FT_ARITY_LOOP_PREFIX 1 +# include BOOST_FT_AL_INCLUDE_FILE +# undef BOOST_FT_ARITY_LOOP_PREFIX + +# if !BOOST_PP_IS_ITERATING +# define BOOST_PP_FILENAME_1 BOOST_FT_AL_INCLUDE_FILE +# elif BOOST_PP_ITERATION_DEPTH() == 1 +# define BOOST_PP_FILENAME_2 BOOST_FT_AL_INCLUDE_FILE +# else +# error "loops nested too deeply" +# endif + +# define BOOST_FT_arity BOOST_PP_ITERATION() +# define BOOST_FT_n BOOST_PP_INC(BOOST_FT_arity) + +# define BOOST_FT_type \ + BOOST_FT_syntax(BOOST_FT_cc,BOOST_FT_type_name BOOST_PP_EMPTY)\ + (BOOST_FT_params(BOOST_PP_EMPTY) BOOST_FT_ell) BOOST_FT_cv + +# define BOOST_FT_tplargs(prefx) \ + prefx() R BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_FT_arity,prefx() T) + +# if !BOOST_FT_mfp + +# define BOOST_FT_params(prefx) \ + BOOST_PP_IF(BOOST_FT_arity,BOOST_PP_ENUM_PARAMS, \ + BOOST_FT_nullary_param BOOST_PP_TUPLE_EAT(2))( \ + BOOST_FT_arity,prefx() T) +# else + +# define BOOST_FT_params(prefx) \ + BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_FT_arity,prefx() T) + +# endif + +# if !BOOST_FT_FROM_ARITY +# define BOOST_PP_ITERATION_LIMITS (BOOST_FT_mfp, BOOST_FT_MAX_ARITY) +# else +# define BOOST_PP_ITERATION_LIMITS \ + (BOOST_FT_FROM_ARITY+1, BOOST_FT_MAX_ARITY) +# endif + +# define BOOST_FT_ARITY_LOOP_IS_ITERATING 1 +# include BOOST_PP_ITERATE() +# undef BOOST_FT_ARITY_LOOP_IS_ITERATING + +# undef BOOST_FT_arity +# undef BOOST_FT_params +# undef BOOST_FT_tplargs +# undef BOOST_FT_type + +# define BOOST_FT_ARITY_LOOP_SUFFIX 1 +# include BOOST_FT_AL_INCLUDE_FILE +# undef BOOST_FT_ARITY_LOOP_SUFFIX + +# undef BOOST_FT_AL_INCLUDE_FILE +# endif + +# undef BOOST_FT_FROM_ARITY + +#else +# error "attempt to nest arity loops" +#endif + diff --git a/win32/include/boost/function_types/detail/pp_cc_loop/master.hpp b/win32/include/boost/function_types/detail/pp_cc_loop/master.hpp new file mode 100755 index 000000000..232eb4793 --- /dev/null +++ b/win32/include/boost/function_types/detail/pp_cc_loop/master.hpp @@ -0,0 +1,136 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusions + +#ifdef __WAVE__ +// this file has been generated from the master.hpp file in the same directory +# pragma wave option(preserve: 0) +#endif + + +#if !BOOST_PP_IS_ITERATING + +# ifndef BOOST_FT_DETAIL_CC_LOOP_MASTER_HPP_INCLUDED +# define BOOST_FT_DETAIL_CC_LOOP_MASTER_HPP_INCLUDED +# include + +# include +# include +# include +# include +# include +# include +# include +# endif + +# include +# include + +# define BOOST_PP_FILENAME_1 \ + +# define BOOST_PP_ITERATION_LIMITS \ + (0,BOOST_PP_SEQ_SIZE(BOOST_FT_CC_NAMES_SEQ)-1) +# include BOOST_PP_ITERATE() +# if !defined(BOOST_FT_config_valid) && BOOST_FT_CC_PREPROCESSING +# define BOOST_FT_cc_id 1 +# define BOOST_FT_cc_name implicit_cc +# define BOOST_FT_cc BOOST_PP_EMPTY +# define BOOST_FT_cond callable_builtin +# include BOOST_FT_cc_file +# undef BOOST_FT_cond +# undef BOOST_FT_cc_name +# undef BOOST_FT_cc +# undef BOOST_FT_cc_id +# elif !defined(BOOST_FT_config_valid) // and generating preprocessed file +BOOST_PP_EXPAND(#) ifndef BOOST_FT_config_valid +BOOST_PP_EXPAND(#) define BOOST_FT_cc_id 1 +BOOST_PP_EXPAND(#) define BOOST_FT_cc_name implicit_cc +BOOST_PP_EXPAND(#) define BOOST_FT_cc BOOST_PP_EMPTY +BOOST_PP_EXPAND(#) define BOOST_FT_cond callable_builtin +#define _() +BOOST_PP_EXPAND(#) include BOOST_FT_cc_file +#undef _ +BOOST_PP_EXPAND(#) undef BOOST_FT_cond +BOOST_PP_EXPAND(#) undef BOOST_FT_cc_name +BOOST_PP_EXPAND(#) undef BOOST_FT_cc +BOOST_PP_EXPAND(#) undef BOOST_FT_cc_id +BOOST_PP_EXPAND(#) else +BOOST_PP_EXPAND(#) undef BOOST_FT_config_valid +BOOST_PP_EXPAND(#) endif + +# else +# undef BOOST_FT_config_valid +# endif + +# include +# include + +#elif BOOST_FT_CC_PREPROCESSING + +# define BOOST_FT_cc_id BOOST_PP_INC(BOOST_PP_FRAME_ITERATION(1)) +# define BOOST_FT_cc_inf \ + BOOST_PP_SEQ_ELEM(BOOST_PP_FRAME_ITERATION(1),BOOST_FT_CC_NAMES_SEQ) + +# define BOOST_FT_cc_pp_name BOOST_PP_TUPLE_ELEM(3,0,BOOST_FT_cc_inf) +# define BOOST_FT_cc_name BOOST_PP_TUPLE_ELEM(3,1,BOOST_FT_cc_inf) +# define BOOST_FT_cc BOOST_PP_TUPLE_ELEM(3,2,BOOST_FT_cc_inf) + +# define BOOST_FT_cond BOOST_PP_CAT(BOOST_FT_CC_,BOOST_FT_cc_pp_name) + +# if BOOST_FT_cond +# define BOOST_FT_config_valid 1 +# include BOOST_FT_cc_file +# endif + +# undef BOOST_FT_cond + +# undef BOOST_FT_cc_pp_name +# undef BOOST_FT_cc_name +# undef BOOST_FT_cc + +# undef BOOST_FT_cc_id +# undef BOOST_FT_cc_inf + +#else // if generating preprocessed file +BOOST_PP_EXPAND(#) define BOOST_FT_cc_id BOOST_PP_INC(BOOST_PP_ITERATION()) + +# define BOOST_FT_cc_inf \ + BOOST_PP_SEQ_ELEM(BOOST_PP_ITERATION(),BOOST_FT_CC_NAMES_SEQ) + +# define BOOST_FT_cc_pp_name BOOST_PP_TUPLE_ELEM(3,0,BOOST_FT_cc_inf) + +# define BOOST_FT_CC_DEF(name,index) \ + name BOOST_PP_TUPLE_ELEM(3,index,BOOST_FT_cc_inf) +BOOST_PP_EXPAND(#) define BOOST_FT_CC_DEF(BOOST_FT_cc_name,1) +BOOST_PP_EXPAND(#) define BOOST_FT_CC_DEF(BOOST_FT_cc,2) +# undef BOOST_FT_CC_DEF + +# define BOOST_FT_cc_cond_v BOOST_PP_CAT(BOOST_FT_CC_,BOOST_FT_cc_pp_name) +BOOST_PP_EXPAND(#) define BOOST_FT_cond BOOST_FT_cc_cond_v +# undef BOOST_FT_cc_cond_v + +# undef BOOST_FT_cc_pp_name +# undef BOOST_FT_cc_inf + +BOOST_PP_EXPAND(#) if BOOST_FT_cond +BOOST_PP_EXPAND(#) define BOOST_FT_config_valid 1 +#define _() +BOOST_PP_EXPAND(#) include BOOST_FT_cc_file +#undef _ +BOOST_PP_EXPAND(#) endif + +BOOST_PP_EXPAND(#) undef BOOST_FT_cond + +BOOST_PP_EXPAND(#) undef BOOST_FT_cc_name +BOOST_PP_EXPAND(#) undef BOOST_FT_cc + +BOOST_PP_EXPAND(#) undef BOOST_FT_cc_id + +#endif + diff --git a/win32/include/boost/function_types/detail/pp_cc_loop/preprocessed.hpp b/win32/include/boost/function_types/detail/pp_cc_loop/preprocessed.hpp new file mode 100755 index 000000000..aaee74f09 --- /dev/null +++ b/win32/include/boost/function_types/detail/pp_cc_loop/preprocessed.hpp @@ -0,0 +1,120 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusions + +// this file has been generated from the master.hpp file in the same directory +# define BOOST_FT_cc_id 1 +# define BOOST_FT_cc_name implicit_cc +# define BOOST_FT_cc BOOST_PP_EMPTY +# define BOOST_FT_cond BOOST_FT_CC_IMPLICIT +# if BOOST_FT_cond +# define BOOST_FT_config_valid 1 +# include BOOST_FT_cc_file +# endif +# undef BOOST_FT_cond +# undef BOOST_FT_cc_name +# undef BOOST_FT_cc +# undef BOOST_FT_cc_id +# define BOOST_FT_cc_id 2 +# define BOOST_FT_cc_name cdecl_cc +# define BOOST_FT_cc BOOST_PP_IDENTITY(__cdecl ) +# define BOOST_FT_cond BOOST_FT_CC_CDECL +# if BOOST_FT_cond +# define BOOST_FT_config_valid 1 +# include BOOST_FT_cc_file +# endif +# undef BOOST_FT_cond +# undef BOOST_FT_cc_name +# undef BOOST_FT_cc +# undef BOOST_FT_cc_id +# define BOOST_FT_cc_id 3 +# define BOOST_FT_cc_name stdcall_cc +# define BOOST_FT_cc BOOST_PP_IDENTITY(__stdcall ) +# define BOOST_FT_cond BOOST_FT_CC_STDCALL +# if BOOST_FT_cond +# define BOOST_FT_config_valid 1 +# include BOOST_FT_cc_file +# endif +# undef BOOST_FT_cond +# undef BOOST_FT_cc_name +# undef BOOST_FT_cc +# undef BOOST_FT_cc_id +# define BOOST_FT_cc_id 4 +# define BOOST_FT_cc_name pascal_cc +# define BOOST_FT_cc BOOST_PP_IDENTITY(pascal ) +# define BOOST_FT_cond BOOST_FT_CC_PASCAL +# if BOOST_FT_cond +# define BOOST_FT_config_valid 1 +# include BOOST_FT_cc_file +# endif +# undef BOOST_FT_cond +# undef BOOST_FT_cc_name +# undef BOOST_FT_cc +# undef BOOST_FT_cc_id +# define BOOST_FT_cc_id 5 +# define BOOST_FT_cc_name fastcall_cc +# define BOOST_FT_cc BOOST_PP_IDENTITY(__fastcall) +# define BOOST_FT_cond BOOST_FT_CC_FASTCALL +# if BOOST_FT_cond +# define BOOST_FT_config_valid 1 +# include BOOST_FT_cc_file +# endif +# undef BOOST_FT_cond +# undef BOOST_FT_cc_name +# undef BOOST_FT_cc +# undef BOOST_FT_cc_id +# define BOOST_FT_cc_id 6 +# define BOOST_FT_cc_name clrcall_cc +# define BOOST_FT_cc BOOST_PP_IDENTITY(__clrcall ) +# define BOOST_FT_cond BOOST_FT_CC_CLRCALL +# if BOOST_FT_cond +# define BOOST_FT_config_valid 1 +# include BOOST_FT_cc_file +# endif +# undef BOOST_FT_cond +# undef BOOST_FT_cc_name +# undef BOOST_FT_cc +# undef BOOST_FT_cc_id +# define BOOST_FT_cc_id 7 +# define BOOST_FT_cc_name thiscall_cc +# define BOOST_FT_cc BOOST_PP_IDENTITY(__thiscall) +# define BOOST_FT_cond BOOST_FT_CC_THISCALL +# if BOOST_FT_cond +# define BOOST_FT_config_valid 1 +# include BOOST_FT_cc_file +# endif +# undef BOOST_FT_cond +# undef BOOST_FT_cc_name +# undef BOOST_FT_cc +# undef BOOST_FT_cc_id +# define BOOST_FT_cc_id 8 +# define BOOST_FT_cc_name thiscall_cc +# define BOOST_FT_cc BOOST_PP_EMPTY +# define BOOST_FT_cond BOOST_FT_CC_IMPLICIT_THISCALL +# if BOOST_FT_cond +# define BOOST_FT_config_valid 1 +# include BOOST_FT_cc_file +# endif +# undef BOOST_FT_cond +# undef BOOST_FT_cc_name +# undef BOOST_FT_cc +# undef BOOST_FT_cc_id +# ifndef BOOST_FT_config_valid +# define BOOST_FT_cc_id 1 +# define BOOST_FT_cc_name implicit_cc +# define BOOST_FT_cc BOOST_PP_EMPTY +# define BOOST_FT_cond 0x00000001 +# include BOOST_FT_cc_file +# undef BOOST_FT_cond +# undef BOOST_FT_cc_name +# undef BOOST_FT_cc +# undef BOOST_FT_cc_id +# else +# undef BOOST_FT_config_valid +# endif diff --git a/win32/include/boost/function_types/detail/pp_loop.hpp b/win32/include/boost/function_types/detail/pp_loop.hpp new file mode 100755 index 000000000..97c595af0 --- /dev/null +++ b/win32/include/boost/function_types/detail/pp_loop.hpp @@ -0,0 +1,80 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusions + +#ifndef BOOST_FT_DETAIL_PP_LOOP_HPP_INCLUDED +#define BOOST_FT_DETAIL_PP_LOOP_HPP_INCLUDED +# include +# include +# include +#endif + +#include +#include + +#if defined(BOOST_FT_PREPROCESSING_MODE) +# define BOOST_FT_loop +#else +# define BOOST_FT_loop \ + +#endif + +#if defined(BOOST_FT_al_path) + +# define BOOST_FT_cc_file \ + +# define BOOST_FT_variate_file \ + + +# ifndef BOOST_FT_type_function +# define BOOST_FT_type_function(cc,name) BOOST_FT_SYNTAX( \ + R BOOST_PP_EMPTY,BOOST_PP_EMPTY,cc,BOOST_PP_EMPTY,name,BOOST_PP_EMPTY) +# endif +# ifndef BOOST_FT_type_function_pointer +# define BOOST_FT_type_function_pointer(cc,name) BOOST_FT_SYNTAX( \ + R BOOST_PP_EMPTY,BOOST_PP_LPAREN,cc,* BOOST_PP_EMPTY,name,BOOST_PP_RPAREN) +# endif +# ifndef BOOST_FT_type_function_reference +# define BOOST_FT_type_function_reference(cc,name) BOOST_FT_SYNTAX( \ + R BOOST_PP_EMPTY,BOOST_PP_LPAREN,cc,& BOOST_PP_EMPTY,name,BOOST_PP_RPAREN) +# endif +# ifndef BOOST_FT_type_member_function_pointer +# define BOOST_FT_type_member_function_pointer(cc,name) BOOST_FT_SYNTAX( \ + R BOOST_PP_EMPTY,BOOST_PP_LPAREN,cc,T0::* BOOST_PP_EMPTY,name,BOOST_PP_RPAREN) +# endif + +# include BOOST_FT_loop + +# undef BOOST_FT_type_function +# undef BOOST_FT_type_function_pointer +# undef BOOST_FT_type_function_reference +# undef BOOST_FT_type_member_function_pointer + +# undef BOOST_FT_variations +# undef BOOST_FT_variate_file +# undef BOOST_FT_cc_file +# undef BOOST_FT_al_path + +#elif defined(BOOST_FT_cc_file) + +# include BOOST_FT_loop +# undef BOOST_FT_cc_file + +#else + +# error "argument missing" + +#endif + +#undef BOOST_FT_loop + +#include +#include + + diff --git a/win32/include/boost/function_types/detail/pp_retag_default_cc/master.hpp b/win32/include/boost/function_types/detail/pp_retag_default_cc/master.hpp new file mode 100755 index 000000000..4123d3798 --- /dev/null +++ b/win32/include/boost/function_types/detail/pp_retag_default_cc/master.hpp @@ -0,0 +1,103 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is guarded externally + +#ifdef __WAVE__ +// this file has been generated from the master.hpp file in the same directory +# pragma wave option(preserve: 0) +#endif + +#if !defined(BOOST_PP_VALUE) +# include +# include + +# include +# include + +namespace boost { namespace function_types { + +namespace detail +{ + template struct selector_bits + { +# define BOOST_PP_VALUE non_member|member|non_variadic|variadic +# include BOOST_PP_ASSIGN_SLOT(1) + + BOOST_STATIC_CONSTANT(bits_t, value = ( + ::boost::function_types::detail::bits::value & BOOST_FT_default_cc + | ::boost::function_types::detail::bits::value & BOOST_PP_SLOT(1) + )); + }; + + template struct default_cc_tag; + + template struct retag_default_cc + : detail::compound_tag + < Tag, detail::default_cc_tag< + ::boost::function_types::detail::selector_bits::value > > + { }; + + template struct default_cc_tag + { + typedef null_tag::bits bits; + typedef null_tag::mask mask; + }; + + class test_class; + typedef constant cc_mask_constant; + +# define BOOST_FT_self \ + + +# define default_cc_ BOOST_FT_default_cc + +# define BOOST_PP_VALUE default_cc_|non_member|non_variadic +# define BOOST_FT_tester void (*tester)() +# define BOOST_PP_INDIRECT_SELF BOOST_FT_self +# include BOOST_PP_INCLUDE_SELF() + +# define BOOST_PP_VALUE default_cc_|non_member|variadic +# define BOOST_FT_tester void (*tester)(...) +# define BOOST_PP_INDIRECT_SELF BOOST_FT_self +# include BOOST_PP_INCLUDE_SELF() + +# define BOOST_PP_VALUE default_cc_|member|non_variadic +# define BOOST_FT_tester void (test_class::*tester)() +# define BOOST_PP_INDIRECT_SELF BOOST_FT_self +# include BOOST_PP_INCLUDE_SELF() + +# define BOOST_PP_VALUE default_cc_|member|variadic +# define BOOST_FT_tester void (test_class::*tester)(...) +# define BOOST_PP_INDIRECT_SELF BOOST_FT_self +# include BOOST_PP_INCLUDE_SELF() + +# undef default_cc_ + +# undef BOOST_FT_self + +} } } // namespace ::boost::function_types::detail + +# include +# include + +#else // if defined(BOOST_PP_VALUE) + +# include BOOST_PP_ASSIGN_SLOT(1) + + template<> struct default_cc_tag + { + typedef BOOST_FT_tester; + typedef mpl::bitand_::bits,cc_mask_constant> bits; + typedef cc_mask_constant mask; + }; + +# undef BOOST_FT_tester + +#endif + diff --git a/win32/include/boost/function_types/detail/pp_retag_default_cc/preprocessed.hpp b/win32/include/boost/function_types/detail/pp_retag_default_cc/preprocessed.hpp new file mode 100755 index 000000000..f41972828 --- /dev/null +++ b/win32/include/boost/function_types/detail/pp_retag_default_cc/preprocessed.hpp @@ -0,0 +1,59 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is guarded externally + +// this file has been generated from the master.hpp file in the same directory +namespace boost { namespace function_types { +namespace detail +{ +template struct selector_bits +{ +BOOST_STATIC_CONSTANT(bits_t, value = ( +::boost::function_types::detail::bits ::value & 0x00008000 +| ::boost::function_types::detail::bits ::value & 802 +)); +}; +template struct default_cc_tag; +template struct retag_default_cc +: detail::compound_tag +< Tag, detail::default_cc_tag< +::boost::function_types::detail::selector_bits ::value > > +{ }; +template struct default_cc_tag +{ +typedef null_tag::bits bits; +typedef null_tag::mask mask; +}; +class test_class; +typedef constant<0x00ff8000> cc_mask_constant; +template< > struct default_cc_tag<33282> +{ +typedef void ( *tester)(); +typedef mpl::bitand_ ::bits,cc_mask_constant> bits; +typedef cc_mask_constant mask; +}; +template< > struct default_cc_tag<33026> +{ +typedef void ( *tester)( ... ); +typedef mpl::bitand_ ::bits,cc_mask_constant> bits; +typedef cc_mask_constant mask; +}; +template< > struct default_cc_tag<33312> +{ +typedef void (test_class:: *tester)(); +typedef mpl::bitand_ ::bits,cc_mask_constant> bits; +typedef cc_mask_constant mask; +}; +template< > struct default_cc_tag<33056> +{ +typedef void (test_class:: *tester)( ... ); +typedef mpl::bitand_ ::bits,cc_mask_constant> bits; +typedef cc_mask_constant mask; +}; +} } } diff --git a/win32/include/boost/function_types/detail/pp_tags/cc_tag.hpp b/win32/include/boost/function_types/detail/pp_tags/cc_tag.hpp new file mode 100755 index 000000000..743f787da --- /dev/null +++ b/win32/include/boost/function_types/detail/pp_tags/cc_tag.hpp @@ -0,0 +1,17 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusions + + struct BOOST_FT_cc_name + { + typedef detail::encode_bits<0,BOOST_FT_cc_id> bits; + typedef detail::constant mask; + }; + + diff --git a/win32/include/boost/function_types/detail/pp_tags/master.hpp b/win32/include/boost/function_types/detail/pp_tags/master.hpp new file mode 100755 index 000000000..3b3b72712 --- /dev/null +++ b/win32/include/boost/function_types/detail/pp_tags/master.hpp @@ -0,0 +1,126 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is guarded externally + +#ifdef __WAVE__ +// this file has been generated from the master.hpp file in the same directory +# pragma wave option(preserve: 0) +#endif + +#if !defined(BOOST_FT_PREPROCESSING_MODE) || defined(BOOST_FT_CONFIG_HPP_INCLUDED) +# error "this file used with two-pass preprocessing, only" +#endif + +#include +#include + +namespace boost { namespace function_types { + +typedef detail::property_tag non_variadic; +typedef detail::property_tag variadic; + +typedef detail::property_tag<0,BOOST_FT_const> non_const; +typedef detail::property_tag const_qualified; + +typedef detail::property_tag<0,BOOST_FT_volatile> non_volatile; +typedef detail::property_tag volatile_qualified; + +typedef detail::property_tag default_cc; + +#define BOOST_PP_VALUE BOOST_FT_const|BOOST_FT_volatile +#include BOOST_PP_ASSIGN_SLOT(1) + +typedef detail::property_tag<0 , BOOST_PP_SLOT(1)> non_cv; +typedef detail::property_tag const_non_volatile; +typedef detail::property_tag volatile_non_const; +typedef detail::property_tag cv_qualified; + +namespace detail { + + typedef constant full_mask; + + template struct encode_bits_impl + { + BOOST_STATIC_CONSTANT( bits_t, value = + Flags | (BOOST_FT_default_cc * CCID) << 1 ); + }; + + template + struct encode_charr_impl + { + BOOST_STATIC_CONSTANT(std::size_t, value = (std::size_t)(1+ + Flags | (BOOST_FT_default_cc * CCID) << 1 | Arity << BOOST_FT_arity_shift + )); + }; + + template struct decode_bits + { + BOOST_STATIC_CONSTANT(bits_t, flags = Bits & BOOST_FT_flags_mask); + + BOOST_STATIC_CONSTANT(bits_t, cc_id = + ( (Bits & BOOST_FT_full_mask) / BOOST_FT_default_cc) >> 1 + ); + + BOOST_STATIC_CONSTANT(bits_t, tag_bits = (Bits & BOOST_FT_full_mask)); + + BOOST_STATIC_CONSTANT(std::size_t, arity = (std::size_t) + (Bits >> BOOST_FT_arity_shift) + ); + }; + + template + struct tag_ice + { + BOOST_STATIC_CONSTANT(bool, match = + RHS_bits == (LHS_bits & RHS_mask & (RHS_bits |~BOOST_FT_type_mask)) + ); + + BOOST_STATIC_CONSTANT(bits_t, combined_bits = + LHS_bits & ~RHS_mask | RHS_bits + ); + + BOOST_STATIC_CONSTANT(bits_t, combined_mask = + LHS_mask | RHS_mask + ); + + BOOST_STATIC_CONSTANT(bits_t, extracted_bits = + LHS_bits & RHS_mask + ); + + }; + +#define BOOST_FT_mask BOOST_FT_type_mask + typedef property_tag callable_builtin_tag; + typedef property_tag nonmember_callable_builtin_tag; + typedef property_tag function_tag; + typedef property_tag reference_tag; + typedef property_tag pointer_tag; + typedef property_tag member_function_pointer_tag; + typedef property_tag member_object_pointer_tag; + typedef property_tag member_object_pointer_base; + typedef property_tag member_pointer_tag; +#undef BOOST_FT_mask + +#define BOOST_PP_VALUE BOOST_FT_function|BOOST_FT_non_variadic|BOOST_FT_default_cc +#include BOOST_PP_ASSIGN_SLOT(1) +#define BOOST_PP_VALUE BOOST_FT_type_mask|BOOST_FT_variadic_mask|BOOST_FT_cc_mask +#include BOOST_PP_ASSIGN_SLOT(2) + + typedef property_tag< BOOST_PP_SLOT(1) , BOOST_PP_SLOT(2) > nv_dcc_func; + +#define BOOST_PP_VALUE \ + BOOST_FT_member_function_pointer|BOOST_FT_non_variadic|BOOST_FT_default_cc +#include BOOST_PP_ASSIGN_SLOT(1) + + typedef property_tag< BOOST_PP_SLOT(1) , BOOST_PP_SLOT(2) > nv_dcc_mfp; + +} // namespace detail + +} } // namespace ::boost::function_types + diff --git a/win32/include/boost/function_types/detail/pp_tags/preprocessed.hpp b/win32/include/boost/function_types/detail/pp_tags/preprocessed.hpp new file mode 100755 index 000000000..7b0de662d --- /dev/null +++ b/win32/include/boost/function_types/detail/pp_tags/preprocessed.hpp @@ -0,0 +1,77 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is guarded externally + +// this file has been generated from the master.hpp file in the same directory +namespace boost { namespace function_types { +typedef detail::property_tag<0x00000200,0x00000300> non_variadic; +typedef detail::property_tag<0x00000100,0x00000300> variadic; +typedef detail::property_tag<0,0x00000400> non_const; +typedef detail::property_tag<0x00000400,0x00000400> const_qualified; +typedef detail::property_tag<0,0x00000800> non_volatile; +typedef detail::property_tag<0x00000800,0x00000800> volatile_qualified; +typedef detail::property_tag<0x00008000,0x00ff8000> default_cc; +typedef detail::property_tag<0 , 3072> non_cv; +typedef detail::property_tag<0x00000400 , 3072> const_non_volatile; +typedef detail::property_tag<0x00000800, 3072> volatile_non_const; +typedef detail::property_tag<3072 , 3072> cv_qualified; +namespace detail { +typedef constant<0x00ff0fff> full_mask; +template struct encode_bits_impl +{ +BOOST_STATIC_CONSTANT( bits_t, value = +Flags | (0x00008000 * CCID) << 1 ); +}; +template +struct encode_charr_impl +{ +BOOST_STATIC_CONSTANT(std::size_t, value = (std::size_t)(1+ +Flags | (0x00008000 * CCID) << 1 | Arity << 24 +)); +}; +template struct decode_bits +{ +BOOST_STATIC_CONSTANT(bits_t, flags = Bits & 0x00000fff); +BOOST_STATIC_CONSTANT(bits_t, cc_id = +( (Bits & 0x00ff0fff) / 0x00008000) >> 1 +); +BOOST_STATIC_CONSTANT(bits_t, tag_bits = (Bits & 0x00ff0fff)); +BOOST_STATIC_CONSTANT(std::size_t, arity = (std::size_t) +(Bits >> 24) +); +}; +template +struct tag_ice +{ +BOOST_STATIC_CONSTANT(bool, match = +RHS_bits == (LHS_bits & RHS_mask & (RHS_bits | ~0x000000ff)) +); +BOOST_STATIC_CONSTANT(bits_t, combined_bits = +LHS_bits & ~RHS_mask | RHS_bits +); +BOOST_STATIC_CONSTANT(bits_t, combined_mask = +LHS_mask | RHS_mask +); +BOOST_STATIC_CONSTANT(bits_t, extracted_bits = +LHS_bits & RHS_mask +); +}; +typedef property_tag<0x00000001,0x000000ff> callable_builtin_tag; +typedef property_tag<0x00000003,0x000000ff> nonmember_callable_builtin_tag; +typedef property_tag<0x00000007,0x000000ff> function_tag; +typedef property_tag<0x00000013,0x000000ff> reference_tag; +typedef property_tag<0x0000000b,0x000000ff> pointer_tag; +typedef property_tag<0x00000061,0x000000ff> member_function_pointer_tag; +typedef property_tag<0x000000a3,0x000000ff> member_object_pointer_tag; +typedef property_tag<0x000002a3,0x00ff0fff> member_object_pointer_base; +typedef property_tag<0x00000020,0x000000ff> member_pointer_tag; +typedef property_tag< 33287 , 16745471 > nv_dcc_func; +typedef property_tag< 33377 , 16745471 > nv_dcc_mfp; +} +} } diff --git a/win32/include/boost/function_types/detail/pp_variate_loop/master.hpp b/win32/include/boost/function_types/detail/pp_variate_loop/master.hpp new file mode 100755 index 000000000..ae7d99529 --- /dev/null +++ b/win32/include/boost/function_types/detail/pp_variate_loop/master.hpp @@ -0,0 +1,152 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifdef __WAVE__ +// this file has been generated from the master.hpp file in the same directory +# pragma wave option(preserve: 0) +#endif + +#if !defined(BOOST_FT_PREPROCESSING_MODE) +# error "this file is only for two-pass preprocessing" +#endif + +#if !defined(BOOST_PP_VALUE) +# include +# include +# include +# include + +BOOST_PP_EXPAND(#) define BOOST_FT_mfp 0 +BOOST_PP_EXPAND(#) define BOOST_FT_syntax BOOST_FT_type_function + +# define BOOST_PP_VALUE \ + BOOST_FT_function|BOOST_FT_non_variadic +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_function|BOOST_FT_variadic +# include __FILE__ + +BOOST_PP_EXPAND(#) if !BOOST_FT_NO_CV_FUNC_SUPPORT +# define BOOST_PP_VALUE \ + BOOST_FT_function|BOOST_FT_non_variadic|BOOST_FT_const +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_function|BOOST_FT_variadic|BOOST_FT_const +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_function|BOOST_FT_non_variadic|BOOST_FT_volatile +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_function|BOOST_FT_variadic|BOOST_FT_volatile +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_function|BOOST_FT_non_variadic|BOOST_FT_const|BOOST_FT_volatile +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_function|BOOST_FT_variadic|BOOST_FT_const|BOOST_FT_volatile +# include __FILE__ +BOOST_PP_EXPAND(#) endif + + +BOOST_PP_EXPAND(#) undef BOOST_FT_syntax +BOOST_PP_EXPAND(#) define BOOST_FT_syntax BOOST_FT_type_function_pointer + +# define BOOST_PP_VALUE \ + BOOST_FT_pointer|BOOST_FT_non_variadic +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_pointer|BOOST_FT_variadic +# include __FILE__ + +BOOST_PP_EXPAND(#) undef BOOST_FT_syntax +BOOST_PP_EXPAND(#) define BOOST_FT_syntax BOOST_FT_type_function_reference + +# define BOOST_PP_VALUE \ + BOOST_FT_reference|BOOST_FT_non_variadic +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_reference|BOOST_FT_variadic +# include __FILE__ + +BOOST_PP_EXPAND(#) undef BOOST_FT_syntax +BOOST_PP_EXPAND(#) undef BOOST_FT_mfp + +BOOST_PP_EXPAND(#) define BOOST_FT_mfp 1 +BOOST_PP_EXPAND(#) define BOOST_FT_syntax BOOST_FT_type_member_function_pointer + +# define BOOST_PP_VALUE \ + BOOST_FT_member_function_pointer|BOOST_FT_non_variadic +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_member_function_pointer|BOOST_FT_variadic +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_member_function_pointer|BOOST_FT_non_variadic|BOOST_FT_const +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_member_function_pointer|BOOST_FT_variadic|BOOST_FT_const +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_member_function_pointer|BOOST_FT_non_variadic|BOOST_FT_volatile +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_member_function_pointer|BOOST_FT_variadic|BOOST_FT_volatile +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_member_function_pointer|BOOST_FT_non_variadic|BOOST_FT_const|BOOST_FT_volatile +# include __FILE__ +# define BOOST_PP_VALUE \ + BOOST_FT_member_function_pointer|BOOST_FT_variadic|BOOST_FT_const|BOOST_FT_volatile +# include __FILE__ + +BOOST_PP_EXPAND(#) undef BOOST_FT_syntax +BOOST_PP_EXPAND(#) undef BOOST_FT_mfp + +# include +#else + +# include BOOST_PP_ASSIGN_SLOT(1) + +# define BOOST_PP_VALUE BOOST_PP_SLOT(1) & BOOST_FT_kind_mask +# include BOOST_PP_ASSIGN_SLOT(2) + +BOOST_PP_EXPAND(#) if !!(BOOST_PP_SLOT(2) & (BOOST_FT_variations)) +BOOST_PP_EXPAND(#) if (BOOST_PP_SLOT(1) & (BOOST_FT_cond)) == (BOOST_FT_cond) + +# if ( BOOST_PP_SLOT(1) & (BOOST_FT_variadic) ) +BOOST_PP_EXPAND(#) define BOOST_FT_ell ... +BOOST_PP_EXPAND(#) define BOOST_FT_nullary_param +# else +BOOST_PP_EXPAND(#) define BOOST_FT_ell +BOOST_PP_EXPAND(#) define BOOST_FT_nullary_param BOOST_FT_NULLARY_PARAM +# endif + +# if !( BOOST_PP_SLOT(1) & (BOOST_FT_volatile) ) +# if !( BOOST_PP_SLOT(1) & (BOOST_FT_const) ) +BOOST_PP_EXPAND(#) define BOOST_FT_cv +# else +BOOST_PP_EXPAND(#) define BOOST_FT_cv const +# endif +# else +# if !( BOOST_PP_SLOT(1) & (BOOST_FT_const) ) +BOOST_PP_EXPAND(#) define BOOST_FT_cv volatile +# else +BOOST_PP_EXPAND(#) define BOOST_FT_cv const volatile +# endif +# endif +BOOST_PP_EXPAND(#) define BOOST_FT_flags BOOST_PP_SLOT(1) +BOOST_PP_EXPAND(#) include BOOST_FT_variate_file + +BOOST_PP_EXPAND(#) undef BOOST_FT_cv +BOOST_PP_EXPAND(#) undef BOOST_FT_ell +BOOST_PP_EXPAND(#) undef BOOST_FT_nullary_param +BOOST_PP_EXPAND(#) undef BOOST_FT_flags +BOOST_PP_EXPAND(#) endif +BOOST_PP_EXPAND(#) endif +#endif + diff --git a/win32/include/boost/function_types/detail/pp_variate_loop/preprocessed.hpp b/win32/include/boost/function_types/detail/pp_variate_loop/preprocessed.hpp new file mode 100755 index 000000000..a5ca48fd9 --- /dev/null +++ b/win32/include/boost/function_types/detail/pp_variate_loop/preprocessed.hpp @@ -0,0 +1,283 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// this file has been generated from the master.hpp file in the same directory +# define BOOST_FT_mfp 0 +# define BOOST_FT_syntax BOOST_FT_type_function +# if ! ! (4 & (BOOST_FT_variations)) +# if (519 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell +# define BOOST_FT_nullary_param BOOST_FT_NULLARY_PARAM +# define BOOST_FT_cv +# define BOOST_FT_flags 519 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (4 & (BOOST_FT_variations)) +# if (263 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell ... +# define BOOST_FT_nullary_param +# define BOOST_FT_cv +# define BOOST_FT_flags 263 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if !BOOST_FT_NO_CV_FUNC_SUPPORT +# if ! ! (4 & (BOOST_FT_variations)) +# if (1543 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell +# define BOOST_FT_nullary_param BOOST_FT_NULLARY_PARAM +# define BOOST_FT_cv const +# define BOOST_FT_flags 1543 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (4 & (BOOST_FT_variations)) +# if (1287 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell ... +# define BOOST_FT_nullary_param +# define BOOST_FT_cv const +# define BOOST_FT_flags 1287 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (4 & (BOOST_FT_variations)) +# if (2567 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell +# define BOOST_FT_nullary_param BOOST_FT_NULLARY_PARAM +# define BOOST_FT_cv volatile +# define BOOST_FT_flags 2567 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (4 & (BOOST_FT_variations)) +# if (2311 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell ... +# define BOOST_FT_nullary_param +# define BOOST_FT_cv volatile +# define BOOST_FT_flags 2311 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (4 & (BOOST_FT_variations)) +# if (3591 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell +# define BOOST_FT_nullary_param BOOST_FT_NULLARY_PARAM +# define BOOST_FT_cv const volatile +# define BOOST_FT_flags 3591 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (4 & (BOOST_FT_variations)) +# if (3335 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell ... +# define BOOST_FT_nullary_param +# define BOOST_FT_cv const volatile +# define BOOST_FT_flags 3335 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# endif +# undef BOOST_FT_syntax +# define BOOST_FT_syntax BOOST_FT_type_function_pointer +# if ! ! (8 & (BOOST_FT_variations)) +# if (523 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell +# define BOOST_FT_nullary_param BOOST_FT_NULLARY_PARAM +# define BOOST_FT_cv +# define BOOST_FT_flags 523 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (8 & (BOOST_FT_variations)) +# if (267 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell ... +# define BOOST_FT_nullary_param +# define BOOST_FT_cv +# define BOOST_FT_flags 267 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# undef BOOST_FT_syntax +# define BOOST_FT_syntax BOOST_FT_type_function_reference +# if ! ! (16 & (BOOST_FT_variations)) +# if (531 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell +# define BOOST_FT_nullary_param BOOST_FT_NULLARY_PARAM +# define BOOST_FT_cv +# define BOOST_FT_flags 531 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (16 & (BOOST_FT_variations)) +# if (275 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell ... +# define BOOST_FT_nullary_param +# define BOOST_FT_cv +# define BOOST_FT_flags 275 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# undef BOOST_FT_syntax +# undef BOOST_FT_mfp +# define BOOST_FT_mfp 1 +# define BOOST_FT_syntax BOOST_FT_type_member_function_pointer +# if ! ! (96 & (BOOST_FT_variations)) +# if (609 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell +# define BOOST_FT_nullary_param BOOST_FT_NULLARY_PARAM +# define BOOST_FT_cv +# define BOOST_FT_flags 609 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (96 & (BOOST_FT_variations)) +# if (353 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell ... +# define BOOST_FT_nullary_param +# define BOOST_FT_cv +# define BOOST_FT_flags 353 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (96 & (BOOST_FT_variations)) +# if (1633 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell +# define BOOST_FT_nullary_param BOOST_FT_NULLARY_PARAM +# define BOOST_FT_cv const +# define BOOST_FT_flags 1633 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (96 & (BOOST_FT_variations)) +# if (1377 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell ... +# define BOOST_FT_nullary_param +# define BOOST_FT_cv const +# define BOOST_FT_flags 1377 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (96 & (BOOST_FT_variations)) +# if (2657 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell +# define BOOST_FT_nullary_param BOOST_FT_NULLARY_PARAM +# define BOOST_FT_cv volatile +# define BOOST_FT_flags 2657 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (96 & (BOOST_FT_variations)) +# if (2401 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell ... +# define BOOST_FT_nullary_param +# define BOOST_FT_cv volatile +# define BOOST_FT_flags 2401 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (96 & (BOOST_FT_variations)) +# if (3681 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell +# define BOOST_FT_nullary_param BOOST_FT_NULLARY_PARAM +# define BOOST_FT_cv const volatile +# define BOOST_FT_flags 3681 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# if ! ! (96 & (BOOST_FT_variations)) +# if (3425 & (BOOST_FT_cond)) == (BOOST_FT_cond) +# define BOOST_FT_ell ... +# define BOOST_FT_nullary_param +# define BOOST_FT_cv const volatile +# define BOOST_FT_flags 3425 +# include BOOST_FT_variate_file +# undef BOOST_FT_cv +# undef BOOST_FT_ell +# undef BOOST_FT_nullary_param +# undef BOOST_FT_flags +# endif +# endif +# undef BOOST_FT_syntax +# undef BOOST_FT_mfp diff --git a/win32/include/boost/function_types/detail/retag_default_cc.hpp b/win32/include/boost/function_types/detail/retag_default_cc.hpp new file mode 100755 index 000000000..324c6bbae --- /dev/null +++ b/win32/include/boost/function_types/detail/retag_default_cc.hpp @@ -0,0 +1,23 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_DETAIL_RETAG_DEFAULT_CC_HPP_INCLUDED +#define BOOST_FT_DETAIL_RETAG_DEFAULT_CC_HPP_INCLUDED + +#include + +#include + +#if defined(BOOST_FT_PREPROCESSING_MODE) +# include +#else +# include +#endif + +#endif + diff --git a/win32/include/boost/function_types/detail/synthesize.hpp b/win32/include/boost/function_types/detail/synthesize.hpp new file mode 100755 index 000000000..dcd98d5b9 --- /dev/null +++ b/win32/include/boost/function_types/detail/synthesize.hpp @@ -0,0 +1,79 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_DETAIL_SYNTHESIZE_HPP_INCLUDED +#define BOOST_FT_DETAIL_SYNTHESIZE_HPP_INCLUDED + +#include + +#include +#include + +#include +#include +#include +#include + +namespace boost { namespace function_types { namespace detail { + +template +struct synthesize_impl_o +{ + template struct synthesize_impl_i { }; +}; + +template +struct synthesize_impl + : detail::synthesize_impl_o + < ::boost::function_types::detail::decode_bits::flags + , ::boost::function_types::detail::decode_bits::cc_id + , ::boost::mpl::size::value + > + ::template synthesize_impl_i +{ }; + +template +struct synthesize_func + : detail::synthesize_impl + < Seq + , ::boost::function_types::detail::bits + < detail::retag_default_cc + < function_types::tag > + >::value + > +{ }; + +template +struct synthesize_mfp + : detail::synthesize_impl + < Seq + , ::boost::function_types::detail::bits + < detail::retag_default_cc + < function_types::tag + < typename detail::cv_traits< typename mpl::at_c::type >::tag + , nv_dcc_mfp, Tag + > > + >::value + > +{ }; + +template::type, + typename C = typename mpl::at_c::type> +struct synthesize_mop +{ + typedef R C::* type; +}; + +#define BOOST_FT_variations BOOST_FT_function|BOOST_FT_member_pointer +#define BOOST_FT_al_path boost/function_types/detail/synthesize_impl +#include + +} } } // namespace ::boost::function_types::detail + +#endif + diff --git a/win32/include/boost/function_types/detail/synthesize_impl/arity10_0.hpp b/win32/include/boost/function_types/detail/synthesize_impl/arity10_0.hpp new file mode 100755 index 000000000..6d7c0f056 --- /dev/null +++ b/win32/include/boost/function_types/detail/synthesize_impl/arity10_0.hpp @@ -0,0 +1,334 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# define BOOST_FT_make_type(flags,cc,arity) BOOST_FT_make_type_impl(flags,cc,arity) +# define BOOST_FT_make_type_impl(flags,cc,arity) make_type_ ## flags ## _ ## cc ## _ ## arity +template< typename R > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,0) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (BOOST_FT_nullary_param BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 1 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,0) +< typename mpl::deref< iter_0 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,1) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 2 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,1) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,2) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 3 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,2) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,3) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 4 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,3) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,4) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 5 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,4) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,5) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 6 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,5) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,6) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 7 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,6) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,7) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 8 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,7) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,8) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 9 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,8) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,9) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 10 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,9) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,10) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 11 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,10) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +> ::type type; +}; +}; +# undef BOOST_FT_make_type +# undef BOOST_FT_make_type_impl + diff --git a/win32/include/boost/function_types/detail/synthesize_impl/arity10_1.hpp b/win32/include/boost/function_types/detail/synthesize_impl/arity10_1.hpp new file mode 100755 index 000000000..38a9200f1 --- /dev/null +++ b/win32/include/boost/function_types/detail/synthesize_impl/arity10_1.hpp @@ -0,0 +1,326 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# define BOOST_FT_make_type(flags,cc,arity) BOOST_FT_make_type_impl(flags,cc,arity) +# define BOOST_FT_make_type_impl(flags,cc,arity) make_type_ ## flags ## _ ## cc ## _ ## arity +template< typename R , typename T0 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,1) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) ( BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 2 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,1) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,2) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 3 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,2) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,3) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 4 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,3) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,4) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 5 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,4) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,5) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 6 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,5) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,6) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 7 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,6) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,7) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 8 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,7) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,8) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 9 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,8) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,9) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 10 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,9) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,10) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 11 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,10) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +> ::type type; +}; +}; +# undef BOOST_FT_make_type +# undef BOOST_FT_make_type_impl + diff --git a/win32/include/boost/function_types/detail/synthesize_impl/arity20_0.hpp b/win32/include/boost/function_types/detail/synthesize_impl/arity20_0.hpp new file mode 100755 index 000000000..4f25172a3 --- /dev/null +++ b/win32/include/boost/function_types/detail/synthesize_impl/arity20_0.hpp @@ -0,0 +1,517 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +# define BOOST_FT_make_type(flags,cc,arity) BOOST_FT_make_type_impl(flags,cc,arity) +# define BOOST_FT_make_type_impl(flags,cc,arity) make_type_ ## flags ## _ ## cc ## _ ## arity +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,11) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 12 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,11) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,12) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 13 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,12) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,13) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 14 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,13) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,14) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 15 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,14) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,15) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 16 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,15) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,16) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 17 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,16) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,17) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 18 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,17) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,18) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 19 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,18) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,19) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 20 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,19) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,20) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 21 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,20) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +> ::type type; +}; +}; +# undef BOOST_FT_make_type +# undef BOOST_FT_make_type_impl + diff --git a/win32/include/boost/function_types/detail/synthesize_impl/arity20_1.hpp b/win32/include/boost/function_types/detail/synthesize_impl/arity20_1.hpp new file mode 100755 index 000000000..fa3f0e22a --- /dev/null +++ b/win32/include/boost/function_types/detail/synthesize_impl/arity20_1.hpp @@ -0,0 +1,527 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +# define BOOST_FT_make_type(flags,cc,arity) BOOST_FT_make_type_impl(flags,cc,arity) +# define BOOST_FT_make_type_impl(flags,cc,arity) make_type_ ## flags ## _ ## cc ## _ ## arity +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,11) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 12 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,11) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,12) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 13 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,12) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,13) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 14 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,13) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,14) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 15 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,14) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,15) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 16 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,15) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,16) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 17 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,16) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,17) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 18 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,17) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,18) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 19 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,18) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,19) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 20 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,19) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,20) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 21 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,20) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +> ::type type; +}; +}; +# undef BOOST_FT_make_type +# undef BOOST_FT_make_type_impl + diff --git a/win32/include/boost/function_types/detail/synthesize_impl/arity30_0.hpp b/win32/include/boost/function_types/detail/synthesize_impl/arity30_0.hpp new file mode 100755 index 000000000..9cd81decd --- /dev/null +++ b/win32/include/boost/function_types/detail/synthesize_impl/arity30_0.hpp @@ -0,0 +1,717 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +# define BOOST_FT_make_type(flags,cc,arity) BOOST_FT_make_type_impl(flags,cc,arity) +# define BOOST_FT_make_type_impl(flags,cc,arity) make_type_ ## flags ## _ ## cc ## _ ## arity +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,21) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 22 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,21) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,22) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 23 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,22) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,23) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 24 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,23) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,24) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 25 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,24) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,25) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 26 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,25) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,26) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 27 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,26) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,27) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 28 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,27) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,28) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 29 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,28) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,29) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 30 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,29) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,30) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 31 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,30) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +> ::type type; +}; +}; +# undef BOOST_FT_make_type +# undef BOOST_FT_make_type_impl + diff --git a/win32/include/boost/function_types/detail/synthesize_impl/arity30_1.hpp b/win32/include/boost/function_types/detail/synthesize_impl/arity30_1.hpp new file mode 100755 index 000000000..708d3517b --- /dev/null +++ b/win32/include/boost/function_types/detail/synthesize_impl/arity30_1.hpp @@ -0,0 +1,727 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +# define BOOST_FT_make_type(flags,cc,arity) BOOST_FT_make_type_impl(flags,cc,arity) +# define BOOST_FT_make_type_impl(flags,cc,arity) make_type_ ## flags ## _ ## cc ## _ ## arity +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,21) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 22 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,21) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,22) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 23 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,22) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,23) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 24 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,23) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,24) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 25 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,24) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,25) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 26 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,25) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,26) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 27 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,26) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,27) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 28 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,27) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,28) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 29 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,28) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,29) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 30 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,29) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,30) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 31 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,30) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +> ::type type; +}; +}; +# undef BOOST_FT_make_type +# undef BOOST_FT_make_type_impl + diff --git a/win32/include/boost/function_types/detail/synthesize_impl/arity40_0.hpp b/win32/include/boost/function_types/detail/synthesize_impl/arity40_0.hpp new file mode 100755 index 000000000..a7d922f5f --- /dev/null +++ b/win32/include/boost/function_types/detail/synthesize_impl/arity40_0.hpp @@ -0,0 +1,917 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +# define BOOST_FT_make_type(flags,cc,arity) BOOST_FT_make_type_impl(flags,cc,arity) +# define BOOST_FT_make_type_impl(flags,cc,arity) make_type_ ## flags ## _ ## cc ## _ ## arity +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,31) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 32 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,31) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,32) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 33 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,32) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,33) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 34 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,33) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,34) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 35 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,34) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,35) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 36 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,35) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,36) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 37 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,36) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,37) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 38 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,37) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,38) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 39 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,38) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,39) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 40 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,39) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,40) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 41 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,40) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +> ::type type; +}; +}; +# undef BOOST_FT_make_type +# undef BOOST_FT_make_type_impl + diff --git a/win32/include/boost/function_types/detail/synthesize_impl/arity40_1.hpp b/win32/include/boost/function_types/detail/synthesize_impl/arity40_1.hpp new file mode 100755 index 000000000..37a119009 --- /dev/null +++ b/win32/include/boost/function_types/detail/synthesize_impl/arity40_1.hpp @@ -0,0 +1,927 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +# define BOOST_FT_make_type(flags,cc,arity) BOOST_FT_make_type_impl(flags,cc,arity) +# define BOOST_FT_make_type_impl(flags,cc,arity) make_type_ ## flags ## _ ## cc ## _ ## arity +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,31) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 32 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,31) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,32) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 33 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,32) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,33) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 34 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,33) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,34) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 35 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,34) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,35) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 36 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,35) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,36) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 37 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,36) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,37) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 38 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,37) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,38) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 39 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,38) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,39) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 40 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,39) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,40) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 41 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,40) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +> ::type type; +}; +}; +# undef BOOST_FT_make_type +# undef BOOST_FT_make_type_impl + diff --git a/win32/include/boost/function_types/detail/synthesize_impl/arity50_0.hpp b/win32/include/boost/function_types/detail/synthesize_impl/arity50_0.hpp new file mode 100755 index 000000000..2f7100c7d --- /dev/null +++ b/win32/include/boost/function_types/detail/synthesize_impl/arity50_0.hpp @@ -0,0 +1,1117 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +# define BOOST_FT_make_type(flags,cc,arity) BOOST_FT_make_type_impl(flags,cc,arity) +# define BOOST_FT_make_type_impl(flags,cc,arity) make_type_ ## flags ## _ ## cc ## _ ## arity +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,41) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 42 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,41) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,42) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 43 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,42) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,43) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 44 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,43) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,44) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 45 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +typedef typename mpl::next< iter_43 > ::type iter_44; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,44) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +, typename mpl::deref< iter_44 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,45) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 46 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +typedef typename mpl::next< iter_43 > ::type iter_44; +typedef typename mpl::next< iter_44 > ::type iter_45; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,45) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +, typename mpl::deref< iter_44 > ::type +, typename mpl::deref< iter_45 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,46) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 47 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +typedef typename mpl::next< iter_43 > ::type iter_44; +typedef typename mpl::next< iter_44 > ::type iter_45; +typedef typename mpl::next< iter_45 > ::type iter_46; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,46) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +, typename mpl::deref< iter_44 > ::type +, typename mpl::deref< iter_45 > ::type +, typename mpl::deref< iter_46 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,47) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 48 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +typedef typename mpl::next< iter_43 > ::type iter_44; +typedef typename mpl::next< iter_44 > ::type iter_45; +typedef typename mpl::next< iter_45 > ::type iter_46; +typedef typename mpl::next< iter_46 > ::type iter_47; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,47) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +, typename mpl::deref< iter_44 > ::type +, typename mpl::deref< iter_45 > ::type +, typename mpl::deref< iter_46 > ::type +, typename mpl::deref< iter_47 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,48) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 49 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +typedef typename mpl::next< iter_43 > ::type iter_44; +typedef typename mpl::next< iter_44 > ::type iter_45; +typedef typename mpl::next< iter_45 > ::type iter_46; +typedef typename mpl::next< iter_46 > ::type iter_47; +typedef typename mpl::next< iter_47 > ::type iter_48; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,48) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +, typename mpl::deref< iter_44 > ::type +, typename mpl::deref< iter_45 > ::type +, typename mpl::deref< iter_46 > ::type +, typename mpl::deref< iter_47 > ::type +, typename mpl::deref< iter_48 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 , typename T48 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,49) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 , T48 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 50 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +typedef typename mpl::next< iter_43 > ::type iter_44; +typedef typename mpl::next< iter_44 > ::type iter_45; +typedef typename mpl::next< iter_45 > ::type iter_46; +typedef typename mpl::next< iter_46 > ::type iter_47; +typedef typename mpl::next< iter_47 > ::type iter_48; +typedef typename mpl::next< iter_48 > ::type iter_49; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,49) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +, typename mpl::deref< iter_44 > ::type +, typename mpl::deref< iter_45 > ::type +, typename mpl::deref< iter_46 > ::type +, typename mpl::deref< iter_47 > ::type +, typename mpl::deref< iter_48 > ::type +, typename mpl::deref< iter_49 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 , typename T48 , typename T49 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,50) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 , T48 , T49 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 51 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +typedef typename mpl::next< iter_43 > ::type iter_44; +typedef typename mpl::next< iter_44 > ::type iter_45; +typedef typename mpl::next< iter_45 > ::type iter_46; +typedef typename mpl::next< iter_46 > ::type iter_47; +typedef typename mpl::next< iter_47 > ::type iter_48; +typedef typename mpl::next< iter_48 > ::type iter_49; +typedef typename mpl::next< iter_49 > ::type iter_50; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,50) +< typename mpl::deref< iter_0 > ::type +, typename mpl::deref< iter_1 > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +, typename mpl::deref< iter_44 > ::type +, typename mpl::deref< iter_45 > ::type +, typename mpl::deref< iter_46 > ::type +, typename mpl::deref< iter_47 > ::type +, typename mpl::deref< iter_48 > ::type +, typename mpl::deref< iter_49 > ::type +, typename mpl::deref< iter_50 > ::type +> ::type type; +}; +}; +# undef BOOST_FT_make_type +# undef BOOST_FT_make_type_impl + diff --git a/win32/include/boost/function_types/detail/synthesize_impl/arity50_1.hpp b/win32/include/boost/function_types/detail/synthesize_impl/arity50_1.hpp new file mode 100755 index 000000000..27afcfcf3 --- /dev/null +++ b/win32/include/boost/function_types/detail/synthesize_impl/arity50_1.hpp @@ -0,0 +1,1127 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +// input: BOOST_FT_syntax type macro to use +// input: BOOST_FT_cc empty or cc specifier +// input: BOOST_FT_ell empty or "..." +// input: BOOST_FT_cv empty or cv qualifiers +// input: BOOST_FT_flags single decimal integer encoding the flags +// output: BOOST_FT_n number of component types (arity+1) +// output: BOOST_FT_arity current arity +// output: BOOST_FT_type macro that expands to the type +// output: BOOST_FT_tplargs(p) template arguments with given prefix +// output: BOOST_FT_params(p) parameters with given prefix + +# include +# define BOOST_FT_make_type(flags,cc,arity) BOOST_FT_make_type_impl(flags,cc,arity) +# define BOOST_FT_make_type_impl(flags,cc,arity) make_type_ ## flags ## _ ## cc ## _ ## arity +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,41) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 42 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,41) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,42) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 43 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,42) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,43) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 44 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,43) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,44) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 45 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +typedef typename mpl::next< iter_43 > ::type iter_44; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,44) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +, typename mpl::deref< iter_44 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,45) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 46 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +typedef typename mpl::next< iter_43 > ::type iter_44; +typedef typename mpl::next< iter_44 > ::type iter_45; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,45) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +, typename mpl::deref< iter_44 > ::type +, typename mpl::deref< iter_45 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,46) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 47 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +typedef typename mpl::next< iter_43 > ::type iter_44; +typedef typename mpl::next< iter_44 > ::type iter_45; +typedef typename mpl::next< iter_45 > ::type iter_46; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,46) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +, typename mpl::deref< iter_44 > ::type +, typename mpl::deref< iter_45 > ::type +, typename mpl::deref< iter_46 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,47) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 48 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +typedef typename mpl::next< iter_43 > ::type iter_44; +typedef typename mpl::next< iter_44 > ::type iter_45; +typedef typename mpl::next< iter_45 > ::type iter_46; +typedef typename mpl::next< iter_46 > ::type iter_47; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,47) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +, typename mpl::deref< iter_44 > ::type +, typename mpl::deref< iter_45 > ::type +, typename mpl::deref< iter_46 > ::type +, typename mpl::deref< iter_47 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,48) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 49 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +typedef typename mpl::next< iter_43 > ::type iter_44; +typedef typename mpl::next< iter_44 > ::type iter_45; +typedef typename mpl::next< iter_45 > ::type iter_46; +typedef typename mpl::next< iter_46 > ::type iter_47; +typedef typename mpl::next< iter_47 > ::type iter_48; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,48) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +, typename mpl::deref< iter_44 > ::type +, typename mpl::deref< iter_45 > ::type +, typename mpl::deref< iter_46 > ::type +, typename mpl::deref< iter_47 > ::type +, typename mpl::deref< iter_48 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 , typename T48 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,49) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 , T48 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 50 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +typedef typename mpl::next< iter_43 > ::type iter_44; +typedef typename mpl::next< iter_44 > ::type iter_45; +typedef typename mpl::next< iter_45 > ::type iter_46; +typedef typename mpl::next< iter_46 > ::type iter_47; +typedef typename mpl::next< iter_47 > ::type iter_48; +typedef typename mpl::next< iter_48 > ::type iter_49; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,49) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +, typename mpl::deref< iter_44 > ::type +, typename mpl::deref< iter_45 > ::type +, typename mpl::deref< iter_46 > ::type +, typename mpl::deref< iter_47 > ::type +, typename mpl::deref< iter_48 > ::type +, typename mpl::deref< iter_49 > ::type +> ::type type; +}; +}; +template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9 , typename T10 , typename T11 , typename T12 , typename T13 , typename T14 , typename T15 , typename T16 , typename T17 , typename T18 , typename T19 , typename T20 , typename T21 , typename T22 , typename T23 , typename T24 , typename T25 , typename T26 , typename T27 , typename T28 , typename T29 , typename T30 , typename T31 , typename T32 , typename T33 , typename T34 , typename T35 , typename T36 , typename T37 , typename T38 , typename T39 , typename T40 , typename T41 , typename T42 , typename T43 , typename T44 , typename T45 , typename T46 , typename T47 , typename T48 , typename T49 > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,50) +{ +typedef BOOST_FT_syntax(BOOST_FT_cc,type BOOST_PP_EMPTY) (T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 , T25 , T26 , T27 , T28 , T29 , T30 , T31 , T32 , T33 , T34 , T35 , T36 , T37 , T38 , T39 , T40 , T41 , T42 , T43 , T44 , T45 , T46 , T47 , T48 , T49 BOOST_FT_ell) BOOST_FT_cv ; +}; +template< > +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, 51 > +{ +template struct synthesize_impl_i +{ +private: +typedef typename mpl::begin ::type iter_0; +typedef typename mpl::next< iter_0 > ::type iter_1; +typedef typename mpl::next< iter_1 > ::type iter_2; +typedef typename mpl::next< iter_2 > ::type iter_3; +typedef typename mpl::next< iter_3 > ::type iter_4; +typedef typename mpl::next< iter_4 > ::type iter_5; +typedef typename mpl::next< iter_5 > ::type iter_6; +typedef typename mpl::next< iter_6 > ::type iter_7; +typedef typename mpl::next< iter_7 > ::type iter_8; +typedef typename mpl::next< iter_8 > ::type iter_9; +typedef typename mpl::next< iter_9 > ::type iter_10; +typedef typename mpl::next< iter_10 > ::type iter_11; +typedef typename mpl::next< iter_11 > ::type iter_12; +typedef typename mpl::next< iter_12 > ::type iter_13; +typedef typename mpl::next< iter_13 > ::type iter_14; +typedef typename mpl::next< iter_14 > ::type iter_15; +typedef typename mpl::next< iter_15 > ::type iter_16; +typedef typename mpl::next< iter_16 > ::type iter_17; +typedef typename mpl::next< iter_17 > ::type iter_18; +typedef typename mpl::next< iter_18 > ::type iter_19; +typedef typename mpl::next< iter_19 > ::type iter_20; +typedef typename mpl::next< iter_20 > ::type iter_21; +typedef typename mpl::next< iter_21 > ::type iter_22; +typedef typename mpl::next< iter_22 > ::type iter_23; +typedef typename mpl::next< iter_23 > ::type iter_24; +typedef typename mpl::next< iter_24 > ::type iter_25; +typedef typename mpl::next< iter_25 > ::type iter_26; +typedef typename mpl::next< iter_26 > ::type iter_27; +typedef typename mpl::next< iter_27 > ::type iter_28; +typedef typename mpl::next< iter_28 > ::type iter_29; +typedef typename mpl::next< iter_29 > ::type iter_30; +typedef typename mpl::next< iter_30 > ::type iter_31; +typedef typename mpl::next< iter_31 > ::type iter_32; +typedef typename mpl::next< iter_32 > ::type iter_33; +typedef typename mpl::next< iter_33 > ::type iter_34; +typedef typename mpl::next< iter_34 > ::type iter_35; +typedef typename mpl::next< iter_35 > ::type iter_36; +typedef typename mpl::next< iter_36 > ::type iter_37; +typedef typename mpl::next< iter_37 > ::type iter_38; +typedef typename mpl::next< iter_38 > ::type iter_39; +typedef typename mpl::next< iter_39 > ::type iter_40; +typedef typename mpl::next< iter_40 > ::type iter_41; +typedef typename mpl::next< iter_41 > ::type iter_42; +typedef typename mpl::next< iter_42 > ::type iter_43; +typedef typename mpl::next< iter_43 > ::type iter_44; +typedef typename mpl::next< iter_44 > ::type iter_45; +typedef typename mpl::next< iter_45 > ::type iter_46; +typedef typename mpl::next< iter_46 > ::type iter_47; +typedef typename mpl::next< iter_47 > ::type iter_48; +typedef typename mpl::next< iter_48 > ::type iter_49; +typedef typename mpl::next< iter_49 > ::type iter_50; +public: +typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,50) +< typename mpl::deref< iter_0 > ::type +, typename detail::cv_traits< +typename mpl::deref< iter_1 > ::type > ::type +, typename mpl::deref< iter_2 > ::type +, typename mpl::deref< iter_3 > ::type +, typename mpl::deref< iter_4 > ::type +, typename mpl::deref< iter_5 > ::type +, typename mpl::deref< iter_6 > ::type +, typename mpl::deref< iter_7 > ::type +, typename mpl::deref< iter_8 > ::type +, typename mpl::deref< iter_9 > ::type +, typename mpl::deref< iter_10 > ::type +, typename mpl::deref< iter_11 > ::type +, typename mpl::deref< iter_12 > ::type +, typename mpl::deref< iter_13 > ::type +, typename mpl::deref< iter_14 > ::type +, typename mpl::deref< iter_15 > ::type +, typename mpl::deref< iter_16 > ::type +, typename mpl::deref< iter_17 > ::type +, typename mpl::deref< iter_18 > ::type +, typename mpl::deref< iter_19 > ::type +, typename mpl::deref< iter_20 > ::type +, typename mpl::deref< iter_21 > ::type +, typename mpl::deref< iter_22 > ::type +, typename mpl::deref< iter_23 > ::type +, typename mpl::deref< iter_24 > ::type +, typename mpl::deref< iter_25 > ::type +, typename mpl::deref< iter_26 > ::type +, typename mpl::deref< iter_27 > ::type +, typename mpl::deref< iter_28 > ::type +, typename mpl::deref< iter_29 > ::type +, typename mpl::deref< iter_30 > ::type +, typename mpl::deref< iter_31 > ::type +, typename mpl::deref< iter_32 > ::type +, typename mpl::deref< iter_33 > ::type +, typename mpl::deref< iter_34 > ::type +, typename mpl::deref< iter_35 > ::type +, typename mpl::deref< iter_36 > ::type +, typename mpl::deref< iter_37 > ::type +, typename mpl::deref< iter_38 > ::type +, typename mpl::deref< iter_39 > ::type +, typename mpl::deref< iter_40 > ::type +, typename mpl::deref< iter_41 > ::type +, typename mpl::deref< iter_42 > ::type +, typename mpl::deref< iter_43 > ::type +, typename mpl::deref< iter_44 > ::type +, typename mpl::deref< iter_45 > ::type +, typename mpl::deref< iter_46 > ::type +, typename mpl::deref< iter_47 > ::type +, typename mpl::deref< iter_48 > ::type +, typename mpl::deref< iter_49 > ::type +, typename mpl::deref< iter_50 > ::type +> ::type type; +}; +}; +# undef BOOST_FT_make_type +# undef BOOST_FT_make_type_impl + diff --git a/win32/include/boost/function_types/detail/synthesize_impl/master.hpp b/win32/include/boost/function_types/detail/synthesize_impl/master.hpp new file mode 100755 index 000000000..131be3d42 --- /dev/null +++ b/win32/include/boost/function_types/detail/synthesize_impl/master.hpp @@ -0,0 +1,87 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +// no include guards, this file is intended for multiple inclusion + +#if BOOST_FT_ARITY_LOOP_PREFIX + +# ifndef BOOST_FT_DETAIL_SYNTHESIZE_IMPL_MASTER_HPP_INCLUDED +# define BOOST_FT_DETAIL_SYNTHESIZE_IMPL_MASTER_HPP_INCLUDED +# include +# include +# include +# include +# include +# endif + +# define BOOST_FT_type_name type + +# ifdef BOOST_FT_flags +# define BOOST_FT_make_type(flags,cc,arity) BOOST_FT_make_type_impl(flags,cc,arity) +# define BOOST_FT_make_type_impl(flags,cc,arity) make_type_ ## flags ## _ ## cc ## _ ## arity +# else +BOOST_PP_EXPAND(#) define BOOST_FT_make_type(flags,cc,arity) BOOST_FT_make_type_impl(flags,cc,arity) +BOOST_PP_EXPAND(#) define BOOST_FT_make_type_impl(flags,cc,arity) make_type_ ## flags ## _ ## cc ## _ ## arity +# endif + +# define BOOST_FT_iter(i) BOOST_PP_CAT(iter_,i) + +#elif BOOST_FT_ARITY_LOOP_IS_ITERATING + +template< BOOST_FT_tplargs(BOOST_PP_IDENTITY(typename)) > +struct BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,BOOST_FT_arity) +{ + typedef BOOST_FT_type ; +}; + +template<> +struct synthesize_impl_o< BOOST_FT_flags, BOOST_FT_cc_id, BOOST_FT_n > +{ + template struct synthesize_impl_i + { + private: + typedef typename mpl::begin::type BOOST_FT_iter(0); +# if BOOST_FT_n > 1 +# define BOOST_PP_LOCAL_MACRO(i) typedef typename mpl::next< \ + BOOST_FT_iter(BOOST_PP_DEC(i)) >::type BOOST_FT_iter(i); +# define BOOST_PP_LOCAL_LIMITS (1,BOOST_FT_n-1) +# include BOOST_PP_LOCAL_ITERATE() +# endif + public: + typedef typename detail::BOOST_FT_make_type(BOOST_FT_flags,BOOST_FT_cc_id,BOOST_FT_arity) + < typename mpl::deref< BOOST_FT_iter(0) >::type +# if BOOST_FT_mfp + , typename detail::cv_traits< + typename mpl::deref< BOOST_FT_iter(1) >::type >::type +# endif +# if BOOST_FT_n > (BOOST_FT_mfp+1) +# define BOOST_PP_LOCAL_LIMITS (BOOST_FT_mfp+1,BOOST_FT_n-1) +# define BOOST_PP_LOCAL_MACRO(i) \ + , typename mpl::deref< BOOST_FT_iter(i) >::type +# include BOOST_PP_LOCAL_ITERATE() +# endif + >::type type; + }; +}; + +#elif BOOST_FT_ARITY_LOOP_SUFFIX + +# ifdef BOOST_FT_flags +# undef BOOST_FT_make_type +# undef BOOST_FT_make_type_impl +# else +BOOST_PP_EXPAND(#) undef BOOST_FT_make_type +BOOST_PP_EXPAND(#) undef BOOST_FT_make_type_impl +# endif +# undef BOOST_FT_iter +# undef BOOST_FT_type_name + +#else +# error "attempt to use arity loop master file without loop" +#endif + diff --git a/win32/include/boost/function_types/detail/to_sequence.hpp b/win32/include/boost/function_types/detail/to_sequence.hpp new file mode 100755 index 000000000..aa3e2a1a3 --- /dev/null +++ b/win32/include/boost/function_types/detail/to_sequence.hpp @@ -0,0 +1,47 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_DETAIL_TO_SEQUENCE_HPP_INCLUDED +#define BOOST_FT_DETAIL_TO_SEQUENCE_HPP_INCLUDED + +#include +#include +#include +#include +#include + +#include + +namespace boost { namespace function_types { namespace detail { + +// wrap first arguments in components, if callable builtin type +template +struct to_sequence +{ + typedef typename + mpl::eval_if + < is_callable_builtin + , to_sequence< components > + , mpl::identity< T > + >::type + type; +}; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +// reduce template instantiations, if possible +template +struct to_sequence< components > +{ + typedef typename components::types type; +}; +#endif + +} } } // namespace ::boost::function_types::detail + +#endif + diff --git a/win32/include/boost/function_types/function_arity.hpp b/win32/include/boost/function_types/function_arity.hpp new file mode 100755 index 000000000..84d2f2b14 --- /dev/null +++ b/win32/include/boost/function_types/function_arity.hpp @@ -0,0 +1,38 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_FUNCTION_ARITY_HPP_INCLUDED +#define BOOST_FT_FUNCTION_ARITY_HPP_INCLUDED + +#include +#include + +#include +#include + +#include +#include + +namespace boost +{ + namespace function_types + { + template struct function_arity + : mpl::if_ + < function_types::is_callable_builtin + , typename components::function_arity, boost::blank + >::type + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,function_arity,(T)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1,function_types::function_arity) +} + +#endif + diff --git a/win32/include/boost/function_types/function_pointer.hpp b/win32/include/boost/function_types/function_pointer.hpp new file mode 100755 index 000000000..5182bc958 --- /dev/null +++ b/win32/include/boost/function_types/function_pointer.hpp @@ -0,0 +1,32 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_FUNCTION_POINTER_HPP_INCLUDED +#define BOOST_FT_FUNCTION_POINTER_HPP_INCLUDED + +#include +#include + +#include + +namespace boost +{ + namespace function_types + { + template struct function_pointer + { + typedef typename function_types::function_type::type * type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,function_pointer,(Types,Tag)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::function_pointer) +} + +#endif + diff --git a/win32/include/boost/function_types/function_reference.hpp b/win32/include/boost/function_types/function_reference.hpp new file mode 100755 index 000000000..58d0bbb90 --- /dev/null +++ b/win32/include/boost/function_types/function_reference.hpp @@ -0,0 +1,32 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_FUNCTION_REFERENCE_HPP_INCLUDED +#define BOOST_FT_FUNCTION_REFERENCE_HPP_INCLUDED + +#include +#include + +#include + +namespace boost +{ + namespace function_types + { + template struct function_reference + { + typedef typename function_types::function_type::type & type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,function_reference,(Types,Tag)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::function_reference) +} + +#endif + diff --git a/win32/include/boost/function_types/function_type.hpp b/win32/include/boost/function_types/function_type.hpp new file mode 100755 index 000000000..2fca24233 --- /dev/null +++ b/win32/include/boost/function_types/function_type.hpp @@ -0,0 +1,29 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_FUNCTION_TYPE_HPP_INCLUDED +#define BOOST_FT_FUNCTION_TYPE_HPP_INCLUDED + +#include +#include + +namespace boost +{ + namespace function_types + { + template struct function_type + : detail::synthesize_func::type, Tag> + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,function_type,(Types,Tag)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::function_type) +} + +#endif + diff --git a/win32/include/boost/function_types/is_callable_builtin.hpp b/win32/include/boost/function_types/is_callable_builtin.hpp new file mode 100755 index 000000000..f323cda60 --- /dev/null +++ b/win32/include/boost/function_types/is_callable_builtin.hpp @@ -0,0 +1,35 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_IS_CALLABLE_BUILTIN_HPP_INCLUDED +#define BOOST_FT_IS_CALLABLE_BUILTIN_HPP_INCLUDED + +#include +#include + +#include + +namespace boost +{ + namespace function_types + { + template< typename T, typename Tag = null_tag > + struct is_callable_builtin + : function_types::represents + < function_types::components + , function_types::tag + > + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,is_callable_builtin,(T,Tag)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::is_callable_builtin) +} + +#endif + diff --git a/win32/include/boost/function_types/is_function.hpp b/win32/include/boost/function_types/is_function.hpp new file mode 100755 index 000000000..6cb2049bf --- /dev/null +++ b/win32/include/boost/function_types/is_function.hpp @@ -0,0 +1,34 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_IS_FUNCTION_HPP_INCLUDED +#define BOOST_FT_IS_FUNCTION_HPP_INCLUDED + +#include +#include + +#include + +namespace boost +{ + namespace function_types + { + template< typename T, typename Tag = null_tag > + struct is_function + : function_types::represents + < function_types::components + , function_types::tag + > + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,is_function,(T,Tag)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::is_function) +} + +#endif + diff --git a/win32/include/boost/function_types/is_function_pointer.hpp b/win32/include/boost/function_types/is_function_pointer.hpp new file mode 100755 index 000000000..be52c2baa --- /dev/null +++ b/win32/include/boost/function_types/is_function_pointer.hpp @@ -0,0 +1,34 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_IS_FUNCTION_POINTER_HPP_INCLUDED +#define BOOST_FT_IS_FUNCTION_POINTER_HPP_INCLUDED + +#include +#include + +#include + +namespace boost +{ + namespace function_types + { + template< typename T, typename Tag = null_tag > + struct is_function_pointer + : function_types::represents + < function_types::components + , function_types::tag + > + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,is_function_pointer,(T,Tag)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::is_function_pointer) +} + +#endif diff --git a/win32/include/boost/function_types/is_function_reference.hpp b/win32/include/boost/function_types/is_function_reference.hpp new file mode 100755 index 000000000..08b464422 --- /dev/null +++ b/win32/include/boost/function_types/is_function_reference.hpp @@ -0,0 +1,34 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_IS_FUNCTION_REFERENCE_HPP_INCLUDED +#define BOOST_FT_IS_FUNCTION_REFERENCE_HPP_INCLUDED + +#include +#include + +#include + +namespace boost +{ + namespace function_types + { + template< typename T, typename Tag = null_tag > + struct is_function_reference + : function_types::represents + < function_types::components + , function_types::tag > + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,is_function_reference,(T,Tag)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::is_function_reference) +} + +#endif + diff --git a/win32/include/boost/function_types/is_member_function_pointer.hpp b/win32/include/boost/function_types/is_member_function_pointer.hpp new file mode 100755 index 000000000..744829bd6 --- /dev/null +++ b/win32/include/boost/function_types/is_member_function_pointer.hpp @@ -0,0 +1,33 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_IS_MEMBER_FUNCTION_POINTER_HPP_INCLUDED +#define BOOST_FT_IS_MEMBER_FUNCTION_POINTER_HPP_INCLUDED + +#include +#include + +#include + +namespace boost +{ + namespace function_types + { + template< typename T, typename Tag = null_tag > + struct is_member_function_pointer + : function_types::represents + < function_types::components + , function_types::tag > + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,is_member_function_pointer,(T,Tag)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::is_member_function_pointer) +} +#endif + diff --git a/win32/include/boost/function_types/is_member_object_pointer.hpp b/win32/include/boost/function_types/is_member_object_pointer.hpp new file mode 100755 index 000000000..a21a68f85 --- /dev/null +++ b/win32/include/boost/function_types/is_member_object_pointer.hpp @@ -0,0 +1,34 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_IS_MEMBER_OBJECT_POINTER_HPP_INCLUDED +#define BOOST_FT_IS_MEMBER_OBJECT_POINTER_HPP_INCLUDED + +#include +#include + +#include + +namespace boost +{ + namespace function_types + { + template< typename T > + struct is_member_object_pointer + : function_types::detail::represents_impl + < function_types::components + , detail::member_object_pointer_tag > + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_member_object_pointer,(T)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1,function_types::is_member_object_pointer) +} + +#endif + diff --git a/win32/include/boost/function_types/is_member_pointer.hpp b/win32/include/boost/function_types/is_member_pointer.hpp new file mode 100755 index 000000000..2d3b89ad2 --- /dev/null +++ b/win32/include/boost/function_types/is_member_pointer.hpp @@ -0,0 +1,34 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_IS_MEMBER_POINTER_HPP_INCLUDED +#define BOOST_FT_IS_MEMBER_POINTER_HPP_INCLUDED + +#include +#include + +#include + +namespace boost +{ + namespace function_types + { + template< typename T, typename Tag = null_tag > + struct is_member_pointer + : function_types::represents + < function_types::components + , function_types::tag + > + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,is_member_pointer,(T,Tag)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::is_member_pointer) +} + +#endif + diff --git a/win32/include/boost/function_types/is_nonmember_callable_builtin.hpp b/win32/include/boost/function_types/is_nonmember_callable_builtin.hpp new file mode 100755 index 000000000..f63babc45 --- /dev/null +++ b/win32/include/boost/function_types/is_nonmember_callable_builtin.hpp @@ -0,0 +1,35 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_IS_NONMEMBER_CALLABLE_BUILTIN_HPP_INCLUDED +#define BOOST_FT_IS_NONMEMBER_CALLABLE_BUILTIN_HPP_INCLUDED + +#include +#include + +#include + +namespace boost +{ + namespace function_types + { + template< typename T, typename Tag = null_tag > + struct is_nonmember_callable_builtin + : function_types::represents + < function_types::components + , function_types::tag + > + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,is_nonmember_callable_builtin,(T,Tag)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::is_nonmember_callable_builtin) +} + +#endif + diff --git a/win32/include/boost/function_types/member_function_pointer.hpp b/win32/include/boost/function_types/member_function_pointer.hpp new file mode 100755 index 000000000..082713c09 --- /dev/null +++ b/win32/include/boost/function_types/member_function_pointer.hpp @@ -0,0 +1,33 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_MEMBER_FUNCTION_POINTER_HPP_INCLUDED +#define BOOST_FT_MEMBER_FUNCTION_POINTER_HPP_INCLUDED + +#include +#include + +#include +#include + +namespace boost +{ + namespace function_types + { + template + struct member_function_pointer + : detail::synthesize_mfp< typename detail::to_sequence::type, Tag > + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,member_function_pointer,(Types,Tag)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::member_function_pointer) +} + +#endif + diff --git a/win32/include/boost/function_types/member_object_pointer.hpp b/win32/include/boost/function_types/member_object_pointer.hpp new file mode 100755 index 000000000..070a334b2 --- /dev/null +++ b/win32/include/boost/function_types/member_object_pointer.hpp @@ -0,0 +1,34 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_MEMBER_OBJECT_POINTER_HPP_INCLUDED +#define BOOST_FT_MEMBER_OBJECT_POINTER_HPP_INCLUDED + +#include +#include + +#include +#include + +namespace boost +{ + namespace function_types + { + template + struct member_object_pointer + : detail::synthesize_mop< typename detail::to_sequence::type > + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,member_object_pointer,(Types)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1,function_types::member_object_pointer) +} + +#endif + + diff --git a/win32/include/boost/function_types/parameter_types.hpp b/win32/include/boost/function_types/parameter_types.hpp new file mode 100755 index 000000000..08fb79332 --- /dev/null +++ b/win32/include/boost/function_types/parameter_types.hpp @@ -0,0 +1,55 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_PARAMETER_TYPES_HPP_INCLUDED +#define BOOST_FT_PARAMETER_TYPES_HPP_INCLUDED + +#include +#include + +#include +#include + +#include + +#include +#include + +namespace boost +{ + namespace function_types + { + using mpl::placeholders::_; + + template< typename T, typename ClassTypeTransform = add_reference<_> > + struct parameter_types; + + namespace detail + { + template + struct parameter_types_impl + : mpl::pop_front + < typename function_types::components::types + >::type + { }; + } + + template struct parameter_types + : mpl::if_ + < function_types::is_callable_builtin + , detail::parameter_types_impl, boost::blank + >::type + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,parameter_types,(T,ClassTypeTransform)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(2,function_types::parameter_types) +} + +#endif + diff --git a/win32/include/boost/function_types/property_tags.hpp b/win32/include/boost/function_types/property_tags.hpp new file mode 100755 index 000000000..74f710adb --- /dev/null +++ b/win32/include/boost/function_types/property_tags.hpp @@ -0,0 +1,149 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_DETAIL_TAGS_HPP_INCLUDED +#define BOOST_FT_DETAIL_TAGS_HPP_INCLUDED + +#include + +#include +#include + + +namespace boost { namespace function_types { + +namespace detail +{ + typedef long bits_t; + + template struct constant + : boost::integral_constant + { }; + + template struct property_tag + { + typedef constant bits; + typedef constant mask; + }; + + template struct bits : T::bits { }; + template struct mask : T::mask { }; + + // forward declaration, defined in pp_tags + template struct encode_bits_impl; + + // forward declaration, defined in pp_tags + template + struct tag_ice; + + // forward declaration, defined in retag_default_cc + template struct retag_default_cc; + + template struct encode_bits + : constant< + ::boost::function_types::detail::encode_bits_impl::value + > + { }; + + template struct compound_tag + { + typedef constant< + ::boost::function_types::detail::tag_ice + < ::boost::function_types::detail::bits::value + , ::boost::function_types::detail::mask::value + , ::boost::function_types::detail::bits::value + , ::boost::function_types::detail::mask::value + >::combined_bits + > bits; + + typedef constant< + ::boost::function_types::detail::tag_ice + < ::boost::function_types::detail::bits::value + , ::boost::function_types::detail::mask::value + , ::boost::function_types::detail::bits::value + , ::boost::function_types::detail::mask::value + >::combined_mask + > mask; + }; + + template + struct changed_tag + : Base + { + typedef mpl::bitxor_ + + bits; + }; + + template struct represents_impl + : boost::integral_constant::value + , ::boost::function_types::detail::mask::value + , ::boost::function_types::detail::bits::value + , ::boost::function_types::detail::mask::value + >::match + > + { }; + +} // namespace detail + +typedef detail::property_tag<0,0> null_tag; + +template +struct tag + : detail::compound_tag< detail::compound_tag, + detail::compound_tag > +{ }; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template struct tag + : detail::compound_tag,Tag3> +{ }; +template struct tag + : detail::compound_tag +{ }; +template struct tag + : Tag1 +{ }; +#endif + + +template struct represents + : detail::represents_impl > +{ }; + + +template struct extract +{ + typedef detail::constant< + ::boost::function_types::detail::tag_ice + < ::boost::function_types::detail::bits::value + , ::boost::function_types::detail::mask::value + , ::boost::function_types::detail::bits::value + , ::boost::function_types::detail::mask::value + >::extracted_bits + > bits; + + typedef detail::constant< + ::boost::function_types::detail::mask::value + > mask; +}; + +} } // namespace ::boost::function_types + +#include + +namespace boost { namespace function_types { +#define BOOST_FT_cc_file +#include +} } // namespace boost::function_types + +#endif + diff --git a/win32/include/boost/function_types/result_type.hpp b/win32/include/boost/function_types/result_type.hpp new file mode 100755 index 000000000..3bf172638 --- /dev/null +++ b/win32/include/boost/function_types/result_type.hpp @@ -0,0 +1,50 @@ + +// (C) Copyright Tobias Schwinger +// +// Use modification and distribution are subject to the boost Software License, +// Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt). + +//------------------------------------------------------------------------------ + +#ifndef BOOST_FT_RESULT_TYPE_HPP_INCLUDED +#define BOOST_FT_RESULT_TYPE_HPP_INCLUDED + +#include +#include + +#include +#include + +#include + +#include +#include + +namespace boost +{ + namespace function_types + { + template< typename T > struct result_type; + + namespace detail + { + template struct result_type_impl + : mpl::at_c + < typename function_types::components::types, 0 > + { }; + } + + template struct result_type + : mpl::if_ + < function_types::is_callable_builtin + , detail::result_type_impl, boost::blank + >::type + { + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,result_type,(T)) + }; + } + BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1,function_types::result_type) +} + +#endif + diff --git a/win32/include/boost/functional.hpp b/win32/include/boost/functional.hpp new file mode 100755 index 000000000..b1854a939 --- /dev/null +++ b/win32/include/boost/functional.hpp @@ -0,0 +1,548 @@ +// ------------------------------------------------------------------------------ +// Copyright (c) 2000 Cadenza New Zealand Ltd +// Distributed under the Boost Software License, Version 1.0. (See accompany- +// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// ------------------------------------------------------------------------------ +// Boost functional.hpp header file +// See http://www.boost.org/libs/functional for documentation. +// ------------------------------------------------------------------------------ +// $Id: functional.hpp 36246 2006-12-02 14:17:26Z andreas_huber69 $ +// ------------------------------------------------------------------------------ + +#ifndef BOOST_FUNCTIONAL_HPP +#define BOOST_FUNCTIONAL_HPP + +#include +#include +#include + +namespace boost +{ +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // -------------------------------------------------------------------------- + // The following traits classes allow us to avoid the need for ptr_fun + // because the types of arguments and the result of a function can be + // deduced. + // + // In addition to the standard types defined in unary_function and + // binary_function, we add + // + // - function_type, the type of the function or function object itself. + // + // - param_type, the type that should be used for passing the function or + // function object as an argument. + // -------------------------------------------------------------------------- + namespace detail + { + template + struct unary_traits_imp; + + template + struct unary_traits_imp + { + typedef Operation function_type; + typedef const function_type & param_type; + typedef typename Operation::result_type result_type; + typedef typename Operation::argument_type argument_type; + }; + + template + struct unary_traits_imp + { + typedef R (*function_type)(A); + typedef R (*param_type)(A); + typedef R result_type; + typedef A argument_type; + }; + + template + struct binary_traits_imp; + + template + struct binary_traits_imp + { + typedef Operation function_type; + typedef const function_type & param_type; + typedef typename Operation::result_type result_type; + typedef typename Operation::first_argument_type first_argument_type; + typedef typename Operation::second_argument_type second_argument_type; + }; + + template + struct binary_traits_imp + { + typedef R (*function_type)(A1,A2); + typedef R (*param_type)(A1,A2); + typedef R result_type; + typedef A1 first_argument_type; + typedef A2 second_argument_type; + }; + } // namespace detail + + template + struct unary_traits + { + typedef typename detail::unary_traits_imp::function_type function_type; + typedef typename detail::unary_traits_imp::param_type param_type; + typedef typename detail::unary_traits_imp::result_type result_type; + typedef typename detail::unary_traits_imp::argument_type argument_type; + }; + + template + struct unary_traits + { + typedef R (*function_type)(A); + typedef R (*param_type)(A); + typedef R result_type; + typedef A argument_type; + }; + + template + struct binary_traits + { + typedef typename detail::binary_traits_imp::function_type function_type; + typedef typename detail::binary_traits_imp::param_type param_type; + typedef typename detail::binary_traits_imp::result_type result_type; + typedef typename detail::binary_traits_imp::first_argument_type first_argument_type; + typedef typename detail::binary_traits_imp::second_argument_type second_argument_type; + }; + + template + struct binary_traits + { + typedef R (*function_type)(A1,A2); + typedef R (*param_type)(A1,A2); + typedef R result_type; + typedef A1 first_argument_type; + typedef A2 second_argument_type; + }; +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // -------------------------------------------------------------------------- + // If we have no partial specialisation available, decay to a situation + // that is no worse than in the Standard, i.e., ptr_fun will be required. + // -------------------------------------------------------------------------- + + template + struct unary_traits + { + typedef Operation function_type; + typedef const Operation& param_type; + typedef typename Operation::result_type result_type; + typedef typename Operation::argument_type argument_type; + }; + + template + struct binary_traits + { + typedef Operation function_type; + typedef const Operation & param_type; + typedef typename Operation::result_type result_type; + typedef typename Operation::first_argument_type first_argument_type; + typedef typename Operation::second_argument_type second_argument_type; + }; +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // -------------------------------------------------------------------------- + // unary_negate, not1 + // -------------------------------------------------------------------------- + template + class unary_negate + : public std::unary_function::argument_type,bool> + { + public: + explicit unary_negate(typename unary_traits::param_type x) + : + pred(x) + {} + bool operator()(typename call_traits::argument_type>::param_type x) const + { + return !pred(x); + } + private: + typename unary_traits::function_type pred; + }; + + template + unary_negate not1(const Predicate &pred) + { + // The cast is to placate Borland C++Builder in certain circumstances. + // I don't think it should be necessary. + return unary_negate((typename unary_traits::param_type)pred); + } + + template + unary_negate not1(Predicate &pred) + { + return unary_negate(pred); + } + + // -------------------------------------------------------------------------- + // binary_negate, not2 + // -------------------------------------------------------------------------- + template + class binary_negate + : public std::binary_function::first_argument_type, + typename binary_traits::second_argument_type, + bool> + { + public: + explicit binary_negate(typename binary_traits::param_type x) + : + pred(x) + {} + bool operator()(typename call_traits::first_argument_type>::param_type x, + typename call_traits::second_argument_type>::param_type y) const + { + return !pred(x,y); + } + private: + typename binary_traits::function_type pred; + }; + + template + binary_negate not2(const Predicate &pred) + { + // The cast is to placate Borland C++Builder in certain circumstances. + // I don't think it should be necessary. + return binary_negate((typename binary_traits::param_type)pred); + } + + template + binary_negate not2(Predicate &pred) + { + return binary_negate(pred); + } + + // -------------------------------------------------------------------------- + // binder1st, bind1st + // -------------------------------------------------------------------------- + template + class binder1st + : public std::unary_function::second_argument_type, + typename binary_traits::result_type> + { + public: + binder1st(typename binary_traits::param_type x, + typename call_traits::first_argument_type>::param_type y) + : + op(x), value(y) + {} + + typename binary_traits::result_type + operator()(typename call_traits::second_argument_type>::param_type x) const + { + return op(value, x); + } + + protected: + typename binary_traits::function_type op; + typename binary_traits::first_argument_type value; + }; + + template + inline binder1st bind1st(const Operation &op, + typename call_traits< + typename binary_traits::first_argument_type + >::param_type x) + { + // The cast is to placate Borland C++Builder in certain circumstances. + // I don't think it should be necessary. + return binder1st((typename binary_traits::param_type)op, x); + } + + template + inline binder1st bind1st(Operation &op, + typename call_traits< + typename binary_traits::first_argument_type + >::param_type x) + { + return binder1st(op, x); + } + + // -------------------------------------------------------------------------- + // binder2nd, bind2nd + // -------------------------------------------------------------------------- + template + class binder2nd + : public std::unary_function::first_argument_type, + typename binary_traits::result_type> + { + public: + binder2nd(typename binary_traits::param_type x, + typename call_traits::second_argument_type>::param_type y) + : + op(x), value(y) + {} + + typename binary_traits::result_type + operator()(typename call_traits::first_argument_type>::param_type x) const + { + return op(x, value); + } + + protected: + typename binary_traits::function_type op; + typename binary_traits::second_argument_type value; + }; + + template + inline binder2nd bind2nd(const Operation &op, + typename call_traits< + typename binary_traits::second_argument_type + >::param_type x) + { + // The cast is to placate Borland C++Builder in certain circumstances. + // I don't think it should be necessary. + return binder2nd((typename binary_traits::param_type)op, x); + } + + template + inline binder2nd bind2nd(Operation &op, + typename call_traits< + typename binary_traits::second_argument_type + >::param_type x) + { + return binder2nd(op, x); + } + + // -------------------------------------------------------------------------- + // mem_fun, etc + // -------------------------------------------------------------------------- + template + class mem_fun_t : public std::unary_function + { + public: + explicit mem_fun_t(S (T::*p)()) + : + ptr(p) + {} + S operator()(T* p) const + { + return (p->*ptr)(); + } + private: + S (T::*ptr)(); + }; + + template + class mem_fun1_t : public std::binary_function + { + public: + explicit mem_fun1_t(S (T::*p)(A)) + : + ptr(p) + {} + S operator()(T* p, typename call_traits::param_type x) const + { + return (p->*ptr)(x); + } + private: + S (T::*ptr)(A); + }; + + template + class const_mem_fun_t : public std::unary_function + { + public: + explicit const_mem_fun_t(S (T::*p)() const) + : + ptr(p) + {} + S operator()(const T* p) const + { + return (p->*ptr)(); + } + private: + S (T::*ptr)() const; + }; + + template + class const_mem_fun1_t : public std::binary_function + { + public: + explicit const_mem_fun1_t(S (T::*p)(A) const) + : + ptr(p) + {} + S operator()(const T* p, typename call_traits::param_type x) const + { + return (p->*ptr)(x); + } + private: + S (T::*ptr)(A) const; + }; + + template + inline mem_fun_t mem_fun(S (T::*f)()) + { + return mem_fun_t(f); + } + + template + inline mem_fun1_t mem_fun(S (T::*f)(A)) + { + return mem_fun1_t(f); + } + +#ifndef BOOST_NO_POINTER_TO_MEMBER_CONST + template + inline const_mem_fun_t mem_fun(S (T::*f)() const) + { + return const_mem_fun_t(f); + } + + template + inline const_mem_fun1_t mem_fun(S (T::*f)(A) const) + { + return const_mem_fun1_t(f); + } +#endif // BOOST_NO_POINTER_TO_MEMBER_CONST + + // -------------------------------------------------------------------------- + // mem_fun_ref, etc + // -------------------------------------------------------------------------- + template + class mem_fun_ref_t : public std::unary_function + { + public: + explicit mem_fun_ref_t(S (T::*p)()) + : + ptr(p) + {} + S operator()(T& p) const + { + return (p.*ptr)(); + } + private: + S (T::*ptr)(); + }; + + template + class mem_fun1_ref_t : public std::binary_function + { + public: + explicit mem_fun1_ref_t(S (T::*p)(A)) + : + ptr(p) + {} + S operator()(T& p, typename call_traits::param_type x) const + { + return (p.*ptr)(x); + } + private: + S (T::*ptr)(A); + }; + + template + class const_mem_fun_ref_t : public std::unary_function + { + public: + explicit const_mem_fun_ref_t(S (T::*p)() const) + : + ptr(p) + {} + + S operator()(const T &p) const + { + return (p.*ptr)(); + } + private: + S (T::*ptr)() const; + }; + + template + class const_mem_fun1_ref_t : public std::binary_function + { + public: + explicit const_mem_fun1_ref_t(S (T::*p)(A) const) + : + ptr(p) + {} + + S operator()(const T& p, typename call_traits::param_type x) const + { + return (p.*ptr)(x); + } + private: + S (T::*ptr)(A) const; + }; + + template + inline mem_fun_ref_t mem_fun_ref(S (T::*f)()) + { + return mem_fun_ref_t(f); + } + + template + inline mem_fun1_ref_t mem_fun_ref(S (T::*f)(A)) + { + return mem_fun1_ref_t(f); + } + +#ifndef BOOST_NO_POINTER_TO_MEMBER_CONST + template + inline const_mem_fun_ref_t mem_fun_ref(S (T::*f)() const) + { + return const_mem_fun_ref_t(f); + } + + template + inline const_mem_fun1_ref_t mem_fun_ref(S (T::*f)(A) const) + { + return const_mem_fun1_ref_t(f); + } +#endif // BOOST_NO_POINTER_TO_MEMBER_CONST + + // -------------------------------------------------------------------------- + // ptr_fun + // -------------------------------------------------------------------------- + template + class pointer_to_unary_function : public std::unary_function + { + public: + explicit pointer_to_unary_function(Result (*f)(Arg)) + : + func(f) + {} + + Result operator()(typename call_traits::param_type x) const + { + return func(x); + } + + private: + Result (*func)(Arg); + }; + + template + inline pointer_to_unary_function ptr_fun(Result (*f)(Arg)) + { + return pointer_to_unary_function(f); + } + + template + class pointer_to_binary_function : public std::binary_function + { + public: + explicit pointer_to_binary_function(Result (*f)(Arg1, Arg2)) + : + func(f) + {} + + Result operator()(typename call_traits::param_type x, typename call_traits::param_type y) const + { + return func(x,y); + } + + private: + Result (*func)(Arg1, Arg2); + }; + + template + inline pointer_to_binary_function ptr_fun(Result (*f)(Arg1, Arg2)) + { + return pointer_to_binary_function(f); + } +} // namespace boost + +#endif diff --git a/win32/include/boost/functional/detail/container_fwd.hpp b/win32/include/boost/functional/detail/container_fwd.hpp new file mode 100755 index 000000000..3de6b9d5c --- /dev/null +++ b/win32/include/boost/functional/detail/container_fwd.hpp @@ -0,0 +1,95 @@ + +// Copyright 2005-2008 Daniel James. +// 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_DETAIL_CONTAINER_FWD_HPP) +#define BOOST_DETAIL_CONTAINER_FWD_HPP + +#include +#include + +#if BOOST_WORKAROUND(__GNUC__, < 3) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) +#define BOOST_HASH_CHAR_TRAITS string_char_traits +#else +#define BOOST_HASH_CHAR_TRAITS char_traits +#endif + +#if (defined(__GLIBCXX__) && defined(_GLIBCXX_DEBUG)) \ + || BOOST_WORKAROUND(__BORLANDC__, > 0x551) \ + || BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x842)) \ + || (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) + +#include +#include +#include +#include +#include +#include +#include +#include + +#else + +#include + +#if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) && \ + defined(__STL_CONFIG_H) + +#define BOOST_CONTAINER_FWD_BAD_BITSET + +#if !defined(__STL_NON_TYPE_TMPL_PARAM_BUG) +#define BOOST_CONTAINER_FWD_BAD_DEQUE +#endif + +#endif + +#if defined(BOOST_CONTAINER_FWD_BAD_DEQUE) +#include +#endif + +#if defined(BOOST_CONTAINER_FWD_BAD_BITSET) +#include +#endif + +#if defined(BOOST_MSVC) +#pragma warning(push) +#pragma warning(disable:4099) // struct/class mismatch in fwd declarations +#endif + +namespace std +{ + template class allocator; + template class basic_string; + template struct BOOST_HASH_CHAR_TRAITS; + template class complex; +} + +// gcc 3.4 and greater +namespace std +{ +#if !defined(BOOST_CONTAINER_FWD_BAD_DEQUE) + template class deque; +#endif + + template class list; + template class vector; + template class map; + template + class multimap; + template class set; + template class multiset; + +#if !defined(BOOST_CONTAINER_FWD_BAD_BITSET) + template class bitset; +#endif + template struct pair; +} + +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + +#endif + +#endif diff --git a/win32/include/boost/functional/detail/float_functions.hpp b/win32/include/boost/functional/detail/float_functions.hpp new file mode 100755 index 000000000..7600126a5 --- /dev/null +++ b/win32/include/boost/functional/detail/float_functions.hpp @@ -0,0 +1,154 @@ + +// Copyright 2005-2008 Daniel James. +// 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_FUNCTIONAL_DETAIL_FLOAT_FUNCTIONS_HPP) +#define BOOST_FUNCTIONAL_DETAIL_FLOAT_FUNCTIONS_HPP + +#include + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// The C++ standard requires that the C float functions are overloarded +// for float, double and long double in the std namespace, but some of the older +// library implementations don't support this. On some that don't, the C99 +// float functions (frexpf, frexpl, etc.) are available. +// +// Some of this is based on guess work. If I don't know any better I assume that +// the standard C++ overloaded functions are available. If they're not then this +// means that the argument is cast to a double and back, which is inefficient +// and will give pretty bad results for long doubles - so if you know better +// let me know. + +// STLport: +#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION) +# if (defined(__GNUC__) && __GNUC__ < 3 && (defined(linux) || defined(__linux) || defined(__linux__))) || defined(__DMC__) +# define BOOST_HASH_USE_C99_FLOAT_FUNCS +# elif defined(BOOST_MSVC) && BOOST_MSVC < 1300 +# define BOOST_HASH_USE_C99_FLOAT_FUNCS +# else +# define BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS +# endif + +// Roguewave: +// +// On borland 5.51, with roguewave 2.1.1 the standard C++ overloads aren't +// defined, but for the same version of roguewave on sunpro they are. +#elif defined(_RWSTD_VER) +# if defined(__BORLANDC__) +# define BOOST_HASH_USE_C99_FLOAT_FUNCS +# define BOOST_HASH_C99_NO_FLOAT_FUNCS +# elif defined(__DECCXX) +# define BOOST_HASH_USE_C99_FLOAT_FUNCS +# else +# define BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS +# endif + +// libstdc++ (gcc 3.0 onwards, I think) +#elif defined(__GLIBCPP__) || defined(__GLIBCXX__) +# define BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS + +// SGI: +#elif defined(__STL_CONFIG_H) +# if defined(linux) || defined(__linux) || defined(__linux__) +# define BOOST_HASH_USE_C99_FLOAT_FUNCS +# else +# define BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS +# endif + +// Dinkumware. +#elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER) +// Overloaded float functions were probably introduced in an earlier version +// than this. +# if defined(_CPPLIB_VER) && (_CPPLIB_VER >= 402) +# define BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS +# else +# define BOOST_HASH_USE_C99_FLOAT_FUNCS +# endif + +// Digital Mars +#elif defined(__DMC__) +# define BOOST_HASH_USE_C99_FLOAT_FUNCS + +// Use overloaded float functions by default. +#else +# define BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS +#endif + +namespace boost +{ + namespace hash_detail + { + + inline float call_ldexp(float v, int exp) + { + using namespace std; +#if defined(BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS) || \ + defined(BOOST_HASH_C99_NO_FLOAT_FUNCS) + return ldexp(v, exp); +#else + return ldexpf(v, exp); +#endif + } + + inline double call_ldexp(double v, int exp) + { + using namespace std; + return ldexp(v, exp); + } + + inline long double call_ldexp(long double v, int exp) + { + using namespace std; +#if defined(BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS) + return ldexp(v, exp); +#else + return ldexpl(v, exp); +#endif + } + + inline float call_frexp(float v, int* exp) + { + using namespace std; +#if defined(BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS) || \ + defined(BOOST_HASH_C99_NO_FLOAT_FUNCS) + return frexp(v, exp); +#else + return frexpf(v, exp); +#endif + } + + inline double call_frexp(double v, int* exp) + { + using namespace std; + return frexp(v, exp); + } + + inline long double call_frexp(long double v, int* exp) + { + using namespace std; +#if defined(BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS) + return frexp(v, exp); +#else + return frexpl(v, exp); +#endif + } + } +} + +#if defined(BOOST_HASH_USE_C99_FLOAT_FUNCS) +#undef BOOST_HASH_USE_C99_FLOAT_FUNCS +#endif + +#if defined(BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS) +#undef BOOST_HASH_USE_OVERLOAD_FLOAT_FUNCS +#endif + +#if defined(BOOST_HASH_C99_NO_FLOAT_FUNCS) +#undef BOOST_HASH_C99_NO_FLOAT_FUNCS +#endif + +#endif diff --git a/win32/include/boost/functional/detail/hash_float.hpp b/win32/include/boost/functional/detail/hash_float.hpp new file mode 100755 index 000000000..c0b8fc769 --- /dev/null +++ b/win32/include/boost/functional/detail/hash_float.hpp @@ -0,0 +1,201 @@ + +// Copyright 2005-2008 Daniel James. +// 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) + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +#if !defined(BOOST_FUNCTIONAL_DETAIL_HASH_FLOAT_HEADER) +#define BOOST_FUNCTIONAL_DETAIL_HASH_FLOAT_HEADER + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#if defined(BOOST_MSVC) +#pragma warning(push) +#if BOOST_MSVC >= 1400 +#pragma warning(disable:6294) // Ill-defined for-loop: initial condition does + // not satisfy test. Loop body not executed +#endif +#endif + +#include +#include +#include +#include +#include + +// Select implementation for the current platform. + +// Cygwn +#if defined(__CYGWIN__) +# if defined(__i386__) || defined(_M_IX86) +# define BOOST_HASH_USE_x86_BINARY_HASH +# endif + +// STLport +#elif defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION) +// fpclassify aren't good enough on STLport. + +// GNU libstdc++ 3 +#elif defined(__GLIBCPP__) || defined(__GLIBCXX__) +# if (defined(__USE_ISOC99) || defined(_GLIBCXX_USE_C99_MATH)) && \ + !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) +# define BOOST_HASH_USE_FPCLASSIFY +# endif + +// Dinkumware Library, on Visual C++ +#elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER) + +// Not using _fpclass because it is only available for double. + +#endif + +// On OpenBSD, numeric_limits is not reliable for long doubles, but +// the macros defined in are. + +#if defined(__OpenBSD__) +#include +#endif + +namespace boost +{ + namespace hash_detail + { + template + struct limits : std::numeric_limits {}; + +#if defined(__OpenBSD__) + template <> + struct limits + : std::numeric_limits + { + static long double epsilon() { + return LDBL_EPSILON; + } + + static long double (max)() { + return LDBL_MAX; + } + + static long double (min)() { + return LDBL_MIN; + } + + BOOST_STATIC_CONSTANT(int, digits = LDBL_MANT_DIG); + BOOST_STATIC_CONSTANT(int, max_exponent = LDBL_MAX_EXP); + BOOST_STATIC_CONSTANT(int, min_exponent = LDBL_MIN_EXP); + }; +#endif // __OpenBSD__ + + inline void hash_float_combine(std::size_t& seed, std::size_t value) + { + seed ^= value + (seed<<6) + (seed>>2); + } + +// A simple, non-portable hash algorithm for x86. +#if defined(BOOST_HASH_USE_x86_BINARY_HASH) + inline std::size_t float_hash_impl(float v) + { + boost::uint32_t* ptr = (boost::uint32_t*)&v; + std::size_t seed = *ptr; + return seed; + } + + inline std::size_t float_hash_impl(double v) + { + boost::uint32_t* ptr = (boost::uint32_t*)&v; + std::size_t seed = *ptr++; + hash_float_combine(seed, *ptr); + return seed; + } + + inline std::size_t float_hash_impl(long double v) + { + boost::uint32_t* ptr = (boost::uint32_t*)&v; + std::size_t seed = *ptr++; + hash_float_combine(seed, *ptr++); + hash_float_combine(seed, *(boost::uint16_t*)ptr); + return seed; + } + +#else + + template + inline std::size_t float_hash_impl(T v) + { + int exp = 0; + + v = boost::hash_detail::call_frexp(v, &exp); + + // A postive value is easier to hash, so combine the + // sign with the exponent. + if(v < 0) { + v = -v; + exp += limits::max_exponent - + limits::min_exponent; + } + + // The result of frexp is always between 0.5 and 1, so its + // top bit will always be 1. Subtract by 0.5 to remove that. + v -= T(0.5); + v = boost::hash_detail::call_ldexp(v, + limits::digits + 1); + std::size_t seed = static_cast(v); + v -= seed; + + // ceiling(digits(T) * log2(radix(T))/ digits(size_t)) - 1; + std::size_t const length + = (limits::digits * + boost::static_log2::radix>::value - 1) + / limits::digits; + + for(std::size_t i = 0; i != length; ++i) + { + v = boost::hash_detail::call_ldexp(v, + limits::digits); + std::size_t part = static_cast(v); + v -= part; + hash_float_combine(seed, part); + } + + hash_float_combine(seed, exp); + + return seed; + } +#endif + + template + inline std::size_t float_hash_value(T v) + { +#if defined(BOOST_HASH_USE_FPCLASSIFY) + using namespace std; + switch (fpclassify(v)) { + case FP_ZERO: + return 0; + case FP_INFINITE: + return (std::size_t)(v > 0 ? -1 : -2); + case FP_NAN: + return (std::size_t)(-3); + case FP_NORMAL: + case FP_SUBNORMAL: + return float_hash_impl(v); + default: + BOOST_ASSERT(0); + return 0; + } +#else + return v == 0 ? 0 : float_hash_impl(v); +#endif + } + } +} + +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + +#endif diff --git a/win32/include/boost/functional/hash.hpp b/win32/include/boost/functional/hash.hpp new file mode 100755 index 000000000..0e49f3fc2 --- /dev/null +++ b/win32/include/boost/functional/hash.hpp @@ -0,0 +1,11 @@ + +// Copyright 2005-2008 Daniel James. +// 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) + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +#include + diff --git a/win32/include/boost/functional/hash/deque.hpp b/win32/include/boost/functional/hash/deque.hpp new file mode 100755 index 000000000..a285ee752 --- /dev/null +++ b/win32/include/boost/functional/hash/deque.hpp @@ -0,0 +1,27 @@ + +// Copyright 2005-2008 Daniel James. +// 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) + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +#if !defined(BOOST_FUNCTIONAL_HASH_DEQUE_HPP) +#define BOOST_FUNCTIONAL_HASH_DEQUE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#if defined(__EDG__) +#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +#pragma message("Warning: boost/functional/hash/deque.hpp is deprecated, use boost/functional/hash.hpp instead.") +#elif defined(__GNUC__) || defined(__HP_aCC) || \ + defined(__SUNPRO_CC) || defined(__IBMCPP__) +#warning "boost/functional/hash/deque.hpp is deprecated, use boost/functional/hash.hpp instead." +#endif + +#include + +#endif diff --git a/win32/include/boost/functional/hash/extensions.hpp b/win32/include/boost/functional/hash/extensions.hpp new file mode 100755 index 000000000..896a5ff67 --- /dev/null +++ b/win32/include/boost/functional/hash/extensions.hpp @@ -0,0 +1,182 @@ + +// Copyright 2005-2008 Daniel James. +// 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) + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +#if !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP) +#define BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +namespace boost +{ + +#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + namespace hash_detail + { + template + struct call_hash_impl + { + template + struct inner + { + static std::size_t call(T const& v) + { + using namespace boost; + return hash_value(v); + } + }; + }; + + template <> + struct call_hash_impl + { + template + struct inner + { +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + static std::size_t call(Array const& v) +#else + static std::size_t call(Array& v) +#endif + { + const int size = sizeof(v) / sizeof(*v); + return boost::hash_range(v, v + size); + } + }; + }; + + template + struct call_hash + : public call_hash_impl::value> + ::BOOST_NESTED_TEMPLATE inner + { + }; + } +#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + template struct hash + : std::unary_function + { +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + std::size_t operator()(T const& val) const + { + return hash_value(val); + } +#else + std::size_t operator()(T const& val) const + { + return hash_detail::call_hash::call(val); + } +#endif + }; + +#if BOOST_WORKAROUND(__DMC__, <= 0x848) + template struct hash + : std::unary_function + { + std::size_t operator()(const T* val) const + { + return boost::hash_range(val, val+n); + } + }; +#endif + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // On compilers without partial specialization, boost::hash + // has already been declared to deal with pointers, so just + // need to supply the non-pointer version. + + namespace hash_detail + { + template + struct hash_impl; + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + + template <> + struct hash_impl + { + template + struct inner + : std::unary_function + { +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + std::size_t operator()(T const& val) const + { + return hash_value(val); + } +#else + std::size_t operator()(T const& val) const + { + return hash_detail::call_hash::call(val); + } +#endif + }; + }; + +#else // Visual C++ 6.5 + + // There's probably a more elegant way to Visual C++ 6.5 to work + // but I don't know what it is. + + template + struct hash_impl_msvc + { + template + struct inner + : public std::unary_function + { + std::size_t operator()(T const& val) const + { + return hash_detail::call_hash::call(val); + } + + std::size_t operator()(T& val) const + { + return hash_detail::call_hash::call(val); + } + }; + }; + + template <> + struct hash_impl_msvc + { + template + struct inner + : public std::unary_function + { + std::size_t operator()(T& val) const + { + return hash_detail::call_hash::call(val); + } + }; + }; + + template + struct hash_impl_msvc2 + : public hash_impl_msvc::value> + ::BOOST_NESTED_TEMPLATE inner {}; + + template <> + struct hash_impl + { + template + struct inner : public hash_impl_msvc2 {}; + }; + +#endif // Visual C++ 6.5 + } +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +} + +#endif diff --git a/win32/include/boost/functional/hash/hash.hpp b/win32/include/boost/functional/hash/hash.hpp new file mode 100755 index 000000000..138b39992 --- /dev/null +++ b/win32/include/boost/functional/hash/hash.hpp @@ -0,0 +1,529 @@ + +// Copyright 2005-2008 Daniel James. +// 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) + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +#if !defined(BOOST_FUNCTIONAL_HASH_HASH_HPP) +#define BOOST_FUNCTIONAL_HASH_HASH_HPP + +#include +#include +#include +#include +#include + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +#include +#endif + +#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) +#include +#endif + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +#include +#endif + +namespace boost +{ + std::size_t hash_value(bool); + std::size_t hash_value(char); + std::size_t hash_value(unsigned char); + std::size_t hash_value(signed char); + std::size_t hash_value(short); + std::size_t hash_value(unsigned short); + std::size_t hash_value(int); + std::size_t hash_value(unsigned int); + std::size_t hash_value(long); + std::size_t hash_value(unsigned long); + +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) + std::size_t hash_value(wchar_t); +#endif + +#if defined(BOOST_HAS_LONG_LONG) + std::size_t hash_value(boost::long_long_type); + std::size_t hash_value(boost::ulong_long_type); +#endif + +#if !BOOST_WORKAROUND(__DMC__, <= 0x848) + template std::size_t hash_value(T* const&); +#else + template std::size_t hash_value(T*); +#endif + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + template< class T, unsigned N > + std::size_t hash_value(const T (&array)[N]); + + template< class T, unsigned N > + std::size_t hash_value(T (&array)[N]); +#endif + + std::size_t hash_value(float v); + std::size_t hash_value(double v); + std::size_t hash_value(long double v); + + template + std::size_t hash_value(std::basic_string, A> const&); + + template + std::size_t hash_value(std::pair const&); + template + std::size_t hash_value(std::vector const&); + template + std::size_t hash_value(std::list const& v); + template + std::size_t hash_value(std::deque const& v); + template + std::size_t hash_value(std::set const& v); + template + std::size_t hash_value(std::multiset const& v); + template + std::size_t hash_value(std::map const& v); + template + std::size_t hash_value(std::multimap const& v); + + template + std::size_t hash_value(std::complex const&); + + // Implementation + + namespace hash_detail + { + template + inline std::size_t hash_value_signed(T val) + { + const int size_t_bits = std::numeric_limits::digits; + // ceiling(std::numeric_limits::digits / size_t_bits) - 1 + const int length = (std::numeric_limits::digits - 1) + / size_t_bits; + + std::size_t seed = 0; + T positive = val < 0 ? -1 - val : val; + + // Hopefully, this loop can be unrolled. + for(unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits) + { + seed ^= (std::size_t) (positive >> i) + (seed<<6) + (seed>>2); + } + seed ^= (std::size_t) val + (seed<<6) + (seed>>2); + + return seed; + } + + template + inline std::size_t hash_value_unsigned(T val) + { + const int size_t_bits = std::numeric_limits::digits; + // ceiling(std::numeric_limits::digits / size_t_bits) - 1 + const int length = (std::numeric_limits::digits - 1) + / size_t_bits; + + std::size_t seed = 0; + + // Hopefully, this loop can be unrolled. + for(unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits) + { + seed ^= (std::size_t) (val >> i) + (seed<<6) + (seed>>2); + } + seed ^= (std::size_t) val + (seed<<6) + (seed>>2); + + return seed; + } + } + + inline std::size_t hash_value(bool v) + { + return static_cast(v); + } + + inline std::size_t hash_value(char v) + { + return static_cast(v); + } + + inline std::size_t hash_value(unsigned char v) + { + return static_cast(v); + } + + inline std::size_t hash_value(signed char v) + { + return static_cast(v); + } + + inline std::size_t hash_value(short v) + { + return static_cast(v); + } + + inline std::size_t hash_value(unsigned short v) + { + return static_cast(v); + } + + inline std::size_t hash_value(int v) + { + return static_cast(v); + } + + inline std::size_t hash_value(unsigned int v) + { + return static_cast(v); + } + + inline std::size_t hash_value(long v) + { + return static_cast(v); + } + + inline std::size_t hash_value(unsigned long v) + { + return static_cast(v); + } + +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) + inline std::size_t hash_value(wchar_t v) + { + return static_cast(v); + } +#endif + +#if defined(BOOST_HAS_LONG_LONG) + inline std::size_t hash_value(boost::long_long_type v) + { + return hash_detail::hash_value_signed(v); + } + + inline std::size_t hash_value(boost::ulong_long_type v) + { + return hash_detail::hash_value_unsigned(v); + } +#endif + + // Implementation by Alberto Barbati and Dave Harris. +#if !BOOST_WORKAROUND(__DMC__, <= 0x848) + template std::size_t hash_value(T* const& v) +#else + template std::size_t hash_value(T* v) +#endif + { + std::size_t x = static_cast( + reinterpret_cast(v)); + + return x + (x >> 3); + } + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + template + inline void hash_combine(std::size_t& seed, T& v) +#else + template + inline void hash_combine(std::size_t& seed, T const& v) +#endif + { + boost::hash hasher; + seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); + } + + template + inline std::size_t hash_range(It first, It last) + { + std::size_t seed = 0; + + for(; first != last; ++first) + { + hash_combine(seed, *first); + } + + return seed; + } + + template + inline void hash_range(std::size_t& seed, It first, It last) + { + for(; first != last; ++first) + { + hash_combine(seed, *first); + } + } + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + template + inline std::size_t hash_range(T* first, T* last) + { + std::size_t seed = 0; + + for(; first != last; ++first) + { + boost::hash hasher; + seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2); + } + + return seed; + } + + template + inline void hash_range(std::size_t& seed, T* first, T* last) + { + for(; first != last; ++first) + { + boost::hash hasher; + seed ^= hasher(*first) + 0x9e3779b9 + (seed<<6) + (seed>>2); + } + } +#endif + +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + template< class T, unsigned N > + inline std::size_t hash_value(const T (&array)[N]) + { + return hash_range(array, array + N); + } + + template< class T, unsigned N > + inline std::size_t hash_value(T (&array)[N]) + { + return hash_range(array, array + N); + } +#endif + + template + inline std::size_t hash_value(std::basic_string, A> const& v) + { + return hash_range(v.begin(), v.end()); + } + + inline std::size_t hash_value(float v) + { + return boost::hash_detail::float_hash_value(v); + } + + inline std::size_t hash_value(double v) + { + return boost::hash_detail::float_hash_value(v); + } + + inline std::size_t hash_value(long double v) + { + return boost::hash_detail::float_hash_value(v); + } + + template + std::size_t hash_value(std::pair const& v) + { + std::size_t seed = 0; + hash_combine(seed, v.first); + hash_combine(seed, v.second); + return seed; + } + + template + std::size_t hash_value(std::vector const& v) + { + return hash_range(v.begin(), v.end()); + } + + template + std::size_t hash_value(std::list const& v) + { + return hash_range(v.begin(), v.end()); + } + + template + std::size_t hash_value(std::deque const& v) + { + return hash_range(v.begin(), v.end()); + } + + template + std::size_t hash_value(std::set const& v) + { + return hash_range(v.begin(), v.end()); + } + + template + std::size_t hash_value(std::multiset const& v) + { + return hash_range(v.begin(), v.end()); + } + + template + std::size_t hash_value(std::map const& v) + { + return hash_range(v.begin(), v.end()); + } + + template + std::size_t hash_value(std::multimap const& v) + { + return hash_range(v.begin(), v.end()); + } + + template + std::size_t hash_value(std::complex const& v) + { + boost::hash hasher; + std::size_t seed = hasher(v.imag()); + seed ^= hasher(v.real()) + (seed<<6) + (seed>>2); + return seed; + } + + // + // boost::hash + // + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) +#define BOOST_HASH_SPECIALIZE(type) \ + template <> struct hash \ + : public std::unary_function \ + { \ + std::size_t operator()(type v) const \ + { \ + return boost::hash_value(v); \ + } \ + }; + +#define BOOST_HASH_SPECIALIZE_REF(type) \ + template <> struct hash \ + : public std::unary_function \ + { \ + std::size_t operator()(type const& v) const \ + { \ + return boost::hash_value(v); \ + } \ + }; +#else +#define BOOST_HASH_SPECIALIZE(type) \ + template <> struct hash \ + : public std::unary_function \ + { \ + std::size_t operator()(type v) const \ + { \ + return boost::hash_value(v); \ + } \ + }; \ + \ + template <> struct hash \ + : public std::unary_function \ + { \ + std::size_t operator()(const type v) const \ + { \ + return boost::hash_value(v); \ + } \ + }; + +#define BOOST_HASH_SPECIALIZE_REF(type) \ + template <> struct hash \ + : public std::unary_function \ + { \ + std::size_t operator()(type const& v) const \ + { \ + return boost::hash_value(v); \ + } \ + }; \ + \ + template <> struct hash \ + : public std::unary_function \ + { \ + std::size_t operator()(type const& v) const \ + { \ + return boost::hash_value(v); \ + } \ + }; +#endif + + BOOST_HASH_SPECIALIZE(bool) + BOOST_HASH_SPECIALIZE(char) + BOOST_HASH_SPECIALIZE(signed char) + BOOST_HASH_SPECIALIZE(unsigned char) +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) + BOOST_HASH_SPECIALIZE(wchar_t) +#endif + BOOST_HASH_SPECIALIZE(short) + BOOST_HASH_SPECIALIZE(unsigned short) + BOOST_HASH_SPECIALIZE(int) + BOOST_HASH_SPECIALIZE(unsigned int) + BOOST_HASH_SPECIALIZE(long) + BOOST_HASH_SPECIALIZE(unsigned long) + + BOOST_HASH_SPECIALIZE(float) + BOOST_HASH_SPECIALIZE(double) + BOOST_HASH_SPECIALIZE(long double) + + BOOST_HASH_SPECIALIZE_REF(std::string) +#if !defined(BOOST_NO_STD_WSTRING) + BOOST_HASH_SPECIALIZE_REF(std::wstring) +#endif + +#undef BOOST_HASH_SPECIALIZE +#undef BOOST_HASH_SPECIALIZE_REF + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + template + struct hash + : public std::unary_function + { + std::size_t operator()(T* v) const + { +#if !BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) + return boost::hash_value(v); +#else + std::size_t x = static_cast( + reinterpret_cast(v)); + + return x + (x >> 3); +#endif + } + }; +#else + namespace hash_detail + { + template + struct hash_impl; + + template <> + struct hash_impl + { + template + struct inner + : public std::unary_function + { + std::size_t operator()(T val) const + { +#if !BOOST_WORKAROUND(__SUNPRO_CC, <= 590) + return boost::hash_value(val); +#else + std::size_t x = static_cast( + reinterpret_cast(val)); + + return x + (x >> 3); +#endif + } + }; + }; + } + + template struct hash + : public boost::hash_detail::hash_impl::value> + ::BOOST_NESTED_TEMPLATE inner + { + }; +#endif +} + +#endif // BOOST_FUNCTIONAL_HASH_HASH_HPP + +// Include this outside of the include guards in case the file is included +// twice - once with BOOST_HASH_NO_EXTENSIONS defined, and then with it +// undefined. + +#if !defined(BOOST_HASH_NO_EXTENSIONS) \ + && !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP) +#include +#endif diff --git a/win32/include/boost/functional/hash/list.hpp b/win32/include/boost/functional/hash/list.hpp new file mode 100755 index 000000000..9b94d3d90 --- /dev/null +++ b/win32/include/boost/functional/hash/list.hpp @@ -0,0 +1,27 @@ + +// Copyright 2005-2008 Daniel James. +// 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) + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +#if !defined(BOOST_FUNCTIONAL_HASH_LIST_HPP) +#define BOOST_FUNCTIONAL_HASH_LIST_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#if defined(__EDG__) +#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +#pragma message("Warning: boost/functional/hash/list.hpp is deprecated, use boost/functional/hash.hpp instead.") +#elif defined(__GNUC__) || defined(__HP_aCC) || \ + defined(__SUNPRO_CC) || defined(__IBMCPP__) +#warning "boost/functional/hash/list.hpp is deprecated, use boost/functional/hash.hpp instead." +#endif + +#include + +#endif diff --git a/win32/include/boost/functional/hash/map.hpp b/win32/include/boost/functional/hash/map.hpp new file mode 100755 index 000000000..48eda7a65 --- /dev/null +++ b/win32/include/boost/functional/hash/map.hpp @@ -0,0 +1,27 @@ + +// Copyright 2005-2008 Daniel James. +// 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) + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +#if !defined(BOOST_FUNCTIONAL_HASH_MAP_HPP) +#define BOOST_FUNCTIONAL_HASH_MAP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#if defined(__EDG__) +#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +#pragma message("Warning: boost/functional/hash/map.hpp is deprecated, use boost/functional/hash.hpp instead.") +#elif defined(__GNUC__) || defined(__HP_aCC) || \ + defined(__SUNPRO_CC) || defined(__IBMCPP__) +#warning "boost/functional/hash/map.hpp is deprecated, use boost/functional/hash.hpp instead." +#endif + +#include + +#endif diff --git a/win32/include/boost/functional/hash/pair.hpp b/win32/include/boost/functional/hash/pair.hpp new file mode 100755 index 000000000..c1989d5ac --- /dev/null +++ b/win32/include/boost/functional/hash/pair.hpp @@ -0,0 +1,27 @@ + +// Copyright 2005-2008 Daniel James. +// 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) + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +#if !defined(BOOST_FUNCTIONAL_HASH_PAIR_HPP) +#define BOOST_FUNCTIONAL_HASH_PAIR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#if defined(__EDG__) +#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +#pragma message("Warning: boost/functional/hash/pair.hpp is deprecated, use boost/functional/hash.hpp instead.") +#elif defined(__GNUC__) || defined(__HP_aCC) || \ + defined(__SUNPRO_CC) || defined(__IBMCPP__) +#warning "boost/functional/hash/pair.hpp is deprecated, use boost/functional/hash.hpp instead." +#endif + +#include + +#endif diff --git a/win32/include/boost/functional/hash/set.hpp b/win32/include/boost/functional/hash/set.hpp new file mode 100755 index 000000000..19db6eb8a --- /dev/null +++ b/win32/include/boost/functional/hash/set.hpp @@ -0,0 +1,27 @@ + +// Copyright 2005-2008 Daniel James. +// 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) + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +#if !defined(BOOST_FUNCTIONAL_HASH_SET_HPP) +#define BOOST_FUNCTIONAL_HASH_SET_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#if defined(__EDG__) +#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +#pragma message("Warning: boost/functional/hash/set.hpp is deprecated, use boost/functional/hash.hpp instead.") +#elif defined(__GNUC__) || defined(__HP_aCC) || \ + defined(__SUNPRO_CC) || defined(__IBMCPP__) +#warning "boost/functional/hash/set.hpp is deprecated, use boost/functional/hash.hpp instead." +#endif + +#include + +#endif diff --git a/win32/include/boost/functional/hash/vector.hpp b/win32/include/boost/functional/hash/vector.hpp new file mode 100755 index 000000000..659f2b2cb --- /dev/null +++ b/win32/include/boost/functional/hash/vector.hpp @@ -0,0 +1,27 @@ + +// Copyright 2005-2008 Daniel James. +// 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) + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +#if !defined(BOOST_FUNCTIONAL_HASH_VECTOR_HPP) +#define BOOST_FUNCTIONAL_HASH_VECTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#if defined(__EDG__) +#elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__) +#pragma message("Warning: boost/functional/hash/vector.hpp is deprecated, use boost/functional/hash.hpp instead.") +#elif defined(__GNUC__) || defined(__HP_aCC) || \ + defined(__SUNPRO_CC) || defined(__IBMCPP__) +#warning "boost/functional/hash/vector.hpp is deprecated, use boost/functional/hash.hpp instead." +#endif + +#include + +#endif diff --git a/win32/include/boost/functional/hash_fwd.hpp b/win32/include/boost/functional/hash_fwd.hpp new file mode 100755 index 000000000..ccdb28a55 --- /dev/null +++ b/win32/include/boost/functional/hash_fwd.hpp @@ -0,0 +1,40 @@ + +// Copyright 2005-2008 Daniel James. +// 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) + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +#if !defined(BOOST_FUNCTIONAL_HASH_FWD_HPP) +#define BOOST_FUNCTIONAL_HASH_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ + template struct hash; + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + template void hash_combine(std::size_t& seed, T& v); +#else + template void hash_combine(std::size_t& seed, T const& v); +#endif + + template std::size_t hash_range(It, It); + template void hash_range(std::size_t&, It, It); + +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + template inline std::size_t hash_range(T*, T*); + template inline void hash_range(std::size_t&, T*, T*); +#endif +} + +#endif diff --git a/win32/include/boost/fusion/adapted.hpp b/win32/include/boost/fusion/adapted.hpp new file mode 100755 index 000000000..7a797ed8b --- /dev/null +++ b/win32/include/boost/fusion/adapted.hpp @@ -0,0 +1,17 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_ADAPTED_30122005_1420) +#define BOOST_FUSION_ADAPTED_30122005_1420 + +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/adapted/array.hpp b/win32/include/boost/fusion/adapted/array.hpp new file mode 100755 index 000000000..71bd2128a --- /dev/null +++ b/win32/include/boost/fusion/adapted/array.hpp @@ -0,0 +1,22 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_ARRAY_27122005_1035) +#define BOOST_FUSION_ARRAY_27122005_1035 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/adapted/array/array_iterator.hpp b/win32/include/boost/fusion/adapted/array/array_iterator.hpp new file mode 100755 index 000000000..2830dff81 --- /dev/null +++ b/win32/include/boost/fusion/adapted/array/array_iterator.hpp @@ -0,0 +1,107 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_ARRAY_ITERATOR_26122005_2250) +#define BOOST_FUSION_ARRAY_ITERATOR_26122005_2250 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct random_access_traversal_tag; + + template + struct array_iterator + : iterator_facade, random_access_traversal_tag> + { + BOOST_MPL_ASSERT_RELATION(Pos, >=, 0); + BOOST_MPL_ASSERT_RELATION(Pos, <=, Array::static_size); + + typedef mpl::int_ index; + typedef Array array_type; + + array_iterator(Array& a) + : array(a) {} + + Array& array; + + template + struct value_of + { + typedef typename Iterator::array_type array_type; + typedef typename array_type::value_type type; + }; + + template + struct deref + { + typedef typename Iterator::array_type array_type; + typedef typename + mpl::if_< + is_const + , typename array_type::const_reference + , typename array_type::reference + >::type + type; + + static type + call(Iterator const & it) + { + return it.array[Iterator::index::value]; + } + }; + + template + struct advance + { + typedef typename Iterator::index index; + typedef typename Iterator::array_type array_type; + typedef array_iterator type; + + static type + call(Iterator const& i) + { + return type(i.array); + } + }; + + template + struct next : advance > {}; + + template + struct prior : advance > {}; + + template + struct distance : mpl::minus + { + typedef typename + mpl::minus< + typename I2::index, typename I1::index + >::type + type; + + static type + call(I1 const&, I2 const&) + { + return type(); + } + }; + + private: + + array_iterator& operator=(array_iterator const&); + }; +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/array/detail/at_impl.hpp b/win32/include/boost/fusion/adapted/array/detail/at_impl.hpp new file mode 100755 index 000000000..4b9ee2362 --- /dev/null +++ b/win32/include/boost/fusion/adapted/array/detail/at_impl.hpp @@ -0,0 +1,45 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_AT_IMPL_27122005_1241) +#define BOOST_FUSION_AT_IMPL_27122005_1241 + +#include + +#include + +namespace boost { namespace fusion { + + struct array_tag; + + namespace extension + { + template + struct at_impl; + + template<> + struct at_impl + { + template + struct apply + { + typedef typename mpl::if_< + is_const, + typename Sequence::const_reference, + typename Sequence::reference>::type type; + + static type + call(Sequence& seq) + { + return seq[N::value]; + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/array/detail/begin_impl.hpp b/win32/include/boost/fusion/adapted/array/detail/begin_impl.hpp new file mode 100755 index 000000000..75864e7ea --- /dev/null +++ b/win32/include/boost/fusion/adapted/array/detail/begin_impl.hpp @@ -0,0 +1,40 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_BEGIN_IMPL_27122005_1117) +#define BOOST_FUSION_BEGIN_IMPL_27122005_1117 + +#include + +namespace boost { namespace fusion { + + struct array_tag; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef array_iterator type; + + static type + call(Sequence& v) + { + return type(v); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/array/detail/category_of_impl.hpp b/win32/include/boost/fusion/adapted/array/detail/category_of_impl.hpp new file mode 100755 index 000000000..f11aef68c --- /dev/null +++ b/win32/include/boost/fusion/adapted/array/detail/category_of_impl.hpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_CATEGORY_OF_IMPL_27122005_1044) +#define BOOST_FUSION_CATEGORY_OF_IMPL_27122005_1044 + +#include + +namespace boost { namespace fusion { + + struct array_tag; + struct random_access_traversal_tag; + + namespace extension + { + template + struct category_of_impl; + + template<> + struct category_of_impl + { + template + struct apply + { + typedef random_access_traversal_tag type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/array/detail/end_impl.hpp b/win32/include/boost/fusion/adapted/array/detail/end_impl.hpp new file mode 100755 index 000000000..ffbc0b5a0 --- /dev/null +++ b/win32/include/boost/fusion/adapted/array/detail/end_impl.hpp @@ -0,0 +1,40 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_END_IMPL_27122005_1120) +#define BOOST_FUSION_END_IMPL_27122005_1120 + +#include + +namespace boost { namespace fusion { + + struct array_tag; + + namespace extension + { + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef array_iterator type; + + static type + call(Sequence& v) + { + return type(v); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/array/detail/is_sequence_impl.hpp b/win32/include/boost/fusion/adapted/array/detail/is_sequence_impl.hpp new file mode 100755 index 000000000..12fe24f1b --- /dev/null +++ b/win32/include/boost/fusion/adapted/array/detail/is_sequence_impl.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_IS_SEQUENCE_IMPL_27122005_1648) +#define BOOST_FUSION_IS_SEQUENCE_IMPL_27122005_1648 + +#include + +namespace boost { namespace fusion { + + struct array_tag; + + namespace extension + { + template + struct is_sequence_impl; + + template<> + struct is_sequence_impl + { + template + struct apply : mpl::true_ {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/array/detail/is_view_impl.hpp b/win32/include/boost/fusion/adapted/array/detail/is_view_impl.hpp new file mode 100755 index 000000000..355f67fcf --- /dev/null +++ b/win32/include/boost/fusion/adapted/array/detail/is_view_impl.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_IS_VIEW_IMPL_27042006_2221) +#define BOOST_FUSION_IS_VIEW_IMPL_27042006_2221 + +#include + +namespace boost { namespace fusion +{ + struct array_tag; + + namespace extension + { + template + struct is_view_impl; + + template<> + struct is_view_impl + { + template + struct apply : mpl::false_ + {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/array/detail/size_impl.hpp b/win32/include/boost/fusion/adapted/array/detail/size_impl.hpp new file mode 100755 index 000000000..81970cea9 --- /dev/null +++ b/win32/include/boost/fusion/adapted/array/detail/size_impl.hpp @@ -0,0 +1,29 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_SIZE_IMPL_27122005_1251) +#define BOOST_FUSION_SIZE_IMPL_27122005_1251 + +namespace boost { namespace fusion { + + struct array_tag; + + namespace extension + { + template + struct size_impl; + + template<> + struct size_impl + { + template + struct apply : mpl::int_ {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/array/detail/value_at_impl.hpp b/win32/include/boost/fusion/adapted/array/detail/value_at_impl.hpp new file mode 100755 index 000000000..fbf74ed57 --- /dev/null +++ b/win32/include/boost/fusion/adapted/array/detail/value_at_impl.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_VALUE_AT_IMPL_27122005_1256) +#define BOOST_FUSION_VALUE_AT_IMPL_27122005_1256 + +namespace boost { namespace fusion { + + struct array_tag; + + namespace extension + { + template + struct value_at_impl; + + template <> + struct value_at_impl + { + template + struct apply + { + typedef typename Sequence::value_type type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/array/tag_of.hpp b/win32/include/boost/fusion/adapted/array/tag_of.hpp new file mode 100755 index 000000000..c3c3697ca --- /dev/null +++ b/win32/include/boost/fusion/adapted/array/tag_of.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_SEQUENCE_TAG_OF_27122005_1030) +#define FUSION_SEQUENCE_TAG_OF_27122005_1030 + +#include + +#include + +namespace boost +{ + template + class array; +} + +namespace boost { namespace fusion +{ + struct array_tag; + + namespace traits + { + template +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + struct tag_of, void > +#else + struct tag_of > +#endif + { + typedef array_tag type; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/boost_tuple.hpp b/win32/include/boost/fusion/adapted/boost_tuple.hpp new file mode 100755 index 000000000..0b26fbb86 --- /dev/null +++ b/win32/include/boost/fusion/adapted/boost_tuple.hpp @@ -0,0 +1,20 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_BOOST_TUPLE_09272006_0732) +#define BOOST_FUSION_BOOST_TUPLE_09272006_0732 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/adapted/boost_tuple/boost_tuple_iterator.hpp b/win32/include/boost/fusion/adapted/boost_tuple/boost_tuple_iterator.hpp new file mode 100755 index 000000000..9f7a55260 --- /dev/null +++ b/win32/include/boost/fusion/adapted/boost_tuple/boost_tuple_iterator.hpp @@ -0,0 +1,149 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BOOST_TUPLE_ITERATOR_09262006_1851) +#define FUSION_BOOST_TUPLE_ITERATOR_09262006_1851 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct forward_traversal_tag; + + namespace detail + { + template + struct boost_tuple_is_empty : mpl::false_ {}; + + template <> + struct boost_tuple_is_empty : mpl::true_ {}; + + template <> + struct boost_tuple_is_empty : mpl::true_ {}; + + template <> + struct boost_tuple_is_empty > : mpl::true_ {}; + + template <> + struct boost_tuple_is_empty const> : mpl::true_ {}; + } + + template + struct boost_tuple_iterator + : iterator_facade, forward_traversal_tag> + { + typedef Cons cons_type; + + explicit boost_tuple_iterator(Cons& cons) + : cons(cons) {} + Cons& cons; + + template + struct value_of : mpl::identity {}; + + template + struct deref + { + typedef typename value_of::type element; + + typedef typename + mpl::if_< + is_const + , typename tuples::access_traits::const_type + , typename tuples::access_traits::non_const_type + >::type + type; + + static type + call(Iterator const& iter) + { + return iter.cons.get_head(); + } + }; + + template + struct next + { + typedef typename Iterator::cons_type cons_type; + typedef typename cons_type::tail_type tail_type; + + typedef boost_tuple_iterator< + typename mpl::eval_if< + is_const + , add_const + , mpl::identity + >::type> + type; + + static type + call(Iterator const& iter) + { + return type(iter.cons.get_tail()); + } + }; + }; + + template + struct boost_tuple_null_iterator + : iterator_facade, forward_traversal_tag> + { + typedef Null cons_type; + + template + struct equal_to + : mpl::or_< + is_same + , mpl::and_< + detail::boost_tuple_is_empty + , detail::boost_tuple_is_empty + > + > + {}; + }; + + template <> + struct boost_tuple_iterator + : boost_tuple_null_iterator + { + template + explicit boost_tuple_iterator(Cons const&) {} + }; + + template <> + struct boost_tuple_iterator + : boost_tuple_null_iterator + { + template + explicit boost_tuple_iterator(Cons const&) {} + }; + + template <> + struct boost_tuple_iterator > + : boost_tuple_null_iterator > + { + template + explicit boost_tuple_iterator(Cons const&) {} + }; + + template <> + struct boost_tuple_iterator const> + : boost_tuple_null_iterator const> + { + template + explicit boost_tuple_iterator(Cons const&) {} + }; +}} + +#endif + + diff --git a/win32/include/boost/fusion/adapted/boost_tuple/detail/at_impl.hpp b/win32/include/boost/fusion/adapted/boost_tuple/detail/at_impl.hpp new file mode 100755 index 000000000..3f0369a7e --- /dev/null +++ b/win32/include/boost/fusion/adapted/boost_tuple/detail/at_impl.hpp @@ -0,0 +1,50 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_AT_IMPL_09262006_1920) +#define BOOST_FUSION_AT_IMPL_09262006_1920 + +#include +#include + +namespace boost { namespace fusion +{ + struct boost_tuple_tag; + + namespace extension + { + template + struct at_impl; + + template <> + struct at_impl + { + template + struct apply + { + typedef typename + tuples::element::type + element; + + typedef typename + mpl::if_< + is_const + , typename tuples::access_traits::const_type + , typename tuples::access_traits::non_const_type + >::type + type; + + static type + call(Sequence& seq) + { + return tuples::get(seq); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/boost_tuple/detail/begin_impl.hpp b/win32/include/boost/fusion/adapted/boost_tuple/detail/begin_impl.hpp new file mode 100755 index 000000000..4364f65d6 --- /dev/null +++ b/win32/include/boost/fusion/adapted/boost_tuple/detail/begin_impl.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_BEGIN_IMPL_09272006_0719) +#define BOOST_FUSION_BEGIN_IMPL_09272006_0719 + +#include + +namespace boost { namespace fusion +{ + struct boost_tuple_tag; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef boost_tuple_iterator type; + + static type + call(Sequence& v) + { + return type(v); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/boost_tuple/detail/category_of_impl.hpp b/win32/include/boost/fusion/adapted/boost_tuple/detail/category_of_impl.hpp new file mode 100755 index 000000000..663b69e4a --- /dev/null +++ b/win32/include/boost/fusion/adapted/boost_tuple/detail/category_of_impl.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_CATEGORY_OF_IMPL_09272006_0726) +#define BOOST_FUSION_CATEGORY_OF_IMPL_09272006_0726 + +namespace boost { namespace fusion +{ + struct boost_tuple_tag; + struct forward_traversal_tag; + + namespace extension + { + template + struct category_of_impl; + + template<> + struct category_of_impl + { + template + struct apply + { + typedef forward_traversal_tag type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/boost_tuple/detail/end_impl.hpp b/win32/include/boost/fusion/adapted/boost_tuple/detail/end_impl.hpp new file mode 100755 index 000000000..70ab663b6 --- /dev/null +++ b/win32/include/boost/fusion/adapted/boost_tuple/detail/end_impl.hpp @@ -0,0 +1,54 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_END_IMPL_09272006_0721) +#define BOOST_FUSION_END_IMPL_09272006_0721 + +#include +#include +#include + +namespace boost { namespace tuples +{ + struct null_type; +}} + +namespace boost { namespace fusion +{ + struct boost_tuple_tag; + + namespace extension + { + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef + boost_tuple_iterator< + typename mpl::if_< + is_const + , tuples::null_type const + , tuples::null_type + >::type + > + type; + + static type + call(Sequence& seq) + { + return type(seq); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/boost_tuple/detail/is_sequence_impl.hpp b/win32/include/boost/fusion/adapted/boost_tuple/detail/is_sequence_impl.hpp new file mode 100755 index 000000000..c8336b9d3 --- /dev/null +++ b/win32/include/boost/fusion/adapted/boost_tuple/detail/is_sequence_impl.hpp @@ -0,0 +1,30 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_IS_SEQUENCE_IMPL_09272006_0726) +#define BOOST_FUSION_IS_SEQUENCE_IMPL_09272006_0726 + +#include + +namespace boost { namespace fusion +{ + struct boost_tuple_tag; + + namespace extension + { + template + struct is_sequence_impl; + + template<> + struct is_sequence_impl + { + template + struct apply : mpl::true_ {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/boost_tuple/detail/is_view_impl.hpp b/win32/include/boost/fusion/adapted/boost_tuple/detail/is_view_impl.hpp new file mode 100755 index 000000000..d5182fc64 --- /dev/null +++ b/win32/include/boost/fusion/adapted/boost_tuple/detail/is_view_impl.hpp @@ -0,0 +1,30 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_IS_VIEW_IMPL_09272006_0725) +#define BOOST_FUSION_IS_VIEW_IMPL_09272006_0725 + +#include + +namespace boost { namespace fusion +{ + struct boost_tuple_tag; + + namespace extension + { + template + struct is_view_impl; + + template<> + struct is_view_impl + { + template + struct apply : mpl::false_ {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/boost_tuple/detail/size_impl.hpp b/win32/include/boost/fusion/adapted/boost_tuple/detail/size_impl.hpp new file mode 100755 index 000000000..73aac0dfc --- /dev/null +++ b/win32/include/boost/fusion/adapted/boost_tuple/detail/size_impl.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_SIZE_IMPL_09272006_0724) +#define BOOST_FUSION_SIZE_IMPL_09272006_0724 + +#include +#include + +namespace boost { namespace fusion +{ + struct boost_tuple_tag; + + namespace extension + { + template + struct size_impl; + + template <> + struct size_impl + { + template + struct apply : mpl::int_::value> {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/boost_tuple/detail/value_at_impl.hpp b/win32/include/boost/fusion/adapted/boost_tuple/detail/value_at_impl.hpp new file mode 100755 index 000000000..b45fbd64e --- /dev/null +++ b/win32/include/boost/fusion/adapted/boost_tuple/detail/value_at_impl.hpp @@ -0,0 +1,30 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_VALUE_AT_IMPL_09262006_1926) +#define BOOST_FUSION_VALUE_AT_IMPL_09262006_1926 + +#include + +namespace boost { namespace fusion +{ + struct boost_tuple_tag; + + namespace extension + { + template + struct value_at_impl; + + template <> + struct value_at_impl + { + template + struct apply : tuples::element {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/boost_tuple/tag_of.hpp b/win32/include/boost/fusion/adapted/boost_tuple/tag_of.hpp new file mode 100755 index 000000000..15cfe1c60 --- /dev/null +++ b/win32/include/boost/fusion/adapted/boost_tuple/tag_of.hpp @@ -0,0 +1,63 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_TAG_OF_09262006_1900) +#define BOOST_FUSION_TAG_OF_09262006_1900 + +#include + +namespace boost { namespace tuples +{ + struct null_type; + + template < + class T0, class T1, class T2, class T3, class T4, + class T5, class T6, class T7, class T8, class T9 + > + class tuple; + + template + struct cons; +}} + +namespace boost { namespace fusion +{ + struct boost_tuple_tag; + + namespace traits + { + template < + class T0, class T1, class T2, class T3, class T4, + class T5, class T6, class T7, class T8, class T9 + > +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + struct tag_of, void > +#else + struct tag_of > +#endif + { + typedef boost_tuple_tag type; + }; + + template +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + struct tag_of, void > +#else + struct tag_of > +#endif + { + typedef boost_tuple_tag type; + }; + + template <> + struct tag_of + { + typedef boost_tuple_tag type; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/mpl.hpp b/win32/include/boost/fusion/adapted/mpl.hpp new file mode 100755 index 000000000..3f021cf25 --- /dev/null +++ b/win32/include/boost/fusion/adapted/mpl.hpp @@ -0,0 +1,21 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_MPL_31122005_1152) +#define BOOST_FUSION_MPL_31122005_1152 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/adapted/mpl/detail/at_impl.hpp b/win32/include/boost/fusion/adapted/mpl/detail/at_impl.hpp new file mode 100755 index 000000000..38e7ec0ed --- /dev/null +++ b/win32/include/boost/fusion/adapted/mpl/detail/at_impl.hpp @@ -0,0 +1,40 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_AT_IMPL_31122005_1642) +#define BOOST_FUSION_AT_IMPL_31122005_1642 + +#include + +namespace boost { namespace fusion +{ + struct mpl_sequence_tag; + + namespace extension + { + template + struct at_impl; + + template <> + struct at_impl + { + template + struct apply + { + typedef typename mpl::at::type type; + + static type + call(Sequence) + { + return type(); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/mpl/detail/begin_impl.hpp b/win32/include/boost/fusion/adapted/mpl/detail/begin_impl.hpp new file mode 100755 index 000000000..66ca4ba8f --- /dev/null +++ b/win32/include/boost/fusion/adapted/mpl/detail/begin_impl.hpp @@ -0,0 +1,45 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_BEGIN_IMPL_31122005_1209) +#define BOOST_FUSION_BEGIN_IMPL_31122005_1209 + +#include +#include +#include + +namespace boost { namespace fusion { + + struct mpl_sequence_tag; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef typename mpl::begin< + typename remove_const::type + >::type iterator; + typedef mpl_iterator type; + + static type + call(Sequence) + { + return type(); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/mpl/detail/category_of_impl.hpp b/win32/include/boost/fusion/adapted/mpl/detail/category_of_impl.hpp new file mode 100755 index 000000000..c3f862adb --- /dev/null +++ b/win32/include/boost/fusion/adapted/mpl/detail/category_of_impl.hpp @@ -0,0 +1,54 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_CATEGORY_OF_IMPL_20060217_2141) +#define BOOST_FUSION_CATEGORY_OF_IMPL_20060217_2141 + +#include +#include +#include +#include + +namespace boost { namespace fusion { + + namespace detail + { + template + struct mpl_sequence_category_of + { + // assumes T is an mpl sequence + // there should be no way this will ever be + // called where T is an mpl iterator + + BOOST_STATIC_ASSERT(mpl::is_sequence::value); + typedef typename + mpl_iterator_category< + typename mpl::begin::type::category + >::type + type; + }; + } + + struct mpl_sequence_tag; + + namespace extension + { + template + struct category_of_impl; + + template<> + struct category_of_impl + { + template + struct apply + : detail::mpl_sequence_category_of + {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/mpl/detail/empty_impl.hpp b/win32/include/boost/fusion/adapted/mpl/detail/empty_impl.hpp new file mode 100755 index 000000000..6d3bb0ff5 --- /dev/null +++ b/win32/include/boost/fusion/adapted/mpl/detail/empty_impl.hpp @@ -0,0 +1,28 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_EMPTY_IMPL_31122005_1554) +#define BOOST_FUSION_EMPTY_IMPL_31122005_1554 + +#include + +namespace boost { namespace fusion +{ + struct mpl_sequence_tag; + + namespace extension + { + template <> + struct empty_impl + { + template + struct apply : mpl::empty {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/mpl/detail/end_impl.hpp b/win32/include/boost/fusion/adapted/mpl/detail/end_impl.hpp new file mode 100755 index 000000000..7db72a915 --- /dev/null +++ b/win32/include/boost/fusion/adapted/mpl/detail/end_impl.hpp @@ -0,0 +1,45 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_END_IMPL_31122005_1237) +#define BOOST_FUSION_END_IMPL_31122005_1237 + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct mpl_sequence_tag; + + namespace extension + { + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef typename mpl::end< + typename remove_const::type + >::type iterator; + typedef mpl_iterator type; + + static type + call(Sequence) + { + return type(); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/mpl/detail/has_key_impl.hpp b/win32/include/boost/fusion/adapted/mpl/detail/has_key_impl.hpp new file mode 100755 index 000000000..9a032780a --- /dev/null +++ b/win32/include/boost/fusion/adapted/mpl/detail/has_key_impl.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_HAS_KEY_IMPL_31122005_1647) +#define BOOST_FUSION_HAS_KEY_IMPL_31122005_1647 + +#include + +namespace boost { namespace fusion +{ + struct mpl_sequence_tag; + + namespace extension + { + template + struct has_key_impl; + + template <> + struct has_key_impl + { + template + struct apply : mpl::has_key {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/mpl/detail/is_sequence_impl.hpp b/win32/include/boost/fusion/adapted/mpl/detail/is_sequence_impl.hpp new file mode 100755 index 000000000..497be618c --- /dev/null +++ b/win32/include/boost/fusion/adapted/mpl/detail/is_sequence_impl.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_IS_SEQUENCE_IMPL_31122005_1505) +#define BOOST_FUSION_IS_SEQUENCE_IMPL_31122005_1505 + +#include + +namespace boost { namespace fusion +{ + struct mpl_sequence_tag; + + namespace extension + { + template + struct is_sequence_impl; + + template<> + struct is_sequence_impl + { + template + struct apply : mpl::true_ {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/mpl/detail/is_view_impl.hpp b/win32/include/boost/fusion/adapted/mpl/detail/is_view_impl.hpp new file mode 100755 index 000000000..3b935bafe --- /dev/null +++ b/win32/include/boost/fusion/adapted/mpl/detail/is_view_impl.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_IS_VIEW_IMPL_03202006_0048) +#define BOOST_FUSION_IS_VIEW_IMPL_03202006_0048 + +#include + +namespace boost { namespace fusion +{ + struct mpl_sequence_tag; + + namespace extension + { + template + struct is_view_impl; + + template<> + struct is_view_impl + { + template + struct apply : mpl::true_ + {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/mpl/detail/size_impl.hpp b/win32/include/boost/fusion/adapted/mpl/detail/size_impl.hpp new file mode 100755 index 000000000..d3bfdac33 --- /dev/null +++ b/win32/include/boost/fusion/adapted/mpl/detail/size_impl.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_SIZE_IMPL_31122005_1508) +#define BOOST_FUSION_SIZE_IMPL_31122005_1508 + +#include + +namespace boost { namespace fusion +{ + struct mpl_sequence_tag; + + namespace extension + { + template + struct size_impl; + + template <> + struct size_impl + { + template + struct apply : mpl::size {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/mpl/detail/value_at_impl.hpp b/win32/include/boost/fusion/adapted/mpl/detail/value_at_impl.hpp new file mode 100755 index 000000000..7368baceb --- /dev/null +++ b/win32/include/boost/fusion/adapted/mpl/detail/value_at_impl.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_VALUE_AT_IMPL_31122005_1621) +#define BOOST_FUSION_VALUE_AT_IMPL_31122005_1621 + +#include + +namespace boost { namespace fusion +{ + struct mpl_sequence_tag; + + namespace extension + { + template + struct value_at_impl; + + template <> + struct value_at_impl + { + template + struct apply : mpl::at {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/mpl/mpl_iterator.hpp b/win32/include/boost/fusion/adapted/mpl/mpl_iterator.hpp new file mode 100755 index 000000000..06db99e35 --- /dev/null +++ b/win32/include/boost/fusion/adapted/mpl/mpl_iterator.hpp @@ -0,0 +1,113 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_MPL_ITERATOR_05052005_0731) +#define FUSION_MPL_ITERATOR_05052005_0731 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + template + struct mpl_iterator + : iterator_facade< + mpl_iterator + , typename detail::mpl_iterator_category::type + > + { + typedef typename remove_const::type iterator_type; + + template + struct value_of : mpl::deref {}; + + template + struct deref + { + typedef typename mpl::deref< + typename Iterator::iterator_type>::type + type; + + static type + call(Iterator) + { + return type(); + } + }; + + template + struct next + { + typedef mpl_iterator< + typename mpl::next::type> + type; + + static type + call(Iterator) + { + return type(); + } + }; + + template + struct prior + { + typedef mpl_iterator< + typename mpl::prior::type> + type; + + static type + call(Iterator) + { + return type(); + } + }; + + template + struct advance + { + typedef mpl_iterator< + typename mpl::advance::type> + type; + + static type + call(Iterator const& i) + { + return type(); + } + }; + + template + struct distance : + mpl::distance< + typename I1::iterator_type + , typename I2::iterator_type> + { + typedef typename + mpl::distance< + typename I1::iterator_type + , typename I2::iterator_type + >::type + type; + + static type + call(I1 const&, I2 const&) + { + return type(); + } + }; + }; +}} + +#endif + + diff --git a/win32/include/boost/fusion/adapted/std_pair.hpp b/win32/include/boost/fusion/adapted/std_pair.hpp new file mode 100755 index 000000000..cb37fea14 --- /dev/null +++ b/win32/include/boost/fusion/adapted/std_pair.hpp @@ -0,0 +1,70 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_STD_PAIR_24122005_1744) +#define BOOST_FUSION_STD_PAIR_24122005_1744 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct struct_tag; + + namespace traits + { + template +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + struct tag_of, void > +#else + struct tag_of > +#endif + { + typedef struct_tag type; + }; + } + + namespace extension + { + template + struct struct_member; + + template + struct struct_size; + + template + struct struct_member, 0> + { + typedef T1 type; + + static type& call(std::pair& pair) + { + return pair.first; + } + }; + + template + struct struct_member, 1> + { + typedef T2 type; + + static type& call(std::pair& pair) + { + return pair.second; + } + }; + + template + struct struct_size > : mpl::int_<2> + { + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/std_pair/detail/at_impl.hpp b/win32/include/boost/fusion/adapted/std_pair/detail/at_impl.hpp new file mode 100755 index 000000000..f6d124c34 --- /dev/null +++ b/win32/include/boost/fusion/adapted/std_pair/detail/at_impl.hpp @@ -0,0 +1,71 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_AT_IMPL_24122005_1807) +#define BOOST_FUSION_AT_IMPL_24122005_1807 + +#include +#include +#include +#include + +namespace boost { namespace fusion { + + struct std_pair_tag; + + namespace extension + { + template + struct at_impl; + + template <> + struct at_impl + { + template + struct apply + { + static int const n_value = N::value; + BOOST_STATIC_ASSERT((n_value >= 0 && n_value < 2)); + typedef typename + mpl::if_c< + (n_value == 0) + , typename Sequence::first_type + , typename Sequence::second_type + > + element; + + typedef typename + mpl::eval_if< + is_const + , detail::cref_result + , detail::ref_result + >::type + type; + + template + static RT get(Sequence& p, mpl::int_<0>) + { + return p.first; + } + + template + static RT get(Sequence& p, mpl::int_<1>) + { + return p.second; + } + + static type + call(Sequence& p) + { + return get(p, N()); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/std_pair/detail/begin_impl.hpp b/win32/include/boost/fusion/adapted/std_pair/detail/begin_impl.hpp new file mode 100755 index 000000000..2c42d4d1f --- /dev/null +++ b/win32/include/boost/fusion/adapted/std_pair/detail/begin_impl.hpp @@ -0,0 +1,40 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_BEGIN_IMPL_24122005_1752) +#define BOOST_FUSION_BEGIN_IMPL_24122005_1752 + +#include + +namespace boost { namespace fusion { + + struct std_pair_tag; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef std_pair_iterator type; + + static type + call(Sequence& v) + { + return type(v); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/std_pair/detail/category_of_impl.hpp b/win32/include/boost/fusion/adapted/std_pair/detail/category_of_impl.hpp new file mode 100755 index 000000000..248a437f7 --- /dev/null +++ b/win32/include/boost/fusion/adapted/std_pair/detail/category_of_impl.hpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_CATEGORY_OF_IMPL_24122005_1731) +#define BOOST_FUSION_CATEGORY_OF_IMPL_24122005_1731 + +#include + +namespace boost { namespace fusion { + + struct std_pair_tag; + struct random_access_traversal_tag; + + namespace extension + { + template + struct category_of_impl; + + template<> + struct category_of_impl + { + template + struct apply + { + typedef random_access_traversal_tag type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/std_pair/detail/end_impl.hpp b/win32/include/boost/fusion/adapted/std_pair/detail/end_impl.hpp new file mode 100755 index 000000000..a0f9f3da7 --- /dev/null +++ b/win32/include/boost/fusion/adapted/std_pair/detail/end_impl.hpp @@ -0,0 +1,40 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_END_IMPL_24122005_1755) +#define BOOST_FUSION_END_IMPL_24122005_1755 + +#include + +namespace boost { namespace fusion { + + struct std_pair_tag; + + namespace extension + { + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef std_pair_iterator type; + + static type + call(Sequence& v) + { + return type(v); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/std_pair/detail/is_sequence_impl.hpp b/win32/include/boost/fusion/adapted/std_pair/detail/is_sequence_impl.hpp new file mode 100755 index 000000000..45d5bbf2a --- /dev/null +++ b/win32/include/boost/fusion/adapted/std_pair/detail/is_sequence_impl.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_IS_SEQUENCE_IMPL_27122005_1651) +#define BOOST_FUSION_IS_SEQUENCE_IMPL_27122005_1651 + +#include + +namespace boost { namespace fusion { + + struct std_pair_tag; + + namespace extension + { + template + struct is_sequence_impl; + + template<> + struct is_sequence_impl + { + template + struct apply : mpl::true_ {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/std_pair/detail/is_view_impl.hpp b/win32/include/boost/fusion/adapted/std_pair/detail/is_view_impl.hpp new file mode 100755 index 000000000..f171fb451 --- /dev/null +++ b/win32/include/boost/fusion/adapted/std_pair/detail/is_view_impl.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_IS_VIEW_IMPL_27042006_2219) +#define BOOST_FUSION_IS_VIEW_IMPL_27042006_2219 + +#include + +namespace boost { namespace fusion +{ + struct std_pair_tag; + + namespace extension + { + template + struct is_view_impl; + + template<> + struct is_view_impl + { + template + struct apply : mpl::false_ + {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/std_pair/detail/size_impl.hpp b/win32/include/boost/fusion/adapted/std_pair/detail/size_impl.hpp new file mode 100755 index 000000000..1b8d2f947 --- /dev/null +++ b/win32/include/boost/fusion/adapted/std_pair/detail/size_impl.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_SIZE_IMPL_24122005_1759) +#define BOOST_FUSION_SIZE_IMPL_24122005_1759 + +#include + +namespace boost { namespace fusion { + + struct std_pair_tag; + + namespace extension + { + template + struct size_impl; + + template <> + struct size_impl + { + template + struct apply : mpl::int_<2> {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/std_pair/detail/value_at_impl.hpp b/win32/include/boost/fusion/adapted/std_pair/detail/value_at_impl.hpp new file mode 100755 index 000000000..2a5a42ad7 --- /dev/null +++ b/win32/include/boost/fusion/adapted/std_pair/detail/value_at_impl.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_VALUE_AT_IMPL_24122005_1917) +#define BOOST_FUSION_VALUE_AT_IMPL_24122005_1917 + +#include +#include + +namespace boost { namespace fusion { + + struct std_pair_tag; + + namespace extension + { + template + struct value_at_impl; + + template <> + struct value_at_impl + { + template + struct apply + { + static int const n_value = N::value; + BOOST_STATIC_ASSERT((n_value >= 0 && n_value < 2)); + typedef typename + mpl::if_c< + (n_value == 0) + , typename Sequence::first_type + , typename Sequence::second_type + >::type + type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/std_pair/std_pair_iterator.hpp b/win32/include/boost/fusion/adapted/std_pair/std_pair_iterator.hpp new file mode 100755 index 000000000..64f6c1d6a --- /dev/null +++ b/win32/include/boost/fusion/adapted/std_pair/std_pair_iterator.hpp @@ -0,0 +1,127 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_STD_PAIR_ITERATOR_09262005_0934) +#define FUSION_STD_PAIR_ITERATOR_09262005_0934 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct random_access_traversal_tag; + + template + struct std_pair_iterator + : iterator_facade, random_access_traversal_tag> + { + BOOST_MPL_ASSERT_RELATION(N_, >=, 0); + BOOST_MPL_ASSERT_RELATION(N_, <=, 2); + + typedef mpl::int_ index; + typedef Pair_ pair_type; + + std_pair_iterator(Pair_& pair) + : pair(pair) {} + Pair_& pair; + + template + struct value_of; + + template + struct value_of > + : mpl::identity {}; + + template + struct value_of > + : mpl::identity {}; + + template + struct deref; + + template + struct deref > + { + typedef typename + mpl::if_< + is_const + , typename Pair::first_type const& + , typename Pair::first_type& + >::type + type; + + static type + call(std_pair_iterator const& iter) + { + return iter.pair.first; + } + }; + + template + struct deref > + { + typedef typename + mpl::if_< + is_const + , typename Pair::second_type const& + , typename Pair::second_type& + >::type + type; + + static type + call(std_pair_iterator const& iter) + { + return iter.pair.second; + } + }; + + template + struct advance + { + typedef typename Iterator::index index; + typedef typename Iterator::pair_type pair_type; + typedef std_pair_iterator type; + + static type + call(Iterator const& iter) + { + return type(iter.pair); + } + }; + + template + struct next : advance > {}; + + template + struct prior : advance > {}; + + template + struct distance : mpl::minus + { + typedef typename + mpl::minus< + typename I2::index, typename I1::index + >::type + type; + + static type + call(I1 const&, I2 const&) + { + return type(); + } + }; + }; +}} + +#endif + + diff --git a/win32/include/boost/fusion/adapted/std_pair/tag_of.hpp b/win32/include/boost/fusion/adapted/std_pair/tag_of.hpp new file mode 100755 index 000000000..c2c37404c --- /dev/null +++ b/win32/include/boost/fusion/adapted/std_pair/tag_of.hpp @@ -0,0 +1,29 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_TAG_OF_24122005_1722) +#define BOOST_FUSION_TAG_OF_24122005_1722 + +#include + +#include + +namespace boost { namespace fusion { + + struct std_pair_tag; + + namespace traits + { + template + struct tag_of > + { + typedef std_pair_tag type; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/struct.hpp b/win32/include/boost/fusion/adapted/struct.hpp new file mode 100755 index 000000000..b662c0842 --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct.hpp @@ -0,0 +1,28 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_STRUCT_24122005_1744) +#define BOOST_FUSION_STRUCT_24122005_1744 + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/adapted/struct/adapt_assoc_struct.hpp b/win32/include/boost/fusion/adapted/struct/adapt_assoc_struct.hpp new file mode 100755 index 000000000..3f44d0fcd --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/adapt_assoc_struct.hpp @@ -0,0 +1,94 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2007 Dan Marsden + + 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_FUSION_ADAPT_ASSOC_STRUCT_20070508_2207) +#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_20070508_2207 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace extension { + template + struct struct_assoc_member; +}}} + + +#define BOOST_FUSION_ADAPT_ASSOC_STRUCT(name, bseq) \ + BOOST_FUSION_ADAPT_ASSOC_STRUCT_I( \ + name, BOOST_PP_CAT(BOOST_FUSION_ADAPT_ASSOC_STRUCT_X bseq, 0)) \ + /***/ + +#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_X(x, y, z) ((x, y, z)) BOOST_FUSION_ADAPT_ASSOC_STRUCT_Y +#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_Y(x, y, z) ((x, y, z)) BOOST_FUSION_ADAPT_ASSOC_STRUCT_X +#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_X0 +#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_Y0 + +// BOOST_FUSION_ADAPT_ASSOC_STRUCT_I generates the overarching structure and uses +// SEQ_FOR_EACH_I to generate the "linear" substructures. +// Thanks to Paul Mensonides for the PP macro help + +#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_I(name, seq) \ + namespace boost { namespace fusion { namespace traits \ + { \ + template <> \ + struct tag_of \ + { \ + typedef struct_tag type; \ + }; \ + }}} \ + namespace boost { namespace fusion { namespace extension \ + { \ + template <> \ + struct struct_size : mpl::int_ {}; \ + BOOST_PP_SEQ_FOR_EACH_I(BOOST_FUSION_ADAPT_ASSOC_STRUCT_C, name, seq) \ + }}} \ + /***/ + +#define BOOST_FUSION_ADAPT_ASSOC_STRUCT_C(r, name, i, xy) \ + template <> \ + struct struct_member \ + { \ + typedef BOOST_PP_TUPLE_ELEM(3, 0, xy) type; \ + static type& call(name& struct_) \ + { \ + return struct_.BOOST_PP_TUPLE_ELEM(3, 1, xy); \ + }; \ + }; \ + template<> \ + struct struct_assoc_member \ + { \ + typedef BOOST_PP_TUPLE_ELEM(3, 0, xy) type; \ + static type& call(name& struct_) \ + { \ + return struct_.BOOST_PP_TUPLE_ELEM(3, 1, xy); \ + }; \ + }; + /***/ + +#endif diff --git a/win32/include/boost/fusion/adapted/struct/adapt_struct.hpp b/win32/include/boost/fusion/adapted/struct/adapt_struct.hpp new file mode 100755 index 000000000..d95e708ae --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/adapt_struct.hpp @@ -0,0 +1,75 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_ADAPT_STRUCT_APRIL_2_2007_1158AM) +#define BOOST_FUSION_ADAPT_STRUCT_APRIL_2_2007_1158AM + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BOOST_FUSION_ADAPT_STRUCT(name, bseq) \ + BOOST_FUSION_ADAPT_STRUCT_I( \ + name, BOOST_PP_CAT(BOOST_FUSION_ADAPT_STRUCT_X bseq, 0)) \ + /***/ + +#define BOOST_FUSION_ADAPT_STRUCT_X(x, y) ((x, y)) BOOST_FUSION_ADAPT_STRUCT_Y +#define BOOST_FUSION_ADAPT_STRUCT_Y(x, y) ((x, y)) BOOST_FUSION_ADAPT_STRUCT_X +#define BOOST_FUSION_ADAPT_STRUCT_X0 +#define BOOST_FUSION_ADAPT_STRUCT_Y0 + +// BOOST_FUSION_ADAPT_STRUCT_I generates the overarching structure and uses +// SEQ_FOR_EACH_I to generate the "linear" substructures. +// Thanks to Paul Mensonides for the PP macro help + +#define BOOST_FUSION_ADAPT_STRUCT_I(name, seq) \ + namespace boost { namespace fusion { namespace traits \ + { \ + template <> \ + struct tag_of \ + { \ + typedef struct_tag type; \ + }; \ + }}} \ + namespace boost { namespace fusion { namespace extension \ + { \ + template <> \ + struct struct_size : mpl::int_ {}; \ + BOOST_PP_SEQ_FOR_EACH_I(BOOST_FUSION_ADAPT_STRUCT_C, name, seq) \ + }}} \ + /***/ + +#define BOOST_FUSION_ADAPT_STRUCT_C(r, name, i, xy) \ + template <> \ + struct struct_member \ + { \ + typedef BOOST_PP_TUPLE_ELEM(2, 0, xy) type; \ + static type& call(name& struct_) \ + { \ + return struct_.BOOST_PP_TUPLE_ELEM(2, 1, xy); \ + }; \ + }; \ + /***/ + +#endif diff --git a/win32/include/boost/fusion/adapted/struct/detail/at_impl.hpp b/win32/include/boost/fusion/adapted/struct/detail/at_impl.hpp new file mode 100755 index 000000000..2705d9528 --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/detail/at_impl.hpp @@ -0,0 +1,63 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_AT_IMPL_24122005_1807) +#define BOOST_FUSION_AT_IMPL_24122005_1807 + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct struct_tag; + + namespace extension + { + template + struct at_impl; + + template + struct struct_member; + + template + struct struct_size; + + template <> + struct at_impl + { + template + struct apply + { + static int const n_value = N::value; + BOOST_MPL_ASSERT_RELATION( + n_value, <=, extension::struct_size::value); + + typedef typename + extension::struct_member + element; + + typedef typename + mpl::eval_if< + is_const + , detail::cref_result + , detail::ref_result + >::type + type; + + static type + call(Sequence& seq) + { + return extension:: + struct_member::call(seq); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/struct/detail/at_key_impl.hpp b/win32/include/boost/fusion/adapted/struct/detail/at_key_impl.hpp new file mode 100755 index 000000000..b75945eac --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/detail/at_key_impl.hpp @@ -0,0 +1,54 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2005-2007 Dan Marsden + + 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_FUSION_AT_KEY_IMPL_20070508_2248) +#define BOOST_FUSION_AT_KEY_IMPL_20070508_2248 + +#include + +namespace boost { namespace fusion +{ + struct struct_tag; + + namespace extension + { + template + struct at_key_impl; + + template + struct struct_assoc_member; + + template <> + struct at_key_impl + { + template + struct apply + { + typedef typename + extension::struct_assoc_member + element; + + typedef typename + mpl::eval_if< + is_const + , detail::cref_result + , detail::ref_result + >::type + type; + + static type + call(Sequence& seq) + { + return extension:: + struct_assoc_member::call(seq); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/struct/detail/begin_impl.hpp b/win32/include/boost/fusion/adapted/struct/detail/begin_impl.hpp new file mode 100755 index 000000000..5154c2aa5 --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/detail/begin_impl.hpp @@ -0,0 +1,40 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_BEGIN_IMPL_24122005_1752) +#define BOOST_FUSION_BEGIN_IMPL_24122005_1752 + +#include + +namespace boost { namespace fusion +{ + struct struct_tag; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef struct_iterator type; + + static type + call(Sequence& v) + { + return type(v); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/struct/detail/category_of_impl.hpp b/win32/include/boost/fusion/adapted/struct/detail/category_of_impl.hpp new file mode 100755 index 000000000..a302ce915 --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/detail/category_of_impl.hpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_CATEGORY_OF_IMPL_24122005_1731) +#define BOOST_FUSION_CATEGORY_OF_IMPL_24122005_1731 + +#include + +namespace boost { namespace fusion +{ + struct struct_tag; + struct random_access_traversal_tag; + + namespace extension + { + template + struct category_of_impl; + + template<> + struct category_of_impl + { + template + struct apply + { + typedef random_access_traversal_tag type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/struct/detail/end_impl.hpp b/win32/include/boost/fusion/adapted/struct/detail/end_impl.hpp new file mode 100755 index 000000000..b79788550 --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/detail/end_impl.hpp @@ -0,0 +1,48 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_END_IMPL_24122005_1755) +#define BOOST_FUSION_END_IMPL_24122005_1755 + +#include + +namespace boost { namespace fusion +{ + struct struct_tag; + + namespace extension + { + template + struct end_impl; + + template + struct struct_size; + + template <> + struct end_impl + { + template + struct apply + { + typedef + struct_iterator< + Sequence + , struct_size::value + > + type; + + static type + call(Sequence& v) + { + return type(v); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/struct/detail/has_key_impl.hpp b/win32/include/boost/fusion/adapted/struct/detail/has_key_impl.hpp new file mode 100755 index 000000000..50b8127db --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/detail/has_key_impl.hpp @@ -0,0 +1,40 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2005-2007 Dan Marsden + + 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_FUSION_HAS_KEY_IMPL_20070508_2231) +#define BOOST_FUSION_HAS_KEY_IMPL_20070508_2231 + +#include +#include + +namespace boost { namespace fusion { + + struct struct_tag; + + namespace extension + { + struct no_such_member; + + template + struct has_key_impl; + + template + struct struct_assoc_member; + + template<> + struct has_key_impl + { + template + struct apply + : mpl::not_::type> > + { + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/struct/detail/is_sequence_impl.hpp b/win32/include/boost/fusion/adapted/struct/detail/is_sequence_impl.hpp new file mode 100755 index 000000000..52a7d5bbe --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/detail/is_sequence_impl.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_IS_SEQUENCE_IMPL_27122005_1651) +#define BOOST_FUSION_IS_SEQUENCE_IMPL_27122005_1651 + +#include + +namespace boost { namespace fusion +{ + struct struct_tag; + + namespace extension + { + template + struct is_sequence_impl; + + template<> + struct is_sequence_impl + { + template + struct apply : mpl::true_ {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/struct/detail/is_view_impl.hpp b/win32/include/boost/fusion/adapted/struct/detail/is_view_impl.hpp new file mode 100755 index 000000000..1df129c70 --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/detail/is_view_impl.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_IS_VIEW_IMPL_27042006_2219) +#define BOOST_FUSION_IS_VIEW_IMPL_27042006_2219 + +#include + +namespace boost { namespace fusion +{ + struct struct_tag; + + namespace extension + { + template + struct is_view_impl; + + template<> + struct is_view_impl + { + template + struct apply : mpl::false_ + {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/struct/detail/size_impl.hpp b/win32/include/boost/fusion/adapted/struct/detail/size_impl.hpp new file mode 100755 index 000000000..0db70006d --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/detail/size_impl.hpp @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_SIZE_IMPL_24122005_1759) +#define BOOST_FUSION_SIZE_IMPL_24122005_1759 + +#include + +namespace boost { namespace fusion +{ + namespace extension + { + template + struct struct_size; + } + + struct struct_tag; + + namespace extension + { + template + struct size_impl; + + template <> + struct size_impl + { + template + struct apply : extension::struct_size {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/struct/detail/value_at_impl.hpp b/win32/include/boost/fusion/adapted/struct/detail/value_at_impl.hpp new file mode 100755 index 000000000..e7d7a9ce2 --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/detail/value_at_impl.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_VALUE_AT_IMPL_24122005_1917) +#define BOOST_FUSION_VALUE_AT_IMPL_24122005_1917 + +#include +#include + +namespace boost { namespace fusion +{ + struct struct_tag; + + namespace extension + { + template + struct value_at_impl; + + template + struct struct_member; + + template + struct struct_size; + + template <> + struct value_at_impl + { + template + struct apply + { + static int const n_value = N::value; + BOOST_MPL_ASSERT_RELATION( + n_value, <=, extension::struct_size::value); + + typedef typename + extension::struct_member::type + type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/struct/detail/value_at_key_impl.hpp b/win32/include/boost/fusion/adapted/struct/detail/value_at_key_impl.hpp new file mode 100755 index 000000000..69578a670 --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/detail/value_at_key_impl.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2005-2007 Dan Marsden + + 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_FUSION_VALUE_AT_KEY_IMPL_20070508_2300) +#define BOOST_FUSION_VALUE_AT_KEY_IMPL_20070508_2300 + +#include + +namespace boost { namespace fusion +{ + struct struct_tag; + + namespace extension + { + template + struct value_at_key_impl; + + template + struct struct_assoc_member; + + template <> + struct value_at_key_impl + { + template + struct apply + { + typedef typename + extension::struct_assoc_member::type + type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/adapted/struct/extension.hpp b/win32/include/boost/fusion/adapted/struct/extension.hpp new file mode 100755 index 000000000..7e7109a26 --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/extension.hpp @@ -0,0 +1,68 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_STRUCT_EXTENSION_APRIL_2_2007_1008AM) +#define FUSION_STRUCT_EXTENSION_APRIL_2_2007_1008AM + +#include + +namespace boost { namespace fusion { namespace extension +{ + template + struct struct_member; + + template + struct struct_size; + + template + struct struct_member + { + typedef typename + add_const::type>::type + type; + + static type& + call(Struct const& struct_) + { + return struct_member::call( + const_cast(struct_)); + } + }; + + template + struct struct_size + : struct_size + {}; + + struct no_such_member; + + template + struct struct_assoc_member + { + typedef no_such_member type; + }; + + template + struct struct_assoc_member + { + typedef typename + add_const::type>::type + type; + + static type& + call(Struct const& struct_) + { + return struct_assoc_member::call( + const_cast(struct_)); + } + }; + +}}} + +#endif + + diff --git a/win32/include/boost/fusion/adapted/struct/struct_iterator.hpp b/win32/include/boost/fusion/adapted/struct/struct_iterator.hpp new file mode 100755 index 000000000..fa4cd9698 --- /dev/null +++ b/win32/include/boost/fusion/adapted/struct/struct_iterator.hpp @@ -0,0 +1,103 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_STRUCT_ITERATOR_APRIL_2_2007_1008AM) +#define FUSION_STRUCT_ITERATOR_APRIL_2_2007_1008AM + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct random_access_traversal_tag; + + template + struct struct_iterator + : iterator_facade, random_access_traversal_tag> + { + BOOST_MPL_ASSERT_RELATION(N_, >=, 0); + BOOST_MPL_ASSERT_RELATION(N_, <=, extension::struct_size::value); + + typedef mpl::int_ index; + typedef Struct struct_type; + + struct_iterator(Struct& struct_) + : struct_(struct_) {} + Struct& struct_; + + template + struct value_of + : extension::struct_member + { + }; + + template + struct deref + { + typedef typename + add_reference< + typename extension::struct_member::type + >::type + type; + + static type + call(Iterator const& iter) + { + return extension::struct_member:: + call(iter.struct_); + } + }; + + template + struct advance + { + typedef typename Iterator::index index; + typedef typename Iterator::struct_type struct_type; + typedef struct_iterator type; + + static type + call(Iterator const& iter) + { + return type(iter.struct_); + } + }; + + template + struct next : advance > {}; + + template + struct prior : advance > {}; + + template + struct distance : mpl::minus + { + typedef typename + mpl::minus< + typename I2::index, typename I1::index + >::type + type; + + static type + call(I1 const&, I2 const&) + { + return type(); + } + }; + }; +}} + +#endif + + diff --git a/win32/include/boost/fusion/algorithm.hpp b/win32/include/boost/fusion/algorithm.hpp new file mode 100755 index 000000000..3beb66e3e --- /dev/null +++ b/win32/include/boost/fusion/algorithm.hpp @@ -0,0 +1,14 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ALGORITHM_10022005_0549) +#define FUSION_ALGORITHM_10022005_0549 + +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/algorithm/iteration.hpp b/win32/include/boost/fusion/algorithm/iteration.hpp new file mode 100755 index 000000000..db2400b1a --- /dev/null +++ b/win32/include/boost/fusion/algorithm/iteration.hpp @@ -0,0 +1,14 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ALGORITHM_ITERATION_10022005_0549) +#define FUSION_ALGORITHM_ITERATION_10022005_0549 + +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/algorithm/iteration/accumulate.hpp b/win32/include/boost/fusion/algorithm/iteration/accumulate.hpp new file mode 100755 index 000000000..2cc381073 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/iteration/accumulate.hpp @@ -0,0 +1,40 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ACCUMULATE_09172005_1032) +#define FUSION_ACCUMULATE_09172005_1032 + +#include + +namespace boost { namespace fusion +{ + struct void_; + + namespace result_of + { + template + struct accumulate + : result_of::fold + {}; + } + + template + inline typename result_of::accumulate::type + accumulate(Sequence& seq, State const& state, F f) + { + return fusion::fold(seq, state, f); + } + + template + inline typename result_of::accumulate::type + accumulate(Sequence const& seq, State const& state, F f) + { + return fusion::fold(seq, state, f); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/iteration/detail/fold.hpp b/win32/include/boost/fusion/algorithm/iteration/detail/fold.hpp new file mode 100755 index 000000000..0b8c2388e --- /dev/null +++ b/win32/include/boost/fusion/algorithm/iteration/detail/fold.hpp @@ -0,0 +1,278 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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_FUSION_FOLD_HPP_20070528_1253) +#define BOOST_FUSION_FOLD_HPP_20070528_1253 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { namespace fusion { +namespace result_of +{ + template + struct fold; +} +namespace detail +{ + template + struct apply_fold_result + { + template + struct apply + : boost::result_of + {}; + }; + + template + struct fold_apply + { + typedef typename result_of::deref::type dereferenced; + typedef typename add_reference::type>::type lvalue_state; + typedef typename boost::result_of::type type; + }; + + template + struct static_fold; + + template + struct next_result_of_fold + { + typedef typename + static_fold< + typename result_of::next::type + , Last + , typename fold_apply::type + , F + >::type + type; + }; + + template + struct static_fold + { + typedef typename + mpl::if_< + result_of::equal_to + , mpl::identity + , next_result_of_fold + >::type + result; + + typedef typename result::type type; + }; + + template + struct result_of_unrolled_fold; + + template + struct unrolled_fold + { + template + static typename result_of_unrolled_fold::type + call(I0 const& i0, State const& state, F f) + { + typedef typename result_of::next::type I1; + I1 i1 = fusion::next(i0); + typedef typename result_of::next::type I2; + I2 i2 = fusion::next(i1); + typedef typename result_of::next::type I3; + I3 i3 = fusion::next(i2); + typedef typename result_of::next::type I4; + I4 i4 = fusion::next(i3); + + return unrolled_fold::call(i4, f(*i3, f(*i2, f(*i1, f(*i0, state)))), f); + } + }; + + template<> + struct unrolled_fold<3> + { + template + static typename result_of_unrolled_fold::type + call(I0 const& i0, State const& state, F f) + { + typedef typename result_of::next::type I1; + I1 i1 = fusion::next(i0); + typedef typename result_of::next::type I2; + I2 i2 = fusion::next(i1); + return f(*i2, f(*i1, f(*i0, state))); + } + }; + + template<> + struct unrolled_fold<2> + { + template + static typename result_of_unrolled_fold::type + call(I0 const& i0, State const& state, F f) + { + typedef typename result_of::next::type I1; + I1 i1 = fusion::next(i0); + return f(*i1, f(*i0, state)); + } + }; + + template<> + struct unrolled_fold<1> + { + template + static typename result_of_unrolled_fold::type + call(I0 const& i0, State const& state, F f) + { + return f(*i0, state); + } + }; + + template<> + struct unrolled_fold<0> + { + template + static State call(I0 const&, State const& state, F) + { + return state; + } + }; + + // terminal case + template + inline State const& + linear_fold(First const&, Last const&, State const& state, F, mpl::true_) + { + return state; + } + + // non-terminal case + template + inline typename static_fold::type + linear_fold( + First const& first + , Last const& last + , State const& state + , F f + , mpl::false_) + { + return detail::linear_fold( + fusion::next(first) + , last + , f(*first, state) + , f + , result_of::equal_to::type, Last>() + ); + } + + template + struct result_of_unrolled_fold + { + typedef typename result_of::next::type I1; + typedef typename result_of::next::type I2; + typedef typename result_of::next::type I3; + typedef typename result_of::next::type I4; + typedef typename fold_apply::type Rest1; + typedef typename fold_apply::type Rest2; + typedef typename fold_apply::type Rest3; + typedef typename fold_apply::type Rest4; + + typedef typename result_of_unrolled_fold::type type; + }; + + template + struct result_of_unrolled_fold + { + typedef typename result_of::next::type I1; + typedef typename result_of::next::type I2; + typedef typename fold_apply::type Rest; + typedef typename fold_apply::type Rest2; + typedef typename fold_apply::type type; + }; + + template + struct result_of_unrolled_fold + { + typedef typename result_of::next::type I1; + typedef typename fold_apply::type Rest; + typedef typename fold_apply::type type; + }; + + template + struct result_of_unrolled_fold + { + typedef typename fold_apply::type type; + }; + + template + struct result_of_unrolled_fold + { + typedef State type; + }; + + template + struct choose_fold; + + template + struct choose_fold + { + typedef typename result_of::begin::type begin; + typedef typename result_of::end::type end; + typedef typename result_of_unrolled_fold< + begin, State, F, result_of::distance::type::value>::type type; + }; + + template + struct choose_fold + { + typedef typename + detail::static_fold< + typename result_of::begin::type + , typename result_of::end::type + , State + , F + >::type + type; + }; + + template + typename result_of::fold::type + fold(Sequence& seq, State const& state, F f, Tag) + { + return linear_fold( + fusion::begin(seq) + , fusion::end(seq) + , state + , f + , result_of::equal_to< + typename result_of::begin::type + , typename result_of::end::type>() + ); + } + + template + typename result_of::fold::type + fold(Sequence& seq, State const& state, F f, random_access_traversal_tag) + { + typedef typename result_of::begin::type begin; + typedef typename result_of::end::type end; + return unrolled_fold::type::value>::call( + fusion::begin(seq) + , state + , f); + } +}}} + +#endif diff --git a/win32/include/boost/fusion/algorithm/iteration/detail/for_each.hpp b/win32/include/boost/fusion/algorithm/iteration/detail/for_each.hpp new file mode 100755 index 000000000..c48c93798 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/iteration/detail/for_each.hpp @@ -0,0 +1,130 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_FOR_EACH_05052005_1028) +#define FUSION_FOR_EACH_05052005_1028 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { +namespace detail +{ + template + inline void + for_each_linear(First const&, Last const&, F const&, mpl::true_) + { + } + + template + inline void + for_each_linear(First const& first, Last const& last, F const& f, mpl::false_) + { + f(*first); + detail::for_each_linear(fusion::next(first), last, f, + result_of::equal_to::type, Last>()); + } + + + template + inline void + for_each(Sequence& seq, F const& f, Tag) + { + detail::for_each_linear( + fusion::begin(seq) + , fusion::end(seq) + , f + , result_of::equal_to< + typename result_of::begin::type + , typename result_of::end::type>()); + } + + template + struct for_each_unrolled + { + template + static void call(I0 const& i0, F const& f) + { + f(*i0); + typedef typename result_of::next::type I1; + I1 i1(fusion::next(i0)); + f(*i1); + typedef typename result_of::next::type I2; + I2 i2(fusion::next(i1)); + f(*i2); + typedef typename result_of::next::type I3; + I3 i3(fusion::next(i2)); + f(*i3); + for_each_unrolled::call(fusion::next(i3), f); + } + }; + + template<> + struct for_each_unrolled<3> + { + template + static void call(I0 const& i0, F const& f) + { + f(*i0); + typedef typename result_of::next::type I1; + I1 i1(fusion::next(i0)); + f(*i1); + typedef typename result_of::next::type I2; + I2 i2(fusion::next(i1)); + f(*i2); + } + }; + + template<> + struct for_each_unrolled<2> + { + template + static void call(I0 const& i0, F const& f) + { + f(*i0); + typedef typename result_of::next::type I1; + I1 i1(fusion::next(i0)); + f(*i1); + } + }; + + template<> + struct for_each_unrolled<1> + { + template + static void call(I0 const& i0, F const& f) + { + f(*i0); + } + }; + + template<> + struct for_each_unrolled<0> + { + template + static void call(It const&, F const&) + { + } + }; + + template + inline void + for_each(Sequence& seq, F const& f, random_access_traversal_tag) + { + typedef typename result_of::begin::type begin; + typedef typename result_of::end::type end; + for_each_unrolled::type::value>::call(fusion::begin(seq), f); + } +}}} + + +#endif + diff --git a/win32/include/boost/fusion/algorithm/iteration/ext_/for_each_s.hpp b/win32/include/boost/fusion/algorithm/iteration/ext_/for_each_s.hpp new file mode 100755 index 000000000..e1174c8bf --- /dev/null +++ b/win32/include/boost/fusion/algorithm/iteration/ext_/for_each_s.hpp @@ -0,0 +1,91 @@ +/*============================================================================= + Copyright (c) 2006 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_FOR_EACH_S_05022006_1027) +#define FUSION_FOR_EACH_S_05022006_1027 + +#include +#include +#include +#include +#include + +// fwd declarations +namespace boost { namespace fusion +{ + template + void + for_each_s(Sequence& seq, F const& f); + + template + void + for_each_s(Sequence const& seq, F const& f); +}} + +namespace boost { namespace fusion { namespace detail +{ + template + struct for_each_s_bind + { + explicit for_each_s_bind(F const &f) + : f_(f) + {} + + template + void operator ()(Sequence &seq) const + { + fusion::for_each_s(seq, this->f_); + } + + template + void operator ()(Sequence const &seq) const + { + fusion::for_each_s(seq, this->f_); + } + private: + F const &f_; + }; + + template + void for_each_s(Sequence &seq, F const &f, mpl::true_) + { + fusion::for_each_s(fusion::segments(seq), for_each_s_bind(f)); + } + + template + void for_each_s(Sequence &seq, F const &f, mpl::false_) + { + fusion::for_each(seq, f); + } +}}} + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct for_each_s + { + typedef void type; + }; + } + + template + inline void + for_each_s(Sequence& seq, F const& f) + { + detail::for_each_s(seq, f, traits::is_segmented()); + } + + template + inline void + for_each_s(Sequence const& seq, F const& f) + { + detail::for_each_s(seq, f, traits::is_segmented()); + } +}} + +#endif diff --git a/win32/include/boost/fusion/algorithm/iteration/fold.hpp b/win32/include/boost/fusion/algorithm/iteration/fold.hpp new file mode 100755 index 000000000..497e89f30 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/iteration/fold.hpp @@ -0,0 +1,48 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2007 Dan Marsden + + 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_FUSION_FOLD_05052005_1214) +#define BOOST_FUSION_FOLD_05052005_1214 + +#include +#include +#include + +#include +#include + +namespace boost { namespace fusion { + + struct random_access_traversal_tag; + + namespace result_of + { + template + struct fold + : fusion::detail::choose_fold< + Sequence, State, F + , is_base_of::type>::value> + {}; + } + + template + inline typename result_of::fold::type + fold(Sequence& seq, State const& state, F f) + { + return detail::fold(seq, state, f, typename traits::category_of::type()); + } + + template + inline typename result_of::fold::type + fold(Sequence const& seq, State const& state, F f) + { + return detail::fold(seq, state, f, typename traits::category_of::type()); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/iteration/for_each.hpp b/win32/include/boost/fusion/algorithm/iteration/for_each.hpp new file mode 100755 index 000000000..e7b516564 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/iteration/for_each.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + Copyright (c) 2007 Dan Marsden + + 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_FUSION_FOR_EACH_20070527_0943) +#define BOOST_FUSION_FOR_EACH_20070527_0943 + +#include + +#include + +namespace boost { namespace fusion { + + namespace result_of + { + template + struct for_each + { + typedef void type; + }; + } + + struct random_access_traversal_tag; + + template + inline void + for_each(Sequence& seq, F const& f) + { + detail::for_each(seq, f, typename traits::category_of::type()); + } + + template + inline void + for_each(Sequence const& seq, F const& f) + { + detail::for_each(seq, f, typename traits::category_of::type()); + } +}} + +#endif diff --git a/win32/include/boost/fusion/algorithm/query.hpp b/win32/include/boost/fusion/algorithm/query.hpp new file mode 100755 index 000000000..2536c08e3 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query.hpp @@ -0,0 +1,18 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ALGORITHM_QUERY_10022005_0549) +#define FUSION_ALGORITHM_QUERY_10022005_0549 + +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/algorithm/query/all.hpp b/win32/include/boost/fusion/algorithm/query/all.hpp new file mode 100755 index 000000000..82739e9c9 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query/all.hpp @@ -0,0 +1,34 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2007 Dan Marsden + + 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_FUSION_ALL_05052005_1238) +#define BOOST_FUSION_ALL_05052005_1238 + +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct all + { + typedef bool type; + }; + } + + template + inline bool + all(Sequence const& seq, F f) + { + return detail::all(seq, f, typename traits::category_of::type()); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/query/any.hpp b/win32/include/boost/fusion/algorithm/query/any.hpp new file mode 100755 index 000000000..f72a6d062 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query/any.hpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005 Eric Niebler + Copyright (c) 2007 Dan Marsden + + 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(FUSION_ANY_05052005_1230) +#define FUSION_ANY_05052005_1230 + +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct any + { + typedef bool type; + }; + } + + template + inline bool + any(Sequence const& seq, F f) + { + return detail::any(seq, f, typename traits::category_of::type()); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/query/count.hpp b/win32/include/boost/fusion/algorithm/query/count.hpp new file mode 100755 index 000000000..d61a4958a --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query/count.hpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2007 + + 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_FUSION_COUNT_09162005_0150) +#define BOOST_FUSION_COUNT_09162005_0150 + +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct count + { + typedef int type; + }; + } + + template + inline int + count(Sequence const& seq, T const& x) + { + detail::count_compare f(x); + return fusion::count_if(seq, f); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/query/count_if.hpp b/win32/include/boost/fusion/algorithm/query/count_if.hpp new file mode 100755 index 000000000..9889e976c --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query/count_if.hpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2007 Dan Marsden + + 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_FUSION_COUNT_IF_09162005_0137) +#define BOOST_FUSION_COUNT_IF_09162005_0137 + +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct count_if + { + typedef int type; + }; + } + + template + inline int + count_if(Sequence const& seq, F f) + { + return detail::count_if( + seq, f, typename traits::category_of::type()); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/query/detail/all.hpp b/win32/include/boost/fusion/algorithm/query/detail/all.hpp new file mode 100755 index 000000000..9d4cef861 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query/detail/all.hpp @@ -0,0 +1,127 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2007 Dan Marsden + + 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(FUSION_ALL_05052005_1237) +#define FUSION_ALL_05052005_1237 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + inline bool + linear_all(First const&, Last const&, F const&, mpl::true_) + { + return true; + } + + template + inline bool + linear_all(First const& first, Last const& last, F& f, mpl::false_) + { + typename result_of::deref::type x = *first; + return f(x) && + detail::linear_all( + fusion::next(first) + , last + , f + , result_of::equal_to::type, Last>()); + } + + template + inline bool + all(Sequence const& seq, F f, Tag) + { + return detail::linear_all( + fusion::begin(seq) + , fusion::end(seq) + , f + , result_of::equal_to< + typename result_of::begin::type + , typename result_of::end::type>()); + } + + template + struct unrolled_all + { + template + static bool call(It const& it, F f) + { + return + f(*it) && + f(*fusion::advance_c<1>(it))&& + f(*fusion::advance_c<2>(it)) && + f(*fusion::advance_c<3>(it)) && + detail::unrolled_all::call(fusion::advance_c<4>(it), f); + } + }; + + template<> + struct unrolled_all<3> + { + template + static bool call(It const& it, F f) + { + return + f(*it) && + f(*fusion::advance_c<1>(it)) && + f(*fusion::advance_c<2>(it)); + } + }; + + template<> + struct unrolled_all<2> + { + template + static bool call(It const& it, F f) + { + return + f(*it) && + f(*fusion::advance_c<1>(it)); + } + }; + + template<> + struct unrolled_all<1> + { + template + static bool call(It const& it, F f) + { + return f(*it); + } + }; + + template<> + struct unrolled_all<0> + { + template + static bool call(It const& it, F f) + { + return false; + } + }; + + template + inline bool + all(Sequence const& seq, F f, random_access_traversal_tag) + { + typedef typename result_of::begin::type begin; + typedef typename result_of::end::type end; + return detail::unrolled_all::type::value>::call( + fusion::begin(seq), f); + } +}}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/query/detail/any.hpp b/win32/include/boost/fusion/algorithm/query/detail/any.hpp new file mode 100755 index 000000000..aedac55d1 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query/detail/any.hpp @@ -0,0 +1,130 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005 Eric Niebler + Copyright (c) 2007 Dan Marsden + + 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(FUSION_ANY_05052005_1229) +#define FUSION_ANY_05052005_1229 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { + struct random_access_traversal_tag; +namespace detail +{ + template + inline bool + linear_any(First const&, Last const&, F const&, mpl::true_) + { + return false; + } + + template + inline bool + linear_any(First const& first, Last const& last, F& f, mpl::false_) + { + typename result_of::deref::type x = *first; + return f(x) || + detail::linear_any( + fusion::next(first) + , last + , f + , result_of::equal_to::type, Last>()); + } + + template + inline bool + any(Sequence const& seq, F f, Tag) + { + return detail::linear_any( + fusion::begin(seq) + , fusion::end(seq) + , f + , result_of::equal_to< + typename result_of::begin::type + , typename result_of::end::type>()); + } + + template + struct unrolled_any + { + template + static bool call(It const& it, F f) + { + return + f(*it) || + f(*fusion::advance_c<1>(it))|| + f(*fusion::advance_c<2>(it)) || + f(*fusion::advance_c<3>(it)) || + detail::unrolled_any::call(fusion::advance_c<4>(it), f); + } + }; + + template<> + struct unrolled_any<3> + { + template + static bool call(It const& it, F f) + { + return + f(*it) || + f(*fusion::advance_c<1>(it)) || + f(*fusion::advance_c<2>(it)); + } + }; + + template<> + struct unrolled_any<2> + { + template + static bool call(It const& it, F f) + { + return + f(*it) || + f(*fusion::advance_c<1>(it)); + } + }; + + template<> + struct unrolled_any<1> + { + template + static bool call(It const& it, F f) + { + return f(*it); + } + }; + + template<> + struct unrolled_any<0> + { + template + static bool call(It const& it, F f) + { + return false; + } + }; + + template + inline bool + any(Sequence const& seq, F f, random_access_traversal_tag) + { + typedef typename result_of::begin::type begin; + typedef typename result_of::end::type end; + return detail::unrolled_any::type::value>::call( + fusion::begin(seq), f); + } +}}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/query/detail/assoc_find.hpp b/win32/include/boost/fusion/algorithm/query/detail/assoc_find.hpp new file mode 100755 index 000000000..eebb9a07c --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query/detail/assoc_find.hpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ASSOC_FIND_09242005_1133) +#define FUSION_ASSOC_FIND_09242005_1133 + +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct assoc_find + { + typedef typename + mpl::if_< + is_const + , typename Sequence::template meta_find_impl_const::type + , typename Sequence::template meta_find_impl::type + >::type + type; + + static type + call(Sequence& s) + { + return s.find_impl(mpl::identity()); + } + }; +}}} + +#endif diff --git a/win32/include/boost/fusion/algorithm/query/detail/count.hpp b/win32/include/boost/fusion/algorithm/query/detail/count.hpp new file mode 100755 index 000000000..0140a024c --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query/detail/count.hpp @@ -0,0 +1,68 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_COUNT_09162005_0158) +#define FUSION_COUNT_09162005_0158 + +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct compare_convertible; + + // T1 is convertible to T2 or vice versa + template <> + struct compare_convertible + { + template + static bool + call(T1 const& x, T2 const& y) + { + return x == y; + } + }; + + // T1 is NOT convertible to T2 NOR vice versa + template <> + struct compare_convertible + { + template + static bool + call(T1 const&, T2 const&) + { + return false; + } + }; + + template + struct count_compare + { + typedef typename detail::call_param::type param; + count_compare(param x) + : x(x) {} + + template + bool + operator()(T2 const& y) + { + return + compare_convertible< + mpl::or_< + is_convertible + , is_convertible + >::value + >::call(x, y); + } + + param x; + }; +}}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/query/detail/count_if.hpp b/win32/include/boost/fusion/algorithm/query/detail/count_if.hpp new file mode 100755 index 000000000..91b56fc6a --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query/detail/count_if.hpp @@ -0,0 +1,170 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2007 Dan Marsden + + 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_FUSION_COUNT_IF_09162005_0141) +#define BOOST_FUSION_COUNT_IF_09162005_0141 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { + struct random_access_traversal_tag; +namespace detail +{ + template + inline int + linear_count_if(First const&, Last const&, F const&, mpl::true_) + { + return 0; + } + + template + inline int + linear_count_if(First const& first, Last const& last, F& f, mpl::false_) + { + int n = + detail::linear_count_if( + fusion::next(first) + , last + , f + , result_of::equal_to::type, Last>()); + if (f(*first)) + ++n; + return n; + } + + template + inline int + count_if(Sequence const& seq, F f, Tag) + { + return detail::linear_count_if( + fusion::begin(seq) + , fusion::end(seq) + , f + , result_of::equal_to< + typename result_of::begin::type + , typename result_of::end::type>()); + } + + template + struct unrolled_count_if + { + template + static int call(I0 const& i0, F f) + { + int ct = unrolled_count_if:: + call(fusion::advance_c<4>(i0), f); + if(f(*i0)) + ++ct; + + typedef typename result_of::next::type I1; + I1 i1(fusion::next(i0)); + if(f(*i1)) + ++ct; + + typedef typename result_of::next::type I2; + I2 i2(fusion::next(i1)); + if(f(*i2)) + ++ct; + + typedef typename result_of::next::type I3; + I3 i3(fusion::next(i2)); + if(f(*i3)) + ++ct; + + return ct; + } + }; + + template<> + struct unrolled_count_if<3> + { + template + static int call(I0 const& i0, F f) + { + int ct = 0; + if(f(*i0)) + ++ct; + + typedef typename result_of::next::type I1; + I1 i1(fusion::next(i0)); + if(f(*i1)) + ++ct; + + typedef typename result_of::next::type I2; + I2 i2(fusion::next(i1)); + if(f(*i2)) + ++ct; + + return ct; + } + }; + + template<> + struct unrolled_count_if<2> + { + template + static int call(I0 const& i0, F f) + { + int ct = 0; + + if(f(*i0)) + ++ct; + + typedef typename result_of::next::type I1; + I1 i1(fusion::next(i0)); + if(f(*i1)) + ++ct; + + return ct; + } + }; + + template<> + struct unrolled_count_if<1> + { + template + static int call(I0 const& i0, F f) + { + int ct = 0; + if(f(*i0)) + ++ct; + return ct; + } + }; + + + template<> + struct unrolled_count_if<0> + { + template + static int call(I0 const&, F) + { + return 0; + } + }; + + template + inline int + count_if(Sequence const& seq, F f, random_access_traversal_tag) + { + typedef typename result_of::begin::type begin; + typedef typename result_of::end::type end; + return detail::unrolled_count_if::type::value>:: + call(fusion::begin(seq), f); + } +}}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/query/detail/find_if.hpp b/win32/include/boost/fusion/algorithm/query/detail/find_if.hpp new file mode 100755 index 000000000..b25dec3fb --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query/detail/find_if.hpp @@ -0,0 +1,252 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2007 Dan Marsden + + 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(FUSION_FIND_IF_05052005_1107) +#define FUSION_FIND_IF_05052005_1107 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { + struct random_access_traversal_tag; +namespace detail +{ + template + struct apply_filter + { + typedef typename mpl::apply1< + Pred, typename result_of::value_of::type>::type type; + BOOST_STATIC_CONSTANT(int, value = type::value); + }; + + template + struct main_find_if; + + template + struct recursive_find_if + { + typedef typename + main_find_if< + typename result_of::next::type, Last, Pred + >::type + type; + }; + + template + struct main_find_if + { + typedef mpl::or_< + result_of::equal_to + , apply_filter > + filter; + + typedef typename + mpl::eval_if< + filter + , mpl::identity + , recursive_find_if + >::type + type; + }; + + template< + typename First, typename Last, + typename Pred, bool> + struct choose_find_if; + + template + struct choose_find_if + : main_find_if + {}; + + template + struct unroll_again; + + template + struct apply_offset_filter + { + typedef typename result_of::advance_c::type Shifted; + typedef typename + mpl::apply1< + Pred + , typename result_of::value_of::type + >::type + type; + BOOST_STATIC_CONSTANT(int, value = type::value); + }; + + template + struct unrolled_find_if + { + typedef typename mpl::eval_if< + apply_filter, + mpl::identity, + mpl::eval_if< + apply_offset_filter, + result_of::advance_c, + mpl::eval_if< + apply_offset_filter, + result_of::advance_c, + mpl::eval_if< + apply_offset_filter, + result_of::advance_c, + unroll_again< + Iter, + Pred, + n, + 4> > > > >::type type; + }; + + template + struct unrolled_find_if + { + typedef typename mpl::eval_if< + apply_filter, + mpl::identity, + mpl::eval_if< + apply_offset_filter, + result_of::advance_c, + mpl::eval_if< + apply_offset_filter, + result_of::advance_c, + result_of::advance_c > > >::type type; + }; + + template + struct unrolled_find_if + { + typedef typename mpl::eval_if< + apply_filter, + mpl::identity, + mpl::eval_if< + apply_offset_filter, + result_of::advance_c, + result_of::advance_c > >::type type; + }; + + template + struct unrolled_find_if + { + typedef typename mpl::eval_if< + apply_filter, + mpl::identity, + result_of::advance_c >::type type; + }; + + template + struct unroll_again + { + typedef typename unrolled_find_if< + typename result_of::advance_c::type, + Pred, + n-unrolling>::type type; + }; + + template + struct unrolled_find_if + { + typedef Iter type; + }; + + template + struct choose_find_if + { + typedef typename result_of::distance::type N; + typedef typename unrolled_find_if::type type; + }; + + template + struct static_find_if + { + typedef typename + choose_find_if< + First + , Last + , typename mpl::lambda::type + , is_base_of::type>::value + >::type + type; + + template + static type + recursive_call(Iterator const& iter, mpl::true_) + { + return iter; + } + + template + static type + recursive_call(Iterator const& iter, mpl::false_) + { + return recursive_call(fusion::next(iter)); + } + + template + static type + recursive_call(Iterator const& iter) + { + typedef result_of::equal_to found; + return recursive_call(iter, found()); + } + + template + static type + choose_call(Iterator const& iter, Tag) + { + return recursive_call(iter); + } + + template + static type + choose_call(Iterator const& iter, random_access_traversal_tag) + { + typedef typename result_of::distance::type N; + return fusion::advance(iter); + } + + template + static type + call(Iterator const& iter) + { + return choose_call(iter, typename traits::category_of::type()); + } + }; + + template + struct static_seq_find_if : static_find_if + { + typedef typename static_find_if::type type; + + template + static type + call(Sequence const& seq) + { + return static_find_if::call(fusion::begin(seq)); + } + + template + static type + call(Sequence& seq) + { + return static_find_if::call(fusion::begin(seq)); + } + }; +}}} + +#endif diff --git a/win32/include/boost/fusion/algorithm/query/ext_/find_if_s.hpp b/win32/include/boost/fusion/algorithm/query/ext_/find_if_s.hpp new file mode 100755 index 000000000..e84db95f6 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query/ext_/find_if_s.hpp @@ -0,0 +1,222 @@ +/*============================================================================= + Copyright (c) 2006 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FIND_IF_S_05152006_1027) +#define FIND_IF_S_05152006_1027 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// fwd declarations +namespace boost { namespace fusion +{ + namespace detail + { + template::value> + struct static_find_if_s_recurse; + } + + namespace result_of + { + template + struct find_if_s; + } +}} + +namespace boost { namespace fusion { namespace detail +{ + + template::value> + struct is_found + : mpl::not_::type> > + {}; + + template + struct is_found + : mpl::not_ > + {}; + + template< + typename SegmentedRange + , typename Where + , typename Sequence = typename remove_reference< + typename result_of::deref< + typename SegmentedRange::iterator_type + >::type + >::type + , bool IsSegmented = traits::is_segmented::value + > + struct as_segmented_cons + { + typedef cons< + SegmentedRange + , cons > + > type; + + static type call(SegmentedRange const &range, Where const &where) + { + return fusion::make_cons( + range + , fusion::make_cons( + segmented_range(*fusion::begin(range), where) + ) + ); + } + }; + + template< + typename SegmentedRange + , typename Where + , typename Sequence + > + struct as_segmented_cons + { + typedef cons type; + + static type call(SegmentedRange const &range, Where const &where) + { + return fusion::make_cons(range, where); + } + }; + + template< + typename SegmentedRange + , typename Pred + , bool IsEmpty = is_empty::value + > + struct static_find_if_s_seg + { + typedef typename SegmentedRange::iterator_type first; + typedef typename result_of::deref::type segment_ref; + typedef typename remove_reference::type segment; + typedef static_find_if_s_recurse where; + typedef range_next next; + typedef is_found is_found; + typedef as_segmented_cons found; + typedef static_find_if_s_seg not_found; + typedef typename mpl::eval_if::type type; + + static type call(SegmentedRange const &range) + { + return call_(range, is_found()); + } + + private: + static type call_(SegmentedRange const &range, mpl::true_) + { + return found::call(range, where::call(*range.where_)); + } + + static type call_(SegmentedRange const &range, mpl::false_) + { + return not_found::call(next::call(range)); + } + }; + + template< + typename SegmentedRange + , typename Pred + > + struct static_find_if_s_seg + { + typedef nil type; + + static type call(SegmentedRange const &) + { + return nil(); + } + }; + + template + struct static_find_if_s_recurse + { + typedef typename as_segmented_range::type range; + typedef static_find_if_s_seg find_if; + typedef typename find_if::type type; + + static type call(Sequence &seq) + { + return find_if::call(range(fusion::segments(seq))); + } + }; + + template + struct static_find_if_s_recurse + { + typedef typename result_of::find_if::type type; + + static type call(Sequence &seq) + { + return fusion::find_if(seq); + } + }; + + template::value> + struct static_find_if_s + : static_find_if_s_recurse + {}; + + template + struct static_find_if_s + { + typedef typename as_segmented_range::type range; + typedef static_find_if_s_recurse find_if; + typedef typename find_if::type found; + + typedef segmented_iterator::type> type; + + static type call(Sequence &seq) + { + return type(reverse_cons::call(find_if::call(seq))); + } + }; +}}} + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct find_if_s + { + typedef typename + detail::static_find_if_s< + Sequence + , Pred + >::type + type; + }; + } + + template + typename lazy_disable_if< + is_const + , result_of::find_if_s + >::type + find_if_s(Sequence& seq) + { + return detail::static_find_if_s::call(seq); + } + + template + typename result_of::find_if_s::type + find_if_s(Sequence const& seq) + { + return detail::static_find_if_s::call(seq); + } +}} + +#endif diff --git a/win32/include/boost/fusion/algorithm/query/find.hpp b/win32/include/boost/fusion/algorithm/query/find.hpp new file mode 100755 index 000000000..74be3103d --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query/find.hpp @@ -0,0 +1,75 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_FIND_05052005_1107) +#define FUSION_FIND_05052005_1107 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct associative_sequence_tag; + + namespace result_of + { + template < + typename Sequence + , typename T + , bool is_associative_sequence = traits::is_associative::value > + struct find; + + template + struct find + { + typedef + detail::static_seq_find_if< + typename result_of::begin::type + , typename result_of::end::type + , is_same + > + filter; + + typedef typename filter::type type; + }; + + template + struct find + { + typedef detail::assoc_find filter; + typedef typename filter::type type; + }; + } + + template + inline typename + lazy_disable_if< + is_const + , result_of::find + >::type const + find(Sequence& seq) + { + typedef typename result_of::find::filter filter; + return filter::call(seq); + } + + template + inline typename result_of::find::type const + find(Sequence const& seq) + { + typedef typename result_of::find::filter filter; + return filter::call(seq); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/query/find_if.hpp b/win32/include/boost/fusion/algorithm/query/find_if.hpp new file mode 100755 index 000000000..90d0b7f80 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query/find_if.hpp @@ -0,0 +1,69 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_FIND_IF_05052005_1108) +#define FUSION_FIND_IF_05052005_1108 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct find_if + { + typedef typename + detail::static_find_if< + typename result_of::begin::type + , typename result_of::end::type + , Pred + >::type + type; + }; + } + + template + inline typename + lazy_disable_if< + is_const + , result_of::find_if + >::type + find_if(Sequence& seq) + { + typedef + detail::static_find_if< + typename result_of::begin::type + , typename result_of::end::type + , Pred + > + filter; + + return filter::call(fusion::begin(seq)); + } + + template + inline typename result_of::find_if::type const + find_if(Sequence const& seq) + { + typedef + detail::static_find_if< + typename result_of::begin::type + , typename result_of::end::type + , Pred + > + filter; + + return filter::call(fusion::begin(seq)); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/query/none.hpp b/win32/include/boost/fusion/algorithm/query/none.hpp new file mode 100755 index 000000000..fcf663ac5 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/query/none.hpp @@ -0,0 +1,33 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2007 Dan Marsden + + 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_FUSION_NONE_07062005_1128) +#define BOOST_FUSION_NONE_07062005_1128 + +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct none + { + typedef bool type; + }; + } + + template + inline bool + none(Sequence const& seq, F f) + { + return !fusion::any(seq, f); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation.hpp b/win32/include/boost/fusion/algorithm/transformation.hpp new file mode 100755 index 000000000..f0b2c610b --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation.hpp @@ -0,0 +1,28 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ALGORITHM_TRANSFORMATION_10022005_0551) +#define FUSION_ALGORITHM_TRANSFORMATION_10022005_0551 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/algorithm/transformation/clear.hpp b/win32/include/boost/fusion/algorithm/transformation/clear.hpp new file mode 100755 index 000000000..4fae37c14 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/clear.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_CLEAR_09172005_1127) +#define FUSION_CLEAR_09172005_1127 + +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct clear + { + typedef vector0 type; + }; + } + + template + inline typename result_of::clear::type + clear(Sequence const& seq) + { + return vector0(); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/detail/replace.hpp b/win32/include/boost/fusion/algorithm/transformation/detail/replace.hpp new file mode 100755 index 000000000..ab73075a8 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/detail/replace.hpp @@ -0,0 +1,73 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_REPLACE_08182005_0841) +#define FUSION_REPLACE_08182005_0841 + +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct replacer_helper; + + template <> + struct replacer_helper + { + template + static U& + call(U& x, T const&, T const&) + { + return x; + } + }; + + template <> + struct replacer_helper + { + template + static U + call(U& x, T const& old_value, T const& new_value) + { + return (x == old_value) ? new_value : x; + } + }; + + template + struct replacer + { + replacer(T const& old_value, T const& new_value) + : old_value(old_value), new_value(new_value) {} + + template + struct result; + + template + struct result(U2)> + { + typedef typename remove_reference::type value; + typedef typename + mpl::if_, value, value const&>::type + type; + }; + + template + typename result::type + operator()(U const& x) const + { + return replacer_helper::value>:: + call(x, old_value, new_value); + } + + T old_value; + T new_value; + }; +}}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/detail/replace_if.hpp b/win32/include/boost/fusion/algorithm/transformation/detail/replace_if.hpp new file mode 100755 index 000000000..d4f6f7d33 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/detail/replace_if.hpp @@ -0,0 +1,73 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_REPLACE_IF_08182005_0946) +#define FUSION_REPLACE_IF_08182005_0946 + +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct replacer_if_helper; + + template <> + struct replacer_if_helper + { + template + static U& + call(U& x, F&, T const&) + { + return x; + } + }; + + template <> + struct replacer_if_helper + { + template + static U + call(U& x, F& f, T const& new_value) + { + return f(x) ? new_value : x; + } + }; + + template + struct replacer_if + { + replacer_if(F f, T const& new_value) + : f(f), new_value(new_value) {} + + template + struct result; + + template + struct result(U)> + { + typedef typename remove_reference::type value; + typedef typename + mpl::if_, value, value const&>::type + type; + }; + + template + typename result::type + operator()(U const& x) const + { + return replacer_if_helper::value>:: + call(x, f, new_value); + } + + F f; + T new_value; + }; +}}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/erase.hpp b/win32/include/boost/fusion/algorithm/transformation/erase.hpp new file mode 100755 index 000000000..9806ac77b --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/erase.hpp @@ -0,0 +1,108 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ERASE_07232005_0534) +#define FUSION_ERASE_07232005_0534 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct compute_erase_last // put this in detail!!! + { + typedef typename result_of::end::type seq_last_type; + typedef typename convert_iterator::type first_type; + typedef typename + mpl::if_< + result_of::equal_to + , first_type + , typename result_of::next::type + >::type + type; + + static type + call(First const& first, mpl::false_) + { + return fusion::next(convert_iterator::call(first)); + } + + static type + call(First const& first, mpl::true_) + { + return convert_iterator::call(first); + } + + static type + call(First const& first) + { + return call(first, result_of::equal_to()); + } + }; + + template < + typename Sequence + , typename First + , typename Last = typename compute_erase_last::type> + struct erase + { + typedef typename result_of::begin::type seq_first_type; + typedef typename result_of::end::type seq_last_type; + BOOST_STATIC_ASSERT((!result_of::equal_to::value)); + + typedef typename convert_iterator::type first_type; + typedef typename convert_iterator::type last_type; + typedef iterator_range left_type; + typedef iterator_range right_type; + typedef joint_view type; + }; + } + + template + typename result_of::erase::type + erase(Sequence const& seq, First const& first) + { + typedef result_of::erase result_of; + typedef typename result_of::left_type left_type; + typedef typename result_of::right_type right_type; + typedef typename result_of::type result_type; + + left_type left( + fusion::begin(seq) + , convert_iterator::call(first)); + right_type right( + fusion::result_of::compute_erase_last::call(first) + , fusion::end(seq)); + return result_type(left, right); + } + + template + typename result_of::erase::type + erase(Sequence const& seq, First const& first, Last const& last) + { + typedef result_of::erase result_of; + typedef typename result_of::left_type left_type; + typedef typename result_of::right_type right_type; + typedef typename result_of::type result_type; + + left_type left(fusion::begin(seq), first); + right_type right(last, fusion::end(seq)); + return result_type(left, right); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/erase_key.hpp b/win32/include/boost/fusion/algorithm/transformation/erase_key.hpp new file mode 100755 index 000000000..e19521734 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/erase_key.hpp @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ERASE_KEY_10022005_1851) +#define FUSION_ERASE_KEY_10022005_1851 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct erase_key + { + typedef detail::assoc_find filter; + typedef typename erase::type type; + }; + } + + template + inline typename result_of::erase_key::type + erase_key(Sequence const& seq) + { + typedef typename result_of::erase_key::filter filter; + return erase(seq, filter::call(seq)); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/filter.hpp b/win32/include/boost/fusion/algorithm/transformation/filter.hpp new file mode 100755 index 000000000..b39d47894 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/filter.hpp @@ -0,0 +1,34 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_FILTER_02122005_1839) +#define FUSION_FILTER_02122005_1839 + +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct filter + { + typedef filter_view > type; + }; + } + + template + inline typename result_of::filter::type + filter(Sequence const& seq) + { + return filter_view >(seq); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/filter_if.hpp b/win32/include/boost/fusion/algorithm/transformation/filter_if.hpp new file mode 100755 index 000000000..227ccc28c --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/filter_if.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_FILTER_IF_07172005_0818) +#define FUSION_FILTER_IF_07172005_0818 + +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct filter_if + { + typedef filter_view type; + }; + } + + template + inline typename result_of::filter_if::type + filter_if(Sequence const& seq) + { + return filter_view(seq); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/insert.hpp b/win32/include/boost/fusion/algorithm/transformation/insert.hpp new file mode 100755 index 000000000..638fdec26 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/insert.hpp @@ -0,0 +1,63 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INSERT_07222005_0730) +#define FUSION_INSERT_07222005_0730 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct insert + { + typedef typename detail::as_fusion_element::type element_type; + typedef typename convert_iterator::type pos_type; + typedef typename result_of::begin::type first_type; + typedef typename result_of::end::type last_type; + + typedef iterator_range left_type; + typedef iterator_range right_type; + typedef fusion::single_view single_view; + typedef joint_view left_insert_type; + typedef joint_view type; + }; + } + + template + inline typename result_of::insert< + Sequence const, Position, T>::type + insert(Sequence const& seq, Position const& pos, T const& x) + { + typedef result_of::insert< + Sequence const, Position, T> + result_of; + typedef typename result_of::left_type left_type; + typedef typename result_of::right_type right_type; + typedef typename result_of::single_view single_view; + typedef typename result_of::left_insert_type left_insert_type; + typedef typename result_of::type result; + + left_type left(fusion::begin(seq), convert_iterator::call(pos)); + right_type right(convert_iterator::call(pos), fusion::end(seq)); + single_view insert(x); + left_insert_type left_insert(left, insert); + return result(left_insert, right); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/insert_range.hpp b/win32/include/boost/fusion/algorithm/transformation/insert_range.hpp new file mode 100755 index 000000000..8dc229015 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/insert_range.hpp @@ -0,0 +1,55 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INSERT_RANGE_009172005_1147) +#define FUSION_INSERT_RANGE_009172005_1147 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct insert_range + { + typedef typename convert_iterator::type pos_type; + typedef typename result_of::begin::type first_type; + typedef typename result_of::end::type last_type; + + typedef iterator_range left_type; + typedef iterator_range right_type; + typedef joint_view left_insert_type; + typedef joint_view type; + }; + } + + template + inline typename result_of::insert_range::type + insert_range(Sequence const& seq, Position const& pos, Range const& range) + { + typedef result_of::insert_range result_of; + typedef typename result_of::left_type left_type; + typedef typename result_of::right_type right_type; + typedef typename result_of::left_insert_type left_insert_type; + typedef typename result_of::type result; + + left_type left(fusion::begin(seq), convert_iterator::call(pos)); + right_type right(convert_iterator::call(pos), fusion::end(seq)); + left_insert_type left_insert(left, range); + return result(left_insert, right); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/join.hpp b/win32/include/boost/fusion/algorithm/transformation/join.hpp new file mode 100755 index 000000000..62842bb2b --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/join.hpp @@ -0,0 +1,33 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_JOIN_200601222109) +#define FUSION_JOIN_200601222109 + +#include + +namespace boost { namespace fusion { + + namespace result_of + { + template + struct join + { + typedef joint_view type; + }; + } + + template + inline typename result_of::join::type + join(LhSequence const& lhs, RhSequence const& rhs) + { + return typename result_of::join::type( + lhs, rhs); + } +}} + +#endif diff --git a/win32/include/boost/fusion/algorithm/transformation/pop_back.hpp b/win32/include/boost/fusion/algorithm/transformation/pop_back.hpp new file mode 100755 index 000000000..b23a7006f --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/pop_back.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_POP_BACK_09172005_1038) +#define FUSION_POP_BACK_09172005_1038 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct pop_back + { + typedef + iterator_range< + typename begin::type + , typename prior< + typename end::type + >::type + > + type; + }; + } + + template + inline typename result_of::pop_back::type + pop_back(Sequence const& seq) + { + typedef typename result_of::pop_back::type result; + return result(fusion::begin(seq), fusion::prior(fusion::end(seq))); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/pop_front.hpp b/win32/include/boost/fusion/algorithm/transformation/pop_front.hpp new file mode 100755 index 000000000..6e59a73e7 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/pop_front.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_POP_FRONT_09172005_1115) +#define FUSION_POP_FRONT_09172005_1115 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct pop_front + { + typedef + iterator_range< + typename next< + typename begin::type + >::type + , typename end::type + > + type; + }; + } + + template + inline typename result_of::pop_front::type + pop_front(Sequence const& seq) + { + typedef typename result_of::pop_front::type result; + return result(fusion::next(fusion::begin(seq)), fusion::end(seq)); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/push_back.hpp b/win32/include/boost/fusion/algorithm/transformation/push_back.hpp new file mode 100755 index 000000000..cd48d3ac0 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/push_back.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_PUSH_BACK_07162005_0235) +#define FUSION_PUSH_BACK_07162005_0235 + +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct push_back + { + typedef fusion::single_view::type> single_view; + typedef joint_view type; + }; + } + + template + inline typename result_of::push_back::type + push_back(Sequence const& seq, T const& x) + { + typedef typename result_of::push_back push_back; + typedef typename push_back::single_view single_view; + typedef typename push_back::type result; + single_view x_(x); + return result(seq, x_); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/push_front.hpp b/win32/include/boost/fusion/algorithm/transformation/push_front.hpp new file mode 100755 index 000000000..c6ef7f65b --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/push_front.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_PUSH_FRONT_07162005_0749) +#define FUSION_PUSH_FRONT_07162005_0749 + +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct push_front + { + typedef fusion::single_view::type> single_view; + typedef joint_view type; + }; + } + + template + inline typename result_of::push_front::type + push_front(Sequence const& seq, T const& x) + { + typedef typename result_of::push_front push_front; + typedef typename push_front::single_view single_view; + typedef typename push_front::type result; + single_view x_(x); + return result(x_, seq); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/remove.hpp b/win32/include/boost/fusion/algorithm/transformation/remove.hpp new file mode 100755 index 000000000..40c2370e6 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/remove.hpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_REMOVE_07162005_0818) +#define FUSION_REMOVE_07162005_0818 + +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct remove + { + typedef filter_view > > type; + }; + } + + template + inline typename result_of::remove::type + remove(Sequence const& seq) + { + typedef typename result_of::remove::type result_type; + return result_type(seq); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/remove_if.hpp b/win32/include/boost/fusion/algorithm/transformation/remove_if.hpp new file mode 100755 index 000000000..e4fb5613b --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/remove_if.hpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_REMOVE_IF_07162005_0818) +#define FUSION_REMOVE_IF_07162005_0818 + +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct remove_if + { + typedef filter_view > type; + }; + } + + template + inline typename result_of::remove_if::type + remove_if(Sequence const& seq) + { + typedef typename result_of::remove_if::type result_type; + return result_type(seq); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/replace.hpp b/win32/include/boost/fusion/algorithm/transformation/replace.hpp new file mode 100755 index 000000000..be8487f30 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/replace.hpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_REPLACE_08182005_0830) +#define FUSION_REPLACE_08182005_0830 + +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct replace + { + typedef transform_view > type; + }; + } + + template + inline typename result_of::replace::type + replace(Sequence const& seq, T const& old_value, T const& new_value) + { + typedef typename result_of::replace::type result; + detail::replacer f(old_value, new_value); + return result(seq, f); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/replace_if.hpp b/win32/include/boost/fusion/algorithm/transformation/replace_if.hpp new file mode 100755 index 000000000..df8c714ea --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/replace_if.hpp @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_REPLACE_IF_08182005_0939) +#define FUSION_REPLACE_IF_08182005_0939 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct replace_if + { + typedef transform_view > type; + }; + } + + template + inline typename result_of::replace_if::type + replace_if(Sequence const& seq, F pred, T const& new_value) + { + typedef typename result_of::replace_if::type result; + detail::replacer_if f(pred, new_value); + return result(seq, f); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/reverse.hpp b/win32/include/boost/fusion/algorithm/transformation/reverse.hpp new file mode 100755 index 000000000..34df14cd7 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/reverse.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_REVERSE_07212005_1230) +#define FUSION_REVERSE_07212005_1230 + +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct reverse + { + typedef reverse_view type; + }; + } + + template + inline reverse_view + reverse(Sequence const& view) + { + return reverse_view(view); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/transform.hpp b/win32/include/boost/fusion/algorithm/transformation/transform.hpp new file mode 100755 index 000000000..3e63209fb --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/transform.hpp @@ -0,0 +1,51 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_TRANSFORM_07052005_1057) +#define FUSION_TRANSFORM_07052005_1057 + +#include + +namespace boost { namespace fusion +{ + struct void_; + + namespace result_of + { + template + struct transform + { + typedef transform_view type; + }; + + template +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + struct transform +#else + struct transform +#endif + { + typedef transform_view type; + }; + } + + template + inline typename result_of::transform::type + transform(Sequence const& seq, F f) + { + return transform_view(seq, f); + } + + template + inline typename result_of::transform::type + transform(Sequence1 const& seq1, Sequence2 const& seq2, F f) + { + return transform_view(seq1, seq2, f); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/algorithm/transformation/zip.hpp b/win32/include/boost/fusion/algorithm/transformation/zip.hpp new file mode 100755 index 000000000..70e1803a5 --- /dev/null +++ b/win32/include/boost/fusion/algorithm/transformation/zip.hpp @@ -0,0 +1,86 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_ZIP_HPP_20060125_2058) +#define FUSION_ZIP_HPP_20060125_2058 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(FUSION_MAX_ZIP_SEQUENCES) +#define FUSION_MAX_ZIP_SEQUENCES 10 +#endif + +namespace boost { namespace fusion { + + struct void_; + + namespace result_of + { + template + struct zip; + } + +#define BOOST_PP_FILENAME_1 \ + +#define BOOST_PP_ITERATION_LIMITS (2, FUSION_MAX_ZIP_SEQUENCES) +#include BOOST_PP_ITERATE() + +}} + +#endif + +#else + +#define ZIP_ITERATION BOOST_PP_ITERATION() + + namespace result_of + { + template< BOOST_PP_ENUM_PARAMS(ZIP_ITERATION, typename T) > +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + #define TEXT(z, n, text) , text + struct zip< BOOST_PP_ENUM_PARAMS(ZIP_ITERATION, T) BOOST_PP_REPEAT_FROM_TO(BOOST_PP_DEC(ZIP_ITERATION), FUSION_MAX_ZIP_SEQUENCES, TEXT, void_) > + #undef TEXT +#else + struct zip< BOOST_PP_ENUM_PARAMS(ZIP_ITERATION, T) > +#endif + { + typedef mpl::vector< BOOST_PP_ENUM_PARAMS(ZIP_ITERATION, T) > sequences; + typedef typename mpl::transform >::type ref_params; + typedef zip_view::type> type; + }; + } + +#define FUSION_REF_PARAM(z, n, data) const T ## n& + + template + inline typename result_of::zip::type + zip(BOOST_PP_ENUM_BINARY_PARAMS(ZIP_ITERATION, T, const& t)) + { + fusion::vector seqs( + BOOST_PP_ENUM_PARAMS(ZIP_ITERATION, t)); + return typename result_of::zip::type( + seqs); + } + +#undef FUSION_REF_PARAM +#undef ZIP_ITERATION + +#endif diff --git a/win32/include/boost/fusion/container.hpp b/win32/include/boost/fusion/container.hpp new file mode 100755 index 000000000..f92aa044c --- /dev/null +++ b/win32/include/boost/fusion/container.hpp @@ -0,0 +1,17 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_CLASS_10022005_0614) +#define FUSION_SEQUENCE_CLASS_10022005_0614 + +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/container/deque.hpp b/win32/include/boost/fusion/container/deque.hpp new file mode 100755 index 000000000..433c1a259 --- /dev/null +++ b/win32/include/boost/fusion/container/deque.hpp @@ -0,0 +1,15 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_SEQUENCE_CONTAINER_DEQUE_24112006_2036) +#define BOOST_FUSION_SEQUENCE_CONTAINER_DEQUE_24112006_2036 + +#include +#include + +#endif + diff --git a/win32/include/boost/fusion/container/deque/back_extended_deque.hpp b/win32/include/boost/fusion/container/deque/back_extended_deque.hpp new file mode 100755 index 000000000..747f5ce7b --- /dev/null +++ b/win32/include/boost/fusion/container/deque/back_extended_deque.hpp @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_BACK_EXTENDED_DEQUE_26112006_2209) +#define BOOST_FUSION_BACK_EXTENDED_DEQUE_26112006_2209 + +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { namespace fusion { + template + struct back_extended_deque + : detail::keyed_element, + sequence_base > + { + typedef detail::keyed_element base; + typedef typename Deque::next_down next_down; + typedef mpl::int_ >::value> next_up; + typedef mpl::plus::type, mpl::int_<1> > size; + + back_extended_deque(Deque const& deque, typename add_reference::type>::type t) + : base(t, deque) + {} + }; +}} + +#endif diff --git a/win32/include/boost/fusion/container/deque/convert.hpp b/win32/include/boost/fusion/container/deque/convert.hpp new file mode 100755 index 000000000..ea7170ad1 --- /dev/null +++ b/win32/include/boost/fusion/container/deque/convert.hpp @@ -0,0 +1,48 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_CONVERT_20061213_2207) +#define FUSION_CONVERT_20061213_2207 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct as_deque + { + typedef typename detail::as_deque::value> gen; + typedef typename gen:: + template apply::type>::type + type; + }; + } + + template + inline typename result_of::as_deque::type + as_deque(Sequence& seq) + { + typedef typename result_of::as_deque::gen gen; + return gen::call(fusion::begin(seq)); + } + + template + inline typename result_of::as_deque::type + as_deque(Sequence const& seq) + { + typedef typename result_of::as_deque::gen gen; + return gen::call(fusion::begin(seq)); + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/deque/deque.hpp b/win32/include/boost/fusion/container/deque/deque.hpp new file mode 100755 index 000000000..842e43cc7 --- /dev/null +++ b/win32/include/boost/fusion/container/deque/deque.hpp @@ -0,0 +1,93 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_DEQUE_26112006_1649) +#define BOOST_FUSION_DEQUE_26112006_1649 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { namespace fusion { + + struct deque_tag; + + template + struct deque + : + detail::deque_keyed_values::type, + sequence_base > + { + typedef deque_tag fusion_tag; + typedef typename detail::deque_keyed_values::type base; + typedef typename detail::deque_initial_size::type size; + typedef mpl::int_ next_up; + typedef mpl::int_< + mpl::if_ >, mpl::int_<0>, mpl::int_<-1> >::type::value> next_down; + typedef mpl::false_ is_view; + +#include + + deque() + {} + + explicit deque(typename add_reference::type>::type t0) + : base(t0, detail::nil_keyed_element()) + {} + + template + deque(deque const& seq) + : base(seq) + {} + + template + deque(Sequence const& seq, typename disable_if >::type* dummy = 0) + : base(base::from_iterator(fusion::begin(seq))) + {} + + template + deque& + operator=(deque const& rhs) + { + base::operator=(rhs); + return *this; + } + + template + deque& + operator=(T const& rhs) + { + base::operator=(rhs); + return *this; + } + + }; +}} + +#endif diff --git a/win32/include/boost/fusion/container/deque/deque_fwd.hpp b/win32/include/boost/fusion/container/deque/deque_fwd.hpp new file mode 100755 index 000000000..2839e3a15 --- /dev/null +++ b/win32/include/boost/fusion/container/deque/deque_fwd.hpp @@ -0,0 +1,24 @@ +/*============================================================================= + Copyright (c) 2005-2007 Joel de Guzman + Copyright (c) 2005-2007 Dan Marsden + + 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(FUSION_DEQUE_FORWARD_02092007_0749) +#define FUSION_DEQUE_FORWARD_02092007_0749 + +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + template< + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_DEQUE_SIZE, typename T, void_)> + struct deque; +}} + +#endif diff --git a/win32/include/boost/fusion/container/deque/deque_iterator.hpp b/win32/include/boost/fusion/container/deque/deque_iterator.hpp new file mode 100755 index 000000000..5723ccaf7 --- /dev/null +++ b/win32/include/boost/fusion/container/deque/deque_iterator.hpp @@ -0,0 +1,106 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_DEQUE_ITERATOR_26112006_2154) +#define BOOST_FUSION_DEQUE_ITERATOR_26112006_2154 + +#include +#include +#include +#include + +namespace boost { namespace fusion { + + struct bidirectional_traversal_tag; + + template + struct deque_iterator + : iterator_facade, bidirectional_traversal_tag> + { + typedef Seq sequence; + typedef mpl::int_ index; + + deque_iterator(Seq& seq) + : seq_(seq) + {} + + template + struct value_of + : detail::keyed_element_value_at< + typename Iterator::sequence, typename Iterator::index> + {}; + + template + struct deref + { + typedef typename detail::keyed_element_value_at< + typename Iterator::sequence, typename Iterator::index>::type element_type; + + typedef typename add_reference< + typename mpl::eval_if< + is_const, + add_const, + mpl::identity >::type>::type type; + + static type + call(Iterator const& it) + { + return it.seq_.get(typename Iterator::index()); + } + }; + + template + struct advance + { + typedef typename Iterator::index index; + typedef typename Iterator::sequence sequence; + typedef deque_iterator type; + + static type + call(Iterator const& i) + { + return type(i.seq_); + } + }; + + template + struct next + : advance > + {}; + + template + struct prior + : advance > + {}; + + template + struct distance : mpl::minus + { + typedef typename + mpl::minus< + typename I2::index, typename I1::index + >::type + type; + + static type + call(I1 const&, I2 const&) + { + return type(); + } + }; + + template + struct equal_to + : mpl::equal_to + {}; + + Seq& seq_; + }; + +}} + +#endif diff --git a/win32/include/boost/fusion/container/deque/detail/as_deque.hpp b/win32/include/boost/fusion/container/deque/detail/as_deque.hpp new file mode 100755 index 000000000..e13289e22 --- /dev/null +++ b/win32/include/boost/fusion/container/deque/detail/as_deque.hpp @@ -0,0 +1,102 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_AS_DEQUE_20061213_2210) +#define FUSION_AS_DEQUE_20061213_2210 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct as_deque; + + template <> + struct as_deque<0> + { + template + struct apply + { + typedef deque<> type; + }; + + template + static typename apply::type + call(Iterator) + { + return deque<>(); + } + }; + +#define BOOST_FUSION_NEXT_ITERATOR(z, n, data) \ + typedef typename fusion::result_of::next::type \ + BOOST_PP_CAT(I, BOOST_PP_INC(n)); + +#define BOOST_FUSION_NEXT_CALL_ITERATOR(z, n, data) \ + typename gen::BOOST_PP_CAT(I, BOOST_PP_INC(n)) \ + BOOST_PP_CAT(i, BOOST_PP_INC(n)) = fusion::next(BOOST_PP_CAT(i, n)); + +#define BOOST_FUSION_VALUE_OF_ITERATOR(z, n, data) \ + typedef typename fusion::result_of::value_of::type \ + BOOST_PP_CAT(T, n); + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_DEQUE_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_NEXT_ITERATOR +#undef BOOST_FUSION_NEXT_CALL_ITERATOR +#undef BOOST_FUSION_VALUE_OF_ITERATOR + +}}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + template <> + struct as_deque + { + template + struct apply + { + BOOST_PP_REPEAT(N, BOOST_FUSION_NEXT_ITERATOR, _) + BOOST_PP_REPEAT(N, BOOST_FUSION_VALUE_OF_ITERATOR, _) + typedef deque type; + }; + + template + static typename apply::type + call(Iterator const& i0) + { + typedef apply gen; + typedef typename gen::type result; + BOOST_PP_REPEAT(BOOST_PP_DEC(N), BOOST_FUSION_NEXT_CALL_ITERATOR, _) + return result(BOOST_PP_ENUM_PARAMS(N, *i)); + } + }; + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/deque/detail/at_impl.hpp b/win32/include/boost/fusion/container/deque/detail/at_impl.hpp new file mode 100755 index 000000000..94b0751df --- /dev/null +++ b/win32/include/boost/fusion/container/deque/detail/at_impl.hpp @@ -0,0 +1,59 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_DEQUE_AT_IMPL_09122006_2017) +#define BOOST_FUSION_DEQUE_AT_IMPL_09122006_2017 + +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { namespace fusion { + + struct deque_tag; + + namespace extension + { + template + struct at_impl; + + template<> + struct at_impl + { + template + struct apply + { + typedef typename Sequence::next_up next_up; + typedef typename Sequence::next_down next_down; + BOOST_MPL_ASSERT_RELATION(next_down::value, !=, next_up::value); + + typedef mpl::plus > offset; + typedef mpl::int_::value> adjusted_index; + typedef typename detail::keyed_element_value_at::type element_type; + typedef typename add_reference< + typename mpl::eval_if< + is_const, + add_const, + mpl::identity >::type>::type type; + + static type call(Sequence& seq) + { + return seq.get(adjusted_index()); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/deque/detail/begin_impl.hpp b/win32/include/boost/fusion/container/deque/detail/begin_impl.hpp new file mode 100755 index 000000000..e33fb3190 --- /dev/null +++ b/win32/include/boost/fusion/container/deque/detail/begin_impl.hpp @@ -0,0 +1,46 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_DEQUE_BEGIN_IMPL_09122006_2034) +#define BOOST_FUSION_DEQUE_BEGIN_IMPL_09122006_2034 + +#include + +#include +#include + +namespace boost { namespace fusion { + + struct deque_tag; + + namespace extension + { + template + struct begin_impl; + + template<> + struct begin_impl + { + template + struct apply + { + typedef typename mpl::if_< + mpl::equal_to, + deque_iterator, + deque_iterator< + Sequence, mpl::plus >::value> >::type type; + + static type call(Sequence& seq) + { + return type(seq); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/deque/detail/convert_impl.hpp b/win32/include/boost/fusion/container/deque/detail/convert_impl.hpp new file mode 100755 index 000000000..82c5d9586 --- /dev/null +++ b/win32/include/boost/fusion/container/deque/detail/convert_impl.hpp @@ -0,0 +1,45 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_CONVERT_IMPL_20061213_2207) +#define FUSION_CONVERT_IMPL_20061213_2207 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct deque_tag; + + namespace extension + { + template + struct convert_impl; + + template <> + struct convert_impl + { + template + struct apply + { + typedef typename detail::as_deque::value> gen; + typedef typename gen:: + template apply::type>::type + type; + + static type call(Sequence& seq) + { + return gen::call(fusion::begin(seq)); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/deque/detail/deque_forward_ctor.hpp b/win32/include/boost/fusion/container/deque/detail/deque_forward_ctor.hpp new file mode 100755 index 000000000..ecdabdcb3 --- /dev/null +++ b/win32/include/boost/fusion/container/deque/detail/deque_forward_ctor.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_PP_IS_ITERATING) +#if !defined(BOOST_FUSION_SEQUENCE_DEQUE_DETAIL_DEQUE_FORWARD_CTOR_04122006_2212) +#define BOOST_FUSION_SEQUENCE_DEQUE_DETAIL_DEQUE_FORWARD_CTOR_04122006_2212 + +#include +#include +#include + +#define BOOST_PP_FILENAME_1 \ + +#define BOOST_PP_ITERATION_LIMITS (2, FUSION_MAX_DEQUE_SIZE) +#include BOOST_PP_ITERATE() + +#endif +#else + +#define N BOOST_PP_ITERATION() + +deque(BOOST_PP_ENUM_BINARY_PARAMS(N, typename add_reference::type>::type t)) + : base(detail::deque_keyed_values::call(BOOST_PP_ENUM_PARAMS(N, t))) +{} + +#undef N +#endif diff --git a/win32/include/boost/fusion/container/deque/detail/deque_initial_size.hpp b/win32/include/boost/fusion/container/deque/detail/deque_initial_size.hpp new file mode 100755 index 000000000..e7b29e448 --- /dev/null +++ b/win32/include/boost/fusion/container/deque/detail/deque_initial_size.hpp @@ -0,0 +1,33 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_DEQUE_DETAIL_DEQUE_INITIAL_SIZE_26112006_2139) +#define BOOST_FUSION_DEQUE_DETAIL_DEQUE_INITIAL_SIZE_26112006_2139 + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { + + struct void_; + +namespace detail { + + template + struct deque_initial_size + { + typedef mpl::vector args; + typedef typename mpl::find::type first_void; + typedef typename mpl::distance::type, first_void>::type type; + }; +}}} + +#endif diff --git a/win32/include/boost/fusion/container/deque/detail/deque_keyed_values.hpp b/win32/include/boost/fusion/container/deque/detail/deque_keyed_values.hpp new file mode 100755 index 000000000..b44ee1f21 --- /dev/null +++ b/win32/include/boost/fusion/container/deque/detail/deque_keyed_values.hpp @@ -0,0 +1,75 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_DEQUE_DETAIL_DEQUE_KEYED_VALUES_26112006_1330) +#define BOOST_FUSION_DEQUE_DETAIL_DEQUE_KEYED_VALUES_26112006_1330 + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define FUSION_VOID(z, n, _) void_ + +namespace boost { namespace fusion { + + struct void_; + +namespace detail { + + template + struct keyed_element; + + struct nil_keyed_element; + + template + struct deque_keyed_values_impl; + + template + struct deque_keyed_values_impl + { + typedef nil_keyed_element type; + + static type call() + { + return type(); + } + }; + + template + struct deque_keyed_values_impl + { + typedef mpl::int_ >::value> next_index; + + typedef typename deque_keyed_values_impl< + next_index, + BOOST_PP_ENUM_SHIFTED_PARAMS(FUSION_MAX_DEQUE_SIZE, T)>::type tail; + typedef keyed_element type; + +#include + + }; + + template + struct deque_keyed_values + : deque_keyed_values_impl, BOOST_PP_ENUM_PARAMS(FUSION_MAX_DEQUE_SIZE, T)> + {}; + +}}} + +#undef FUSION_VOID + +#endif diff --git a/win32/include/boost/fusion/container/deque/detail/deque_keyed_values_call.hpp b/win32/include/boost/fusion/container/deque/detail/deque_keyed_values_call.hpp new file mode 100755 index 000000000..41c98cac5 --- /dev/null +++ b/win32/include/boost/fusion/container/deque/detail/deque_keyed_values_call.hpp @@ -0,0 +1,38 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_PP_IS_ITERATING) +#if !defined(BOOST_FUSION_SEQUENCE_DEQUE_DETAIL_DEQUE_KEYED_VALUES_CALL_04122006_2211) +#define BOOST_FUSION_SEQUENCE_DEQUE_DETAIL_DEQUE_KEYED_VALUES_CALL_04122006_2211 + +#include +#include +#include + +#define BOOST_PP_FILENAME_1 \ + +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_DEQUE_SIZE) +#include BOOST_PP_ITERATE() + +#endif +#else + +#define N BOOST_PP_ITERATION() + +static type call(BOOST_PP_ENUM_BINARY_PARAMS(N, typename add_reference::type>::type t)) +{ + return type(t0, + deque_keyed_values_impl< + next_index +#if N > 1 + , BOOST_PP_ENUM_SHIFTED_PARAMS(N, T) +#endif + >::call(BOOST_PP_ENUM_SHIFTED_PARAMS(N, t))); +} + +#undef N +#endif diff --git a/win32/include/boost/fusion/container/deque/detail/end_impl.hpp b/win32/include/boost/fusion/container/deque/detail/end_impl.hpp new file mode 100755 index 000000000..5e7aa4e6b --- /dev/null +++ b/win32/include/boost/fusion/container/deque/detail/end_impl.hpp @@ -0,0 +1,46 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_DEQUE_END_IMPL_09122006_2034) +#define BOOST_FUSION_DEQUE_END_IMPL_09122006_2034 + +#include + +#include +#include + +namespace boost { namespace fusion { + + struct deque_tag; + + namespace extension + { + template + struct end_impl; + + template<> + struct end_impl + { + template + struct apply + { + typedef typename mpl::if_< + mpl::equal_to, + deque_iterator, + deque_iterator< + Sequence, Sequence::next_up::value> >::type type; + + static type call(Sequence& seq) + { + return type(seq); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/deque/detail/keyed_element.hpp b/win32/include/boost/fusion/container/deque/detail/keyed_element.hpp new file mode 100755 index 000000000..e02ff4937 --- /dev/null +++ b/win32/include/boost/fusion/container/deque/detail/keyed_element.hpp @@ -0,0 +1,111 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_DEQUE_DETAIL_KEYED_ELEMENT_26112006_1330) +#define BOOST_FUSION_DEQUE_DETAIL_KEYED_ELEMENT_26112006_1330 + +#include +#include + +#include +#include + +namespace boost { namespace fusion { + + struct fusion_sequence_tag; + +namespace detail { + + struct nil_keyed_element + { + typedef fusion_sequence_tag tag; + void get(); + + template + static nil_keyed_element + from_iterator(It const&) + { + return nil_keyed_element(); + } + }; + + template + struct keyed_element + : Rest + { + typedef Rest base; + typedef fusion_sequence_tag tag; + using Rest::get; + + template + static keyed_element + from_iterator(It const& it) + { + return keyed_element( + *it, base::from_iterator(fusion::next(it))); + } + + template + keyed_element(keyed_element const& rhs) + : Rest(rhs.get_base()), value_(rhs.value_) + {} + + Rest const get_base() const + { + return *this; + } + + typename add_reference::type>::type get(Key) const + { + return value_; + } + + typename add_reference::type get(Key) + { + return value_; + } + + keyed_element(typename add_reference::type>::type value, Rest const& rest) + : Rest(rest), value_(value) + {} + + keyed_element() + : Rest(), value_() + {} + + template + keyed_element& operator=(keyed_element const& rhs) + { + base::operator=(static_cast(rhs)); // cast for msvc-7.1 + value_ = rhs.value_; + return *this; + } + + keyed_element& operator=(keyed_element const& rhs) + { + base::operator=(rhs); + value_ = rhs.value_; + return *this; + } + + Value value_; + }; + + template + struct keyed_element_value_at + : keyed_element_value_at + {}; + + template + struct keyed_element_value_at, Key> + { + typedef Value type; + }; + +}}} + +#endif diff --git a/win32/include/boost/fusion/container/deque/detail/value_at_impl.hpp b/win32/include/boost/fusion/container/deque/detail/value_at_impl.hpp new file mode 100755 index 000000000..838feb452 --- /dev/null +++ b/win32/include/boost/fusion/container/deque/detail/value_at_impl.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_DEQUE_VALUE_AT_IMPL_08122006_0756) +#define BOOST_FUSION_DEQUE_VALUE_AT_IMPL_08122006_0756 + +#include + +#include +#include + +namespace boost { namespace fusion { + + struct deque_tag; + + namespace extension + { + template + struct value_at_impl; + + template<> + struct value_at_impl + { + template + struct apply + { + typedef typename Sequence::next_up next_up; + typedef typename Sequence::next_down next_down; + BOOST_MPL_ASSERT_RELATION(next_down::value, !=, next_up::value); + + typedef mpl::plus > offset; + typedef mpl::int_::value> adjusted_index; + typedef typename detail::keyed_element_value_at::type type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/deque/front_extended_deque.hpp b/win32/include/boost/fusion/container/deque/front_extended_deque.hpp new file mode 100755 index 000000000..8e1add27d --- /dev/null +++ b/win32/include/boost/fusion/container/deque/front_extended_deque.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_FRONT_EXTENDED_DEQUE_26112006_2209) +#define BOOST_FUSION_FRONT_EXTENDED_DEQUE_26112006_2209 + +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace boost { namespace fusion { + template + struct front_extended_deque + : detail::keyed_element, + sequence_base > + { + typedef detail::keyed_element base; + typedef mpl::int_ >::value> next_down; + typedef typename Deque::next_up next_up; + typedef mpl::plus::type, mpl::int_<1> > size; + + front_extended_deque(Deque const& deque, typename add_reference::type>::type t) + : base(t, deque) + {} + }; +}} + +#endif diff --git a/win32/include/boost/fusion/container/deque/limits.hpp b/win32/include/boost/fusion/container/deque/limits.hpp new file mode 100755 index 000000000..7a5336dd2 --- /dev/null +++ b/win32/include/boost/fusion/container/deque/limits.hpp @@ -0,0 +1,15 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_DEQUE_LIMITS_26112006_1737) +#define BOOST_FUSION_DEQUE_LIMITS_26112006_1737 + +#if !defined(FUSION_MAX_DEQUE_SIZE) +#define FUSION_MAX_DEQUE_SIZE 10 +#endif + +#endif diff --git a/win32/include/boost/fusion/container/ext_/tree.hpp b/win32/include/boost/fusion/container/ext_/tree.hpp new file mode 100755 index 000000000..1ea832047 --- /dev/null +++ b/win32/include/boost/fusion/container/ext_/tree.hpp @@ -0,0 +1,130 @@ +/*============================================================================= + Copyright (c) 2006 Eric Niebler + + Use, modification and distribution is subject to the Boost Software + License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef FUSION_BINARY_TREE_EAN_05032006_1027 +#define FUSION_BINARY_TREE_EAN_05032006_1027 + +#include +#include +#include +#include +#include +#include +#include +#include // for nil +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct tree_tag; + + namespace detail + { + template + struct reference : add_reference {}; + + template + struct reference : reference::type, false> {}; + + template + struct reference : reference {}; + } + + template + struct tree + : sequence_base > + { + typedef Data data_type; + typedef Left left_type; + typedef Right right_type; + typedef tree_tag fusion_tag; + typedef forward_traversal_tag category; + typedef mpl::false_ is_view; + + typedef typename mpl::if_< + traits::is_sequence + , Data + , single_view + >::type data_view; + + explicit tree( + typename fusion::detail::call_param::type data_ + , typename fusion::detail::call_param::type left_ = Left() + , typename fusion::detail::call_param::type right_ = Right() + ) + : segments(left_, data_view(data_), right_) + {} + + typedef vector3 segments_type; + segments_type segments; + }; + + template + tree make_tree(Data const &data) + { + return tree(data); + } + + template + tree make_tree(Data const &data, Left const &left, Right const &right) + { + return tree(data, left, right); + } + + namespace extension + { + template<> + struct is_segmented_impl + { + template + struct apply : mpl::true_ {}; + }; + + template<> + struct segments_impl + { + template + struct apply + { + typedef typename mpl::if_< + is_const + , typename Sequence::segments_type const & + , typename Sequence::segments_type & + >::type type; + + static type call(Sequence &seq) + { + return seq.segments; + } + }; + }; + + template<> + struct begin_impl + { + template + struct apply + : segmented_begin + {}; + }; + + template<> + struct end_impl + { + template + struct apply + : segmented_end + {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/generation.hpp b/win32/include/boost/fusion/container/generation.hpp new file mode 100755 index 000000000..40d96ee8a --- /dev/null +++ b/win32/include/boost/fusion/container/generation.hpp @@ -0,0 +1,20 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_GENERATION_10022005_0615) +#define FUSION_SEQUENCE_GENERATION_10022005_0615 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/container/generation/cons_tie.hpp b/win32/include/boost/fusion/container/generation/cons_tie.hpp new file mode 100755 index 000000000..bd6900672 --- /dev/null +++ b/win32/include/boost/fusion/container/generation/cons_tie.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_CONS_TIE_07182005_0854) +#define FUSION_CONS_TIE_07182005_0854 + +#include + +namespace boost { namespace fusion +{ + struct nil; + + namespace result_of + { + template + struct cons_tie + { + typedef cons type; + }; + } + + // $$$ do we really want a cons_tie? $$$ + template + inline cons + cons_tie(Car& car) + { + return cons(car); + } + + // $$$ do we really want a cons_tie? $$$ + template + inline cons + cons_tie(Car& car, Cdr const& cdr) + { + return cons(car, cdr); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/container/generation/deque_tie.hpp b/win32/include/boost/fusion/container/generation/deque_tie.hpp new file mode 100755 index 000000000..0cc587676 --- /dev/null +++ b/win32/include/boost/fusion/container/generation/deque_tie.hpp @@ -0,0 +1,79 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_DEQUE_TIE_07192005_1242) +#define FUSION_DEQUE_TIE_07192005_1242 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + namespace result_of + { + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_DEQUE_SIZE, typename T, void_) + , typename Extra = void_ + > + struct deque_tie; + } + +#define BOOST_FUSION_REF(z, n, data) BOOST_PP_CAT(T, n)& + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_DEQUE_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_REF + +}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + namespace result_of + { + template +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + #define TEXT(z, n, text) , text + struct deque_tie< BOOST_PP_ENUM_PARAMS(N, T) BOOST_PP_REPEAT_FROM_TO(BOOST_PP_DEC(N), FUSION_MAX_DEQUE_SIZE, TEXT, void_) > + #undef TEXT +#else + struct deque_tie +#endif + { + typedef deque type; + }; + } + + template + inline deque + deque_tie(BOOST_PP_ENUM_BINARY_PARAMS(N, T, & _)) + { + return deque( + BOOST_PP_ENUM_PARAMS(N, _)); + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/generation/ignore.hpp b/win32/include/boost/fusion/container/generation/ignore.hpp new file mode 100755 index 000000000..3e28b8060 --- /dev/null +++ b/win32/include/boost/fusion/container/generation/ignore.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2001 Doug Gregor + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_IGNORE_07192005_0329) +#define FUSION_IGNORE_07192005_0329 + +namespace boost { namespace fusion +{ + // Swallows any assignment (by Doug Gregor) + namespace detail + { + struct swallow_assign + { + template + swallow_assign const& + operator=(const T&) const + { + return *this; + } + }; + } + + // "ignore" allows tuple positions to be ignored when using "tie". + detail::swallow_assign const ignore = detail::swallow_assign(); +}} + +#endif diff --git a/win32/include/boost/fusion/container/generation/list_tie.hpp b/win32/include/boost/fusion/container/generation/list_tie.hpp new file mode 100755 index 000000000..dc80cd0a9 --- /dev/null +++ b/win32/include/boost/fusion/container/generation/list_tie.hpp @@ -0,0 +1,79 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_LIST_TIE_07192005_0109) +#define FUSION_LIST_TIE_07192005_0109 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + namespace result_of + { + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_LIST_SIZE, typename T, void_) + , typename Extra = void_ + > + struct list_tie; + } + +// $$$ shouldn't we remove_reference first to allow references? $$$ +#define BOOST_FUSION_REF(z, n, data) BOOST_PP_CAT(T, n)& + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_LIST_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_REF + +}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + namespace result_of + { + template +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + #define TEXT(z, n, text) , text + struct list_tie< BOOST_PP_ENUM_PARAMS(N, T) BOOST_PP_REPEAT_FROM_TO(BOOST_PP_DEC(N), FUSION_MAX_LIST_SIZE, TEXT, void_) > + #undef TEXT +#else + struct list_tie +#endif + { + typedef list type; + }; + } + + template + inline list + list_tie(BOOST_PP_ENUM_BINARY_PARAMS(N, T, & _)) + { + return list( + BOOST_PP_ENUM_PARAMS(N, _)); + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/generation/make_cons.hpp b/win32/include/boost/fusion/container/generation/make_cons.hpp new file mode 100755 index 000000000..9eab8015c --- /dev/null +++ b/win32/include/boost/fusion/container/generation/make_cons.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + Copyright (c) 2005 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_MAKE_CONS_07172005_0918) +#define FUSION_MAKE_CONS_07172005_0918 + +#include +#include + +namespace boost { namespace fusion +{ + struct nil; + + namespace result_of + { + template + struct make_cons + { + typedef cons::type, Cdr> type; + }; + } + + template + inline cons::type> + make_cons(Car const& car) + { + return cons::type>(car); + } + + template + inline cons::type, Cdr> + make_cons(Car const& car, Cdr const& cdr) + { + return cons::type, Cdr>(car, cdr); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/container/generation/make_deque.hpp b/win32/include/boost/fusion/container/generation/make_deque.hpp new file mode 100755 index 000000000..80197f3ae --- /dev/null +++ b/win32/include/boost/fusion/container/generation/make_deque.hpp @@ -0,0 +1,98 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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) +==============================================================================*/ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_MAKE_DEQUE_07162005_0243) +#define FUSION_MAKE_DEQUE_07162005_0243 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + namespace result_of + { + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_DEQUE_SIZE, typename T, void_) + , typename Extra = void_ + > + struct make_deque; + + template <> + struct make_deque<> + { + typedef deque<> type; + }; + } + + inline deque<> + make_deque() + { + return deque<>(); + } + +#define BOOST_FUSION_AS_FUSION_ELEMENT(z, n, data) \ + typename detail::as_fusion_element::type + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_DEQUE_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_AS_FUSION_ELEMENT + +}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + namespace result_of + { + template +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + #define TEXT(z, n, text) , text + struct make_deque< BOOST_PP_ENUM_PARAMS(N, T) BOOST_PP_REPEAT_FROM_TO(BOOST_PP_DEC(N), FUSION_MAX_DEQUE_SIZE, TEXT, void_) > + #undef TEXT +#else + struct make_deque +#endif + { + typedef deque type; + }; + } + + template + inline deque + make_deque(BOOST_PP_ENUM_BINARY_PARAMS(N, T, const& _)) + { + return deque( + BOOST_PP_ENUM_PARAMS(N, _)); + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/generation/make_list.hpp b/win32/include/boost/fusion/container/generation/make_list.hpp new file mode 100755 index 000000000..be7c93d67 --- /dev/null +++ b/win32/include/boost/fusion/container/generation/make_list.hpp @@ -0,0 +1,91 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_MAKE_LIST_07192005_1239) +#define FUSION_MAKE_LIST_07192005_1239 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + namespace result_of + { + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_LIST_SIZE, typename T, void_) + , typename Extra = void_ + > + struct make_list; + + template <> + struct make_list<> + { + typedef list<> type; + }; + } + + inline list<> + make_list() + { + return list<>(); + } + +#define BOOST_FUSION_AS_FUSION_ELEMENT(z, n, data) \ + typename detail::as_fusion_element::type + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_LIST_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_AS_FUSION_ELEMENT + +}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + namespace result_of + { + template +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + #define TEXT(z, n, text) , text + struct make_list< BOOST_PP_ENUM_PARAMS(N, T) BOOST_PP_REPEAT_FROM_TO(BOOST_PP_DEC(N), FUSION_MAX_LIST_SIZE, TEXT, void_) > + #undef TEXT +#else + struct make_list +#endif + { + typedef list type; + }; + } + + template + inline list + make_list(BOOST_PP_ENUM_BINARY_PARAMS(N, T, const& _)) + { + return list( + BOOST_PP_ENUM_PARAMS(N, _)); + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/generation/make_map.hpp b/win32/include/boost/fusion/container/generation/make_map.hpp new file mode 100755 index 000000000..08b7dfa40 --- /dev/null +++ b/win32/include/boost/fusion/container/generation/make_map.hpp @@ -0,0 +1,106 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_MAKE_MAP_07222005_1247) +#define FUSION_MAKE_MAP_07222005_1247 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + namespace result_of + { + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_VECTOR_SIZE, typename K, void_) + , BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_VECTOR_SIZE, typename D, void_) + , typename Extra = void_ + > + struct make_map; + + template <> + struct make_map<> + { + typedef map<> type; + }; + } + + inline map<> + make_map() + { + return map<>(); + } + +#define BOOST_FUSION_PAIR(z, n, data) \ + fusion::pair< \ + BOOST_PP_CAT(K, n) \ + , typename detail::as_fusion_element::type> + +#define BOOST_FUSION_MAKE_PAIR(z, n, data) \ + fusion::make_pair(BOOST_PP_CAT(_, n)) \ + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_VECTOR_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_PAIR +#undef BOOST_FUSION_MAKE_PAIR + +}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + namespace result_of + { + template < + BOOST_PP_ENUM_PARAMS(N, typename K) + , BOOST_PP_ENUM_PARAMS(N, typename D) + > +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + #define TEXT(z, n, text) , text + struct make_map + #undef TEXT +#else + struct make_map +#endif + { + typedef map type; + }; + } + + template < + BOOST_PP_ENUM_PARAMS(N, typename K) + , BOOST_PP_ENUM_PARAMS(N, typename D) + > + inline map + make_map(BOOST_PP_ENUM_BINARY_PARAMS(N, D, const& _)) + { + return map( + BOOST_PP_ENUM(N, BOOST_FUSION_MAKE_PAIR, _)); + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/generation/make_set.hpp b/win32/include/boost/fusion/container/generation/make_set.hpp new file mode 100755 index 000000000..683d0b5d0 --- /dev/null +++ b/win32/include/boost/fusion/container/generation/make_set.hpp @@ -0,0 +1,93 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_MAKE_SET_09162005_1125) +#define FUSION_MAKE_SET_09162005_1125 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + namespace result_of + { + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_VECTOR_SIZE, typename T, void_) + , typename Extra = void_ + > + struct make_set; + + template <> + struct make_set<> + { + typedef set<> type; + }; + } + + inline set<> + make_set() + { + return set<>(); + } + +#define BOOST_FUSION_AS_FUSION_ELEMENT(z, n, data) \ + typename detail::as_fusion_element::type + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_VECTOR_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_ELEMENT +#undef BOOST_FUSION_AS_ELEMENT + +}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + namespace result_of + { + template +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + #define TEXT(z, n, text) , text + struct make_set< BOOST_PP_ENUM_PARAMS(N, T) BOOST_PP_REPEAT_FROM_TO(BOOST_PP_DEC(N), FUSION_MAX_SET_SIZE, TEXT, void_) > + #undef TEXT +#else + struct make_set +#endif + { + typedef set type; + }; + } + + template + inline set + make_set(BOOST_PP_ENUM_BINARY_PARAMS(N, T, const& _)) + { + return set( + BOOST_PP_ENUM_PARAMS(N, _)); + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/generation/make_vector.hpp b/win32/include/boost/fusion/container/generation/make_vector.hpp new file mode 100755 index 000000000..0439ae6ce --- /dev/null +++ b/win32/include/boost/fusion/container/generation/make_vector.hpp @@ -0,0 +1,91 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_MAKE_VECTOR_07162005_0243) +#define FUSION_MAKE_VECTOR_07162005_0243 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + namespace result_of + { + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_VECTOR_SIZE, typename T, void_) + , typename Extra = void_ + > + struct make_vector; + + template <> + struct make_vector<> + { + typedef vector<> type; + }; + } + + inline vector<> + make_vector() + { + return vector<>(); + } + +#define BOOST_FUSION_AS_FUSION_ELEMENT(z, n, data) \ + typename detail::as_fusion_element::type + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_VECTOR_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_AS_FUSION_ELEMENT + +}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + namespace result_of + { + template +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + #define TEXT(z, n, text) , text + struct make_vector< BOOST_PP_ENUM_PARAMS(N, T) BOOST_PP_REPEAT_FROM_TO(BOOST_PP_DEC(N), FUSION_MAX_VECTOR_SIZE, TEXT, void_) > + #undef TEXT +#else + struct make_vector +#endif + { + typedef vector type; + }; + } + + template + inline vector + make_vector(BOOST_PP_ENUM_BINARY_PARAMS(N, T, const& _)) + { + return vector( + BOOST_PP_ENUM_PARAMS(N, _)); + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/generation/map_tie.hpp b/win32/include/boost/fusion/container/generation/map_tie.hpp new file mode 100755 index 000000000..7b1f477e3 --- /dev/null +++ b/win32/include/boost/fusion/container/generation/map_tie.hpp @@ -0,0 +1,110 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_MAP_TIE_20060814_1116) +#define FUSION_MAP_TIE_20060814_1116 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + namespace result_of + { + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_MAP_SIZE, typename K, void_) + , BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_MAP_SIZE, typename D, void_) + , typename Extra = void_ + > + struct map_tie; + + template <> + struct map_tie<> + { + typedef map<> type; + }; + } + + inline map<> + map_tie() + { + return map<>(); + } + +#define BOOST_FUSION_TIED_PAIR(z, n, data) \ + fusion::pair< \ + BOOST_PP_CAT(K, n) \ + , typename add_reference::type> + +#define BOOST_FUSION_PAIR_TIE(z, n, data) \ + fusion::pair_tie(BOOST_PP_CAT(_, n)) \ + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_MAP_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_PAIR +#undef BOOST_FUSION_MAKE_PAIR + +}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + namespace result_of + { + template < + BOOST_PP_ENUM_PARAMS(N, typename K) + , BOOST_PP_ENUM_PARAMS(N, typename D) + > +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + #define TEXT(z, n, text) , text + + struct map_tie + #undef TEXT +#else + struct map_tie +#endif + { + typedef map type; + }; + } + + template < + BOOST_PP_ENUM_PARAMS(N, typename K) + , BOOST_PP_ENUM_PARAMS(N, typename D) + > + inline map + map_tie(BOOST_PP_ENUM_BINARY_PARAMS(N, D, & _)) + { + return map( + BOOST_PP_ENUM(N, BOOST_FUSION_PAIR_TIE, _)); + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/generation/pair_tie.hpp b/win32/include/boost/fusion/container/generation/pair_tie.hpp new file mode 100755 index 000000000..d66900cb2 --- /dev/null +++ b/win32/include/boost/fusion/container/generation/pair_tie.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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_FUSION_PAIR_TIE_20060812_2058) +#define BOOST_FUSION_PAIR_TIE_20060812_2058 + +#include +#include + +namespace boost { namespace fusion { + + template + struct pair; + + namespace result_of + { + template + struct pair_tie + { + typedef fusion::pair type; + }; + } + + template + typename disable_if, typename result_of::pair_tie::type>::type + pair_tie(T& t) + { + return typename result_of::pair_tie::type(t); + } + + template + typename result_of::pair_tie::type + pair_tie(T const& t) + { + return typename result_of::pair_tie::type(t); + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/generation/vector_tie.hpp b/win32/include/boost/fusion/container/generation/vector_tie.hpp new file mode 100755 index 000000000..e07b40ebf --- /dev/null +++ b/win32/include/boost/fusion/container/generation/vector_tie.hpp @@ -0,0 +1,78 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_VECTOR_TIE_07192005_1242) +#define FUSION_VECTOR_TIE_07192005_1242 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + namespace result_of + { + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_VECTOR_SIZE, typename T, void_) + , typename Extra = void_ + > + struct vector_tie; + } + +#define BOOST_FUSION_REF(z, n, data) BOOST_PP_CAT(T, n)& + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_VECTOR_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_REF + +}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + namespace result_of + { + template +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + #define TEXT(z, n, text) , text + struct vector_tie< BOOST_PP_ENUM_PARAMS(N, T) BOOST_PP_REPEAT_FROM_TO(BOOST_PP_DEC(N), FUSION_MAX_VECTOR_SIZE, TEXT, void_) > + #undef TEXT +#else + struct vector_tie +#endif + { + typedef vector type; + }; + } + + template + inline vector + vector_tie(BOOST_PP_ENUM_BINARY_PARAMS(N, T, & _)) + { + return vector( + BOOST_PP_ENUM_PARAMS(N, _)); + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/list.hpp b/win32/include/boost/fusion/container/list.hpp new file mode 100755 index 000000000..5da732c57 --- /dev/null +++ b/win32/include/boost/fusion/container/list.hpp @@ -0,0 +1,17 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_CLASS_LIST_10022005_0605) +#define FUSION_SEQUENCE_CLASS_LIST_10022005_0605 + +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/container/list/cons.hpp b/win32/include/boost/fusion/container/list/cons.hpp new file mode 100755 index 000000000..09daf437b --- /dev/null +++ b/win32/include/boost/fusion/container/list/cons.hpp @@ -0,0 +1,143 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + Copyright (c) 2005 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_CONS_07172005_0843) +#define FUSION_CONS_07172005_0843 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + struct cons_tag; + struct forward_traversal_tag; + struct fusion_sequence_tag; + + struct nil : sequence_base + { + typedef mpl::int_<0> size; + typedef cons_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef mpl::false_ is_view; + typedef forward_traversal_tag category; + typedef void_ car_type; + typedef void_ cdr_type; + + nil() {} + + template + nil(Iterator const& iter, mpl::true_ /*this_is_an_iterator*/) + {} + + template + void assign_from_iter(Iterator const& iter) + { + } + }; + + template + struct cons : sequence_base > + { + typedef mpl::int_ size; + typedef cons_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef mpl::false_ is_view; + typedef forward_traversal_tag category; + typedef Car car_type; + typedef Cdr cdr_type; + + cons() + : car(), cdr() {} + + explicit cons(typename detail::call_param::type car) + : car(car), cdr() {} + + cons( + typename detail::call_param::type car + , typename detail::call_param::type cdr) + : car(car), cdr(cdr) {} + + template + cons(cons const& rhs) + : car(rhs.car), cdr(rhs.cdr) {} + + cons(cons const& rhs) + : car(rhs.car), cdr(rhs.cdr) {} + + template + cons( + Sequence const& seq + , typename disable_if< + mpl::or_< + is_convertible // use copy ctor instead + , is_convertible // use copy to car instead + > + >::type* dummy = 0 + ) + : car(*fusion::begin(seq)) + , cdr(fusion::next(fusion::begin(seq)), mpl::true_()) {} + + template + cons(Iterator const& iter, mpl::true_ /*this_is_an_iterator*/) + : car(*iter) + , cdr(fusion::next(iter), mpl::true_()) {} + + template + cons& operator=(cons const& rhs) + { + car = rhs.car; + cdr = rhs.cdr; + return *this; + } + + cons& operator=(cons const& rhs) + { + car = rhs.car; + cdr = rhs.cdr; + return *this; + } + + template + typename disable_if, cons&>::type + operator=(Sequence const& seq) + { + typedef typename result_of::begin::type Iterator; + Iterator iter = fusion::begin(seq); + this->assign_from_iter(iter); + return *this; + } + + template + void assign_from_iter(Iterator const& iter) + { + car = *iter; + cdr.assign_from_iter(fusion::next(iter)); + } + + car_type car; + cdr_type cdr; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/container/list/cons_iterator.hpp b/win32/include/boost/fusion/container/list/cons_iterator.hpp new file mode 100755 index 000000000..2fa1c63b1 --- /dev/null +++ b/win32/include/boost/fusion/container/list/cons_iterator.hpp @@ -0,0 +1,85 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + Copyright (c) 2005 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_CONS_ITERATOR_07172005_0849) +#define FUSION_CONS_ITERATOR_07172005_0849 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct nil; + struct cons_iterator_tag; + struct forward_traversal_tag; + + template + struct cons_iterator_identity; + + template + struct cons_iterator : iterator_base > + { + typedef cons_iterator_tag fusion_tag; + typedef forward_traversal_tag category; + typedef Cons cons_type; + typedef cons_iterator_identity< + typename add_const::type> + identity; + + explicit cons_iterator(cons_type& cons) + : cons(cons) {} + + cons_type& cons; + }; + + struct nil_iterator : iterator_base + { + typedef forward_traversal_tag category; + typedef cons_iterator_tag fusion_tag; + typedef nil cons_type; + typedef cons_iterator_identity< + add_const::type> + identity; + nil_iterator() {} + explicit nil_iterator(nil const&) {} + }; + + template <> + struct cons_iterator : nil_iterator + { + cons_iterator() {} + explicit cons_iterator(nil const&) {} + }; + + template <> + struct cons_iterator : nil_iterator + { + cons_iterator() {} + explicit cons_iterator(nil const&) {} + }; + + template <> + struct cons_iterator > : nil_iterator + { + cons_iterator() {} + explicit cons_iterator(nil const&) {} + }; + + template <> + struct cons_iterator const> : nil_iterator + { + cons_iterator() {} + explicit cons_iterator(nil const&) {} + }; +}} + +#endif diff --git a/win32/include/boost/fusion/container/list/convert.hpp b/win32/include/boost/fusion/container/list/convert.hpp new file mode 100755 index 000000000..61c371c53 --- /dev/null +++ b/win32/include/boost/fusion/container/list/convert.hpp @@ -0,0 +1,56 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_CONVERT_09232005_1215) +#define FUSION_CONVERT_09232005_1215 + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct as_list + { + typedef typename + detail::build_cons< + typename result_of::begin::type + , typename result_of::end::type + > + build_cons; + + typedef typename build_cons::type type; + + static type + call(Sequence& seq) + { + return build_cons::call(fusion::begin(seq), fusion::end(seq)); + } + }; + } + + template + inline typename result_of::as_list::type + as_list(Sequence& seq) + { + return result_of::as_list::call(seq); + } + + template + inline typename result_of::as_list::type + as_list(Sequence const& seq) + { + return result_of::as_list::call(seq); + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/list/detail/at_impl.hpp b/win32/include/boost/fusion/container/list/detail/at_impl.hpp new file mode 100755 index 000000000..593f01eef --- /dev/null +++ b/win32/include/boost/fusion/container/list/detail/at_impl.hpp @@ -0,0 +1,79 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_AT_IMPL_07172005_0726) +#define FUSION_AT_IMPL_07172005_0726 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct cons_tag; + + namespace extension + { + template + struct at_impl; + + template <> + struct at_impl + { + template + struct apply + { + typedef typename + mpl::eval_if< + is_const + , add_const + , mpl::identity + >::type + cdr_type; + + typedef typename + mpl::eval_if< + mpl::bool_ + , mpl::identity + , apply > + > + element; + + typedef typename + mpl::eval_if< + is_const + , detail::cref_result + , detail::ref_result + >::type + type; + + template + static type + call(Cons& s, mpl::int_) + { + return call(s.cdr, mpl::int_()); + } + + template + static type + call(Cons& s, mpl::int_<0>) + { + return s.car; + } + + static type + call(Sequence& s) + { + return call(s, mpl::int_()); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/list/detail/begin_impl.hpp b/win32/include/boost/fusion/container/list/detail/begin_impl.hpp new file mode 100755 index 000000000..2228d2671 --- /dev/null +++ b/win32/include/boost/fusion/container/list/detail/begin_impl.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + Copyright (c) 2005 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BEGIN_IMPL_07172005_0824) +#define FUSION_BEGIN_IMPL_07172005_0824 + +#include +#include + +namespace boost { namespace fusion +{ + struct nil; + + struct cons_tag; + + template + struct cons; + + template + struct cons_iterator; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef cons_iterator type; + + static type + call(Sequence& t) + { + return type(t); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/list/detail/build_cons.hpp b/win32/include/boost/fusion/container/list/detail/build_cons.hpp new file mode 100755 index 000000000..9abd1d916 --- /dev/null +++ b/win32/include/boost/fusion/container/list/detail/build_cons.hpp @@ -0,0 +1,57 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BUILD_CONS_09232005_1222) +#define FUSION_BUILD_CONS_09232005_1222 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template < + typename First + , typename Last + , bool is_empty = result_of::equal_to::value> + struct build_cons; + + template + struct build_cons + { + typedef nil type; + + static nil + call(First const&, Last const&) + { + return nil(); + } + }; + + template + struct build_cons + { + typedef + build_cons::type, Last> + next_build_cons; + + typedef cons< + typename result_of::value_of::type + , typename next_build_cons::type> + type; + + static type + call(First const& f, Last const& l) + { + return type(*f, next_build_cons::call(fusion::next(f), l)); + } + }; + +}}} + +#endif diff --git a/win32/include/boost/fusion/container/list/detail/convert_impl.hpp b/win32/include/boost/fusion/container/list/detail/convert_impl.hpp new file mode 100755 index 000000000..332f15b72 --- /dev/null +++ b/win32/include/boost/fusion/container/list/detail/convert_impl.hpp @@ -0,0 +1,51 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_CONVERT_IMPL_09232005_1215) +#define FUSION_CONVERT_IMPL_09232005_1215 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct cons_tag; + + namespace extension + { + template + struct convert_impl; + + template <> + struct convert_impl + { + template + struct apply + { + typedef typename + detail::build_cons< + typename result_of::begin::type + , typename result_of::end::type + > + build_cons; + + typedef typename build_cons::type type; + + static type + call(Sequence& seq) + { + return build_cons::call(fusion::begin(seq), fusion::end(seq)); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/list/detail/deref_impl.hpp b/win32/include/boost/fusion/container/list/detail/deref_impl.hpp new file mode 100755 index 000000000..1ab9f983f --- /dev/null +++ b/win32/include/boost/fusion/container/list/detail/deref_impl.hpp @@ -0,0 +1,52 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + Copyright (c) 2005 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_DEREF_IMPL_07172005_0831) +#define FUSION_DEREF_IMPL_07172005_0831 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct cons_iterator_tag; + + namespace extension + { + template + struct deref_impl; + + template <> + struct deref_impl + { + template + struct apply + { + typedef typename Iterator::cons_type cons_type; + typedef typename cons_type::car_type value_type; + + typedef typename mpl::eval_if< + is_const + , add_reference::type> + , add_reference >::type + type; + + static type + call(Iterator const& i) + { + return i.cons.car; + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/container/list/detail/empty_impl.hpp b/win32/include/boost/fusion/container/list/detail/empty_impl.hpp new file mode 100755 index 000000000..cf4f0976f --- /dev/null +++ b/win32/include/boost/fusion/container/list/detail/empty_impl.hpp @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + 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_FUSION_SEQUENCE_EMPTY_IMPL_HPP_INCLUDED) +#define BOOST_FUSION_SEQUENCE_EMPTY_IMPL_HPP_INCLUDED + +#include + +namespace boost { namespace fusion +{ + struct cons_tag; + + struct nil; + + template + struct cons; + + namespace extension + { + template + struct empty_impl; + + template <> + struct empty_impl + { + template + struct apply + : boost::is_convertible + {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/list/detail/end_impl.hpp b/win32/include/boost/fusion/container/list/detail/end_impl.hpp new file mode 100755 index 000000000..fa693d8a2 --- /dev/null +++ b/win32/include/boost/fusion/container/list/detail/end_impl.hpp @@ -0,0 +1,51 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + Copyright (c) 2005 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_END_IMPL_07172005_0828) +#define FUSION_END_IMPL_07172005_0828 + +#include +#include + +namespace boost { namespace fusion +{ + struct nil; + + struct cons_tag; + + template + struct cons; + + template + struct cons_iterator; + + namespace extension + { + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef cons_iterator< + typename mpl::if_, nil const, nil>::type> + type; + + static type + call(Sequence&) + { + return type(); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/list/detail/equal_to_impl.hpp b/win32/include/boost/fusion/container/list/detail/equal_to_impl.hpp new file mode 100755 index 000000000..6f4dad18c --- /dev/null +++ b/win32/include/boost/fusion/container/list/detail/equal_to_impl.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_EQUAL_TO_IMPL_09172005_1120) +#define FUSION_EQUAL_TO_IMPL_09172005_1120 + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct cons_iterator_tag; + + namespace extension + { + template + struct equal_to_impl; + + template <> + struct equal_to_impl + { + template + struct apply + : is_same< + typename I1::identity + , typename I2::identity + > + { + }; + }; + } +}} + +#endif + diff --git a/win32/include/boost/fusion/container/list/detail/list_forward_ctor.hpp b/win32/include/boost/fusion/container/list/detail/list_forward_ctor.hpp new file mode 100755 index 000000000..9fcee3d53 --- /dev/null +++ b/win32/include/boost/fusion/container/list/detail/list_forward_ctor.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_LIST_FORWARD_CTOR_07172005_0113) +#define FUSION_LIST_FORWARD_CTOR_07172005_0113 + +#include +#include +#include +#include +#include + +#define FUSION_LIST_CTOR_MAKE_CONS(z, n, type) tie_cons(BOOST_PP_CAT(_, n) +#define FUSION_LIST_CL_PAREN(z, n, type) ) + +#define BOOST_PP_FILENAME_1 \ + +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_LIST_SIZE) +#include BOOST_PP_ITERATE() + +#undef FUSION_LIST_CTOR_MAKE_CONS +#undef FUSION_LIST_CL_PAREN + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// +#define N BOOST_PP_ITERATION() + +#if N == 1 + explicit +#endif + list(BOOST_PP_ENUM_BINARY_PARAMS( + N, typename detail::call_param::type _)) + : inherited_type(list_to_cons::call(BOOST_PP_ENUM_PARAMS(N, _))) + {} + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/list/detail/list_to_cons.hpp b/win32/include/boost/fusion/container/list/detail/list_to_cons.hpp new file mode 100755 index 000000000..745d827d4 --- /dev/null +++ b/win32/include/boost/fusion/container/list/detail/list_to_cons.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_LIST_TO_CONS_07172005_1041) +#define FUSION_LIST_TO_CONS_07172005_1041 + +#include +#include +#include +#include +#include +#include + +#define FUSION_VOID(z, n, _) void_ + +namespace boost { namespace fusion +{ + struct nil; + struct void_; +}} + +namespace boost { namespace fusion { namespace detail +{ + template + struct list_to_cons + { + typedef T0 head_type; + typedef list_to_cons< + BOOST_PP_ENUM_SHIFTED_PARAMS(FUSION_MAX_LIST_SIZE, T), void_> + tail_list_to_cons; + typedef typename tail_list_to_cons::type tail_type; + + typedef cons type; + + #include + }; + + template <> + struct list_to_cons + { + typedef nil type; + }; +}}} + +#undef FUSION_VOID +#endif diff --git a/win32/include/boost/fusion/container/list/detail/list_to_cons_call.hpp b/win32/include/boost/fusion/container/list/detail/list_to_cons_call.hpp new file mode 100755 index 000000000..9c59dd2b8 --- /dev/null +++ b/win32/include/boost/fusion/container/list/detail/list_to_cons_call.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_LIST_TO_CONS_CALL_07192005_0138) +#define FUSION_LIST_TO_CONS_CALL_07192005_0138 + +#include +#include +#include + +#define BOOST_PP_FILENAME_1 \ + +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_LIST_SIZE) +#include BOOST_PP_ITERATE() + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// +#define N BOOST_PP_ITERATION() + + static type + call(BOOST_PP_ENUM_BINARY_PARAMS( + N, typename detail::call_param::type _)) + { + return type(_0 +#if N > 1 + , tail_list_to_cons::call(BOOST_PP_ENUM_SHIFTED_PARAMS(N, _))); +#else + ); +#endif + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/list/detail/next_impl.hpp b/win32/include/boost/fusion/container/list/detail/next_impl.hpp new file mode 100755 index 000000000..20acaa67a --- /dev/null +++ b/win32/include/boost/fusion/container/list/detail/next_impl.hpp @@ -0,0 +1,59 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + Copyright (c) 2005 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_NEXT_IMPL_07172005_0836) +#define FUSION_NEXT_IMPL_07172005_0836 + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct cons_iterator_tag; + + template + struct cons_iterator; + + namespace extension + { + template + struct next_impl; + + template <> + struct next_impl + { + template + struct apply + { + typedef typename Iterator::cons_type cons_type; + typedef typename cons_type::cdr_type cdr_type; + + typedef cons_iterator< + typename mpl::eval_if< + is_const + , add_const + , mpl::identity + >::type> + type; + + static type + call(Iterator const& i) + { + return type(i.cons.cdr); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/container/list/detail/value_at_impl.hpp b/win32/include/boost/fusion/container/list/detail/value_at_impl.hpp new file mode 100755 index 000000000..472a89db0 --- /dev/null +++ b/win32/include/boost/fusion/container/list/detail/value_at_impl.hpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VALUE_AT_IMPL_07172005_0952) +#define FUSION_VALUE_AT_IMPL_07172005_0952 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct cons_tag; + + namespace extension + { + template + struct value_at_impl; + + template <> + struct value_at_impl + { + template + struct apply + { + typedef typename + mpl::eval_if< + mpl::bool_ + , mpl::identity + , apply > + >::type + type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/list/detail/value_of_impl.hpp b/win32/include/boost/fusion/container/list/detail/value_of_impl.hpp new file mode 100755 index 000000000..01a14e504 --- /dev/null +++ b/win32/include/boost/fusion/container/list/detail/value_of_impl.hpp @@ -0,0 +1,36 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + Copyright (c) 2005 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VALUE_OF_IMPL_07172005_0838) +#define FUSION_VALUE_OF_IMPL_07172005_0838 + +namespace boost { namespace fusion +{ + struct cons_iterator_tag; + + namespace extension + { + template + struct value_of_impl; + + template <> + struct value_of_impl + { + template + struct apply + { + typedef typename Iterator::cons_type cons_type; + typedef typename cons_type::car_type type; + }; + }; + } + +}} + +#endif + + diff --git a/win32/include/boost/fusion/container/list/limits.hpp b/win32/include/boost/fusion/container/list/limits.hpp new file mode 100755 index 000000000..c84cfdb7f --- /dev/null +++ b/win32/include/boost/fusion/container/list/limits.hpp @@ -0,0 +1,19 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_LIST_LIMITS_07172005_0112) +#define FUSION_LIST_LIMITS_07172005_0112 + +#if !defined(FUSION_MAX_LIST_SIZE) +# define FUSION_MAX_LIST_SIZE 10 +#else +# if FUSION_MAX_LIST_SIZE < 3 +# undef FUSION_MAX_LIST_SIZE +# define FUSION_MAX_LIST_SIZE 10 +# endif +#endif + +#endif diff --git a/win32/include/boost/fusion/container/list/list.hpp b/win32/include/boost/fusion/container/list/list.hpp new file mode 100755 index 000000000..fa5226cfe --- /dev/null +++ b/win32/include/boost/fusion/container/list/list.hpp @@ -0,0 +1,68 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_LIST_07172005_1153) +#define FUSION_LIST_07172005_1153 + +#include +#include + +namespace boost { namespace fusion +{ + struct nil; + struct void_; + + template + struct list + : detail::list_to_cons::type + { + private: + typedef + detail::list_to_cons + list_to_cons; + + public: + typedef typename list_to_cons::type inherited_type; + + list() + : inherited_type() {} + + template + list(list const& rhs) + : inherited_type(rhs) {} + + template + list(Sequence const& rhs) + : inherited_type(rhs) {} + + // Expand a couple of forwarding constructors for arguments + // of type (T0), (T0, T1), (T0, T1, T2) etc. Exanple: + // + // list( + // typename detail::call_param::type _0 + // , typename detail::call_param::type _1) + // : inherited_type(list_to_cons::call(_0, _1)) {} + #include + + template + list& + operator=(list const& rhs) + { + inherited_type::operator=(rhs); + return *this; + } + + template + list& + operator=(T const& rhs) + { + inherited_type::operator=(rhs); + return *this; + } + }; +}} + +#endif diff --git a/win32/include/boost/fusion/container/list/list_fwd.hpp b/win32/include/boost/fusion/container/list/list_fwd.hpp new file mode 100755 index 000000000..283ba4401 --- /dev/null +++ b/win32/include/boost/fusion/container/list/list_fwd.hpp @@ -0,0 +1,24 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_LIST_FORWARD_07172005_0224) +#define FUSION_LIST_FORWARD_07172005_0224 + +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_LIST_SIZE, typename T, void_) + > + struct list; +}} + +#endif diff --git a/win32/include/boost/fusion/container/map.hpp b/win32/include/boost/fusion/container/map.hpp new file mode 100755 index 000000000..120772d26 --- /dev/null +++ b/win32/include/boost/fusion/container/map.hpp @@ -0,0 +1,15 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_CLASS_MAP_10022005_0606) +#define FUSION_SEQUENCE_CLASS_MAP_10022005_0606 + +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/container/map/convert.hpp b/win32/include/boost/fusion/container/map/convert.hpp new file mode 100755 index 000000000..860512ab8 --- /dev/null +++ b/win32/include/boost/fusion/container/map/convert.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_CONVERT_09232005_1340) +#define FUSION_CONVERT_09232005_1340 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct as_map + { + typedef typename detail::as_map::value> gen; + typedef typename gen:: + template apply::type>::type + type; + }; + } + + template + inline typename result_of::as_map::type + as_map(Sequence& seq) + { + typedef typename result_of::as_map::gen gen; + return gen::call(fusion::begin(seq)); + } + + template + inline typename result_of::as_map::type + as_map(Sequence const& seq) + { + typedef typename result_of::as_map::gen gen; + return gen::call(fusion::begin(seq)); + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/map/detail/as_map.hpp b/win32/include/boost/fusion/container/map/detail/as_map.hpp new file mode 100755 index 000000000..e1a6d4c2e --- /dev/null +++ b/win32/include/boost/fusion/container/map/detail/as_map.hpp @@ -0,0 +1,101 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_AS_MAP_0932005_1339) +#define FUSION_AS_MAP_0932005_1339 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct as_map; + + template <> + struct as_map<0> + { + template + struct apply + { + typedef map<> type; + }; + + template + static typename apply::type + call(Iterator) + { + return map<>(); + } + }; + +#define BOOST_FUSION_NEXT_ITERATOR(z, n, data) \ + typedef typename fusion::result_of::next::type \ + BOOST_PP_CAT(I, BOOST_PP_INC(n)); + +#define BOOST_FUSION_NEXT_CALL_ITERATOR(z, n, data) \ + typename gen::BOOST_PP_CAT(I, BOOST_PP_INC(n)) \ + BOOST_PP_CAT(i, BOOST_PP_INC(n)) = fusion::next(BOOST_PP_CAT(i, n)); + +#define BOOST_FUSION_VALUE_OF_ITERATOR(z, n, data) \ + typedef typename fusion::result_of::value_of::type \ + BOOST_PP_CAT(T, n); + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_MAP_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_NEXT_ITERATOR +#undef BOOST_FUSION_NEXT_CALL_ITERATOR +#undef BOOST_FUSION_VALUE_OF_ITERATOR + +}}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + template <> + struct as_map + { + template + struct apply + { + BOOST_PP_REPEAT(N, BOOST_FUSION_NEXT_ITERATOR, _) + BOOST_PP_REPEAT(N, BOOST_FUSION_VALUE_OF_ITERATOR, _) + typedef map type; + }; + + template + static typename apply::type + call(Iterator const& i0) + { + typedef apply gen; + typedef typename gen::type result; + BOOST_PP_REPEAT(BOOST_PP_DEC(N), BOOST_FUSION_NEXT_CALL_ITERATOR, _) + return result(BOOST_PP_ENUM_PARAMS(N, *i)); + } + }; + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/map/detail/at_key_impl.hpp b/win32/include/boost/fusion/container/map/detail/at_key_impl.hpp new file mode 100755 index 000000000..fba7d1389 --- /dev/null +++ b/win32/include/boost/fusion/container/map/detail/at_key_impl.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_AT_KEY_IMPL_05222005_0254) +#define FUSION_AT_KEY_IMPL_05222005_0254 + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct map_tag; + + namespace extension + { + template + struct at_key_impl; + + template <> + struct at_key_impl + { + template + struct apply + { + typedef typename Sequence::template meta_at_impl element; + + typedef typename + mpl::eval_if< + is_const + , detail::cref_result + , detail::ref_result + >::type + type; + + static type + call(Sequence& m) + { + return m.at_impl(mpl::identity()); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/map/detail/begin_impl.hpp b/win32/include/boost/fusion/container/map/detail/begin_impl.hpp new file mode 100755 index 000000000..f22483f0d --- /dev/null +++ b/win32/include/boost/fusion/container/map/detail/begin_impl.hpp @@ -0,0 +1,56 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BEGIN_IMPL_05222005_1108) +#define FUSION_BEGIN_IMPL_05222005_1108 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct map_tag; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef typename + result_of::begin::type + iterator_type; + + typedef typename + result_of::begin::type + const_iterator_type; + + typedef typename + mpl::eval_if< + is_const + , mpl::identity + , mpl::identity + >::type + type; + + static type + call(Sequence& m) + { + return fusion::begin(m.get_data()); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/map/detail/convert_impl.hpp b/win32/include/boost/fusion/container/map/detail/convert_impl.hpp new file mode 100755 index 000000000..d6d535030 --- /dev/null +++ b/win32/include/boost/fusion/container/map/detail/convert_impl.hpp @@ -0,0 +1,45 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_CONVERT_IMPL_09232005_1340) +#define FUSION_CONVERT_IMPL_09232005_1340 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct map_tag; + + namespace extension + { + template + struct convert_impl; + + template <> + struct convert_impl + { + template + struct apply + { + typedef typename detail::as_map::value> gen; + typedef typename gen:: + template apply::type>::type + type; + + static type call(Sequence& seq) + { + return gen::call(fusion::begin(seq)); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/map/detail/end_impl.hpp b/win32/include/boost/fusion/container/map/detail/end_impl.hpp new file mode 100755 index 000000000..f95de6278 --- /dev/null +++ b/win32/include/boost/fusion/container/map/detail/end_impl.hpp @@ -0,0 +1,53 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_END_IMPL_05222005_1108) +#define FUSION_END_IMPL_05222005_1108 + +#include + +namespace boost { namespace fusion +{ + struct map_tag; + + namespace extension + { + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef typename + result_of::end::type + iterator_type; + + typedef typename + result_of::end::type + const_iterator_type; + + typedef typename + mpl::eval_if< + is_const + , mpl::identity + , mpl::identity + >::type + type; + + static type + call(Sequence& m) + { + return fusion::end(m.get_data()); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/map/detail/lookup_key.hpp b/win32/include/boost/fusion/container/map/detail/lookup_key.hpp new file mode 100755 index 000000000..1d30e21ef --- /dev/null +++ b/win32/include/boost/fusion/container/map/detail/lookup_key.hpp @@ -0,0 +1,99 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_LOOKUP_KEY_07222005_1248) +#define FUSION_LOOKUP_KEY_07222005_1248 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; +}} + +namespace boost { namespace fusion { namespace detail +{ + template + struct map_data_type + { + typedef typename + add_reference< + typename T::second_type + >::type + type; + }; + + template <> + struct map_data_type + { + typedef void_& type; + }; + + template + struct map_const_data_type + { + typedef typename + add_reference< + typename add_const< + typename T::second_type + >::type + >::type + type; + }; + + template <> + struct map_const_data_type + { + typedef void_ const& type; + }; + + template + struct map_value_type + { + typedef typename T::second_type type; + }; + + template <> + struct map_value_type + { + typedef void_ type; + }; + + template + struct map_key_type + { + typedef typename T::first_type type; + }; + + template + struct map_key_type + { + typedef unknown_key type; + }; + + template + struct map_lookup_key + { + static RT + call(Vector& vec) + { + return vec.at_impl(mpl::int_()).second; + } + }; + + template + struct map_lookup_key, Vector> + { + static void_& + call(Vector& vec); // intentionally undefined + }; +}}} + +#endif + diff --git a/win32/include/boost/fusion/container/map/detail/map_forward_ctor.hpp b/win32/include/boost/fusion/container/map/detail/map_forward_ctor.hpp new file mode 100755 index 000000000..cea402f7d --- /dev/null +++ b/win32/include/boost/fusion/container/map/detail/map_forward_ctor.hpp @@ -0,0 +1,38 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_MAP_FORWARD_CTOR_07222005_0106) +#define FUSION_MAP_FORWARD_CTOR_07222005_0106 + +#include +#include +#include + +#define BOOST_PP_FILENAME_1 \ + +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_MAP_SIZE) +#include BOOST_PP_ITERATE() + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + +#if N == 1 + explicit +#endif + map(BOOST_PP_ENUM_BINARY_PARAMS(N, T, const& _)) + : data(BOOST_PP_ENUM_PARAMS(N, _)) {} + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/map/detail/map_lookup.hpp b/win32/include/boost/fusion/container/map/detail/map_lookup.hpp new file mode 100755 index 000000000..8372c142d --- /dev/null +++ b/win32/include/boost/fusion/container/map/detail/map_lookup.hpp @@ -0,0 +1,128 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_MAP_LOOKUP_07212005_1118) +#define FUSION_MAP_LOOKUP_07212005_1118 + +#include +#include +#include +#include +#include + +#if defined(BOOST_MSVC) && (BOOST_MSVC == 1310) +#pragma warning (push) +#pragma warning(disable: 4348) // redefinition of default parameter +#endif + + template + struct meta_at_impl + { + typedef void_ type; + }; + + template + struct meta_find_impl + { + typedef vector_iterator type; + }; + + template + struct meta_find_impl_const + { + typedef vector_iterator type; + }; + + template + vector_iterator + find_impl(mpl::identity) const + { + return vector_iterator(data); + } + + template + vector_iterator + find_impl(mpl::identity) + { + return vector_iterator(data); + } + +#define BOOST_PP_FILENAME_1 \ + +#define BOOST_PP_ITERATION_LIMITS (0, BOOST_PP_DEC(FUSION_MAX_MAP_SIZE)) +#include BOOST_PP_ITERATE() + +#if defined(BOOST_MSVC) && (BOOST_MSVC == 1310) +#pragma warning (pop) +#endif + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + template + struct meta_at_impl< + typename detail::map_key_type::type, dummy> + { + typedef typename detail::map_value_type::type type; + }; + + typename detail::map_data_type::type + at_impl(mpl::identity::type>) + { + return detail::map_lookup_key< + N + , typename detail::map_data_type::type + , typename detail::map_key_type::type + , storage_type>::call(data); + } + + typename detail::map_const_data_type::type + at_impl(mpl::identity::type>) const + { + return detail::map_lookup_key< + N + , typename detail::map_const_data_type::type + , typename detail::map_key_type::type + , storage_type const>::call(data); + } + + template + struct meta_find_impl< + typename detail::map_key_type::type, dummy> + { + typedef vector_iterator type; + }; + + template + struct meta_find_impl_const< + typename detail::map_key_type::type, dummy> + { + typedef vector_iterator type; + }; + + vector_iterator + find_impl(mpl::identity::type>) + { + return vector_iterator(data); + } + + vector_iterator + find_impl(mpl::identity::type>) const + { + return vector_iterator(data); + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/map/detail/value_at_key_impl.hpp b/win32/include/boost/fusion/container/map/detail/value_at_key_impl.hpp new file mode 100755 index 000000000..fa014ef7e --- /dev/null +++ b/win32/include/boost/fusion/container/map/detail/value_at_key_impl.hpp @@ -0,0 +1,33 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_VALUE_AT_KEY_IMPL_05222005_0325) +#define FUSION_VALUE_AT_KEY_IMPL_05222005_0325 + +namespace boost { namespace fusion +{ + struct map_tag; + + namespace extension + { + template + struct value_at_key_impl; + + template <> + struct value_at_key_impl + { + template + struct apply + { + typedef typename Sequence:: + template meta_at_impl::type type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/map/limits.hpp b/win32/include/boost/fusion/container/map/limits.hpp new file mode 100755 index 000000000..23d3e7fe3 --- /dev/null +++ b/win32/include/boost/fusion/container/map/limits.hpp @@ -0,0 +1,25 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_MAP_LIMITS_07212005_1104) +#define FUSION_MAP_LIMITS_07212005_1104 + +#include + +#if !defined(FUSION_MAX_MAP_SIZE) +# define FUSION_MAX_MAP_SIZE FUSION_MAX_VECTOR_SIZE +#else +# if FUSION_MAX_MAP_SIZE < 3 +# undef FUSION_MAX_MAP_SIZE +# if (FUSION_MAX_VECTOR_SIZE > 10) +# define FUSION_MAX_MAP_SIZE 10 +# else +# define FUSION_MAX_MAP_SIZE FUSION_MAX_VECTOR_SIZE +# endif +# endif +#endif + +#endif diff --git a/win32/include/boost/fusion/container/map/map.hpp b/win32/include/boost/fusion/container/map/map.hpp new file mode 100755 index 000000000..1d2285630 --- /dev/null +++ b/win32/include/boost/fusion/container/map/map.hpp @@ -0,0 +1,71 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_MAP_07212005_1106) +#define FUSION_MAP_07212005_1106 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + struct map_tag; + struct fusion_sequence_tag; + + template + struct map : sequence_base > + { + struct category : forward_traversal_tag, associative_sequence_tag {}; + + typedef map_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef mpl::false_ is_view; + + typedef vector< + BOOST_PP_ENUM_PARAMS(FUSION_MAX_MAP_SIZE, T)> + storage_type; + + typedef typename storage_type::size size; + + map() + : data() {} + + template + map(Sequence const& rhs) + : data(rhs) {} + + #include + #include + + template + map& + operator=(T const& rhs) + { + data = rhs; + return *this; + } + + storage_type& get_data() { return data; } + storage_type const& get_data() const { return data; } + + private: + + storage_type data; + }; +}} + +#endif diff --git a/win32/include/boost/fusion/container/map/map_fwd.hpp b/win32/include/boost/fusion/container/map/map_fwd.hpp new file mode 100755 index 000000000..6542a7e7a --- /dev/null +++ b/win32/include/boost/fusion/container/map/map_fwd.hpp @@ -0,0 +1,24 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_MAP_FORWARD_07212005_1105) +#define FUSION_MAP_FORWARD_07212005_1105 + +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_MAP_SIZE, typename T, void_) + > + struct map; +}} + +#endif diff --git a/win32/include/boost/fusion/container/set.hpp b/win32/include/boost/fusion/container/set.hpp new file mode 100755 index 000000000..b0620e356 --- /dev/null +++ b/win32/include/boost/fusion/container/set.hpp @@ -0,0 +1,15 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_CLASS_SET_10022005_0607) +#define FUSION_SEQUENCE_CLASS_SET_10022005_0607 + +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/container/set/convert.hpp b/win32/include/boost/fusion/container/set/convert.hpp new file mode 100755 index 000000000..d7da9e599 --- /dev/null +++ b/win32/include/boost/fusion/container/set/convert.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_CONVERT_09232005_1341) +#define FUSION_CONVERT_09232005_1341 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct as_set + { + typedef typename detail::as_set::value> gen; + typedef typename gen:: + template apply::type>::type + type; + }; + } + + template + inline typename result_of::as_set::type + as_set(Sequence& seq) + { + typedef typename result_of::as_set::gen gen; + return gen::call(fusion::begin(seq)); + } + + template + inline typename result_of::as_set::type + as_set(Sequence const& seq) + { + typedef typename result_of::as_set::gen gen; + return gen::call(fusion::begin(seq)); + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/set/detail/as_set.hpp b/win32/include/boost/fusion/container/set/detail/as_set.hpp new file mode 100755 index 000000000..536de9bc1 --- /dev/null +++ b/win32/include/boost/fusion/container/set/detail/as_set.hpp @@ -0,0 +1,101 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_AS_SET_0932005_1341) +#define FUSION_AS_SET_0932005_1341 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct as_set; + + template <> + struct as_set<0> + { + template + struct apply + { + typedef set<> type; + }; + + template + static typename apply::type + call(Iterator) + { + return set<>(); + } + }; + +#define BOOST_FUSION_NEXT_ITERATOR(z, n, data) \ + typedef typename fusion::result_of::next::type \ + BOOST_PP_CAT(I, BOOST_PP_INC(n)); + +#define BOOST_FUSION_NEXT_CALL_ITERATOR(z, n, data) \ + typename gen::BOOST_PP_CAT(I, BOOST_PP_INC(n)) \ + BOOST_PP_CAT(i, BOOST_PP_INC(n)) = fusion::next(BOOST_PP_CAT(i, n)); + +#define BOOST_FUSION_VALUE_OF_ITERATOR(z, n, data) \ + typedef typename fusion::result_of::value_of::type \ + BOOST_PP_CAT(T, n); + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_SET_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_NEXT_ITERATOR +#undef BOOST_FUSION_NEXT_CALL_ITERATOR +#undef BOOST_FUSION_VALUE_OF_ITERATOR + +}}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + template <> + struct as_set + { + template + struct apply + { + BOOST_PP_REPEAT(N, BOOST_FUSION_NEXT_ITERATOR, _) + BOOST_PP_REPEAT(N, BOOST_FUSION_VALUE_OF_ITERATOR, _) + typedef set type; + }; + + template + static typename apply::type + call(Iterator const& i0) + { + typedef apply gen; + typedef typename gen::type result; + BOOST_PP_REPEAT(BOOST_PP_DEC(N), BOOST_FUSION_NEXT_CALL_ITERATOR, _) + return result(BOOST_PP_ENUM_PARAMS(N, *i)); + } + }; + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/set/detail/at_key_impl.hpp b/win32/include/boost/fusion/container/set/detail/at_key_impl.hpp new file mode 100755 index 000000000..fd167a58c --- /dev/null +++ b/win32/include/boost/fusion/container/set/detail/at_key_impl.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_AT_KEY_IMPL_09162005_1118) +#define FUSION_AT_KEY_IMPL_09162005_1118 + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct set_tag; + + namespace extension + { + template + struct at_key_impl; + + template <> + struct at_key_impl + { + template + struct apply + { + typedef typename Sequence::template meta_at_impl element; + + typedef typename + mpl::eval_if< + is_const + , detail::cref_result + , detail::ref_result + >::type + type; + + static type + call(Sequence& s) + { + return s.at_impl(mpl::identity()); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/set/detail/begin_impl.hpp b/win32/include/boost/fusion/container/set/detail/begin_impl.hpp new file mode 100755 index 000000000..7dece64f9 --- /dev/null +++ b/win32/include/boost/fusion/container/set/detail/begin_impl.hpp @@ -0,0 +1,56 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BEGIN_IMPL_09162005_1120) +#define FUSION_BEGIN_IMPL_09162005_1120 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct set_tag; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef typename + result_of::begin::type + iterator_type; + + typedef typename + result_of::begin::type + const_iterator_type; + + typedef typename + mpl::eval_if< + is_const + , mpl::identity + , mpl::identity + >::type + type; + + static type + call(Sequence& s) + { + return fusion::begin(s.get_data()); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/set/detail/convert_impl.hpp b/win32/include/boost/fusion/container/set/detail/convert_impl.hpp new file mode 100755 index 000000000..e77bd8733 --- /dev/null +++ b/win32/include/boost/fusion/container/set/detail/convert_impl.hpp @@ -0,0 +1,45 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_CONVERT_IMPL_09232005_1341) +#define FUSION_CONVERT_IMPL_09232005_1341 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct set_tag; + + namespace extension + { + template + struct convert_impl; + + template <> + struct convert_impl + { + template + struct apply + { + typedef typename detail::as_set::value> gen; + typedef typename gen:: + template apply::type>::type + type; + + static type call(Sequence& seq) + { + return gen::call(fusion::begin(seq)); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/set/detail/end_impl.hpp b/win32/include/boost/fusion/container/set/detail/end_impl.hpp new file mode 100755 index 000000000..f01b4e468 --- /dev/null +++ b/win32/include/boost/fusion/container/set/detail/end_impl.hpp @@ -0,0 +1,53 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_END_IMPL_09162005_1121) +#define FUSION_END_IMPL_09162005_1121 + +#include + +namespace boost { namespace fusion +{ + struct set_tag; + + namespace extension + { + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef typename + result_of::end::type + iterator_type; + + typedef typename + result_of::end::type + const_iterator_type; + + typedef typename + mpl::eval_if< + is_const + , mpl::identity + , mpl::identity + >::type + type; + + static type + call(Sequence& s) + { + return fusion::end(s.get_data()); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/set/detail/lookup_key.hpp b/win32/include/boost/fusion/container/set/detail/lookup_key.hpp new file mode 100755 index 000000000..2af31ee3d --- /dev/null +++ b/win32/include/boost/fusion/container/set/detail/lookup_key.hpp @@ -0,0 +1,93 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_LOOKUP_KEY_09162005_1111) +#define FUSION_LOOKUP_KEY_09162005_1111 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; +}} + +namespace boost { namespace fusion { namespace detail +{ + template + struct set_data_type + { + typedef typename add_reference::type type; + }; + + template <> + struct set_data_type + { + typedef void_& type; + }; + + template + struct set_const_data_type + { + typedef typename + add_reference< + typename add_const::type + >::type + type; + }; + + template <> + struct set_const_data_type + { + typedef void_ const& type; + }; + + template + struct set_value_type + { + typedef T type; + }; + + template <> + struct set_value_type + { + typedef void_ type; + }; + + template + struct set_key_type + { + typedef T type; + }; + + template + struct set_key_type + { + typedef unknown_key type; + }; + + template + struct set_lookup_key + { + static RT + call(Vector& vec) + { + return vec.at_impl(mpl::int_()); + } + }; + + template + struct set_lookup_key, Vector> + { + static void_& + call(Vector& vec); // intentionally undefined + }; +}}} + +#endif + diff --git a/win32/include/boost/fusion/container/set/detail/set_forward_ctor.hpp b/win32/include/boost/fusion/container/set/detail/set_forward_ctor.hpp new file mode 100755 index 000000000..80b220743 --- /dev/null +++ b/win32/include/boost/fusion/container/set/detail/set_forward_ctor.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_SET_FORWARD_CTOR_09162005_1115) +#define FUSION_SET_FORWARD_CTOR_09162005_1115 + +#include +#include +#include + +#define BOOST_PP_FILENAME_1 \ + +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_SET_SIZE) +#include BOOST_PP_ITERATE() + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + +#if N == 1 + explicit +#endif + set(BOOST_PP_ENUM_BINARY_PARAMS( + N, typename detail::call_param::type _)) + : data(BOOST_PP_ENUM_PARAMS(N, _)) {} + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/set/detail/set_lookup.hpp b/win32/include/boost/fusion/container/set/detail/set_lookup.hpp new file mode 100755 index 000000000..59e9a776f --- /dev/null +++ b/win32/include/boost/fusion/container/set/detail/set_lookup.hpp @@ -0,0 +1,128 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_SET_LOOKUP_09162005_1116) +#define FUSION_SET_LOOKUP_09162005_1116 + +#include +#include +#include +#include +#include + +#if defined(BOOST_MSVC) && (BOOST_MSVC == 1310) +#pragma warning (push) +#pragma warning(disable: 4348) // redefinition of default parameter +#endif + + template + struct meta_at_impl + { + typedef void_ type; + }; + + template + struct meta_find_impl + { + typedef vector_iterator type; + }; + + template + struct meta_find_impl_const + { + typedef vector_iterator type; + }; + + template + vector_iterator + find_impl(mpl::identity) const + { + return vector_iterator(data); + } + + template + vector_iterator + find_impl(mpl::identity) + { + return vector_iterator(data); + } + +#define BOOST_PP_FILENAME_1 \ + +#define BOOST_PP_ITERATION_LIMITS (0, BOOST_PP_DEC(FUSION_MAX_SET_SIZE)) +#include BOOST_PP_ITERATE() + +#if defined(BOOST_MSVC) && (BOOST_MSVC == 1310) +#pragma warning (pop) +#endif + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + template + struct meta_at_impl< + typename detail::set_key_type::type, dummy> + { + typedef typename detail::set_value_type::type type; + }; + + typename detail::set_data_type::type + at_impl(mpl::identity::type>) + { + return detail::set_lookup_key< + N + , typename detail::set_data_type::type + , typename detail::set_key_type::type + , storage_type>::call(data); + } + + typename detail::set_const_data_type::type + at_impl(mpl::identity::type>) const + { + return detail::set_lookup_key< + N + , typename detail::set_const_data_type::type + , typename detail::set_key_type::type + , storage_type const>::call(data); + } + + template + struct meta_find_impl< + typename detail::set_key_type::type, dummy> + { + typedef vector_iterator type; + }; + + template + struct meta_find_impl_const< + typename detail::set_key_type::type, dummy> + { + typedef vector_iterator type; + }; + + vector_iterator + find_impl(mpl::identity::type>) + { + return vector_iterator(data); + } + + vector_iterator + find_impl(mpl::identity::type>) const + { + return vector_iterator(data); + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/set/detail/value_at_key_impl.hpp b/win32/include/boost/fusion/container/set/detail/value_at_key_impl.hpp new file mode 100755 index 000000000..4fbd726bd --- /dev/null +++ b/win32/include/boost/fusion/container/set/detail/value_at_key_impl.hpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_VALUE_AT_KEY_IMPL_09162005_1123) +#define FUSION_VALUE_AT_KEY_IMPL_09162005_1123 + +#include + +namespace boost { namespace fusion +{ + struct set_tag; + + namespace extension + { + template + struct value_at_key_impl; + + template <> + struct value_at_key_impl + { + template + struct apply + { + typedef typename Sequence:: + template meta_at_impl::type type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/set/limits.hpp b/win32/include/boost/fusion/container/set/limits.hpp new file mode 100755 index 000000000..7bc590abc --- /dev/null +++ b/win32/include/boost/fusion/container/set/limits.hpp @@ -0,0 +1,25 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SET_LIMITS_09162005_1103) +#define FUSION_SET_LIMITS_09162005_1103 + +#include + +#if !defined(FUSION_MAX_SET_SIZE) +# define FUSION_MAX_SET_SIZE FUSION_MAX_VECTOR_SIZE +#else +# if FUSION_MAX_SET_SIZE < 3 +# undef FUSION_MAX_SET_SIZE +# if (FUSION_MAX_VECTOR_SIZE > 10) +# define FUSION_MAX_SET_SIZE 10 +# else +# define FUSION_MAX_SET_SIZE FUSION_MAX_VECTOR_SIZE +# endif +# endif +#endif + +#endif diff --git a/win32/include/boost/fusion/container/set/set.hpp b/win32/include/boost/fusion/container/set/set.hpp new file mode 100755 index 000000000..08e5bf138 --- /dev/null +++ b/win32/include/boost/fusion/container/set/set.hpp @@ -0,0 +1,71 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SET_09162005_1104) +#define FUSION_SET_09162005_1104 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + struct set_tag; + struct fusion_sequence_tag; + + template + struct set : sequence_base > + { + struct category : forward_traversal_tag, associative_sequence_tag {}; + + typedef set_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef mpl::false_ is_view; + + typedef vector< + BOOST_PP_ENUM_PARAMS(FUSION_MAX_SET_SIZE, T)> + storage_type; + + typedef typename storage_type::size size; + + set() + : data() {} + + template + set(Sequence const& rhs) + : data(rhs) {} + + #include + #include + + template + set& + operator=(T const& rhs) + { + data = rhs; + return *this; + } + + storage_type& get_data() { return data; } + storage_type const& get_data() const { return data; } + + private: + + storage_type data; + }; +}} + +#endif diff --git a/win32/include/boost/fusion/container/set/set_fwd.hpp b/win32/include/boost/fusion/container/set/set_fwd.hpp new file mode 100755 index 000000000..522dd6cdd --- /dev/null +++ b/win32/include/boost/fusion/container/set/set_fwd.hpp @@ -0,0 +1,24 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SET_FORWARD_09162005_1102) +#define FUSION_SET_FORWARD_09162005_1102 + +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_SET_SIZE, typename T, void_) + > + struct set; +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector.hpp b/win32/include/boost/fusion/container/vector.hpp new file mode 100755 index 000000000..975578637 --- /dev/null +++ b/win32/include/boost/fusion/container/vector.hpp @@ -0,0 +1,21 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_CLASS_VECTOR_10022005_0602) +#define FUSION_SEQUENCE_CLASS_VECTOR_10022005_0602 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/container/vector/convert.hpp b/win32/include/boost/fusion/container/vector/convert.hpp new file mode 100755 index 000000000..8a49d5d5d --- /dev/null +++ b/win32/include/boost/fusion/container/vector/convert.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_CONVERT_09222005_1104) +#define FUSION_CONVERT_09222005_1104 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template + struct as_vector + { + typedef typename detail::as_vector::value> gen; + typedef typename gen:: + template apply::type>::type + type; + }; + } + + template + inline typename result_of::as_vector::type + as_vector(Sequence& seq) + { + typedef typename result_of::as_vector::gen gen; + return gen::call(fusion::begin(seq)); + } + + template + inline typename result_of::as_vector::type + as_vector(Sequence const& seq) + { + typedef typename result_of::as_vector::gen gen; + return gen::call(fusion::begin(seq)); + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector/detail/advance_impl.hpp b/win32/include/boost/fusion/container/vector/detail/advance_impl.hpp new file mode 100755 index 000000000..348d6b04f --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/advance_impl.hpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ADVANCE_IMPL_09172005_1156) +#define FUSION_ADVANCE_IMPL_09172005_1156 + +namespace boost { namespace fusion +{ + struct vector_iterator_tag; + + template + struct vector_iterator; + + namespace extension + { + template + struct advance_impl; + + template <> + struct advance_impl + { + template + struct apply + { + typedef typename Iterator::index index; + typedef typename Iterator::vector vector; + typedef vector_iterator type; + + static type + call(Iterator const& i) + { + return type(i.vec); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector/detail/as_vector.hpp b/win32/include/boost/fusion/container/vector/detail/as_vector.hpp new file mode 100755 index 000000000..8def5eb9e --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/as_vector.hpp @@ -0,0 +1,101 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_AS_VECTOR_09222005_0950) +#define FUSION_AS_VECTOR_09222005_0950 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct as_vector; + + template <> + struct as_vector<0> + { + template + struct apply + { + typedef vector<> type; + }; + + template + static typename apply::type + call(Iterator) + { + return vector<>(); + } + }; + +#define BOOST_FUSION_NEXT_ITERATOR(z, n, data) \ + typedef typename fusion::result_of::next::type \ + BOOST_PP_CAT(I, BOOST_PP_INC(n)); + +#define BOOST_FUSION_NEXT_CALL_ITERATOR(z, n, data) \ + typename gen::BOOST_PP_CAT(I, BOOST_PP_INC(n)) \ + BOOST_PP_CAT(i, BOOST_PP_INC(n)) = fusion::next(BOOST_PP_CAT(i, n)); + +#define BOOST_FUSION_VALUE_OF_ITERATOR(z, n, data) \ + typedef typename fusion::result_of::value_of::type \ + BOOST_PP_CAT(T, n); + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_VECTOR_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_NEXT_ITERATOR +#undef BOOST_FUSION_NEXT_CALL_ITERATOR +#undef BOOST_FUSION_VALUE_OF_ITERATOR + +}}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + template <> + struct as_vector + { + template + struct apply + { + BOOST_PP_REPEAT(N, BOOST_FUSION_NEXT_ITERATOR, _) + BOOST_PP_REPEAT(N, BOOST_FUSION_VALUE_OF_ITERATOR, _) + typedef vector type; + }; + + template + static typename apply::type + call(Iterator const& i0) + { + typedef apply gen; + typedef typename gen::type result; + BOOST_PP_REPEAT(BOOST_PP_DEC(N), BOOST_FUSION_NEXT_CALL_ITERATOR, _) + return result(BOOST_PP_ENUM_PARAMS(N, *i)); + } + }; + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/vector/detail/at_impl.hpp b/win32/include/boost/fusion/container/vector/detail/at_impl.hpp new file mode 100755 index 000000000..4c4736817 --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/at_impl.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_AT_IMPL_05042005_0741) +#define FUSION_AT_IMPL_05042005_0741 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct vector_tag; + + namespace extension + { + template + struct at_impl; + + template <> + struct at_impl + { + template + struct apply + { + typedef mpl::at element; + typedef typename + mpl::eval_if< + is_const + , detail::cref_result + , detail::ref_result + >::type + type; + + static type + call(Sequence& v) + { + return v.at_impl(N()); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector/detail/begin_impl.hpp b/win32/include/boost/fusion/container/vector/detail/begin_impl.hpp new file mode 100755 index 000000000..5d397e48f --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/begin_impl.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BEGIN_IMPL_05042005_1136) +#define FUSION_BEGIN_IMPL_05042005_1136 + +#include + +namespace boost { namespace fusion +{ + struct vector_tag; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef vector_iterator type; + + static type + call(Sequence& v) + { + return type(v); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector/detail/convert_impl.hpp b/win32/include/boost/fusion/container/vector/detail/convert_impl.hpp new file mode 100755 index 000000000..7a29baf3a --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/convert_impl.hpp @@ -0,0 +1,45 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_CONVERT_IMPL_09222005_1104) +#define FUSION_CONVERT_IMPL_09222005_1104 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct vector_tag; + + namespace extension + { + template + struct convert_impl; + + template <> + struct convert_impl + { + template + struct apply + { + typedef typename detail::as_vector::value> gen; + typedef typename gen:: + template apply::type>::type + type; + + static type call(Sequence& seq) + { + return gen::call(fusion::begin(seq)); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector/detail/deref_impl.hpp b/win32/include/boost/fusion/container/vector/detail/deref_impl.hpp new file mode 100755 index 000000000..d88f2558e --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/deref_impl.hpp @@ -0,0 +1,53 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_DEREF_IMPL_05042005_1037) +#define FUSION_DEREF_IMPL_05042005_1037 + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct vector_iterator_tag; + + namespace extension + { + template + struct deref_impl; + + template <> + struct deref_impl + { + template + struct apply + { + typedef typename Iterator::vector vector; + typedef typename Iterator::index index; + typedef typename mpl::at< + typename vector::types, index> + element; + + typedef typename + mpl::eval_if< + is_const + , fusion::detail::cref_result + , fusion::detail::ref_result + >::type + type; + + static type + call(Iterator const& i) + { + return i.vec.at_impl(index()); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector/detail/distance_impl.hpp b/win32/include/boost/fusion/container/vector/detail/distance_impl.hpp new file mode 100755 index 000000000..c61d6c6df --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/distance_impl.hpp @@ -0,0 +1,41 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_DISTANCE_IMPL_09172005_0751) +#define FUSION_DISTANCE_IMPL_09172005_0751 + +#include + +namespace boost { namespace fusion +{ + struct vector_iterator_tag; + + namespace extension + { + template + struct distance_impl; + + template <> + struct distance_impl + { + template + struct apply : mpl::minus + { + static typename mpl::minus< + typename Last::index, typename First::index>::type + call(First const&, Last const&) + { + typedef typename mpl::minus< + typename Last::index, typename First::index>::type + result; + return result(); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector/detail/end_impl.hpp b/win32/include/boost/fusion/container/vector/detail/end_impl.hpp new file mode 100755 index 000000000..9d5f864ba --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/end_impl.hpp @@ -0,0 +1,40 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_END_IMPL_05042005_1142) +#define FUSION_END_IMPL_05042005_1142 + +#include + +namespace boost { namespace fusion +{ + struct vector_tag; + + namespace extension + { + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef typename Sequence::size size; + typedef vector_iterator type; + + static type + call(Sequence& v) + { + return type(v); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector/detail/equal_to_impl.hpp b/win32/include/boost/fusion/container/vector/detail/equal_to_impl.hpp new file mode 100755 index 000000000..612751bfe --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/equal_to_impl.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_EQUAL_TO_IMPL_05052005_1215) +#define FUSION_EQUAL_TO_IMPL_05052005_1215 + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct vector_iterator_tag; + + namespace extension + { + template + struct equal_to_impl; + + template <> + struct equal_to_impl + { + template + struct apply + : is_same< + typename I1::identity + , typename I2::identity + > + { + }; + }; + } +}} + +#endif + diff --git a/win32/include/boost/fusion/container/vector/detail/next_impl.hpp b/win32/include/boost/fusion/container/vector/detail/next_impl.hpp new file mode 100755 index 000000000..8ab794cfa --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/next_impl.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_NEXT_IMPL_05042005_1058) +#define FUSION_NEXT_IMPL_05042005_1058 + +#include + +namespace boost { namespace fusion +{ + struct vector_iterator_tag; + template + struct vector_iterator; + + namespace extension + { + template + struct next_impl; + + template <> + struct next_impl + { + template + struct apply + { + typedef typename Iterator::vector vector; + typedef typename Iterator::index index; + typedef vector_iterator type; + + static type + call(Iterator const& i) + { + return type(i.vec); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector/detail/prior_impl.hpp b/win32/include/boost/fusion/container/vector/detail/prior_impl.hpp new file mode 100755 index 000000000..4251b511c --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/prior_impl.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_PRIOR_IMPL_05042005_1145) +#define FUSION_PRIOR_IMPL_05042005_1145 + +#include + +namespace boost { namespace fusion +{ + struct vector_iterator_tag; + template + struct vector_iterator; + + namespace extension + { + template + struct prior_impl; + + template <> + struct prior_impl + { + template + struct apply + { + typedef typename Iterator::vector vector; + typedef typename Iterator::index index; + typedef vector_iterator type; + + static type + call(Iterator const& i) + { + return type(i.vec); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector/detail/value_at_impl.hpp b/win32/include/boost/fusion/container/vector/detail/value_at_impl.hpp new file mode 100755 index 000000000..9c6b894f5 --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/value_at_impl.hpp @@ -0,0 +1,33 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VALUE_AT_IMPL_05052005_0232) +#define FUSION_VALUE_AT_IMPL_05052005_0232 + +#include + +namespace boost { namespace fusion +{ + struct vector_tag; + + namespace extension + { + template + struct value_at_impl; + + template <> + struct value_at_impl + { + template + struct apply + { + typedef typename mpl::at::type type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector/detail/value_of_impl.hpp b/win32/include/boost/fusion/container/vector/detail/value_of_impl.hpp new file mode 100755 index 000000000..4b6613be8 --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/value_of_impl.hpp @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VALUE_OF_IMPL_05052005_1128) +#define FUSION_VALUE_OF_IMPL_05052005_1128 + +#include + +namespace boost { namespace fusion +{ + struct vector_iterator_tag; + + namespace extension + { + template + struct value_of_impl; + + template <> + struct value_of_impl + { + template + struct apply + { + typedef typename Iterator::vector vector; + typedef typename Iterator::index index; + typedef typename mpl::at< + typename vector::types, index>::type + type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector/detail/vector_forward_ctor.hpp b/win32/include/boost/fusion/container/vector/detail/vector_forward_ctor.hpp new file mode 100755 index 000000000..d5c8b3c76 --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/vector_forward_ctor.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_VECTOR_FORWARD_CTOR_07122005_1123) +#define FUSION_VECTOR_FORWARD_CTOR_07122005_1123 + +#include +#include +#include + +#define BOOST_PP_FILENAME_1 \ + +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_VECTOR_SIZE) +#include BOOST_PP_ITERATE() + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + +#if N == 1 + explicit +#endif + vector(BOOST_PP_ENUM_BINARY_PARAMS( + N, typename detail::call_param::type _)) + : vec(BOOST_PP_ENUM_PARAMS(N, _)) {} + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/container/vector/detail/vector_n.hpp b/win32/include/boost/fusion/container/vector/detail/vector_n.hpp new file mode 100755 index 000000000..9a12966d6 --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/vector_n.hpp @@ -0,0 +1,150 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +// No include guard. This file is meant to be included many times + +#if !defined(FUSION_MACRO_05042005) +#define FUSION_MACRO_05042005 + +#define FUSION_MEMBER_DEFAULT_INIT(z, n, _) m##n(T##n()) +#define FUSION_MEMBER_INIT(z, n, _) m##n(_##n) +#define FUSION_COPY_INIT(z, n, _) m##n(other.m##n) +#define FUSION_MEMBER_DECL(z, n, _) T##n m##n; + +#define FUSION_MEMBER_ASSIGN(z, n, _) \ + this->BOOST_PP_CAT(m, n) = vec.BOOST_PP_CAT(m, n); + +#define FUSION_DEREF_MEMBER_ASSIGN(z, n, _) \ + this->BOOST_PP_CAT(m, n) = *BOOST_PP_CAT(i, n); + +#define FUSION_AT_IMPL(z, n, _) \ + typename add_reference::type \ + at_impl(mpl::int_) { return this->m##n; } \ + typename add_reference::type>::type \ + at_impl(mpl::int_) const { return this->m##n; } + +#define FUSION_ITER_DECL_VAR(z, n, _) \ + typedef typename result_of::next< \ + BOOST_PP_CAT(I, BOOST_PP_DEC(n))>::type BOOST_PP_CAT(I, n); \ + BOOST_PP_CAT(I, n) BOOST_PP_CAT(i, n) \ + = fusion::next(BOOST_PP_CAT(i, BOOST_PP_DEC(n))); + +#endif + +#define N BOOST_PP_ITERATION() + + template + struct BOOST_PP_CAT(vector_data, N) : sequence_base + { + BOOST_PP_CAT(vector_data, N)() + : BOOST_PP_ENUM(N, FUSION_MEMBER_DEFAULT_INIT, _) {} + + BOOST_PP_CAT(vector_data, N)( + BOOST_PP_ENUM_BINARY_PARAMS( + N, typename detail::call_param::type _)) + : BOOST_PP_ENUM(N, FUSION_MEMBER_INIT, _) {} + + BOOST_PP_CAT(vector_data, N)( + BOOST_PP_CAT(vector_data, N) const& other) + : BOOST_PP_ENUM(N, FUSION_COPY_INIT, _) {} + + BOOST_PP_CAT(vector_data, N)& + operator=(BOOST_PP_CAT(vector_data, N) const& vec) + { + BOOST_PP_REPEAT(N, FUSION_MEMBER_ASSIGN, _) + return *this; + } + + template + static BOOST_PP_CAT(vector_data, N) + init_from_sequence(Sequence const& seq) + { + typedef typename result_of::begin::type I0; + I0 i0 = fusion::begin(seq); + BOOST_PP_REPEAT_FROM_TO(1, N, FUSION_ITER_DECL_VAR, _) + return BOOST_PP_CAT(vector_data, N)(BOOST_PP_ENUM_PARAMS(N, *i)); + } + + BOOST_PP_REPEAT(N, FUSION_MEMBER_DECL, _) + }; + + template + struct BOOST_PP_CAT(vector, N) + : BOOST_PP_CAT(vector_data, N)< + BOOST_PP_CAT(vector, N) + , BOOST_PP_ENUM_PARAMS(N, T)> + { + typedef BOOST_PP_CAT(vector, N) this_type; + typedef BOOST_PP_CAT(vector_data, N) base_type; + typedef mpl::BOOST_PP_CAT(vector, N) types; + typedef vector_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef mpl::false_ is_view; + typedef random_access_traversal_tag category; + typedef mpl::int_ size; + + BOOST_PP_CAT(vector, N)() {} + +#if (N == 1) + explicit +#endif + BOOST_PP_CAT(vector, N)( + BOOST_PP_ENUM_BINARY_PARAMS( + N, typename detail::call_param::type _)) + : base_type(BOOST_PP_ENUM_PARAMS(N, _)) {} + + template + BOOST_PP_CAT(vector, N)( + BOOST_PP_CAT(vector, N) const& vec) + : base_type(BOOST_PP_ENUM_PARAMS(N, vec.m)) {} + + template + BOOST_PP_CAT(vector, N)( + Sequence const& seq +#if (N == 1) + , typename disable_if >::type* dummy = 0 +#endif + ) + : base_type(base_type::init_from_sequence(seq)) {} + + template + BOOST_PP_CAT(vector, N)& + operator=(BOOST_PP_CAT(vector, N) const& vec) + { + BOOST_PP_REPEAT(N, FUSION_MEMBER_ASSIGN, _) + return *this; + } + + template + typename disable_if, this_type&>::type + operator=(Sequence const& seq) + { + typedef typename result_of::begin::type I0; + I0 i0 = fusion::begin(seq); + BOOST_PP_REPEAT_FROM_TO(1, N, FUSION_ITER_DECL_VAR, _) + BOOST_PP_REPEAT(N, FUSION_DEREF_MEMBER_ASSIGN, _) + return *this; + } + + BOOST_PP_REPEAT(N, FUSION_AT_IMPL, _) + + template + typename add_reference::type>::type + at_impl(I i) + { + return this->at_impl(mpl::int_()); + } + + template + typename add_reference::type>::type>::type + at_impl(I i) const + { + return this->at_impl(mpl::int_()); + } + }; + +#undef N + diff --git a/win32/include/boost/fusion/container/vector/detail/vector_n_chooser.hpp b/win32/include/boost/fusion/container/vector/detail/vector_n_chooser.hpp new file mode 100755 index 000000000..66691fbd3 --- /dev/null +++ b/win32/include/boost/fusion/container/vector/detail/vector_n_chooser.hpp @@ -0,0 +1,99 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_VECTOR_N_CHOOSER_07072005_1248) +#define FUSION_VECTOR_N_CHOOSER_07072005_1248 + +#include + +// include vector0..N where N is FUSION_MAX_VECTOR_SIZE +#include +#if (FUSION_MAX_VECTOR_SIZE > 10) +#include +#endif +#if (FUSION_MAX_VECTOR_SIZE > 20) +#include +#endif +#if (FUSION_MAX_VECTOR_SIZE > 30) +#include +#endif +#if (FUSION_MAX_VECTOR_SIZE > 40) +#include +#endif + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; +}} + +namespace boost { namespace fusion { namespace detail +{ + template + struct get_vector_n; + + template <> + struct get_vector_n<0> + { + template + struct call + { + typedef vector0 type; + }; + }; + +#define BOOST_PP_FILENAME_1 \ + +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_VECTOR_SIZE) +#include BOOST_PP_ITERATE() + + template + struct vector_n_chooser + { + typedef + mpl::BOOST_PP_CAT(vector, FUSION_MAX_VECTOR_SIZE) + + input; + + typedef typename mpl::begin::type begin; + typedef typename mpl::find::type end; + typedef typename mpl::distance::type size; + + typedef typename get_vector_n::template + call::type + type; + }; +}}} + +#endif + +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// +#else // defined(BOOST_PP_IS_ITERATING) + +#define N BOOST_PP_ITERATION() + + template <> + struct get_vector_n + { + template + struct call + { + typedef BOOST_PP_CAT(vector, N) type; + }; + }; + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) diff --git a/win32/include/boost/fusion/container/vector/limits.hpp b/win32/include/boost/fusion/container/vector/limits.hpp new file mode 100755 index 000000000..be00c6558 --- /dev/null +++ b/win32/include/boost/fusion/container/vector/limits.hpp @@ -0,0 +1,19 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VECTOR_LIMITS_07072005_1246) +#define FUSION_VECTOR_LIMITS_07072005_1246 + +#if !defined(FUSION_MAX_VECTOR_SIZE) +# define FUSION_MAX_VECTOR_SIZE 10 +#else +# if FUSION_MAX_VECTOR_SIZE < 3 +# undef FUSION_MAX_VECTOR_SIZE +# define FUSION_MAX_VECTOR_SIZE 10 +# endif +#endif + +#endif diff --git a/win32/include/boost/fusion/container/vector/vector.hpp b/win32/include/boost/fusion/container/vector/vector.hpp new file mode 100755 index 000000000..6e1336761 --- /dev/null +++ b/win32/include/boost/fusion/container/vector/vector.hpp @@ -0,0 +1,151 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VECTOR_07072005_1244) +#define FUSION_VECTOR_07072005_1244 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + struct fusion_sequence_tag; + + template + struct vector + : sequence_base > + { + private: + + typedef typename detail::vector_n_chooser< + BOOST_PP_ENUM_PARAMS(FUSION_MAX_VECTOR_SIZE, T)>::type + vector_n; + + template + friend struct vector; + + public: + + typedef typename vector_n::types types; + typedef typename vector_n::fusion_tag fusion_tag; + typedef typename vector_n::tag tag; + typedef typename vector_n::size size; + typedef typename vector_n::category category; + typedef typename vector_n::is_view is_view; + + vector() + : vec() {} + + template + vector(vector const& rhs) + : vec(rhs.vec) {} + + vector(vector const& rhs) + : vec(rhs.vec) {} + + template + vector(Sequence const& rhs) +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1400) + : vec(ctor_helper(rhs, is_base_of())) {} +#else + : vec(rhs) {} +#endif + + // Expand a couple of forwarding constructors for arguments + // of type (T0), (T0, T1), (T0, T1, T2) etc. Example: + // + // vector( + // typename detail::call_param::type _0 + // , typename detail::call_param::type _1) + // : vec(_0, _1) {} + #include + + template + vector& + operator=(vector const& rhs) + { + vec = rhs.vec; + return *this; + } + + template + vector& + operator=(T const& rhs) + { + vec = rhs; + return *this; + } + + template + typename add_reference< + typename mpl::at_c::type + >::type + at_impl(mpl::int_ index) + { + return vec.at_impl(index); + } + + template + typename add_reference< + typename add_const< + typename mpl::at_c::type + >::type + >::type + at_impl(mpl::int_ index) const + { + return vec.at_impl(index); + } + + template + typename add_reference< + typename mpl::at::type + >::type + at_impl(I index) + { + return vec.at_impl(mpl::int_()); + } + + template + typename add_reference< + typename add_const< + typename mpl::at::type + >::type + >::type + at_impl(I index) const + { + return vec.at_impl(mpl::int_()); + } + + private: + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1400) + static vector_n const& + ctor_helper(vector const& rhs, mpl::true_) + { + return rhs.vec; + } + + template + static T const& + ctor_helper(T const& rhs, mpl::false_) + { + return rhs; + } +#endif + + vector_n vec; + }; +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector/vector10.hpp b/win32/include/boost/fusion/container/vector/vector10.hpp new file mode 100755 index 000000000..f2a842618 --- /dev/null +++ b/win32/include/boost/fusion/container/vector/vector10.hpp @@ -0,0 +1,66 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VECTOR10_05042005_0257) +#define FUSION_VECTOR10_05042005_0257 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct vector_tag; + struct fusion_sequence_tag; + struct random_access_traversal_tag; + + struct vector0 : sequence_base + { + typedef mpl::vector0<> types; + typedef vector_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef mpl::false_ is_view; + typedef random_access_traversal_tag category; + typedef mpl::int_<0> size; + + vector0() {} + + template + vector0(Sequence const& seq) + {} + }; + +// expand vector1 to vector10 +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, 10) +#include BOOST_PP_ITERATE() + +}} + +#endif + diff --git a/win32/include/boost/fusion/container/vector/vector20.hpp b/win32/include/boost/fusion/container/vector/vector20.hpp new file mode 100755 index 000000000..816d1be3a --- /dev/null +++ b/win32/include/boost/fusion/container/vector/vector20.hpp @@ -0,0 +1,50 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VECTOR20_05052005_0205) +#define FUSION_VECTOR20_05052005_0205 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct vector_tag; + struct fusion_sequence_tag; + struct random_access_traversal_tag; + +// expand vector11 to vector20 +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (11, 20) +#include BOOST_PP_ITERATE() + +}} + +#endif + diff --git a/win32/include/boost/fusion/container/vector/vector30.hpp b/win32/include/boost/fusion/container/vector/vector30.hpp new file mode 100755 index 000000000..02a40c272 --- /dev/null +++ b/win32/include/boost/fusion/container/vector/vector30.hpp @@ -0,0 +1,50 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VECTOR30_05052005_0206) +#define FUSION_VECTOR30_05052005_0206 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct vector_tag; + struct fusion_sequence_tag; + struct random_access_traversal_tag; + +// expand vector21 to vector30 +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (21, 30) +#include BOOST_PP_ITERATE() + +}} + +#endif + diff --git a/win32/include/boost/fusion/container/vector/vector40.hpp b/win32/include/boost/fusion/container/vector/vector40.hpp new file mode 100755 index 000000000..5b6d7d5eb --- /dev/null +++ b/win32/include/boost/fusion/container/vector/vector40.hpp @@ -0,0 +1,50 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VECTOR40_05052005_0208) +#define FUSION_VECTOR40_05052005_0208 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct vector_tag; + struct fusion_sequence_tag; + struct random_access_traversal_tag; + +// expand vector31 to vector40 +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (31, 40) +#include BOOST_PP_ITERATE() + +}} + +#endif + diff --git a/win32/include/boost/fusion/container/vector/vector50.hpp b/win32/include/boost/fusion/container/vector/vector50.hpp new file mode 100755 index 000000000..f1387db74 --- /dev/null +++ b/win32/include/boost/fusion/container/vector/vector50.hpp @@ -0,0 +1,50 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VECTOR50_05052005_0207) +#define FUSION_VECTOR50_05052005_0207 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct vector_tag; + struct fusion_sequence_tag; + struct random_access_traversal_tag; + +// expand vector41 to vector50 +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (41, 50) +#include BOOST_PP_ITERATE() + +}} + +#endif + diff --git a/win32/include/boost/fusion/container/vector/vector_fwd.hpp b/win32/include/boost/fusion/container/vector/vector_fwd.hpp new file mode 100755 index 000000000..5c366f99b --- /dev/null +++ b/win32/include/boost/fusion/container/vector/vector_fwd.hpp @@ -0,0 +1,25 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VECTOR_FORWARD_07072005_0125) +#define FUSION_VECTOR_FORWARD_07072005_0125 + +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_VECTOR_SIZE, typename T, void_) + > + struct vector; +}} + +#endif diff --git a/win32/include/boost/fusion/container/vector/vector_iterator.hpp b/win32/include/boost/fusion/container/vector/vector_iterator.hpp new file mode 100755 index 000000000..5cc9f2645 --- /dev/null +++ b/win32/include/boost/fusion/container/vector/vector_iterator.hpp @@ -0,0 +1,46 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VECTOR_ITERATOR_05042005_0635) +#define FUSION_VECTOR_ITERATOR_05042005_0635 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct vector_iterator_tag; + struct random_access_traversal_tag; + + template + struct vector_iterator_identity; + + template + struct vector_iterator : iterator_base > + { + typedef mpl::int_ index; + typedef Vector vector; + typedef vector_iterator_tag fusion_tag; + typedef random_access_traversal_tag category; + typedef vector_iterator_identity< + typename add_const::type, N> identity; + + vector_iterator(Vector& vec) + : vec(vec) {} + Vector& vec; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/functional.hpp b/win32/include/boost/fusion/functional.hpp new file mode 100755 index 000000000..e0457e999 --- /dev/null +++ b/win32/include/boost/fusion/functional.hpp @@ -0,0 +1,17 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_HPP_INCLUDED + +#include +#include +#include + +#endif + diff --git a/win32/include/boost/fusion/functional/adapter.hpp b/win32/include/boost/fusion/functional/adapter.hpp new file mode 100755 index 000000000..8c377f32a --- /dev/null +++ b/win32/include/boost/fusion/functional/adapter.hpp @@ -0,0 +1,18 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_ADAPTER_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_ADAPTER_HPP_INCLUDED +#include +#include +#include +#include +#include +#include +#include +#endif diff --git a/win32/include/boost/fusion/functional/adapter/detail/access.hpp b/win32/include/boost/fusion/functional/adapter/detail/access.hpp new file mode 100755 index 000000000..bc8898e90 --- /dev/null +++ b/win32/include/boost/fusion/functional/adapter/detail/access.hpp @@ -0,0 +1,41 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_ADAPTER_DETAIL_ACCESS_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_ADAPTER_DETAIL_ACCESS_HPP_INCLUDED + +namespace boost { namespace fusion { namespace detail +{ + // const reference deduction for function templates that accept T const & + template struct cref { typedef T const& type; }; + template struct cref { typedef T const& type; }; + template struct cref { typedef T const& type; }; + + // mutable reference deduction for function templates that accept T & + template struct mref { typedef T & type; }; + template struct mref { typedef T & type; }; + + // generic reference deduction for function templates that are overloaded + // to accept both T const & and T & + template struct gref { typedef T const& type; }; + template struct gref { typedef T & type; }; + template struct gref { typedef T const& type; }; + + // appropriately qualified target function in const context + template struct qf_c { typedef T const type; }; + template struct qf_c { typedef T const type; }; + template struct qf_c { typedef T type; }; + + // appropriately qualified target function in non-const context + template struct qf { typedef T type; }; + template struct qf { typedef T const type; }; + template struct qf { typedef T type; }; +}}} + +#endif + diff --git a/win32/include/boost/fusion/functional/adapter/detail/pow2_explode.hpp b/win32/include/boost/fusion/functional/adapter/detail/pow2_explode.hpp new file mode 100755 index 000000000..2e5b8cf88 --- /dev/null +++ b/win32/include/boost/fusion/functional/adapter/detail/pow2_explode.hpp @@ -0,0 +1,118 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_PP_IS_ITERATING) +# error "This file has to be included by a preprocessor loop construct!" +#elif BOOST_PP_ITERATION_DEPTH() == 1 + +# if !defined(BOOST_FUSION_FUNCTIONAL_ADAPTER_DETAIL_POW2_EXPLODE_HPP_INCLUDED) +# include +# include +# include +# define BOOST_FUSION_FUNCTIONAL_ADAPTER_DETAIL_POW2_EXPLODE_HPP_INCLUDED +# endif + +# define BOOST_PP_VALUE 0 +# include BOOST_PP_ASSIGN_SLOT(1) + +# define BOOST_PP_FILENAME_2 \ + +# define BOOST_PP_VALUE (1 << N) >> 4 +# if BOOST_PP_VALUE > BOOST_PP_LIMIT_ITERATION +# error "Preprocessor limit exceeded." +# endif + +# include BOOST_PP_ASSIGN_SLOT(2) +# define BOOST_PP_ITERATION_LIMITS (0,BOOST_PP_DEC(BOOST_PP_SLOT_2())) +# include BOOST_PP_ITERATE() + +#elif BOOST_PP_ITERATION_DEPTH() == 2 + +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# if BOOST_PP_SLOT_1() < 1 << N +# include BOOST_PP_INDIRECT_SELF +# define BOOST_PP_VALUE BOOST_PP_SLOT_1() + 1 +# include BOOST_PP_ASSIGN_SLOT(1) +# endif +# endif +# endif +# endif +# endif +# endif +# endif +# endif +# endif +# endif +# endif +# endif +# endif +# endif +# endif +# endif + +#endif + diff --git a/win32/include/boost/fusion/functional/adapter/detail/pt_def.hpp b/win32/include/boost/fusion/functional/adapter/detail/pt_def.hpp new file mode 100755 index 000000000..11cc40f6d --- /dev/null +++ b/win32/include/boost/fusion/functional/adapter/detail/pt_def.hpp @@ -0,0 +1,71 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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). +==============================================================================*/ + +// No include guard - this file is included multiple times intentionally. + +#if BOOST_PP_SLOT_1() & 0x001 +# define PT0 T0 & +#else +# define PT0 T0 const & +#endif +#if BOOST_PP_SLOT_1() & 0x002 +# define PT1 T1 & +#else +# define PT1 T1 const & +#endif +#if BOOST_PP_SLOT_1() & 0x004 +# define PT2 T2 & +#else +# define PT2 T2 const & +#endif +#if BOOST_PP_SLOT_1() & 0x008 +# define PT3 T3 & +#else +# define PT3 T3 const & +#endif +#if BOOST_PP_SLOT_1() & 0x010 +# define PT4 T4 & +#else +# define PT4 T4 const & +#endif +#if BOOST_PP_SLOT_1() & 0x020 +# define PT5 T5 & +#else +# define PT5 T5 const & +#endif +#if BOOST_PP_SLOT_1() & 0x040 +# define PT6 T6 & +#else +# define PT6 T6 const & +#endif +#if BOOST_PP_SLOT_1() & 0x080 +# define PT7 T7 & +#else +# define PT7 T7 const & +#endif +#if BOOST_PP_SLOT_1() & 0x100 +# define PT8 T8 & +#else +# define PT8 T8 const & +#endif +#if BOOST_PP_SLOT_1() & 0x200 +# define PT9 T9 & +#else +# define PT9 T9 const & +#endif +#if BOOST_PP_SLOT_1() & 0x400 +# define PT10 T10 & +#else +# define PT10 T10 const & +#endif +#if BOOST_PP_SLOT_1() & 0x800 +# define PT11 T11 & +#else +# define PT11 T11 const & +#endif + diff --git a/win32/include/boost/fusion/functional/adapter/detail/pt_undef.hpp b/win32/include/boost/fusion/functional/adapter/detail/pt_undef.hpp new file mode 100755 index 000000000..c2397239a --- /dev/null +++ b/win32/include/boost/fusion/functional/adapter/detail/pt_undef.hpp @@ -0,0 +1,23 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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). +==============================================================================*/ + +// No include guard - this file is included multiple times intentionally. + +#undef PT0 +#undef PT1 +#undef PT2 +#undef PT3 +#undef PT4 +#undef PT5 +#undef PT6 +#undef PT7 +#undef PT8 +#undef PT9 +#undef PT10 +#undef PT11 + diff --git a/win32/include/boost/fusion/functional/adapter/fused.hpp b/win32/include/boost/fusion/functional/adapter/fused.hpp new file mode 100755 index 000000000..86ae64b14 --- /dev/null +++ b/win32/include/boost/fusion/functional/adapter/fused.hpp @@ -0,0 +1,85 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_ADAPTER_FUSED_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_ADAPTER_FUSED_HPP_INCLUDED + +#include + +#include +#include + +namespace boost { namespace fusion +{ + template class fused; + + //----- ---- --- -- - - - - + + template + class fused + { + Function fnc_transformed; + + typedef typename detail::qf_c::type & func_const_fwd_t; + typedef typename detail::qf::type & func_fwd_t; + + public: + + inline explicit fused(func_const_fwd_t f = Function()) + : fnc_transformed(f) + { } + + template + inline typename result_of::invoke::type + operator()(Seq const & s) const + { + return fusion::invoke(this->fnc_transformed,s); + } + + template + inline typename result_of::invoke::type + operator()(Seq const & s) + { + return fusion::invoke(this->fnc_transformed,s); + } + + template + inline typename result_of::invoke::type + operator()(Seq & s) const + { + return fusion::invoke(this->fnc_transformed,s); + } + + template + inline typename result_of::invoke::type + operator()(Seq & s) + { + return fusion::invoke(this->fnc_transformed,s); + } + + template + struct result; + + template + struct result< Self const (Seq) > + : result_of::invoke::type > + { }; + + template + struct result< Self(Seq) > + : result_of::invoke::type > + { }; + + }; + +}} + +#endif + diff --git a/win32/include/boost/fusion/functional/adapter/fused_function_object.hpp b/win32/include/boost/fusion/functional/adapter/fused_function_object.hpp new file mode 100755 index 000000000..7db735b2f --- /dev/null +++ b/win32/include/boost/fusion/functional/adapter/fused_function_object.hpp @@ -0,0 +1,90 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_ADAPTER_FUSED_FUNCTION_OBJECT_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_ADAPTER_FUSED_FUNCTION_OBJECT_HPP_INCLUDED + +#include + +#include +#include + +namespace boost { namespace fusion +{ + template class fused_function_object; + + //----- ---- --- -- - - - - + + template + class fused_function_object + { + Function fnc_transformed; + + typedef typename detail::qf_c::type & func_const_fwd_t; + typedef typename detail::qf::type & func_fwd_t; + + public: + + inline explicit fused_function_object(func_const_fwd_t f = Function()) + : fnc_transformed(f) + { } + + template + inline typename result_of::invoke_function_object::type operator()(Seq const & s) const + { + return fusion::invoke_function_object< + func_const_fwd_t >(this->fnc_transformed,s); + } + + template + inline typename result_of::invoke_function_object::type + operator()(Seq const & s) + { + return fusion::invoke_function_object< + func_fwd_t >(this->fnc_transformed,s); + } + + template + inline typename result_of::invoke_function_object::type + operator()(Seq & s) const + { + return fusion::invoke_function_object< + func_const_fwd_t >(this->fnc_transformed,s); + } + + template + inline typename result_of::invoke_function_object::type + operator()(Seq & s) + { + return fusion::invoke_function_object< + func_fwd_t >(this->fnc_transformed,s); + } + + template + struct result; + + template + struct result< Self const (Seq) > + : result_of::invoke_function_object::type > + { }; + + template + struct result< Self(Seq) > + : result_of::invoke_function_object::type > + { }; + }; + +}} + +#endif + diff --git a/win32/include/boost/fusion/functional/adapter/fused_procedure.hpp b/win32/include/boost/fusion/functional/adapter/fused_procedure.hpp new file mode 100755 index 000000000..b748519a6 --- /dev/null +++ b/win32/include/boost/fusion/functional/adapter/fused_procedure.hpp @@ -0,0 +1,70 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_ADAPTER_FUSED_PROCEDURE_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_ADAPTER_FUSED_PROCEDURE_HPP_INCLUDED + +#include + +#include +#include + +namespace boost { namespace fusion +{ + template class fused_procedure; + + //----- ---- --- -- - - - - + + template + class fused_procedure + { + Function fnc_transformed; + + typedef typename detail::qf_c::type & func_const_fwd_t; + typedef typename detail::qf::type & func_fwd_t; + + public: + + inline explicit fused_procedure(func_const_fwd_t f = Function()) + : fnc_transformed(f) + { } + + template + inline void operator()(Seq const & s) const + { + fusion::invoke_procedure< + func_const_fwd_t >(this->fnc_transformed,s); + } + + template + inline void operator()(Seq const & s) + { + fusion::invoke_procedure< + func_fwd_t >(this->fnc_transformed,s); + } + + template + inline void operator()(Seq & s) const + { + fusion::invoke_procedure< + func_const_fwd_t >(this->fnc_transformed,s); + } + + template + inline void operator()(Seq & s) + { + return fusion::invoke_procedure< + func_fwd_t >(this->fnc_transformed,s); + } + + typedef void result_type; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/functional/adapter/limits.hpp b/win32/include/boost/fusion/functional/adapter/limits.hpp new file mode 100755 index 000000000..73d11993d --- /dev/null +++ b/win32/include/boost/fusion/functional/adapter/limits.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_ADAPTER_LIMITS_HPP_INCLUDED) +# define BOOST_FUSION_FUNCTIONAL_ADAPTER_LIMITS_HPP_INCLUDED + +# include + +# if !defined(BOOST_FUSION_UNFUSED_GENERIC_MAX_ARITY) +# define BOOST_FUSION_UNFUSED_GENERIC_MAX_ARITY 6 +# elif BOOST_FUSION_UNFUSED_GENERIC_MAX_ARITY > FUSION_MAX_VECTOR_SIZE +# error "BOOST_FUSION_UNFUSED_GENERIC_MAX_ARITY > FUSION_MAX_VECTOR_SIZE" +# endif +# if !defined(BOOST_FUSION_UNFUSED_RVALUE_ARGS_MAX_ARITY) +# define BOOST_FUSION_UNFUSED_RVALUE_ARGS_MAX_ARITY 6 +# elif BOOST_FUSION_UNFUSED_RVALUE_ARGS_MAX_ARITY > FUSION_MAX_VECTOR_SIZE +# error "BOOST_FUSION_UNFUSED_RVALUE_ARGS_MAX_ARITY > FUSION_MAX_VECTOR_SIZE" +# endif +# if !defined(BOOST_FUSION_UNFUSED_LVALUE_ARGS_MAX_ARITY) +# define BOOST_FUSION_UNFUSED_LVALUE_ARGS_MAX_ARITY 6 +# elif BOOST_FUSION_UNFUSED_LVALUE_ARGS_MAX_ARITY > FUSION_MAX_VECTOR_SIZE +# error "BOOST_FUSION_UNFUSED_LVALUE_ARGS_MAX_ARITY > FUSION_MAX_VECTOR_SIZE" +# endif +# if !defined(BOOST_FUSION_UNFUSED_TYPED_MAX_ARITY) +# define BOOST_FUSION_UNFUSED_TYPED_MAX_ARITY 6 +# elif BOOST_FUSION_UNFUSED_TYPED_MAX_ARITY > FUSION_MAX_VECTOR_SIZE +# error "BOOST_FUSION_UNFUSED_TYPED_MAX_ARITY > FUSION_MAX_VECTOR_SIZE" +# endif +# if !defined(BOOST_FUSION_CONSTRUCTOR_MAX_ARITY) +# define BOOST_FUSION_CONSTRUCTOR_MAX_ARITY 6 +# endif + +#endif + diff --git a/win32/include/boost/fusion/functional/adapter/unfused_generic.hpp b/win32/include/boost/fusion/functional/adapter/unfused_generic.hpp new file mode 100755 index 000000000..c6cee2826 --- /dev/null +++ b/win32/include/boost/fusion/functional/adapter/unfused_generic.hpp @@ -0,0 +1,175 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_ADAPTER_UNFUSED_GENERIC_HPP_INCLUDED) +#if !defined(BOOST_PP_IS_ITERATING) + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +namespace boost { namespace fusion +{ + template class unfused_generic; + + //----- ---- --- -- - - - - + + template + class unfused_generic + { + Function fnc_transformed; + + typedef typename detail::qf_c::type function_c; + typedef typename detail::qf::type function; + + typedef typename detail::call_param::type func_const_fwd_t; + + public: + + inline explicit unfused_generic(func_const_fwd_t f = Function()) + : fnc_transformed(f) + { } + + template + struct result; + + typedef typename boost::result_of< + function_c(fusion::vector0 &) >::type call_const_0_result; + + inline call_const_0_result operator()() const + { + fusion::vector0 arg; + return this->fnc_transformed(arg); + } + + typedef typename boost::result_of< + function (fusion::vector0 &) >::type call_0_result; + + inline call_0_result operator()() + { + fusion::vector0 arg; + return this->fnc_transformed(arg); + } + + #define BOOST_FUSION_CODE(tpl_params,arg_types,params,args) \ + template \ + inline typename boost::result_of & )>::type \ + operator()(params) const \ + { \ + BOOST_PP_CAT(fusion::vector,N) arg(args); \ + return this->fnc_transformed(arg); \ + } \ + template \ + inline typename boost::result_of & )>::type \ + operator()(params) \ + { \ + BOOST_PP_CAT(fusion::vector,N) arg(args); \ + return this->fnc_transformed(arg); \ + } + + #define BOOST_PP_INDIRECT_SELF \ + + #define BOOST_PP_FILENAME_1 \ + + #define BOOST_PP_ITERATION_LIMITS \ + (1,BOOST_FUSION_UNFUSED_GENERIC_MAX_ARITY) + #define N BOOST_PP_ITERATION_1 + #include BOOST_PP_ITERATE() + #undef N + + #undef BOOST_FUSION_CODE + }; +}} + +namespace boost +{ + template + struct result_of const ()> + { + typedef typename boost::fusion::unfused_generic::call_const_0_result type; + }; + template + struct result_of()> + { + typedef typename boost::fusion::unfused_generic::call_0_result type; + }; +} + +#define BOOST_FUSION_FUNCTIONAL_ADAPTER_UNFUSED_GENERIC_HPP_INCLUDED +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#include + +#if BOOST_PP_SLOT_1() == 0 + template + struct result + < Self const (BOOST_PP_ENUM_PARAMS(N,T)) > + : boost::result_of::type BOOST_PP_INTERCEPT) > & )> + { }; + + template + struct result + < Self(BOOST_PP_ENUM_PARAMS(N,T)) > + : boost::result_of::type BOOST_PP_INTERCEPT) > & )> + { }; +#endif + +#if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400)) + template + inline typename boost::result_of & )>::type + operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a)) const + { + BOOST_PP_CAT(fusion::vector,N) + arg(BOOST_PP_ENUM_PARAMS(N,a)); + return this->fnc_transformed(arg); + } + template + inline typename boost::result_of & )>::type + operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a)) + { + BOOST_PP_CAT(fusion::vector,N) + arg(BOOST_PP_ENUM_PARAMS(N,a)); + return this->fnc_transformed(arg); + } +#else + BOOST_FUSION_CODE(BOOST_PP_ENUM_PARAMS(N,typename T), + BOOST_PP_ENUM_PARAMS(N,PT), BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a), + BOOST_PP_ENUM_PARAMS(N,a) ) + // ...generates uglier code but is faster - it caches ENUM_* +#endif + +#include + +#endif // defined(BOOST_PP_IS_ITERATING) +#endif + diff --git a/win32/include/boost/fusion/functional/adapter/unfused_lvalue_args.hpp b/win32/include/boost/fusion/functional/adapter/unfused_lvalue_args.hpp new file mode 100755 index 000000000..1ad5631a9 --- /dev/null +++ b/win32/include/boost/fusion/functional/adapter/unfused_lvalue_args.hpp @@ -0,0 +1,136 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_ADAPTER_UNFUSED_LVALUE_ARGS_HPP_INCLUDED) +#if !defined(BOOST_PP_IS_ITERATING) + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +namespace boost { namespace fusion +{ + template class unfused_lvalue_args; + + //----- ---- --- -- - - - - + + template class unfused_lvalue_args + { + Function fnc_transformed; + + typedef typename detail::qf_c::type function_c; + typedef typename detail::qf::type function; + + typedef typename detail::call_param::type func_const_fwd_t; + + public: + + inline explicit unfused_lvalue_args(func_const_fwd_t f = function()) + : fnc_transformed(f) + { } + + template + struct result; + + typedef typename boost::result_of< + function_c(fusion::vector0 &) >::type call_const_0_result; + + inline call_const_0_result operator()() const + { + fusion::vector0 arg; + return this->fnc_transformed(arg); + } + + typedef typename boost::result_of< + function(fusion::vector0 &) >::type call_0_result; + + inline call_0_result operator()() + { + fusion::vector0 arg; + return this->fnc_transformed(arg); + } + + #define BOOST_PP_FILENAME_1 \ + + #define BOOST_PP_ITERATION_LIMITS \ + (1,BOOST_FUSION_UNFUSED_LVALUE_ARGS_MAX_ARITY) + #include BOOST_PP_ITERATE() + }; +}} + +namespace boost +{ + template + struct result_of< boost::fusion::unfused_lvalue_args const () > + { + typedef typename boost::fusion::unfused_lvalue_args::call_const_0_result type; + }; + template + struct result_of< boost::fusion::unfused_lvalue_args() > + { + typedef typename boost::fusion::unfused_lvalue_args::call_0_result type; + }; +} + +#define BOOST_FUSION_FUNCTIONAL_ADAPTER_UNFUSED_LVALUE_ARGS_HPP_INCLUDED +#else // defined(BOOST_PP_IS_ITERATING) +//////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +//////////////////////////////////////////////////////////////////////////////// +#define N BOOST_PP_ITERATION() + + template + struct result< Self const (BOOST_PP_ENUM_PARAMS(N,T)) > + : boost::result_of< function_c( + BOOST_PP_CAT(fusion::vector,N)< BOOST_PP_ENUM_BINARY_PARAMS(N, + typename detail::mref::type BOOST_PP_INTERCEPT) > & )> + { }; + + template + struct result< Self(BOOST_PP_ENUM_PARAMS(N,T)) > + : boost::result_of< function( + BOOST_PP_CAT(fusion::vector,N)< BOOST_PP_ENUM_BINARY_PARAMS(N, + typename detail::mref::type BOOST_PP_INTERCEPT) > & )> + { }; + + template + inline typename boost::result_of & )>::type + operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& a)) const + { + BOOST_PP_CAT(fusion::vector,N)< + BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT) > + arg(BOOST_PP_ENUM_PARAMS(N,a)); + return this->fnc_transformed(arg); + } + + template + inline typename boost::result_of & )>::type + operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,& a)) + { + BOOST_PP_CAT(fusion::vector,N)< + BOOST_PP_ENUM_BINARY_PARAMS(N,T,& BOOST_PP_INTERCEPT) > + arg(BOOST_PP_ENUM_PARAMS(N,a)); + return this->fnc_transformed(arg); + } +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) +#endif + diff --git a/win32/include/boost/fusion/functional/adapter/unfused_rvalue_args.hpp b/win32/include/boost/fusion/functional/adapter/unfused_rvalue_args.hpp new file mode 100755 index 000000000..21ea2048e --- /dev/null +++ b/win32/include/boost/fusion/functional/adapter/unfused_rvalue_args.hpp @@ -0,0 +1,137 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_ADAPTER_UNFUSED_RVALUE_ARGS_HPP_INCLUDED) +#if !defined(BOOST_PP_IS_ITERATING) + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +namespace boost { namespace fusion +{ + template class unfused_rvalue_args; + + //----- ---- --- -- - - - - + + template class unfused_rvalue_args + { + Function fnc_transformed; + + typedef typename detail::qf_c::type function_c; + typedef typename detail::qf::type function; + + typedef typename detail::call_param::type func_const_fwd_t; + + public: + + inline explicit unfused_rvalue_args(func_const_fwd_t f = function()) + : fnc_transformed(f) + { } + + template + struct result; + + typedef typename boost::result_of< + function_c(fusion::vector0 &) >::type call_const_0_result; + + inline call_const_0_result operator()() const + { + fusion::vector0 arg; + return this->fnc_transformed(arg); + } + + typedef typename boost::result_of< + function(fusion::vector0 &) >::type call_0_result; + + inline call_0_result operator()() + { + fusion::vector0 arg; + return this->fnc_transformed(arg); + } + + #define BOOST_PP_FILENAME_1 \ + + #define BOOST_PP_ITERATION_LIMITS \ + (1,BOOST_FUSION_UNFUSED_RVALUE_ARGS_MAX_ARITY) + #include BOOST_PP_ITERATE() + }; +}} + +namespace boost +{ + template + struct result_of const ()> + { + typedef typename boost::fusion::unfused_rvalue_args::call_const_0_result type; + }; + template + struct result_of()> + { + typedef typename boost::fusion::unfused_rvalue_args::call_0_result type; + }; +} + +#define BOOST_FUSION_FUNCTIONAL_ADAPTER_UNFUSED_RVALUE_ARGS_HPP_INCLUDED +#else // defined(BOOST_PP_IS_ITERATING) +//////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +//////////////////////////////////////////////////////////////////////////////// +#define N BOOST_PP_ITERATION() + + template + struct result< Self const (BOOST_PP_ENUM_PARAMS(N,T)) > + : boost::result_of< function_c( + BOOST_PP_CAT(fusion::vector,N)< BOOST_PP_ENUM_BINARY_PARAMS(N, + typename detail::cref::type BOOST_PP_INTERCEPT) > & )> + { }; + + template + struct result< Self (BOOST_PP_ENUM_PARAMS(N,T)) > + : boost::result_of< function( + BOOST_PP_CAT(fusion::vector,N)< BOOST_PP_ENUM_BINARY_PARAMS(N, + typename detail::cref::type BOOST_PP_INTERCEPT) > & )> + { }; + + template + inline typename boost::result_of & )>::type + operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const& a)) const + { + BOOST_PP_CAT(fusion::vector,N)< + BOOST_PP_ENUM_BINARY_PARAMS(N,T,const& BOOST_PP_INTERCEPT) > + arg(BOOST_PP_ENUM_PARAMS(N,a)); + return this->fnc_transformed(arg); + } + + template + inline typename boost::result_of & )>::type + operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,T,const& a)) + { + BOOST_PP_CAT(fusion::vector,N)< + BOOST_PP_ENUM_BINARY_PARAMS(N,T,const& BOOST_PP_INTERCEPT) > + arg(BOOST_PP_ENUM_PARAMS(N,a)); + return this->fnc_transformed(arg); + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) +#endif + diff --git a/win32/include/boost/fusion/functional/adapter/unfused_typed.hpp b/win32/include/boost/fusion/functional/adapter/unfused_typed.hpp new file mode 100755 index 000000000..8d69a88bf --- /dev/null +++ b/win32/include/boost/fusion/functional/adapter/unfused_typed.hpp @@ -0,0 +1,155 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_ADAPTER_UNFUSED_TYPED_HPP_INCLUDED) +#if !defined(BOOST_PP_IS_ITERATING) + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + + +namespace boost { namespace fusion +{ + + template class unfused_typed; + + //----- ---- --- -- - - - - + + namespace detail + { + template + struct unfused_typed_impl; + } + + template + class unfused_typed + : public detail::unfused_typed_impl + < unfused_typed, Function, Sequence, + result_of::size::value > + { + Function fnc_transformed; + + template + friend struct detail::unfused_typed_impl; + + typedef typename detail::call_param::type func_const_fwd_t; + + public: + + inline explicit unfused_typed(func_const_fwd_t f = Function()) + : fnc_transformed(f) + { } + }; + + #define BOOST_PP_FILENAME_1 + #define BOOST_PP_ITERATION_LIMITS (0,BOOST_FUSION_UNFUSED_TYPED_MAX_ARITY) + #include BOOST_PP_ITERATE() + +}} + +namespace boost +{ + template + struct result_of< boost::fusion::unfused_typed const () > + : boost::fusion::unfused_typed::template result< + boost::fusion::unfused_typed const () > + { }; + template + struct result_of< boost::fusion::unfused_typed() > + : boost::fusion::unfused_typed::template result< + boost::fusion::unfused_typed () > + { }; +} + + +#define BOOST_FUSION_FUNCTIONAL_ADAPTER_UNFUSED_TYPED_HPP_INCLUDED +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// +#define N BOOST_PP_ITERATION() + + namespace detail + { + + template + struct unfused_typed_impl + { + typedef typename detail::qf_c::type function_c; + typedef typename detail::qf::type function; + typedef typename result_of::as_vector::type arg_vector_t; + + public: + +#define M(z,i,s) \ + typename call_param::type>::type a##i + + inline typename boost::result_of< + function_c(arg_vector_t &) >::type + operator()(BOOST_PP_ENUM(N,M,arg_vector_t)) const + { +#if N > 0 + arg_vector_t arg(BOOST_PP_ENUM_PARAMS(N,a)); +#else + arg_vector_t arg; +#endif + return static_cast(this)->fnc_transformed(arg); + } + + inline typename boost::result_of< + function(arg_vector_t &) >::type + operator()(BOOST_PP_ENUM(N,M,arg_vector_t)) + { +#if N > 0 + arg_vector_t arg(BOOST_PP_ENUM_PARAMS(N,a)); +#else + arg_vector_t arg; +#endif + return static_cast(this)->fnc_transformed(arg); + } + +#undef M + + template struct result { typedef void type; }; + + template + struct result< Self const (BOOST_PP_ENUM_PARAMS(N,T)) > + : boost::result_of< function_c(arg_vector_t &) > + { }; + + template + struct result< Self (BOOST_PP_ENUM_PARAMS(N,T)) > + : boost::result_of< function(arg_vector_t &) > + { }; + }; + + } // namespace detail + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) +#endif + diff --git a/win32/include/boost/fusion/functional/generation.hpp b/win32/include/boost/fusion/functional/generation.hpp new file mode 100755 index 000000000..a0bec2910 --- /dev/null +++ b/win32/include/boost/fusion/functional/generation.hpp @@ -0,0 +1,19 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_GENERATION_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_GENERATION_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/functional/generation/detail/gen_make_adapter.hpp b/win32/include/boost/fusion/functional/generation/detail/gen_make_adapter.hpp new file mode 100755 index 000000000..3fc36f9d7 --- /dev/null +++ b/win32/include/boost/fusion/functional/generation/detail/gen_make_adapter.hpp @@ -0,0 +1,44 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + Use modification and distribution are subject to 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). +==============================================================================*/ + +// No include guard - this file is included multiple times intentionally. + +#include +#include + +#if !defined(BOOST_FUSION_CLASS_TPL_NAME) +# error "BOOST_FUSION_CLASS_TPL_NAME undefined" +#endif + +#define BOOST_FUSION_FUNC_NAME BOOST_PP_CAT(make_,BOOST_FUSION_CLASS_TPL_NAME) + +namespace boost { namespace fusion +{ + + namespace result_of + { + template + struct BOOST_FUSION_FUNC_NAME + { + typedef fusion::BOOST_FUSION_CLASS_TPL_NAME< + typename fusion::detail::as_fusion_element::type > type; + }; + } + + template + inline typename result_of::BOOST_FUSION_FUNC_NAME::type + BOOST_FUSION_FUNC_NAME(F const & f) + { + return typename result_of::BOOST_FUSION_FUNC_NAME::type(f); + } + +}} + +#undef BOOST_FUSION_CLASS_TPL_NAME +#undef BOOST_FUSION_FUNC_NAME + diff --git a/win32/include/boost/fusion/functional/generation/make_fused.hpp b/win32/include/boost/fusion/functional/generation/make_fused.hpp new file mode 100755 index 000000000..a7a1dba61 --- /dev/null +++ b/win32/include/boost/fusion/functional/generation/make_fused.hpp @@ -0,0 +1,18 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_GENERATION_MAKE_FUSED_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_GENERATION_MAKE_FUSED_HPP_INCLUDED + +#include + +#define BOOST_FUSION_CLASS_TPL_NAME fused +#include + +#endif + diff --git a/win32/include/boost/fusion/functional/generation/make_fused_function_object.hpp b/win32/include/boost/fusion/functional/generation/make_fused_function_object.hpp new file mode 100755 index 000000000..b4c3fceaa --- /dev/null +++ b/win32/include/boost/fusion/functional/generation/make_fused_function_object.hpp @@ -0,0 +1,18 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_GENERATION_MAKE_FUSED_FUNCTION_OBJECT_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_GENERATION_MAKE_FUSED_FUNCTION_OBJECT_HPP_INCLUDED + +#include + +#define BOOST_FUSION_CLASS_TPL_NAME fused_function_object +#include + +#endif + diff --git a/win32/include/boost/fusion/functional/generation/make_fused_procedure.hpp b/win32/include/boost/fusion/functional/generation/make_fused_procedure.hpp new file mode 100755 index 000000000..886a35ba2 --- /dev/null +++ b/win32/include/boost/fusion/functional/generation/make_fused_procedure.hpp @@ -0,0 +1,18 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_GENERATION_MAKE_FUSED_PROCEDURE_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_GENERATION_MAKE_FUSED_PROCEDURE_HPP_INCLUDED + +#include + +#define BOOST_FUSION_CLASS_TPL_NAME fused_procedure +#include + +#endif + diff --git a/win32/include/boost/fusion/functional/generation/make_unfused_generic.hpp b/win32/include/boost/fusion/functional/generation/make_unfused_generic.hpp new file mode 100755 index 000000000..980cf0d47 --- /dev/null +++ b/win32/include/boost/fusion/functional/generation/make_unfused_generic.hpp @@ -0,0 +1,18 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_GENERATION_MAKE_UNFUSED_GENERIC_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_GENERATION_MAKE_UNFUSED_GENERIC_HPP_INCLUDED + +#include + +#define BOOST_FUSION_CLASS_TPL_NAME unfused_generic +#include + +#endif + diff --git a/win32/include/boost/fusion/functional/generation/make_unfused_lvalue_args.hpp b/win32/include/boost/fusion/functional/generation/make_unfused_lvalue_args.hpp new file mode 100755 index 000000000..a085e1867 --- /dev/null +++ b/win32/include/boost/fusion/functional/generation/make_unfused_lvalue_args.hpp @@ -0,0 +1,18 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_GENERATION_MAKE_UNFUSED_LVALUE_ARGS_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_GENERATION_MAKE_UNFUSED_LVALUE_ARGS_HPP_INCLUDED + +#include + +#define BOOST_FUSION_CLASS_TPL_NAME unfused_lvalue_args +#include + +#endif + diff --git a/win32/include/boost/fusion/functional/generation/make_unfused_rvalue_args.hpp b/win32/include/boost/fusion/functional/generation/make_unfused_rvalue_args.hpp new file mode 100755 index 000000000..027b8bb6a --- /dev/null +++ b/win32/include/boost/fusion/functional/generation/make_unfused_rvalue_args.hpp @@ -0,0 +1,18 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_GENERATION_MAKE_UNFUSED_RVALUE_ARGS_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_GENERATION_MAKE_UNFUSED_RVALUE_ARGS_HPP_INCLUDED + +#include + +#define BOOST_FUSION_CLASS_TPL_NAME unfused_rvalue_args +#include + +#endif + diff --git a/win32/include/boost/fusion/functional/invocation.hpp b/win32/include/boost/fusion/functional/invocation.hpp new file mode 100755 index 000000000..95b9311ad --- /dev/null +++ b/win32/include/boost/fusion/functional/invocation.hpp @@ -0,0 +1,16 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_INVOCATION_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_INVOCATION_HPP_INCLUDED + +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/functional/invocation/detail/that_ptr.hpp b/win32/include/boost/fusion/functional/invocation/detail/that_ptr.hpp new file mode 100755 index 000000000..7c32a10c5 --- /dev/null +++ b/win32/include/boost/fusion/functional/invocation/detail/that_ptr.hpp @@ -0,0 +1,87 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_INVOCATION_DETAIL_THAT_PTR_HPP_INCLUDED) +#define BOOST_FUSION_FUNCTIONAL_INVOCATION_DETAIL_THAT_PTR_HPP_INCLUDED + +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct that_ptr + { + private: + + typedef typename remove_reference::type pointee; + + template + static inline pointee * do_get_pointer(T &, pointee * x) + { + return x; + } + template + static inline pointee * do_get_pointer(T & x, void const *) + { + return get_pointer(x); + } + + public: + + static inline pointee * get(pointee * x) + { + return x; + } + + static inline pointee * get(pointee & x) + { + return boost::addressof(x); + } + + template static inline pointee * get(T & x) + { + return do_get_pointer(x, boost::addressof(x)); + } + }; + + template struct non_const_pointee; + + namespace adl_barrier + { + using boost::get_pointer; + void const * BOOST_TT_DECL get_pointer(...); // fallback + + template< typename T> char const_tester(T *); + template< typename T> long const_tester(T const *); + + template + struct non_const_pointee_impl + { + static Ptr & what; + + static bool const value = + sizeof(const_tester(get_pointer(what))) == 1; + }; + } + + template struct non_const_pointee + : adl_barrier::non_const_pointee_impl< + typename remove_cv< + typename remove_reference::type >::type > + { + typedef non_const_pointee type; + typedef bool value_type; + }; + +}}} + +#endif + diff --git a/win32/include/boost/fusion/functional/invocation/invoke.hpp b/win32/include/boost/fusion/functional/invocation/invoke.hpp new file mode 100755 index 000000000..3cd843c5b --- /dev/null +++ b/win32/include/boost/fusion/functional/invocation/invoke.hpp @@ -0,0 +1,306 @@ +/*============================================================================= + Copyright (c) 2005-2006 João Abecasis + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_INVOCATION_INVOKE_HPP_INCLUDED) +#if !defined(BOOST_PP_IS_ITERATING) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template struct invoke; + } + + template + inline typename result_of::invoke::type + invoke(Function, Sequence &); + + template + inline typename result_of::invoke::type + invoke(Function, Sequence const &); + + //----- ---- --- -- - - - - + + namespace detail + { + namespace ft = function_types; + + template< + typename Function, class Sequence, + int N = result_of::size::value, + bool CBI = ft::is_callable_builtin::value, + bool RandomAccess = traits::is_random_access::value + > + struct invoke_impl; + + template + struct invoke_param_types; + + template + struct invoke_data_member; + + template + struct invoke_mem_fn; + + #define BOOST_PP_FILENAME_1 + #define BOOST_PP_ITERATION_LIMITS (0, BOOST_FUSION_INVOKE_MAX_ARITY) + #include BOOST_PP_ITERATE() + + template + struct invoke_nonmember_builtin + // use same implementation as for function objects but... + : invoke_impl< // ...work around boost::result_of bugs + typename mpl::eval_if< ft::is_function, + boost::add_reference, boost::remove_cv >::type, + Sequence, N, false, RandomAccess > + { }; + + template + struct invoke_impl + : mpl::if_< ft::is_member_function_pointer, + invoke_mem_fn, + invoke_nonmember_builtin + >::type + { }; + + template + struct invoke_impl + : mpl::eval_if< ft::is_member_pointer, + mpl::if_< ft::is_member_function_pointer, + invoke_mem_fn, + invoke_data_member >, + mpl::identity< invoke_nonmember_builtin< + Function,Sequence,1,RandomAccess> > + >::type + { }; + + template + struct invoke_data_member< T C::*, Sequence > + { + private: + + typedef typename result_of::front::type that; + + typedef mpl::or_< boost::is_convertible, + boost::is_convertible, + non_const_pointee > non_const_cond; + + typedef typename mpl::eval_if< non_const_cond, + mpl::identity, add_const >::type qualified_class; + + typedef typename mpl::eval_if< non_const_cond, + mpl::identity, add_const >::type qualified_type; + + public: + + typedef typename boost::add_reference::type + result_type; + + static inline result_type call(T C::* f, Sequence & s) + { + typename result_of::front::type c = fusion::front(s); + return that_ptr::get(c)->*f; + } + }; + } + + namespace result_of + { + template struct invoke + { + typedef typename detail::invoke_impl< + typename boost::remove_reference::type, Sequence + >::result_type type; + }; + } + + template + inline typename result_of::invoke::type + invoke(Function f, Sequence & s) + { + return detail::invoke_impl< + typename boost::remove_reference::type,Sequence + >::call(f,s); + } + + template + inline typename result_of::invoke::type + invoke(Function f, Sequence const & s) + { + return detail::invoke_impl< + typename boost::remove_reference::type,Sequence const + >::call(f,s); + } + +}} + +#define BOOST_FUSION_FUNCTIONAL_INVOCATION_INVOKE_HPP_INCLUDED +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// +#define N BOOST_PP_ITERATION() + + template + struct invoke_impl + { + public: + + typedef typename boost::result_of< +#define M(z,j,data) typename result_of::at_c::type + Function(BOOST_PP_ENUM(N,M,~)) >::type result_type; +#undef M + + template + static inline result_type + call(F & f, Sequence & s) + { +#define M(z,j,data) fusion::at_c(s) + return f( BOOST_PP_ENUM(N,M,~) ); + } + }; + + +#if N > 0 + template + struct invoke_mem_fn + { + public: + + typedef typename ft::result_type::type result_type; + + template + static inline result_type + call(F & f, Sequence & s) + { + return (that_ptr >::type + >::get(fusion::at_c<0>(s))->*f)(BOOST_PP_ENUM_SHIFTED(N,M,~)); + } + }; +#endif + +#undef M + +#define M(z,j,data) \ + typename seq::I##j i##j = \ + fusion::next(BOOST_PP_CAT(i,BOOST_PP_DEC(j))); + + template + struct invoke_impl + { + private: + typedef invoke_param_types seq; + public: + + typedef typename boost::result_of< + Function(BOOST_PP_ENUM_PARAMS(N,typename seq::T)) + >::type result_type; + + template + static inline result_type + call(F & f, Sequence & s) + { +#if N > 0 + typename seq::I0 i0 = fusion::begin(s); + BOOST_PP_REPEAT_FROM_TO(1,N,M,~) +#endif + return f( BOOST_PP_ENUM_PARAMS(N,*i) ); + } + }; + +#if N > 0 + template + struct invoke_mem_fn + { + private: + typedef invoke_param_types seq; + public: + + typedef typename ft::result_type::type result_type; + + template + static inline result_type + call(F & f, Sequence & s) + { + typename seq::I0 i0 = fusion::begin(s); + BOOST_PP_REPEAT_FROM_TO(1,N,M,~) + + return (that_ptr< typename mpl::front< + ft::parameter_types >::type + >::get(*i0)->*f)(BOOST_PP_ENUM_SHIFTED_PARAMS(N,*i)); + } + }; +#endif + +#undef M + + template struct invoke_param_types + { +#if N > 0 + typedef typename result_of::begin::type I0; + typedef typename result_of::deref::type T0; + +#define M(z,i,data) \ + typedef typename result_of::next< \ + BOOST_PP_CAT(I,BOOST_PP_DEC(i))>::type I##i; \ + typedef typename result_of::deref::type T##i; + + BOOST_PP_REPEAT_FROM_TO(1,N,M,~) +#undef M +#endif + }; + + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) +#endif + diff --git a/win32/include/boost/fusion/functional/invocation/invoke_function_object.hpp b/win32/include/boost/fusion/functional/invocation/invoke_function_object.hpp new file mode 100755 index 000000000..ce8ad22db --- /dev/null +++ b/win32/include/boost/fusion/functional/invocation/invoke_function_object.hpp @@ -0,0 +1,177 @@ +/*============================================================================= + Copyright (c) 2005-2006 João Abecasis + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_INVOCATION_INVOKE_FUNCTION_OBJECT_HPP_INCLUDED) +#if !defined(BOOST_PP_IS_ITERATING) + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template struct invoke_function_object; + } + + template + inline typename result_of::invoke_function_object::type + invoke_function_object(Function, Sequence &); + + template + inline typename result_of::invoke_function_object::type invoke_function_object(Function, Sequence const &); + + //----- ---- --- -- - - - - + + namespace detail + { + template< + class Function, class Sequence, + int N = result_of::size::value, + bool RandomAccess = traits::is_random_access::value + > + struct invoke_function_object_impl; + + template + struct invoke_function_object_param_types; + + #define BOOST_PP_FILENAME_1 \ + + #define BOOST_PP_ITERATION_LIMITS \ + (0, BOOST_FUSION_INVOKE_FUNCTION_OBJECT_MAX_ARITY) + #include BOOST_PP_ITERATE() + } + + namespace result_of + { + template struct invoke_function_object + { + typedef typename detail::invoke_function_object_impl< + typename boost::remove_reference::type, Sequence + >::result_type type; + }; + } + + template + inline typename result_of::invoke_function_object::type + invoke_function_object(Function f, Sequence & s) + { + return detail::invoke_function_object_impl< + typename boost::remove_reference::type,Sequence + >::call(f,s); + } + + template + inline typename result_of::invoke_function_object::type + invoke_function_object(Function f, Sequence const & s) + { + return detail::invoke_function_object_impl< + typename boost::remove_reference::type,Sequence const + >::call(f,s); + } + +}} + +#define BOOST_FUSION_FUNCTIONAL_INVOCATION_INVOKE_FUNCTION_OBJECT_HPP_INCLUDED +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// +#define N BOOST_PP_ITERATION() + + template + struct invoke_function_object_impl + { + public: + + typedef typename boost::result_of< +#define M(z,j,data) \ + typename result_of::at_c::type + Function (BOOST_PP_ENUM(N,M,~)) >::type result_type; +#undef M + + template + static inline result_type + call(F & f, Sequence & s) + { +#define M(z,j,data) fusion::at_c(s) + return f( BOOST_PP_ENUM(N,M,~) ); +#undef M + } + }; + + template + struct invoke_function_object_impl + { + private: + typedef invoke_function_object_param_types seq; + public: + typedef typename boost::result_of< + Function (BOOST_PP_ENUM_PARAMS(N,typename seq::T)) + >::type result_type; + + template + static inline result_type + call(F & f, Sequence & s) + { +#if N > 0 + typename seq::I0 i0 = fusion::begin(s); +#define M(z,j,data) \ + typename seq::I##j i##j = \ + fusion::next(BOOST_PP_CAT(i,BOOST_PP_DEC(j))); + BOOST_PP_REPEAT_FROM_TO(1,N,M,~) +#undef M +#endif + return f( BOOST_PP_ENUM_PARAMS(N,*i) ); + } + }; + + template + struct invoke_function_object_param_types + { +#if N > 0 + typedef typename result_of::begin::type I0; + typedef typename result_of::deref::type T0; + +#define M(z,i,data) \ + typedef typename result_of::next< \ + BOOST_PP_CAT(I,BOOST_PP_DEC(i))>::type I##i; \ + typedef typename result_of::deref::type T##i; + + BOOST_PP_REPEAT_FROM_TO(1,N,M,~) +#undef M +#endif + }; + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) +#endif + diff --git a/win32/include/boost/fusion/functional/invocation/invoke_procedure.hpp b/win32/include/boost/fusion/functional/invocation/invoke_procedure.hpp new file mode 100755 index 000000000..ae7ef52a6 --- /dev/null +++ b/win32/include/boost/fusion/functional/invocation/invoke_procedure.hpp @@ -0,0 +1,171 @@ +/*============================================================================= + Copyright (c) 2005-2006 João Abecasis + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_INVOCATION_INVOKE_PROCEDURE_HPP_INCLUDED) +#if !defined(BOOST_PP_IS_ITERATING) + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace result_of + { + template struct invoke_procedure + { + typedef void type; + }; + } + + template + inline void invoke_procedure(Function, Sequence &); + + template + inline void invoke_procedure(Function, Sequence const &); + + //----- ---- --- -- - - - - + + namespace detail + { + namespace ft = function_types; + + template< + typename Function, class Sequence, + int N = result_of::size::value, + bool MFP = ft::is_member_function_pointer::value, + bool RandomAccess = traits::is_random_access::value + > + struct invoke_procedure_impl; + + #define BOOST_PP_FILENAME_1 \ + + #define BOOST_PP_ITERATION_LIMITS \ + (0, BOOST_FUSION_INVOKE_PROCEDURE_MAX_ARITY) + #include BOOST_PP_ITERATE() + + } + + template + inline void invoke_procedure(Function f, Sequence & s) + { + detail::invoke_procedure_impl< + typename boost::remove_reference::type,Sequence + >::call(f,s); + } + + template + inline void invoke_procedure(Function f, Sequence const & s) + { + detail::invoke_procedure_impl< + typename boost::remove_reference::type,Sequence const + >::call(f,s); + } + +}} + +#define BOOST_FUSION_FUNCTIONAL_INVOCATION_INVOKE_PROCEDURE_HPP_INCLUDED +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// +#define N BOOST_PP_ITERATION() + +#define M(z,j,data) fusion::at_c(s) + + template + struct invoke_procedure_impl + { + static inline void call(Function & f, Sequence & s) + { + f(BOOST_PP_ENUM(N,M,~)); + } + }; + +#if N > 0 + template + struct invoke_procedure_impl + { + static inline void call(Function & f, Sequence & s) + { + (that_ptr >::type + >::get(fusion::at_c<0>(s))->*f)(BOOST_PP_ENUM_SHIFTED(N,M,~)); + } + }; +#endif + +#undef M + +#define M(z,j,data) \ + typedef typename result_of::next< BOOST_PP_CAT(I,BOOST_PP_DEC(j)) \ + >::type I ## j ; \ + I##j i##j = fusion::next(BOOST_PP_CAT(i,BOOST_PP_DEC(j))); + + template + struct invoke_procedure_impl + { + static inline void call(Function & f, Sequence & s) + { +#if N > 0 + typedef typename result_of::begin::type I0; + I0 i0 = fusion::begin(s); + BOOST_PP_REPEAT_FROM_TO(1,N,M,~) +#endif + f( BOOST_PP_ENUM_PARAMS(N,*i) ); + } + }; + +#if N > 0 + template + struct invoke_procedure_impl + { + static inline void call(Function & f, Sequence & s) + { + typedef typename result_of::begin::type I0; + I0 i0 = fusion::begin(s); + BOOST_PP_REPEAT_FROM_TO(1,N,M,~) + + (that_ptr >::type + >::get(*i0)->*f)(BOOST_PP_ENUM_SHIFTED_PARAMS(N,*i)); + } + }; +#endif + +#undef M + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) +#endif + diff --git a/win32/include/boost/fusion/functional/invocation/limits.hpp b/win32/include/boost/fusion/functional/invocation/limits.hpp new file mode 100755 index 000000000..e90f57d05 --- /dev/null +++ b/win32/include/boost/fusion/functional/invocation/limits.hpp @@ -0,0 +1,23 @@ +/*============================================================================= + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_FUNCTIONAL_INVOCATION_LIMITS_HPP_INCLUDED) +# define BOOST_FUSION_FUNCTIONAL_INVOCATION_LIMITS_HPP_INCLUDED + +# if !defined(BOOST_FUSION_INVOKE_MAX_ARITY) +# define BOOST_FUSION_INVOKE_MAX_ARITY 6 +# endif +# if !defined(BOOST_FUSION_INVOKE_PROCEDURE_MAX_ARITY) +# define BOOST_FUSION_INVOKE_PROCEDURE_MAX_ARITY 6 +# endif +# if !defined(BOOST_FUSION_INVOKE_FUNCTION_OBJECT_MAX_ARITY) +# define BOOST_FUSION_INVOKE_FUNCTION_OBJECT_MAX_ARITY 6 +# endif + +#endif + diff --git a/win32/include/boost/fusion/include/accumulate.hpp b/win32/include/boost/fusion/include/accumulate.hpp new file mode 100755 index 000000000..be3c1c39c --- /dev/null +++ b/win32/include/boost/fusion/include/accumulate.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ACCUMULATE) +#define FUSION_INCLUDE_ACCUMULATE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/adapt_struct.hpp b/win32/include/boost/fusion/include/adapt_struct.hpp new file mode 100755 index 000000000..8d1202539 --- /dev/null +++ b/win32/include/boost/fusion/include/adapt_struct.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ADAPT_STRUCT) +#define FUSION_INCLUDE_ADAPT_STRUCT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/adapted.hpp b/win32/include/boost/fusion/include/adapted.hpp new file mode 100755 index 000000000..17dcb164a --- /dev/null +++ b/win32/include/boost/fusion/include/adapted.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ADAPTED) +#define FUSION_INCLUDE_ADAPTED + +#include + +#endif diff --git a/win32/include/boost/fusion/include/adapter.hpp b/win32/include/boost/fusion/include/adapter.hpp new file mode 100755 index 000000000..b94591f29 --- /dev/null +++ b/win32/include/boost/fusion/include/adapter.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ADAPTER) +#define FUSION_INCLUDE_ADAPTER + +#include + +#endif diff --git a/win32/include/boost/fusion/include/advance.hpp b/win32/include/boost/fusion/include/advance.hpp new file mode 100755 index 000000000..067423712 --- /dev/null +++ b/win32/include/boost/fusion/include/advance.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ADVANCE) +#define FUSION_INCLUDE_ADVANCE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/algorithm.hpp b/win32/include/boost/fusion/include/algorithm.hpp new file mode 100755 index 000000000..2bb296c1e --- /dev/null +++ b/win32/include/boost/fusion/include/algorithm.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ALGORITHM) +#define FUSION_INCLUDE_ALGORITHM + +#include + +#endif diff --git a/win32/include/boost/fusion/include/all.hpp b/win32/include/boost/fusion/include/all.hpp new file mode 100755 index 000000000..b8254c91c --- /dev/null +++ b/win32/include/boost/fusion/include/all.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ALL) +#define FUSION_INCLUDE_ALL + +#include + +#endif diff --git a/win32/include/boost/fusion/include/any.hpp b/win32/include/boost/fusion/include/any.hpp new file mode 100755 index 000000000..891f1ea42 --- /dev/null +++ b/win32/include/boost/fusion/include/any.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ANY) +#define FUSION_INCLUDE_ANY + +#include + +#endif diff --git a/win32/include/boost/fusion/include/array.hpp b/win32/include/boost/fusion/include/array.hpp new file mode 100755 index 000000000..31f2aa66c --- /dev/null +++ b/win32/include/boost/fusion/include/array.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ARRAY) +#define FUSION_INCLUDE_ARRAY + +#include + +#endif diff --git a/win32/include/boost/fusion/include/as_deque.hpp b/win32/include/boost/fusion/include/as_deque.hpp new file mode 100755 index 000000000..45c27ed83 --- /dev/null +++ b/win32/include/boost/fusion/include/as_deque.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_AS_DEQUE) +#define FUSION_INCLUDE_AS_DEQUE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/as_list.hpp b/win32/include/boost/fusion/include/as_list.hpp new file mode 100755 index 000000000..d67d53ce7 --- /dev/null +++ b/win32/include/boost/fusion/include/as_list.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_AS_LIST) +#define FUSION_INCLUDE_AS_LIST + +#include + +#endif diff --git a/win32/include/boost/fusion/include/as_map.hpp b/win32/include/boost/fusion/include/as_map.hpp new file mode 100755 index 000000000..c56e8e54b --- /dev/null +++ b/win32/include/boost/fusion/include/as_map.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_AS_MAP) +#define FUSION_INCLUDE_AS_MAP + +#include + +#endif diff --git a/win32/include/boost/fusion/include/as_set.hpp b/win32/include/boost/fusion/include/as_set.hpp new file mode 100755 index 000000000..fa2721185 --- /dev/null +++ b/win32/include/boost/fusion/include/as_set.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_AS_SET) +#define FUSION_INCLUDE_AS_SET + +#include + +#endif diff --git a/win32/include/boost/fusion/include/as_vector.hpp b/win32/include/boost/fusion/include/as_vector.hpp new file mode 100755 index 000000000..e213f2350 --- /dev/null +++ b/win32/include/boost/fusion/include/as_vector.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_AS_VECTOR) +#define FUSION_INCLUDE_AS_VECTOR + +#include + +#endif diff --git a/win32/include/boost/fusion/include/at.hpp b/win32/include/boost/fusion/include/at.hpp new file mode 100755 index 000000000..0eaf5c5f4 --- /dev/null +++ b/win32/include/boost/fusion/include/at.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_AT) +#define FUSION_INCLUDE_AT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/at_key.hpp b/win32/include/boost/fusion/include/at_key.hpp new file mode 100755 index 000000000..dbeded3c2 --- /dev/null +++ b/win32/include/boost/fusion/include/at_key.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_AT_KEY) +#define FUSION_INCLUDE_AT_KEY + +#include + +#endif diff --git a/win32/include/boost/fusion/include/back.hpp b/win32/include/boost/fusion/include/back.hpp new file mode 100755 index 000000000..b58621d14 --- /dev/null +++ b/win32/include/boost/fusion/include/back.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_BACK) +#define FUSION_INCLUDE_BACK + +#include + +#endif diff --git a/win32/include/boost/fusion/include/begin.hpp b/win32/include/boost/fusion/include/begin.hpp new file mode 100755 index 000000000..dba926b38 --- /dev/null +++ b/win32/include/boost/fusion/include/begin.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_BEGIN) +#define FUSION_INCLUDE_BEGIN + +#include + +#endif diff --git a/win32/include/boost/fusion/include/boost_tuple.hpp b/win32/include/boost/fusion/include/boost_tuple.hpp new file mode 100755 index 000000000..c56b7eddc --- /dev/null +++ b/win32/include/boost/fusion/include/boost_tuple.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_BOOST_TUPLE) +#define FUSION_INCLUDE_BOOST_TUPLE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/category_of.hpp b/win32/include/boost/fusion/include/category_of.hpp new file mode 100755 index 000000000..787d8afd8 --- /dev/null +++ b/win32/include/boost/fusion/include/category_of.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_CATEGORY_OF) +#define FUSION_INCLUDE_CATEGORY_OF + +#include + +#endif diff --git a/win32/include/boost/fusion/include/clear.hpp b/win32/include/boost/fusion/include/clear.hpp new file mode 100755 index 000000000..895b112b2 --- /dev/null +++ b/win32/include/boost/fusion/include/clear.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_CLEAR) +#define FUSION_INCLUDE_CLEAR + +#include + +#endif diff --git a/win32/include/boost/fusion/include/comparison.hpp b/win32/include/boost/fusion/include/comparison.hpp new file mode 100755 index 000000000..f55169dc3 --- /dev/null +++ b/win32/include/boost/fusion/include/comparison.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_COMPARISON) +#define FUSION_INCLUDE_COMPARISON + +#include + +#endif diff --git a/win32/include/boost/fusion/include/cons.hpp b/win32/include/boost/fusion/include/cons.hpp new file mode 100755 index 000000000..b0f257d38 --- /dev/null +++ b/win32/include/boost/fusion/include/cons.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_CONS) +#define FUSION_INCLUDE_CONS + +#include + +#endif diff --git a/win32/include/boost/fusion/include/cons_tie.hpp b/win32/include/boost/fusion/include/cons_tie.hpp new file mode 100755 index 000000000..d79f54590 --- /dev/null +++ b/win32/include/boost/fusion/include/cons_tie.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_CONS_TIE) +#define FUSION_INCLUDE_CONS_TIE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/container.hpp b/win32/include/boost/fusion/include/container.hpp new file mode 100755 index 000000000..984d46c74 --- /dev/null +++ b/win32/include/boost/fusion/include/container.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_CONTAINER) +#define FUSION_INCLUDE_CONTAINER + +#include + +#endif diff --git a/win32/include/boost/fusion/include/convert.hpp b/win32/include/boost/fusion/include/convert.hpp new file mode 100755 index 000000000..16a9fa881 --- /dev/null +++ b/win32/include/boost/fusion/include/convert.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_CONVERT) +#define FUSION_INCLUDE_CONVERT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/count.hpp b/win32/include/boost/fusion/include/count.hpp new file mode 100755 index 000000000..793898d29 --- /dev/null +++ b/win32/include/boost/fusion/include/count.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_COUNT) +#define FUSION_INCLUDE_COUNT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/count_if.hpp b/win32/include/boost/fusion/include/count_if.hpp new file mode 100755 index 000000000..6ba0a10da --- /dev/null +++ b/win32/include/boost/fusion/include/count_if.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_COUNT_IF) +#define FUSION_INCLUDE_COUNT_IF + +#include + +#endif diff --git a/win32/include/boost/fusion/include/deduce.hpp b/win32/include/boost/fusion/include/deduce.hpp new file mode 100755 index 000000000..88a3c85c6 --- /dev/null +++ b/win32/include/boost/fusion/include/deduce.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_DEDUCE) +#define FUSION_INCLUDE_DEDUCE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/deduce_sequence.hpp b/win32/include/boost/fusion/include/deduce_sequence.hpp new file mode 100755 index 000000000..3e88ea6a9 --- /dev/null +++ b/win32/include/boost/fusion/include/deduce_sequence.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_DEDUCE_SEQUENCE) +#define FUSION_INCLUDE_DEDUCE_SEQUENCE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/deque.hpp b/win32/include/boost/fusion/include/deque.hpp new file mode 100755 index 000000000..2df2648fd --- /dev/null +++ b/win32/include/boost/fusion/include/deque.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_DEQUE) +#define FUSION_INCLUDE_DEQUE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/deque_fwd.hpp b/win32/include/boost/fusion/include/deque_fwd.hpp new file mode 100755 index 000000000..b81d8d386 --- /dev/null +++ b/win32/include/boost/fusion/include/deque_fwd.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_DEQUE) +#define FUSION_INCLUDE_DEQUE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/deque_tie.hpp b/win32/include/boost/fusion/include/deque_tie.hpp new file mode 100755 index 000000000..e5c3fba17 --- /dev/null +++ b/win32/include/boost/fusion/include/deque_tie.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_GENERATION) +#define FUSION_INCLUDE_GENERATION + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/include/deref.hpp b/win32/include/boost/fusion/include/deref.hpp new file mode 100755 index 000000000..0cee05bc0 --- /dev/null +++ b/win32/include/boost/fusion/include/deref.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_DEREF) +#define FUSION_INCLUDE_DEREF + +#include + +#endif diff --git a/win32/include/boost/fusion/include/distance.hpp b/win32/include/boost/fusion/include/distance.hpp new file mode 100755 index 000000000..5e68437e7 --- /dev/null +++ b/win32/include/boost/fusion/include/distance.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_DISTANCE) +#define FUSION_INCLUDE_DISTANCE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/empty.hpp b/win32/include/boost/fusion/include/empty.hpp new file mode 100755 index 000000000..884db51c2 --- /dev/null +++ b/win32/include/boost/fusion/include/empty.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_EMPTY) +#define FUSION_INCLUDE_EMPTY + +#include + +#endif diff --git a/win32/include/boost/fusion/include/end.hpp b/win32/include/boost/fusion/include/end.hpp new file mode 100755 index 000000000..6e8a22fec --- /dev/null +++ b/win32/include/boost/fusion/include/end.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_BEGIN) +#define FUSION_INCLUDE_BEGIN + +#include + +#endif diff --git a/win32/include/boost/fusion/include/equal_to.hpp b/win32/include/boost/fusion/include/equal_to.hpp new file mode 100755 index 000000000..b8c89c50e --- /dev/null +++ b/win32/include/boost/fusion/include/equal_to.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_EQUAL_TO) +#define FUSION_INCLUDE_EQUAL_TO + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/include/erase.hpp b/win32/include/boost/fusion/include/erase.hpp new file mode 100755 index 000000000..dec92fb2f --- /dev/null +++ b/win32/include/boost/fusion/include/erase.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ERASE) +#define FUSION_INCLUDE_ERASE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/erase_key.hpp b/win32/include/boost/fusion/include/erase_key.hpp new file mode 100755 index 000000000..4ce77b544 --- /dev/null +++ b/win32/include/boost/fusion/include/erase_key.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ERASE_KEY) +#define FUSION_INCLUDE_ERASE_KEY + +#include + +#endif diff --git a/win32/include/boost/fusion/include/filter.hpp b/win32/include/boost/fusion/include/filter.hpp new file mode 100755 index 000000000..e02103c4a --- /dev/null +++ b/win32/include/boost/fusion/include/filter.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_FILTER) +#define FUSION_INCLUDE_FILTER + +#include + +#endif diff --git a/win32/include/boost/fusion/include/filter_if.hpp b/win32/include/boost/fusion/include/filter_if.hpp new file mode 100755 index 000000000..c8780745c --- /dev/null +++ b/win32/include/boost/fusion/include/filter_if.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_FILTER_IF) +#define FUSION_INCLUDE_FILTER_IF + +#include + +#endif diff --git a/win32/include/boost/fusion/include/filter_view.hpp b/win32/include/boost/fusion/include/filter_view.hpp new file mode 100755 index 000000000..2ffe94522 --- /dev/null +++ b/win32/include/boost/fusion/include/filter_view.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_FILTER_VIEW) +#define FUSION_INCLUDE_FILTER_VIEW + +#include + +#endif diff --git a/win32/include/boost/fusion/include/find.hpp b/win32/include/boost/fusion/include/find.hpp new file mode 100755 index 000000000..deb9545d7 --- /dev/null +++ b/win32/include/boost/fusion/include/find.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_FIND) +#define FUSION_INCLUDE_FIND + +#include + +#endif diff --git a/win32/include/boost/fusion/include/find_if.hpp b/win32/include/boost/fusion/include/find_if.hpp new file mode 100755 index 000000000..bede105a2 --- /dev/null +++ b/win32/include/boost/fusion/include/find_if.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_FIND_IF) +#define FUSION_INCLUDE_FIND_IF + +#include + +#endif diff --git a/win32/include/boost/fusion/include/fold.hpp b/win32/include/boost/fusion/include/fold.hpp new file mode 100755 index 000000000..d294cc1d1 --- /dev/null +++ b/win32/include/boost/fusion/include/fold.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_FOLD) +#define FUSION_INCLUDE_FOLD + +#include + +#endif diff --git a/win32/include/boost/fusion/include/for_each.hpp b/win32/include/boost/fusion/include/for_each.hpp new file mode 100755 index 000000000..f8959acb7 --- /dev/null +++ b/win32/include/boost/fusion/include/for_each.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_FOR_EACH) +#define FUSION_INCLUDE_FOR_EACH + +#include + +#endif diff --git a/win32/include/boost/fusion/include/front.hpp b/win32/include/boost/fusion/include/front.hpp new file mode 100755 index 000000000..aa0a4ad05 --- /dev/null +++ b/win32/include/boost/fusion/include/front.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_FRONT) +#define FUSION_INCLUDE_FRONT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/functional.hpp b/win32/include/boost/fusion/include/functional.hpp new file mode 100755 index 000000000..19d4240f7 --- /dev/null +++ b/win32/include/boost/fusion/include/functional.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_FUNCTIONAL) +#define FUSION_INCLUDE_FUNCTIONAL + +#include + +#endif diff --git a/win32/include/boost/fusion/include/fused.hpp b/win32/include/boost/fusion/include/fused.hpp new file mode 100755 index 000000000..b4f964a99 --- /dev/null +++ b/win32/include/boost/fusion/include/fused.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_FUSED) +#define FUSION_INCLUDE_FUSED + +#include + +#endif diff --git a/win32/include/boost/fusion/include/fused_function_object.hpp b/win32/include/boost/fusion/include/fused_function_object.hpp new file mode 100755 index 000000000..3299128e5 --- /dev/null +++ b/win32/include/boost/fusion/include/fused_function_object.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_FUSED_FUNCTION_OBJECT) +#define FUSION_INCLUDE_FUSED_FUNCTION_OBJECT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/fused_procedure.hpp b/win32/include/boost/fusion/include/fused_procedure.hpp new file mode 100755 index 000000000..d36e0ed3e --- /dev/null +++ b/win32/include/boost/fusion/include/fused_procedure.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_FUSED_PROCEDURE) +#define FUSION_INCLUDE_FUSED_PROCEDURE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/generation.hpp b/win32/include/boost/fusion/include/generation.hpp new file mode 100755 index 000000000..e5c3fba17 --- /dev/null +++ b/win32/include/boost/fusion/include/generation.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_GENERATION) +#define FUSION_INCLUDE_GENERATION + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/include/greater.hpp b/win32/include/boost/fusion/include/greater.hpp new file mode 100755 index 000000000..d0de047da --- /dev/null +++ b/win32/include/boost/fusion/include/greater.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_NOT_GREATER) +#define FUSION_INCLUDE_NOT_GREATER + +#include + +#endif diff --git a/win32/include/boost/fusion/include/greater_equal.hpp b/win32/include/boost/fusion/include/greater_equal.hpp new file mode 100755 index 000000000..b1e7a3977 --- /dev/null +++ b/win32/include/boost/fusion/include/greater_equal.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_GREATER_EQUAL) +#define FUSION_INCLUDE_GREATER_EQUAL + +#include + +#endif diff --git a/win32/include/boost/fusion/include/has_key.hpp b/win32/include/boost/fusion/include/has_key.hpp new file mode 100755 index 000000000..acd578b3b --- /dev/null +++ b/win32/include/boost/fusion/include/has_key.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_HAS_KEY) +#define FUSION_INCLUDE_EMPTY + +#include + +#endif diff --git a/win32/include/boost/fusion/include/ignore.hpp b/win32/include/boost/fusion/include/ignore.hpp new file mode 100755 index 000000000..e5c3fba17 --- /dev/null +++ b/win32/include/boost/fusion/include/ignore.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_GENERATION) +#define FUSION_INCLUDE_GENERATION + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/include/in.hpp b/win32/include/boost/fusion/include/in.hpp new file mode 100755 index 000000000..85d474ed8 --- /dev/null +++ b/win32/include/boost/fusion/include/in.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 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(FUSION_INCLUDE_IN) +#define FUSION_INCLUDE_IN + +#include + +#endif diff --git a/win32/include/boost/fusion/include/insert.hpp b/win32/include/boost/fusion/include/insert.hpp new file mode 100755 index 000000000..38378ef99 --- /dev/null +++ b/win32/include/boost/fusion/include/insert.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_INSERT) +#define FUSION_INCLUDE_INSERT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/insert_range.hpp b/win32/include/boost/fusion/include/insert_range.hpp new file mode 100755 index 000000000..39b88fe26 --- /dev/null +++ b/win32/include/boost/fusion/include/insert_range.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_INSERT_RANGE) +#define FUSION_INCLUDE_INSERT_RANGE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/intrinsic.hpp b/win32/include/boost/fusion/include/intrinsic.hpp new file mode 100755 index 000000000..3c8e13558 --- /dev/null +++ b/win32/include/boost/fusion/include/intrinsic.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_INTRINSIC) +#define FUSION_INCLUDE_INTRINSIC + +#include + +#endif diff --git a/win32/include/boost/fusion/include/invocation.hpp b/win32/include/boost/fusion/include/invocation.hpp new file mode 100755 index 000000000..f9f35b745 --- /dev/null +++ b/win32/include/boost/fusion/include/invocation.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_INVOCATION) +#define FUSION_INCLUDE_INVOCATION + +#include + +#endif diff --git a/win32/include/boost/fusion/include/invoke.hpp b/win32/include/boost/fusion/include/invoke.hpp new file mode 100755 index 000000000..c63e59793 --- /dev/null +++ b/win32/include/boost/fusion/include/invoke.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_INVOKE) +#define FUSION_INCLUDE_INVOKE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/invoke_function_object.hpp b/win32/include/boost/fusion/include/invoke_function_object.hpp new file mode 100755 index 000000000..ac9ca1967 --- /dev/null +++ b/win32/include/boost/fusion/include/invoke_function_object.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_INVOKE_FUNCTION_OBJECT) +#define FUSION_INCLUDE_INVOKE_FUNCTION_OBJECT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/invoke_procedure.hpp b/win32/include/boost/fusion/include/invoke_procedure.hpp new file mode 100755 index 000000000..a5872ff9c --- /dev/null +++ b/win32/include/boost/fusion/include/invoke_procedure.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_INVOKE_PROCEDURE) +#define FUSION_INCLUDE_INVOKE_PROCEDURE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/io.hpp b/win32/include/boost/fusion/include/io.hpp new file mode 100755 index 000000000..cd4015db3 --- /dev/null +++ b/win32/include/boost/fusion/include/io.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 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(FUSION_INCLUDE_IO) +#define FUSION_INCLUDE_IO + +#include + +#endif diff --git a/win32/include/boost/fusion/include/is_iterator.hpp b/win32/include/boost/fusion/include/is_iterator.hpp new file mode 100755 index 000000000..be8fc932c --- /dev/null +++ b/win32/include/boost/fusion/include/is_iterator.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_IS_ITERATOR) +#define FUSION_INCLUDE_IS_ITERATOR + +#include + +#endif diff --git a/win32/include/boost/fusion/include/is_sequence.hpp b/win32/include/boost/fusion/include/is_sequence.hpp new file mode 100755 index 000000000..4007a9074 --- /dev/null +++ b/win32/include/boost/fusion/include/is_sequence.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_IS_SEQUENCE) +#define FUSION_INCLUDE_IS_SEQUENCE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/is_view.hpp b/win32/include/boost/fusion/include/is_view.hpp new file mode 100755 index 000000000..d42f34464 --- /dev/null +++ b/win32/include/boost/fusion/include/is_view.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_IS_VIEW) +#define FUSION_INCLUDE_IS_VIEW + +#include + +#endif diff --git a/win32/include/boost/fusion/include/iteration.hpp b/win32/include/boost/fusion/include/iteration.hpp new file mode 100755 index 000000000..ea8494ba3 --- /dev/null +++ b/win32/include/boost/fusion/include/iteration.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ITERATION) +#define FUSION_INCLUDE_ITERATION + +#include + +#endif diff --git a/win32/include/boost/fusion/include/iterator.hpp b/win32/include/boost/fusion/include/iterator.hpp new file mode 100755 index 000000000..bc1dc426e --- /dev/null +++ b/win32/include/boost/fusion/include/iterator.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ITERATOR) +#define FUSION_INCLUDE_ITERATOR + +#include + +#endif diff --git a/win32/include/boost/fusion/include/iterator_base.hpp b/win32/include/boost/fusion/include/iterator_base.hpp new file mode 100755 index 000000000..738781dd7 --- /dev/null +++ b/win32/include/boost/fusion/include/iterator_base.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ITERATOR_BASE) +#define FUSION_INCLUDE_ITERATOR_BASE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/iterator_facade.hpp b/win32/include/boost/fusion/include/iterator_facade.hpp new file mode 100755 index 000000000..db30003d1 --- /dev/null +++ b/win32/include/boost/fusion/include/iterator_facade.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ITERATOR_FACADE) +#define FUSION_INCLUDE_ITERATOR_FACADE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/iterator_range.hpp b/win32/include/boost/fusion/include/iterator_range.hpp new file mode 100755 index 000000000..0f5f95f03 --- /dev/null +++ b/win32/include/boost/fusion/include/iterator_range.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ITERATOR_RANGE) +#define FUSION_INCLUDE_ITERATOR_RANGE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/join.hpp b/win32/include/boost/fusion/include/join.hpp new file mode 100755 index 000000000..3db572517 --- /dev/null +++ b/win32/include/boost/fusion/include/join.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_JOIN) +#define FUSION_INCLUDE_JOIN + +#include + +#endif diff --git a/win32/include/boost/fusion/include/joint_view.hpp b/win32/include/boost/fusion/include/joint_view.hpp new file mode 100755 index 000000000..22a3d51b9 --- /dev/null +++ b/win32/include/boost/fusion/include/joint_view.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_JOINT_VIEW) +#define FUSION_INCLUDE_JOINT_VIEW + +#include + +#endif diff --git a/win32/include/boost/fusion/include/less.hpp b/win32/include/boost/fusion/include/less.hpp new file mode 100755 index 000000000..e04cc168c --- /dev/null +++ b/win32/include/boost/fusion/include/less.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_LESS) +#define FUSION_INCLUDE_LESS + +#include + +#endif diff --git a/win32/include/boost/fusion/include/less_equal.hpp b/win32/include/boost/fusion/include/less_equal.hpp new file mode 100755 index 000000000..288a8927c --- /dev/null +++ b/win32/include/boost/fusion/include/less_equal.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_LESS_EQUAL) +#define FUSION_INCLUDE_LESS_EQUAL + +#include + +#endif diff --git a/win32/include/boost/fusion/include/list.hpp b/win32/include/boost/fusion/include/list.hpp new file mode 100755 index 000000000..05973de6d --- /dev/null +++ b/win32/include/boost/fusion/include/list.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_LIST) +#define FUSION_INCLUDE_LIST + +#include + +#endif diff --git a/win32/include/boost/fusion/include/list_fwd.hpp b/win32/include/boost/fusion/include/list_fwd.hpp new file mode 100755 index 000000000..047fb283c --- /dev/null +++ b/win32/include/boost/fusion/include/list_fwd.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_LIST_FWD) +#define FUSION_INCLUDE_LIST_FWD + +#include + +#endif diff --git a/win32/include/boost/fusion/include/list_tie.hpp b/win32/include/boost/fusion/include/list_tie.hpp new file mode 100755 index 000000000..e5c3fba17 --- /dev/null +++ b/win32/include/boost/fusion/include/list_tie.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_GENERATION) +#define FUSION_INCLUDE_GENERATION + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/include/make_cons.hpp b/win32/include/boost/fusion/include/make_cons.hpp new file mode 100755 index 000000000..92ed25d3f --- /dev/null +++ b/win32/include/boost/fusion/include/make_cons.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAKE_CONS) +#define FUSION_INCLUDE_MAKE_CONS + +#include + +#endif diff --git a/win32/include/boost/fusion/include/make_deque.hpp b/win32/include/boost/fusion/include/make_deque.hpp new file mode 100755 index 000000000..3c88d1f58 --- /dev/null +++ b/win32/include/boost/fusion/include/make_deque.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAKE_DEQUE) +#define FUSION_INCLUDE_MAKE_DEQUE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/make_fused.hpp b/win32/include/boost/fusion/include/make_fused.hpp new file mode 100755 index 000000000..e58c4518b --- /dev/null +++ b/win32/include/boost/fusion/include/make_fused.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAKE_FUSED) +#define FUSION_INCLUDE_MAKE_FUSED + +#include + +#endif diff --git a/win32/include/boost/fusion/include/make_fused_function_object.hpp b/win32/include/boost/fusion/include/make_fused_function_object.hpp new file mode 100755 index 000000000..cd39298c8 --- /dev/null +++ b/win32/include/boost/fusion/include/make_fused_function_object.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAKE_FUSED_FUNCTION_OBJECT) +#define FUSION_INCLUDE_MAKE_FUSED_FUNCTION_OBJECT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/make_fused_procedure.hpp b/win32/include/boost/fusion/include/make_fused_procedure.hpp new file mode 100755 index 000000000..19022a1ec --- /dev/null +++ b/win32/include/boost/fusion/include/make_fused_procedure.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAKE_FUSED_PROCEDURE) +#define FUSION_INCLUDE_MAKE_FUSED_PROCEDURE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/make_list.hpp b/win32/include/boost/fusion/include/make_list.hpp new file mode 100755 index 000000000..27c80c047 --- /dev/null +++ b/win32/include/boost/fusion/include/make_list.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAKE_LIST) +#define FUSION_INCLUDE_MAKE_LIST + +#include + +#endif diff --git a/win32/include/boost/fusion/include/make_map.hpp b/win32/include/boost/fusion/include/make_map.hpp new file mode 100755 index 000000000..f8a83c32c --- /dev/null +++ b/win32/include/boost/fusion/include/make_map.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAKE_MAP) +#define FUSION_INCLUDE_MAKE_MAP + +#include + +#endif diff --git a/win32/include/boost/fusion/include/make_set.hpp b/win32/include/boost/fusion/include/make_set.hpp new file mode 100755 index 000000000..1896ed3a8 --- /dev/null +++ b/win32/include/boost/fusion/include/make_set.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAKE_SET) +#define FUSION_INCLUDE_MAKE_SET + +#include + +#endif diff --git a/win32/include/boost/fusion/include/make_tuple.hpp b/win32/include/boost/fusion/include/make_tuple.hpp new file mode 100755 index 000000000..49b653edd --- /dev/null +++ b/win32/include/boost/fusion/include/make_tuple.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAKE_TUPLE) +#define FUSION_INCLUDE_MAKE_TUPLE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/make_unfused_generic.hpp b/win32/include/boost/fusion/include/make_unfused_generic.hpp new file mode 100755 index 000000000..4fea38d1b --- /dev/null +++ b/win32/include/boost/fusion/include/make_unfused_generic.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAKE_UNFUSED_GENERIC) +#define FUSION_INCLUDE_MAKE_UNFUSED_GENERIC + +#include + +#endif diff --git a/win32/include/boost/fusion/include/make_unfused_lvalue_args.hpp b/win32/include/boost/fusion/include/make_unfused_lvalue_args.hpp new file mode 100755 index 000000000..ce85b0cc5 --- /dev/null +++ b/win32/include/boost/fusion/include/make_unfused_lvalue_args.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAKE_UNFUSED_LVALUE_ARGS) +#define FUSION_INCLUDE_MAKE_UNFUSED_LVALUE_ARGS + +#include + +#endif diff --git a/win32/include/boost/fusion/include/make_unfused_rvalue_args.hpp b/win32/include/boost/fusion/include/make_unfused_rvalue_args.hpp new file mode 100755 index 000000000..9960c8172 --- /dev/null +++ b/win32/include/boost/fusion/include/make_unfused_rvalue_args.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAKE_UNFUSED_RVALUE_ARGS) +#define FUSION_INCLUDE_MAKE_UNFUSED_RVALUE_ARGS + +#include + +#endif diff --git a/win32/include/boost/fusion/include/make_vector.hpp b/win32/include/boost/fusion/include/make_vector.hpp new file mode 100755 index 000000000..92bea2fb6 --- /dev/null +++ b/win32/include/boost/fusion/include/make_vector.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAKE_VECTOR) +#define FUSION_INCLUDE_MAKE_VECTOR + +#include + +#endif diff --git a/win32/include/boost/fusion/include/map.hpp b/win32/include/boost/fusion/include/map.hpp new file mode 100755 index 000000000..4800d00c7 --- /dev/null +++ b/win32/include/boost/fusion/include/map.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAP) +#define FUSION_INCLUDE_MAP + +#include + +#endif diff --git a/win32/include/boost/fusion/include/map_fwd.hpp b/win32/include/boost/fusion/include/map_fwd.hpp new file mode 100755 index 000000000..ef1111e78 --- /dev/null +++ b/win32/include/boost/fusion/include/map_fwd.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAP_FWD) +#define FUSION_INCLUDE_MAP_FWD + +#include + +#endif diff --git a/win32/include/boost/fusion/include/map_tie.hpp b/win32/include/boost/fusion/include/map_tie.hpp new file mode 100755 index 000000000..eed3f9b5f --- /dev/null +++ b/win32/include/boost/fusion/include/map_tie.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MAP_TIE) +#define FUSION_INCLUDE_MAP_TIE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/mpl.hpp b/win32/include/boost/fusion/include/mpl.hpp new file mode 100755 index 000000000..2d07a1e21 --- /dev/null +++ b/win32/include/boost/fusion/include/mpl.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_MPL) +#define FUSION_INCLUDE_MPL + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/include/next.hpp b/win32/include/boost/fusion/include/next.hpp new file mode 100755 index 000000000..1c63f193d --- /dev/null +++ b/win32/include/boost/fusion/include/next.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_NEXT) +#define FUSION_INCLUDE_NEXT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/none.hpp b/win32/include/boost/fusion/include/none.hpp new file mode 100755 index 000000000..fc475a7cd --- /dev/null +++ b/win32/include/boost/fusion/include/none.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_NONE) +#define FUSION_INCLUDE_NONE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/not_equal_to.hpp b/win32/include/boost/fusion/include/not_equal_to.hpp new file mode 100755 index 000000000..46433bc98 --- /dev/null +++ b/win32/include/boost/fusion/include/not_equal_to.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_NOT_EQUAL_TO) +#define FUSION_INCLUDE_NOT_EQUAL_TO + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/include/out.hpp b/win32/include/boost/fusion/include/out.hpp new file mode 100755 index 000000000..f4df7b5c3 --- /dev/null +++ b/win32/include/boost/fusion/include/out.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 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(FUSION_INCLUDE_OUT) +#define FUSION_INCLUDE_OUT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/pair.hpp b/win32/include/boost/fusion/include/pair.hpp new file mode 100755 index 000000000..8bf6c9672 --- /dev/null +++ b/win32/include/boost/fusion/include/pair.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_PAIR) +#define FUSION_INCLUDE_PAIR + +#include + +#endif diff --git a/win32/include/boost/fusion/include/pair_tie.hpp b/win32/include/boost/fusion/include/pair_tie.hpp new file mode 100755 index 000000000..067bbf476 --- /dev/null +++ b/win32/include/boost/fusion/include/pair_tie.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_PAIR_TIE) +#define FUSION_INCLUDE_PAIR_TIE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/pop_back.hpp b/win32/include/boost/fusion/include/pop_back.hpp new file mode 100755 index 000000000..007ae13d8 --- /dev/null +++ b/win32/include/boost/fusion/include/pop_back.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_POP_BACK) +#define FUSION_INCLUDE_POP_BACK + +#include + +#endif diff --git a/win32/include/boost/fusion/include/pop_front.hpp b/win32/include/boost/fusion/include/pop_front.hpp new file mode 100755 index 000000000..fe3e90010 --- /dev/null +++ b/win32/include/boost/fusion/include/pop_front.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_POP_FRONT) +#define FUSION_INCLUDE_POP_FRONT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/prior.hpp b/win32/include/boost/fusion/include/prior.hpp new file mode 100755 index 000000000..00b19be27 --- /dev/null +++ b/win32/include/boost/fusion/include/prior.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_PRIOR) +#define FUSION_INCLUDE_PRIOR + +#include + +#endif diff --git a/win32/include/boost/fusion/include/push_back.hpp b/win32/include/boost/fusion/include/push_back.hpp new file mode 100755 index 000000000..6924cc1ec --- /dev/null +++ b/win32/include/boost/fusion/include/push_back.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_PUSH_BACK) +#define FUSION_INCLUDE_PUSH_BACK + +#include + +#endif diff --git a/win32/include/boost/fusion/include/push_front.hpp b/win32/include/boost/fusion/include/push_front.hpp new file mode 100755 index 000000000..0e4b88d6a --- /dev/null +++ b/win32/include/boost/fusion/include/push_front.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_PUSH_FRONT) +#define FUSION_INCLUDE_PUSH_FRONT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/query.hpp b/win32/include/boost/fusion/include/query.hpp new file mode 100755 index 000000000..43f97629d --- /dev/null +++ b/win32/include/boost/fusion/include/query.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_QUERY) +#define FUSION_INCLUDE_QUERY + +#include + +#endif diff --git a/win32/include/boost/fusion/include/remove.hpp b/win32/include/boost/fusion/include/remove.hpp new file mode 100755 index 000000000..644081746 --- /dev/null +++ b/win32/include/boost/fusion/include/remove.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_REMOVE_IF) +#define FUSION_INCLUDE_REMOVE_IF + +#include + +#endif diff --git a/win32/include/boost/fusion/include/remove_if.hpp b/win32/include/boost/fusion/include/remove_if.hpp new file mode 100755 index 000000000..644081746 --- /dev/null +++ b/win32/include/boost/fusion/include/remove_if.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_REMOVE_IF) +#define FUSION_INCLUDE_REMOVE_IF + +#include + +#endif diff --git a/win32/include/boost/fusion/include/repetetive_view.hpp b/win32/include/boost/fusion/include/repetetive_view.hpp new file mode 100755 index 000000000..4773c8e7d --- /dev/null +++ b/win32/include/boost/fusion/include/repetetive_view.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_REPETETIVE_VIEW) +#define FUSION_INCLUDE_REPETETIVE_VIEW + +#include + +#endif diff --git a/win32/include/boost/fusion/include/replace.hpp b/win32/include/boost/fusion/include/replace.hpp new file mode 100755 index 000000000..0f9176b68 --- /dev/null +++ b/win32/include/boost/fusion/include/replace.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_REPLACE) +#define FUSION_INCLUDE_REPLACE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/replace_if.hpp b/win32/include/boost/fusion/include/replace_if.hpp new file mode 100755 index 000000000..fc0216398 --- /dev/null +++ b/win32/include/boost/fusion/include/replace_if.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_REPLACE_IF) +#define FUSION_INCLUDE_REPLACE_IF + +#include + +#endif diff --git a/win32/include/boost/fusion/include/reverse.hpp b/win32/include/boost/fusion/include/reverse.hpp new file mode 100755 index 000000000..250d037bf --- /dev/null +++ b/win32/include/boost/fusion/include/reverse.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_REVERSE) +#define FUSION_INCLUDE_REVERSE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/reverse_view.hpp b/win32/include/boost/fusion/include/reverse_view.hpp new file mode 100755 index 000000000..2d47e5db0 --- /dev/null +++ b/win32/include/boost/fusion/include/reverse_view.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_REVERSE_VIEW) +#define FUSION_INCLUDE_REVERSE_VIEW + +#include + +#endif diff --git a/win32/include/boost/fusion/include/sequence.hpp b/win32/include/boost/fusion/include/sequence.hpp new file mode 100755 index 000000000..4d83ba7cc --- /dev/null +++ b/win32/include/boost/fusion/include/sequence.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_SEQUENCE) +#define FUSION_INCLUDE_SEQUENCE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/sequence_base.hpp b/win32/include/boost/fusion/include/sequence_base.hpp new file mode 100755 index 000000000..c68a4fba3 --- /dev/null +++ b/win32/include/boost/fusion/include/sequence_base.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_SEQUENCE_BASE) +#define FUSION_INCLUDE_SEQUENCE_BASE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/sequence_facade.hpp b/win32/include/boost/fusion/include/sequence_facade.hpp new file mode 100755 index 000000000..107e172a1 --- /dev/null +++ b/win32/include/boost/fusion/include/sequence_facade.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_SEQUENCE_FACADE) +#define FUSION_INCLUDE_SEQUENCE_FACADE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/set.hpp b/win32/include/boost/fusion/include/set.hpp new file mode 100755 index 000000000..8773bfc49 --- /dev/null +++ b/win32/include/boost/fusion/include/set.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_SET) +#define FUSION_INCLUDE_SET + +#include + +#endif diff --git a/win32/include/boost/fusion/include/set_fwd.hpp b/win32/include/boost/fusion/include/set_fwd.hpp new file mode 100755 index 000000000..5ddbd51af --- /dev/null +++ b/win32/include/boost/fusion/include/set_fwd.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_SET_FWD) +#define FUSION_INCLUDE_SET_FWD + +#include + +#endif diff --git a/win32/include/boost/fusion/include/single_view.hpp b/win32/include/boost/fusion/include/single_view.hpp new file mode 100755 index 000000000..4eebf1733 --- /dev/null +++ b/win32/include/boost/fusion/include/single_view.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_SINGLE_VIEW) +#define FUSION_INCLUDE_SINGLE_VIEW + +#include + +#endif diff --git a/win32/include/boost/fusion/include/size.hpp b/win32/include/boost/fusion/include/size.hpp new file mode 100755 index 000000000..f4e8a4b2c --- /dev/null +++ b/win32/include/boost/fusion/include/size.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_SIZE) +#define FUSION_INCLUDE_SIZE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/std_pair.hpp b/win32/include/boost/fusion/include/std_pair.hpp new file mode 100755 index 000000000..b15b1449a --- /dev/null +++ b/win32/include/boost/fusion/include/std_pair.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_STD_PAIR) +#define FUSION_INCLUDE_STD_PAIR + +#include + +#endif diff --git a/win32/include/boost/fusion/include/struct.hpp b/win32/include/boost/fusion/include/struct.hpp new file mode 100755 index 000000000..257775546 --- /dev/null +++ b/win32/include/boost/fusion/include/struct.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_STRUCT) +#define FUSION_INCLUDE_STRUCT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/support.hpp b/win32/include/boost/fusion/include/support.hpp new file mode 100755 index 000000000..725aee517 --- /dev/null +++ b/win32/include/boost/fusion/include/support.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_SUPPORT) +#define FUSION_INCLUDE_SUPPORT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/swap.hpp b/win32/include/boost/fusion/include/swap.hpp new file mode 100755 index 000000000..370b2b694 --- /dev/null +++ b/win32/include/boost/fusion/include/swap.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_SWAP) +#define FUSION_INCLUDE_SWAP + +#include + +#endif diff --git a/win32/include/boost/fusion/include/tag_of.hpp b/win32/include/boost/fusion/include/tag_of.hpp new file mode 100755 index 000000000..d07860f85 --- /dev/null +++ b/win32/include/boost/fusion/include/tag_of.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_TAG_OF) +#define FUSION_INCLUDE_TAG_OF + +#include + +#endif diff --git a/win32/include/boost/fusion/include/tag_of_fwd.hpp b/win32/include/boost/fusion/include/tag_of_fwd.hpp new file mode 100755 index 000000000..a0184da3a --- /dev/null +++ b/win32/include/boost/fusion/include/tag_of_fwd.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_TAG_OF_FWD) +#define FUSION_INCLUDE_TAG_OF_FWD + +#include + +#endif diff --git a/win32/include/boost/fusion/include/transform.hpp b/win32/include/boost/fusion/include/transform.hpp new file mode 100755 index 000000000..cbc6dcb25 --- /dev/null +++ b/win32/include/boost/fusion/include/transform.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_TRANSFORM) +#define FUSION_INCLUDE_TRANSFORM + +#include + +#endif diff --git a/win32/include/boost/fusion/include/transform_view.hpp b/win32/include/boost/fusion/include/transform_view.hpp new file mode 100755 index 000000000..fe3628012 --- /dev/null +++ b/win32/include/boost/fusion/include/transform_view.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_TRANSFORM_VIEW) +#define FUSION_INCLUDE_TRANSFORM_VIEW + +#include + +#endif diff --git a/win32/include/boost/fusion/include/transformation.hpp b/win32/include/boost/fusion/include/transformation.hpp new file mode 100755 index 000000000..5a0b7e3c7 --- /dev/null +++ b/win32/include/boost/fusion/include/transformation.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_TRANSFORMATION) +#define FUSION_INCLUDE_TRANSFORMATION + +#include + +#endif diff --git a/win32/include/boost/fusion/include/tuple.hpp b/win32/include/boost/fusion/include/tuple.hpp new file mode 100755 index 000000000..01176b23f --- /dev/null +++ b/win32/include/boost/fusion/include/tuple.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_TUPLE) +#define FUSION_INCLUDE_TUPLE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/tuple_fwd.hpp b/win32/include/boost/fusion/include/tuple_fwd.hpp new file mode 100755 index 000000000..cbf52d8cf --- /dev/null +++ b/win32/include/boost/fusion/include/tuple_fwd.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_TUPLE_FWD) +#define FUSION_INCLUDE_TUPLE_FWD + +#include + +#endif diff --git a/win32/include/boost/fusion/include/tuple_tie.hpp b/win32/include/boost/fusion/include/tuple_tie.hpp new file mode 100755 index 000000000..c1c4aae63 --- /dev/null +++ b/win32/include/boost/fusion/include/tuple_tie.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_TUPLE_TIE) +#define FUSION_INCLUDE_TUPLE_TIE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/unfused_generic.hpp b/win32/include/boost/fusion/include/unfused_generic.hpp new file mode 100755 index 000000000..e916fab9c --- /dev/null +++ b/win32/include/boost/fusion/include/unfused_generic.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_UNFUSED_GENERIC) +#define FUSION_INCLUDE_UNFUSED_GENERIC + +#include + +#endif diff --git a/win32/include/boost/fusion/include/unfused_lvalue_args.hpp b/win32/include/boost/fusion/include/unfused_lvalue_args.hpp new file mode 100755 index 000000000..8c7987113 --- /dev/null +++ b/win32/include/boost/fusion/include/unfused_lvalue_args.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_UNFUSED_LVALUE_ARGS) +#define FUSION_INCLUDE_UNFUSED_LVALUE_ARGS + +#include + +#endif diff --git a/win32/include/boost/fusion/include/unfused_rvalue_args.hpp b/win32/include/boost/fusion/include/unfused_rvalue_args.hpp new file mode 100755 index 000000000..fbd1f631e --- /dev/null +++ b/win32/include/boost/fusion/include/unfused_rvalue_args.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_UNFUSED_RVALUE_ARGS) +#define FUSION_INCLUDE_UNFUSED_RVALUE_ARGS + +#include + +#endif diff --git a/win32/include/boost/fusion/include/unfused_typed.hpp b/win32/include/boost/fusion/include/unfused_typed.hpp new file mode 100755 index 000000000..fd6b08575 --- /dev/null +++ b/win32/include/boost/fusion/include/unfused_typed.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_UNFUSED_TYPED) +#define FUSION_INCLUDE_UNFUSED_TYPED + +#include + +#endif diff --git a/win32/include/boost/fusion/include/unused.hpp b/win32/include/boost/fusion/include/unused.hpp new file mode 100755 index 000000000..e2c52cfaf --- /dev/null +++ b/win32/include/boost/fusion/include/unused.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_UNUSED) +#define FUSION_INCLUDE_UNUSED + +#include + +#endif diff --git a/win32/include/boost/fusion/include/value_at.hpp b/win32/include/boost/fusion/include/value_at.hpp new file mode 100755 index 000000000..3b246f69f --- /dev/null +++ b/win32/include/boost/fusion/include/value_at.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 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(FUSION_INCLUDE_VALUE_AT) +#define FUSION_INCLUDE_VALUE_AT + +#include + +#endif diff --git a/win32/include/boost/fusion/include/value_at_key.hpp b/win32/include/boost/fusion/include/value_at_key.hpp new file mode 100755 index 000000000..e8c059518 --- /dev/null +++ b/win32/include/boost/fusion/include/value_at_key.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_VALUE_AT_KEY) +#define FUSION_INCLUDE_VALUE_AT_KEY + +#include + +#endif diff --git a/win32/include/boost/fusion/include/value_of.hpp b/win32/include/boost/fusion/include/value_of.hpp new file mode 100755 index 000000000..33a6321d6 --- /dev/null +++ b/win32/include/boost/fusion/include/value_of.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_VALUE_OF) +#define FUSION_INCLUDE_VALUE_OF + +#include + +#endif diff --git a/win32/include/boost/fusion/include/vector.hpp b/win32/include/boost/fusion/include/vector.hpp new file mode 100755 index 000000000..452015671 --- /dev/null +++ b/win32/include/boost/fusion/include/vector.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_VECTOR) +#define FUSION_INCLUDE_VECTOR + +#include + +#endif diff --git a/win32/include/boost/fusion/include/vector10.hpp b/win32/include/boost/fusion/include/vector10.hpp new file mode 100755 index 000000000..6d92c5487 --- /dev/null +++ b/win32/include/boost/fusion/include/vector10.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_VECTOR10) +#define FUSION_INCLUDE_VECTOR10 + +#include + +#endif diff --git a/win32/include/boost/fusion/include/vector20.hpp b/win32/include/boost/fusion/include/vector20.hpp new file mode 100755 index 000000000..408c87f44 --- /dev/null +++ b/win32/include/boost/fusion/include/vector20.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_VECTOR20) +#define FUSION_INCLUDE_VECTOR20 + +#include + +#endif diff --git a/win32/include/boost/fusion/include/vector30.hpp b/win32/include/boost/fusion/include/vector30.hpp new file mode 100755 index 000000000..d8dddaaab --- /dev/null +++ b/win32/include/boost/fusion/include/vector30.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_VECTOR30) +#define FUSION_INCLUDE_VECTOR30 + +#include + +#endif diff --git a/win32/include/boost/fusion/include/vector40.hpp b/win32/include/boost/fusion/include/vector40.hpp new file mode 100755 index 000000000..ebac1516b --- /dev/null +++ b/win32/include/boost/fusion/include/vector40.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_VECTOR40) +#define FUSION_INCLUDE_VECTOR40 + +#include + +#endif diff --git a/win32/include/boost/fusion/include/vector50.hpp b/win32/include/boost/fusion/include/vector50.hpp new file mode 100755 index 000000000..b3e352b88 --- /dev/null +++ b/win32/include/boost/fusion/include/vector50.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_VECTOR50) +#define FUSION_INCLUDE_VECTOR50 + +#include + +#endif diff --git a/win32/include/boost/fusion/include/vector_fwd.hpp b/win32/include/boost/fusion/include/vector_fwd.hpp new file mode 100755 index 000000000..de134297c --- /dev/null +++ b/win32/include/boost/fusion/include/vector_fwd.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_VECTOR_FWD) +#define FUSION_INCLUDE_VECTOR_FWD + +#include + +#endif diff --git a/win32/include/boost/fusion/include/vector_tie.hpp b/win32/include/boost/fusion/include/vector_tie.hpp new file mode 100755 index 000000000..a5323beea --- /dev/null +++ b/win32/include/boost/fusion/include/vector_tie.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_VECTOR_TIE) +#define FUSION_INCLUDE_VECTOR_TIE + +#include + +#endif diff --git a/win32/include/boost/fusion/include/view.hpp b/win32/include/boost/fusion/include/view.hpp new file mode 100755 index 000000000..c7c24058d --- /dev/null +++ b/win32/include/boost/fusion/include/view.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_VIEW) +#define FUSION_INCLUDE_VIEW + +#include + +#endif diff --git a/win32/include/boost/fusion/include/void.hpp b/win32/include/boost/fusion/include/void.hpp new file mode 100755 index 000000000..b54032095 --- /dev/null +++ b/win32/include/boost/fusion/include/void.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_VOID) +#define FUSION_INCLUDE_VOID + +#include + +#endif diff --git a/win32/include/boost/fusion/include/zip.hpp b/win32/include/boost/fusion/include/zip.hpp new file mode 100755 index 000000000..c93da438c --- /dev/null +++ b/win32/include/boost/fusion/include/zip.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ZIP) +#define FUSION_INCLUDE_ZIP + +#include + +#endif diff --git a/win32/include/boost/fusion/include/zip_view.hpp b/win32/include/boost/fusion/include/zip_view.hpp new file mode 100755 index 000000000..dbc369a64 --- /dev/null +++ b/win32/include/boost/fusion/include/zip_view.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2007 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INCLUDE_ZIP_VIEW) +#define FUSION_INCLUDE_ZIP_VIEW + +#include + +#endif diff --git a/win32/include/boost/fusion/iterator.hpp b/win32/include/boost/fusion/iterator.hpp new file mode 100755 index 000000000..c8c8d0434 --- /dev/null +++ b/win32/include/boost/fusion/iterator.hpp @@ -0,0 +1,20 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ITERATOR_10022005_0559) +#define FUSION_ITERATOR_10022005_0559 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/iterator/advance.hpp b/win32/include/boost/fusion/iterator/advance.hpp new file mode 100755 index 000000000..50dd509c6 --- /dev/null +++ b/win32/include/boost/fusion/iterator/advance.hpp @@ -0,0 +1,92 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ADVANCE_09172005_1146) +#define FUSION_ADVANCE_09172005_1146 + +#include +#include + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct random_access_traversal_tag; + + // Special tags: + struct iterator_facade_tag; // iterator facade tag + struct array_iterator_tag; // boost::array iterator tag + struct mpl_iterator_tag; // mpl sequence iterator tag + struct std_pair_iterator_tag; // std::pair iterator tag + + namespace extension + { + template + struct advance_impl + { + // default implementation + template + struct apply : + mpl::if_c< + (N::value > 0) + , advance_detail::forward + , advance_detail::backward + >::type + { + BOOST_MPL_ASSERT_NOT((traits::is_random_access)); + }; + }; + + template <> + struct advance_impl + { + template + struct apply : Iterator::template advance {}; + }; + + template <> + struct advance_impl; + + template <> + struct advance_impl; + + template <> + struct advance_impl; + } + + namespace result_of + { + template + struct advance_c + : extension::advance_impl::type>::template apply > + {}; + + template + struct advance + : extension::advance_impl::type>::template apply + {}; + } + + template + inline typename result_of::advance_c::type const + advance_c(Iterator const& i) + { + return result_of::advance_c::call(i); + } + + template + inline typename result_of::advance::type const + advance(Iterator const& i) + { + return result_of::advance::call(i); + } + +}} // namespace boost::fusion + +#endif diff --git a/win32/include/boost/fusion/iterator/deref.hpp b/win32/include/boost/fusion/iterator/deref.hpp new file mode 100755 index 000000000..8cba4f9b4 --- /dev/null +++ b/win32/include/boost/fusion/iterator/deref.hpp @@ -0,0 +1,72 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_DEREF_05042005_1019) +#define FUSION_DEREF_05042005_1019 + +#include +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct iterator_facade_tag; // iterator facade tag + struct array_iterator_tag; // boost::array iterator tag + struct mpl_iterator_tag; // mpl sequence iterator tag + struct std_pair_iterator_tag; // std::pair iterator tag + + namespace extension + { + template + struct deref_impl + { + template + struct apply {}; + }; + + template <> + struct deref_impl + { + template + struct apply : Iterator::template deref {}; + }; + + template <> + struct deref_impl; + + template <> + struct deref_impl; + + template <> + struct deref_impl; + } + + namespace result_of + { + template + struct deref + : extension::deref_impl::type>:: + template apply + {}; + } + + template + typename result_of::deref::type + deref(Iterator const& i) + { + typedef result_of::deref deref_meta; + return deref_meta::call(i); + } + + template + typename result_of::deref::type + operator*(iterator_base const& i) + { + return fusion::deref(i.cast()); + } +}} + +#endif diff --git a/win32/include/boost/fusion/iterator/detail/adapt_deref_traits.hpp b/win32/include/boost/fusion/iterator/detail/adapt_deref_traits.hpp new file mode 100755 index 000000000..cbaf808ff --- /dev/null +++ b/win32/include/boost/fusion/iterator/detail/adapt_deref_traits.hpp @@ -0,0 +1,34 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ADAPT_DEREF_TRAITS_05062005_0900) +#define FUSION_ADAPT_DEREF_TRAITS_05062005_0900 + +#include + +namespace boost { namespace fusion { namespace detail +{ + struct adapt_deref_traits + { + template + struct apply + { + typedef typename + result_of::deref::type + type; + + static type + call(Iterator const& i) + { + return *i.first; + } + }; + }; +}}} + +#endif + + diff --git a/win32/include/boost/fusion/iterator/detail/adapt_value_traits.hpp b/win32/include/boost/fusion/iterator/detail/adapt_value_traits.hpp new file mode 100755 index 000000000..96434fcb9 --- /dev/null +++ b/win32/include/boost/fusion/iterator/detail/adapt_value_traits.hpp @@ -0,0 +1,28 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ADAPT_VALUE_TRAITS_05062005_0859) +#define FUSION_ADAPT_VALUE_TRAITS_05062005_0859 + +#include + +namespace boost { namespace fusion { namespace detail +{ + struct adapt_value_traits + { + template + struct apply + { + typedef typename + result_of::value_of::type + type; + }; + }; +}}} + +#endif + + diff --git a/win32/include/boost/fusion/iterator/detail/advance.hpp b/win32/include/boost/fusion/iterator/detail/advance.hpp new file mode 100755 index 000000000..74d3ca973 --- /dev/null +++ b/win32/include/boost/fusion/iterator/detail/advance.hpp @@ -0,0 +1,102 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ADVANCE_09172005_1149) +#define FUSION_ADVANCE_09172005_1149 + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace advance_detail +{ + // Default advance implementation, perform next(i) + // or prior(i) N times. + + template + struct forward; + + template + struct next_forward + { + typedef typename + forward< + typename result_of::next::type + , N-1 + >::type + type; + }; + + template + struct forward + { + typedef typename + mpl::eval_if_c< + (N == 0) + , mpl::identity + , next_forward + >::type + type; + + static type const& + call(type const& i) + { + return i; + } + + template + static type + call(I const& i) + { + return call(fusion::next(i)); + } + }; + + template + struct backward; + + template + struct next_backward + { + typedef typename + backward< + typename result_of::prior::type + , N+1 + >::type + type; + }; + + template + struct backward + { + typedef typename + mpl::eval_if_c< + (N == 0) + , mpl::identity + , next_backward + >::type + type; + + static type const& + call(type const& i) + { + return i; + } + + template + static type + call(I const& i) + { + return call(fusion::prior(i)); + } + }; + +}}} + +#endif diff --git a/win32/include/boost/fusion/iterator/detail/distance.hpp b/win32/include/boost/fusion/iterator/detail/distance.hpp new file mode 100755 index 000000000..9d24d1d76 --- /dev/null +++ b/win32/include/boost/fusion/iterator/detail/distance.hpp @@ -0,0 +1,64 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_DISTANCE_09172005_0730) +#define FUSION_DISTANCE_09172005_0730 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace distance_detail +{ + // Default distance implementation, linear + // search for the Last iterator. + + template + struct linear_distance; + + template + struct next_distance + { + typedef typename + mpl::next< + typename linear_distance< + typename result_of::next::type + , Last + >::type + >::type + type; + }; + + template + struct linear_distance + : mpl::eval_if< + result_of::equal_to + , mpl::identity > + , next_distance + >::type + { + typedef typename + mpl::eval_if< + result_of::equal_to + , mpl::identity > + , next_distance + >::type + type; + + static type + call(First const&, Last const&) + { + return type(); + } + }; + +}}} + +#endif diff --git a/win32/include/boost/fusion/iterator/distance.hpp b/win32/include/boost/fusion/iterator/distance.hpp new file mode 100755 index 000000000..4a6517f4e --- /dev/null +++ b/win32/include/boost/fusion/iterator/distance.hpp @@ -0,0 +1,81 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_DISTANCE_09172005_0721) +#define FUSION_DISTANCE_09172005_0721 + +#include +#include + +#include +#include +#include + +#include + +namespace boost { namespace fusion +{ + struct random_access_traversal_tag; + + // Special tags: + struct iterator_facade_tag; // iterator facade tag + struct array_iterator_tag; // boost::array iterator tag + struct mpl_iterator_tag; // mpl sequence iterator tag + struct std_pair_iterator_tag; // std::pair iterator tag + + namespace extension + { + template + struct distance_impl + { + // default implementation + template + struct apply : distance_detail::linear_distance + { + BOOST_MPL_ASSERT_NOT((traits::is_random_access)); + BOOST_MPL_ASSERT_NOT((traits::is_random_access)); + }; + }; + + template <> + struct distance_impl + { + template + struct apply : First::template distance {}; + }; + + template <> + struct distance_impl; + + template <> + struct distance_impl; + + template <> + struct distance_impl; + } + + namespace result_of + { + template + struct distance + : extension::distance_impl::type>:: + template apply + { + typedef typename extension::distance_impl::type>:: + template apply::type distance_application; + BOOST_STATIC_CONSTANT(int, value = distance_application::value); + }; + } + + template + inline typename result_of::distance::type + distance(First const& a, Last const& b) + { + return result_of::distance::call(a,b); + } +}} + +#endif diff --git a/win32/include/boost/fusion/iterator/equal_to.hpp b/win32/include/boost/fusion/iterator/equal_to.hpp new file mode 100755 index 000000000..23f431246 --- /dev/null +++ b/win32/include/boost/fusion/iterator/equal_to.hpp @@ -0,0 +1,93 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_EQUAL_TO_05052005_1208) +#define FUSION_EQUAL_TO_05052005_1208 + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct iterator_facade_tag; // iterator facade tag + struct array_iterator_tag; // boost::array iterator tag + struct mpl_iterator_tag; // mpl sequence iterator tag + struct std_pair_iterator_tag; // std::pair iterator tag + + namespace extension + { + template + struct equal_to_impl + { + // default implementation + template + struct apply + : is_same::type, typename add_const::type> + {}; + }; + + template <> + struct equal_to_impl + { + template + struct apply : I1::template equal_to {}; + }; + + template <> + struct equal_to_impl; + + template <> + struct equal_to_impl; + + template <> + struct equal_to_impl; + } + + namespace result_of + { + template + struct equal_to + : extension::equal_to_impl::type>:: + template apply + {}; + } + + namespace iterator_operators + { + template + inline typename + enable_if< + mpl::and_, is_fusion_iterator > + , bool + >::type + operator==(Iter1 const&, Iter2 const&) + { + return result_of::equal_to::value; + } + + template + inline typename + enable_if< + mpl::and_, is_fusion_iterator > + , bool + >::type + operator!=(Iter1 const&, Iter2 const&) + { + return !result_of::equal_to::value; + } + } + + using iterator_operators::operator==; + using iterator_operators::operator!=; +}} + +#endif + diff --git a/win32/include/boost/fusion/iterator/iterator_facade.hpp b/win32/include/boost/fusion/iterator/iterator_facade.hpp new file mode 100755 index 000000000..a0c196c87 --- /dev/null +++ b/win32/include/boost/fusion/iterator/iterator_facade.hpp @@ -0,0 +1,50 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ITERATOR_FACADE_09252006_1011) +#define FUSION_ITERATOR_FACADE_09252006_1011 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct iterator_facade_tag; + + template + struct iterator_facade : iterator_base + { + typedef iterator_facade_tag fusion_tag; + typedef Derived derived_type; + typedef Category category; + + // default implementation + template + struct equal_to // default implementation + : is_same< + typename I1::derived_type + , typename I2::derived_type + > + {}; + + // default implementation + template + struct advance : + mpl::if_c< + (N::value > 0) + , advance_detail::forward + , advance_detail::backward + >::type + { + BOOST_MPL_ASSERT_NOT((traits::is_random_access)); + }; + }; +}} + +#endif diff --git a/win32/include/boost/fusion/iterator/mpl.hpp b/win32/include/boost/fusion/iterator/mpl.hpp new file mode 100755 index 000000000..06d5141f5 --- /dev/null +++ b/win32/include/boost/fusion/iterator/mpl.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ITERATOR_MPL_10022005_0557) +#define FUSION_ITERATOR_MPL_10022005_0557 + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/iterator/mpl/convert_iterator.hpp b/win32/include/boost/fusion/iterator/mpl/convert_iterator.hpp new file mode 100755 index 000000000..16fd22a1e --- /dev/null +++ b/win32/include/boost/fusion/iterator/mpl/convert_iterator.hpp @@ -0,0 +1,58 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_CONVERT_ITERATOR_05062005_1218) +#define FUSION_CONVERT_ITERATOR_05062005_1218 + +#include +#include +#include + +namespace boost { namespace fusion +{ + template + struct mpl_iterator; // forward declaration + + // Test T. If it is a fusion iterator, return a reference to it. + // else, assume it is an mpl iterator. + + template + struct convert_iterator + { + typedef typename + mpl::if_< + is_fusion_iterator + , T + , mpl_iterator + >::type + type; + + static T const& + call(T const& x, mpl::true_) + { + return x; + } + + static mpl_iterator + call(T const& x, mpl::false_) + { + return mpl_iterator(); + } + + static typename + mpl::if_< + is_fusion_iterator + , T const& + , mpl_iterator + >::type + call(T const& x) + { + return call(x, is_fusion_iterator()); + } + }; +}} + +#endif diff --git a/win32/include/boost/fusion/iterator/mpl/fusion_iterator.hpp b/win32/include/boost/fusion/iterator/mpl/fusion_iterator.hpp new file mode 100755 index 000000000..095063789 --- /dev/null +++ b/win32/include/boost/fusion/iterator/mpl/fusion_iterator.hpp @@ -0,0 +1,57 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_FUSION_ITERATOR_10012005_1551) +#define FUSION_FUSION_ITERATOR_10012005_1551 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl +{ + template + struct fusion_iterator + { + typedef typename fusion::result_of::value_of::type type; + typedef typename fusion::traits::category_of::type category; + typedef Iterator iterator; + }; + + template + struct next > + { + typedef fusion_iterator::type> type; + }; + + template + struct prior > + { + typedef fusion_iterator::type> type; + }; + + template + struct advance, N> + { + typedef fusion_iterator::type> type; + }; + + template + struct distance, fusion_iterator > + : fusion::result_of::distance + {}; + +}} + +#endif + + diff --git a/win32/include/boost/fusion/iterator/next.hpp b/win32/include/boost/fusion/iterator/next.hpp new file mode 100755 index 000000000..2ac83e0fd --- /dev/null +++ b/win32/include/boost/fusion/iterator/next.hpp @@ -0,0 +1,63 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_NEXT_05042005_1101) +#define FUSION_NEXT_05042005_1101 + +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct iterator_facade_tag; // iterator facade tag + struct array_iterator_tag; // boost::array iterator tag + struct mpl_iterator_tag; // mpl sequence iterator tag + struct std_pair_iterator_tag; // std::pair iterator tag + + namespace extension + { + template + struct next_impl + { + template + struct apply {}; + }; + + template <> + struct next_impl + { + template + struct apply : Iterator::template next {}; + }; + + template <> + struct next_impl; + + template <> + struct next_impl; + + template <> + struct next_impl; + } + + namespace result_of + { + template + struct next + : extension::next_impl::type>:: + template apply + {}; + } + + template + typename result_of::next::type const + next(Iterator const& i) + { + return result_of::next::call(i); + } +}} + +#endif diff --git a/win32/include/boost/fusion/iterator/prior.hpp b/win32/include/boost/fusion/iterator/prior.hpp new file mode 100755 index 000000000..49c55ca01 --- /dev/null +++ b/win32/include/boost/fusion/iterator/prior.hpp @@ -0,0 +1,63 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_PRIOR_05042005_1144) +#define FUSION_PRIOR_05042005_1144 + +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct iterator_facade_tag; // iterator facade tag + struct array_iterator_tag; // boost::array iterator tag + struct mpl_iterator_tag; // mpl sequence iterator tag + struct std_pair_iterator_tag; // std::pair iterator tag + + namespace extension + { + template + struct prior_impl + { + template + struct apply {}; + }; + + template <> + struct prior_impl + { + template + struct apply : Iterator::template prior {}; + }; + + template <> + struct prior_impl; + + template <> + struct prior_impl; + + template <> + struct prior_impl; + } + + namespace result_of + { + template + struct prior + : extension::prior_impl::type>:: + template apply + {}; + } + + template + typename result_of::prior::type const + prior(Iterator const& i) + { + return result_of::prior::call(i); + } +}} + +#endif diff --git a/win32/include/boost/fusion/iterator/value_of.hpp b/win32/include/boost/fusion/iterator/value_of.hpp new file mode 100755 index 000000000..18a9b46b0 --- /dev/null +++ b/win32/include/boost/fusion/iterator/value_of.hpp @@ -0,0 +1,57 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VALUE_OF_05052005_1126) +#define FUSION_VALUE_OF_05052005_1126 + +#include +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct iterator_facade_tag; // iterator facade tag + struct array_iterator_tag; // boost::array iterator tag + struct mpl_iterator_tag; // mpl sequence iterator tag + struct std_pair_iterator_tag; // std::pair iterator tag + + namespace extension + { + template + struct value_of_impl + { + template + struct apply {}; + }; + + template <> + struct value_of_impl + { + template + struct apply : Iterator::template value_of {}; + }; + + template <> + struct value_of_impl; + + template <> + struct value_of_impl; + + template <> + struct value_of_impl; + } + + namespace result_of + { + template + struct value_of + : extension::value_of_impl::type>:: + template apply + {}; + } +}} + +#endif diff --git a/win32/include/boost/fusion/mpl.hpp b/win32/include/boost/fusion/mpl.hpp new file mode 100755 index 000000000..75a062209 --- /dev/null +++ b/win32/include/boost/fusion/mpl.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_MPL_09172006_2049) +#define FUSION_MPL_09172006_2049 + +// The fusion <--> MPL link headers +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/mpl/at.hpp b/win32/include/boost/fusion/mpl/at.hpp new file mode 100755 index 000000000..8dd6206a2 --- /dev/null +++ b/win32/include/boost/fusion/mpl/at.hpp @@ -0,0 +1,33 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_AT_10022005_1616) +#define FUSION_AT_10022005_1616 + +#include +#include + +namespace boost { +namespace fusion +{ + struct fusion_sequence_tag; +} + +namespace mpl +{ + template + struct at_impl; + + template <> + struct at_impl + { + template + struct apply : fusion::result_of::value_at {}; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/mpl/back.hpp b/win32/include/boost/fusion/mpl/back.hpp new file mode 100755 index 000000000..b80a0c80a --- /dev/null +++ b/win32/include/boost/fusion/mpl/back.hpp @@ -0,0 +1,32 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BACK_10022005_1620) +#define FUSION_BACK_10022005_1620 + +#include +#include +#include +#include + +namespace boost { namespace mpl +{ + template + struct back_impl; + + template <> + struct back_impl + { + template + struct apply : + fusion::result_of::value_of< + typename fusion::result_of::prior< + typename fusion::result_of::end::type + >::type> {}; + }; +}} + +#endif diff --git a/win32/include/boost/fusion/mpl/begin.hpp b/win32/include/boost/fusion/mpl/begin.hpp new file mode 100755 index 000000000..532ad1929 --- /dev/null +++ b/win32/include/boost/fusion/mpl/begin.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BEGIN_10022005_1620) +#define FUSION_BEGIN_10022005_1620 + +#include +#include +#include +#include + +namespace boost { namespace mpl +{ + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef fusion_iterator::type> type; + }; + }; +}} + +#endif diff --git a/win32/include/boost/fusion/mpl/clear.hpp b/win32/include/boost/fusion/mpl/clear.hpp new file mode 100755 index 000000000..fb94dab9c --- /dev/null +++ b/win32/include/boost/fusion/mpl/clear.hpp @@ -0,0 +1,33 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_CLEAR_10022005_1817) +#define FUSION_CLEAR_10022005_1817 + +#include +#include +#include + +namespace boost { namespace mpl +{ + template + struct clear_impl; + + template <> + struct clear_impl + { + template + struct apply + { + typedef typename + fusion::detail::clear::type>::type + type; + }; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/mpl/detail/clear.hpp b/win32/include/boost/fusion/mpl/detail/clear.hpp new file mode 100755 index 000000000..8c1447a71 --- /dev/null +++ b/win32/include/boost/fusion/mpl/detail/clear.hpp @@ -0,0 +1,46 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_CLEAR_10022005_1442) +#define FUSION_CLEAR_10022005_1442 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct cons_tag; + struct map_tag; + struct set_tag; + struct vector_tag; + struct deque_tag; + + namespace detail + { + template + struct clear; + + template <> + struct clear : mpl::identity > {}; + + template <> + struct clear : mpl::identity > {}; + + template <> + struct clear : mpl::identity > {}; + + template <> + struct clear : mpl::identity > {}; + + template <> + struct clear : mpl::identity > {}; + } +}} + +#endif diff --git a/win32/include/boost/fusion/mpl/empty.hpp b/win32/include/boost/fusion/mpl/empty.hpp new file mode 100755 index 000000000..15c7d64e5 --- /dev/null +++ b/win32/include/boost/fusion/mpl/empty.hpp @@ -0,0 +1,26 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_EMPTY_10022005_1619) +#define FUSION_EMPTY_10022005_1619 + +#include +#include + +namespace boost { namespace mpl +{ + template + struct empty_impl; + + template <> + struct empty_impl + { + template + struct apply : fusion::result_of::empty {}; + }; +}} + +#endif diff --git a/win32/include/boost/fusion/mpl/end.hpp b/win32/include/boost/fusion/mpl/end.hpp new file mode 100755 index 000000000..dfcb37a9a --- /dev/null +++ b/win32/include/boost/fusion/mpl/end.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_END_10022005_1619) +#define FUSION_END_10022005_1619 + +#include +#include +#include +#include + +namespace boost { namespace mpl +{ + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef fusion_iterator::type> type; + }; + }; +}} + +#endif diff --git a/win32/include/boost/fusion/mpl/erase.hpp b/win32/include/boost/fusion/mpl/erase.hpp new file mode 100755 index 000000000..9853465c2 --- /dev/null +++ b/win32/include/boost/fusion/mpl/erase.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ERASE_10022005_1835) +#define FUSION_ERASE_10022005_1835 + +#include +#include +#include +#include + +namespace boost { namespace mpl +{ + template + struct erase_impl; + + template <> + struct erase_impl + { + template + struct apply + { + typedef typename + fusion::result_of::erase::type + result; + + typedef typename + fusion::result_of::convert< + typename fusion::detail::tag_of::type, result>::type + type; + }; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/mpl/erase_key.hpp b/win32/include/boost/fusion/mpl/erase_key.hpp new file mode 100755 index 000000000..08162878c --- /dev/null +++ b/win32/include/boost/fusion/mpl/erase_key.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ERASE_KEY_10022005_1907) +#define FUSION_ERASE_KEY_10022005_1907 + +#include +#include +#include +#include + +namespace boost { namespace mpl +{ + template + struct erase_key_impl; + + template <> + struct erase_key_impl + { + template + struct apply + { + typedef typename + fusion::result_of::erase_key::type + result; + + typedef typename + fusion::result_of::convert< + typename fusion::detail::tag_of::type, result>::type + type; + }; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/mpl/front.hpp b/win32/include/boost/fusion/mpl/front.hpp new file mode 100755 index 000000000..1c58225c0 --- /dev/null +++ b/win32/include/boost/fusion/mpl/front.hpp @@ -0,0 +1,28 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_FRONT_10022005_1618) +#define FUSION_FRONT_10022005_1618 + +#include +#include +#include + +namespace boost { namespace mpl +{ + template + struct front_impl; + + template <> + struct front_impl + { + template + struct apply : + fusion::result_of::value_of::type> {}; + }; +}} + +#endif diff --git a/win32/include/boost/fusion/mpl/has_key.hpp b/win32/include/boost/fusion/mpl/has_key.hpp new file mode 100755 index 000000000..f64acc941 --- /dev/null +++ b/win32/include/boost/fusion/mpl/has_key.hpp @@ -0,0 +1,27 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_HAS_KEY_10022005_1617) +#define FUSION_HAS_KEY_10022005_1617 + +#include +#include + +namespace boost { namespace mpl +{ + template + struct has_key_impl; + + template <> + struct has_key_impl + { + template + struct apply : fusion::result_of::has_key {}; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/mpl/insert.hpp b/win32/include/boost/fusion/mpl/insert.hpp new file mode 100755 index 000000000..006282fd2 --- /dev/null +++ b/win32/include/boost/fusion/mpl/insert.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INSERT_10022005_1837) +#define FUSION_INSERT_10022005_1837 + +#include +#include +#include +#include + +namespace boost { namespace mpl +{ + template + struct insert_impl; + + template <> + struct insert_impl + { + template + struct apply + { + typedef typename + fusion::result_of::insert::type + result; + + typedef typename + fusion::result_of::convert< + typename fusion::detail::tag_of::type, result>::type + type; + }; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/mpl/insert_range.hpp b/win32/include/boost/fusion/mpl/insert_range.hpp new file mode 100755 index 000000000..36765bb8a --- /dev/null +++ b/win32/include/boost/fusion/mpl/insert_range.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_INSERT_RANGE_10022005_1838) +#define FUSION_INSERT_RANGE_10022005_1838 + +#include +#include +#include +#include + +namespace boost { namespace mpl +{ + template + struct insert_range_impl; + + template <> + struct insert_range_impl + { + template + struct apply + { + typedef typename + fusion::result_of::insert_range::type + result; + + typedef typename + fusion::result_of::convert< + typename fusion::detail::tag_of::type, result>::type + type; + }; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/mpl/pop_back.hpp b/win32/include/boost/fusion/mpl/pop_back.hpp new file mode 100755 index 000000000..379a4b60c --- /dev/null +++ b/win32/include/boost/fusion/mpl/pop_back.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_POP_BACK_10022005_1801) +#define FUSION_POP_BACK_10022005_1801 + +#include +#include +#include +#include + +namespace boost { namespace mpl +{ + template + struct pop_back_impl; + + template <> + struct pop_back_impl + { + template + struct apply + { + typedef typename + fusion::result_of::pop_back::type + result; + + typedef typename + fusion::result_of::convert< + typename fusion::detail::tag_of::type, result>::type + type; + }; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/mpl/pop_front.hpp b/win32/include/boost/fusion/mpl/pop_front.hpp new file mode 100755 index 000000000..175ad8dfc --- /dev/null +++ b/win32/include/boost/fusion/mpl/pop_front.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_POP_FRONT_10022005_1800) +#define FUSION_POP_FRONT_10022005_1800 + +#include +#include +#include +#include + +namespace boost { namespace mpl +{ + template + struct pop_front_impl; + + template <> + struct pop_front_impl + { + template + struct apply + { + typedef typename + fusion::result_of::pop_front::type + result; + + typedef typename + fusion::result_of::convert< + typename fusion::detail::tag_of::type, result>::type + type; + }; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/mpl/push_back.hpp b/win32/include/boost/fusion/mpl/push_back.hpp new file mode 100755 index 000000000..09ca0857d --- /dev/null +++ b/win32/include/boost/fusion/mpl/push_back.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_PUSH_BACK_10022005_1647) +#define FUSION_PUSH_BACK_10022005_1647 + +#include +#include +#include +#include + +namespace boost { namespace mpl +{ + template + struct push_back_impl; + + template <> + struct push_back_impl + { + template + struct apply + { + typedef typename + fusion::result_of::push_back::type + result; + + typedef typename + fusion::result_of::convert< + typename fusion::detail::tag_of::type, result>::type + type; + }; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/mpl/push_front.hpp b/win32/include/boost/fusion/mpl/push_front.hpp new file mode 100755 index 000000000..15d5622bc --- /dev/null +++ b/win32/include/boost/fusion/mpl/push_front.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_PUSH_FRONT_10022005_1720) +#define FUSION_PUSH_FRONT_10022005_1720 + +#include +#include +#include +#include + +namespace boost { namespace mpl +{ + template + struct push_front_impl; + + template <> + struct push_front_impl + { + template + struct apply + { + typedef typename + fusion::result_of::push_front::type + result; + + typedef typename + fusion::result_of::convert< + typename fusion::detail::tag_of::type, result>::type + type; + }; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/mpl/size.hpp b/win32/include/boost/fusion/mpl/size.hpp new file mode 100755 index 000000000..0b2f06c84 --- /dev/null +++ b/win32/include/boost/fusion/mpl/size.hpp @@ -0,0 +1,26 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SIZE_10022005_1617) +#define FUSION_SIZE_10022005_1617 + +#include +#include + +namespace boost { namespace mpl +{ + template + struct size_impl; + + template <> + struct size_impl + { + template + struct apply : fusion::result_of::size {}; + }; +}} + +#endif diff --git a/win32/include/boost/fusion/sequence.hpp b/win32/include/boost/fusion/sequence.hpp new file mode 100755 index 000000000..bffd60de6 --- /dev/null +++ b/win32/include/boost/fusion/sequence.hpp @@ -0,0 +1,16 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_10022005_0559) +#define FUSION_ITERATOR_10022005_0559 + +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/sequence/comparison.hpp b/win32/include/boost/fusion/sequence/comparison.hpp new file mode 100755 index 000000000..a4325ad8d --- /dev/null +++ b/win32/include/boost/fusion/sequence/comparison.hpp @@ -0,0 +1,17 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_COMPARISON_10022005_0615) +#define FUSION_SEQUENCE_COMPARISON_10022005_0615 + +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/sequence/comparison/detail/enable_comparison.hpp b/win32/include/boost/fusion/sequence/comparison/detail/enable_comparison.hpp new file mode 100755 index 000000000..c393086c4 --- /dev/null +++ b/win32/include/boost/fusion/sequence/comparison/detail/enable_comparison.hpp @@ -0,0 +1,38 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ENABLE_COMPARISON_09232005_1958) +#define FUSION_ENABLE_COMPARISON_09232005_1958 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct is_native_fusion_sequence : is_base_of {}; + + template + struct enable_equality + : mpl::or_, is_native_fusion_sequence > + {}; + + template + struct enable_comparison + : mpl::and_< + mpl::or_, is_native_fusion_sequence > + , mpl::equal_to, result_of::size > + > + {}; + +}}} + +#endif diff --git a/win32/include/boost/fusion/sequence/comparison/detail/equal_to.hpp b/win32/include/boost/fusion/sequence/comparison/detail/equal_to.hpp new file mode 100755 index 000000000..799286e32 --- /dev/null +++ b/win32/include/boost/fusion/sequence/comparison/detail/equal_to.hpp @@ -0,0 +1,60 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_EQUAL_TO_05052005_1142) +#define FUSION_EQUAL_TO_05052005_1142 + +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct sequence_equal_to + { + typedef typename result_of::end::type end1_type; + typedef typename result_of::end::type end2_type; + + template + static bool + call(I1 const&, I2 const&, mpl::true_) + { + return true; + } + + template + static bool + call(I1 const& a, I2 const& b, mpl::false_) + { + return *a == *b + && call(fusion::next(a), fusion::next(b)); + } + + template + static bool + call(I1 const& a, I2 const& b) + { + typename result_of::equal_to::type eq; + return call(a, b, eq); + } + }; + + template + struct sequence_equal_to + { + template + static bool + call(I1 const& a, I2 const& b) + { + return false; + } + }; +}}} + +#endif diff --git a/win32/include/boost/fusion/sequence/comparison/detail/greater.hpp b/win32/include/boost/fusion/sequence/comparison/detail/greater.hpp new file mode 100755 index 000000000..a8387dc5e --- /dev/null +++ b/win32/include/boost/fusion/sequence/comparison/detail/greater.hpp @@ -0,0 +1,50 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_GREATER_05052005_1142) +#define FUSION_GREATER_05052005_1142 + +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct sequence_greater + { + typedef typename result_of::end::type end1_type; + typedef typename result_of::end::type end2_type; + + template + static bool + call(I1 const&, I2 const&, mpl::true_) + { + return false; + } + + template + static bool + call(I1 const& a, I2 const& b, mpl::false_) + { + return *a > *b + || !(*b > *a) + && call(fusion::next(a), fusion::next(b)); + } + + template + static bool + call(I1 const& a, I2 const& b) + { + typename result_of::equal_to::type eq; + return call(a, b, eq); + } + }; +}}} + +#endif diff --git a/win32/include/boost/fusion/sequence/comparison/detail/greater_equal.hpp b/win32/include/boost/fusion/sequence/comparison/detail/greater_equal.hpp new file mode 100755 index 000000000..dcda740be --- /dev/null +++ b/win32/include/boost/fusion/sequence/comparison/detail/greater_equal.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_GREATER_EQUAL_05052005_1142) +#define FUSION_GREATER_EQUAL_05052005_1142 + +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct sequence_greater_equal + { + typedef typename result_of::end::type end1_type; + typedef typename result_of::end::type end2_type; + + template + static bool + call(I1 const&, I2 const&, mpl::true_) + { + return true; + } + + template + static bool + call(I1 const& a, I2 const& b, mpl::false_) + { + return *a >= *b + && (!(*b >= *a) || call(fusion::next(a), fusion::next(b))); + } + + template + static bool + call(I1 const& a, I2 const& b) + { + typename result_of::equal_to::type eq; + return call(a, b, eq); + } + }; +}}} + +#endif diff --git a/win32/include/boost/fusion/sequence/comparison/detail/less.hpp b/win32/include/boost/fusion/sequence/comparison/detail/less.hpp new file mode 100755 index 000000000..f7a866c64 --- /dev/null +++ b/win32/include/boost/fusion/sequence/comparison/detail/less.hpp @@ -0,0 +1,50 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_LESS_05052005_1141) +#define FUSION_LESS_05052005_1141 + +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct sequence_less + { + typedef typename result_of::end::type end1_type; + typedef typename result_of::end::type end2_type; + + template + static bool + call(I1 const&, I2 const&, mpl::true_) + { + return false; + } + + template + static bool + call(I1 const& a, I2 const& b, mpl::false_) + { + return *a < *b + || !(*b < *a) + && call(fusion::next(a), fusion::next(b)); + } + + template + static bool + call(I1 const& a, I2 const& b) + { + typename result_of::equal_to::type eq; + return call(a, b, eq); + } + }; +}}} + +#endif diff --git a/win32/include/boost/fusion/sequence/comparison/detail/less_equal.hpp b/win32/include/boost/fusion/sequence/comparison/detail/less_equal.hpp new file mode 100755 index 000000000..16eaec028 --- /dev/null +++ b/win32/include/boost/fusion/sequence/comparison/detail/less_equal.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_LESS_EQUAL_05052005_1141) +#define FUSION_LESS_EQUAL_05052005_1141 + +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct sequence_less_equal + { + typedef typename result_of::end::type end1_type; + typedef typename result_of::end::type end2_type; + + template + static bool + call(I1 const&, I2 const&, mpl::true_) + { + return true; + } + + template + static bool + call(I1 const& a, I2 const& b, mpl::false_) + { + return *a <= *b + && (!(*b <= *a) || call(fusion::next(a), fusion::next(b))); + } + + template + static bool + call(I1 const& a, I2 const& b) + { + typename result_of::equal_to::type eq; + return call(a, b, eq); + } + }; +}}} + +#endif diff --git a/win32/include/boost/fusion/sequence/comparison/detail/not_equal_to.hpp b/win32/include/boost/fusion/sequence/comparison/detail/not_equal_to.hpp new file mode 100755 index 000000000..f70a42f22 --- /dev/null +++ b/win32/include/boost/fusion/sequence/comparison/detail/not_equal_to.hpp @@ -0,0 +1,60 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_NOT_EQUAL_TO_05052005_1141) +#define FUSION_NOT_EQUAL_TO_05052005_1141 + +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct sequence_not_equal_to + { + typedef typename result_of::end::type end1_type; + typedef typename result_of::end::type end2_type; + + template + static bool + call(I1 const&, I2 const&, mpl::true_) + { + return false; + } + + template + static bool + call(I1 const& a, I2 const& b, mpl::false_) + { + return *a != *b + || call(fusion::next(a), fusion::next(b)); + } + + template + static bool + call(I1 const& a, I2 const& b) + { + typename result_of::equal_to::type eq; + return call(a, b, eq); + } + }; + + template + struct sequence_not_equal_to + { + template + static bool + call(I1 const& a, I2 const& b) + { + return true; + } + }; +}}} + +#endif diff --git a/win32/include/boost/fusion/sequence/comparison/equal_to.hpp b/win32/include/boost/fusion/sequence/comparison/equal_to.hpp new file mode 100755 index 000000000..ba913d848 --- /dev/null +++ b/win32/include/boost/fusion/sequence/comparison/equal_to.hpp @@ -0,0 +1,46 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_EQUAL_TO_05052005_0431) +#define FUSION_EQUAL_TO_05052005_0431 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + template + inline bool + equal_to(Seq1 const& a, Seq2 const& b) + { + return result_of::size::value == result_of::size::value + && detail::sequence_equal_to< + Seq1 const, Seq2 const + , result_of::size::value == result_of::size::value>:: + call(fusion::begin(a), fusion::begin(b)); + } + + namespace operators + { + template + inline typename + enable_if< + detail::enable_equality + , bool + >::type + operator==(Seq1 const& a, Seq2 const& b) + { + return fusion::equal_to(a, b); + } + } + using operators::operator==; +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/comparison/greater.hpp b/win32/include/boost/fusion/sequence/comparison/greater.hpp new file mode 100755 index 000000000..776df52a5 --- /dev/null +++ b/win32/include/boost/fusion/sequence/comparison/greater.hpp @@ -0,0 +1,52 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_GREATER_05052005_0432) +#define FUSION_GREATER_05052005_0432 + +#include +#include +#include +#include + +#if defined(FUSION_DIRECT_OPERATOR_USAGE) +#include +#else +#include +#endif + +namespace boost { namespace fusion +{ + template + inline bool + greater(Seq1 const& a, Seq2 const& b) + { +#if defined(FUSION_DIRECT_OPERATOR_USAGE) + return detail::sequence_greater:: + call(fusion::begin(a), fusion::begin(b)); +#else + return (b < a); +#endif + } + + namespace operators + { + template + inline typename + enable_if< + detail::enable_comparison + , bool + >::type + operator>(Seq1 const& a, Seq2 const& b) + { + return fusion::greater(a, b); + } + } + using operators::operator>; +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/comparison/greater_equal.hpp b/win32/include/boost/fusion/sequence/comparison/greater_equal.hpp new file mode 100755 index 000000000..5a64041e2 --- /dev/null +++ b/win32/include/boost/fusion/sequence/comparison/greater_equal.hpp @@ -0,0 +1,52 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_GREATER_EQUAL_05052005_0432) +#define FUSION_GREATER_EQUAL_05052005_0432 + +#include +#include +#include +#include + +#if defined(FUSION_DIRECT_OPERATOR_USAGE) +#include +#else +#include +#endif + +namespace boost { namespace fusion +{ + template + inline bool + greater_equal(Seq1 const& a, Seq2 const& b) + { +#if defined(FUSION_DIRECT_OPERATOR_USAGE) + return detail::sequence_greater_equal:: + call(fusion::begin(a), fusion::begin(b)); +#else + return !(a < b); +#endif + } + + namespace operators + { + template + inline typename + enable_if< + detail::enable_comparison + , bool + >::type + operator>=(Seq1 const& a, Seq2 const& b) + { + return fusion::greater_equal(a, b); + } + } + using operators::operator>=; +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/comparison/less.hpp b/win32/include/boost/fusion/sequence/comparison/less.hpp new file mode 100755 index 000000000..755da74dd --- /dev/null +++ b/win32/include/boost/fusion/sequence/comparison/less.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_LESS_05052005_0432) +#define FUSION_LESS_05052005_0432 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + template + inline bool + less(Seq1 const& a, Seq2 const& b) + { + return detail::sequence_less:: + call(fusion::begin(a), fusion::begin(b)); + } + + namespace operators + { + template + inline typename + enable_if< + detail::enable_comparison + , bool + >::type + operator<(Seq1 const& a, Seq2 const& b) + { + return fusion::less(a, b); + } + } + using operators::operator<; +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/comparison/less_equal.hpp b/win32/include/boost/fusion/sequence/comparison/less_equal.hpp new file mode 100755 index 000000000..ae62b0ad6 --- /dev/null +++ b/win32/include/boost/fusion/sequence/comparison/less_equal.hpp @@ -0,0 +1,80 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_LESS_EQUAL_05052005_0432) +#define FUSION_LESS_EQUAL_05052005_0432 + +#include +#include +#include +#include + +#if defined(FUSION_DIRECT_OPERATOR_USAGE) +#include +#else +#include +#endif + +namespace boost { namespace fusion +{ + template + inline bool + less_equal(Seq1 const& a, Seq2 const& b) + { +#if defined(FUSION_DIRECT_OPERATOR_USAGE) + return detail::sequence_less_equal:: + call(fusion::begin(a), fusion::begin(b)); +#else + return !(b < a); +#endif + } + + namespace operators + { +#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1400) +// Workaround for VC8.0 and VC7.1 + template + inline bool + operator<=(sequence_base const& a, sequence_base const& b) + { + return less_equal(a.derived(), b.derived()); + } + + template + inline typename disable_if, bool>::type + operator<=(sequence_base const& a, Seq2 const& b) + { + return less_equal(a.derived(), b); + } + + template + inline typename disable_if, bool>::type + operator<=(Seq1 const& a, sequence_base const& b) + { + return less_equal(a, b.derived()); + } + +#else +// Somehow VC8.0 and VC7.1 does not like this code +// but barfs somewhere else. + + template + inline typename + enable_if< + detail::enable_comparison + , bool + >::type + operator<=(Seq1 const& a, Seq2 const& b) + { + return fusion::less_equal(a, b); + } +#endif + } + using operators::operator<=; +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/comparison/not_equal_to.hpp b/win32/include/boost/fusion/sequence/comparison/not_equal_to.hpp new file mode 100755 index 000000000..b485c15e7 --- /dev/null +++ b/win32/include/boost/fusion/sequence/comparison/not_equal_to.hpp @@ -0,0 +1,55 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_NOT_EQUAL_TO_05052005_0431) +#define FUSION_NOT_EQUAL_TO_05052005_0431 + +#include +#include +#include +#include + +#if defined(FUSION_DIRECT_OPERATOR_USAGE) +#include +#else +#include +#endif + +namespace boost { namespace fusion +{ + template + inline bool + not_equal_to(Seq1 const& a, Seq2 const& b) + { +#if defined(FUSION_DIRECT_OPERATOR_USAGE) + return result_of::size::value != result_of::size::value + || detail::sequence_not_equal_to< + Seq1 const, Seq2 const + , result_of::size::value == result_of::size::value>:: + call(fusion::begin(a), fusion::begin(b)); +#else + return !(a == b); +#endif + } + + namespace operators + { + template + inline typename + enable_if< + detail::enable_equality + , bool + >::type + operator!=(Seq1 const& a, Seq2 const& b) + { + return fusion::not_equal_to(a, b); + } + } + using operators::operator!=; +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/convert.hpp b/win32/include/boost/fusion/sequence/convert.hpp new file mode 100755 index 000000000..fc12fd018 --- /dev/null +++ b/win32/include/boost/fusion/sequence/convert.hpp @@ -0,0 +1,48 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_CONVERT_10022005_1442) +#define FUSION_CONVERT_10022005_1442 + +namespace boost { namespace fusion +{ + namespace extension + { + template + struct convert_impl; + } + + namespace result_of + { + template + struct convert + { + typedef typename extension::convert_impl gen; + + typedef typename + gen::template apply::type + type; + }; + } + + template + inline typename result_of::convert::type + convert(Sequence& seq) + { + typedef typename result_of::convert::gen gen; + return gen::call(seq); + } + + template + inline typename result_of::convert::type + convert(Sequence const& seq) + { + typedef typename result_of::convert::gen gen; + return gen::call(seq); + } +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/intrinsic.hpp b/win32/include/boost/fusion/sequence/intrinsic.hpp new file mode 100755 index 000000000..f38210ea2 --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic.hpp @@ -0,0 +1,22 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_INTRINSIC_10022005_0618) +#define FUSION_SEQUENCE_INTRINSIC_10022005_0618 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/sequence/intrinsic/at.hpp b/win32/include/boost/fusion/sequence/intrinsic/at.hpp new file mode 100755 index 000000000..0c773e014 --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic/at.hpp @@ -0,0 +1,106 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_AT_05042005_0722) +#define FUSION_AT_05042005_0722 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct sequence_facade_tag; + struct boost_tuple_tag; // boost::tuples::tuple tag + struct array_tag; // boost::array tag + struct mpl_sequence_tag; // mpl sequence tag + struct std_pair_tag; // std::pair tag + + namespace extension + { + template + struct at_impl + { + template + struct apply; + }; + + template <> + struct at_impl + { + template + struct apply : Sequence::template at {}; + }; + + template <> + struct at_impl; + + template <> + struct at_impl; + + template <> + struct at_impl; + + template <> + struct at_impl; + } + + namespace result_of + { + template + struct at + : extension::at_impl::type>:: + template apply + {}; + + template + struct at_c + : at > + {}; + } + + + template + inline typename + lazy_disable_if< + is_const + , result_of::at + >::type + at(Sequence& seq) + { + return result_of::at::call(seq); + } + + template + inline typename result_of::at::type + at(Sequence const& seq) + { + return result_of::at::call(seq); + } + + template + inline typename + lazy_disable_if< + is_const + , result_of::at_c + >::type + at_c(Sequence& seq) + { + return at >(seq); + } + + template + inline typename result_of::at_c::type + at_c(Sequence const& seq) + { + return at >(seq); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/sequence/intrinsic/at_key.hpp b/win32/include/boost/fusion/sequence/intrinsic/at_key.hpp new file mode 100755 index 000000000..53eaeb7bf --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic/at_key.hpp @@ -0,0 +1,77 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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_FUSION_AT_KEY_20060304_1755) +#define BOOST_FUSION_AT_KEY_20060304_1755 + +#include +#include +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct sequence_facade_tag; + struct array_tag; // boost::array tag + struct mpl_sequence_tag; // mpl sequence tag + struct std_pair_tag; // std::pair tag + + namespace extension + { + template + struct at_key_impl + { + template + struct apply; + }; + + template <> + struct at_key_impl + { + template + struct apply : Sequence::template at_key {}; + }; + + template <> + struct at_key_impl; + + template <> + struct at_key_impl; + + template <> + struct at_key_impl; + } + + namespace result_of + { + template + struct at_key + : extension::at_key_impl::type>:: + template apply + {}; + } + + template + inline typename + lazy_disable_if< + is_const + , result_of::at_key + >::type + at_key(Sequence& seq) + { + return result_of::at_key::call(seq); + } + + template + inline typename result_of::at_key::type + at_key(Sequence const& seq) + { + return result_of::at_key::call(seq); + } +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/intrinsic/back.hpp b/win32/include/boost/fusion/sequence/intrinsic/back.hpp new file mode 100755 index 000000000..486b3f7e4 --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic/back.hpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BACK_09162005_0350) +#define FUSION_BACK_09162005_0350 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct fusion_sequence_tag; + + namespace result_of + { + template + struct back + : result_of::deref::type>::type> + {}; + } + + template + inline typename result_of::back::type + back(Sequence& seq) + { + return *fusion::prior(fusion::end(seq)); + } + + template + inline typename result_of::back::type + back(Sequence const& seq) + { + return *fusion::prior(fusion::end(seq)); + } +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/intrinsic/begin.hpp b/win32/include/boost/fusion/sequence/intrinsic/begin.hpp new file mode 100755 index 000000000..927d8236f --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic/begin.hpp @@ -0,0 +1,74 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BEGIN_04052005_1132) +#define FUSION_BEGIN_04052005_1132 + +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct sequence_facade_tag; // iterator facade tag + struct boost_tuple_tag; // boost::tuples::tuple tag + struct array_tag; // boost::array tag + struct mpl_sequence_tag; // mpl sequence tag + struct std_pair_tag; // std::pair tag + + namespace extension + { + template + struct begin_impl + { + template + struct apply; + }; + + template <> + struct begin_impl + { + template + struct apply : Sequence::template begin {}; + }; + + template <> + struct begin_impl; + + template <> + struct begin_impl; + + template <> + struct begin_impl; + + template <> + struct begin_impl; + } + + namespace result_of + { + template + struct begin + : extension::begin_impl::type>:: + template apply + {}; + } + + template + inline typename result_of::begin::type const + begin(Sequence& seq) + { + return result_of::begin::call(seq); + } + + template + inline typename result_of::begin::type const + begin(Sequence const& seq) + { + return result_of::begin::call(seq); + } +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/intrinsic/empty.hpp b/win32/include/boost/fusion/sequence/intrinsic/empty.hpp new file mode 100755 index 000000000..36cd55fdf --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic/empty.hpp @@ -0,0 +1,60 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_EMPTY_09162005_0335) +#define FUSION_EMPTY_09162005_0335 + +#include +#include +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct sequence_facade_tag; + struct mpl_sequence_tag; // mpl sequence tag + + namespace extension + { + template + struct empty_impl + { + template + struct apply + : mpl::bool_<(result_of::size::value == 0)> + {}; + }; + + template <> + struct empty_impl + { + template + struct apply : Sequence::template empty {}; + }; + + template <> + struct empty_impl; + } + + namespace result_of + { + template + struct empty + : extension::empty_impl::type>:: + template apply + {}; + } + + template + inline typename result_of::empty::type + empty(Sequence const&) + { + typedef typename result_of::empty::type result; + return result(); + } +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/intrinsic/end.hpp b/win32/include/boost/fusion/sequence/intrinsic/end.hpp new file mode 100755 index 000000000..29b284c22 --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic/end.hpp @@ -0,0 +1,74 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_END_04052005_1141) +#define FUSION_END_04052005_1141 + +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct sequence_facade_tag; + struct boost_tuple_tag; // boost::tuples::tuple tag + struct array_tag; // boost::array tag + struct mpl_sequence_tag; // mpl sequence tag + struct std_pair_tag; // std::pair tag + + namespace extension + { + template + struct end_impl + { + template + struct apply; + }; + + template <> + struct end_impl + { + template + struct apply : Sequence::template end {}; + }; + + template <> + struct end_impl; + + template <> + struct end_impl; + + template <> + struct end_impl; + + template <> + struct end_impl; + } + + namespace result_of + { + template + struct end + : extension::end_impl::type>:: + template apply + {}; + } + + template + inline typename result_of::end::type const + end(Sequence& seq) + { + return result_of::end::call(seq); + } + + template + inline typename result_of::end::type const + end(Sequence const& seq) + { + return result_of::end::call(seq); + } +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/intrinsic/ext_/segments.hpp b/win32/include/boost/fusion/sequence/intrinsic/ext_/segments.hpp new file mode 100755 index 000000000..8bd103082 --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic/ext_/segments.hpp @@ -0,0 +1,56 @@ +/*============================================================================= + Copyright (c) 2006 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEGMENTS_04052005_1141) +#define FUSION_SEGMENTS_04052005_1141 + +#include + +namespace boost { namespace fusion +{ + // segments: returns a sequence of sequences + namespace extension + { + template + struct segments_impl + { + template + struct apply {}; + }; + } + + namespace result_of + { + template + struct segments + { + typedef typename + extension::segments_impl::type>:: + template apply::type + type; + }; + } + + template + typename result_of::segments::type + segments(Sequence & seq) + { + return + extension::segments_impl::type>:: + template apply::call(seq); + } + + template + typename result_of::segments::type + segments(Sequence const& seq) + { + return + extension::segments_impl::type>:: + template apply::call(seq); + } +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/intrinsic/ext_/size_s.hpp b/win32/include/boost/fusion/sequence/intrinsic/ext_/size_s.hpp new file mode 100755 index 000000000..d85d97df9 --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic/ext_/size_s.hpp @@ -0,0 +1,57 @@ +/*============================================================================= + Copyright (c) 2006 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SIZE_S_08112006_1141) +#define FUSION_SIZE_S_08112006_1141 + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + /////////////////////////////////////////////////////////////////////////// + // calculates the size of any segmented data structure. + template::value> + struct segmented_size; + + namespace detail + { + struct size_plus + { + template + struct result; + + template + struct result + : mpl::plus< + segmented_size::type> + , typename remove_reference::type + > + {}; + }; + } + + /////////////////////////////////////////////////////////////////////////// + template + struct segmented_size + : result_of::fold< + typename result_of::segments::type + , mpl::size_t<0> + , detail::size_plus + >::type + {}; + + template + struct segmented_size + : result_of::size + {}; +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/intrinsic/front.hpp b/win32/include/boost/fusion/sequence/intrinsic/front.hpp new file mode 100755 index 000000000..0959c7463 --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic/front.hpp @@ -0,0 +1,41 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_FRONT_09162005_0343) +#define FUSION_FRONT_09162005_0343 + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct fusion_sequence_tag; + + namespace result_of + { + template + struct front + : result_of::deref::type> + {}; + } + + template + inline typename result_of::front::type + front(Sequence& seq) + { + return *fusion::begin(seq); + } + + template + inline typename result_of::front::type + front(Sequence const& seq) + { + return *fusion::begin(seq); + } +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/intrinsic/has_key.hpp b/win32/include/boost/fusion/sequence/intrinsic/has_key.hpp new file mode 100755 index 000000000..63498c914 --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic/has_key.hpp @@ -0,0 +1,72 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_HAS_KEY_09232005_1454) +#define FUSION_HAS_KEY_09232005_1454 + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + // Special tags: + struct sequence_facade_tag; + struct array_tag; // boost::array tag + struct mpl_sequence_tag; // mpl sequence tag + struct std_pair_tag; // std::pair tag + + namespace extension + { + template + struct has_key_impl + { + template + struct apply + : mpl::not_::type, void_> > + {}; + }; + + template <> + struct has_key_impl + { + template + struct apply : Sequence::template has_key {}; + }; + + template <> + struct has_key_impl; + + template <> + struct has_key_impl; + + template <> + struct has_key_impl; + } + + namespace result_of + { + template + struct has_key + : extension::has_key_impl::type>:: + template apply + {}; + } + + template + inline typename result_of::has_key::type + has_key(Sequence const& seq) + { + typedef typename result_of::has_key::type result; + return result(); + } +}} + +#endif + diff --git a/win32/include/boost/fusion/sequence/intrinsic/size.hpp b/win32/include/boost/fusion/sequence/intrinsic/size.hpp new file mode 100755 index 000000000..39c9bf43f --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic/size.hpp @@ -0,0 +1,74 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SIZE_05052005_0214) +#define FUSION_SIZE_05052005_0214 + +#include +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct sequence_facade_tag; + struct boost_tuple_tag; // boost::tuples::tuple tag + struct array_tag; // boost::array tag + struct mpl_sequence_tag; // mpl sequence tag + struct std_pair_tag; // std::pair tag + + namespace extension + { + template + struct size_impl + { + template + struct apply : Sequence::size {}; + }; + + template <> + struct size_impl + { + template + struct apply : Sequence::template size {}; + }; + + template <> + struct size_impl; + + template <> + struct size_impl; + + template <> + struct size_impl; + + template <> + struct size_impl; + } + + namespace result_of + { + template + struct size + : extension::size_impl::type>:: + template apply + + { + typedef typename extension::size_impl::type>:: + template apply::type size_application; + BOOST_STATIC_CONSTANT(int, value = size_application::value); + }; + } + + template + inline typename result_of::size::type + size(Sequence const&) + { + typedef typename result_of::size::type result; + return result(); + } +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/intrinsic/swap.hpp b/win32/include/boost/fusion/sequence/intrinsic/swap.hpp new file mode 100755 index 000000000..15cd899e1 --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic/swap.hpp @@ -0,0 +1,59 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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_FUSION_SWAP_20070501_1956) +#define BOOST_FUSION_SWAP_20070501_1956 + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { + namespace result_of + { + template + struct swap + { + typedef void type; + }; + } + + namespace detail + { + struct swap + { + template + struct result + { + typedef void type; + }; + + template + void operator()(Elem const& e) const + { + using std::swap; + swap(front(e), back(e)); + } + }; + } + + template + typename enable_if, traits::is_sequence >, void>::type + swap(Seq1& lhs, Seq2& rhs) + { + typedef vector references; + for_each(zip_view(references(lhs, rhs)), detail::swap()); + } +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/intrinsic/value_at.hpp b/win32/include/boost/fusion/sequence/intrinsic/value_at.hpp new file mode 100755 index 000000000..8dc898bec --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic/value_at.hpp @@ -0,0 +1,67 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VALUE_AT_05052005_0229) +#define FUSION_VALUE_AT_05052005_0229 + +#include +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct sequence_facade_tag; + struct boost_tuple_tag; // boost::tuples::tuple tag + struct array_tag; // boost::array tag + struct mpl_sequence_tag; // mpl sequence tag + struct std_pair_tag; // std::pair tag + + namespace extension + { + template + struct value_at_impl + { + template + struct apply; + }; + + template <> + struct value_at_impl + { + template + struct apply : Sequence::template value_at {}; + }; + + template <> + struct value_at_impl; + + template <> + struct value_at_impl; + + template <> + struct value_at_impl; + + template <> + struct value_at_impl; + } + + namespace result_of + { + template + struct value_at + : extension::value_at_impl::type>:: + template apply + {}; + + template + struct value_at_c + : fusion::result_of::value_at > + {}; + } +}} + +#endif + diff --git a/win32/include/boost/fusion/sequence/intrinsic/value_at_key.hpp b/win32/include/boost/fusion/sequence/intrinsic/value_at_key.hpp new file mode 100755 index 000000000..9add44664 --- /dev/null +++ b/win32/include/boost/fusion/sequence/intrinsic/value_at_key.hpp @@ -0,0 +1,59 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_VALUE_AT_KEY_05052005_0229) +#define FUSION_VALUE_AT_KEY_05052005_0229 + +#include +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct sequence_facade_tag; + struct array_tag; // boost::array tag + struct mpl_sequence_tag; // mpl sequence tag + struct std_pair_tag; // std::pair tag + + namespace extension + { + template + struct value_at_key_impl + { + template + struct apply; + }; + + template <> + struct value_at_key_impl + { + template + struct apply : Sequence::template value_at_key {}; + }; + + template <> + struct value_at_key_impl; + + template <> + struct value_at_key_impl; + + template <> + struct value_at_key_impl; + } + + namespace result_of + { + template + struct value_at_key + : extension::value_at_key_impl::type>:: + template apply + {}; + } +}} + +#endif + diff --git a/win32/include/boost/fusion/sequence/io.hpp b/win32/include/boost/fusion/sequence/io.hpp new file mode 100755 index 000000000..aa6a24417 --- /dev/null +++ b/win32/include/boost/fusion/sequence/io.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_IO_10032005_0836) +#define FUSION_SEQUENCE_IO_10032005_0836 + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/sequence/io/detail/in.hpp b/win32/include/boost/fusion/sequence/io/detail/in.hpp new file mode 100755 index 000000000..ff859f6b8 --- /dev/null +++ b/win32/include/boost/fusion/sequence/io/detail/in.hpp @@ -0,0 +1,85 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 1999-2003 Jeremiah Willcock + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_IN_05052005_0121) +#define FUSION_IN_05052005_0121 + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct delimiter_in + { + // read a delimiter + template + static void + read(IS& is, char const* delim, mpl::false_ = mpl::false_()) + { + detail::string_ios_manip manip(is); + manip.read(delim); + } + + template + static void + read(IS& is, char const* delim, mpl::true_) + { + } + }; + + struct read_sequence_loop + { + template + static void + call(IS& is, First const&, Last const&, mpl::true_) + { + } + + template + static void + call(IS& is, First const& first, Last const& last, mpl::false_) + { + result_of::equal_to< + typename result_of::next::type + , Last + > + is_last; + + is >> *first; + delimiter_in::read(is, " ", is_last); + call(is, fusion::next(first), last, is_last); + } + + template + static void + call(IS& is, First const& first, Last const& last) + { + result_of::equal_to eq; + call(is, first, last, eq); + } + }; + + template + inline void + read_sequence(IS& is, Sequence& seq) + { + delimiter_in::read(is, "("); + read_sequence_loop::call(is, fusion::begin(seq), fusion::end(seq)); + delimiter_in::read(is, ")"); + } +}}} + +#endif diff --git a/win32/include/boost/fusion/sequence/io/detail/manip.hpp b/win32/include/boost/fusion/sequence/io/detail/manip.hpp new file mode 100755 index 000000000..6f70f50d3 --- /dev/null +++ b/win32/include/boost/fusion/sequence/io/detail/manip.hpp @@ -0,0 +1,316 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jeremiah Willcock + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_MANIP_05052005_1200) +#define FUSION_MANIP_05052005_1200 + +#include +#include +#include +#include + +// Tuple I/O manipulators + +#define FUSION_GET_CHAR_TYPE(T) typename T::char_type +#define FUSION_GET_TRAITS_TYPE(T) typename T::traits_type + +#if defined (BOOST_NO_TEMPLATED_STREAMS) +#define FUSION_STRING_OF_STREAM(Stream) std::string +#else +#define FUSION_STRING_OF_STREAM(Stream) \ + std::basic_string< \ + FUSION_GET_CHAR_TYPE(Stream) \ + , FUSION_GET_TRAITS_TYPE(Stream) \ + > +#endif + +//$$$ these should be part of the public API$$$ +//$$$ rename tuple_open, tuple_close and tuple_delimiter to +// open, close and delimeter and add these synonyms to the +// TR1 tuple module. + +namespace boost { namespace fusion +{ + namespace detail + { + template + int get_xalloc_index(Tag* = 0) + { + // each Tag will have a unique index + static int index = std::ios::xalloc(); + return index; + } + + template + struct stream_data + { + struct arena + { + ~arena() + { + for ( + typename std::vector::iterator i = data.begin() + ; i != data.end() + ; ++i) + { + delete *i; + } + } + + std::vector data; + }; + + static void attach(Stream& stream, T const& data) + { + static arena ar; // our arena + ar.data.push_back(new T(data)); + stream.pword(get_xalloc_index()) = ar.data.back(); + } + + static T const* get(Stream& stream) + { + return (T const*)stream.pword(get_xalloc_index()); + } + }; + + template + class string_ios_manip + { + public: + + typedef FUSION_STRING_OF_STREAM(Stream) string_type; + + typedef stream_data stream_data_t; + + string_ios_manip(Stream& str_) + : stream(str_) + {} + + void + set(string_type const& s) + { + stream_data_t::attach(stream, s); + } + + void + print(char const* default_) const + { + // print a delimiter + string_type const* p = stream_data_t::get(stream); + if (p) + stream << *p; + else + stream << default_; + } + + void + read(char const* default_) const + { + // read a delimiter + string_type const* p = stream_data_t::get(stream); + using namespace std; + ws(stream); + + if (p) + { + typedef typename string_type::const_iterator iterator; + for (iterator i = p->begin(); i != p->end(); ++i) + check_delim(*i); + } + else + { + while (*default_) + check_delim(*default_++); + } + } + + private: + + template + void + check_delim(Char c) const + { + if (!isspace(c)) + { + if (stream.get() != c) + { + stream.unget(); + stream.setstate(std::ios::failbit); + } + } + } + + Stream& stream; + }; + + } // detail + +#if defined (BOOST_NO_TEMPLATED_STREAMS) + +#define STD_TUPLE_DEFINE_MANIPULATOR(name) \ + namespace detail \ + { \ + struct name##_tag; \ + \ + struct name##_type \ + { \ + typedef std::string string_type; \ + string_type data; \ + name##_type(const string_type& d): data(d) {} \ + }; \ + \ + template \ + Stream& operator>>(Stream& s, const name##_type& m) \ + { \ + string_ios_manip(s).set(m.data); \ + return s; \ + } \ + \ + template \ + Stream& operator<<(Stream& s, const name##_type& m) \ + { \ + string_ios_manip(s).set(m.data); \ + return s; \ + } \ + } + +#define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name) \ + inline detail::name##_type \ + name(const std::string& s) \ + { \ + return detail::name##_type(s); \ + } \ + \ + inline detail::name##_type \ + name(const char* s) \ + { \ + return detail::name##_type(std::string(s)); \ + } \ + \ + inline detail::name##_type \ + name(char c) \ + { \ + return detail::name##_type(std::string(1, c)); \ + } + +#else // defined(BOOST_NO_TEMPLATED_STREAMS) + +#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + +#define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name) \ + template \ + inline detail::name##_type \ + name(const std::basic_string& s) \ + { \ + return detail::name##_type(s); \ + } \ + \ + inline detail::name##_type \ + name(char const* s) \ + { \ + return detail::name##_type(std::basic_string(s)); \ + } \ + \ + inline detail::name##_type \ + name(wchar_t const* s) \ + { \ + return detail::name##_type(std::basic_string(s)); \ + } \ + \ + inline detail::name##_type \ + name(char c) \ + { \ + return detail::name##_type(std::basic_string(1, c)); \ + } \ + \ + inline detail::name##_type \ + name(wchar_t c) \ + { \ + return detail::name##_type(std::basic_string(1, c)); \ + } + +#else // defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + +#define STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(name) \ + template \ + inline detail::name##_type \ + name(const std::basic_string& s) \ + { \ + return detail::name##_type(s); \ + } \ + \ + template \ + inline detail::name##_type \ + name(Char s[]) \ + { \ + return detail::name##_type(std::basic_string(s)); \ + } \ + \ + template \ + inline detail::name##_type \ + name(Char const s[]) \ + { \ + return detail::name##_type(std::basic_string(s)); \ + } \ + \ + template \ + inline detail::name##_type \ + name(Char c) \ + { \ + return detail::name##_type(std::basic_string(1, c)); \ + } + +#endif + +#define STD_TUPLE_DEFINE_MANIPULATOR(name) \ + namespace detail \ + { \ + struct name##_tag; \ + \ + template > \ + struct name##_type \ + { \ + typedef std::basic_string string_type; \ + string_type data; \ + name##_type(const string_type& d): data(d) {} \ + }; \ + \ + template \ + Stream& operator>>(Stream& s, const name##_type& m) \ + { \ + string_ios_manip(s).set(m.data); \ + return s; \ + } \ + \ + template \ + Stream& operator<<(Stream& s, const name##_type& m) \ + { \ + string_ios_manip(s).set(m.data); \ + return s; \ + } \ + } \ + +#endif // defined(BOOST_NO_TEMPLATED_STREAMS) + + STD_TUPLE_DEFINE_MANIPULATOR(tuple_open) + STD_TUPLE_DEFINE_MANIPULATOR(tuple_close) + STD_TUPLE_DEFINE_MANIPULATOR(tuple_delimiter) + + STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_open) + STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_close) + STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS(tuple_delimiter) + +#undef STD_TUPLE_DEFINE_MANIPULATOR +#undef STD_TUPLE_DEFINE_MANIPULATOR_FUNCTIONS +#undef FUSION_STRING_OF_STREAM +#undef FUSION_GET_CHAR_TYPE +#undef FUSION_GET_TRAITS_TYPE + +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/io/detail/out.hpp b/win32/include/boost/fusion/sequence/io/detail/out.hpp new file mode 100755 index 000000000..a177d1988 --- /dev/null +++ b/win32/include/boost/fusion/sequence/io/detail/out.hpp @@ -0,0 +1,85 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 1999-2003 Jeremiah Willcock + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_OUT_05052005_0121) +#define FUSION_OUT_05052005_0121 + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct delimiter_out + { + // print a delimiter + template + static void + print(OS& os, char const* delim, mpl::false_ = mpl::false_()) + { + detail::string_ios_manip manip(os); + manip.print(delim); + } + + template + static void + print(OS& os, char const* delim, mpl::true_) + { + } + }; + + struct print_sequence_loop + { + template + static void + call(OS& os, First const&, Last const&, mpl::true_) + { + } + + template + static void + call(OS& os, First const& first, Last const& last, mpl::false_) + { + result_of::equal_to< + typename result_of::next::type + , Last + > + is_last; + + os << *first; + delimiter_out::print(os, " ", is_last); + call(os, fusion::next(first), last, is_last); + } + + template + static void + call(OS& os, First const& first, Last const& last) + { + result_of::equal_to eq; + call(os, first, last, eq); + } + }; + + template + inline void + print_sequence(OS& os, Sequence const& seq) + { + delimiter_out::print(os, "("); + print_sequence_loop::call(os, fusion::begin(seq), fusion::end(seq)); + delimiter_out::print(os, ")"); + } +}}} + +#endif diff --git a/win32/include/boost/fusion/sequence/io/in.hpp b/win32/include/boost/fusion/sequence/io/in.hpp new file mode 100755 index 000000000..2e3732d84 --- /dev/null +++ b/win32/include/boost/fusion/sequence/io/in.hpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 1999-2003 Jeremiah Willcock + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_IN_05042005_0120) +#define BOOST_IN_05042005_0120 + +#include +#include +#include + +namespace boost { namespace fusion +{ + template + inline std::istream& + in(std::istream& is, Sequence& seq) + { + detail::read_sequence(is, seq); + return is; + } + + namespace operators + { + template + inline typename + enable_if< + fusion::traits::is_sequence + , std::istream& + >::type + operator>>(std::istream& is, Sequence& seq) + { + return fusion::in(is, seq); + } + } + using operators::operator>>; +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/io/out.hpp b/win32/include/boost/fusion/sequence/io/out.hpp new file mode 100755 index 000000000..4c8df8c19 --- /dev/null +++ b/win32/include/boost/fusion/sequence/io/out.hpp @@ -0,0 +1,44 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 1999-2003 Jeremiah Willcock + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_OUT_05042005_0120) +#define BOOST_OUT_05042005_0120 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + template + inline std::ostream& + out(std::ostream& os, Sequence& seq) + { + detail::print_sequence(os, seq); + return os; + } + + namespace operators + { + template + inline typename + enable_if< + fusion::traits::is_sequence + , std::ostream& + >::type + operator<<(std::ostream& os, Sequence const& seq) + { + return fusion::out(os, seq); + } + } + using operators::operator<<; +}} + +#endif diff --git a/win32/include/boost/fusion/sequence/sequence_facade.hpp b/win32/include/boost/fusion/sequence/sequence_facade.hpp new file mode 100755 index 000000000..d5d4e7775 --- /dev/null +++ b/win32/include/boost/fusion/sequence/sequence_facade.hpp @@ -0,0 +1,27 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_FACADE_09252006_1044) +#define FUSION_SEQUENCE_FACADE_09252006_1044 + +#include +#include + +namespace boost { namespace fusion +{ + struct sequence_facade_tag; + + template + struct sequence_facade : sequence_base + { + typedef sequence_facade_tag fusion_tag; + typedef Derived derived_type; + typedef Category category; + typedef IsView is_view; + }; +}} + +#endif diff --git a/win32/include/boost/fusion/support.hpp b/win32/include/boost/fusion/support.hpp new file mode 100755 index 000000000..08c8c69f7 --- /dev/null +++ b/win32/include/boost/fusion/support.hpp @@ -0,0 +1,22 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SUPPORT_10022005_0545) +#define FUSION_SUPPORT_10022005_0545 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/support/category_of.hpp b/win32/include/boost/fusion/support/category_of.hpp new file mode 100755 index 000000000..5e97cc229 --- /dev/null +++ b/win32/include/boost/fusion/support/category_of.hpp @@ -0,0 +1,112 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_CATEGORY_OF_07202005_0308) +#define FUSION_CATEGORY_OF_07202005_0308 + +#include +#include +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct boost_tuple_tag; // boost::tuples::tuple tag + struct array_tag; // boost::array tag + struct mpl_sequence_tag; // mpl sequence tag + struct std_pair_tag; // std::pair tag + + struct incrementable_traversal_tag {}; + + struct single_pass_traversal_tag + : incrementable_traversal_tag {}; + + struct forward_traversal_tag + : single_pass_traversal_tag {}; + + struct bidirectional_traversal_tag + : forward_traversal_tag {}; + + struct random_access_traversal_tag + : bidirectional_traversal_tag {}; + + struct associative_sequence_tag {}; + + namespace extension + { + template + struct category_of_impl + { + template + struct apply : detail::fusion_category_of {}; + }; + + template <> + struct category_of_impl; + + template <> + struct category_of_impl; + + template <> + struct category_of_impl; + + template <> + struct category_of_impl; + } + + namespace traits + { + template + struct category_of + : extension::category_of_impl::type>:: + template apply + {}; + + template + struct is_associative + : is_base_of< + associative_sequence_tag + , typename category_of::type> + {}; + + template + struct is_incrementable + : is_base_of< + incrementable_traversal_tag + , typename category_of::type> + {}; + + template + struct is_single_pass + : is_base_of< + single_pass_traversal_tag + , typename category_of::type> + {}; + + template + struct is_forward + : is_base_of< + forward_traversal_tag + , typename category_of::type> + {}; + + template + struct is_bidirectional + : is_base_of< + bidirectional_traversal_tag + , typename category_of::type> + {}; + + template + struct is_random_access + : is_base_of< + random_access_traversal_tag + , typename category_of::type> + {}; + } +}} + +#endif diff --git a/win32/include/boost/fusion/support/deduce.hpp b/win32/include/boost/fusion/support/deduce.hpp new file mode 100755 index 000000000..942cedc8b --- /dev/null +++ b/win32/include/boost/fusion/support/deduce.hpp @@ -0,0 +1,105 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_SUPPORT_DEDUCE_HPP_INCLUDED) +#define BOOST_FUSION_SUPPORT_DEDUCE_HPP_INCLUDED + +#include + +namespace boost { namespace fusion { namespace traits +{ + template struct deduce; + + //----- ---- --- -- - - - - + + // Non-references pass unchanged + + template + struct deduce + { + typedef T type; + }; + + template + struct deduce + { + typedef T type; + }; + + template + struct deduce + { + typedef T type; + }; + + template + struct deduce + { + typedef T type; + }; + + // Keep references on mutable LValues + + template + struct deduce + { + typedef T & type; + }; + + template + struct deduce + { + typedef T volatile& type; + }; + + // Store away potential RValues + + template + struct deduce + { + typedef T type; + }; + + template + struct deduce + { + typedef T type; + }; + + // Unwrap Boost.RefS (referencee cv is deduced) + + template + struct deduce & > + { + typedef T& type; + }; + + template + struct deduce const & > + { + typedef T& type; + }; + + // Keep references on arrays, even if const + + template + struct deduce + { + typedef const T(&type)[N]; + }; + + template + struct deduce + { + typedef const volatile T(&type)[N]; + }; + +}}} + +#endif + diff --git a/win32/include/boost/fusion/support/deduce_sequence.hpp b/win32/include/boost/fusion/support/deduce_sequence.hpp new file mode 100755 index 000000000..694bf250c --- /dev/null +++ b/win32/include/boost/fusion/support/deduce_sequence.hpp @@ -0,0 +1,44 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + Use modification and distribution are subject to 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_FUSION_SUPPORT_DEDUCE_SEQUENCE_HPP_INCLUDED) +#define BOOST_FUSION_SUPPORT_DEDUCE_SEQUENCE_HPP_INCLUDED + +#include +#include +#include + + +namespace boost { namespace fusion { namespace traits +{ + template struct deduce_sequence; + + namespace detail + { + struct deducer + { + template + struct result; + + template + struct result< Self(T) > + : fusion::traits::deduce + { }; + }; + } + + template + struct deduce_sequence + : result_of::as_vector< + fusion::transform_view > + { }; + +}}} + +#endif + diff --git a/win32/include/boost/fusion/support/detail/access.hpp b/win32/include/boost/fusion/support/detail/access.hpp new file mode 100755 index 000000000..bab85c171 --- /dev/null +++ b/win32/include/boost/fusion/support/detail/access.hpp @@ -0,0 +1,55 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ACCESS_04182005_0737) +#define FUSION_ACCESS_04182005_0737 + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct ref_result + { + typedef typename add_reference::type type; + }; + + template + struct cref_result + { + typedef typename + add_reference< + typename add_const::type + >::type + type; + }; + + template + struct non_ref_parameter + { + typedef typename boost::remove_cv::type const& type; + }; + + template + struct call_param + { + typedef typename + mpl::eval_if< + is_reference + , mpl::identity + , non_ref_parameter + >::type + type; + }; +}}} + +#endif + diff --git a/win32/include/boost/fusion/support/detail/as_fusion_element.hpp b/win32/include/boost/fusion/support/detail/as_fusion_element.hpp new file mode 100755 index 000000000..659146554 --- /dev/null +++ b/win32/include/boost/fusion/support/detail/as_fusion_element.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 1999-2003 Jaakko Jarvi + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_AS_FUSION_ELEMENT_05052005_0338) +#define FUSION_AS_FUSION_ELEMENT_05052005_0338 + +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct as_fusion_element + { + typedef T type; + }; + + template + struct as_fusion_element > + { + typedef T& type; + }; + + template + struct as_fusion_element + { + typedef const T(&type)[N]; + }; + + template + struct as_fusion_element + { + typedef const volatile T(&type)[N]; + }; + + template + struct as_fusion_element + { + typedef const volatile T(&type)[N]; + }; + +}}} + +#endif diff --git a/win32/include/boost/fusion/support/detail/category_of.hpp b/win32/include/boost/fusion/support/detail/category_of.hpp new file mode 100755 index 000000000..f268e7401 --- /dev/null +++ b/win32/include/boost/fusion/support/detail/category_of.hpp @@ -0,0 +1,19 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_CATEGORY_OF_07212005_1025) +#define FUSION_CATEGORY_OF_07212005_1025 + +namespace boost { namespace fusion { namespace detail +{ + template + struct fusion_category_of + { + typedef typename T::category type; + }; +}}} + +#endif diff --git a/win32/include/boost/fusion/support/detail/is_mpl_sequence.hpp b/win32/include/boost/fusion/support/detail/is_mpl_sequence.hpp new file mode 100755 index 000000000..1713abac1 --- /dev/null +++ b/win32/include/boost/fusion/support/detail/is_mpl_sequence.hpp @@ -0,0 +1,27 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_DETAIL_IS_MPL_SEQUENCE_29122006_1105) +#define FUSION_DETAIL_IS_MPL_SEQUENCE_29122006_1105 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { namespace detail +{ + template + struct is_mpl_sequence + : mpl::and_< + mpl::not_ > + , mpl::is_sequence > + {}; +}}} + +#endif diff --git a/win32/include/boost/fusion/support/detail/is_view.hpp b/win32/include/boost/fusion/support/detail/is_view.hpp new file mode 100755 index 000000000..9925fb1c5 --- /dev/null +++ b/win32/include/boost/fusion/support/detail/is_view.hpp @@ -0,0 +1,19 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_IS_VIEW_03202006_0018) +#define FUSION_IS_VIEW_03202006_0018 + +namespace boost { namespace fusion { namespace detail +{ + template + struct fusion_is_view + { + typedef typename T::is_view type; + }; +}}} + +#endif diff --git a/win32/include/boost/fusion/support/detail/mpl_iterator_category.hpp b/win32/include/boost/fusion/support/detail/mpl_iterator_category.hpp new file mode 100755 index 000000000..1ee0053f8 --- /dev/null +++ b/win32/include/boost/fusion/support/detail/mpl_iterator_category.hpp @@ -0,0 +1,66 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_MPL_ITERATOR_CATEGORY_07212005_0923) +#define FUSION_MPL_ITERATOR_CATEGORY_07212005_0923 + +namespace boost { namespace mpl +{ + struct forward_iterator_tag; + struct bidirectional_iterator_tag; + struct random_access_iterator_tag; +}} + +namespace boost { namespace fusion +{ + struct forward_traversal_tag; + struct bidirectional_traversal_tag; + struct random_access_traversal_tag; +}} + +namespace boost { namespace fusion { namespace detail +{ + template + struct mpl_iterator_category; + + template <> + struct mpl_iterator_category + { + typedef forward_traversal_tag type; + }; + + template <> + struct mpl_iterator_category + { + typedef bidirectional_traversal_tag type; + }; + + template <> + struct mpl_iterator_category + { + typedef random_access_traversal_tag type; + }; + + template <> + struct mpl_iterator_category + { + typedef forward_traversal_tag type; + }; + + template <> + struct mpl_iterator_category + { + typedef bidirectional_traversal_tag type; + }; + + template <> + struct mpl_iterator_category + { + typedef random_access_traversal_tag type; + }; +}}} + +#endif diff --git a/win32/include/boost/fusion/support/detail/unknown_key.hpp b/win32/include/boost/fusion/support/detail/unknown_key.hpp new file mode 100755 index 000000000..a3ec0b5ff --- /dev/null +++ b/win32/include/boost/fusion/support/detail/unknown_key.hpp @@ -0,0 +1,16 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_UNKNOWN_KEY_09242005_1219) +#define FUSION_UNKNOWN_KEY_09242005_1219 + +namespace boost { namespace fusion { namespace detail +{ + template + struct unknown_key {}; +}}} + +#endif diff --git a/win32/include/boost/fusion/support/ext_/is_segmented.hpp b/win32/include/boost/fusion/support/ext_/is_segmented.hpp new file mode 100755 index 000000000..398626635 --- /dev/null +++ b/win32/include/boost/fusion/support/ext_/is_segmented.hpp @@ -0,0 +1,48 @@ +/*============================================================================= + Copyright (c) 2006 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_IS_SEGMENTED_03202006_0015) +#define FUSION_IS_SEGMENTED_03202006_0015 + +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct sequence_facade_tag; + struct boost_tuple_tag; // boost::tuples::tuple tag + struct array_tag; // boost::array tag + struct mpl_sequence_tag; // mpl sequence tag + struct std_pair_tag; // std::pair tag + struct iterator_range_tag; + + namespace extension + { + template + struct is_segmented_impl + { + template + struct apply + : mpl::false_ + {}; + }; + + template<> + struct is_segmented_impl; + } + + namespace traits + { + template + struct is_segmented + : extension::is_segmented_impl::type>:: + template apply + { + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/support/is_iterator.hpp b/win32/include/boost/fusion/support/is_iterator.hpp new file mode 100755 index 000000000..b87de2463 --- /dev/null +++ b/win32/include/boost/fusion/support/is_iterator.hpp @@ -0,0 +1,20 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_IS_ITERATOR_05062005_1219) +#define FUSION_IS_ITERATOR_05062005_1219 + +#include + +namespace boost { namespace fusion +{ + struct iterator_root; + + template + struct is_fusion_iterator : is_base_of {}; +}} + +#endif diff --git a/win32/include/boost/fusion/support/is_sequence.hpp b/win32/include/boost/fusion/support/is_sequence.hpp new file mode 100755 index 000000000..84df48075 --- /dev/null +++ b/win32/include/boost/fusion/support/is_sequence.hpp @@ -0,0 +1,65 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_IS_SEQUENCE_05052005_1002) +#define FUSION_IS_SEQUENCE_05052005_1002 + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct non_fusion_tag; + struct boost_tuple_tag; // boost::tuples::tuple tag + struct array_tag; // boost::array tag + struct mpl_sequence_tag; // mpl sequence tag + struct std_pair_tag; // std::pair tag + + namespace extension + { + template + struct is_sequence_impl + { + template + struct apply : is_base_of {}; + }; + + template <> + struct is_sequence_impl + { + template + struct apply : mpl::false_ {}; + }; + + template <> + struct is_sequence_impl; + + template <> + struct is_sequence_impl; + + template <> + struct is_sequence_impl; + + template <> + struct is_sequence_impl; + } + + namespace traits + { + template + struct is_sequence + : extension::is_sequence_impl::type>:: + template apply + {}; + } +}} + +#endif diff --git a/win32/include/boost/fusion/support/is_view.hpp b/win32/include/boost/fusion/support/is_view.hpp new file mode 100755 index 000000000..5a43591da --- /dev/null +++ b/win32/include/boost/fusion/support/is_view.hpp @@ -0,0 +1,63 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_IS_VIEW_03202006_0015) +#define FUSION_IS_VIEW_03202006_0015 + +#include +#include + +namespace boost { namespace fusion +{ + // Special tags: + struct sequence_facade_tag; + struct boost_tuple_tag; // boost::tuples::tuple tag + struct array_tag; // boost::array tag + struct mpl_sequence_tag; // mpl sequence tag + struct std_pair_tag; // std::pair tag + + namespace extension + { + template + struct is_view_impl + { + template + struct apply + : detail::fusion_is_view + {}; + }; + + template <> + struct is_view_impl + { + template + struct apply : Sequence::is_view {}; + }; + + template <> + struct is_view_impl; + + template <> + struct is_view_impl; + + template <> + struct is_view_impl; + + template <> + struct is_view_impl; + } + + namespace traits + { + template + struct is_view : + extension::is_view_impl::type>:: + template apply::type + {}; + } +}} + +#endif diff --git a/win32/include/boost/fusion/support/iterator_base.hpp b/win32/include/boost/fusion/support/iterator_base.hpp new file mode 100755 index 000000000..e92670379 --- /dev/null +++ b/win32/include/boost/fusion/support/iterator_base.hpp @@ -0,0 +1,31 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ITERATOR_BASE_05042005_1008) +#define FUSION_ITERATOR_BASE_05042005_1008 + +namespace boost { namespace fusion +{ + struct iterator_root {}; + + template + struct iterator_base : iterator_root + { + Iterator const& + cast() const + { + return static_cast(*this); + } + + Iterator& + cast() + { + return static_cast(*this); + } + }; +}} + +#endif diff --git a/win32/include/boost/fusion/support/pair.hpp b/win32/include/boost/fusion/support/pair.hpp new file mode 100755 index 000000000..2b73edcc6 --- /dev/null +++ b/win32/include/boost/fusion/support/pair.hpp @@ -0,0 +1,102 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + Copyright (c) 2006 Tobias Schwinger + + 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(FUSION_PAIR_07222005_1203) +#define FUSION_PAIR_07222005_1203 + +#include +#include + +namespace boost { namespace fusion +{ + // A half runtime pair where the first type does not have data + template + struct pair + { + pair() + : second() {} + + pair(typename detail::call_param::type val) + : second(val) {} + + template + pair(pair const& rhs) + : second(rhs.second) {} + + template + pair& operator=(pair const& rhs) + { + second = rhs.second; + return *this; + } + + typedef First first_type; + typedef Second second_type; + Second second; + }; + + namespace result_of + { + template + struct make_pair + { + typedef fusion::pair::type> type; + }; + + template + struct first + { + typedef typename Pair::first_type type; + }; + + template + struct second + { + typedef typename Pair::second_type type; + }; + } + + template + inline typename result_of::make_pair::type + make_pair(Second const& val) + { + return pair::type>(val); + } + + template + inline OStream& + operator<<(OStream& os, pair const& p) + { + os << p.second; + return os; + } + + template + inline IStream& + operator>>(IStream& is, pair& p) + { + is >> p.second; + return is; + } + + template + inline bool + operator==(pair const& l, pair const& r) + { + return l.second == r.second; + } + + template + inline bool + operator!=(pair const& l, pair const& r) + { + return l.second != r.second; + } +}} + +#endif diff --git a/win32/include/boost/fusion/support/sequence_base.hpp b/win32/include/boost/fusion/support/sequence_base.hpp new file mode 100755 index 000000000..995709368 --- /dev/null +++ b/win32/include/boost/fusion/support/sequence_base.hpp @@ -0,0 +1,45 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2007 Tobias Schwinger + + 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(FUSION_SEQUENCE_BASE_04182005_0737) +#define FUSION_SEQUENCE_BASE_04182005_0737 + +#include + +namespace boost { namespace fusion +{ + struct sequence_root {}; + + template + struct sequence_base : sequence_root + { + Sequence const& + derived() const + { + return static_cast(*this); + } + + Sequence& + derived() + { + return static_cast(*this); + } + }; + + struct fusion_sequence_tag; +}} + +namespace boost { namespace mpl +{ + // Deliberately break mpl::begin, so it doesn't lie that a Fusion sequence + // is not an MPL sequence by returning mpl::void_. + // In other words: Fusion Sequences are always MPL Sequences, but they can + // be incompletely defined. + template<> struct begin_impl< boost::fusion::fusion_sequence_tag >; +}} + +#endif diff --git a/win32/include/boost/fusion/support/tag_of.hpp b/win32/include/boost/fusion/support/tag_of.hpp new file mode 100755 index 000000000..af54d2c33 --- /dev/null +++ b/win32/include/boost/fusion/support/tag_of.hpp @@ -0,0 +1,110 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_TAG_OF_09232005_0845) +#define FUSION_TAG_OF_09232005_0845 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + template + class array; // forward + + namespace tuples + { + struct null_type; + + template < + class T0, class T1, class T2, class T3, class T4, + class T5, class T6, class T7, class T8, class T9 + > + class tuple; + + template + struct cons; + } +} + +namespace boost { namespace fusion +{ + struct non_fusion_tag; + struct mpl_sequence_tag; + + namespace detail + { + BOOST_MPL_HAS_XXX_TRAIT_DEF(fusion_tag) + + template + struct is_specialized + : mpl::false_ + {}; + + template < + class T0, class T1, class T2, class T3, class T4, + class T5, class T6, class T7, class T8, class T9 + > + struct is_specialized > + : mpl::true_ + {}; + + template + struct is_specialized > + : mpl::true_ + {}; + + template <> + struct is_specialized + : mpl::true_ + {}; + + template + struct is_specialized > + : mpl::true_ + {}; + + template + struct is_specialized > + : mpl::true_ + {}; + } + + namespace traits + { + template + struct tag_of + : mpl::if_< detail::is_mpl_sequence, + mpl::identity, + mpl::identity >::type + { + BOOST_MPL_ASSERT_NOT((detail::is_specialized)); + }; + + template + struct tag_of >::type> + { + typedef typename Sequence::fusion_tag type; + }; + } + + namespace detail + { + template + struct tag_of + : traits::tag_of::type> + {}; + } +}} +#endif diff --git a/win32/include/boost/fusion/support/tag_of_fwd.hpp b/win32/include/boost/fusion/support/tag_of_fwd.hpp new file mode 100755 index 000000000..b725bb36c --- /dev/null +++ b/win32/include/boost/fusion/support/tag_of_fwd.hpp @@ -0,0 +1,20 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_TAG_OF_FWD_31122005_1445) +#define BOOST_FUSION_TAG_OF_FWD_31122005_1445 + +namespace boost { namespace fusion +{ + namespace traits + { + template + struct tag_of; + } +}} + +#endif diff --git a/win32/include/boost/fusion/support/unused.hpp b/win32/include/boost/fusion/support/unused.hpp new file mode 100755 index 000000000..ca57fe29f --- /dev/null +++ b/win32/include/boost/fusion/support/unused.hpp @@ -0,0 +1,62 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_SUPPORT_UNUSED_20070305_1038) +#define BOOST_FUSION_SUPPORT_UNUSED_20070305_1038 + +#include +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable: 4522) // multiple assignment operators specified warning +#endif + +namespace boost { namespace fusion { + struct unused_type + { + unused_type() + { + } + + template + unused_type(T const&) + { + } + + template + unused_type const& + operator=(T const&) const + { + return *this; + } + + template + unused_type& + operator=(T const&) + { + return *this; + } + + unused_type const& + operator=(unused_type const&) const + { + return *this; + } + + unused_type& + operator=(unused_type const&) + { + return *this; + } + }; + + unused_type const unused = unused_type(); +}} + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +#endif diff --git a/win32/include/boost/fusion/support/void.hpp b/win32/include/boost/fusion/support/void.hpp new file mode 100755 index 000000000..e0d0c45c1 --- /dev/null +++ b/win32/include/boost/fusion/support/void.hpp @@ -0,0 +1,15 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_SUPPORT_VOID_20070706_2125) +#define BOOST_FUSION_SUPPORT_VOID_20070706_2125 + +namespace boost { namespace fusion +{ + struct void_ {}; +}} + +#endif diff --git a/win32/include/boost/fusion/tuple.hpp b/win32/include/boost/fusion/tuple.hpp new file mode 100755 index 000000000..eeccf5e0a --- /dev/null +++ b/win32/include/boost/fusion/tuple.hpp @@ -0,0 +1,15 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_TUPLE_10032005_0806) +#define FUSION_TUPLE_10032005_0806 + +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/tuple/detail/tuple_forward_ctor.hpp b/win32/include/boost/fusion/tuple/detail/tuple_forward_ctor.hpp new file mode 100755 index 000000000..42b7e0e00 --- /dev/null +++ b/win32/include/boost/fusion/tuple/detail/tuple_forward_ctor.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_TUPLE_FORWARD_CTOR_10032005_0815) +#define FUSION_TUPLE_FORWARD_CTOR_10032005_0815 + +#include +#include +#include + +#define BOOST_PP_FILENAME_1 \ + +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_VECTOR_SIZE) +#include BOOST_PP_ITERATE() + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + +#if N == 1 + explicit +#endif + tuple(BOOST_PP_ENUM_BINARY_PARAMS( + N, typename detail::call_param::type _)) + : base_type(BOOST_PP_ENUM_PARAMS(N, _)) {} + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/tuple/make_tuple.hpp b/win32/include/boost/fusion/tuple/make_tuple.hpp new file mode 100755 index 000000000..46bc14c4e --- /dev/null +++ b/win32/include/boost/fusion/tuple/make_tuple.hpp @@ -0,0 +1,56 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_MAKE_TUPLE_10032005_0843) +#define FUSION_MAKE_TUPLE_10032005_0843 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + inline tuple<> + make_tuple() + { + return tuple<>(); + } + +#define BOOST_FUSION_AS_FUSION_ELEMENT(z, n, data) \ + typename detail::as_fusion_element::type + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_VECTOR_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_AS_FUSION_ELEMENT + +}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + template + inline tuple + make_tuple(BOOST_PP_ENUM_BINARY_PARAMS(N, T, const& _)) + { + return tuple( + BOOST_PP_ENUM_PARAMS(N, _)); + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/tuple/tuple.hpp b/win32/include/boost/fusion/tuple/tuple.hpp new file mode 100755 index 000000000..078d64237 --- /dev/null +++ b/win32/include/boost/fusion/tuple/tuple.hpp @@ -0,0 +1,72 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_TUPLE_10032005_0810) +#define FUSION_TUPLE_10032005_0810 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + template + struct tuple : vector + { + typedef vector< + BOOST_PP_ENUM_PARAMS(FUSION_MAX_VECTOR_SIZE, T)> + base_type; + + tuple() + : base_type() {} + + template + tuple(Sequence const& rhs) + : base_type(rhs) {} + + #include + + template + tuple& + operator=(T const& rhs) + { + base_type::operator=(rhs); + return *this; + } + }; + + template + struct tuple_size : result_of::size {}; + + template + struct tuple_element : result_of::value_at_c {}; + + template + inline typename + lazy_disable_if< + is_const + , result_of::at_c + >::type + get(Tuple& tup) + { + return at_c(tup); + } + + template + inline typename result_of::at_c::type + get(Tuple const& tup) + { + return at_c(tup); + } +}} + +#endif diff --git a/win32/include/boost/fusion/tuple/tuple_fwd.hpp b/win32/include/boost/fusion/tuple/tuple_fwd.hpp new file mode 100755 index 000000000..546e8e456 --- /dev/null +++ b/win32/include/boost/fusion/tuple/tuple_fwd.hpp @@ -0,0 +1,24 @@ +/*============================================================================= + Copyright (c) 2005 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_TUPLE_FORWARD_10032005_0956) +#define FUSION_TUPLE_FORWARD_10032005_0956 + +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + + template < + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( + FUSION_MAX_VECTOR_SIZE, typename T, void_) + > + struct tuple; +}} + +#endif diff --git a/win32/include/boost/fusion/tuple/tuple_tie.hpp b/win32/include/boost/fusion/tuple/tuple_tie.hpp new file mode 100755 index 000000000..4c84c5554 --- /dev/null +++ b/win32/include/boost/fusion/tuple/tuple_tie.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef BOOST_PP_IS_ITERATING +#if !defined(FUSION_TUPLE_TIE_10032005_0846) +#define FUSION_TUPLE_TIE_10032005_0846 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ +#define BOOST_FUSION_REF(z, n, data) BOOST_PP_CAT(T, n)& + +#define BOOST_PP_FILENAME_1 +#define BOOST_PP_ITERATION_LIMITS (1, FUSION_MAX_VECTOR_SIZE) +#include BOOST_PP_ITERATE() + +#undef BOOST_FUSION_REF + +}} + +#endif +#else // defined(BOOST_PP_IS_ITERATING) +/////////////////////////////////////////////////////////////////////////////// +// +// Preprocessor vertical repetition code +// +/////////////////////////////////////////////////////////////////////////////// + +#define N BOOST_PP_ITERATION() + + template + inline tuple + tie(BOOST_PP_ENUM_BINARY_PARAMS(N, T, & _)) + { + return tuple( + BOOST_PP_ENUM_PARAMS(N, _)); + } + +#undef N +#endif // defined(BOOST_PP_IS_ITERATING) + diff --git a/win32/include/boost/fusion/view.hpp b/win32/include/boost/fusion/view.hpp new file mode 100755 index 000000000..805a99f82 --- /dev/null +++ b/win32/include/boost/fusion/view.hpp @@ -0,0 +1,17 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_VIEW_10022005_0620) +#define FUSION_SEQUENCE_VIEW_10022005_0620 + +#include +#include +#include +#include +#include +#include + +#endif diff --git a/win32/include/boost/fusion/view/detail/strictest_traversal.hpp b/win32/include/boost/fusion/view/detail/strictest_traversal.hpp new file mode 100755 index 000000000..b79881d1f --- /dev/null +++ b/win32/include/boost/fusion/view/detail/strictest_traversal.hpp @@ -0,0 +1,68 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_STRICTEST_TRAVERSAL_20060123_2101) +#define FUSION_STRICTEST_TRAVERSAL_20060123_2101 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct forward_traversal_tag; + struct bidirectional_traversal_tag; + struct random_access_traversal_tag; + + namespace detail + { + template::value> + struct stricter_traversal + { + typedef Tag1 type; + }; + + template + struct stricter_traversal + { + typedef Tag2 type; + }; + + struct strictest_traversal_impl + { + template + struct result; + + template + struct result + { + typedef typename remove_reference::type next_value; + typedef typename remove_reference::type strictest_so_far; + + typedef strictest_so_far tag1; + typedef typename traits::category_of::type tag2; + + typedef typename stricter_traversal::type type; + }; + }; + + template + struct strictest_traversal + : result_of::fold< + Sequence, fusion::random_access_traversal_tag, + strictest_traversal_impl> + {}; + + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/ext_/multiple_view.hpp b/win32/include/boost/fusion/view/ext_/multiple_view.hpp new file mode 100755 index 000000000..89c4e4cb6 --- /dev/null +++ b/win32/include/boost/fusion/view/ext_/multiple_view.hpp @@ -0,0 +1,178 @@ +/*============================================================================= + Copyright (c) 2001-2006 Eric Niebler + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef FUSION_MULTIPLE_VIEW_05052005_0335 +#define FUSION_MULTIPLE_VIEW_05052005_0335 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct multiple_view_tag; + struct forward_traversal_tag; + struct fusion_sequence_tag; + + template + struct multiple_view + : sequence_base > + { + typedef multiple_view_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef forward_traversal_tag category; + typedef mpl::true_ is_view; + typedef mpl::int_ size; + typedef T value_type; + + multiple_view() + : val() + {} + + explicit multiple_view(typename detail::call_param::type val) + : val(val) + {} + + value_type val; + }; + + template + inline multiple_view::type> + make_multiple_view(T const& v) + { + return multiple_view::type>(v); + } + + struct multiple_view_iterator_tag; + struct forward_traversal_tag; + + template + struct multiple_view_iterator + : iterator_base > + { + typedef multiple_view_iterator_tag fusion_tag; + typedef forward_traversal_tag category; + typedef typename MultipleView::value_type value_type; + typedef MultipleView multiple_view_type; + typedef Index index; + + explicit multiple_view_iterator(multiple_view_type const &view_) + : view(view_) + {} + + multiple_view_type view; + }; + + namespace extension + { + template + struct next_impl; + + template <> + struct next_impl + { + template + struct apply + { + typedef multiple_view_iterator< + typename mpl::next::type + , typename Iterator::multiple_view_type + > type; + + static type + call(Iterator const &where) + { + return type(where.view); + } + }; + }; + + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef multiple_view_iterator< + typename Sequence::size + , Sequence + > type; + + static type + call(Sequence &seq) + { + return type(seq); + } + }; + }; + + template + struct deref_impl; + + template <> + struct deref_impl + { + template + struct apply + { + typedef typename Iterator::value_type type; + + static type + call(Iterator const& i) + { + return i.view.val; + } + }; + }; + + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef multiple_view_iterator< + mpl::int_<0> + , Sequence + > type; + + static type + call(Sequence &seq) + { + return type(seq); + } + }; + }; + + template + struct value_of_impl; + + template <> + struct value_of_impl + { + template + struct apply + { + typedef typename Iterator::multiple_view_type multiple_view_type; + typedef typename multiple_view_type::value_type type; + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/ext_/segmented_iterator.hpp b/win32/include/boost/fusion/view/ext_/segmented_iterator.hpp new file mode 100755 index 000000000..f5a7f87a0 --- /dev/null +++ b/win32/include/boost/fusion/view/ext_/segmented_iterator.hpp @@ -0,0 +1,425 @@ +/*============================================================================= + Copyright (c) 2006 Eric Niebler + + Use, modification and distribution is subject to the Boost Software + License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef FUSION_SEGMENTED_ITERATOR_EAN_05032006_1027 +#define FUSION_SEGMENTED_ITERATOR_EAN_05032006_1027 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for nil +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct fusion_sequence_tag; + + namespace detail + { + using mpl::_; + using mpl::not_; + + //////////////////////////////////////////////////////////////////////////// + template + struct is_empty + : result_of::equal_to< + typename result_of::begin::type + , typename result_of::end::type + > + {}; + + template + struct is_empty + : is_empty + {}; + + struct segmented_range_tag; + + //////////////////////////////////////////////////////////////////////////// + template + struct segmented_range + : sequence_base > + { + BOOST_MPL_ASSERT_NOT((is_reference)); + typedef mpl::bool_ is_segmented; + typedef segmented_range_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef mpl::true_ is_view; + typedef Iterator iterator_type; + + // If this is a range of segments, skip over the empty ones + typedef typename mpl::if_< + is_segmented + , filter_view > > + , Sequence + >::type sequence_non_ref_type; + + typedef typename mpl::if_< + traits::is_view + , sequence_non_ref_type + , sequence_non_ref_type & + >::type sequence_type; + + typedef typename traits::category_of::type category; + + explicit segmented_range(Sequence &sequence_) + : sequence(sequence_type(sequence_)) + , where_(fusion::begin(sequence)) + {} + + segmented_range(sequence_type sequence_, iterator_type const &wh) + : sequence(sequence_) + , where_(wh) + {} + + sequence_type sequence; + iterator_type where_; + }; + } + + namespace extension + { + template<> + struct is_segmented_impl + { + template + struct apply + : Sequence::is_segmented + {}; + }; + + template<> + struct size_impl + { + template + struct apply + : mpl::int_< + result_of::distance< + typename Sequence::iterator_type + , typename result_of::end::type + >::value + > + {}; + }; + + template<> + struct segments_impl + { + template + struct apply + { + typedef Sequence &type; + static type call(Sequence &seq) + { + return seq; + } + }; + }; + + template<> + struct begin_impl + { + template + struct apply + { + typedef typename Sequence::iterator_type type; + static type call(Sequence &seq) + { + return seq.where_; + } + }; + }; + + template<> + struct end_impl + { + template + struct apply + { + typedef typename Sequence::sequence_non_ref_type sequence; + typedef typename result_of::end::type type; + + static type call(Sequence &seq) + { + return fusion::end(seq.sequence); + } + }; + }; + } + + namespace detail + { + /////////////////////////////////////////////////////////////////////// + template + struct range_next; + + template + struct range_next > + { + typedef typename result_of::next::type iterator_type; + typedef segmented_range type; + + static type call(segmented_range const &rng) + { + return type(rng.sequence, fusion::next(rng.where_)); + } + }; + + /////////////////////////////////////////////////////////////////////// + template + struct is_range_next_empty + : is_empty::type> + {}; + + template<> + struct is_range_next_empty + : mpl::true_ + {}; + + /////////////////////////////////////////////////////////////////////// + template::value> + struct as_segmented_range + { + typedef typename result_of::segments::type segments; + typedef typename remove_reference::type sequence; + typedef typename result_of::begin > > >::type begin; + typedef segmented_range type; + + static type call(Sequence &seq) + { + segments segs(fusion::segments(seq)); + return type(segs); + } + }; + + template + struct as_segmented_range + { + typedef typename remove_reference::type sequence; + typedef typename result_of::begin::type begin; + typedef segmented_range type; + + static type call(Sequence &seq) + { + return type(seq); + } + }; + + template + struct as_segmented_range, IsSegmented> + { + typedef segmented_range type; + static type &call(type &seq) + { + return seq; + } + }; + + /////////////////////////////////////////////////////////////////////// + template< + typename Sequence + , typename State = nil + , bool IsSegmented = traits::is_segmented::value + > + struct push_segments + { + typedef typename as_segmented_range::type range; + typedef typename result_of::begin::type begin; + typedef typename result_of::deref::type next_ref; + typedef typename remove_reference::type next; + typedef push_segments > push; + typedef typename push::type type; + + static type call(Sequence &seq, State const &state) + { + range rng(as_segmented_range::call(seq)); + next_ref nxt(*fusion::begin(rng)); + return push::call(nxt, fusion::make_cons(rng, state)); + } + }; + + template + struct push_segments + { + typedef typename as_segmented_range::type range; + typedef cons type; + + static type call(Sequence &seq, State const &state) + { + range rng(as_segmented_range::call(seq)); + return fusion::make_cons(rng, state); + } + }; + + /////////////////////////////////////////////////////////////////////// + template::value> + struct pop_segments + { + typedef range_next next; + typedef push_segments push; + typedef typename push::type type; + + static type call(State const &state) + { + typename next::type rng(next::call(state.car)); + return push::call(rng, state.cdr); + } + }; + + template + struct pop_segments + { + typedef pop_segments pop; + typedef typename pop::type type; + + static type call(State const &state) + { + return pop::call(state.cdr); + } + }; + + template<> + struct pop_segments + { + typedef nil type; + + static type call(nil const &) + { + return nil(); + } + }; + } // namespace detail + + struct segmented_iterator_tag; + + //////////////////////////////////////////////////////////////////////////// + template + struct segmented_iterator + : fusion::iterator_base > + { + typedef segmented_iterator_tag fusion_tag; + typedef fusion::forward_traversal_tag category; + + typedef Cons cons_type; + typedef typename Cons::car_type car_type; + typedef typename Cons::cdr_type cdr_type; + + explicit segmented_iterator(Cons const &cons) + : cons_(cons) + {} + + cons_type const &cons() const { return this->cons_; }; + car_type const &car() const { return this->cons_.car; }; + cdr_type const &cdr() const { return this->cons_.cdr; }; + + private: + Cons cons_; + }; + + /////////////////////////////////////////////////////////////////////////// + template + struct segmented_begin + { + typedef typename detail::push_segments push; + typedef segmented_iterator type; + + static type call(Sequence &seq) + { + return type(push::call(seq, nil())); + } + }; + + /////////////////////////////////////////////////////////////////////////// + template + struct segmented_end + { + typedef segmented_iterator type; + + static type call(Sequence &) + { + return type(nil()); + } + }; + + namespace extension + { + template<> + struct value_of_impl + { + template + struct apply + { + typedef typename result_of::begin::type begin; + typedef typename result_of::value_of::type type; + }; + }; + + template<> + struct deref_impl + { + template + struct apply + { + typedef typename result_of::begin::type begin; + typedef typename result_of::deref::type type; + + static type call(Iterator const &it) + { + return *fusion::begin(it.car()); + } + }; + }; + + // discards the old head, expands the right child of the new head + // and pushes the result to the head of the list. + + template<> + struct next_impl + { + template< + typename Iterator + , bool IsSegmentDone = detail::is_range_next_empty::value + > + struct apply + { + typedef typename Iterator::cdr_type cdr_type; + typedef detail::range_next next; + typedef segmented_iterator > type; + + static type call(Iterator const &it) + { + return type(fusion::make_cons(next::call(it.car()), it.cdr())); + } + }; + + template + struct apply // segment done, move to next segment + { + typedef typename Iterator::cdr_type cdr_type; + typedef typename detail::pop_segments pop; + typedef segmented_iterator type; + + static type call(Iterator const &it) + { + return type(pop::call(it.cdr())); + } + }; + }; + } +}} // namespace boost::fusion + +#endif diff --git a/win32/include/boost/fusion/view/ext_/segmented_iterator_range.hpp b/win32/include/boost/fusion/view/ext_/segmented_iterator_range.hpp new file mode 100755 index 000000000..86feddd24 --- /dev/null +++ b/win32/include/boost/fusion/view/ext_/segmented_iterator_range.hpp @@ -0,0 +1,537 @@ +/*============================================================================= + Copyright (c) 2006 Eric Niebler + + Use, modification and distribution is subject to the Boost Software + License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#ifndef FUSION_SEGMENTED_ITERATOR_RANGE_EAN_05032006_1027 +#define FUSION_SEGMENTED_ITERATOR_RANGE_EAN_05032006_1027 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + namespace detail + { + //////////////////////////////////////////////////////////////////////////// + template + struct reverse_cons; + + template + struct reverse_cons, State> + { + typedef reverse_cons > reverse; + typedef typename reverse::type type; + + static type call(cons const &cons, State const &state = State()) + { + return reverse::call(cons.cdr, fusion::make_cons(cons.car, state)); + } + }; + + template + struct reverse_cons + { + typedef State type; + + static State const &call(nil const &, State const &state = State()) + { + return state; + } + }; + + //////////////////////////////////////////////////////////////////////////// + // tags + struct full_view {}; + struct left_view {}; + struct right_view {}; + struct center_view {}; + + template + struct segmented_view_tag; + + //////////////////////////////////////////////////////////////////////////// + // a segmented view of that includes all elements either to the + // right or the left of a segmented iterator. + template + struct segmented_view + : sequence_base > + { + typedef segmented_view_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef mpl::true_ is_view; + typedef forward_traversal_tag category; + + explicit segmented_view(Cons1 const &cons) + : cons(cons) + {} + + typedef Cons1 cons_type; + cons_type const &cons; + }; + + // a segmented view that contains all the elements in between + // two segmented iterators + template + struct segmented_view + : sequence_base > + { + typedef segmented_view_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef mpl::true_ is_view; + typedef forward_traversal_tag category; + + segmented_view(Cons1 const &lcons, Cons2 const &rcons) + : left_cons(lcons) + , right_cons(rcons) + {} + + typedef Cons1 left_cons_type; + typedef Cons2 right_cons_type; + + left_cons_type const &left_cons; + right_cons_type const &right_cons; + }; + + //////////////////////////////////////////////////////////////////////////// + // Used to transform a sequence of segments. The first segment is + // bounded by RightCons, and the last segment is bounded by LeftCons + // and all the others are passed through unchanged. + template + struct segments_transform + { + explicit segments_transform(RightCons const &cons_) + : right_cons(cons_) + , left_cons(cons_) + {} + + segments_transform(RightCons const &right_cons_, LeftCons const &left_cons_) + : right_cons(right_cons_) + , left_cons(left_cons_) + {} + + template + struct result_; + + template + struct result_ + { + typedef segmented_view type; + }; + + template + struct result_ + { + typedef segmented_view type; + }; + + template + struct result_ + { + typedef Second type; + }; + + template + struct result; + + template + struct result + : result_< + typename remove_cv::type>::type + , typename remove_cv::type>::type + > + {}; + + template + segmented_view operator ()(right_view, Second &second) const + { + return segmented_view(this->right_cons); + } + + template + segmented_view operator ()(left_view, Second &second) const + { + return segmented_view(this->left_cons); + } + + template + Second &operator ()(full_view, Second &second) const + { + return second; + } + + private: + RightCons const &right_cons; + LeftCons const &left_cons; + }; + + } // namespace detail + + namespace extension + { + //////////////////////////////////////////////////////////////////////////// + template + struct is_segmented_impl > + { + template + struct apply + : mpl::true_ + {}; + }; + + //////////////////////////////////////////////////////////////////////////// + template<> + struct segments_impl > + { + template< + typename Sequence + , typename Cdr = typename Sequence::cons_type::cdr_type + > + struct apply + { + typedef typename Sequence::cons_type::car_type segmented_range; + typedef typename result_of::size::type size; + typedef typename mpl::prior::type size_minus_1; + typedef detail::segments_transform tfx; + typedef joint_view< + single_view const + , multiple_view const + > mask; + typedef transform_view type; + + static type call(Sequence &seq) + { + return type( + mask( + make_single_view(detail::right_view()) + , make_multiple_view(detail::full_view()) + ) + , seq.cons.car + , tfx(seq.cons.cdr) + ); + } + }; + + template + struct apply + { + typedef typename Sequence::cons_type::car_type segmented_range; + typedef typename segmented_range::iterator_type begin; + typedef typename segmented_range::sequence_non_ref_type sequence_type; + typedef typename result_of::end::type end; + typedef iterator_range range; + typedef single_view type; + + static type call(Sequence &seq) + { + return type(range(seq.cons.car.where_, fusion::end(seq.cons.car.sequence))); + } + }; + }; + + //////////////////////////////////////////////////////////////////////////// + template<> + struct segments_impl > + { + template< + typename Sequence + , typename Cdr = typename Sequence::cons_type::cdr_type + > + struct apply + { + typedef typename Sequence::cons_type::car_type right_segmented_range; + typedef typename right_segmented_range::sequence_type sequence_type; + typedef typename right_segmented_range::iterator_type iterator_type; + + typedef iterator_range< + typename result_of::begin::type + , typename result_of::next::type + > segmented_range; + + typedef detail::segments_transform tfx; + typedef typename result_of::size::type size; + typedef typename mpl::prior::type size_minus_1; + typedef joint_view< + multiple_view const + , single_view const + > mask; + typedef transform_view type; + + static type call(Sequence &seq) + { + return type( + mask( + make_multiple_view(detail::full_view()) + , make_single_view(detail::left_view()) + ) + , segmented_range(fusion::begin(seq.cons.car.sequence), fusion::next(seq.cons.car.where_)) + , tfx(seq.cons.cdr) + ); + } + }; + + template + struct apply + { + typedef typename Sequence::cons_type::car_type segmented_range; + typedef typename segmented_range::sequence_non_ref_type sequence_type; + typedef typename result_of::begin::type begin; + typedef typename segmented_range::iterator_type end; + typedef iterator_range range; + typedef single_view type; + + static type call(Sequence &seq) + { + return type(range(fusion::begin(seq.cons.car.sequence), seq.cons.car.where_)); + } + }; + }; + + //////////////////////////////////////////////////////////////////////////// + template<> + struct segments_impl > + { + template + struct apply + { + typedef typename Sequence::right_cons_type right_cons_type; + typedef typename Sequence::left_cons_type left_cons_type; + typedef typename right_cons_type::car_type right_segmented_range; + typedef typename left_cons_type::car_type left_segmented_range; + + typedef iterator_range< + typename result_of::begin::type + , typename result_of::next::type>::type + > segmented_range; + + typedef typename mpl::minus< + typename result_of::size::type + , mpl::int_<2> + >::type size_minus_2; + + BOOST_MPL_ASSERT_RELATION(0, <=, size_minus_2::value); + + typedef detail::segments_transform< + typename left_cons_type::cdr_type + , typename right_cons_type::cdr_type + > tfx; + + typedef joint_view< + multiple_view const + , single_view const + > left_mask; + + typedef joint_view< + single_view const + , left_mask const + > mask; + + typedef transform_view type; + + static type call(Sequence &seq) + { + left_mask lmask( + make_multiple_view(detail::full_view()) + , make_single_view(detail::left_view()) + ); + return type( + mask(make_single_view(detail::right_view()), lmask) + , segmented_range(fusion::begin(seq.left_cons.car), fusion::next(fusion::begin(seq.right_cons.car))) + , tfx(seq.left_cons.cdr, seq.right_cons.cdr) + ); + } + }; + }; + } + + // specialize iterator_range for use with segmented iterators, so that + // it presents a segmented view of the range. + template + struct iterator_range; + + template + struct iterator_range, segmented_iterator > + : sequence_base, segmented_iterator > > + { + typedef typename convert_iterator >::type begin_type; + typedef typename convert_iterator >::type end_type; + typedef typename detail::reverse_cons::type begin_cons_type; + typedef typename detail::reverse_cons::type end_cons_type; + typedef iterator_range_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef typename traits::category_of::type category; + typedef typename result_of::distance::type size; + typedef mpl::true_ is_view; + + iterator_range(segmented_iterator const& first_, segmented_iterator const& last_) + : first(convert_iterator >::call(first_)) + , last(convert_iterator >::call(last_)) + , first_cons(detail::reverse_cons::call(first_.cons())) + , last_cons(detail::reverse_cons::call(last_.cons())) + {} + + begin_type first; + end_type last; + + begin_cons_type first_cons; + end_cons_type last_cons; + }; + + namespace detail + { + + template + struct same_segment + : mpl::false_ + {}; + + template + struct same_segment, cons > + : mpl::and_< + traits::is_segmented + , is_same + > + {}; + + //////////////////////////////////////////////////////////////////////////// + template + struct segments_gen; + + //////////////////////////////////////////////////////////////////////////// + template + struct segments_gen2 + { + typedef segments_gen gen; + typedef typename gen::type type; + + static type call(Cons1 const &cons1, Cons2 const &cons2) + { + return gen::call(cons1.cdr, cons2.cdr); + } + }; + + template + struct segments_gen2 + { + typedef segmented_view view; + typedef typename result_of::segments::type type; + + static type call(Cons1 const &cons1, Cons2 const &cons2) + { + view v(cons1, cons2); + return fusion::segments(v); + } + }; + + template + struct segments_gen2, cons, false> + { + typedef iterator_range< + typename Car1::iterator_type + , typename Car2::iterator_type + > range; + + typedef single_view type; + + static type call(cons const &cons1, cons const &cons2) + { + return type(range(cons1.car.where_, cons2.car.where_)); + } + }; + + //////////////////////////////////////////////////////////////////////////// + template + struct segments_gen + : segments_gen2::value> + {}; + + template + struct segments_gen, nil> + { + typedef segmented_view > view; + typedef typename result_of::segments::type type; + + static type call(cons const &cons, nil const &) + { + view v(cons); + return fusion::segments(v); + } + }; + + template<> + struct segments_gen + { + typedef nil type; + + static type call(nil const &, nil const &) + { + return nil(); + } + }; + } // namespace detail + + namespace extension + { + template + struct is_segmented_impl; + + // An iterator_range of segmented_iterators is segmented + template<> + struct is_segmented_impl + { + template + struct is_segmented_iterator : mpl::false_ {}; + + template + struct is_segmented_iterator > : mpl::true_ {}; + + template + struct apply + : mpl::and_< + is_segmented_iterator + , is_segmented_iterator + > + {}; + }; + + template + struct segments_impl; + + template<> + struct segments_impl + { + template + struct apply + { + typedef typename Sequence::begin_cons_type begin_cons; + typedef typename Sequence::end_cons_type end_cons; + + typedef detail::segments_gen gen; + typedef typename gen::type type; + + static type call(Sequence &sequence) + { + return gen::call(sequence.first_cons, sequence.last_cons); + } + }; + }; + } + +}} + +#endif diff --git a/win32/include/boost/fusion/view/filter_view.hpp b/win32/include/boost/fusion/view/filter_view.hpp new file mode 100755 index 000000000..2db434e81 --- /dev/null +++ b/win32/include/boost/fusion/view/filter_view.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_VIEW_FILTER_VIEW_10022005_0608) +#define FUSION_SEQUENCE_VIEW_FILTER_VIEW_10022005_0608 + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/view/filter_view/detail/begin_impl.hpp b/win32/include/boost/fusion/view/filter_view/detail/begin_impl.hpp new file mode 100755 index 000000000..998e4f7f0 --- /dev/null +++ b/win32/include/boost/fusion/view/filter_view/detail/begin_impl.hpp @@ -0,0 +1,45 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BEGIN_IMPL_05062005_0903) +#define FUSION_BEGIN_IMPL_05062005_0903 + +namespace boost { namespace fusion +{ + struct filter_view_tag; + + template + struct filter_iterator; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef typename Sequence::first_type first_type; + typedef typename Sequence::last_type last_type; + typedef typename Sequence::pred_type pred_type; + typedef filter_iterator type; + + static type + call(Sequence& s) + { + return type(s.first()); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/filter_view/detail/deref_impl.hpp b/win32/include/boost/fusion/view/filter_view/detail/deref_impl.hpp new file mode 100755 index 000000000..13f2cf44c --- /dev/null +++ b/win32/include/boost/fusion/view/filter_view/detail/deref_impl.hpp @@ -0,0 +1,29 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_DEREF_IMPL_05062005_0905) +#define FUSION_DEREF_IMPL_05062005_0905 + +#include + +namespace boost { namespace fusion +{ + struct filter_view_iterator_tag; + + namespace extension + { + template + struct deref_impl; + + template <> + struct deref_impl + : detail::adapt_deref_traits {}; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/filter_view/detail/end_impl.hpp b/win32/include/boost/fusion/view/filter_view/detail/end_impl.hpp new file mode 100755 index 000000000..1708b40d5 --- /dev/null +++ b/win32/include/boost/fusion/view/filter_view/detail/end_impl.hpp @@ -0,0 +1,44 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_END_IMPL_05062005_0906) +#define FUSION_END_IMPL_05062005_0906 + +namespace boost { namespace fusion +{ + struct filter_view_tag; + + template + struct filter_iterator; + + namespace extension + { + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef typename Sequence::last_type last_type; + typedef typename Sequence::pred_type pred_type; + typedef filter_iterator type; + + static type + call(Sequence& s) + { + return type(s.last()); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/filter_view/detail/equal_to_impl.hpp b/win32/include/boost/fusion/view/filter_view/detail/equal_to_impl.hpp new file mode 100755 index 000000000..cf6903452 --- /dev/null +++ b/win32/include/boost/fusion/view/filter_view/detail/equal_to_impl.hpp @@ -0,0 +1,34 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_EQUAL_TO_IMPL_02012005_2133) +#define BOOST_FUSION_EQUAL_TO_IMPL_02012005_2133 + +namespace boost { namespace fusion +{ + struct filter_view_iterator_tag; + + namespace extension + { + template + struct equal_to; + + template + struct equal_to_impl; + + template<> + struct equal_to_impl + { + template + struct apply + : result_of::equal_to + {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/filter_view/detail/next_impl.hpp b/win32/include/boost/fusion/view/filter_view/detail/next_impl.hpp new file mode 100755 index 000000000..d6df5308e --- /dev/null +++ b/win32/include/boost/fusion/view/filter_view/detail/next_impl.hpp @@ -0,0 +1,64 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_NEXT_IMPL_06052005_0900) +#define FUSION_NEXT_IMPL_06052005_0900 + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct filter_view_iterator_tag; + + template + struct filter_iterator; + + namespace extension + { + template + struct next_impl; + + template <> + struct next_impl + { + template + struct apply + { + typedef typename Iterator::first_type first_type; + typedef typename Iterator::last_type last_type; + typedef typename Iterator::pred_type pred_type; + + typedef typename + mpl::eval_if< + result_of::equal_to + , mpl::identity + , result_of::next + >::type + next_type; + + typedef typename detail::static_find_if< + next_type, last_type, pred_type> + filter; + + typedef filter_iterator< + typename filter::type, last_type, pred_type> + type; + + static type + call(Iterator const& i) + { + return type(filter::call(i.first)); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/filter_view/detail/size_impl.hpp b/win32/include/boost/fusion/view/filter_view/detail/size_impl.hpp new file mode 100755 index 000000000..e81cc1f93 --- /dev/null +++ b/win32/include/boost/fusion/view/filter_view/detail/size_impl.hpp @@ -0,0 +1,38 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SIZE_IMPL_09232005_1058) +#define FUSION_SIZE_IMPL_09232005_1058 + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct filter_view_tag; + + namespace extension + { + template + struct size_impl; + + template <> + struct size_impl + { + template + struct apply + : result_of::distance< + typename result_of::begin::type + , typename result_of::end::type> + {}; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/filter_view/detail/value_of_impl.hpp b/win32/include/boost/fusion/view/filter_view/detail/value_of_impl.hpp new file mode 100755 index 000000000..25c3b4a91 --- /dev/null +++ b/win32/include/boost/fusion/view/filter_view/detail/value_of_impl.hpp @@ -0,0 +1,29 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VALUE_OF_IMPL_05062005_0857) +#define FUSION_VALUE_OF_IMPL_05062005_0857 + +#include + +namespace boost { namespace fusion +{ + struct filter_view_iterator_tag; + + namespace extension + { + template + struct value_of_impl; + + template <> + struct value_of_impl + : detail::adapt_value_traits {}; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/filter_view/filter_view.hpp b/win32/include/boost/fusion/view/filter_view/filter_view.hpp new file mode 100755 index 000000000..014999351 --- /dev/null +++ b/win32/include/boost/fusion/view/filter_view/filter_view.hpp @@ -0,0 +1,51 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_FILTER_VIEW_HPP) +#define FUSION_SEQUENCE_FILTER_VIEW_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct filter_view_tag; + struct forward_traversal_tag; + struct fusion_sequence_tag; + + template + struct filter_view : sequence_base > + { + typedef filter_view_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef forward_traversal_tag category; + typedef mpl::true_ is_view; + + typedef typename result_of::begin::type first_type; + typedef typename result_of::end::type last_type; + typedef Pred pred_type; + + filter_view(Sequence& seq) + : seq(seq) + {} + + first_type first() const { return fusion::begin(seq); } + last_type last() const { return fusion::end(seq); } + typename mpl::if_, Sequence, Sequence&>::type seq; + }; +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/filter_view/filter_view_iterator.hpp b/win32/include/boost/fusion/view/filter_view/filter_view_iterator.hpp new file mode 100755 index 000000000..71a1f7360 --- /dev/null +++ b/win32/include/boost/fusion/view/filter_view/filter_view_iterator.hpp @@ -0,0 +1,48 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_FILTER_VIEW_ITERATOR_05062005_0849) +#define FUSION_FILTER_VIEW_ITERATOR_05062005_0849 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct filter_view_iterator_tag; + struct forward_traversal_tag; + + template + struct filter_iterator : iterator_base > + { + typedef convert_iterator first_converter; + typedef typename first_converter::type first_iter; + typedef convert_iterator last_converter; + typedef typename last_converter::type last_iter; + + typedef filter_view_iterator_tag fusion_tag; + typedef forward_traversal_tag category; + typedef detail::static_find_if filter; + typedef typename filter::type first_type; + typedef last_iter last_type; + typedef Pred pred_type; + + filter_iterator(First const& first) + : first(filter::call(first_converter::call(first))) {} + + first_type first; + }; +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/iterator_range.hpp b/win32/include/boost/fusion/view/iterator_range.hpp new file mode 100755 index 000000000..b23a89034 --- /dev/null +++ b/win32/include/boost/fusion/view/iterator_range.hpp @@ -0,0 +1,12 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_VIEW_ITERATOR_RANGE_10022005_0610) +#define FUSION_SEQUENCE_VIEW_ITERATOR_RANGE_10022005_0610 + +#include + +#endif diff --git a/win32/include/boost/fusion/view/iterator_range/detail/at_impl.hpp b/win32/include/boost/fusion/view/iterator_range/detail/at_impl.hpp new file mode 100755 index 000000000..f48df8cb1 --- /dev/null +++ b/win32/include/boost/fusion/view/iterator_range/detail/at_impl.hpp @@ -0,0 +1,44 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + 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_FUSION_ITERATOR_RANGE_AT_IMPL_HPP_INCLUDED) +#define BOOST_FUSION_ITERATOR_RANGE_AT_IMPL_HPP_INCLUDED + +#include +#include + +namespace boost { namespace fusion +{ + struct iterator_range_tag; + + namespace extension + { + template + struct at_impl; + + template <> + struct at_impl + { + template + struct apply + { + typedef typename Seq::begin_type begin_type; + typedef typename result_of::advance::type pos; + typedef typename result_of::deref::type type; + + static type + call(Seq& s) + { + return * advance(s.first); + } + }; + }; + } +}} + +#endif + diff --git a/win32/include/boost/fusion/view/iterator_range/detail/begin_impl.hpp b/win32/include/boost/fusion/view/iterator_range/detail/begin_impl.hpp new file mode 100755 index 000000000..47971db6b --- /dev/null +++ b/win32/include/boost/fusion/view/iterator_range/detail/begin_impl.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BEGIN_IMPL_05062005_1226) +#define FUSION_BEGIN_IMPL_05062005_1226 + +namespace boost { namespace fusion +{ + struct iterator_range_tag; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef typename Sequence::begin_type type; + + static type + call(Sequence& s) + { + return s.first; + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/iterator_range/detail/end_impl.hpp b/win32/include/boost/fusion/view/iterator_range/detail/end_impl.hpp new file mode 100755 index 000000000..10a391fa4 --- /dev/null +++ b/win32/include/boost/fusion/view/iterator_range/detail/end_impl.hpp @@ -0,0 +1,39 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_END_IMPL_05062005_1226) +#define FUSION_END_IMPL_05062005_1226 + +namespace boost { namespace fusion +{ + struct iterator_range_tag; + + namespace extension + { + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef typename Sequence::end_type type; + + static type + call(Sequence& s) + { + return s.last; + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/iterator_range/detail/value_at_impl.hpp b/win32/include/boost/fusion/view/iterator_range/detail/value_at_impl.hpp new file mode 100755 index 000000000..d2a342e12 --- /dev/null +++ b/win32/include/boost/fusion/view/iterator_range/detail/value_at_impl.hpp @@ -0,0 +1,38 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + 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_FUSION_ITERATOR_RANGE_VALUE_AT_IMPL_HPP_INCLUDED) +#define BOOST_FUSION_ITERATOR_RANGE_VALUE_AT_IMPL_HPP_INCLUDED + +#include +#include + +namespace boost { namespace fusion +{ + struct iterator_range_tag; + + namespace extension + { + template + struct value_at_impl; + + template <> + struct value_at_impl + { + template + struct apply + { + typedef typename Seq::begin_type begin_type; + typedef typename result_of::advance::type pos; + typedef typename result_of::value_of::type type; + }; + }; + } +}} + +#endif + diff --git a/win32/include/boost/fusion/view/iterator_range/iterator_range.hpp b/win32/include/boost/fusion/view/iterator_range/iterator_range.hpp new file mode 100755 index 000000000..e75e73f5e --- /dev/null +++ b/win32/include/boost/fusion/view/iterator_range/iterator_range.hpp @@ -0,0 +1,50 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_ITERATOR_RANGE_05062005_1224) +#define FUSION_ITERATOR_RANGE_05062005_1224 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct iterator_range_tag; + struct fusion_sequence_tag; + + template + struct iterator_range : sequence_base > + { + typedef typename convert_iterator::type begin_type; + typedef typename convert_iterator::type end_type; + typedef iterator_range_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef typename result_of::distance::type size; + typedef mpl::true_ is_view; + + typedef typename traits::category_of::type category; + + iterator_range(First const& first, Last const& last) + : first(convert_iterator::call(first)) + , last(convert_iterator::call(last)) {} + + begin_type first; + end_type last; + }; +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/joint_view.hpp b/win32/include/boost/fusion/view/joint_view.hpp new file mode 100755 index 000000000..8cfae3a75 --- /dev/null +++ b/win32/include/boost/fusion/view/joint_view.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_VIEW_JOINT_VIEW_10022005_0610) +#define FUSION_SEQUENCE_VIEW_JOINT_VIEW_10022005_0610 + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/view/joint_view/detail/begin_impl.hpp b/win32/include/boost/fusion/view/joint_view/detail/begin_impl.hpp new file mode 100755 index 000000000..9415f68c0 --- /dev/null +++ b/win32/include/boost/fusion/view/joint_view/detail/begin_impl.hpp @@ -0,0 +1,66 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BEGIN_IMPL_07162005_0115) +#define FUSION_BEGIN_IMPL_07162005_0115 + +#include +#include + +namespace boost { namespace fusion +{ + struct joint_view_tag; + + template + struct joint_view_iterator; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef typename Sequence::first_type first_type; + typedef typename Sequence::last_type last_type; + typedef typename Sequence::concat_type concat_type; + typedef result_of::equal_to equal_to; + + typedef typename + mpl::if_< + equal_to + , concat_type + , joint_view_iterator + >::type + type; + + static type + call(Sequence& s, mpl::true_) + { + return s.concat(); + } + + static type + call(Sequence& s, mpl::false_) + { + return type(s.first(), s.concat()); + } + + static type + call(Sequence& s) + { + return call(s, equal_to()); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/joint_view/detail/deref_impl.hpp b/win32/include/boost/fusion/view/joint_view/detail/deref_impl.hpp new file mode 100755 index 000000000..444704f61 --- /dev/null +++ b/win32/include/boost/fusion/view/joint_view/detail/deref_impl.hpp @@ -0,0 +1,29 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_DEREF_IMPL_07162005_0137) +#define FUSION_DEREF_IMPL_07162005_0137 + +#include + +namespace boost { namespace fusion +{ + struct joint_view_iterator_tag; + + namespace extension + { + template + struct deref_impl; + + template <> + struct deref_impl + : detail::adapt_deref_traits {}; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/joint_view/detail/end_impl.hpp b/win32/include/boost/fusion/view/joint_view/detail/end_impl.hpp new file mode 100755 index 000000000..fecaa7a14 --- /dev/null +++ b/win32/include/boost/fusion/view/joint_view/detail/end_impl.hpp @@ -0,0 +1,40 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_END_IMPL_07162005_0128) +#define FUSION_END_IMPL_07162005_0128 + +#include +#include + +namespace boost { namespace fusion +{ + struct joint_view_tag; + + namespace extension + { + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef typename Sequence::concat_last_type type; + + static type + call(Sequence& s) + { + return s.concat_last(); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/joint_view/detail/next_impl.hpp b/win32/include/boost/fusion/view/joint_view/detail/next_impl.hpp new file mode 100755 index 000000000..4db931974 --- /dev/null +++ b/win32/include/boost/fusion/view/joint_view/detail/next_impl.hpp @@ -0,0 +1,70 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_NEXT_IMPL_07162005_0136) +#define FUSION_NEXT_IMPL_07162005_0136 + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct joint_view_iterator_tag; + + template + struct joint_view_iterator; + + namespace extension + { + template + struct next_impl; + + template <> + struct next_impl + { + template + struct apply + { + typedef typename Iterator::first_type first_type; + typedef typename Iterator::last_type last_type; + typedef typename Iterator::concat_type concat_type; + typedef typename result_of::next::type next_type; + typedef result_of::equal_to equal_to; + + typedef typename + mpl::if_< + equal_to + , concat_type + , joint_view_iterator + >::type + type; + + static type + call(Iterator const& i, mpl::true_) + { + return i.concat; + } + + static type + call(Iterator const& i, mpl::false_) + { + return type(fusion::next(i.first), i.concat); + } + + static type + call(Iterator const& i) + { + return call(i, equal_to()); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/joint_view/detail/value_of_impl.hpp b/win32/include/boost/fusion/view/joint_view/detail/value_of_impl.hpp new file mode 100755 index 000000000..a84b0cf83 --- /dev/null +++ b/win32/include/boost/fusion/view/joint_view/detail/value_of_impl.hpp @@ -0,0 +1,29 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VALUE_IMPL_07162005_0132) +#define FUSION_VALUE_IMPL_07162005_0132 + +#include + +namespace boost { namespace fusion +{ + struct joint_view_iterator_tag; + + namespace extension + { + template + struct value_of_impl; + + template <> + struct value_of_impl + : detail::adapt_value_traits {}; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/joint_view/joint_view.hpp b/win32/include/boost/fusion/view/joint_view/joint_view.hpp new file mode 100755 index 000000000..ad08506c8 --- /dev/null +++ b/win32/include/boost/fusion/view/joint_view/joint_view.hpp @@ -0,0 +1,61 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_JOINT_VIEW_07162005_0140) +#define FUSION_JOINT_VIEW_07162005_0140 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct joint_view_tag; + struct forward_traversal_tag; + struct fusion_sequence_tag; + + template + struct joint_view : sequence_base > + { + typedef joint_view_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef forward_traversal_tag category; + typedef mpl::true_ is_view; + + typedef typename result_of::begin::type first_type; + typedef typename result_of::end::type last_type; + typedef typename result_of::begin::type concat_type; + typedef typename result_of::end::type concat_last_type; + typedef typename mpl::plus, result_of::size >::type size; + + joint_view(Sequence1& seq1, Sequence2& seq2) + : seq1(seq1) + , seq2(seq2) + {} + + first_type first() const { return fusion::begin(seq1); } + concat_type concat() const { return fusion::begin(seq2); } + concat_last_type concat_last() const { return fusion::end(seq2); } + + private: + + typename mpl::if_, Sequence1, Sequence1&>::type seq1; + typename mpl::if_, Sequence2, Sequence2&>::type seq2; + }; +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/joint_view/joint_view_iterator.hpp b/win32/include/boost/fusion/view/joint_view/joint_view_iterator.hpp new file mode 100755 index 000000000..e922073df --- /dev/null +++ b/win32/include/boost/fusion/view/joint_view/joint_view_iterator.hpp @@ -0,0 +1,52 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_JOINT_VIEW_ITERATOR_07162005_0140) +#define FUSION_JOINT_VIEW_ITERATOR_07162005_0140 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct joint_view_iterator_tag; + struct forward_traversal_tag; + + template + struct joint_view_iterator + : iterator_base > + { + typedef convert_iterator first_converter; + typedef convert_iterator last_converter; + typedef convert_iterator concat_converter; + + typedef typename first_converter::type first_type; + typedef typename last_converter::type last_type; + typedef typename concat_converter::type concat_type; + + typedef joint_view_iterator_tag fusion_tag; + typedef forward_traversal_tag category; + BOOST_STATIC_ASSERT((!result_of::equal_to::value)); + + joint_view_iterator(First const& first, Concat const& concat) + : first(first_converter::call(first)) + , concat(concat_converter::call(concat)) + {} + + first_type first; + concat_type concat; + }; +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/repetitive_view.hpp b/win32/include/boost/fusion/view/repetitive_view.hpp new file mode 100755 index 000000000..c5f220899 --- /dev/null +++ b/win32/include/boost/fusion/view/repetitive_view.hpp @@ -0,0 +1,15 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + 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_FUSION_REPETITIVE_VIEW_HPP_INCLUDED) +#define BOOST_FUSION_REPETITIVE_VIEW_HPP_INCLUDED + +#include +#include + +#endif + diff --git a/win32/include/boost/fusion/view/repetitive_view/detail/begin_impl.hpp b/win32/include/boost/fusion/view/repetitive_view/detail/begin_impl.hpp new file mode 100755 index 000000000..540fb5909 --- /dev/null +++ b/win32/include/boost/fusion/view/repetitive_view/detail/begin_impl.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + 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_FUSION_REPETITIVE_VIEW_BEGIN_IMPL_HPP_INCLUDED) +#define BOOST_FUSION_REPETITIVE_VIEW_BEGIN_IMPL_HPP_INCLUDED + +#include +#include + +namespace boost { namespace fusion +{ + struct repetitive_view_tag; + + template + struct repetitive_view_iterator; + + namespace extension + { + template + struct begin_impl; + + template<> + struct begin_impl + { + template + struct apply + { + typedef typename View::sequence_type sequence_type; + + typedef repetitive_view_iterator::type > type; + + static type call(View const& v) + { + return type(v.seq); + } + }; + }; + + } + +}} + +#endif + diff --git a/win32/include/boost/fusion/view/repetitive_view/detail/deref_impl.hpp b/win32/include/boost/fusion/view/repetitive_view/detail/deref_impl.hpp new file mode 100755 index 000000000..90c1cf29d --- /dev/null +++ b/win32/include/boost/fusion/view/repetitive_view/detail/deref_impl.hpp @@ -0,0 +1,44 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + 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_FUSION_REPETITIVE_VIEW_DEREF_IMPL_HPP_INCLUDED) +#define BOOST_FUSION_REPETITIVE_VIEW_DEREF_IMPL_HPP_INCLUDED + +#include + +namespace boost { namespace fusion +{ + struct repetitive_view_iterator_tag; + + namespace extension + { + template + struct deref_impl; + + template<> + struct deref_impl + { + template + struct apply + { + typedef typename + result_of::deref::type + type; + + static type call(Iterator const& i) + { + return *i.pos; + } + }; + }; + + } + +}} + +#endif + diff --git a/win32/include/boost/fusion/view/repetitive_view/detail/end_impl.hpp b/win32/include/boost/fusion/view/repetitive_view/detail/end_impl.hpp new file mode 100755 index 000000000..2766c6a9e --- /dev/null +++ b/win32/include/boost/fusion/view/repetitive_view/detail/end_impl.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + 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_FUSION_REPETITIVE_VIEW_END_IMPL_HPP_INCLUDED) +#define BOOST_FUSION_REPETITIVE_VIEW_END_IMPL_HPP_INCLUDED + +#include +#include + +namespace boost { namespace fusion +{ + struct repetitive_view_tag; + + template + struct repetitive_view_iterator; + + namespace extension + { + template + struct end_impl; + + template<> + struct end_impl + { + template + struct apply + { + typedef typename View::sequence_type sequence_type; + + typedef repetitive_view_iterator::type > type; + + static type call(View const& v) + { + return type(v.seq,end(v.seq)); + } + }; + }; + + } + +}} + +#endif + diff --git a/win32/include/boost/fusion/view/repetitive_view/detail/next_impl.hpp b/win32/include/boost/fusion/view/repetitive_view/detail/next_impl.hpp new file mode 100755 index 000000000..be9c1f2ee --- /dev/null +++ b/win32/include/boost/fusion/view/repetitive_view/detail/next_impl.hpp @@ -0,0 +1,90 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + 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_FUSION_REPETITIVE_VIEW_NEXT_IMPL_HPP_INCLUDED) +#define BOOST_FUSION_REPETITIVE_VIEW_NEXT_IMPL_HPP_INCLUDED + +#include +#include + +namespace boost { namespace fusion +{ + struct repetitive_view_iterator_tag; + + template + struct repetitive_view_iterator; + + namespace extension + { + template + struct next_impl; + + template <> + struct next_impl + { + template::type>::value > + struct apply_nonempty // + { + // advanvce to next position + + typedef repetitive_view_iterator< + typename Iterator::sequence_type, + typename result_of::next::type + > + type; + + static type call(Iterator const& i) + { + return type(i.seq, next(i.pos)); + } + }; + template + struct apply_nonempty + { + // reset to beginning + + typedef repetitive_view_iterator< + typename Iterator::sequence_type, + typename Iterator::first_type + > + type; + + static type call(Iterator const& i) + { + return type(i.seq); + } + }; + + template ::value > + struct apply // + : apply_nonempty + { }; + + template + struct apply + { + // eps^n = eps + + typedef Iterator type; + + static type call(Iterator const& i) + { + return type(i); + } + }; + }; + } +}} + +#endif + diff --git a/win32/include/boost/fusion/view/repetitive_view/detail/value_of_impl.hpp b/win32/include/boost/fusion/view/repetitive_view/detail/value_of_impl.hpp new file mode 100755 index 000000000..0fa76e1d6 --- /dev/null +++ b/win32/include/boost/fusion/view/repetitive_view/detail/value_of_impl.hpp @@ -0,0 +1,34 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + 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_FUSION_REPETITIVE_VIEW_VALUE_OF_IMPL_HPP_INCLUDED) +#define BOOST_FUSION_REPETITIVE_VIEW_VALUE_OF_IMPL_HPP_INCLUDED + +#include + +namespace boost { namespace fusion +{ + struct repetitive_view_iterator_tag; + + namespace extension + { + template + struct value_of_impl; + + template<> + struct value_of_impl + { + template + struct apply + : result_of::value_of + { }; + }; + } +}} + +#endif + diff --git a/win32/include/boost/fusion/view/repetitive_view/repetitive_view.hpp b/win32/include/boost/fusion/view/repetitive_view/repetitive_view.hpp new file mode 100755 index 000000000..990ca0297 --- /dev/null +++ b/win32/include/boost/fusion/view/repetitive_view/repetitive_view.hpp @@ -0,0 +1,48 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + 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_FUSION_REPETITIVE_REPETITIVE_VIEW_VIEW_HPP_INCLUDED) +#define BOOST_FUSION_REPETITIVE_VIEW_REPETITIVE_VIEW_HPP_INCLUDED + +#include +#include + +#include +#include + +#include +#include + + +namespace boost { namespace fusion +{ + struct repetitive_view_tag; + struct fusion_sequence_tag; + + template struct repetitive_view + : sequence_base< repetitive_view > + { + typedef repetitive_view_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef mpl::true_ is_view; + + typedef single_pass_traversal_tag category; + + typedef typename boost::remove_reference::type sequence_type; + typedef typename + mpl::if_, Sequence, sequence_type&>::type + stored_seq_type; + + repetitive_view(Sequence& seq) + : seq(seq) {} + + stored_seq_type seq; + }; + +}} + +#endif diff --git a/win32/include/boost/fusion/view/repetitive_view/repetitive_view_fwd.hpp b/win32/include/boost/fusion/view/repetitive_view/repetitive_view_fwd.hpp new file mode 100755 index 000000000..08d0e2768 --- /dev/null +++ b/win32/include/boost/fusion/view/repetitive_view/repetitive_view_fwd.hpp @@ -0,0 +1,19 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + 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_FUSION_REPETITIVE_VIEW_FWD_HPP_INCLUDED) +#define BOOST_FUSION_REPETITIVE_VIEW_FWD_HPP_INCLUDED + +namespace boost { namespace fusion +{ + struct repetitive_view_tag; + + template struct repetitive_view; +}} + +#endif + diff --git a/win32/include/boost/fusion/view/repetitive_view/repetitive_view_iterator.hpp b/win32/include/boost/fusion/view/repetitive_view/repetitive_view_iterator.hpp new file mode 100755 index 000000000..b9e162552 --- /dev/null +++ b/win32/include/boost/fusion/view/repetitive_view/repetitive_view_iterator.hpp @@ -0,0 +1,51 @@ +/*============================================================================= + Copyright (c) 2007 Tobias Schwinger + + 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_FUSION_REPETITIVE_VIEW_ITERATOR_HPP_INCLUDED) +#define BOOST_FUSION_REPETITIVE_VIEW_HPP_ITERATOR_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct repetitive_view_iterator_tag; + + template::type> + struct repetitive_view_iterator + : iterator_base< repetitive_view_iterator > + { + typedef repetitive_view_iterator_tag fusion_tag; + + typedef Sequence sequence_type; + typedef typename convert_iterator::type pos_type; + typedef typename convert_iterator::type>::type first_type; + typedef typename convert_iterator::type>::type end_type; + typedef single_pass_traversal_tag category; + + explicit repetitive_view_iterator(Sequence& seq) + : seq(seq), pos(begin(seq)) {} + + repetitive_view_iterator(Sequence& seq, pos_type const& pos) + : seq(seq), pos(pos) {} + + Sequence& seq; + pos_type pos; + + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/view/reverse_view.hpp b/win32/include/boost/fusion/view/reverse_view.hpp new file mode 100755 index 000000000..d10dad327 --- /dev/null +++ b/win32/include/boost/fusion/view/reverse_view.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_VIEW_REVERSE_VIEW_10022005_0612) +#define FUSION_SEQUENCE_VIEW_REVERSE_VIEW_10022005_0612 + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/view/reverse_view/detail/advance_impl.hpp b/win32/include/boost/fusion/view/reverse_view/detail/advance_impl.hpp new file mode 100755 index 000000000..ebb2c84cf --- /dev/null +++ b/win32/include/boost/fusion/view/reverse_view/detail/advance_impl.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_ADVANCE_IMPL_14122005_2015) +#define FUSION_ADVANCE_IMPL_14122005_2015 + +#include +#include + +namespace boost { namespace fusion { + + struct reverse_view_iterator_tag; + + template + struct reverse_view_iterator; + + namespace extension + { + template + struct advance_impl; + + template<> + struct advance_impl + { + template + struct apply + { + typedef typename Iterator::first_type first_type; + typedef typename mpl::negate::type negative_dist; + typedef typename result_of::advance::type advanced_type; + typedef reverse_view_iterator type; + + static type + call(Iterator const& i) + { + return type(boost::fusion::advance(i.first)); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/reverse_view/detail/begin_impl.hpp b/win32/include/boost/fusion/view/reverse_view/detail/begin_impl.hpp new file mode 100755 index 000000000..32e4b344c --- /dev/null +++ b/win32/include/boost/fusion/view/reverse_view/detail/begin_impl.hpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BEGIN_IMPL_07202005_0849) +#define FUSION_BEGIN_IMPL_07202005_0849 + +namespace boost { namespace fusion +{ + struct reverse_view_tag; + + template + struct reverse_view_iterator; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef reverse_view_iterator type; + + static type + call(Sequence const& s) + { + return type(s.last()); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/reverse_view/detail/deref_impl.hpp b/win32/include/boost/fusion/view/reverse_view/detail/deref_impl.hpp new file mode 100755 index 000000000..260077ea5 --- /dev/null +++ b/win32/include/boost/fusion/view/reverse_view/detail/deref_impl.hpp @@ -0,0 +1,48 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_DEREF_IMPL_07202005_0851) +#define FUSION_DEREF_IMPL_07202005_0851 + +#include +#include + +namespace boost { namespace fusion +{ + struct reverse_view_iterator_tag; + + namespace extension + { + template + struct deref_impl; + + template <> + struct deref_impl + { + template + struct apply + { + typedef typename + result_of::deref< + typename result_of::prior< + typename Iterator::first_type + >::type + >::type + type; + + static type + call(Iterator const& i) + { + return *fusion::prior(i.first); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/reverse_view/detail/distance_impl.hpp b/win32/include/boost/fusion/view/reverse_view/detail/distance_impl.hpp new file mode 100755 index 000000000..32c6f2157 --- /dev/null +++ b/win32/include/boost/fusion/view/reverse_view/detail/distance_impl.hpp @@ -0,0 +1,45 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_DISTANCE_IMPL_14122005_2104) +#define FUSION_DISTANCE_IMPL_14122005_2104 + +#include + +namespace boost { namespace fusion { + + struct reverse_view_iterator_tag; + + template + struct reverse_view_iterator; + + namespace extension + { + template + struct distance_impl; + + template<> + struct distance_impl + { + template + struct apply + { + typedef typename First::first_type first_type; + typedef typename Last::first_type last_type; + typedef typename result_of::distance::type type; + + static type + call(First const& first, Last const& last) + { + return boost::fusion::distance(last.first, first.first); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/reverse_view/detail/end_impl.hpp b/win32/include/boost/fusion/view/reverse_view/detail/end_impl.hpp new file mode 100755 index 000000000..eda092eb6 --- /dev/null +++ b/win32/include/boost/fusion/view/reverse_view/detail/end_impl.hpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_END_IMPL_07202005_0851) +#define FUSION_END_IMPL_07202005_0851 + +namespace boost { namespace fusion +{ + struct reverse_view_tag; + + template + struct reverse_view_iterator; + + namespace extension + { + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef reverse_view_iterator type; + + static type + call(Sequence const& s) + { + return type(s.first()); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/reverse_view/detail/next_impl.hpp b/win32/include/boost/fusion/view/reverse_view/detail/next_impl.hpp new file mode 100755 index 000000000..d519af29e --- /dev/null +++ b/win32/include/boost/fusion/view/reverse_view/detail/next_impl.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_NEXT_IMPL_07202005_0856) +#define FUSION_NEXT_IMPL_07202005_0856 + +#include +#include + +namespace boost { namespace fusion +{ + struct reverse_view_iterator_tag; + + template + struct reverse_view_iterator; + + namespace extension + { + template <> + struct next_impl + { + template + struct apply + { + typedef typename Iterator::first_type first_type; + typedef typename prior_impl:: + template apply + wrapped; + + typedef reverse_view_iterator type; + + static type + call(Iterator const& i) + { + return type(wrapped::call(i.first)); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/reverse_view/detail/prior_impl.hpp b/win32/include/boost/fusion/view/reverse_view/detail/prior_impl.hpp new file mode 100755 index 000000000..49a0b93ee --- /dev/null +++ b/win32/include/boost/fusion/view/reverse_view/detail/prior_impl.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_PRIOR_IMPL_07202005_0857) +#define FUSION_PRIOR_IMPL_07202005_0857 + +#include +#include + +namespace boost { namespace fusion +{ + struct reverse_view_iterator_tag; + + template + struct reverse_view_iterator; + + namespace extension + { + template <> + struct prior_impl + { + template + struct apply + { + typedef typename Iterator::first_type first_type; + typedef typename next_impl:: + template apply + wrapped; + + typedef reverse_view_iterator type; + + static type + call(Iterator const& i) + { + return type(wrapped::call(i.first)); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/reverse_view/detail/value_of_impl.hpp b/win32/include/boost/fusion/view/reverse_view/detail/value_of_impl.hpp new file mode 100755 index 000000000..bb6e4b06a --- /dev/null +++ b/win32/include/boost/fusion/view/reverse_view/detail/value_of_impl.hpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VALUE_OF_IMPL_07202005_0900) +#define FUSION_VALUE_OF_IMPL_07202005_0900 + +#include +#include + +namespace boost { namespace fusion +{ + struct reverse_view_iterator_tag; + + namespace extension + { + template + struct value_of_impl; + + template <> + struct value_of_impl + { + template + struct apply + { + typedef typename + result_of::value_of< + typename result_of::prior< + typename Iterator::first_type + >::type + >::type + type; + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/reverse_view/reverse_view.hpp b/win32/include/boost/fusion/view/reverse_view/reverse_view.hpp new file mode 100755 index 000000000..c0fd481b1 --- /dev/null +++ b/win32/include/boost/fusion/view/reverse_view/reverse_view.hpp @@ -0,0 +1,58 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_REVERSE_VIEW_07202005_0836) +#define FUSION_REVERSE_VIEW_07202005_0836 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct reverse_view_tag; + struct fusion_sequence_tag; + + template + struct reverse_view : sequence_base > + { + typedef reverse_view_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef mpl::true_ is_view; + + typedef typename traits::category_of::type category; + typedef typename result_of::begin::type first_type; + typedef typename result_of::end::type last_type; + typedef typename result_of::size::type size; + + BOOST_STATIC_ASSERT(( + is_base_of< + bidirectional_traversal_tag + , typename traits::category_of::type>::value)); + + reverse_view(Sequence& seq) + : seq(seq) + {} + + first_type first() const { return fusion::begin(seq); } + last_type last() const { return fusion::end(seq); } + typename mpl::if_, Sequence, Sequence&>::type seq; + }; +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/reverse_view/reverse_view_iterator.hpp b/win32/include/boost/fusion/view/reverse_view/reverse_view_iterator.hpp new file mode 100755 index 000000000..dcab3bed6 --- /dev/null +++ b/win32/include/boost/fusion/view/reverse_view/reverse_view_iterator.hpp @@ -0,0 +1,49 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_REVERSE_VIEW_ITERATOR_07202005_0835) +#define FUSION_REVERSE_VIEW_ITERATOR_07202005_0835 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct reverse_view_iterator_tag; + + template + struct reverse_view_iterator + : iterator_base > + { + typedef convert_iterator converter; + typedef typename converter::type first_type; + typedef reverse_view_iterator_tag fusion_tag; + typedef typename traits::category_of::type category; + + BOOST_STATIC_ASSERT(( + is_base_of< + bidirectional_traversal_tag + , category>::value)); + + reverse_view_iterator(First const& first) + : first(converter::call(first)) {} + + first_type first; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/view/single_view.hpp b/win32/include/boost/fusion/view/single_view.hpp new file mode 100755 index 000000000..700344264 --- /dev/null +++ b/win32/include/boost/fusion/view/single_view.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SINGLE_VIEW_03192006_2216) +#define FUSION_SINGLE_VIEW_03192006_2216 + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/view/single_view/detail/begin_impl.hpp b/win32/include/boost/fusion/view/single_view/detail/begin_impl.hpp new file mode 100755 index 000000000..933802ba2 --- /dev/null +++ b/win32/include/boost/fusion/view/single_view/detail/begin_impl.hpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BEGIN_IMPL_05052005_0305) +#define FUSION_BEGIN_IMPL_05052005_0305 + +namespace boost { namespace fusion +{ + struct single_view_tag; + + template + struct single_view_iterator; + + namespace extension + { + template + struct begin_impl; + + template <> + struct begin_impl + { + template + struct apply + { + typedef single_view_iterator type; + + static type + call(Sequence& s) + { + return type(s); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/single_view/detail/deref_impl.hpp b/win32/include/boost/fusion/view/single_view/detail/deref_impl.hpp new file mode 100755 index 000000000..900fa6fc9 --- /dev/null +++ b/win32/include/boost/fusion/view/single_view/detail/deref_impl.hpp @@ -0,0 +1,43 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_DEREF_IMPL_05052005_0258) +#define FUSION_DEREF_IMPL_05052005_0258 + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct single_view_iterator_tag; + + namespace extension + { + template + struct deref_impl; + + template <> + struct deref_impl + { + template + struct apply + { + typedef typename Iterator::value_type type; + + static type + call(Iterator const& i) + { + return i.val; + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/single_view/detail/end_impl.hpp b/win32/include/boost/fusion/view/single_view/detail/end_impl.hpp new file mode 100755 index 000000000..7b84f2947 --- /dev/null +++ b/win32/include/boost/fusion/view/single_view/detail/end_impl.hpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_END_IMPL_05052005_0332) +#define FUSION_END_IMPL_05052005_0332 + +namespace boost { namespace fusion +{ + struct single_view_tag; + + template + struct single_view_iterator_end; + + namespace extension + { + template + struct end_impl; + + template <> + struct end_impl + { + template + struct apply + { + typedef single_view_iterator_end type; + + static type + call(Sequence&) + { + return type(); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/single_view/detail/next_impl.hpp b/win32/include/boost/fusion/view/single_view/detail/next_impl.hpp new file mode 100755 index 000000000..650fb6b3e --- /dev/null +++ b/win32/include/boost/fusion/view/single_view/detail/next_impl.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_NEXT_IMPL_05052005_0331) +#define FUSION_NEXT_IMPL_05052005_0331 + +namespace boost { namespace fusion +{ + struct single_view_iterator_tag; + + template + struct single_view_iterator_end; + + template + struct single_view_iterator; + + namespace extension + { + template + struct next_impl; + + template <> + struct next_impl + { + template + struct apply + { + typedef single_view_iterator_end< + typename Iterator::single_view_type> + type; + + static type + call(Iterator) + { + return type(); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/single_view/detail/value_of_impl.hpp b/win32/include/boost/fusion/view/single_view/detail/value_of_impl.hpp new file mode 100755 index 000000000..8c313e3ba --- /dev/null +++ b/win32/include/boost/fusion/view/single_view/detail/value_of_impl.hpp @@ -0,0 +1,34 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VALUE_IMPL_05052005_0324) +#define FUSION_VALUE_IMPL_05052005_0324 + +namespace boost { namespace fusion +{ + struct single_view_iterator_tag; + + namespace extension + { + template + struct value_of_impl; + + template <> + struct value_of_impl + { + template + struct apply + { + typedef typename Iterator::single_view_type single_view_type; + typedef typename single_view_type::value_type type; + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/single_view/single_view.hpp b/win32/include/boost/fusion/view/single_view/single_view.hpp new file mode 100755 index 000000000..2ddd3488c --- /dev/null +++ b/win32/include/boost/fusion/view/single_view/single_view.hpp @@ -0,0 +1,54 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SINGLE_VIEW_05052005_0335) +#define FUSION_SINGLE_VIEW_05052005_0335 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct single_view_tag; + struct forward_traversal_tag; + struct fusion_sequence_tag; + + template + struct single_view : sequence_base > + { + typedef single_view_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef forward_traversal_tag category; + typedef mpl::true_ is_view; + typedef mpl::int_<1> size; + typedef T value_type; + + single_view() + : val() {} + + explicit single_view(typename detail::call_param::type val) + : val(val) {} + + value_type val; + }; + + template + inline single_view::type> + make_single_view(T const& v) + { + return single_view::type>(v); + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/single_view/single_view_iterator.hpp b/win32/include/boost/fusion/view/single_view/single_view_iterator.hpp new file mode 100755 index 000000000..b5cb3304c --- /dev/null +++ b/win32/include/boost/fusion/view/single_view/single_view_iterator.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SINGLE_VIEW_ITERATOR_05052005_0340) +#define FUSION_SINGLE_VIEW_ITERATOR_05052005_0340 + +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct single_view_iterator_tag; + struct forward_traversal_tag; + + template + struct single_view_iterator_end + : iterator_base > + { + typedef single_view_iterator_tag fusion_tag; + typedef forward_traversal_tag category; + }; + + template + struct single_view_iterator + : iterator_base > + { + typedef single_view_iterator_tag fusion_tag; + typedef forward_traversal_tag category; + typedef typename SingleView::value_type value_type; + typedef SingleView single_view_type; + + explicit single_view_iterator(single_view_type const& view) + : val(view.val) {} + + value_type val; + }; +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/transform_view.hpp b/win32/include/boost/fusion/view/transform_view.hpp new file mode 100755 index 000000000..aa0cf59ed --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view.hpp @@ -0,0 +1,13 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_SEQUENCE_VIEW_TRANSFORM_VIEW_10022005_0612) +#define FUSION_SEQUENCE_VIEW_TRANSFORM_VIEW_10022005_0612 + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/view/transform_view/detail/advance_impl.hpp b/win32/include/boost/fusion/view/transform_view/detail/advance_impl.hpp new file mode 100755 index 000000000..41f329424 --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/detail/advance_impl.hpp @@ -0,0 +1,75 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_ADVANCE_IMPL_13122005_1906) +#define FUSION_ADVANCE_IMPL_13122005_1906 + +#include + +namespace boost { namespace fusion +{ + struct transform_view_iterator_tag; + struct transform_view_iterator2_tag; + + template + struct transform_view_iterator; + + template + struct transform_view_iterator2; + + namespace extension + { + template + struct advance_impl; + + // Unary Version + template<> + struct advance_impl + { + template + struct apply + { + typedef typename Iterator::first_type first_type; + typedef typename result_of::advance::type advanced_type; + typedef typename Iterator::transform_type transform_type; + typedef transform_view_iterator type; + + static type + call(Iterator const& i) + { + return type(boost::fusion::advance(i.first), i.f); + } + }; + }; + + // Binary Version + template<> + struct advance_impl + { + template + struct apply + { + typedef typename Iterator::first1_type first1_type; + typedef typename Iterator::first2_type first2_type; + typedef typename result_of::advance::type advanced1_type; + typedef typename result_of::advance::type advanced2_type; + typedef typename Iterator::transform_type transform_type; + typedef transform_view_iterator2 type; + + static type + call(Iterator const& i) + { + return type( + boost::fusion::advance(i.first1) + , boost::fusion::advance(i.first2), i.f); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/transform_view/detail/apply_transform_result.hpp b/win32/include/boost/fusion/view/transform_view/detail/apply_transform_result.hpp new file mode 100755 index 000000000..2913a4303 --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/detail/apply_transform_result.hpp @@ -0,0 +1,37 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2007 Dan Marsden + + 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_FUSION_APPLY_TRANSFORM_RESULT_02092006_1936) +#define BOOST_FUSION_APPLY_TRANSFORM_RESULT_02092006_1936 + +#include + +namespace boost { namespace fusion +{ + struct void_; + + namespace detail + { + template + struct apply_transform_result + { + template + struct apply + : boost::result_of + {}; + + template + struct apply + : boost::result_of + {}; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/transform_view/detail/at_impl.hpp b/win32/include/boost/fusion/view/transform_view/detail/at_impl.hpp new file mode 100755 index 000000000..27e299c0d --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/detail/at_impl.hpp @@ -0,0 +1,63 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_AT_IMPL_20061029_1946) +#define BOOST_FUSION_AT_IMPL_20061029_1946 + +#include +#include +#include + +namespace boost { namespace fusion { + struct transform_view_tag; + struct transform_view2_tag; + + namespace extension + { + template + struct at_impl; + + template<> + struct at_impl + { + template + struct apply + { + typedef typename Seq::transform_type F; + typedef detail::apply_transform_result transform_type; + typedef typename boost::fusion::result_of::at::type value_type; + typedef typename mpl::apply::type type; + + static type call(Seq& seq) + { + return seq.f(boost::fusion::at(seq.seq)); + } + }; + }; + + template<> + struct at_impl + { + template + struct apply + { + typedef typename Seq::transform_type F; + typedef detail::apply_transform_result transform_type; + typedef typename boost::fusion::result_of::at::type value1_type; + typedef typename boost::fusion::result_of::at::type value2_type; + typedef typename mpl::apply::type type; + + static type call(Seq& seq) + { + return seq.f(boost::fusion::at(seq.seq1), boost::fusion::at(seq.seq2)); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/transform_view/detail/begin_impl.hpp b/win32/include/boost/fusion/view/transform_view/detail/begin_impl.hpp new file mode 100755 index 000000000..bcf3311ba --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/detail/begin_impl.hpp @@ -0,0 +1,68 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_BEGIN_IMPL_07162005_1031) +#define FUSION_BEGIN_IMPL_07162005_1031 + +#include + +namespace boost { namespace fusion +{ + template + struct transform_view_iterator; + + template + struct transform_view_iterator2; + + namespace extension + { + template + struct begin_impl; + + // Unary Version + template <> + struct begin_impl + { + template + struct apply + { + typedef typename Sequence::first_type first_type; + typedef typename Sequence::transform_type transform_type; + typedef transform_view_iterator type; + + static type + call(Sequence& s) + { + return type(s.first(), s.f); + } + }; + }; + + // Binary Version + template <> + struct begin_impl + { + template + struct apply + { + typedef typename Sequence::first1_type first1_type; + typedef typename Sequence::first2_type first2_type; + typedef typename Sequence::transform_type transform_type; + typedef transform_view_iterator2 type; + + static type + call(Sequence& s) + { + return type(s.first1(), s.first2(), s.f); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/transform_view/detail/deref_impl.hpp b/win32/include/boost/fusion/view/transform_view/detail/deref_impl.hpp new file mode 100755 index 000000000..342fbaf77 --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/detail/deref_impl.hpp @@ -0,0 +1,76 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_DEREF_IMPL_07162005_1026) +#define FUSION_DEREF_IMPL_07162005_1026 + +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct transform_view_iterator_tag; + struct transform_view_iterator2_tag; + + namespace extension + { + template + struct deref_impl; + + // Unary Version + template <> + struct deref_impl + { + template + struct apply + { + typedef typename + result_of::deref::type + value_type; + + typedef detail::apply_transform_result transform_type; + typedef typename mpl::apply::type type; + + static type + call(Iterator const& i) + { + return i.f(*i.first); + } + }; + }; + + // Binary Version + template <> + struct deref_impl + { + template + struct apply + { + typedef typename + result_of::deref::type + value1_type; + typedef typename + result_of::deref::type + value2_type; + + typedef detail::apply_transform_result transform_type; + typedef typename mpl::apply::type type; + + static type + call(Iterator const& i) + { + return i.f(*i.first1, *i.first2); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/transform_view/detail/distance_impl.hpp b/win32/include/boost/fusion/view/transform_view/detail/distance_impl.hpp new file mode 100755 index 000000000..158e25b50 --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/detail/distance_impl.hpp @@ -0,0 +1,59 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_DISTANCE_IMPL_13122005_2139) +#define FUSION_DISTANCE_IMPL_13122005_2139 + +#include + +namespace boost { namespace fusion { + + struct transform_view_iterator_tag; + struct transform_view_iterator2_tag; + + namespace extension + { + template + struct distance_impl; + + // Unary Version + template<> + struct distance_impl + { + template + struct apply + : result_of::distance + { + static + typename result_of::distance::type + call(First const& first, Last const& last) + { + return boost::fusion::distance(first.first, last.first); + } + }; + }; + + // Binary Version + template<> + struct distance_impl + { + template + struct apply + : result_of::distance + { + static + typename result_of::distance::type + call(First const& first, Last const& last) + { + return boost::fusion::distance(first.first1, last.first1); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/transform_view/detail/end_impl.hpp b/win32/include/boost/fusion/view/transform_view/detail/end_impl.hpp new file mode 100755 index 000000000..7d600de0f --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/detail/end_impl.hpp @@ -0,0 +1,68 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_END_IMPL_07162005_1028) +#define FUSION_END_IMPL_07162005_1028 + +#include + +namespace boost { namespace fusion +{ + template + struct transform_view_iterator; + + template + struct transform_view_iterator2; + + namespace extension + { + template + struct end_impl; + + // Unary Version + template <> + struct end_impl + { + template + struct apply + { + typedef typename Sequence::last_type last_type; + typedef typename Sequence::transform_type transform_type; + typedef transform_view_iterator type; + + static type + call(Sequence& s) + { + return type(s.last(), s.f); + } + }; + }; + + // Binary Version + template <> + struct end_impl + { + template + struct apply + { + typedef typename Sequence::last1_type last1_type; + typedef typename Sequence::last2_type last2_type; + typedef typename Sequence::transform_type transform_type; + typedef transform_view_iterator2 type; + + static type + call(Sequence& s) + { + return type(s.last1(), s.last2(), s.f); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/transform_view/detail/equal_to_impl.hpp b/win32/include/boost/fusion/view/transform_view/detail/equal_to_impl.hpp new file mode 100755 index 000000000..3d1e8e6b7 --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/detail/equal_to_impl.hpp @@ -0,0 +1,42 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(BOOST_FUSION_TRANSFORM_VIEW_ITERATOR_20070127_0957) +#define BOOST_FUSION_TRANSFORM_VIEW_ITERATOR_20070127_0957 + +#include + +namespace boost { namespace fusion { + + struct transform_view_iterator_tag; + struct transform_view_iterator2_tag; + + namespace extension + { + template + struct equal_to_impl; + + template<> + struct equal_to_impl + { + template + struct apply + : result_of::equal_to + {}; + }; + + template<> + struct equal_to_impl + { + template + struct apply + : result_of::equal_to + {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/transform_view/detail/next_impl.hpp b/win32/include/boost/fusion/view/transform_view/detail/next_impl.hpp new file mode 100755 index 000000000..0cdbb99aa --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/detail/next_impl.hpp @@ -0,0 +1,74 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_NEXT_IMPL_07162005_1029) +#define FUSION_NEXT_IMPL_07162005_1029 + +#include + +namespace boost { namespace fusion +{ + struct transform_view_iterator_tag; + struct transform_view_iterator2_tag; + + template + struct transform_view_iterator; + + template + struct transform_view_iterator2; + + namespace extension + { + template + struct next_impl; + + // Unary Version + template <> + struct next_impl + { + template + struct apply + { + typedef typename Iterator::first_type first_type; + typedef typename result_of::next::type next_type; + typedef typename Iterator::transform_type transform_type; + typedef transform_view_iterator type; + + static type + call(Iterator const& i) + { + return type(fusion::next(i.first), i.f); + } + }; + }; + + // Binary Version + template <> + struct next_impl + { + template + struct apply + { + typedef typename Iterator::first1_type first1_type; + typedef typename Iterator::first2_type first2_type; + typedef typename result_of::next::type next1_type; + typedef typename result_of::next::type next2_type; + typedef typename Iterator::transform_type transform_type; + typedef transform_view_iterator2 type; + + static type + call(Iterator const& i) + { + return type(fusion::next(i.first1), fusion::next(i.first2), i.f); + } + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/transform_view/detail/prior_impl.hpp b/win32/include/boost/fusion/view/transform_view/detail/prior_impl.hpp new file mode 100755 index 000000000..57da20bbf --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/detail/prior_impl.hpp @@ -0,0 +1,73 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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(FUSION_PREV_IMPL_13122005_2110) +#define FUSION_PREV_IMPL_13122005_2110 + +#include + +namespace boost { namespace fusion +{ + struct transform_view_iterator_tag; + struct transform_view_iterator2_tag; + + template + struct transform_view_iterator; + + template + struct transform_view_iterator2; + + namespace extension + { + template + struct prior_impl; + + // Unary Version + template<> + struct prior_impl + { + template + struct apply + { + typedef typename Iterator::first_type first_type; + typedef typename result_of::prior::type prior_type; + typedef typename Iterator::transform_type transform_type; + typedef transform_view_iterator type; + + static type + call(Iterator const& i) + { + return type(fusion::prior(i.first), i.f); + } + }; + }; + + // Binary Version + template<> + struct prior_impl + { + template + struct apply + { + typedef typename Iterator::first1_type first1_type; + typedef typename Iterator::first2_type first2_type; + typedef typename result_of::prior::type prior1_type; + typedef typename result_of::prior::type prior2_type; + typedef typename Iterator::transform_type transform_type; + typedef transform_view_iterator2 type; + + static type + call(Iterator const& i) + { + return type(fusion::prior(i.first1), fusion::prior(i.first2), i.f); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/transform_view/detail/value_at_impl.hpp b/win32/include/boost/fusion/view/transform_view/detail/value_at_impl.hpp new file mode 100755 index 000000000..055ad43c9 --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/detail/value_at_impl.hpp @@ -0,0 +1,53 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2005-2006 Dan Marsden + + 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_FUSION_VALUE_AT_IMPL_20061101_0745) +#define BOOST_FUSION_VALUE_AT_IMPL_20061101_0745 + +#include +#include +#include + +namespace boost { namespace fusion { + struct transform_view_tag; + struct transform_view2_tag; + + namespace extension + { + template + struct value_at_impl; + + template<> + struct value_at_impl + { + template + struct apply + { + typedef typename Seq::transform_type F; + typedef detail::apply_transform_result transform_type; + typedef typename boost::fusion::result_of::value_at::type value_type; + typedef typename mpl::apply::type type; + }; + }; + + template<> + struct value_at_impl + { + template + struct apply + { + typedef typename Seq::transform_type F; + typedef detail::apply_transform_result transform_type; + typedef typename boost::fusion::result_of::value_at::type value1_type; + typedef typename boost::fusion::result_of::value_at::type value2_type; + typedef typename mpl::apply::type type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/transform_view/detail/value_of_impl.hpp b/win32/include/boost/fusion/view/transform_view/detail/value_of_impl.hpp new file mode 100755 index 000000000..44ccfbb03 --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/detail/value_of_impl.hpp @@ -0,0 +1,63 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_VALUE_OF_IMPL_07162005_1030) +#define FUSION_VALUE_OF_IMPL_07162005_1030 + +#include +#include +#include + +namespace boost { namespace fusion +{ + struct transform_view_iterator_tag; + struct transform_view_iterator2_tag; + + namespace extension + { + template + struct value_of_impl; + + // Unary Version + template <> + struct value_of_impl + { + template + struct apply + { + typedef typename + result_of::value_of::type + value_type; + + typedef detail::apply_transform_result transform_type; + typedef typename mpl::apply::type type; + }; + }; + + // Binary Version + template <> + struct value_of_impl + { + template + struct apply + { + typedef typename + result_of::value_of::type + value1_type; + typedef typename + result_of::value_of::type + value2_type; + + typedef detail::apply_transform_result transform_type; + typedef typename mpl::apply::type type; + }; + }; + } +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/transform_view/transform_view.hpp b/win32/include/boost/fusion/view/transform_view/transform_view.hpp new file mode 100755 index 000000000..60c7a44ed --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/transform_view.hpp @@ -0,0 +1,107 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_TRANSFORM_VIEW_07162005_1037) +#define FUSION_TRANSFORM_VIEW_07162005_1037 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct void_; + struct transform_view_tag; + struct transform_view2_tag; + struct fusion_sequence_tag; + + // Binary Version + template + struct transform_view : sequence_base > + { + BOOST_STATIC_ASSERT(result_of::size::value == result_of::size::value); + typedef transform_view2_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef mpl::true_ is_view; + + typedef typename traits::category_of::type category1; + typedef typename traits::category_of::type category2; + typedef typename detail::strictest_traversal< + fusion::vector2 >::type category; + typedef typename result_of::begin::type first1_type; + typedef typename result_of::begin::type first2_type; + typedef typename result_of::end::type last1_type; + typedef typename result_of::end::type last2_type; + typedef typename result_of::size::type size; + typedef Sequence1 sequence1_type; + typedef Sequence2 sequence2_type; + typedef F transform_type; + + transform_view(Sequence1& seq1, Sequence2& seq2, F const& binop) + : f(binop) + , seq1(seq1) + , seq2(seq2) + {} + + first1_type first1() const { return fusion::begin(seq1); } + first2_type first2() const { return fusion::begin(seq2); } + last1_type last1() const { return fusion::end(seq1); } + last2_type last2() const { return fusion::end(seq2); } + + transform_type f; + typename mpl::if_, Sequence1, Sequence1&>::type seq1; + typename mpl::if_, Sequence2, Sequence2&>::type seq2; + }; + + // Unary Version + template +#if defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS) + struct transform_view : sequence_base > +#else + struct transform_view : sequence_base > +#endif + { + typedef transform_view_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef mpl::true_ is_view; + + typedef typename traits::category_of::type category; + typedef typename result_of::begin::type first_type; + typedef typename result_of::end::type last_type; + typedef typename result_of::size::type size; + typedef Sequence sequence_type; + typedef F transform_type; + + transform_view(Sequence& seq, F const& f) + : seq(seq) + , f(f) + {} + + first_type first() const { return fusion::begin(seq); } + last_type last() const { return fusion::end(seq); } + typename mpl::if_, Sequence, Sequence&>::type seq; + transform_type f; + }; +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/transform_view/transform_view_fwd.hpp b/win32/include/boost/fusion/view/transform_view/transform_view_fwd.hpp new file mode 100755 index 000000000..2062f5ce5 --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/transform_view_fwd.hpp @@ -0,0 +1,22 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_TRANSFORM_VIEW_FORWARD_01052006_1839) +#define FUSION_TRANSFORM_VIEW_FORWARD_01052006_1839 + +namespace boost { namespace fusion +{ + struct void_; + struct transform_view_tag; + struct transform_view2_tag; + + template + struct transform_view; +}} + +#endif + + diff --git a/win32/include/boost/fusion/view/transform_view/transform_view_iterator.hpp b/win32/include/boost/fusion/view/transform_view/transform_view_iterator.hpp new file mode 100755 index 000000000..c0bebc911 --- /dev/null +++ b/win32/include/boost/fusion/view/transform_view/transform_view_iterator.hpp @@ -0,0 +1,69 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +==============================================================================*/ +#if !defined(FUSION_TRANSFORM_VIEW_ITERATOR_07162005_1033) +#define FUSION_TRANSFORM_VIEW_ITERATOR_07162005_1033 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + // Unary Version + struct transform_view_iterator_tag; + + template + struct transform_view_iterator + : iterator_base > + { + typedef transform_view_iterator_tag fusion_tag; + typedef convert_iterator converter; + typedef typename converter::type first_type; + typedef typename traits::category_of::type category; + typedef F transform_type; + + transform_view_iterator(First const& first, F const& f) + : first(converter::call(first)), f(f) {} + + first_type first; + transform_type f; + }; + + // Binary Version + struct transform_view_iterator2_tag; + + template + struct transform_view_iterator2 + : iterator_base > + { + typedef transform_view_iterator2_tag fusion_tag; + typedef convert_iterator converter1; + typedef convert_iterator converter2; + typedef typename converter1::type first1_type; + typedef typename converter2::type first2_type; + typedef typename traits::category_of::type category; + typedef F transform_type; + + transform_view_iterator2(First1 const& first1, First2 const& first2, F const& f) + : first1(converter1::call(first1)), first2(converter2::call(first2)), f(f) {} + + first1_type first1; + first2_type first2; + transform_type f; + }; +}} + +#endif + diff --git a/win32/include/boost/fusion/view/zip_view.hpp b/win32/include/boost/fusion/view/zip_view.hpp new file mode 100755 index 000000000..669f952a3 --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view.hpp @@ -0,0 +1,14 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_ZIP_VIEW_23012006_0811) +#define FUSION_ZIP_VIEW_23012006_0811 + +#include +#include + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/detail/advance_impl.hpp b/win32/include/boost/fusion/view/zip_view/detail/advance_impl.hpp new file mode 100755 index 000000000..f59bc0c64 --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/detail/advance_impl.hpp @@ -0,0 +1,69 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_ADVANCE_IMPL_20061024_2021) +#define FUSION_ADVANCE_IMPL_20061024_2021 + +#include +#include +#include +#include + +namespace boost { namespace fusion { + + struct zip_view_iterator_tag; + + namespace detail + { + template + struct poly_advance + { + template + struct result; + + template + struct result(It)> + { + typedef typename remove_reference::type it; + typedef typename result_of::advance::type type; + }; + + template + typename result::type + operator()(const It& it) const + { + return fusion::advance(it); + } + }; + } + + namespace extension + { + template + struct advance_impl; + + template<> + struct advance_impl + { + template + struct apply + { + typedef zip_view_iterator< + typename result_of::transform >::type> type; + + static type + call(It const& it) + { + return type( + fusion::transform(it.iterators_, detail::poly_advance())); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/detail/at_impl.hpp b/win32/include/boost/fusion/view/zip_view/detail/at_impl.hpp new file mode 100755 index 000000000..5a70f274a --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/detail/at_impl.hpp @@ -0,0 +1,92 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_AT_IMPL_20060124_1933) +#define FUSION_AT_IMPL_20060124_1933 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace fusion +{ + struct zip_view_tag; + + namespace detail + { + template + struct poly_at + { + template + struct result; + + template + struct result(SeqRef)> + : mpl::eval_if, + mpl::identity, + result_of::at::type, N> > + { + BOOST_MPL_ASSERT((is_reference)); + }; + + template + typename result::type + operator()(Seq& seq) const + { + return fusion::at(seq); + } + + template + typename result::type + operator()(Seq const& seq) const + { + return fusion::at(seq); + } + + unused_type operator()(unused_type const&) const + { + return unused_type(); + } + }; + } + + namespace extension + { + template + struct at_impl; + + template<> + struct at_impl + { + template + struct apply + { + typedef typename result_of::as_vector< + typename result_of::transform< + typename Seq::sequences, detail::poly_at >::type>::type type; + + static type + call(Seq& seq) + { + return type( + fusion::transform(seq.sequences_, detail::poly_at())); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/detail/begin_impl.hpp b/win32/include/boost/fusion/view/zip_view/detail/begin_impl.hpp new file mode 100755 index 000000000..53e82a0a1 --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/detail/begin_impl.hpp @@ -0,0 +1,92 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_BEGIN_IMPL_20060123_2147) +#define FUSION_BEGIN_IMPL_20060123_2147 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { + + struct zip_view_tag; + + namespace detail + { + struct poly_begin + { + template + struct result; + + template + struct result + : mpl::eval_if, + mpl::identity, + result_of::begin::type> > + { + BOOST_MPL_ASSERT((is_reference)); + }; + + template + typename result::type + operator()(Seq& seq) const + { + return fusion::begin(seq); + } + + template + typename result::type + operator()(Seq const& seq) const + { + return fusion::begin(seq); + } + + unused_type operator()(unused_type const&) const + { + return unused_type(); + } + }; + } + + namespace extension + { + template + struct begin_impl; + + template<> + struct begin_impl + { + template + struct apply + { + typedef zip_view_iterator< + typename result_of::transform::type, + typename Sequence::category> type; + + static type + call(Sequence& sequence) + { + return type( + fusion::transform(sequence.sequences_, detail::poly_begin())); + } + }; + + + + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/detail/deref_impl.hpp b/win32/include/boost/fusion/view/zip_view/detail/deref_impl.hpp new file mode 100755 index 000000000..80b7168e2 --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/detail/deref_impl.hpp @@ -0,0 +1,83 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_DEREF_IMPL_20061024_1959) +#define FUSION_DEREF_IMPL_20061024_1959 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { + + struct zip_view_iterator_tag; + + namespace detail + { + struct poly_deref + { + template + struct result; + + template + struct result + { + typedef typename remove_const< + typename remove_reference::type>::type it; + + typedef typename mpl::eval_if, + mpl::identity, + result_of::deref >::type type; + }; + + template + typename result::type + operator()(const It& it) const + { + return fusion::deref(it); + } + + unused_type operator()(unused_type const&) const + { + return unused_type(); + } + }; + } + + namespace extension + { + template + struct deref_impl; + + template<> + struct deref_impl + { + template + struct apply + { + typedef typename result_of::as_vector< + typename result_of::transform::type>::type type; + + static type + call(It const& it) + { + return type( + fusion::transform(it.iterators_, detail::poly_deref())); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/detail/distance_impl.hpp b/win32/include/boost/fusion/view/zip_view/detail/distance_impl.hpp new file mode 100755 index 000000000..1b167ccb5 --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/detail/distance_impl.hpp @@ -0,0 +1,82 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_DISTANCE_IMPL_20060124_2033) +#define FUSION_DISTANCE_IMPL_20060124_2033 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { + + struct zip_view_iterator_tag; + + struct random_access_iterator_tag; + + namespace detail + { + template + struct best_distance + { + typedef typename result_of::find_if< + typename SearchIt::iterators, is_same, random_access_iterator_tag> > finder; + + BOOST_MPL_ASSERT_NOT((is_same >)); + + typedef typename result_of::distance::type type; + }; + + template + struct default_distance + : result_of::distance< + typename result_of::value_at_c::type, + typename result_of::value_at_c::type> + {}; + + template + struct zip_view_iterator_distance + { + typedef typename result_of::find_if< + typename It1::iterators, is_same, random_access_iterator_tag> > finder; + + typedef typename mpl::eval_if< + is_same::type>, + detail::default_distance , + detail::best_distance >::type type; + }; + } + + namespace extension + { + template + struct distance_impl; + + template<> + struct distance_impl + { + template + struct apply + : detail::zip_view_iterator_distance::type + { + static typename detail::zip_view_iterator_distance::type + call(It1 const& it1, It2 const& it2) + { + return typename detail::zip_view_iterator_distance::type(); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/detail/end_impl.hpp b/win32/include/boost/fusion/view/zip_view/detail/end_impl.hpp new file mode 100755 index 000000000..fb5fba1d1 --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/detail/end_impl.hpp @@ -0,0 +1,103 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_END_IMPL_20060123_2208) +#define FUSION_END_IMPL_20060123_2208 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { namespace fusion { + + struct zip_view_tag; + + namespace detail + { + template + struct get_endpoint + { + typedef typename remove_reference::type Seq; + typedef typename result_of::begin::type begin; + typedef typename result_of::advance::type type; + }; + + template + struct endpoints + { + template + struct result; + + template + struct result(SeqRef)> + : mpl::eval_if, + mpl::identity, + get_endpoint > + { + BOOST_MPL_ASSERT((is_reference)); + }; + + template + typename result::type + operator()(Seq& seq) const + { + return fusion::advance(fusion::begin(seq)); + } + + template + typename result::type + operator()(Seq const& seq) + { + return fusion::advance(fusion::begin(seq)); + } + + unused_type operator()(unused_type const&) const + { + return unused_type(); + } + }; + } + + namespace extension + { + template + struct end_impl; + + template<> + struct end_impl + { + template + struct apply + { + typedef zip_view_iterator< + typename result_of::transform >::type, + typename Sequence::category> type; + + static type + call(Sequence& sequence) + { + return type( + fusion::transform(sequence.sequences_, detail::endpoints())); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/detail/equal_to_impl.hpp b/win32/include/boost/fusion/view/zip_view/detail/equal_to_impl.hpp new file mode 100755 index 000000000..7a18678ad --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/detail/equal_to_impl.hpp @@ -0,0 +1,62 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_EQUAL_TO_IMPL_20060128_1423) +#define FUSION_EQUAL_TO_IMPL_20060128_1423 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace boost { namespace fusion { + + struct zip_view_iterator_tag; + + namespace detail + { + template + struct zip_iterators_equal + { + typedef mpl::zip_view > zipped; + typedef mpl::transform_view > > transformed; + + typedef typename mpl::find_if >::type found; + + typedef typename is_same::type, found>::type type; + }; + } + + namespace extension + { + template + struct equal_to_impl; + + template<> + struct equal_to_impl + { + template + struct apply + : detail::zip_iterators_equal::type + {}; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/detail/next_impl.hpp b/win32/include/boost/fusion/view/zip_view/detail/next_impl.hpp new file mode 100755 index 000000000..ef89868a1 --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/detail/next_impl.hpp @@ -0,0 +1,83 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_NEXT_IMPL_20060124_2006) +#define FUSION_NEXT_IMPL_20060124_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { + + struct zip_view_iterator_tag; + + namespace detail + { + struct poly_next + { + template + struct result; + + template + struct result + { + typedef typename remove_const< + typename remove_reference::type>::type it; + + typedef typename mpl::eval_if, + mpl::identity, + result_of::next >::type type; + }; + + template + typename result::type + operator()(const It& it) const + { + return fusion::next(it); + } + + unused_type operator()(unused_type const&) const + { + return unused_type(); + } + }; + } + + namespace extension + { + template + struct next_impl; + + template<> + struct next_impl + { + template + struct apply + { + typedef fusion::zip_view_iterator< + typename result_of::transform::type, + typename Iterator::category> type; + + static type + call(Iterator const& it) + { + return type( + fusion::transform(it.iterators_, detail::poly_next())); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/detail/prior_impl.hpp b/win32/include/boost/fusion/view/zip_view/detail/prior_impl.hpp new file mode 100755 index 000000000..83ea2baef --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/detail/prior_impl.hpp @@ -0,0 +1,83 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_PRIOR_IMPL_20060124_2006) +#define FUSION_PRIOR_IMPL_20060124_2006 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { + + struct zip_view_iterator_tag; + + namespace detail + { + struct poly_prior + { + template + struct result; + + template + struct result + { + typedef typename remove_const< + typename remove_reference::type>::type it; + typedef typename mpl::eval_if, + mpl::identity, + result_of::prior >::type type; + }; + + template + typename result::type + operator()(const It& it) const + { + return fusion::prior(it); + } + + unused_type operator()(unused_type const&) const + { + return unused_type(); + } + }; + } + + namespace extension + { + template + struct prior_impl; + + template<> + struct prior_impl + { + template + struct apply + { + typedef zip_view_iterator< + typename result_of::transform::type, + typename Iterator::category> type; + + static type + call(Iterator const& it) + + { + return type( + fusion::transform(it.iterators_, detail::poly_prior())); + } + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/detail/size_impl.hpp b/win32/include/boost/fusion/view/zip_view/detail/size_impl.hpp new file mode 100755 index 000000000..03e6c1872 --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/detail/size_impl.hpp @@ -0,0 +1,35 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_SIZE_IMPL_20060124_0800) +#define FUSION_SIZE_IMPL_20060124_0800 + +namespace boost { namespace fusion { + + struct zip_view_tag; + + namespace extension + { + template + struct size; + + template + struct size_impl; + + template<> + struct size_impl + { + template + struct apply + { + typedef typename Sequence::size type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/detail/value_at_impl.hpp b/win32/include/boost/fusion/view/zip_view/detail/value_at_impl.hpp new file mode 100755 index 000000000..2b52a285b --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/detail/value_at_impl.hpp @@ -0,0 +1,61 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_VALUE_AT_IMPL_20060124_2129) +#define FUSION_VALUE_AT_IMPL_20060124_2129 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion { + + struct zip_view_tag; + + namespace detail + { + template + struct poly_value_at + { + template + struct result; + + template + struct result(Seq)> + : mpl::eval_if, + mpl::identity, + result_of::value_at::type, N> > + {}; + }; + } + + namespace extension + { + template + struct value_at_impl; + + template<> + struct value_at_impl + { + template + struct apply + { + typedef typename result_of::transform< + typename Sequence::sequences, + detail::poly_value_at >::type values; + typedef typename result_of::as_vector::type type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/detail/value_of_impl.hpp b/win32/include/boost/fusion/view/zip_view/detail/value_of_impl.hpp new file mode 100755 index 000000000..c082a597f --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/detail/value_of_impl.hpp @@ -0,0 +1,61 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_VALUE_OF_IMPL_20060124_2147) +#define FUSION_VALUE_OF_IMPL_20060124_2147 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace fusion +{ + struct zip_view_iterator_tag; + + namespace detail + { + struct poly_value_of + { + template + struct result; + + template + struct result + : mpl::eval_if, + mpl::identity, + result_of::value_of > + {}; + }; + } + + namespace extension + { + template + struct value_of_impl; + + template<> + struct value_of_impl + { + template + struct apply + { + typedef typename result_of::transform< + typename Iterator::iterators, + detail::poly_value_of>::type values; + + typedef typename result_of::as_vector::type type; + }; + }; + } +}} + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/zip_view.hpp b/win32/include/boost/fusion/view/zip_view/zip_view.hpp new file mode 100755 index 000000000..1441f0265 --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/zip_view.hpp @@ -0,0 +1,115 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_ZIP_VIEW_23012006_0813) +#define FUSION_ZIP_VIEW_23012006_0813 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { namespace fusion { + + namespace detail + { + template + struct all_references + : fusion::result_of::equal_to > >::type, typename fusion::result_of::end::type> + {}; + + struct seq_ref_size + { + template + struct result; + + template + struct result + { + static int const high_int = static_cast( + (static_cast(~0) >> 1) - 1); + + typedef typename remove_reference::type SeqClass; + + typedef typename mpl::eval_if< + traits::is_forward, + result_of::size, + mpl::int_ >::type type; + }; + }; + + struct poly_min + { + template + struct result; + + template + struct result + { + typedef typename remove_reference::type lhs; + typedef typename remove_reference::type rhs; + typedef typename mpl::min::type type; + }; + }; + + template + struct min_size + { + typedef typename result_of::transform::type sizes; + typedef typename result_of::fold::type, detail::poly_min>::type type; + }; + } + + struct zip_view_tag; + struct fusion_sequence_tag; + + template + struct zip_view : sequence_base< zip_view > + { + typedef typename result_of::remove::type real_sequences; + BOOST_MPL_ASSERT((detail::all_references)); + typedef typename detail::strictest_traversal::type category; + typedef zip_view_tag fusion_tag; + typedef fusion_sequence_tag tag; // this gets picked up by MPL + typedef mpl::true_ is_view; + typedef typename fusion::result_of::as_vector::type sequences; + typedef typename detail::min_size::type size; + + zip_view( + const Sequences& seqs) + : sequences_(seqs) + {}; + + sequences sequences_; + }; +}} + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/zip_view_iterator.hpp b/win32/include/boost/fusion/view/zip_view/zip_view_iterator.hpp new file mode 100755 index 000000000..3afbe0cbb --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/zip_view_iterator.hpp @@ -0,0 +1,47 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_ZIP_VIEW_ITERATOR_23012006_0814) +#define FUSION_ZIP_VIEW_ITERATOR_23012006_0814 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { namespace fusion { + + struct zip_view_iterator_tag; + + template< + typename IteratorSequence, + typename Traversal> + struct zip_view_iterator + : iterator_base > + { + typedef zip_view_iterator_tag fusion_tag; + typedef Traversal category; + + template + zip_view_iterator( + const InitSeq& iterator_seq) + : iterators_(iterator_seq) + {} + + typedef typename result_of::as_vector::type iterators; + iterators iterators_; + }; +}} + +#endif diff --git a/win32/include/boost/fusion/view/zip_view/zip_view_iterator_fwd.hpp b/win32/include/boost/fusion/view/zip_view/zip_view_iterator_fwd.hpp new file mode 100755 index 000000000..87b2abcbc --- /dev/null +++ b/win32/include/boost/fusion/view/zip_view/zip_view_iterator_fwd.hpp @@ -0,0 +1,22 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006 Dan Marsden + + 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(FUSION_ZIP_VIEW_ITERATOR_FWD) +#define FUSION_ZIP_VIEW_ITERATOR_FWD + +#include + +namespace boost { namespace fusion { + + template< + typename IteratorSequence, + typename Traversal = typename detail::strictest_traversal::type> + struct zip_view_iterator; + +}} + +#endif diff --git a/win32/include/boost/generator_iterator.hpp b/win32/include/boost/generator_iterator.hpp new file mode 100755 index 000000000..fc273712a --- /dev/null +++ b/win32/include/boost/generator_iterator.hpp @@ -0,0 +1,80 @@ +// (C) Copyright Jens Maurer 2001. +// 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) +// +// Revision History: + +// 15 Nov 2001 Jens Maurer +// created. + +// See http://www.boost.org/libs/utility/iterator_adaptors.htm for documentation. + +#ifndef BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP +#define BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP + +#include +#include + +namespace boost { + +template +class generator_iterator + : public iterator_facade< + generator_iterator + , typename Generator::result_type + , single_pass_traversal_tag + , typename Generator::result_type const& + > +{ + typedef iterator_facade< + generator_iterator + , typename Generator::result_type + , single_pass_traversal_tag + , typename Generator::result_type const& + > super_t; + + public: + generator_iterator() {} + generator_iterator(Generator* g) : m_g(g), m_value((*m_g)()) {} + + void increment() + { + m_value = (*m_g)(); + } + + const typename Generator::result_type& + dereference() const + { + return m_value; + } + + bool equal(generator_iterator const& y) const + { + return this->m_g == y.m_g && this->m_value == y.m_value; + } + + private: + Generator* m_g; + typename Generator::result_type m_value; +}; + +template +struct generator_iterator_generator +{ + typedef generator_iterator type; +}; + +template +inline generator_iterator +make_generator_iterator(Generator & gen) +{ + typedef generator_iterator result_t; + return result_t(&gen); +} + +} // namespace boost + + +#endif // BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP + diff --git a/win32/include/boost/get_pointer.hpp b/win32/include/boost/get_pointer.hpp new file mode 100755 index 000000000..22066e895 --- /dev/null +++ b/win32/include/boost/get_pointer.hpp @@ -0,0 +1,29 @@ +// Copyright Peter Dimov and David Abrahams 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef GET_POINTER_DWA20021219_HPP +# define GET_POINTER_DWA20021219_HPP + +# include + +namespace boost { + +// get_pointer(p) extracts a ->* capable pointer from p + +template T * get_pointer(T * p) +{ + return p; +} + +// get_pointer(shared_ptr const & p) has been moved to shared_ptr.hpp + +template T * get_pointer(std::auto_ptr const& p) +{ + return p.get(); +} + + +} // namespace boost + +#endif // GET_POINTER_DWA20021219_HPP diff --git a/win32/include/boost/gil/algorithm.hpp b/win32/include/boost/gil/algorithm.hpp new file mode 100755 index 000000000..f3b71c8fa --- /dev/null +++ b/win32/include/boost/gil/algorithm.hpp @@ -0,0 +1,1016 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + + +/*************************************************************************************************/ + +#ifndef GIL_ALGORITHM_HPP +#define GIL_ALGORITHM_HPP + +#include +#include +#include +#include +#include +#include +#include +#include "gil_config.hpp" +#include "gil_concept.hpp" +#include "color_base_algorithm.hpp" +#include "image_view.hpp" +#include "image_view_factory.hpp" +#include "bit_aligned_pixel_iterator.hpp" + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Some basic STL-style algorithms when applied to image views +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2008 \n Last updated on March 12, 2008 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +//#ifdef _MSC_VER +//#pragma warning(push) +//#pragma warning(disable : 4244) // conversion from 'gil::image::coord_t' to 'int', possible loss of data (visual studio compiler doesn't realize that the two types are the same) +//#endif + +namespace boost { namespace gil { + +//forward declarations +template +struct planar_pixel_iterator; +template +class memory_based_step_iterator; +template +class memory_based_2d_locator; + +// a tag denoting incompatible arguments +struct error_t {}; + +/// \defgroup ImageViewSTLAlgorithms STL-like Algorithms +/// \ingroup ImageViewAlgorithm +/// \brief Image view-equivalents of STL algorithms +/// +/// Image views provide 1D iteration of their pixels via \p begin() and \p end() methods, +/// which makes it possible to use STL algorithms with them. However, using nested loops +/// over X and Y is in many cases more efficient. The algorithms in this section resemble +/// STL algorithms, but they abstract away the nested loops and take views (as opposed to ranges) as input. +/// +/// Most algorithms check whether the image views are 1D-traversable. A 1D-traversable image view has no gaps +/// at the end of the rows. In other words, if an x_iterator of that view is advanced past the last pixel in a row +/// it will move to the first pixel of the next row. When image views are 1D-traversable, the algorithms use +/// a single loop and run more efficiently. If one or more of the input views are not 1D-traversable, the algorithms +/// fall-back to an X-loop nested inside a Y-loop. +/// +/// The algorithms typically delegate the work to their corresponding STL algorithms. For example, \p copy_pixels calls +/// \p std::copy either for each row, or, when the images are 1D-traversable, once for all pixels. +/// +/// In addition, overloads are sometimes provided for the STL algorithms. For example, std::copy for planar iterators +/// is overloaded to perform \p std::copy for each of the planes. \p std::copy over bitwise-copiable pixels results in +/// std::copy over unsigned char, which STL typically implements via \p memmove. +/// +/// As a result \p copy_pixels may result in a single call to \p memmove for interleaved 1D-traversable views, +/// or one per each plane of planar 1D-traversable views, or one per each row of interleaved non-1D-traversable images, etc. + + +/// \defgroup STLOptimizations Performance overloads of STL algorithms +/// \ingroup ImageViewAlgorithm +/// \brief overloads of STL algorithms allowing more efficient implementation when used with GIL constructs + +/// \brief A generic binary operation on views +/// \ingroup ImageViewSTLAlgorithms +/// +/// Use this class as a convenience superclass when defining an operation for any image views. +/// Many operations have different behavior when the two views are compatible. This class checks +/// for compatibility and invokes apply_compatible(V1,V2) or apply_incompatible(V1,V2) of the subclass. +/// You must provide apply_compatible(V1,V2) method in your subclass, but apply_incompatible(V1,V2) +/// is not required and the default throws std::bad_cast. +template +struct binary_operation_obj { + typedef Result result_type; + + template GIL_FORCEINLINE + result_type operator()(const std::pair& p) const { + return apply(*p.first, *p.second, typename views_are_compatible::type()); + } + + template GIL_FORCEINLINE + result_type operator()(const V1& v1, const V2& v2) const { + return apply(v1, v2, typename views_are_compatible::type()); + } + + result_type operator()(const error_t&) const { throw std::bad_cast(); } +private: + + // dispatch from apply overload to a function with distinct name + template + GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::false_) const { + return ((const Derived*)this)->apply_incompatible(v1,v2); + } + + // dispatch from apply overload to a function with distinct name + template + GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, mpl::true_) const { + return ((const Derived*)this)->apply_compatible(v1,v2); + } + + // function with distinct name - it can be overloaded by subclasses + template + GIL_FORCEINLINE result_type apply_incompatible(const V1& v1, const V2& v2) const { + throw std::bad_cast(); + } +}; +} } // namespace boost::gil + +////////////////////////////////////////////////////////////////////////////////////// +/// +/// std::copy and gil::copy_pixels +/// +////////////////////////////////////////////////////////////////////////////////////// + +/// \defgroup ImageViewSTLAlgorithmsCopyPixels copy_pixels +/// \ingroup ImageViewSTLAlgorithms +/// \brief std::copy for image views + +namespace std { + +/// \ingroup STLOptimizations +/// \brief Copy when both src and dst are interleaved and of the same type can be just memmove +template +GIL_FORCEINLINE boost::gil::pixel* +copy(boost::gil::pixel* first, boost::gil::pixel* last, + boost::gil::pixel* dst) { + return (boost::gil::pixel*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst); +} + +/// \ingroup STLOptimizations +/// \brief Copy when both src and dst are interleaved and of the same type can be just memmove +template +GIL_FORCEINLINE boost::gil::pixel* +copy(const boost::gil::pixel* first, const boost::gil::pixel* last, + boost::gil::pixel* dst) { + return (boost::gil::pixel*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst); +} +} // namespace std + +namespace boost { namespace gil { +namespace detail { +template struct copy_fn { + GIL_FORCEINLINE I operator()(I first, I last, O dst) const { return std::copy(first,last,dst); } +}; +} // namespace detail +} } // namespace boost::gil + +namespace std { +/// \ingroup STLOptimizations +/// \brief Copy when both src and dst are planar pointers is copy for each channel +template GIL_FORCEINLINE +boost::gil::planar_pixel_iterator copy(boost::gil::planar_pixel_iterator first, boost::gil::planar_pixel_iterator last, boost::gil::planar_pixel_iterator dst) { + boost::gil::gil_function_requires::value_type,typename std::iterator_traits::value_type> >(); + static_for_each(first,last,dst,boost::gil::detail::copy_fn()); + return dst+(last-first); +} +} // namespace std + +namespace boost { namespace gil { +namespace detail { +/// Does a copy-n. If the inputs contain image iterators, performs a copy at each row using the row iterators +/// \ingroup CopyPixels +template +struct copier_n { + GIL_FORCEINLINE void operator()(I src, typename std::iterator_traits::difference_type n, O dst) const { std::copy(src,src+n, dst); } +}; + +/// Source range is delimited by image iterators +template // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept +struct copier_n,O> { + typedef typename std::iterator_traits >::difference_type diff_t; + GIL_FORCEINLINE void operator()(iterator_from_2d src, diff_t n, O dst) const { + gil_function_requires >(); + gil_function_requires >(); + while (n>0) { + typedef typename iterator_from_2d::difference_type diff_t; + diff_t l=src.width()-src.x_pos(); + diff_t numToCopy=(n // I Models ConstPixelIteratorConcept, OL Models PixelLocatorConcept +struct copier_n > { + typedef typename std::iterator_traits::difference_type diff_t; + GIL_FORCEINLINE void operator()(I src, diff_t n, iterator_from_2d

    dst) const { + gil_function_requires >(); + gil_function_requires >(); + while (n>0) { + diff_t l=dst.width()-dst.x_pos(); + diff_t numToCopy=(n +struct copier_n,iterator_from_2d
      > { + typedef typename iterator_from_2d::difference_type diff_t; + GIL_FORCEINLINE void operator()(iterator_from_2d src, diff_t n, iterator_from_2d
        dst) const { + gil_function_requires >(); + gil_function_requires >(); + if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) { + while(n-->0) { + *dst++=*src++; + } + } + while (n>0) { + diff_t l=dst.width()-dst.x_pos(); + diff_t numToCopy=(n +GIL_FORCEINLINE DstIterator copy_with_2d_iterators(SrcIterator first, SrcIterator last, DstIterator dst) { + typedef typename SrcIterator::x_iterator src_x_iterator; + typedef typename DstIterator::x_iterator dst_x_iterator; + + typename SrcIterator::difference_type n = last - first; + + if (first.is_1d_traversable()) { + if (dst.is_1d_traversable()) + copier_n()(first.x(),n, dst.x()); + else + copier_n()(first.x(),n, dst); + } else { + if (dst.is_1d_traversable()) + copier_n()(first,n, dst.x()); + else + copier_n()(first,n,dst); + } + return dst+n; +} + +} // namespace detail +} } // namespace boost::gil + +namespace std { +/// \ingroup STLOptimizations +/// \brief std::copy(I1,I1,I2) with I1 and I2 being a iterator_from_2d +template +GIL_FORCEINLINE boost::gil::iterator_from_2d
          copy1(boost::gil::iterator_from_2d first, boost::gil::iterator_from_2d last, boost::gil::iterator_from_2d
            dst) { + return boost::gil::detail::copy_with_2d_iterators(first,last,dst); +} + +} // namespace std + +namespace boost { namespace gil { + + +/// \ingroup ImageViewSTLAlgorithmsCopyPixels +/// \brief std::copy for image views +template GIL_FORCEINLINE +void copy_pixels(const View1& src, const View2& dst) { + assert(src.dimensions()==dst.dimensions()); + detail::copy_with_2d_iterators(src.begin(),src.end(),dst.begin()); +} + +////////////////////////////////////////////////////////////////////////////////////// +/// +/// copy_and_convert_pixels +/// +////////////////////////////////////////////////////////////////////////////////////// + +/// \defgroup ImageViewSTLAlgorithmsCopyAndConvertPixels copy_and_convert_pixels +/// \ingroup ImageViewSTLAlgorithms +/// \brief copies src view into dst view, color converting if necessary. +/// +/// Versions taking static and runtime views are provided. Versions taking user-defined color convered are provided. + +namespace detail { +template +class copy_and_convert_pixels_fn : public binary_operation_obj > { +private: + CC _cc; +public: + typedef typename binary_operation_obj >::result_type result_type; + copy_and_convert_pixels_fn() {} + copy_and_convert_pixels_fn(CC cc_in) : _cc(cc_in) {} + // when the two color spaces are incompatible, a color conversion is performed + template GIL_FORCEINLINE + result_type apply_incompatible(const V1& src, const V2& dst) const { + copy_pixels(color_converted_view(src,_cc),dst); + } + + // If the two color spaces are compatible, copy_and_convert is just copy + template GIL_FORCEINLINE + result_type apply_compatible(const V1& src, const V2& dst) const { + copy_pixels(src,dst); + } +}; +} // namespace detail + +/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels +template +GIL_FORCEINLINE +void copy_and_convert_pixels(const V1& src, const V2& dst,CC cc) { + detail::copy_and_convert_pixels_fn ccp(cc); + ccp(src,dst); +} + +struct default_color_converter; + +/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels +template +GIL_FORCEINLINE +void copy_and_convert_pixels(const View1& src, const View2& dst) { + detail::copy_and_convert_pixels_fn ccp; + ccp(src,dst); +} + +} } // namespace boost::gil + +////////////////////////////////////////////////////////////////////////////////////// +// +// std::fill and gil::fill_pixels +// +////////////////////////////////////////////////////////////////////////////////////// + +/// \defgroup ImageViewSTLAlgorithmsFillPixels fill_pixels +/// \ingroup ImageViewSTLAlgorithms +/// \brief std::fill for image views + + +namespace std { +/// \ingroup STLOptimizations +/// \brief std::fill(I,I,V) with I being a iterator_from_2d +/// +/// Invoked when one calls std::fill(I,I,V) with I being a iterator_from_2d (which is +/// a 1D iterator over the pixels in an image). For contiguous images (i.e. images that have +/// no alignment gap at the end of each row) it is more efficient to use the underlying +/// pixel iterator that does not check for the end of rows. For non-contiguous images fill +/// resolves to fill of each row using the underlying pixel iterator, which is still faster +template +void fill(boost::gil::iterator_from_2d first, boost::gil::iterator_from_2d last, const V& val) { + boost::gil::gil_function_requires >(); + if (first.is_1d_traversable()) { + std::fill(first.x(), last.x(), val); + } else { + // fill row by row + std::ptrdiff_t n=last-first; + while (n>0) { + std::ptrdiff_t numToDo=std::min(n,(std::ptrdiff_t)(first.width()-first.x_pos())); + fill_n(first.x(), numToDo, val); + first+=numToDo; + n-=numToDo; + } + } +} +} // namespace std + +namespace boost { namespace gil { + +namespace detail { +/// struct to do std::fill +struct std_fill_t { + template + void operator()(It first, It last, const P& p_in) { + std::fill(first,last,p_in); + } +}; +/// std::fill for planar iterators +template +GIL_FORCEINLINE +void fill_aux(It first, It last, const P& p, mpl::true_) { + static_for_each(first,last,p,std_fill_t()); +} +/// std::fill for interleaved iterators +template +GIL_FORCEINLINE +void fill_aux(It first, It last, const P& p,mpl::false_) { + std::fill(first,last,p); +} +} // namespace detail + +/// \ingroup ImageViewSTLAlgorithmsFillPixels +/// \brief std::fill for image views +template GIL_FORCEINLINE +void fill_pixels(const View& img_view, const Value& val) { + if (img_view.is_1d_traversable()) + detail::fill_aux(img_view.begin().x(), img_view.end().x(), + val,is_planar()); + else + for (std::ptrdiff_t y=0; y()); +} + +////////////////////////////////////////////////////////////////////////////////////// +/// +/// destruct_pixels +/// +////////////////////////////////////////////////////////////////////////////////////// + +/// \defgroup ImageViewSTLAlgorithmsDestructPixels destruct_pixels +/// \ingroup ImageViewSTLAlgorithms +/// \brief invokes the destructor on every pixel of an image view + + +namespace detail { + +template GIL_FORCEINLINE +void destruct_range_impl(It first, It last, mpl::true_) { + typedef typename std::iterator_traits::value_type value_t; + if (boost::has_trivial_destructor::value) + return; + while (first!=last) { + first->~value_t(); + ++first; + } +} +template GIL_FORCEINLINE +void destruct_range_impl(It first, It last, mpl::false_) {} + +template GIL_FORCEINLINE +void destruct_range(It first, It last) { + destruct_range_impl(first,last,typename is_pointer::type()); +} + +struct std_destruct_t { + template void operator()(It first, It last) const { destruct_range(first,last); } +}; + +/// destruct for planar iterators +template +GIL_FORCEINLINE +void destruct_aux(It first, It last, mpl::true_) { + static_for_each(first,last,std_destruct_t()); +} +/// destruct for interleaved iterators +template +GIL_FORCEINLINE +void destruct_aux(It first, It last, mpl::false_) { + destruct_range(first,last); +} + +} // namespace detail + +/// \ingroup ImageViewSTLAlgorithmsDestructPixels +/// \brief Invokes the in-place destructor on every pixel of the view +template GIL_FORCEINLINE +void destruct_pixels(const View& img_view) { + if (img_view.is_1d_traversable()) + detail::destruct_aux(img_view.begin().x(), img_view.end().x(), + is_planar()); + else + for (std::ptrdiff_t y=0; y()); +} + +////////////////////////////////////////////////////////////////////////////////////// +/// +/// uninitialized_fill_pixels +/// +////////////////////////////////////////////////////////////////////////////////////// + +/// \defgroup ImageViewSTLAlgorithmsUninitializedFillPixels uninitialized_fill_pixels +/// \ingroup ImageViewSTLAlgorithms +/// \brief std::uninitialized_fill for image views + + +namespace detail { + +/// std::uninitialized_fill for planar iterators +/// If an exception is thrown destructs any in-place copy-constructed objects +template +GIL_FORCEINLINE +void uninitialized_fill_aux(It first, It last, + const P& p, mpl::true_) { + int channel=0; + try { + typedef typename std::iterator_traits::value_type pixel_t; + while (channel < num_channels::value) { + std::uninitialized_fill(dynamic_at_c(first,channel), dynamic_at_c(last,channel), + dynamic_at_c(p,channel)); + ++channel; + } + } catch (...) { + for (int c=0; c +GIL_FORCEINLINE +void uninitialized_fill_aux(It first, It last, + const P& p,mpl::false_) { + std::uninitialized_fill(first,last,p); +} + +} // namespace detail + +/// \ingroup ImageViewSTLAlgorithmsUninitializedFillPixels +/// \brief std::uninitialized_fill for image views. +/// Does not support planar heterogeneous views. +/// If an exception is thrown destructs any in-place copy-constructed pixels +template +void uninitialized_fill_pixels(const View& img_view, const Value& val) { + if (img_view.is_1d_traversable()) + detail::uninitialized_fill_aux(img_view.begin().x(), img_view.end().x(), + val,is_planar()); + else { + typename View::y_coord_t y; + try { + for (y=0; y()); + } catch(...) { + for (typename View::y_coord_t y0=0; y0()); + throw; + } + } +} + +////////////////////////////////////////////////////////////////////////////////////// +/// +/// default_construct_pixels +/// +////////////////////////////////////////////////////////////////////////////////////// + +/// \defgroup ImageViewSTLAlgorithmsDefaultConstructPixels default_construct_pixels +/// \ingroup ImageViewSTLAlgorithms +/// \brief invokes the default constructor on every pixel of an image view + +namespace detail { + +template GIL_FORCEINLINE +void default_construct_range_impl(It first, It last, mpl::true_) { + typedef typename std::iterator_traits::value_type value_t; + It first1=first; + try { + while (first!=last) { + new (first) value_t(); + ++first; + } + } catch (...) { + destruct_range(first1,first); + throw; + } +} + +template GIL_FORCEINLINE +void default_construct_range_impl(It first, It last, mpl::false_) {} + +template GIL_FORCEINLINE +void default_construct_range(It first, It last) { default_construct_range_impl(first, last, typename is_pointer::type()); } + +/// uninitialized_default_construct for planar iterators +template +GIL_FORCEINLINE +void default_construct_aux(It first, It last, mpl::true_) { + int channel=0; + try { + typedef typename std::iterator_traits::value_type pixel_t; + while (channel < num_channels::value) { + default_construct_range(dynamic_at_c(first,channel), dynamic_at_c(last,channel)); + ++channel; + } + } catch (...) { + for (int c=0; c +GIL_FORCEINLINE +void default_construct_aux(It first, It last, mpl::false_) { + default_construct_range(first,last); +} + +template +struct has_trivial_pixel_constructor : public boost::has_trivial_constructor {}; +template +struct has_trivial_pixel_constructor : public boost::has_trivial_constructor::type> {}; + +} // namespace detail + +/// \ingroup ImageViewSTLAlgorithmsDefaultConstructPixels +/// \brief Invokes the in-place default constructor on every pixel of the (uninitialized) view. +/// Does not support planar heterogeneous views. +/// If an exception is thrown destructs any in-place default-constructed pixels +template +void default_construct_pixels(const View& img_view) { + if (detail::has_trivial_pixel_constructor::value>::value) + return; + + if (img_view.is_1d_traversable()) + detail::default_construct_aux(img_view.begin().x(), img_view.end().x(), is_planar()); + else { + typename View::y_coord_t y; + try { + for (y=0; y()); + } catch(...) { + for (typename View::y_coord_t y0=0; y0()); + throw; + } + } +} + + +////////////////////////////////////////////////////////////////////////////////////// +/// +/// uninitialized_copy_pixels +/// +////////////////////////////////////////////////////////////////////////////////////// + +/// \defgroup ImageViewSTLAlgorithmsUninitializedCopyPixels uninitialized_copy_pixels +/// \ingroup ImageViewSTLAlgorithms +/// \brief std::uninitialized_copy for image views + +namespace detail { + +/// std::uninitialized_copy for pairs of planar iterators +template +GIL_FORCEINLINE +void uninitialized_copy_aux(It1 first1, It1 last1, + It2 first2, mpl::true_) { + int channel=0; + try { + typedef typename std::iterator_traits::value_type pixel_t; + while (channel < num_channels::value) { + std::uninitialized_copy(dynamic_at_c(first1,channel), dynamic_at_c(last1,channel), dynamic_at_c(first2,channel)); + ++channel; + } + } catch (...) { + It2 last2=first2; + std::advance(last2, std::distance(first1,last1)); + for (int c=0; c +GIL_FORCEINLINE +void uninitialized_copy_aux(It1 first1, It1 last1, + It2 first2,mpl::false_) { + std::uninitialized_copy(first1,last1,first2); +} +} // namespace detail + +/// \ingroup ImageViewSTLAlgorithmsUninitializedCopyPixels +/// \brief std::uninitialized_copy for image views. +/// Does not support planar heterogeneous views. +/// If an exception is thrown destructs any in-place copy-constructed objects +template +void uninitialized_copy_pixels(const View1& view1, const View2& view2) { + typedef mpl::bool_::value && is_planar::value> is_planar; + assert(view1.dimensions()==view2.dimensions()); + if (view1.is_1d_traversable() && view2.is_1d_traversable()) + detail::uninitialized_copy_aux(view1.begin().x(), view1.end().x(), + view2.begin().x(), + is_planar()); + else { + typename View1::y_coord_t y; + try { + for (y=0; y +F for_each_pixel(const V& img, F fun) { + if (img.is_1d_traversable()) { + return std::for_each(img.begin().x(), img.end().x(), fun); + } else { + for (std::ptrdiff_t y=0; y +F for_each_pixel_position(const View& img, F fun) { + typename View::xy_locator loc=img.xy_at(0,0); + for (std::ptrdiff_t y=0; y +void generate_pixels(const View& v, F fun) { + if (v.is_1d_traversable()) { + std::generate(v.begin().x(), v.end().x(), fun); + } else { + for (std::ptrdiff_t y=0; y GIL_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2); + +namespace detail { + +template +struct equal_n_fn { + GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const { return std::equal(i1,i1+n, i2); } +}; + +/// Equal when both ranges are interleaved and of the same type. +/// GIL pixels are bitwise comparable, so memcmp is used. User-defined pixels that are not bitwise comparable need to provide an overload +template +struct equal_n_fn*, const pixel*> { + GIL_FORCEINLINE bool operator()(const pixel* i1, std::ptrdiff_t n, const pixel* i2) const { + return memcmp(i1, i2, n*sizeof(pixel))==0; + } +}; +template +struct equal_n_fn*, pixel*> : equal_n_fn*, const pixel*> {}; + +/// EqualPixels +/// Equal when both ranges are planar pointers of the same type. memcmp is invoked for each channel plane +/// User-defined channels that are not bitwise comparable need to provide an overload +template +struct equal_n_fn, planar_pixel_iterator > { + GIL_FORCEINLINE bool operator()(const planar_pixel_iterator i1, std::ptrdiff_t n, const planar_pixel_iterator i2) const { + ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits::value_type); + + for (std::ptrdiff_t i=0; i::value; ++i) + if (memcmp(dynamic_at_c(i1,i), dynamic_at_c(i2,i), numBytes)!=0) + return false; + return true; + } +}; + + +/// Source range is delimited by image iterators +template // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept +struct equal_n_fn,I2> { + GIL_FORCEINLINE bool operator()(boost::gil::iterator_from_2d i1, std::ptrdiff_t n, I2 i2) const { + gil_function_requires >(); + gil_function_requires >(); + while (n>0) { + std::ptrdiff_t num=std::min(n, i1.width()-i1.x_pos()); + if (!equal_n(i1.x(), num, i2)) + return false; + i1+=num; + i2+=num; + n-=num; + } + return true; + } +}; + +/// Destination range is delimited by image iterators +template // I Models PixelIteratorConcept, OL Models PixelLocatorConcept +struct equal_n_fn > { + GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, boost::gil::iterator_from_2d i2) const { + gil_function_requires >(); + gil_function_requires >(); + while (n>0) { + std::ptrdiff_t num=std::min(n,i2.width()-i2.x_pos()); + if (!equal_n(i1, num, i2.x())) + return false; + i1+=num; + i2+=num; + n-=num; + } + return true; + } +}; + +/// Both source and destination ranges are delimited by image iterators +template +struct equal_n_fn,boost::gil::iterator_from_2d > { + GIL_FORCEINLINE bool operator()(boost::gil::iterator_from_2d i1, std::ptrdiff_t n, boost::gil::iterator_from_2d i2) const { + gil_function_requires >(); + gil_function_requires >(); + if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) { + while(n-->0) { + if (*i1++!=*i2++) return false; + } + } + while (n>0) { + std::ptrdiff_t num=std::min(n,i2.width()-i2.x_pos()); + if (!equal_n(i1.x(), num, i2.x())) + return false; + i1+=num; + i2+=num; + n-=num; + } + return true; + } +}; +} // namespace detail + +template GIL_FORCEINLINE +bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) { + return detail::equal_n_fn()(i1,n,i2); +} +} } // namespace boost::gil + +namespace std { +/// \ingroup STLOptimizations +/// \brief std::equal(I1,I1,I2) with I1 and I2 being a iterator_from_2d +/// +/// Invoked when one calls std::equal(I1,I1,I2) with I1 and I2 being a iterator_from_2d (which is +/// a 1D iterator over the pixels in an image). Attempts to demote the source and destination +/// iterators to simpler/faster types if the corresponding range is contiguous. +/// For contiguous images (i.e. images that have +/// no alignment gap at the end of each row) it is more efficient to use the underlying +/// pixel iterator that does not check for the end of rows. If the underlying pixel iterator +/// happens to be a fundamental planar/interleaved pointer, the call may further resolve +/// to memcmp. Otherwise it resolves to copying each row using the underlying pixel iterator +template GIL_FORCEINLINE +bool equal(boost::gil::iterator_from_2d first, boost::gil::iterator_from_2d last, boost::gil::iterator_from_2d first2) { + boost::gil::gil_function_requires >(); + boost::gil::gil_function_requires >(); + std::ptrdiff_t n=last-first; + if (first.is_1d_traversable()) { + if (first2.is_1d_traversable()) + return boost::gil::detail::equal_n_fn()(first.x(),n, first2.x()); + else + return boost::gil::detail::equal_n_fn >()(first.x(),n, first2); + } else { + if (first2.is_1d_traversable()) + return boost::gil::detail::equal_n_fn,typename Loc2::x_iterator>()(first,n, first2.x()); + else + return boost::gil::detail::equal_n_fn,boost::gil::iterator_from_2d >()(first,n,first2); + } +} +} // namespace std + +namespace boost { namespace gil { + +/// \ingroup ImageViewSTLAlgorithmsEqualPixels +/// \brief std::equal for image views +template GIL_FORCEINLINE +bool equal_pixels(const View1& v1, const View2& v2) { + assert(v1.dimensions()==v2.dimensions()); + return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance +} + +////////////////////////////////////////////////////////////////////////////////////// +/// +/// transform_pixels +/// +////////////////////////////////////////////////////////////////////////////////////// + +/// \defgroup ImageViewSTLAlgorithmsTransformPixels transform_pixels +/// \ingroup ImageViewSTLAlgorithms +/// \brief std::transform for image views + +/// \ingroup ImageViewSTLAlgorithmsTransformPixels +/// \brief std::transform for image views +template GIL_FORCEINLINE +F transform_pixels(const View1& src,const View2& dst, F fun) { + assert(src.dimensions()==dst.dimensions()); + for (std::ptrdiff_t y=0; y GIL_FORCEINLINE +F transform_pixels(const View1& src1, const View2& src2,const View3& dst, F fun) { + for (std::ptrdiff_t y=0; y GIL_FORCEINLINE +F transform_pixel_positions(const View1& src,const View2& dst, F fun) { + assert(src.dimensions()==dst.dimensions()); + typename View1::xy_locator loc=src.xy_at(0,0); + for (std::ptrdiff_t y=0; y GIL_FORCEINLINE +F transform_pixel_positions(const View1& src1,const View2& src2,const View3& dst, F fun) { + assert(src1.dimensions()==dst.dimensions()); + assert(src2.dimensions()==dst.dimensions()); + typename View1::xy_locator loc1=src1.xy_at(0,0); + typename View2::xy_locator loc2=src2.xy_at(0,0); + for (std::ptrdiff_t y=0; y +#include +#include "gil_config.hpp" +#include "bit_aligned_pixel_reference.hpp" +#include "pixel_iterator.hpp" + +namespace boost { namespace gil { + +/// \defgroup PixelIteratorNonAlignedPixelIterator bit_aligned_pixel_iterator +/// \ingroup PixelIteratorModel +/// \brief An iterator over non-byte-aligned pixels. Models PixelIteratorConcept, PixelBasedConcept, MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept + +//////////////////////////////////////////////////////////////////////////////////////// +/// \brief An iterator over non-byte-aligned pixels. Models PixelIteratorConcept, PixelBasedConcept, MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept +/// +/// An iterator over pixels that correspond to non-byte-aligned bit ranges. Examples of such pixels are single bit grayscale pixel, or a 6-bit RGB 222 pixel. +/// +/// \ingroup PixelIteratorNonAlignedPixelIterator PixelBasedModel + +template +struct bit_aligned_pixel_iterator : public iterator_facade, + typename NonAlignedPixelReference::value_type, + random_access_traversal_tag, + const NonAlignedPixelReference, + typename NonAlignedPixelReference::bit_range_t::difference_type> { +private: + typedef iterator_facade, + typename NonAlignedPixelReference::value_type, + random_access_traversal_tag, + const NonAlignedPixelReference, + typename NonAlignedPixelReference::bit_range_t::difference_type> parent_t; + template friend struct bit_aligned_pixel_iterator; + + typedef typename NonAlignedPixelReference::bit_range_t bit_range_t; +public: + typedef typename parent_t::difference_type difference_type; + typedef typename parent_t::reference reference; + + bit_aligned_pixel_iterator() {} + bit_aligned_pixel_iterator(const bit_aligned_pixel_iterator& p) : _bit_range(p._bit_range) {} + bit_aligned_pixel_iterator& operator=(const bit_aligned_pixel_iterator& p) { _bit_range=p._bit_range; return *this; } + + template bit_aligned_pixel_iterator(const bit_aligned_pixel_iterator& p) : _bit_range(p._bit_range) {} + + bit_aligned_pixel_iterator(reference* ref) : _bit_range(ref->bit_range()) {} + explicit bit_aligned_pixel_iterator(typename bit_range_t::byte_t* data, int bit_offset=0) : _bit_range(data,bit_offset) {} + + /// For some reason operator[] provided by iterator_adaptor returns a custom class that is convertible to reference + /// We require our own reference because it is registered in iterator_traits + reference operator[](difference_type d) const { bit_aligned_pixel_iterator it=*this; it.advance(d); return *it; } + + reference operator->() const { return **this; } + const bit_range_t& bit_range() const { return _bit_range; } + bit_range_t& bit_range() { return _bit_range; } +private: + bit_range_t _bit_range; + BOOST_STATIC_CONSTANT(int, bit_size = NonAlignedPixelReference::bit_size); + + friend class boost::iterator_core_access; + reference dereference() const { return NonAlignedPixelReference(_bit_range); } + void increment() { ++_bit_range; } + void decrement() { --_bit_range; } + void advance(difference_type d) { _bit_range.bit_advance(d*bit_size); } + + difference_type distance_to(const bit_aligned_pixel_iterator& it) const { return _bit_range.bit_distance_to(it._bit_range) / bit_size; } + bool equal(const bit_aligned_pixel_iterator& it) const { return _bit_range==it._bit_range; } +}; + +template +struct const_iterator_type > { + typedef bit_aligned_pixel_iterator type; +}; + +template +struct iterator_is_mutable > : public mpl::bool_ {}; + +template +struct is_iterator_adaptor > : public mpl::false_ {}; + +///////////////////////////// +// PixelBasedConcept +///////////////////////////// + +template +struct color_space_type > : public color_space_type {}; + +template +struct channel_mapping_type > : public channel_mapping_type {}; + +template +struct is_planar > : public is_planar {}; // == false + +///////////////////////////// +// MemoryBasedIteratorConcept +///////////////////////////// + +template +struct byte_to_memunit > : public mpl::int_<8> {}; + +template +inline std::ptrdiff_t memunit_step(const bit_aligned_pixel_iterator&) { + return NonAlignedPixelReference::bit_size; +} + +template +inline std::ptrdiff_t memunit_distance(const bit_aligned_pixel_iterator& p1, const bit_aligned_pixel_iterator& p2) { + return (p2.bit_range().current_byte() - p1.bit_range().current_byte())*8 + p2.bit_range().bit_offset() - p1.bit_range().bit_offset(); +} + +template +inline void memunit_advance(bit_aligned_pixel_iterator& p, std::ptrdiff_t diff) { + p.bit_range().bit_advance(diff); +} + +template +inline bit_aligned_pixel_iterator memunit_advanced(const bit_aligned_pixel_iterator& p, std::ptrdiff_t diff) { + bit_aligned_pixel_iterator ret=p; + memunit_advance(ret, diff); + return ret; +} + +template inline +NonAlignedPixelReference memunit_advanced_ref(bit_aligned_pixel_iterator it, std::ptrdiff_t diff) { + return *memunit_advanced(it,diff); +} +///////////////////////////// +// HasDynamicXStepTypeConcept +///////////////////////////// + +template +struct dynamic_x_step_type > { + typedef memory_based_step_iterator > type; +}; + +///////////////////////////// +// iterator_type_from_pixel +///////////////////////////// + +template +struct iterator_type_from_pixel,false,false,false> { + typedef bit_aligned_pixel_iterator > type; +}; + +template +struct iterator_type_from_pixel,false,false,true> { + typedef bit_aligned_pixel_iterator > type; +}; + +template +struct iterator_type_from_pixel,IsPlanar,IsStep,IsMutable> + : public iterator_type_from_pixel,IsPlanar,IsStep,IsMutable> {}; + +} } // namespace boost::gil + +namespace std { + +// It is important to provide an overload of uninitialized_copy for bit_aligned_pixel_iterator. The default STL implementation calls placement new, +// which is not defined for bit_aligned_pixel_iterator. +template +boost::gil::bit_aligned_pixel_iterator uninitialized_copy(boost::gil::bit_aligned_pixel_iterator first, + boost::gil::bit_aligned_pixel_iterator last, + boost::gil::bit_aligned_pixel_iterator dst) { + return std::copy(first,last,dst); +} + +} // namespace std +#endif diff --git a/win32/include/boost/gil/bit_aligned_pixel_reference.hpp b/win32/include/boost/gil/bit_aligned_pixel_reference.hpp new file mode 100755 index 000000000..0d14dfe70 --- /dev/null +++ b/win32/include/boost/gil/bit_aligned_pixel_reference.hpp @@ -0,0 +1,302 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://stlab.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_BIT_ALIGNED_PIXEL_REFERENCE_HPP +#define GIL_BIT_ALIGNED_PIXEL_REFERENCE_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief A model of a heterogeneous pixel that is not byte aligned. Examples are bitmap (1-bit pixels) or 6-bit RGB (222) +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on September 28, 2006 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include "gil_config.hpp" +#include "pixel.hpp" +#include "channel.hpp" + +namespace boost { namespace gil { + +///////////////////////////// +// bit_range +// +// Represents a range of bits that can span multiple consecutive bytes. The range has a size fixed at compile time, but the offset is specified at run time. +///////////////////////////// + +template +class bit_range { +public: + typedef typename mpl::if_c::type byte_t; + typedef std::ptrdiff_t difference_type; + template friend class bit_range; +private: + byte_t* _current_byte; // the starting byte of the bit range + int _bit_offset; // offset from the beginning of the current byte. 0<=_bit_offset<=7 + +public: + bit_range() : _current_byte(NULL), _bit_offset(0) {} + bit_range(byte_t* current_byte, int bit_offset) : _current_byte(current_byte), _bit_offset(bit_offset) { assert(bit_offset>=0 && bit_offset<8); } + + bit_range(const bit_range& br) : _current_byte(br._current_byte), _bit_offset(br._bit_offset) {} + template bit_range(const bit_range& br) : _current_byte(br._current_byte), _bit_offset(br._bit_offset) {} + + bit_range& operator=(const bit_range& br) { _current_byte = br._current_byte; _bit_offset=br._bit_offset; return *this; } + bool operator==(const bit_range& br) const { return _current_byte==br._current_byte && _bit_offset==br._bit_offset; } + + bit_range& operator++() { + _current_byte += (_bit_offset+RangeSize) / 8; + _bit_offset = (_bit_offset+RangeSize) % 8; + return *this; + } + bit_range& operator--() { bit_advance(-RangeSize); return *this; } + + void bit_advance(difference_type num_bits) { + int new_offset = int(_bit_offset+num_bits); + _current_byte += new_offset / 8; + _bit_offset = new_offset % 8; + if (_bit_offset<0) { + _bit_offset+=8; + --_current_byte; + } + } + difference_type bit_distance_to(const bit_range& b) const { + return (b.current_byte() - current_byte())*8 + b.bit_offset()-bit_offset(); + } + byte_t* current_byte() const { return _current_byte; } + int bit_offset() const { return _bit_offset; } +}; + + +/// \defgroup ColorBaseModelNonAlignedPixel bit_aligned_pixel_reference +/// \ingroup ColorBaseModel +/// \brief A heterogeneous color base representing pixel that may not be byte aligned, i.e. it may correspond to a bit range that does not start/end at a byte boundary. Models ColorBaseConcept. + +/** +\defgroup PixelModelNonAlignedPixel bit_aligned_pixel_reference +\ingroup PixelModel +\brief A heterogeneous pixel reference used to represent non-byte-aligned pixels. Models PixelConcept + +Example: +\code +unsigned char data=0; + +// A mutable reference to a 6-bit BGR pixel in "123" format (1 bit for red, 2 bits for green, 3 bits for blue) +typedef const bit_aligned_pixel_reference, rgb_layout_t, true> rgb123_ref_t; + +// create the pixel reference at bit offset 2 +// (i.e. red = [2], green = [3,4], blue = [5,6,7] bits) +rgb123_ref_t ref(&data, 2); +get_color(ref, red_t()) = 1; +assert(data == 0x04); +get_color(ref, green_t()) = 3; +assert(data == 0x1C); +get_color(ref, blue_t()) = 7; +assert(data == 0xFC); +\endcode +*/ +/// \ingroup ColorBaseModelNonAlignedPixel PixelModelNonAlignedPixel PixelBasedModel +/// \brief Heterogeneous pixel reference corresponding to non-byte-aligned bit range. Models ColorBaseConcept, PixelConcept, PixelBasedConcept +template + typename Layout, + bool IsMutable> +struct bit_aligned_pixel_reference { + BOOST_STATIC_CONSTANT(int, bit_size = (mpl::accumulate, mpl::plus >::type::value)); + typedef boost::gil::bit_range bit_range_t; + typedef BitField bitfield_t; + typedef typename mpl::if_c::type data_ptr_t; + + typedef Layout layout_t; + + typedef typename packed_pixel_type::type value_type; + typedef const bit_aligned_pixel_reference reference; + typedef const bit_aligned_pixel_reference const_reference; + + BOOST_STATIC_CONSTANT(bool, is_mutable = IsMutable); + + bit_aligned_pixel_reference(){} + bit_aligned_pixel_reference(data_ptr_t data_ptr, int bit_offset) : _bit_range(data_ptr, bit_offset) {} + explicit bit_aligned_pixel_reference(const bit_range_t& bit_range) : _bit_range(bit_range) {} + template bit_aligned_pixel_reference(const bit_aligned_pixel_reference& p) : _bit_range(p._bit_range) {} + + // Grayscale references can be constructed from the channel reference + explicit bit_aligned_pixel_reference(const typename kth_element_type::type channel0) : _bit_range(static_cast(&channel0), channel0.first_bit()) { + BOOST_STATIC_ASSERT((num_channels::value==1)); + } + + // Construct from another compatible pixel type + bit_aligned_pixel_reference(const bit_aligned_pixel_reference& p) : _bit_range(p._bit_range) {} + template bit_aligned_pixel_reference(packed_pixel& p) : _bit_range(static_cast(&at_c<0>(p)), at_c<0>(p).first_bit()) { + check_compatible >(); + } + + const bit_aligned_pixel_reference& operator=(const bit_aligned_pixel_reference& p) const { static_copy(p,*this); return *this; } + template const bit_aligned_pixel_reference& operator=(const P& p) const { assign(p, mpl::bool_::value>()); return *this; } + + template bool operator==(const P& p) const { return equal(p, mpl::bool_::value>()); } + template bool operator!=(const P& p) const { return !(*this==p); } + + const bit_aligned_pixel_reference* operator->() const { return this; } + + const bit_range_t& bit_range() const { return _bit_range; } +private: + mutable bit_range_t _bit_range; + template friend struct bit_aligned_pixel_reference; + + template static void check_compatible() { gil_function_requires >(); } + + template void assign(const Pixel& p, mpl::true_) const { check_compatible(); static_copy(p,*this); } + template bool equal(const Pixel& p, mpl::true_) const { check_compatible(); return static_equal(*this,p); } + +private: + static void check_gray() { BOOST_STATIC_ASSERT((is_same::value)); } + template void assign(const Channel& chan, mpl::false_) const { check_gray(); at_c<0>(*this)=chan; } + template bool equal (const Channel& chan, mpl::false_) const { check_gray(); return at_c<0>(*this)==chan; } +}; + +///////////////////////////// +// ColorBasedConcept +///////////////////////////// + +template +struct kth_element_type, K> { +public: + typedef const packed_dynamic_channel_reference::type::value, IsMutable> type; +}; + +template +struct kth_element_reference_type, K> + : public kth_element_type, K> {}; + +template +struct kth_element_const_reference_type, K> + : public kth_element_type, K> {}; + + +namespace detail { + // returns sum of IntegralVector[0] ... IntegralVector[K-1] + template + struct sum_k : public mpl::plus, typename mpl::at_c::type > {}; + + template struct sum_k : public mpl::int_<0> {}; +} + +// at_c required by MutableColorBaseConcept +template inline +typename kth_element_reference_type,K>::type +at_c(const bit_aligned_pixel_reference& p) { + typedef bit_aligned_pixel_reference pixel_t; + typedef typename kth_element_reference_type::type channel_t; + typedef typename pixel_t::bit_range_t bit_range_t; + + bit_range_t bit_range(p.bit_range()); + bit_range.bit_advance(detail::sum_k::value); + + return channel_t(bit_range.current_byte(), bit_range.bit_offset()); +} + +///////////////////////////// +// PixelConcept +///////////////////////////// + +/// Metafunction predicate that flags bit_aligned_pixel_reference as a model of PixelConcept. Required by PixelConcept +template +struct is_pixel > : public mpl::true_{}; + +///////////////////////////// +// PixelBasedConcept +///////////////////////////// + +template +struct color_space_type > { + typedef typename L::color_space_t type; +}; + +template +struct channel_mapping_type > { + typedef typename L::channel_mapping_t type; +}; + +template +struct is_planar > : mpl::false_ {}; + +///////////////////////////// +// pixel_reference_type +///////////////////////////// + +namespace detail { + // returns a vector containing K copies of the type T + template struct k_copies; + template struct k_copies<0,T> { + typedef mpl::vector0<> type; + }; + template struct k_copies : public mpl::push_back::type, T> {}; +} + +// Constructs a homogeneous bit_aligned_pixel_reference given a channel reference +template +struct pixel_reference_type, Layout, false, false> { +private: + typedef typename mpl::size::type size_t; + typedef typename detail::k_copies >::type channel_bit_sizes_t; +public: + typedef bit_aligned_pixel_reference type; +}; + +// Same but for the mutable case. We cannot combine the mutable and read-only cases because this triggers ambiguity +template +struct pixel_reference_type, Layout, false, true> { +private: + typedef typename mpl::size::type size_t; + typedef typename detail::k_copies >::type channel_bit_sizes_t; +public: + typedef bit_aligned_pixel_reference type; +}; + +} } // namespace boost::gil + +namespace std { +// We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified. +// swap with 'left bias': +// - swap between proxy and anything +// - swap between value type and proxy +// - swap between proxy and proxy +// Having three overloads allows us to swap between different (but compatible) models of PixelConcept + +template inline +void swap(const boost::gil::bit_aligned_pixel_reference x, R& y) { + boost::gil::swap_proxy::value_type>(x,y); +} + + +template inline +void swap(typename boost::gil::bit_aligned_pixel_reference::value_type& x, const boost::gil::bit_aligned_pixel_reference y) { + boost::gil::swap_proxy::value_type>(x,y); +} + + +template inline +void swap(const boost::gil::bit_aligned_pixel_reference x, const boost::gil::bit_aligned_pixel_reference y) { + boost::gil::swap_proxy::value_type>(x,y); +} +} // namespace std +#endif diff --git a/win32/include/boost/gil/channel.hpp b/win32/include/boost/gil/channel.hpp new file mode 100755 index 000000000..530c9dbde --- /dev/null +++ b/win32/include/boost/gil/channel.hpp @@ -0,0 +1,643 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://stlab.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_CHANNEL_HPP +#define GIL_CHANNEL_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Channel utilities +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on May 6, 2007 +/// +/// Definitions of standard GIL channel models +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "gil_config.hpp" +#include "utilities.hpp" + +namespace boost { namespace gil { + + +/////////////////////////////////////////// +//// channel_traits +//// +//// \ingroup ChannelModel +//// \class channel_traits +//// \brief defines properties of channels, such as their range and associated types +//// +//// The channel traits must be defined for every model of ChannelConcept +//// Default traits are provided. For built-in types the default traits use +//// built-in pointer and reference and the channel range is the physical +//// range of the type. For classes, the default traits forward the associated types +//// and range to the class. +//// +/////////////////////////////////////////// + +namespace detail { + template struct channel_traits_impl; + + // channel traits for custom class + template + struct channel_traits_impl { + typedef typename T::value_type value_type; + typedef typename T::reference reference; + typedef typename T::pointer pointer; + typedef typename T::const_reference const_reference; + typedef typename T::const_pointer const_pointer; + BOOST_STATIC_CONSTANT(bool, is_mutable=T::is_mutable); + static value_type min_value() { return T::min_value(); } + static value_type max_value() { return T::max_value(); } + }; + + // channel traits implementation for built-in integral or floating point channel type + template + struct channel_traits_impl { + typedef T value_type; + typedef T& reference; + typedef T* pointer; + typedef const T& const_reference; + typedef T const* const_pointer; + BOOST_STATIC_CONSTANT(bool, is_mutable=true); + static value_type min_value() { return (std::numeric_limits::min)(); } + static value_type max_value() { return (std::numeric_limits::max)(); } + }; + + // channel traits implementation for constant built-in scalar or floating point type + template + struct channel_traits_impl : public channel_traits_impl { + typedef const T& reference; + typedef const T* pointer; + BOOST_STATIC_CONSTANT(bool, is_mutable=false); + }; +} + +/** +\ingroup ChannelModel +\brief Traits for channels. Contains the following members: +\code +template +struct channel_traits { + typedef ... value_type; + typedef ... reference; + typedef ... pointer; + typedef ... const_reference; + typedef ... const_pointer; + + static const bool is_mutable; + static value_type min_value(); + static value_type max_value(); +}; +\endcode +*/ +template +struct channel_traits : public detail::channel_traits_impl::value> {}; + +// Channel traits for C++ reference type - remove the reference +template struct channel_traits< T&> : public channel_traits {}; + +// Channel traits for constant C++ reference type +template struct channel_traits : public channel_traits { + typedef typename channel_traits::const_reference reference; + typedef typename channel_traits::const_pointer pointer; + BOOST_STATIC_CONSTANT(bool, is_mutable=false); +}; + +/////////////////////////////////////////// +//// +//// scoped_channel_value +//// +/////////////////////////////////////////// + +/** +\defgroup ScopedChannelValue scoped_channel_value +\ingroup ChannelModel +\brief A channel adaptor that modifies the range of the source channel. Models: ChannelValueConcept + +Example: +\code +// Create a double channel with range [-0.5 .. 0.5] +struct double_minus_half { static double apply() { return -0.5; } }; +struct double_plus_half { static double apply() { return 0.5; } }; +typedef scoped_channel_value bits64custom_t; + +// channel_convert its maximum should map to the maximum +bits64custom_t x = channel_traits::max_value(); +assert(x == 0.5); +bits16 y = channel_convert(x); +assert(y == 65535); +\endcode +*/ + +/// \ingroup ScopedChannelValue +/// \brief A channel adaptor that modifies the range of the source channel. Models: ChannelValueConcept +template // classes with a static apply() function returning the minimum/maximum channel values +struct scoped_channel_value { + typedef scoped_channel_value value_type; + typedef value_type& reference; + typedef value_type* pointer; + typedef const value_type& const_reference; + typedef const value_type* const_pointer; + BOOST_STATIC_CONSTANT(bool, is_mutable=channel_traits::is_mutable); + + static value_type min_value() { return MinVal::apply(); } + static value_type max_value() { return MaxVal::apply(); } + + scoped_channel_value() {} + scoped_channel_value(const scoped_channel_value& c) : _value(c._value) {} + scoped_channel_value(BaseChannelValue val) : _value(val) {} + + scoped_channel_value& operator++() { ++_value; return *this; } + scoped_channel_value& operator--() { --_value; return *this; } + + scoped_channel_value operator++(int) { scoped_channel_value tmp=*this; this->operator++(); return tmp; } + scoped_channel_value operator--(int) { scoped_channel_value tmp=*this; this->operator--(); return tmp; } + + template scoped_channel_value& operator+=(Scalar2 v) { _value+=v; return *this; } + template scoped_channel_value& operator-=(Scalar2 v) { _value-=v; return *this; } + template scoped_channel_value& operator*=(Scalar2 v) { _value*=v; return *this; } + template scoped_channel_value& operator/=(Scalar2 v) { _value/=v; return *this; } + + scoped_channel_value& operator=(BaseChannelValue v) { _value=v; return *this; } + operator BaseChannelValue() const { return _value; } +private: + BaseChannelValue _value; +}; + +struct float_zero { static float apply() { return 0.0f; } }; +struct float_one { static float apply() { return 1.0f; } }; + + +/////////////////////////////////////////// +//// +//// Support for sub-byte channels. These are integral channels whose value is contained in a range of bits inside an integral type +//// +/////////////////////////////////////////// + +// It is necessary for packed channels to have their own value type. They cannot simply use an integral large enough to store the data. Here is why: +// - Any operation that requires returning the result by value will otherwise return the built-in integral type, which will have incorrect range +// That means that after getting the value of the channel we cannot properly do channel_convert, channel_invert, etc. +// - Two channels are declared compatible if they have the same value type. That means that a packed channel is incorrectly declared compatible with an integral type +namespace detail { + // returns the smallest fast unsigned integral type that has at least NumBits bits + template + struct min_fast_uint : public mpl::if_c< (NumBits<=8), + uint_least8_t, + typename mpl::if_c< (NumBits<=16), + uint_least16_t, + typename mpl::if_c< (NumBits<=32), + uint_least32_t, + uintmax_t + >::type + >::type + > {}; +} + +/** +\defgroup PackedChannelValueModel packed_channel_value +\ingroup ChannelModel +\brief Represents the value of an unsigned integral channel operating over a bit range. Models: ChannelValueConcept +Example: +\code +// A 4-bit unsigned integral channel. +typedef packed_channel_value<4> bits4; + +assert(channel_traits::min_value()==0); +assert(channel_traits::max_value()==15); +assert(sizeof(bits4)==1); +BOOST_STATIC_ASSERT((boost::is_integral::value)); +\endcode +*/ + +/// \ingroup PackedChannelValueModel +/// \brief The value of a subbyte channel. Models: ChannelValueConcept +template +class packed_channel_value { + static const std::size_t num_values = 1<::type integer_t; + + typedef packed_channel_value value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* pointer; + typedef const value_type* const_pointer; + + static value_type min_value() { return value_type(0); } + static value_type max_value() { return value_type(num_values-1); } + BOOST_STATIC_CONSTANT(bool, is_mutable=true); + + packed_channel_value() {} + packed_channel_value(integer_t v) : _value(v % num_values) {} + packed_channel_value(const packed_channel_value& v) : _value(v._value) {} + template packed_channel_value(Scalar v) : _value(integer_t(v) % num_values) {} // suppress GCC implicit conversion warnings in channel regression file + + operator integer_t() const { return _value; } +private: + integer_t _value; +}; + +namespace detail { + +template +struct static_copy_bytes { + void operator()(const unsigned char* from, unsigned char* to) const { + *to = *from; + static_copy_bytes()(++from,++to); + } +}; + +template <> +struct static_copy_bytes<0> { + void operator()(const unsigned char* , unsigned char*) const {} +}; + +template +class packed_channel_reference_base { +protected: + typedef typename mpl::if_c::type data_ptr_t; +public: + data_ptr_t _data_ptr; // void* pointer to the first byte of the bit range + + typedef packed_channel_value value_type; + typedef const Derived reference; + typedef value_type* pointer; + typedef const value_type* const_pointer; + BOOST_STATIC_CONSTANT(int, num_bits=NumBits); + BOOST_STATIC_CONSTANT(bool, is_mutable=Mutable); + + static value_type min_value() { return channel_traits::min_value(); } + static value_type max_value() { return channel_traits::max_value(); } + + typedef BitField bitfield_t; + typedef typename value_type::integer_t integer_t; + + packed_channel_reference_base(data_ptr_t data_ptr) : _data_ptr(data_ptr) {} + packed_channel_reference_base(const packed_channel_reference_base& ref) : _data_ptr(ref._data_ptr) {} + const Derived& operator=(integer_t v) const { set(v); return derived(); } + + const Derived& operator++() const { set(get()+1); return derived(); } + const Derived& operator--() const { set(get()-1); return derived(); } + + Derived operator++(int) const { Derived tmp=derived(); this->operator++(); return tmp; } + Derived operator--(int) const { Derived tmp=derived(); this->operator--(); return tmp; } + + template const Derived& operator+=(Scalar2 v) const { set(get()+v); return derived(); } + template const Derived& operator-=(Scalar2 v) const { set(get()-v); return derived(); } + template const Derived& operator*=(Scalar2 v) const { set(get()*v); return derived(); } + template const Derived& operator/=(Scalar2 v) const { set(get()/v); return derived(); } + + operator integer_t() const { return get(); } + data_ptr_t operator &() const {return _data_ptr;} +protected: + static const integer_t max_val = (1<(_data_ptr); } + void set_data(const bitfield_t& val) const { *static_cast< bitfield_t*>(_data_ptr) = val; } +#else + bitfield_t get_data() const { + bitfield_t ret; + static_copy_bytes()(gil_reinterpret_cast_c(_data_ptr),gil_reinterpret_cast(&ret)); + return ret; + } + void set_data(const bitfield_t& val) const { + static_copy_bytes()(gil_reinterpret_cast_c(&val),gil_reinterpret_cast(_data_ptr)); + } +#endif + +private: + void set(integer_t value) const { // can this be done faster?? + const integer_t num_values = max_val+1; + this->derived().set_unsafe(((value % num_values) + num_values) % num_values); + } + integer_t get() const { return derived().get(); } + const Derived& derived() const { return static_cast(*this); } +}; +} // namespace detail + +/** +\defgroup PackedChannelReferenceModel packed_channel_reference +\ingroup ChannelModel +\brief Represents a reference proxy to a channel operating over a bit range whose offset is fixed at compile time. Models ChannelConcept +Example: +\code +// Reference to a 2-bit channel starting at bit 1 (i.e. the second bit) +typedef const packed_channel_reference bits2_1_ref_t; + +uint16_t data=0; +bits2_1_ref_t channel_ref(&data); +channel_ref = channel_traits::max_value(); // == 3 +assert(data == 6); // == 3<<1 == 6 +\endcode +*/ + +template // true if the reference is mutable +class packed_channel_reference; + +template // true if the reference is mutable +class packed_dynamic_channel_reference; + +/// \ingroup PackedChannelReferenceModel +/// \brief A constant subbyte channel reference whose bit offset is fixed at compile time. Models ChannelConcept +template +class packed_channel_reference + : public detail::packed_channel_reference_base,BitField,NumBits,false> { + typedef detail::packed_channel_reference_base,BitField,NumBits,false> parent_t; + friend class packed_channel_reference; + + static const BitField channel_mask = parent_t::max_val< const_reference; + typedef const packed_channel_reference mutable_reference; + typedef typename parent_t::integer_t integer_t; + + explicit packed_channel_reference(const void* data_ptr) : parent_t(data_ptr) {} + packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {} + packed_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr) {} + + unsigned first_bit() const { return FirstBit; } + + integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); } +}; + +/// \ingroup PackedChannelReferenceModel +/// \brief A mutable subbyte channel reference whose bit offset is fixed at compile time. Models ChannelConcept +template +class packed_channel_reference + : public detail::packed_channel_reference_base,BitField,NumBits,true> { + typedef detail::packed_channel_reference_base,BitField,NumBits,true> parent_t; + friend class packed_channel_reference; + + static const BitField channel_mask = parent_t::max_val< const_reference; + typedef const packed_channel_reference mutable_reference; + typedef typename parent_t::integer_t integer_t; + + explicit packed_channel_reference(void* data_ptr) : parent_t(data_ptr) {} + packed_channel_reference(const packed_channel_reference& ref) : parent_t(ref._data_ptr) {} + + const packed_channel_reference& operator=(integer_t value) const { assert(value<=parent_t::max_val); set_unsafe(value); return *this; } + const packed_channel_reference& operator=(const mutable_reference& ref) const { set_from_reference(ref.get_data()); return *this; } + const packed_channel_reference& operator=(const const_reference& ref) const { set_from_reference(ref.get_data()); return *this; } + + template + const packed_channel_reference& operator=(const packed_dynamic_channel_reference& ref) const { set_unsafe(ref.get()); return *this; } + + unsigned first_bit() const { return FirstBit; } + + integer_t get() const { return integer_t((this->get_data()&channel_mask) >> FirstBit); } + void set_unsafe(integer_t value) const { this->set_data((this->get_data() & ~channel_mask) | (value<set_data((this->get_data() & ~channel_mask) | (other_bits & channel_mask)); } +}; + +} } // namespace boost::gil + +namespace std { +// We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified. +// swap with 'left bias': +// - swap between proxy and anything +// - swap between value type and proxy +// - swap between proxy and proxy + +/// \ingroup PackedChannelReferenceModel +/// \brief swap for packed_channel_reference +template inline +void swap(const boost::gil::packed_channel_reference x, R& y) { + boost::gil::swap_proxy::value_type>(x,y); +} + + +/// \ingroup PackedChannelReferenceModel +/// \brief swap for packed_channel_reference +template inline +void swap(typename boost::gil::packed_channel_reference::value_type& x, const boost::gil::packed_channel_reference y) { + boost::gil::swap_proxy::value_type>(x,y); +} + + +/// \ingroup PackedChannelReferenceModel +/// \brief swap for packed_channel_reference +template inline +void swap(const boost::gil::packed_channel_reference x, const boost::gil::packed_channel_reference y) { + boost::gil::swap_proxy::value_type>(x,y); +} +} // namespace std + +namespace boost { namespace gil { + +/** +\defgroup PackedChannelDynamicReferenceModel packed_dynamic_channel_reference +\ingroup ChannelModel +\brief Represents a reference proxy to a channel operating over a bit range whose offset is specified at run time. Models ChannelConcept + +Example: +\code +// Reference to a 2-bit channel whose offset is specified at construction time +typedef const packed_dynamic_channel_reference bits2_dynamic_ref_t; + +uint16_t data=0; +bits2_dynamic_ref_t channel_ref(&data,1); +channel_ref = channel_traits::max_value(); // == 3 +assert(data == 6); // == (3<<1) == 6 +\endcode +*/ + +/// \brief Models a constant subbyte channel reference whose bit offset is a runtime parameter. Models ChannelConcept +/// Same as packed_channel_reference, except that the offset is a runtime parameter +/// \ingroup PackedChannelDynamicReferenceModel +template +class packed_dynamic_channel_reference + : public detail::packed_channel_reference_base,BitField,NumBits,false> { + typedef detail::packed_channel_reference_base,BitField,NumBits,false> parent_t; + friend class packed_dynamic_channel_reference; + + unsigned _first_bit; // 0..7 + + void operator=(const packed_dynamic_channel_reference&); +public: + typedef const packed_dynamic_channel_reference const_reference; + typedef const packed_dynamic_channel_reference mutable_reference; + typedef typename parent_t::integer_t integer_t; + + packed_dynamic_channel_reference(const void* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {} + packed_dynamic_channel_reference(const const_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {} + packed_dynamic_channel_reference(const mutable_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {} + + unsigned first_bit() const { return _first_bit; } + + integer_t get() const { + const BitField channel_mask = parent_t::max_val<<_first_bit; + return (this->get_data()&channel_mask) >> _first_bit; + } +}; + +/// \brief Models a mutable subbyte channel reference whose bit offset is a runtime parameter. Models ChannelConcept +/// Same as packed_channel_reference, except that the offset is a runtime parameter +/// \ingroup PackedChannelDynamicReferenceModel +template +class packed_dynamic_channel_reference + : public detail::packed_channel_reference_base,BitField,NumBits,true> { + typedef detail::packed_channel_reference_base,BitField,NumBits,true> parent_t; + friend class packed_dynamic_channel_reference; + + unsigned _first_bit; + +public: + typedef const packed_dynamic_channel_reference const_reference; + typedef const packed_dynamic_channel_reference mutable_reference; + typedef typename parent_t::integer_t integer_t; + + packed_dynamic_channel_reference(void* data_ptr, unsigned first_bit) : parent_t(data_ptr), _first_bit(first_bit) {} + packed_dynamic_channel_reference(const packed_dynamic_channel_reference& ref) : parent_t(ref._data_ptr), _first_bit(ref._first_bit) {} + + const packed_dynamic_channel_reference& operator=(integer_t value) const { assert(value<=parent_t::max_val); set_unsafe(value); return *this; } + const packed_dynamic_channel_reference& operator=(const mutable_reference& ref) const { set_unsafe(ref.get()); return *this; } + const packed_dynamic_channel_reference& operator=(const const_reference& ref) const { set_unsafe(ref.get()); return *this; } + + template + const packed_dynamic_channel_reference& operator=(const packed_channel_reference& ref) const + { set_unsafe(ref.get()); return *this; } + + unsigned first_bit() const { return _first_bit; } + + integer_t get() const { + const BitField channel_mask = parent_t::max_val<<_first_bit; + return (this->get_data()&channel_mask) >> _first_bit; + } + void set_unsafe(integer_t value) const { + const BitField channel_mask = parent_t::max_val<<_first_bit; + this->set_data((this->get_data() & ~channel_mask) | value<<_first_bit); + } +}; +} } // namespace boost::gil + +namespace std { +// We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified. +// swap with 'left bias': +// - swap between proxy and anything +// - swap between value type and proxy +// - swap between proxy and proxy + + +/// \ingroup PackedChannelDynamicReferenceModel +/// \brief swap for packed_dynamic_channel_reference +template inline +void swap(const boost::gil::packed_dynamic_channel_reference x, R& y) { + boost::gil::swap_proxy::value_type>(x,y); +} + + +/// \ingroup PackedChannelDynamicReferenceModel +/// \brief swap for packed_dynamic_channel_reference +template inline +void swap(typename boost::gil::packed_dynamic_channel_reference::value_type& x, const boost::gil::packed_dynamic_channel_reference y) { + boost::gil::swap_proxy::value_type>(x,y); +} + + +/// \ingroup PackedChannelDynamicReferenceModel +/// \brief swap for packed_dynamic_channel_reference +template inline +void swap(const boost::gil::packed_dynamic_channel_reference x, const boost::gil::packed_dynamic_channel_reference y) { + boost::gil::swap_proxy::value_type>(x,y); +} +} // namespace std + +namespace boost { namespace gil { +/////////////////////////////////////////// +//// +//// Built-in channel models +//// +/////////////////////////////////////////// + +/// \defgroup bits8 bits8 +/// \ingroup ChannelModel +/// \brief 8-bit unsigned integral channel type (typedef from uint8_t). Models ChannelValueConcept + +/// \ingroup bits8 +typedef uint8_t bits8; + +/// \defgroup bits16 bits16 +/// \ingroup ChannelModel +/// \brief 16-bit unsigned integral channel type (typedef from uint16_t). Models ChannelValueConcept + +/// \ingroup bits16 +typedef uint16_t bits16; + +/// \defgroup bits32 bits32 +/// \ingroup ChannelModel +/// \brief 32-bit unsigned integral channel type (typedef from uint32_t). Models ChannelValueConcept + +/// \ingroup bits32 +typedef uint32_t bits32; + +/// \defgroup bits8s bits8s +/// \ingroup ChannelModel +/// \brief 8-bit signed integral channel type (typedef from int8_t). Models ChannelValueConcept + +/// \ingroup bits8s +typedef int8_t bits8s; + +/// \defgroup bits16s bits16s +/// \ingroup ChannelModel +/// \brief 16-bit signed integral channel type (typedef from int16_t). Models ChannelValueConcept + +/// \ingroup bits16s +typedef int16_t bits16s; + +/// \defgroup bits32s bits32s +/// \ingroup ChannelModel +/// \brief 32-bit signed integral channel type (typedef from int32_t). Models ChannelValueConcept + +/// \ingroup bits32s +typedef int32_t bits32s; + +/// \defgroup bits32f bits32f +/// \ingroup ChannelModel +/// \brief 32-bit floating point channel type with range [0.0f ... 1.0f]. Models ChannelValueConcept + +/// \ingroup bits32f +typedef scoped_channel_value bits32f; + +} } // namespace boost::gil + +namespace boost { + +template +struct is_integral > : public mpl::true_ {}; + +template +struct is_integral > : public mpl::true_ {}; + +template +struct is_integral > : public mpl::true_ {}; + +template +struct is_integral > : public is_integral {}; + +} + +#endif diff --git a/win32/include/boost/gil/channel_algorithm.hpp b/win32/include/boost/gil/channel_algorithm.hpp new file mode 100755 index 000000000..965826d0a --- /dev/null +++ b/win32/include/boost/gil/channel_algorithm.hpp @@ -0,0 +1,469 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ +/*************************************************************************************************/ + +#ifndef GIL_CHANNEL_ALGORITHM_HPP +#define GIL_CHANNEL_ALGORITHM_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Channel algorithms +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on May 6, 2007 +/// +/// Definitions of standard GIL 8-bit, 16-bit, 32-bit channels +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include "gil_config.hpp" +#include "channel.hpp" +#include +#include +#include +#include + +namespace boost { namespace gil { + +//#ifdef _MSC_VER +//#pragma warning(push) +//#pragma warning(disable: 4309) // disable truncation of constant value warning (using -1 to get the max value of an integral) +//#endif + +namespace detail { + +// some forward declarations +template struct channel_converter_unsigned_impl; +template struct channel_converter_unsigned_integral; +template struct channel_converter_unsigned_integral_impl; +template struct channel_converter_unsigned_integral_nondivisible; + +////////////////////////////////////// +//// unsigned_integral_max_value - given an unsigned integral channel type, returns its maximum value as an MPL integral constant +////////////////////////////////////// + + +template +struct unsigned_integral_max_value : public mpl::integral_c {}; + +template <> +struct unsigned_integral_max_value : public mpl::integral_c {}; +template <> +struct unsigned_integral_max_value : public mpl::integral_c {}; +template <> +struct unsigned_integral_max_value : public mpl::integral_c {}; + + +template +struct unsigned_integral_max_value > + : public mpl::integral_c::integer_t, (1< {}; + +////////////////////////////////////// +//// unsigned_integral_num_bits - given an unsigned integral channel type, returns the minimum number of bits needed to represent it +////////////////////////////////////// + +template +struct unsigned_integral_num_bits : public mpl::int_ {}; + +template +struct unsigned_integral_num_bits > + : public mpl::int_ {}; + +} // namespace detail + +/** +\defgroup ChannelConvertAlgorithm channel_convert +\brief Converting from one channel type to another +\ingroup ChannelAlgorithm + +Conversion is done as a simple linear mapping of one channel range to the other, +such that the minimum/maximum value of the source maps to the minimum/maximum value of the destination. +One implication of this is that the value 0 of signed channels may not be preserved! + +When creating new channel models, it is often a good idea to provide specializations for the channel conversion algorithms, for +example, for performance optimizations. If the new model is an integral type that can be signed, it is easier to define the conversion +only for the unsigned type (\p channel_converter_unsigned) and provide specializations of \p detail::channel_convert_to_unsigned +and \p detail::channel_convert_from_unsigned to convert between the signed and unsigned type. + +Example: +\code +// bits32f is a floating point channel with range [0.0f ... 1.0f] +bits32f src_channel = channel_traits::max_value(); +assert(src_channel == 1); + +// bits8 is 8-bit unsigned integral channel (typedef-ed from unsigned char) +bits8 dst_channel = channel_convert(src_channel); +assert(dst_channel == 255); // max value goes to max value +\endcode +*/ + +/** +\defgroup ChannelConvertUnsignedAlgorithm channel_converter_unsigned +\ingroup ChannelConvertAlgorithm +\brief Convert one unsigned/floating point channel to another. Converts both the channel type and range + @{ + */ + +////////////////////////////////////// +//// channel_converter_unsigned +////////////////////////////////////// + +template // Model ChannelValueConcept +struct channel_converter_unsigned + : public detail::channel_converter_unsigned_impl::value,is_integral::value> {}; + + +/// \brief Converting a channel to itself - identity operation +template struct channel_converter_unsigned : public detail::identity {}; + + +namespace detail { + +////////////////////////////////////// +//// channel_converter_unsigned_impl +////////////////////////////////////// + +/// \brief This is the default implementation. Performance specializatons are provided +template +struct channel_converter_unsigned_impl : public std::unary_function { + DstChannelV operator()(SrcChannelV src) const { + return DstChannelV(channel_traits::min_value() + + (src - channel_traits::min_value()) / channel_range() * channel_range()); + } +private: + template + static double channel_range() { + return double(channel_traits::max_value()) - double(channel_traits::min_value()); + } +}; + +// When both the source and the destination are integral channels, perform a faster conversion +template +struct channel_converter_unsigned_impl + : public channel_converter_unsigned_integral,unsigned_integral_max_value >::value > {}; + + +////////////////////////////////////// +//// channel_converter_unsigned_integral +////////////////////////////////////// + +template +struct channel_converter_unsigned_integral + : public channel_converter_unsigned_integral_impl::value % unsigned_integral_max_value::value) > {}; + +template +struct channel_converter_unsigned_integral + : public channel_converter_unsigned_integral_impl::value % unsigned_integral_max_value::value) > {}; + + +////////////////////////////////////// +//// channel_converter_unsigned_integral_impl +////////////////////////////////////// + +// Both source and destination are unsigned integral channels, +// the src max value is less than the dst max value, +// and the dst max value is divisible by the src max value +template +struct channel_converter_unsigned_integral_impl { + DstChannelV operator()(SrcChannelV src) const { + typedef typename unsigned_integral_max_value::value_type integer_t; + static const integer_t mul = unsigned_integral_max_value::value / unsigned_integral_max_value::value; + return DstChannelV(src * mul); + } +}; + +// Both source and destination are unsigned integral channels, +// the dst max value is less than (or equal to) the src max value, +// and the src max value is divisible by the dst max value +template +struct channel_converter_unsigned_integral_impl { + DstChannelV operator()(SrcChannelV src) const { + typedef typename unsigned_integral_max_value::value_type integer_t; + static const integer_t div = unsigned_integral_max_value::value / unsigned_integral_max_value::value; + static const integer_t div2 = div/2; + return DstChannelV((src + div2) / div); + } +}; + +// Prevent overflow for the largest integral type +template +struct channel_converter_unsigned_integral_impl { + DstChannelV operator()(uintmax_t src) const { + static const uintmax_t div = unsigned_integral_max_value::value / unsigned_integral_max_value::value; + static const uintmax_t div2 = div/2; + if (src > unsigned_integral_max_value::value - div2) + return unsigned_integral_max_value::value; + return DstChannelV((src + div2) / div); + } +}; + +// Both source and destination are unsigned integral channels, +// and the dst max value is not divisible by the src max value +// See if you can represent the expression (src * dst_max) / src_max in integral form +template +struct channel_converter_unsigned_integral_impl + : public channel_converter_unsigned_integral_nondivisible,unsigned_integral_num_bits >, + unsigned_integral_num_bits + >::value> {}; + + +// Both source and destination are unsigned integral channels, +// the src max value is less than the dst max value, +// and the dst max value is not divisible by the src max value +// The expression (src * dst_max) / src_max fits in an integer +template +struct channel_converter_unsigned_integral_nondivisible { + DstChannelV operator()(SrcChannelV src) const { + typedef typename detail::min_fast_uint::value+unsigned_integral_num_bits::value>::type integer_t; + return DstChannelV(integer_t(src * unsigned_integral_max_value::value) / unsigned_integral_max_value::value); + } +}; + +// Both source and destination are unsigned integral channels, +// the src max value is less than the dst max value, +// and the dst max value is not divisible by the src max value +// The expression (src * dst_max) / src_max cannot fit in an integer (overflows). Use a double +template +struct channel_converter_unsigned_integral_nondivisible { + DstChannelV operator()(SrcChannelV src) const { + static const double mul = unsigned_integral_max_value::value / double(unsigned_integral_max_value::value); + return DstChannelV(src * mul); + } +}; + + +// Both source and destination are unsigned integral channels, +// the dst max value is less than (or equal to) the src max value, +// and the src max value is not divisible by the dst max value +template +struct channel_converter_unsigned_integral_nondivisible { + DstChannelV operator()(SrcChannelV src) const { + typedef typename unsigned_integral_max_value::value_type integer_t; + + static const double div = unsigned_integral_max_value::value / double(unsigned_integral_max_value::value); + static const integer_t div2 = integer_t(div/2); + return DstChannelV((src + div2) / div); + } +}; + +} // namespace detail + +///////////////////////////////////////////////////// +/// bits32f conversion +///////////////////////////////////////////////////// + +template struct channel_converter_unsigned : public std::unary_function { + DstChannelV operator()(bits32f x) const { return DstChannelV(x*channel_traits::max_value()+0.5f); } +}; + +template struct channel_converter_unsigned : public std::unary_function { + bits32f operator()(SrcChannelV x) const { return bits32f(x/float(channel_traits::max_value())); } +}; + +template <> struct channel_converter_unsigned : public std::unary_function { + bits32f operator()(bits32f x) const { return x; } +}; + + +/// \brief 32 bit <-> float channel conversion +template <> struct channel_converter_unsigned : public std::unary_function { + bits32f operator()(bits32 x) const { + // unfortunately without an explicit check it is possible to get a round-off error. We must ensure that max_value of bits32 matches max_value of bits32f + if (x>=channel_traits::max_value()) return channel_traits::max_value(); + return float(x) / float(channel_traits::max_value()); + } +}; +/// \brief 32 bit <-> float channel conversion +template <> struct channel_converter_unsigned : public std::unary_function { + bits32 operator()(bits32f x) const { + // unfortunately without an explicit check it is possible to get a round-off error. We must ensure that max_value of bits32 matches max_value of bits32f + if (x>=channel_traits::max_value()) return channel_traits::max_value(); + return bits32(x * channel_traits::max_value() + 0.5f); + } +}; + +/// @} + +namespace detail { +// Converting from signed to unsigned integral channel. +// It is both a unary function, and a metafunction (thus requires the 'type' nested typedef, which equals result_type) +template // Model ChannelValueConcept +struct channel_convert_to_unsigned : public detail::identity { + typedef ChannelValue type; +}; + +template <> struct channel_convert_to_unsigned : public std::unary_function { + typedef bits8 type; + type operator()(bits8s val) const { return val+128; } +}; + +template <> struct channel_convert_to_unsigned : public std::unary_function { + typedef bits16 type; + type operator()(bits16s val) const { return val+32768; } +}; + +template <> struct channel_convert_to_unsigned : public std::unary_function { + typedef bits32 type; + type operator()(bits32s x) const { return static_cast(x+(1<<31)); } +}; + + +// Converting from unsigned to signed integral channel +// It is both a unary function, and a metafunction (thus requires the 'type' nested typedef, which equals result_type) +template // Model ChannelValueConcept +struct channel_convert_from_unsigned : public detail::identity { + typedef ChannelValue type; +}; + +template <> struct channel_convert_from_unsigned : public std::unary_function { + typedef bits8s type; + type operator()(bits8 val) const { return val-128; } +}; + +template <> struct channel_convert_from_unsigned : public std::unary_function { + typedef bits16s type; + type operator()(bits16 val) const { return val-32768; } +}; + +template <> struct channel_convert_from_unsigned : public std::unary_function { + typedef bits32s type; + type operator()(bits32 x) const { return static_cast(x-(1<<31)); } +}; + +} // namespace detail + +/// \ingroup ChannelConvertAlgorithm +/// \brief A unary function object converting between channel types +template // Model ChannelValueConcept +struct channel_converter : public std::unary_function { + DstChannelV operator()(SrcChannelV src) const { + typedef detail::channel_convert_to_unsigned to_unsigned; + typedef detail::channel_convert_from_unsigned from_unsigned; + typedef channel_converter_unsigned converter_unsigned; + return from_unsigned()(converter_unsigned()(to_unsigned()(src))); + } +}; + +/// \ingroup ChannelConvertAlgorithm +/// \brief Converting from one channel type to another. +template // Model ChannelConcept (could be channel references) +inline typename channel_traits::value_type channel_convert(SrcChannel src) { + return channel_converter::value_type, + typename channel_traits::value_type>()(src); +} + +/// \ingroup ChannelConvertAlgorithm +/// \brief Same as channel_converter, except it takes the destination channel by reference, which allows +/// us to move the templates from the class level to the method level. This is important when invoking it +/// on heterogeneous pixels. +struct default_channel_converter { + template + void operator()(const Ch1& src, Ch2& dst) const { + dst=channel_convert(src); + } +}; + +namespace detail { + // fast integer division by 255 + inline uint32_t div255(uint32_t in) { uint32_t tmp=in+128; return (tmp + (tmp>>8))>>8; } + + // fast integer divison by 32768 + inline uint32_t div32768(uint32_t in) { return (in+16384)>>15; } +} + +/** +\defgroup ChannelMultiplyAlgorithm channel_multiply +\ingroup ChannelAlgorithm +\brief Multiplying unsigned channel values of the same type. Performs scaled multiplication result = a * b / max_value + +Example: +\code +bits8 x=128; +bits8 y=128; +bits8 mul = channel_multiply(x,y); +assert(mul == 64); // 64 = 128 * 128 / 255 +\endcode +*/ +/// @{ + +/// \brief This is the default implementation. Performance specializatons are provided +template +struct channel_multiplier_unsigned : public std::binary_function { + ChannelValue operator()(ChannelValue a, ChannelValue b) const { + return ChannelValue(a / double(channel_traits::max_value()) * b); + } +}; + +/// \brief Specialization of channel_multiply for 8-bit unsigned channels +template<> struct channel_multiplier_unsigned : public std::binary_function { + bits8 operator()(bits8 a, bits8 b) const { return bits8(detail::div255(uint32_t(a) * uint32_t(b))); } +}; + +/// \brief Specialization of channel_multiply for 16-bit unsigned channels +template<> struct channel_multiplier_unsigned : public std::binary_function { + bits16 operator()(bits16 a, bits16 b) const { return bits16((uint32_t(a) * uint32_t(b))/65535); } +}; + +/// \brief Specialization of channel_multiply for float 0..1 channels +template<> struct channel_multiplier_unsigned : public std::binary_function { + bits32f operator()(bits32f a, bits32f b) const { return a*b; } +}; + +/// \brief A function object to multiply two channels. result = a * b / max_value +template +struct channel_multiplier : public std::binary_function { + ChannelValue operator()(ChannelValue a, ChannelValue b) const { + typedef detail::channel_convert_to_unsigned to_unsigned; + typedef detail::channel_convert_from_unsigned from_unsigned; + typedef channel_multiplier_unsigned multiplier_unsigned; + return from_unsigned()(multiplier_unsigned()(to_unsigned()(a), to_unsigned()(b))); + } +}; + +/// \brief A function multiplying two channels. result = a * b / max_value +template // Models ChannelConcept (could be a channel reference) +inline typename channel_traits::value_type channel_multiply(Channel a, Channel b) { + return channel_multiplier::value_type>()(a,b); +} +/// @} + +/** +\defgroup ChannelInvertAlgorithm channel_invert +\ingroup ChannelAlgorithm +\brief Returns the inverse of a channel. result = max_value - x + min_value + +Example: +\code +// bits8 == uint8_t == unsigned char +bits8 x=255; +bits8 inv = channel_invert(x); +assert(inv == 0); +\endcode +*/ + +/// \brief Default implementation. Provide overloads for performance +/// \ingroup ChannelInvertAlgorithm channel_invert +template // Models ChannelConcept (could be a channel reference) +inline typename channel_traits::value_type channel_invert(Channel x) { + return channel_traits::max_value()-x + channel_traits::min_value(); +} + +//#ifdef _MSC_VER +//#pragma warning(pop) +//#endif + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/cmyk.hpp b/win32/include/boost/gil/cmyk.hpp new file mode 100755 index 000000000..e7e163e02 --- /dev/null +++ b/win32/include/boost/gil/cmyk.hpp @@ -0,0 +1,66 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_CMYK_H +#define GIL_CMYK_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Support for CMYK color space and variants +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on October 10, 2007 +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include "gil_config.hpp" +#include "metafunctions.hpp" +#include +#include + +namespace boost { namespace gil { + + +/// \addtogroup ColorNameModel +/// \{ + +/// \brief Cyan +struct cyan_t {}; + +/// \brief Magenta +struct magenta_t {}; + +/// \brief Yellow +struct yellow_t {}; + +/// \brief Black +struct black_t {}; +/// \} + +/// \ingroup ColorSpaceModel +typedef mpl::vector4 cmyk_t; + +/// \ingroup LayoutModel +typedef layout cmyk_layout_t; + +/// \ingroup ImageViewConstructors +/// \brief from raw CMYK planar data +template +inline typename type_from_x_iterator >::view_t +planar_cmyk_view(std::size_t width, std::size_t height, IC c, IC m, IC y, IC k, std::ptrdiff_t rowsize_in_bytes) { + typedef typename type_from_x_iterator >::view_t RView; + return RView(width, height, typename RView::locator(planar_pixel_iterator(c,m,y,k), rowsize_in_bytes)); +} + +} } // namespace gil + +#endif diff --git a/win32/include/boost/gil/color_base.hpp b/win32/include/boost/gil/color_base.hpp new file mode 100755 index 000000000..5bdc3777a --- /dev/null +++ b/win32/include/boost/gil/color_base.hpp @@ -0,0 +1,410 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://stlab.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_COLOR_BASE_HPP +#define GIL_COLOR_BASE_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief pixel class and related utilities +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on May 6, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +#include "gil_config.hpp" +#include "utilities.hpp" +#include "gil_concept.hpp" + +namespace boost { namespace gil { + +// Forward-declare +template P* memunit_advanced(const P* p, std::ptrdiff_t diff); + +// Forward-declare semantic_at_c +template +typename disable_if,typename kth_semantic_element_reference_type::type>::type semantic_at_c(ColorBase& p); +template +typename kth_semantic_element_const_reference_type::type semantic_at_c(const ColorBase& p); + +// Forward declare element_reference_type +template struct element_reference_type; +template struct element_const_reference_type; +template struct kth_element_type; +template struct kth_element_type : public kth_element_type {}; +template struct kth_element_reference_type; +template struct kth_element_reference_type : public kth_element_reference_type {}; +template struct kth_element_const_reference_type; +template struct kth_element_const_reference_type : public kth_element_const_reference_type {}; + +namespace detail { + +template +struct mapping_transform + : public mpl::at >::type + >::type {}; + +/// \defgroup ColorBaseModelHomogeneous detail::homogeneous_color_base +/// \ingroup ColorBaseModel +/// \brief A homogeneous color base holding one color element. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept +/// If the element type models Regular, this class models HomogeneousColorBaseValueConcept. + + +/// \brief A homogeneous color base holding one color element. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept +/// \ingroup ColorBaseModelHomogeneous +template +struct homogeneous_color_base { +private: + Element _v0; +public: + typedef Layout layout_t; + typename element_reference_type::type at(mpl::int_<0>) { return _v0; } + typename element_const_reference_type::type at(mpl::int_<0>) const { return _v0; } + + homogeneous_color_base() {} + homogeneous_color_base(Element v) : _v0(v) {} + + // grayscale pixel values are convertible to channel type + operator Element () const { return _v0; } + + template homogeneous_color_base(const homogeneous_color_base& c) : _v0(at_c<0>(c)) {} +}; + + +/// \brief A homogeneous color base holding two color elements. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept +/// \ingroup ColorBaseModelHomogeneous +template +struct homogeneous_color_base { +private: + Element _v0, _v1; +public: + typedef Layout layout_t; + typename element_reference_type::type at(mpl::int_<0>) { return _v0; } + typename element_const_reference_type::type at(mpl::int_<0>) const { return _v0; } + typename element_reference_type::type at(mpl::int_<1>) { return _v1; } + typename element_const_reference_type::type at(mpl::int_<1>) const { return _v1; } + + homogeneous_color_base() {} + explicit homogeneous_color_base(Element v) : _v0(v), _v1(v) {} + homogeneous_color_base(Element v0, Element v1) : _v0(v0), _v1(v1) {} + + template homogeneous_color_base(const homogeneous_color_base& c) : + _v0(at_c::value>(c)), + _v1(at_c::value>(c)) {} + + // Support for l-value reference proxy copy construction + template homogeneous_color_base( homogeneous_color_base& c) : + _v0(at_c::value>(c)), + _v1(at_c::value>(c)) {} + + // Support for planar_pixel_iterator construction and dereferencing + template homogeneous_color_base(P* p,bool) : + _v0(&semantic_at_c<0>(*p)), + _v1(&semantic_at_c<1>(*p)) {} + template Ref deref() const { + return Ref(*semantic_at_c<0>(*this), + *semantic_at_c<1>(*this)); } + + // Support for planar_pixel_reference offset constructor + template homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff) + : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)), + _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)) {} + + // Support for planar_pixel_reference operator[] + Element at_c_dynamic(std::size_t i) const { + if (i==0) return _v0; + return _v1; + } +}; + +/// \brief A homogeneous color base holding three color elements. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept +/// \ingroup ColorBaseModelHomogeneous +template +struct homogeneous_color_base { +private: + Element _v0, _v1, _v2; +public: + typedef Layout layout_t; + typename element_reference_type::type at(mpl::int_<0>) { return _v0; } + typename element_const_reference_type::type at(mpl::int_<0>) const { return _v0; } + typename element_reference_type::type at(mpl::int_<1>) { return _v1; } + typename element_const_reference_type::type at(mpl::int_<1>) const { return _v1; } + typename element_reference_type::type at(mpl::int_<2>) { return _v2; } + typename element_const_reference_type::type at(mpl::int_<2>) const { return _v2; } + + homogeneous_color_base() {} + explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v) {} + homogeneous_color_base(Element v0, Element v1, Element v2) : _v0(v0), _v1(v1), _v2(v2) {} + + template homogeneous_color_base(const homogeneous_color_base& c) : + _v0(at_c::value>(c)), + _v1(at_c::value>(c)), + _v2(at_c::value>(c)) {} + + // Support for l-value reference proxy copy construction + template homogeneous_color_base( homogeneous_color_base& c) : + _v0(at_c::value>(c)), + _v1(at_c::value>(c)), + _v2(at_c::value>(c)) {} + + // Support for planar_pixel_iterator construction and dereferencing + template homogeneous_color_base(P* p,bool) : + _v0(&semantic_at_c<0>(*p)), + _v1(&semantic_at_c<1>(*p)), + _v2(&semantic_at_c<2>(*p)) {} + template Ref deref() const { + return Ref(*semantic_at_c<0>(*this), + *semantic_at_c<1>(*this), + *semantic_at_c<2>(*this)); } + + // Support for planar_pixel_reference offset constructor + template homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff) + : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)), + _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)), + _v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)) {} + + // Support for planar_pixel_reference operator[] + Element at_c_dynamic(std::size_t i) const { + switch (i) { + case 0: return _v0; + case 1: return _v1; + } + return _v2; + } +}; + +/// \brief A homogeneous color base holding four color elements. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept +/// \ingroup ColorBaseModelHomogeneous +template +struct homogeneous_color_base { +private: + Element _v0, _v1, _v2, _v3; +public: + typedef Layout layout_t; + typename element_reference_type::type at(mpl::int_<0>) { return _v0; } + typename element_const_reference_type::type at(mpl::int_<0>) const { return _v0; } + typename element_reference_type::type at(mpl::int_<1>) { return _v1; } + typename element_const_reference_type::type at(mpl::int_<1>) const { return _v1; } + typename element_reference_type::type at(mpl::int_<2>) { return _v2; } + typename element_const_reference_type::type at(mpl::int_<2>) const { return _v2; } + typename element_reference_type::type at(mpl::int_<3>) { return _v3; } + typename element_const_reference_type::type at(mpl::int_<3>) const { return _v3; } + homogeneous_color_base() {} + explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v), _v3(v) {} + homogeneous_color_base(Element v0, Element v1, Element v2, Element v3) : _v0(v0), _v1(v1), _v2(v2), _v3(v3) {} + + template homogeneous_color_base(const homogeneous_color_base& c) : + _v0(at_c::value>(c)), + _v1(at_c::value>(c)), + _v2(at_c::value>(c)), + _v3(at_c::value>(c)) {} + + // Support for l-value reference proxy copy construction + template homogeneous_color_base( homogeneous_color_base& c) : + _v0(at_c::value>(c)), + _v1(at_c::value>(c)), + _v2(at_c::value>(c)), + _v3(at_c::value>(c)) {} + + // Support for planar_pixel_iterator construction and dereferencing + template homogeneous_color_base(P* p,bool) : + _v0(&semantic_at_c<0>(*p)), + _v1(&semantic_at_c<1>(*p)), + _v2(&semantic_at_c<2>(*p)), + _v3(&semantic_at_c<3>(*p)) {} + + template Ref deref() const { + return Ref(*semantic_at_c<0>(*this), + *semantic_at_c<1>(*this), + *semantic_at_c<2>(*this), + *semantic_at_c<3>(*this)); } + + // Support for planar_pixel_reference offset constructor + template homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff) + : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)), + _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)), + _v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)), + _v3(*memunit_advanced(semantic_at_c<3>(ptr),diff)) {} + + // Support for planar_pixel_reference operator[] + Element at_c_dynamic(std::size_t i) const { + switch (i) { + case 0: return _v0; + case 1: return _v1; + case 2: return _v2; + } + return _v3; + } +}; + +/// \brief A homogeneous color base holding five color elements. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept +/// \ingroup ColorBaseModelHomogeneous +template +struct homogeneous_color_base { +private: + Element _v0, _v1, _v2, _v3, _v4; +public: + typedef Layout layout_t; + typename element_reference_type::type at(mpl::int_<0>) { return _v0; } + typename element_const_reference_type::type at(mpl::int_<0>) const { return _v0; } + typename element_reference_type::type at(mpl::int_<1>) { return _v1; } + typename element_const_reference_type::type at(mpl::int_<1>) const { return _v1; } + typename element_reference_type::type at(mpl::int_<2>) { return _v2; } + typename element_const_reference_type::type at(mpl::int_<2>) const { return _v2; } + typename element_reference_type::type at(mpl::int_<3>) { return _v3; } + typename element_const_reference_type::type at(mpl::int_<3>) const { return _v3; } + typename element_reference_type::type at(mpl::int_<4>) { return _v4; } + typename element_const_reference_type::type at(mpl::int_<4>) const { return _v4; } + homogeneous_color_base() {} + explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v), _v3(v), _v4(v) {} + homogeneous_color_base(Element v0, Element v1, Element v2, Element v3, Element v4) : _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4) {} + + template homogeneous_color_base(const homogeneous_color_base& c) : + _v0(at_c::value>(c)), + _v1(at_c::value>(c)), + _v2(at_c::value>(c)), + _v3(at_c::value>(c)), + _v4(at_c::value>(c)) {} + + // Support for l-value reference proxy copy construction + template homogeneous_color_base( homogeneous_color_base& c) : + _v0(at_c::value>(c)), + _v1(at_c::value>(c)), + _v2(at_c::value>(c)), + _v3(at_c::value>(c)), + _v4(at_c::value>(c)) {} + + // Support for planar_pixel_iterator construction and dereferencing + template homogeneous_color_base(P* p,bool) : + _v0(&semantic_at_c<0>(*p)), + _v1(&semantic_at_c<1>(*p)), + _v2(&semantic_at_c<2>(*p)), + _v3(&semantic_at_c<3>(*p)), + _v4(&semantic_at_c<4>(*p)) {} + + template Ref deref() const { + return Ref(*semantic_at_c<0>(*this), + *semantic_at_c<1>(*this), + *semantic_at_c<2>(*this), + *semantic_at_c<3>(*this), + *semantic_at_c<4>(*this)); } + + // Support for planar_pixel_reference offset constructor + template homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff) + : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)), + _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)), + _v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)), + _v3(*memunit_advanced(semantic_at_c<3>(ptr),diff)), + _v4(*memunit_advanced(semantic_at_c<4>(ptr),diff)) {} + + // Support for planar_pixel_reference operator[] + Element at_c_dynamic(std::size_t i) const { + switch (i) { + case 0: return _v0; + case 1: return _v1; + case 2: return _v2; + case 3: return _v3; + } + return _v4; + } +}; + +// The following way of casting adjacent channels (the contents of color_base) into an array appears to be unsafe +// -- there is no guarantee that the compiler won't add any padding between adjacent channels. +// Note, however, that GIL _must_ be compiled with compiler settings ensuring there is no padding in the color base structs. +// This is because the color base structs must model the interleaved organization in memory. In other words, the client may +// have existing RGB image in the form "RGBRGBRGB..." and we must be able to represent it with an array of RGB color bases (i.e. RGB pixels) +// with no padding. We have tested with char/int/float/double channels on gcc and VC and have so far discovered no problem. +// We have even tried using strange channels consisting of short + char (3 bytes). With the default 4-byte alignment on VC, the size +// of this channel is padded to 4 bytes, so an RGB pixel of it will be 4x3=12 bytes. The code below will still work properly. +// However, the client must nevertheless ensure that proper compiler settings are used for their compiler and their channel types. + +template +typename element_reference_type >::type +dynamic_at_c(homogeneous_color_base& cb, std::size_t i) { + assert(i(&cb))[i]; +} + +template +typename element_const_reference_type >::type +dynamic_at_c(const homogeneous_color_base& cb, std::size_t i) { + assert(i(&cb))[i]; +} + +template +typename element_reference_type >::type +dynamic_at_c(const homogeneous_color_base& cb, std::size_t i) { + assert(i +typename element_const_reference_type >::type +dynamic_at_c(const homogeneous_color_base& cb, std::size_t i) { + assert(i +struct kth_element_type, K> { + typedef Element type; +}; + +template +struct kth_element_reference_type, K> : public add_reference {}; + +template +struct kth_element_const_reference_type, K> : public add_reference::type> {}; + +/// \brief Provides mutable access to the K-th element, in physical order +/// \ingroup ColorBaseModelHomogeneous +template inline +typename add_reference::type +at_c( detail::homogeneous_color_base& p) { return p.at(mpl::int_()); } + +/// \brief Provides constant access to the K-th element, in physical order +/// \ingroup ColorBaseModelHomogeneous +template inline +typename add_reference::type>::type +at_c(const detail::homogeneous_color_base& p) { return p.at(mpl::int_()); } + +namespace detail { + struct swap_fn { + template void operator()(T& x, T& y) const { + using std::swap; + swap(x,y); + } + }; +} +template inline +void swap(detail::homogeneous_color_base& x, detail::homogeneous_color_base& y) { + static_for_each(x,y,detail::swap_fn()); +} + + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/color_base_algorithm.hpp b/win32/include/boost/gil/color_base_algorithm.hpp new file mode 100755 index 000000000..00edca5d2 --- /dev/null +++ b/win32/include/boost/gil/color_base_algorithm.hpp @@ -0,0 +1,696 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_COLOR_BASE_ALGORITHM_HPP +#define GIL_COLOR_BASE_ALGORITHM_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief pixel related algorithms +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on February 16, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "gil_config.hpp" +#include "gil_concept.hpp" +#include "utilities.hpp" + +namespace boost { namespace gil { + + +/////////////////////////////////////// +/// +/// size: Semantic channel size +/// +/////////////////////////////////////// + +/** +\defgroup ColorBaseAlgorithmSize size +\ingroup ColorBaseAlgorithm +\brief Returns an MPL integral type specifying the number of elements in a color base + +Example: +\code +BOOST_STATIC_ASSERT((size::value == 3)); +BOOST_STATIC_ASSERT((size::value == 4)); +\endcode +*/ + +/// \brief Returns an MPL integral type specifying the number of elements in a color base +/// \ingroup ColorBaseAlgorithmSize +template +struct size : public mpl::size {}; + +/////////////////////////////////////// +/// +/// semantic_at_c: Semantic channel accessors +/// +/////////////////////////////////////// + +/** +\defgroup ColorBaseAlgorithmSemanticAtC kth_semantic_element_type, kth_semantic_element_reference_type, kth_semantic_element_const_reference_type, semantic_at_c +\ingroup ColorBaseAlgorithm +\brief Support for accessing the elements of a color base by semantic index + +The semantic index of an element is the index of its color in the color space. Semantic indexing allows for proper pairing of elements of color bases +independent on their layout. For example, red is the first semantic element of a color base regardless of whether it has an RGB layout or a BGR layout. +All GIL color base algorithms taking multiple color bases use semantic indexing to access their elements. + +Example: +\code +// 16-bit BGR pixel, 4 bits for the blue, 3 bits for the green, 2 bits for the red channel and 7 unused bits +typedef packed_pixel_type, bgr_layout_t>::type bgr432_pixel_t; + +// A reference to its red channel. Although the red channel is the third, its semantic index is 0 in the RGB color space +typedef kth_semantic_element_reference_type::type red_channel_reference_t; + +// Initialize the pixel to black +bgr432_pixel_t red_pixel(0,0,0); + +// Set the red channel to 100% +red_channel_reference_t red_channel = semantic_at_c<0>(red_pixel); +red_channel = channel_traits::max_value(); + +\endcode +*/ +/// \brief Specifies the type of the K-th semantic element of a color base +/// \ingroup ColorBaseAlgorithmSemanticAtC +template struct kth_semantic_element_type { + BOOST_STATIC_CONSTANT(int, semantic_index = (mpl::at_c::type::value)); + typedef typename kth_element_type::type type; +}; + +/// \brief Specifies the return type of the mutable semantic_at_c(color_base); +/// \ingroup ColorBaseAlgorithmSemanticAtC +template struct kth_semantic_element_reference_type { + BOOST_STATIC_CONSTANT(int, semantic_index = (mpl::at_c::type::value)); + typedef typename kth_element_reference_type::type type; + static type get(ColorBase& cb) { return at_c(cb); } +}; + +/// \brief Specifies the return type of the constant semantic_at_c(color_base); +/// \ingroup ColorBaseAlgorithmSemanticAtC +template struct kth_semantic_element_const_reference_type { + BOOST_STATIC_CONSTANT(int, semantic_index = (mpl::at_c::type::value)); + typedef typename kth_element_const_reference_type::type type; + static type get(const ColorBase& cb) { return at_c(cb); } +}; + +/// \brief A mutable accessor to the K-th semantic element of a color base +/// \ingroup ColorBaseAlgorithmSemanticAtC +template inline +typename disable_if,typename kth_semantic_element_reference_type::type>::type +semantic_at_c(ColorBase& p) { + return kth_semantic_element_reference_type::get(p); +} + +/// \brief A constant accessor to the K-th semantic element of a color base +/// \ingroup ColorBaseAlgorithmSemanticAtC +template inline +typename kth_semantic_element_const_reference_type::type +semantic_at_c(const ColorBase& p) { + return kth_semantic_element_const_reference_type::get(p); +} + +/////////////////////////////////////// +/// +/// get_color: Named channel accessors +/// +/////////////////////////////////////// + +/** +\defgroup ColorBaseAlgorithmColor color_element_type, color_element_reference_type, color_element_const_reference_type, get_color, contains_color +\ingroup ColorBaseAlgorithm +\brief Support for accessing the elements of a color base by color name + +Example: A function that takes a generic pixel containing a red channel and sets it to 100%: + +\code +template +void set_red_to_max(Pixel& pixel) { + boost::function_requires >(); + BOOST_STATIC_ASSERT((contains_color::value)); + + typedef typename color_element_type::type red_channel_t; + get_color(pixel, red_t()) = channel_traits::max_value(); +} +\endcode +*/ + +/// \brief A predicate metafunction determining whether a given color base contains a given color +/// \ingroup ColorBaseAlgorithmColor +template +struct contains_color : public mpl::contains {}; + +template +struct color_index_type : public detail::type_to_index {}; + +/// \brief Specifies the type of the element associated with a given color tag +/// \ingroup ColorBaseAlgorithmColor +template +struct color_element_type : public kth_semantic_element_type::value> {}; + +/// \brief Specifies the return type of the mutable element accessor by color name, get_color(color_base, Color()); +/// \ingroup ColorBaseAlgorithmColor +template +struct color_element_reference_type : public kth_semantic_element_reference_type::value> {}; + +/// \brief Specifies the return type of the constant element accessor by color name, get_color(color_base, Color()); +/// \ingroup ColorBaseAlgorithmColor +template +struct color_element_const_reference_type : public kth_semantic_element_const_reference_type::value> {}; + +/// \brief Mutable accessor to the element associated with a given color name +/// \ingroup ColorBaseAlgorithmColor +template +typename color_element_reference_type::type get_color(ColorBase& cb, Color=Color()) { + return color_element_reference_type::get(cb); +} + +/// \brief Constant accessor to the element associated with a given color name +/// \ingroup ColorBaseAlgorithmColor +template +typename color_element_const_reference_type::type get_color(const ColorBase& cb, Color=Color()) { + return color_element_const_reference_type::get(cb); +} + +/////////////////////////////////////// +/// +/// element_type, element_reference_type, element_const_reference_type: Support for homogeneous color bases +/// +/////////////////////////////////////// + +/** +\defgroup ColorBaseAlgorithmHomogeneous element_type, element_reference_type, element_const_reference_type +\ingroup ColorBaseAlgorithm +\brief Types for homogeneous color bases + +Example: +\code +typedef element_type::type element_t; +BOOST_STATIC_ASSERT((boost::is_same::value)); +\endcode +*/ +/// \brief Specifies the element type of a homogeneous color base +/// \ingroup ColorBaseAlgorithmHomogeneous +template +struct element_type : public kth_element_type {}; + +/// \brief Specifies the return type of the mutable element accessor at_c of a homogeneous color base +/// \ingroup ColorBaseAlgorithmHomogeneous +template +struct element_reference_type : public kth_element_reference_type {}; + +/// \brief Specifies the return type of the constant element accessor at_c of a homogeneous color base +/// \ingroup ColorBaseAlgorithmHomogeneous +template +struct element_const_reference_type : public kth_element_const_reference_type {}; + + +namespace detail { + +// compile-time recursion for per-element operations on color bases +template +struct element_recursion { + //static_equal + template + static bool static_equal(const P1& p1, const P2& p2) { + return element_recursion::static_equal(p1,p2) && + semantic_at_c(p1)==semantic_at_c(p2); + } + //static_copy + template + static void static_copy(const P1& p1, P2& p2) { + element_recursion::static_copy(p1,p2); + semantic_at_c(p2)=semantic_at_c(p1); + } + //static_fill + template + static void static_fill(P& p, T2 v) { + element_recursion::static_fill(p,v); + semantic_at_c(p)=v; + } + //static_generate + template + static void static_generate(Dst& dst, Op op) { + element_recursion::static_generate(dst,op); + semantic_at_c(dst)=op(); + } + //static_for_each with one source + template + static Op static_for_each(P1& p1, Op op) { + Op op2(element_recursion::static_for_each(p1,op)); + op2(semantic_at_c(p1)); + return op2; + } + template + static Op static_for_each(const P1& p1, Op op) { + Op op2(element_recursion::static_for_each(p1,op)); + op2(semantic_at_c(p1)); + return op2; + } + //static_for_each with two sources + template + static Op static_for_each(P1& p1, P2& p2, Op op) { + Op op2(element_recursion::static_for_each(p1,p2,op)); + op2(semantic_at_c(p1), semantic_at_c(p2)); + return op2; + } + template + static Op static_for_each(P1& p1, const P2& p2, Op op) { + Op op2(element_recursion::static_for_each(p1,p2,op)); + op2(semantic_at_c(p1), semantic_at_c(p2)); + return op2; + } + template + static Op static_for_each(const P1& p1, P2& p2, Op op) { + Op op2(element_recursion::static_for_each(p1,p2,op)); + op2(semantic_at_c(p1), semantic_at_c(p2)); + return op2; + } + template + static Op static_for_each(const P1& p1, const P2& p2, Op op) { + Op op2(element_recursion::static_for_each(p1,p2,op)); + op2(semantic_at_c(p1), semantic_at_c(p2)); + return op2; + } + //static_for_each with three sources + template + static Op static_for_each(P1& p1, P2& p2, P3& p3, Op op) { + Op op2(element_recursion::static_for_each(p1,p2,p3,op)); + op2(semantic_at_c(p1), semantic_at_c(p2), semantic_at_c(p3)); + return op2; + } + template + static Op static_for_each(P1& p1, P2& p2, const P3& p3, Op op) { + Op op2(element_recursion::static_for_each(p1,p2,p3,op)); + op2(semantic_at_c(p1), semantic_at_c(p2), semantic_at_c(p3)); + return op2; + } + template + static Op static_for_each(P1& p1, const P2& p2, P3& p3, Op op) { + Op op2(element_recursion::static_for_each(p1,p2,p3,op)); + op2(semantic_at_c(p1), semantic_at_c(p2), semantic_at_c(p3)); + return op2; + } + template + static Op static_for_each(P1& p1, const P2& p2, const P3& p3, Op op) { + Op op2(element_recursion::static_for_each(p1,p2,p3,op)); + op2(semantic_at_c(p1), semantic_at_c(p2), semantic_at_c(p3)); + return op2; + } + template + static Op static_for_each(const P1& p1, P2& p2, P3& p3, Op op) { + Op op2(element_recursion::static_for_each(p1,p2,p3,op)); + op2(semantic_at_c(p1), semantic_at_c(p2), semantic_at_c(p3)); + return op2; + } + template + static Op static_for_each(const P1& p1, P2& p2, const P3& p3, Op op) { + Op op2(element_recursion::static_for_each(p1,p2,p3,op)); + op2(semantic_at_c(p1), semantic_at_c(p2), semantic_at_c(p3)); + return op2; + } + template + static Op static_for_each(const P1& p1, const P2& p2, P3& p3, Op op) { + Op op2(element_recursion::static_for_each(p1,p2,p3,op)); + op2(semantic_at_c(p1), semantic_at_c(p2), semantic_at_c(p3)); + return op2; + } + template + static Op static_for_each(const P1& p1, const P2& p2, const P3& p3, Op op) { + Op op2(element_recursion::static_for_each(p1,p2,p3,op)); + op2(semantic_at_c(p1), semantic_at_c(p2), semantic_at_c(p3)); + return op2; + } + //static_transform with one source + template + static Op static_transform(P1& src, Dst& dst, Op op) { + Op op2(element_recursion::static_transform(src,dst,op)); + semantic_at_c(dst)=op2(semantic_at_c(src)); + return op2; + } + template + static Op static_transform(const P1& src, Dst& dst, Op op) { + Op op2(element_recursion::static_transform(src,dst,op)); + semantic_at_c(dst)=op2(semantic_at_c(src)); + return op2; + } + //static_transform with two sources + template + static Op static_transform(P1& src1, P2& src2, Dst& dst, Op op) { + Op op2(element_recursion::static_transform(src1,src2,dst,op)); + semantic_at_c(dst)=op2(semantic_at_c(src1), semantic_at_c(src2)); + return op2; + } + template + static Op static_transform(P1& src1, const P2& src2, Dst& dst, Op op) { + Op op2(element_recursion::static_transform(src1,src2,dst,op)); + semantic_at_c(dst)=op2(semantic_at_c(src1), semantic_at_c(src2)); + return op2; + } + template + static Op static_transform(const P1& src1, P2& src2, Dst& dst, Op op) { + Op op2(element_recursion::static_transform(src1,src2,dst,op)); + semantic_at_c(dst)=op2(semantic_at_c(src1), semantic_at_c(src2)); + return op2; + } + template + static Op static_transform(const P1& src1, const P2& src2, Dst& dst, Op op) { + Op op2(element_recursion::static_transform(src1,src2,dst,op)); + semantic_at_c(dst)=op2(semantic_at_c(src1), semantic_at_c(src2)); + return op2; + } +}; + +// Termination condition of the compile-time recursion for element operations on a color base +template<> struct element_recursion<0> { + //static_equal + template + static bool static_equal(const P1&, const P2&) { return true; } + //static_copy + template + static void static_copy(const P1&, const P2&) {} + //static_fill + template + static void static_fill(const P&, T2) {} + //static_generate + template + static void static_generate(const Dst&,Op){} + //static_for_each with one source + template + static Op static_for_each(const P1&,Op op){return op;} + //static_for_each with two sources + template + static Op static_for_each(const P1&,const P2&,Op op){return op;} + //static_for_each with three sources + template + static Op static_for_each(const P1&,const P2&,const P3&,Op op){return op;} + //static_transform with one source + template + static Op static_transform(const P1&,const Dst&,Op op){return op;} + //static_transform with two sources + template + static Op static_transform(const P1&,const P2&,const Dst&,Op op){return op;} +}; + +// std::min and std::max don't have the mutable overloads... +template inline const Q& mutable_min(const Q& x, const Q& y) { return x inline Q& mutable_min( Q& x, Q& y) { return x inline const Q& mutable_max(const Q& x, const Q& y) { return x inline Q& mutable_max( Q& x, Q& y) { return x +struct min_max_recur { + template static typename element_const_reference_type

            ::type max_(const P& p) { + return mutable_max(min_max_recur::max_(p),semantic_at_c(p)); + } + template static typename element_reference_type

            ::type max_( P& p) { + return mutable_max(min_max_recur::max_(p),semantic_at_c(p)); + } + template static typename element_const_reference_type

            ::type min_(const P& p) { + return mutable_min(min_max_recur::min_(p),semantic_at_c(p)); + } + template static typename element_reference_type

            ::type min_( P& p) { + return mutable_min(min_max_recur::min_(p),semantic_at_c(p)); + } +}; + +// termination condition of the compile-time recursion for min/max element +template <> +struct min_max_recur<1> { + template static typename element_const_reference_type

            ::type max_(const P& p) { return semantic_at_c<0>(p); } + template static typename element_reference_type

            ::type max_( P& p) { return semantic_at_c<0>(p); } + template static typename element_const_reference_type

            ::type min_(const P& p) { return semantic_at_c<0>(p); } + template static typename element_reference_type

            ::type min_( P& p) { return semantic_at_c<0>(p); } +}; +} // namespace detail + + +/** +\defgroup ColorBaseAlgorithmMinMax static_min, static_max +\ingroup ColorBaseAlgorithm +\brief Equivalents to std::min_element and std::max_element for homogeneous color bases + +Example: +\code +rgb8_pixel_t pixel(10,20,30); +assert(pixel[2] == 30); +static_max(pixel) = static_min(pixel); +assert(pixel[2] == 10); +\endcode +\{ +*/ + +template +GIL_FORCEINLINE +typename element_const_reference_type

            ::type static_max(const P& p) { return detail::min_max_recur::value>::max_(p); } + +template +GIL_FORCEINLINE +typename element_reference_type

            ::type static_max( P& p) { return detail::min_max_recur::value>::max_(p); } + +template +GIL_FORCEINLINE +typename element_const_reference_type

            ::type static_min(const P& p) { return detail::min_max_recur::value>::min_(p); } + +template +GIL_FORCEINLINE +typename element_reference_type

            ::type static_min( P& p) { return detail::min_max_recur::value>::min_(p); } +/// \} + +/** +\defgroup ColorBaseAlgorithmEqual static_equal +\ingroup ColorBaseAlgorithm +\brief Equivalent to std::equal. Pairs the elements semantically + +Example: +\code +rgb8_pixel_t rgb_red(255,0,0); +bgr8_pixel_t bgr_red(0,0,255); +assert(rgb_red[0]==255 && bgr_red[0]==0); + +assert(static_equal(rgb_red,bgr_red)); +assert(rgb_red==bgr_red); // operator== invokes static_equal +\endcode +\{ +*/ + +template +GIL_FORCEINLINE +bool static_equal(const P1& p1, const P2& p2) { return detail::element_recursion::value>::static_equal(p1,p2); } + +/// \} + +/** +\defgroup ColorBaseAlgorithmCopy static_copy +\ingroup ColorBaseAlgorithm +\brief Equivalent to std::copy. Pairs the elements semantically + +Example: +\code +rgb8_pixel_t rgb_red(255,0,0); +bgr8_pixel_t bgr_red; +static_copy(rgb_red, bgr_red); // same as bgr_red = rgb_red + +assert(rgb_red[0] == 255 && bgr_red[0] == 0); +assert(rgb_red == bgr_red); +\endcode +\{ +*/ + +template +GIL_FORCEINLINE +void static_copy(const Src& src, Dst& dst) { detail::element_recursion::value>::static_copy(src,dst); } + +/// \} + +/** +\defgroup ColorBaseAlgorithmFill static_fill +\ingroup ColorBaseAlgorithm +\brief Equivalent to std::fill. + +Example: +\code +rgb8_pixel_t p; +static_fill(p, 10); +assert(p == rgb8_pixel_t(10,10,10)); +\endcode +\{ +*/ +template +GIL_FORCEINLINE +void static_fill(P& p, const V& v) { detail::element_recursion::value>::static_fill(p,v); } +/// \} + +/** +\defgroup ColorBaseAlgorithmGenerate static_generate +\ingroup ColorBaseAlgorithm +\brief Equivalent to std::generate. + +Example: Set each channel of a pixel to its semantic index. The channels must be assignable from an integer. +\code +struct consecutive_fn { + int& _current; + consecutive_fn(int& start) : _current(start) {} + int operator()() { return _current++; } +}; +rgb8_pixel_t p; +int start=0; +static_generate(p, consecutive_fn(start)); +assert(p == rgb8_pixel_t(0,1,2)); +\endcode + +\{ +*/ + +template +GIL_FORCEINLINE +void static_generate(P1& dst,Op op) { detail::element_recursion::value>::static_generate(dst,op); } +/// \} + +/** +\defgroup ColorBaseAlgorithmTransform static_transform +\ingroup ColorBaseAlgorithm +\brief Equivalent to std::transform. Pairs the elements semantically + +Example: Write a generic function that adds two pixels into a homogeneous result pixel. +\code +template +struct my_plus { + template + Result operator()(T1 f1, T2 f2) const { return f1+f2; } +}; + +template +void sum_channels(const Pixel1& p1, const Pixel2& p2, Pixel3& result) { + typedef typename channel_type::type result_channel_t; + static_transform(p1,p2,result,my_plus()); +} + +rgb8_pixel_t p1(1,2,3); +bgr8_pixel_t p2(3,2,1); +rgb8_pixel_t result; +sum_channels(p1,p2,result); +assert(result == rgb8_pixel_t(2,4,6)); +\endcode +\{ +*/ + +//static_transform with one source +template +GIL_FORCEINLINE +Op static_transform(Src& src,Dst& dst,Op op) { return detail::element_recursion::value>::static_transform(src,dst,op); } +template +GIL_FORCEINLINE +Op static_transform(const Src& src,Dst& dst,Op op) { return detail::element_recursion::value>::static_transform(src,dst,op); } +//static_transform with two sources +template +GIL_FORCEINLINE +Op static_transform(P2& p2,P3& p3,Dst& dst,Op op) { return detail::element_recursion::value>::static_transform(p2,p3,dst,op); } +template +GIL_FORCEINLINE +Op static_transform(P2& p2,const P3& p3,Dst& dst,Op op) { return detail::element_recursion::value>::static_transform(p2,p3,dst,op); } +template +GIL_FORCEINLINE +Op static_transform(const P2& p2,P3& p3,Dst& dst,Op op) { return detail::element_recursion::value>::static_transform(p2,p3,dst,op); } +template +GIL_FORCEINLINE +Op static_transform(const P2& p2,const P3& p3,Dst& dst,Op op) { return detail::element_recursion::value>::static_transform(p2,p3,dst,op); } +/// \} + +/** +\defgroup ColorBaseAlgorithmForEach static_for_each +\ingroup ColorBaseAlgorithm +\brief Equivalent to std::for_each. Pairs the elements semantically + +Example: Use static_for_each to increment a planar pixel iterator +\code +struct increment { + template + void operator()(Incrementable& x) const { ++x; } +}; + +template +void increment_elements(ColorBase& cb) { + static_for_each(cb, increment()); +} + +bits8 red[2], green[2], blue[2]; +rgb8c_planar_ptr_t p1(red,green,blue); +rgb8c_planar_ptr_t p2=p1; +increment_elements(p1); +++p2; +assert(p1 == p2); +\endcode +\{ +*/ + +//static_for_each with one source +template +GIL_FORCEINLINE +Op static_for_each( P1& p1, Op op) { return detail::element_recursion::value>::static_for_each(p1,op); } +template +GIL_FORCEINLINE +Op static_for_each(const P1& p1, Op op) { return detail::element_recursion::value>::static_for_each(p1,op); } +//static_for_each with two sources +template +GIL_FORCEINLINE +Op static_for_each(P1& p1, P2& p2, Op op) { return detail::element_recursion::value>::static_for_each(p1,p2,op); } +template +GIL_FORCEINLINE +Op static_for_each(P1& p1,const P2& p2, Op op) { return detail::element_recursion::value>::static_for_each(p1,p2,op); } +template +GIL_FORCEINLINE +Op static_for_each(const P1& p1, P2& p2, Op op) { return detail::element_recursion::value>::static_for_each(p1,p2,op); } +template +GIL_FORCEINLINE +Op static_for_each(const P1& p1,const P2& p2, Op op) { return detail::element_recursion::value>::static_for_each(p1,p2,op); } +//static_for_each with three sources +template +GIL_FORCEINLINE +Op static_for_each(P1& p1,P2& p2,P3& p3,Op op) { return detail::element_recursion::value>::static_for_each(p1,p2,p3,op); } +template +GIL_FORCEINLINE +Op static_for_each(P1& p1,P2& p2,const P3& p3,Op op) { return detail::element_recursion::value>::static_for_each(p1,p2,p3,op); } +template +GIL_FORCEINLINE +Op static_for_each(P1& p1,const P2& p2,P3& p3,Op op) { return detail::element_recursion::value>::static_for_each(p1,p2,p3,op); } +template +GIL_FORCEINLINE +Op static_for_each(P1& p1,const P2& p2,const P3& p3,Op op) { return detail::element_recursion::value>::static_for_each(p1,p2,p3,op); } +template +GIL_FORCEINLINE +Op static_for_each(const P1& p1,P2& p2,P3& p3,Op op) { return detail::element_recursion::value>::static_for_each(p1,p2,p3,op); } +template +GIL_FORCEINLINE +Op static_for_each(const P1& p1,P2& p2,const P3& p3,Op op) { return detail::element_recursion::value>::static_for_each(p1,p2,p3,op); } +template +GIL_FORCEINLINE +Op static_for_each(const P1& p1,const P2& p2,P3& p3,Op op) { return detail::element_recursion::value>::static_for_each(p1,p2,p3,op); } +template +GIL_FORCEINLINE +Op static_for_each(const P1& p1,const P2& p2,const P3& p3,Op op) { return detail::element_recursion::value>::static_for_each(p1,p2,p3,op); } +///\} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/color_convert.hpp b/win32/include/boost/gil/color_convert.hpp new file mode 100755 index 000000000..211c84df6 --- /dev/null +++ b/win32/include/boost/gil/color_convert.hpp @@ -0,0 +1,314 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ +/*************************************************************************************************/ + +#ifndef GIL_COLOR_CONVERT_HPP +#define GIL_COLOR_CONVERT_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief GIL default color space conversions +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on January 30, 2007 +/// +/// Support for fast and simple color conversion. Accurate color conversion using color +/// profiles can be supplied separately in a dedicated module +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include "gil_config.hpp" +#include "channel_algorithm.hpp" +#include "pixel.hpp" +#include "gray.hpp" +#include "rgb.hpp" +#include "rgba.hpp" +#include "cmyk.hpp" +#include "metafunctions.hpp" +#include "utilities.hpp" +#include "color_base_algorithm.hpp" + +namespace boost { namespace gil { + +// Forward-declare +template struct channel_type; + +//////////////////////////////////////////////////////////////////////////////////////// +/// +/// COLOR SPACE CONVERSION +/// +//////////////////////////////////////////////////////////////////////////////////////// + +/// \ingroup ColorConvert +/// \brief Color Convertion function object. To be specialized for every src/dst color space +template +struct default_color_converter_impl {}; + +/// \ingroup ColorConvert +/// \brief When the color space is the same, color convertion performs channel depth conversion +template +struct default_color_converter_impl { + template + void operator()(const P1& src, P2& dst) const { + static_for_each(src,dst,default_channel_converter()); + } +}; + +namespace detail { + +/// red * .3 + green * .59 + blue * .11 + .5 + +// The default implementation of to_luminance uses float0..1 as the intermediate channel type +template +struct rgb_to_luminance_fn { + GrayChannelValue operator()(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) const { + return channel_convert( bits32f( + channel_convert(red )*0.30f + + channel_convert(green)*0.59f + + channel_convert(blue )*0.11f) ); + } +}; + +// performance specialization for unsigned char +template +struct rgb_to_luminance_fn { + GrayChannelValue operator()(uint8_t red, uint8_t green, uint8_t blue) const { + return channel_convert(uint8_t( + ((uint32_t(red )*4915 + uint32_t(green)*9667 + uint32_t(blue )*1802) + 8192) >> 14)); + } +}; + +template +typename channel_traits::value_type rgb_to_luminance(const RedChannel& red, const GreenChannel& green, const BlueChannel& blue) { + return rgb_to_luminance_fn::value_type>()(red,green,blue); +} + +} // namespace detail + +/// \ingroup ColorConvert +/// \brief Gray to RGB +template <> +struct default_color_converter_impl { + template + void operator()(const P1& src, P2& dst) const { + get_color(dst,red_t()) = + channel_convert::type>(get_color(src,gray_color_t())); + get_color(dst,green_t())= + channel_convert::type>(get_color(src,gray_color_t())); + get_color(dst,blue_t()) = + channel_convert::type>(get_color(src,gray_color_t())); + } +}; + +/// \ingroup ColorConvert +/// \brief Gray to CMYK +template <> +struct default_color_converter_impl { + template + void operator()(const P1& src, P2& dst) const { + get_color(dst,cyan_t())= + channel_traits::type>::min_value(); + get_color(dst,magenta_t())= + channel_traits::type>::min_value(); + get_color(dst,yellow_t())= + channel_traits::type>::min_value(); + get_color(dst,black_t())= + channel_convert::type>(get_color(src,gray_color_t())); + } +}; + +/// \ingroup ColorConvert +/// \brief RGB to Gray +template <> +struct default_color_converter_impl { + template + void operator()(const P1& src, P2& dst) const { + get_color(dst,gray_color_t()) = + detail::rgb_to_luminance::type>( + get_color(src,red_t()), get_color(src,green_t()), get_color(src,blue_t()) + ); + } +}; + + +/// \ingroup ColorConvert +/// \brief RGB to CMYK (not the fastest code in the world) +/// +/// k = min(1 - r, 1 - g, 1 - b) +/// c = (1 - r - k) / (1 - k) +/// m = (1 - g - k) / (1 - k) +/// y = (1 - b - k) / (1 - k) +template <> +struct default_color_converter_impl { + template + void operator()(const P1& src, P2& dst) const { + typedef typename channel_type::type T2; + get_color(dst,cyan_t()) = channel_invert(channel_convert(get_color(src,red_t()))); // c = 1 - r + get_color(dst,magenta_t()) = channel_invert(channel_convert(get_color(src,green_t()))); // m = 1 - g + get_color(dst,yellow_t()) = channel_invert(channel_convert(get_color(src,blue_t()))); // y = 1 - b + get_color(dst,black_t()) = (std::min)(get_color(dst,cyan_t()), + (std::min)(get_color(dst,magenta_t()), + get_color(dst,yellow_t()))); // k = minimum(c, m, y) + T2 x = channel_traits::max_value()-get_color(dst,black_t()); // x = 1 - k + if (x>0.0001f) { + float x1 = channel_traits::max_value()/float(x); + get_color(dst,cyan_t()) = (T2)((get_color(dst,cyan_t()) - get_color(dst,black_t()))*x1); // c = (c - k) / x + get_color(dst,magenta_t()) = (T2)((get_color(dst,magenta_t()) - get_color(dst,black_t()))*x1); // m = (m - k) / x + get_color(dst,yellow_t()) = (T2)((get_color(dst,yellow_t()) - get_color(dst,black_t()))*x1); // y = (y - k) / x + } else { + get_color(dst,cyan_t())=get_color(dst,magenta_t())=get_color(dst,yellow_t())=0; + } + } +}; + +/// \ingroup ColorConvert +/// \brief CMYK to RGB (not the fastest code in the world) +/// +/// r = 1 - min(1, c*(1-k)+k) +/// g = 1 - min(1, m*(1-k)+k) +/// b = 1 - min(1, y*(1-k)+k) +template <> +struct default_color_converter_impl { + template + void operator()(const P1& src, P2& dst) const { + typedef typename channel_type::type T1; + get_color(dst,red_t()) = + channel_convert::type>( + channel_invert( + (std::min)(channel_traits::max_value(), + T1(get_color(src,cyan_t())*channel_invert(get_color(src,black_t()))+get_color(src,black_t()))))); + get_color(dst,green_t())= + channel_convert::type>( + channel_invert( + (std::min)(channel_traits::max_value(), + T1(get_color(src,magenta_t())*channel_invert(get_color(src,black_t()))+get_color(src,black_t()))))); + get_color(dst,blue_t()) = + channel_convert::type>( + channel_invert( + (std::min)(channel_traits::max_value(), + T1(get_color(src,yellow_t())*channel_invert(get_color(src,black_t()))+get_color(src,black_t()))))); + } +}; + + +/// \ingroup ColorConvert +/// \brief CMYK to Gray +/// +/// gray = (1 - 0.212c - 0.715m - 0.0722y) * (1 - k) +template <> +struct default_color_converter_impl { + template + void operator()(const P1& src, P2& dst) const { + get_color(dst,gray_color_t())= + channel_convert::type>( + channel_multiply( + channel_invert( + detail::rgb_to_luminance::type>( + get_color(src,cyan_t()), + get_color(src,magenta_t()), + get_color(src,yellow_t()) + ) + ), + channel_invert(get_color(src,black_t())))); + } +}; + +namespace detail { +template +typename channel_type::type alpha_or_max_impl(const Pixel& p, mpl::true_) { + return get_color(p,alpha_t()); +} +template +typename channel_type::type alpha_or_max_impl(const Pixel& , mpl::false_) { + return channel_traits::type>::max_value(); +} +} // namespace detail + +// Returns max_value if the pixel has no alpha channel. Otherwise returns the alpha. +template +typename channel_type::type alpha_or_max(const Pixel& p) { + return detail::alpha_or_max_impl(p, mpl::contains::type,alpha_t>()); +} + + +/// \ingroup ColorConvert +/// \brief Converting any pixel type to RGBA. Note: Supports homogeneous pixels only. +template +struct default_color_converter_impl { + template + void operator()(const P1& src, P2& dst) const { + typedef typename channel_type::type T2; + pixel tmp; + default_color_converter_impl()(src,tmp); + get_color(dst,red_t()) =get_color(tmp,red_t()); + get_color(dst,green_t())=get_color(tmp,green_t()); + get_color(dst,blue_t()) =get_color(tmp,blue_t()); + get_color(dst,alpha_t())=channel_convert(alpha_or_max(src)); + } +}; + +/// \ingroup ColorConvert +/// \brief Converting RGBA to any pixel type. Note: Supports homogeneous pixels only. +/// +/// Done by multiplying the alpha to get to RGB, then converting the RGB to the target pixel type +/// Note: This may be slower if the compiler doesn't optimize out constructing/destructing a temporary RGB pixel. +/// Consider rewriting if performance is an issue +template +struct default_color_converter_impl { + template + void operator()(const P1& src, P2& dst) const { + typedef typename channel_type::type T1; + default_color_converter_impl()( + pixel(channel_multiply(get_color(src,red_t()), get_color(src,alpha_t())), + channel_multiply(get_color(src,green_t()),get_color(src,alpha_t())), + channel_multiply(get_color(src,blue_t()), get_color(src,alpha_t()))) + ,dst); + } +}; + +/// \ingroup ColorConvert +/// \brief Unfortunately RGBA to RGBA must be explicitly provided - otherwise we get ambiguous specialization error. +template <> +struct default_color_converter_impl { + template + void operator()(const P1& src, P2& dst) const { + static_for_each(src,dst,default_channel_converter()); + } +}; + +/// @defgroup ColorConvert Color Space Converion +/// \ingroup ColorSpaces +/// \brief Support for conversion between pixels of different color spaces and channel depths + +/// \ingroup PixelAlgorithm ColorConvert +/// \brief class for color-converting one pixel to another +struct default_color_converter { + template + void operator()(const SrcP& src,DstP& dst) const { + typedef typename color_space_type::type SrcColorSpace; + typedef typename color_space_type::type DstColorSpace; + default_color_converter_impl()(src,dst); + } +}; + +/// \ingroup PixelAlgorithm +/// \brief helper function for converting one pixel to another using GIL default color-converters +/// where ScrP models HomogeneousPixelConcept +/// DstP models HomogeneousPixelValueConcept +template +inline void color_convert(const SrcP& src, DstP& dst) { + default_color_converter()(src,dst); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/deprecated.hpp b/win32/include/boost/gil/deprecated.hpp new file mode 100755 index 000000000..32c4b5c05 --- /dev/null +++ b/win32/include/boost/gil/deprecated.hpp @@ -0,0 +1,77 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_DEPRECATED_HPP +#define GIL_DEPRECATED_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Deprecated names +/// This file is provided as a courtesy to ease upgrading GIL client code. +/// Please make sure your code compiles when this file is not included. +/// +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on February 12, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#define planar_ptr planar_pixel_iterator +#define planar_ref planar_pixel_reference +#define membased_2d_locator memory_based_2d_locator +#define pixel_step_iterator memory_based_step_iterator +#define pixel_image_iterator iterator_from_2d + +#define equal_channels static_equal +#define copy_channels static_copy +#define fill_channels static_fill +#define generate_channels static_generate +#define for_each_channel static_for_each +#define transform_channels static_transform +#define max_channel static_max +#define min_channel static_min + +#define semantic_channel semantic_at_c + +template +void resize_clobber_image(Img& img, const typename Img::point_t& new_dims) { + img.recreate(new_dims); +} + +template +void resize_clobber_image(Img& img, const typename Img::x_coord_t& width, const typename Img::y_coord_t& height) { + img.recreate(width,height); +} + +template typename T::x_coord_t get_width(const T& a) { return a.width(); } +template typename T::y_coord_t get_height(const T& a) { return a.height(); } +template typename T::point_t get_dimensions(const T& a) { return a.dimensions(); } +template std::size_t get_num_channels(const T& a) { return a.num_channels(); } + +#define GIL boost::gil +#define ADOBE_GIL_NAMESPACE_BEGIN namespace boost { namespace gil { +#define ADOBE_GIL_NAMESPACE_END } } + +#define ByteAdvancableIteratorConcept MemoryBasedIteratorConcept +#define byte_advance memunit_advance +#define byte_advanced memunit_advanced +#define byte_step memunit_step +#define byte_distance memunit_distance + +#define byte_addressable_step_iterator memory_based_step_iterator +#define byte_addressable_2d_locator memory_based_2d_locator + +// These are members of memory-based locators +//#define row_bytes row_size // commented out because row_bytes is commonly used +#define pix_bytestep pixel_size + +#endif diff --git a/win32/include/boost/gil/device_n.hpp b/win32/include/boost/gil/device_n.hpp new file mode 100755 index 000000000..cc6240ca4 --- /dev/null +++ b/win32/include/boost/gil/device_n.hpp @@ -0,0 +1,100 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://stlab.adobe.com/gil for most recent version including documentation. +*/ +/*************************************************************************************************/ + +#ifndef GIL_DEVICE_N_H +#define GIL_DEVICE_N_H + + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Support for color space of N channels and variants +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on October 10, 2007 +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include "gil_config.hpp" +#include +#include +#include + +namespace boost { namespace gil { + +/// \brief unnamed color +/// \ingroup ColorNameModel +template struct devicen_color_t {}; + +template struct devicen_t; + +/// \brief unnamed color space of one channel +/// \ingroup ColorSpaceModel +template <> struct devicen_t<1> : public mpl::vector1 > {}; + +/// \brief unnamed color space of two channels +/// \ingroup ColorSpaceModel +template <> struct devicen_t<2> : public mpl::vector2, devicen_color_t<1> > {}; + +/// \brief unnamed color space of three channels +/// \ingroup ColorSpaceModel +template <> struct devicen_t<3> : public mpl::vector3, devicen_color_t<1>, devicen_color_t<2> > {}; + +/// \brief unnamed color space of four channels +/// \ingroup ColorSpaceModel +template <> struct devicen_t<4> : public mpl::vector4, devicen_color_t<1>, devicen_color_t<2>, devicen_color_t<3> > {}; + +/// \brief unnamed color space of five channels +/// \ingroup ColorSpaceModel +template <> struct devicen_t<5> : public mpl::vector5, devicen_color_t<1>, devicen_color_t<2>, devicen_color_t<3>, devicen_color_t<4> > {}; + +/// \brief unnamed color layout of up to five channels +/// \ingroup LayoutModel +template struct devicen_layout_t : public layout > {}; + +/// \ingroup ImageViewConstructors +/// \brief from 2-channel planar data +template +inline typename type_from_x_iterator > >::view_t +planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, std::ptrdiff_t rowsize_in_bytes) { + typedef typename type_from_x_iterator > >::view_t view_t; + return view_t(width, height, typename view_t::locator(typename view_t::x_iterator(c0,c1), rowsize_in_bytes)); +} + +/// \ingroup ImageViewConstructors +/// \brief from 3-channel planar data +template +inline typename type_from_x_iterator > >::view_t +planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, IC c2, std::ptrdiff_t rowsize_in_bytes) { + typedef typename type_from_x_iterator > >::view_t view_t; + return view_t(width, height, typename view_t::locator(typename view_t::x_iterator(c0,c1,c2), rowsize_in_bytes)); +} + +/// \ingroup ImageViewConstructors +/// \brief from 4-channel planar data +template +inline typename type_from_x_iterator > >::view_t +planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, IC c2, IC c3, std::ptrdiff_t rowsize_in_bytes) { + typedef typename type_from_x_iterator > >::view_t view_t; + return view_t(width, height, typename view_t::locator(typename view_t::x_iterator(c0,c1,c2,c3), rowsize_in_bytes)); +} + +/// \ingroup ImageViewConstructors +/// \brief from 5-channel planar data +template +inline typename type_from_x_iterator > >::view_t +planar_devicen_view(std::size_t width, std::size_t height, IC c0, IC c1, IC c2, IC c3, IC c4, std::ptrdiff_t rowsize_in_bytes) { + typedef typename type_from_x_iterator > >::view_t view_t; + return view_t(width, height, typename view_t::locator(typename view_t::x_iterator(c0,c1,c2,c3,c4), rowsize_in_bytes)); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/extension/dynamic_image/algorithm.hpp b/win32/include/boost/gil/extension/dynamic_image/algorithm.hpp new file mode 100755 index 000000000..30c45bf45 --- /dev/null +++ b/win32/include/boost/gil/extension/dynamic_image/algorithm.hpp @@ -0,0 +1,173 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ +/*************************************************************************************************/ + +#ifndef GIL_DYNAMICIMAGE_ALGORITHM_HPP +#define GIL_DYNAMICIMAGE_ALGORITHM_HPP + +#include "../../algorithm.hpp" +#include "any_image.hpp" +#include + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Some basic STL-style algorithms when applied to runtime type specified image views +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on September 24, 2006 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +namespace boost { namespace gil { + +namespace detail { + struct equal_pixels_fn : public binary_operation_obj { + template + GIL_FORCEINLINE bool apply_compatible(const V1& v1, const V2& v2) const { + return equal_pixels(v1,v2); + } + }; +} // namespace detail + +/// \ingroup ImageViewSTLAlgorithmsEqualPixels +template // Model MutableImageViewConcept +bool equal_pixels(const any_image_view& src, const View2& dst) { + return apply_operation(src,boost::bind(detail::equal_pixels_fn(), _1, dst)); +} + +/// \ingroup ImageViewSTLAlgorithmsEqualPixels +template // Model MPL Random Access Container of models of MutableImageViewConcept +bool equal_pixels(const View1& src, const any_image_view& dst) { + return apply_operation(dst,boost::bind(detail::equal_pixels_fn(), src, _1)); +} + +/// \ingroup ImageViewSTLAlgorithmsEqualPixels +template // Model MPL Random Access Container of models of MutableImageViewConcept +bool equal_pixels(const any_image_view& src, const any_image_view& dst) { + return apply_operation(src,dst,detail::equal_pixels_fn()); +} + +namespace detail { + struct copy_pixels_fn : public binary_operation_obj { + template + GIL_FORCEINLINE void apply_compatible(const View1& src, const View2& dst) const { + copy_pixels(src,dst); + } + }; +} + +/// \ingroup ImageViewSTLAlgorithmsCopyPixels +template // Model MutableImageViewConcept +void copy_pixels(const any_image_view& src, const View2& dst) { + apply_operation(src,boost::bind(detail::copy_pixels_fn(), _1, dst)); +} + +/// \ingroup ImageViewSTLAlgorithmsCopyPixels +template // Model MPL Random Access Container of models of MutableImageViewConcept +void copy_pixels(const View1& src, const any_image_view& dst) { + apply_operation(dst,boost::bind(detail::copy_pixels_fn(), src, _1)); +} + +/// \ingroup ImageViewSTLAlgorithmsCopyPixels +template // Model MPL Random Access Container of models of MutableImageViewConcept +void copy_pixels(const any_image_view& src, const any_image_view& dst) { + apply_operation(src,dst,detail::copy_pixels_fn()); +} + + + +//forward declaration for default_color_converter (see full definition in color_convert.hpp) +struct default_color_converter; + +/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels +template // Model ColorConverterConcept +void copy_and_convert_pixels(const any_image_view& src, const View2& dst, CC cc) { + apply_operation(src,boost::bind(detail::copy_and_convert_pixels_fn(cc), _1, dst)); +} + +/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels +template // Model MutableImageViewConcept +void copy_and_convert_pixels(const any_image_view& src, const View2& dst) { + apply_operation(src,boost::bind(detail::copy_and_convert_pixels_fn(), _1, dst)); +} + +/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels +template // Model ColorConverterConcept +void copy_and_convert_pixels(const View1& src, const any_image_view& dst, CC cc) { + apply_operation(dst,boost::bind(detail::copy_and_convert_pixels_fn(cc), src, _1)); +} + +/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels +template // Model MPL Random Access Container of models of MutableImageViewConcept +void copy_and_convert_pixels(const View1& src, const any_image_view& dst) { + apply_operation(dst,boost::bind(detail::copy_and_convert_pixels_fn(), src, _1)); +} + +/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels +template // Model ColorConverterConcept +void copy_and_convert_pixels(const any_image_view& src, const any_image_view& dst, CC cc) { + apply_operation(src,dst,detail::copy_and_convert_pixels_fn(cc)); +} + +/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels +template // Model MPL Random Access Container of models of MutableImageViewConcept +void copy_and_convert_pixels(const any_image_view& src, const any_image_view& dst) { + apply_operation(src,dst,detail::copy_and_convert_pixels_fn()); +} + +namespace detail { +template struct fill_pixels_fn1 { + template static void apply(const V& src, const Value& val) { fill_pixels(src,val); } +}; + +// copy_pixels invoked on incompatible images +template <> struct fill_pixels_fn1 { + template static void apply(const V& src, const Value& val) { throw std::bad_cast();} +}; + +template +struct fill_pixels_fn { + fill_pixels_fn(const Value& val) : _val(val) {} + + typedef void result_type; + template result_type operator()(const V& img_view) const { + fill_pixels_fn1::value>::apply(img_view,_val); + } + Value _val; +}; +} + +/// \ingroup ImageViewSTLAlgorithmsFillPixels +/// \brief fill_pixels for any image view. The pixel to fill with must be compatible with the current view +template +void fill_pixels(const any_image_view& img_view, const Value& val) { + apply_operation(img_view,detail::fill_pixels_fn(val)); +} + + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/extension/dynamic_image/any_image.hpp b/win32/include/boost/gil/extension/dynamic_image/any_image.hpp new file mode 100755 index 000000000..41f45b296 --- /dev/null +++ b/win32/include/boost/gil/extension/dynamic_image/any_image.hpp @@ -0,0 +1,125 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ +/*************************************************************************************************/ + +#ifndef GIL_DYNAMICIMAGE_ANY_IMAGE_HPP +#define GIL_DYNAMICIMAGE_ANY_IMAGE_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Support for run-time instantiated images and image views +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include "any_image_view.hpp" +#include "../../image.hpp" + +//#ifdef _MSC_VER +//#pragma warning(push) +//#pragma warning(disable : 4244) // conversion from 'std::ptrdiff_t' to 'int', possible loss of data. even if we static-assert the two types are the same (on visual studio 8) +//#endif + +namespace boost { namespace gil { + +namespace detail { + template struct get_view_t { typedef typename T::view_t type; }; + template struct images_get_views_t : public mpl::transform > {}; + + template struct get_const_view_t { typedef typename T::const_view_t type; }; + template struct images_get_const_views_t : public mpl::transform > {}; + + struct recreate_image_fnobj { + typedef void result_type; + const point2& _dimensions; + unsigned _alignment; + + recreate_image_fnobj(const point2& dims, unsigned alignment) : _dimensions(dims), _alignment(alignment) {} + template result_type operator()(Image& img) const { img.recreate(_dimensions,_alignment); } + }; + + template // Models AnyViewConcept + struct any_image_get_view { + typedef AnyView result_type; + template result_type operator()( Image& img) const { return result_type(view(img)); } + }; + + template // Models AnyConstViewConcept + struct any_image_get_const_view { + typedef AnyConstView result_type; + template result_type operator()(const Image& img) const { return result_type(const_view(img)); } + }; +} + +//////////////////////////////////////////////////////////////////////////////////////// +/// \ingroup ImageModel +/// \brief Represents a run-time specified image. Note it does NOT model ImageConcept +/// +/// Represents an image whose type (color space, layout, planar/interleaved organization, etc) can be specified at run time. +/// It is the runtime equivalent of \p image. +/// Some of the requirements of ImageConcept, such as the \p value_type typedef cannot be fulfilled, since the language does not allow runtime type specification. +/// Other requirements, such as access to the pixels, would be inefficient to provide. Thus \p any_image does not fully model ImageConcept. +/// In particular, its \p view and \p const_view methods return \p any_image_view, which does not fully model ImageViewConcept. See \p any_image_view for more. +//////////////////////////////////////////////////////////////////////////////////////// +template +class any_image : public variant { + typedef variant parent_t; +public: + typedef any_image_view::type> const_view_t; + typedef any_image_view::type> view_t; + typedef std::ptrdiff_t x_coord_t; + typedef std::ptrdiff_t y_coord_t; + typedef point2 point_t; + + any_image() : parent_t() {} + template explicit any_image(const T& obj) : parent_t(obj) {} + template explicit any_image(T& obj, bool do_swap) : parent_t(obj,do_swap) {} + any_image(const any_image& v) : parent_t((const parent_t&)v) {} + + template any_image& operator=(const T& obj) { parent_t::operator=(obj); return *this; } + any_image& operator=(const any_image& v) { parent_t::operator=((const parent_t&)v); return *this;} + + void recreate(const point_t& dims, unsigned alignment=1) { apply_operation(*this,detail::recreate_image_fnobj(dims,alignment)); } + void recreate(x_coord_t width, y_coord_t height, unsigned alignment=1) { recreate(point2(width,height),alignment); } + + std::size_t num_channels() const { return apply_operation(*this, detail::any_type_get_num_channels()); } + point_t dimensions() const { return apply_operation(*this, detail::any_type_get_dimensions()); } + x_coord_t width() const { return dimensions().x; } + y_coord_t height() const { return dimensions().y; } +}; + +///@{ +/// \name view, const_view +/// \brief Get an image view from a run-time instantiated image + +/// \ingroup ImageModel + +/// \brief Returns the non-constant-pixel view of any image. The returned view is any view. +template GIL_FORCEINLINE // Models ImageVectorConcept +typename any_image::view_t view(any_image& anyImage) { + return apply_operation(anyImage, detail::any_image_get_view::view_t>()); +} + +/// \brief Returns the constant-pixel view of any image. The returned view is any view. +template GIL_FORCEINLINE // Models ImageVectorConcept +typename any_image::const_view_t const_view(const any_image& anyImage) { + return apply_operation(anyImage, detail::any_image_get_const_view::const_view_t>()); +} +///@} + +} } // namespace boost::gil + +//#ifdef _MSC_VER +//#pragma warning(pop) +//#endif + +#endif diff --git a/win32/include/boost/gil/extension/dynamic_image/any_image_view.hpp b/win32/include/boost/gil/extension/dynamic_image/any_image_view.hpp new file mode 100755 index 000000000..20997fb64 --- /dev/null +++ b/win32/include/boost/gil/extension/dynamic_image/any_image_view.hpp @@ -0,0 +1,115 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_DYNAMICIMAGE_ANY_IMAGEVIEW_HPP +#define GIL_DYNAMICIMAGE_ANY_IMAGEVIEW_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Support for run-time instantiated image view +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include "variant.hpp" +#include "../../image_view.hpp" +#include "../../image.hpp" + +namespace boost { namespace gil { + +namespace detail { + template struct get_const_t { typedef typename View::const_t type; }; + template struct views_get_const_t : public mpl::transform > {}; +} +template struct dynamic_xy_step_type; +template struct dynamic_xy_step_transposed_type; + +namespace detail { + struct any_type_get_num_channels { // works for both image_view and image + typedef int result_type; + template result_type operator()(const T& v) const { return num_channels::value; } + }; + struct any_type_get_dimensions { // works for both image_view and image + typedef point2 result_type; + template result_type operator()(const T& v) const { return v.dimensions(); } + }; +} + +//////////////////////////////////////////////////////////////////////////////////////// +/// CLASS any_image_view +/// +/// \ingroup ImageViewModel +/// \brief Represents a run-time specified image view. Models HasDynamicXStepTypeConcept, HasDynamicYStepTypeConcept, Note that this class does NOT model ImageViewConcept +/// +/// Represents a view whose type (color space, layout, planar/interleaved organization, etc) can be specified at run time. +/// It is the runtime equivalent of \p image_view. +/// Some of the requirements of ImageViewConcept, such as the \p value_type typedef cannot be fulfilled, since the language does not allow runtime type specification. +/// Other requirements, such as access to the pixels, would be inefficient to provide. Thus \p any_image_view does not fully model ImageViewConcept. +/// However, many algorithms provide overloads taking runtime specified views and thus in many cases \p any_image_view can be used in places taking a view. +/// +/// To perform an algorithm on any_image_view, put the algorithm in a function object and invoke it by calling \p apply_operation(runtime_view, algorithm_fn); +//////////////////////////////////////////////////////////////////////////////////////// +template +class any_image_view : public variant { + typedef variant parent_t; +public: + typedef any_image_view::type> const_t; + typedef std::ptrdiff_t x_coord_t; + typedef std::ptrdiff_t y_coord_t; + typedef point2 point_t; + + any_image_view() : parent_t() {} + template explicit any_image_view(const T& obj) : parent_t(obj) {} + any_image_view(const any_image_view& v) : parent_t((const parent_t&)v) {} + + template any_image_view& operator=(const T& obj) { parent_t::operator=(obj); return *this; } + any_image_view& operator=(const any_image_view& v) { parent_t::operator=((const parent_t&)v); return *this;} + + std::size_t num_channels() const { return apply_operation(*this, detail::any_type_get_num_channels()); } + point_t dimensions() const { return apply_operation(*this, detail::any_type_get_dimensions()); } + x_coord_t width() const { return dimensions().x; } + y_coord_t height() const { return dimensions().y; } +}; + +///////////////////////////// +// HasDynamicXStepTypeConcept +///////////////////////////// + +template +struct dynamic_x_step_type > { + typedef any_image_view >::type> type; +}; + +///////////////////////////// +// HasDynamicYStepTypeConcept +///////////////////////////// + +template +struct dynamic_y_step_type > { + typedef any_image_view >::type> type; +}; + +template +struct dynamic_xy_step_type > { + typedef any_image_view >::type> type; +}; + +template +struct dynamic_xy_step_transposed_type > { + typedef any_image_view >::type> type; +}; + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/extension/dynamic_image/apply_operation.hpp b/win32/include/boost/gil/extension/dynamic_image/apply_operation.hpp new file mode 100755 index 000000000..6c95ea2fa --- /dev/null +++ b/win32/include/boost/gil/extension/dynamic_image/apply_operation.hpp @@ -0,0 +1,61 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_APPLY_OPERATION_HPP +#define GIL_APPLY_OPERATION_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Implements apply_operation for variants. Optionally performs type reduction +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on May 4, 2006 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include "apply_operation_base.hpp" +#include "variant.hpp" + +#ifndef GIL_REDUCE_CODE_BLOAT + +namespace boost { namespace gil { + +/// \ingroup Variant +/// \brief Invokes a generic mutable operation (represented as a unary function object) on a variant +template GIL_FORCEINLINE +typename UnaryOp::result_type apply_operation(variant& arg, UnaryOp op) { + return apply_operation_base(arg._bits, arg._index ,op); +} + +/// \ingroup Variant +/// \brief Invokes a generic constant operation (represented as a unary function object) on a variant +template GIL_FORCEINLINE +typename UnaryOp::result_type apply_operation(const variant& arg, UnaryOp op) { + return apply_operation_basec(arg._bits, arg._index ,op); +} + +/// \ingroup Variant +/// \brief Invokes a generic constant operation (represented as a binary function object) on two variants +template GIL_FORCEINLINE +typename BinaryOp::result_type apply_operation(const variant& arg1, const variant& arg2, BinaryOp op) { + return apply_operation_base(arg1._bits, arg1._index, arg2._bits, arg2._index, op); +} + +} } // namespace boost::gil + +#else + +#include "reduce.hpp" + +#endif + +#endif diff --git a/win32/include/boost/gil/extension/dynamic_image/apply_operation_base.hpp b/win32/include/boost/gil/extension/dynamic_image/apply_operation_base.hpp new file mode 100755 index 000000000..ee1782dd1 --- /dev/null +++ b/win32/include/boost/gil/extension/dynamic_image/apply_operation_base.hpp @@ -0,0 +1,162 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_APPLY_OPERATION_BASE_HPP +#define GIL_APPLY_OPERATION_BASE_HPP + +#include "../../gil_config.hpp" +#include "../../utilities.hpp" +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Given an object with run-time specified type (denoted as an array of Bits, dynamic index, and a static set of Types) and a generic operation, +/// casts the object to its appropriate type and applies the operation +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on November 6, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +namespace boost { namespace gil { + +/* +GENERATE_APPLY_FWD_OPS generates for every N functions that look like this (for N==2): + + template <> struct apply_operation_fwd_fn<3> { + template + typename UnaryOp::result_type apply(Bits& bits, std::size_t index, UnaryOp op) const { + typedef typename mpl::begin::type T0; + typedef typename mpl::next::type T1; + typedef typename mpl::next::type T2; + switch (index) { + case 0: return op(reinterpret_cast::type&>(bits)); + case 1: return op(reinterpret_cast::type&>(bits)); + case 2: return op(reinterpret_cast::type&>(bits)); + } + throw; + } + + template + typename UnaryOp::result_type applyc(const Bits& bits, std::size_t index, UnaryOp op) const { + typedef typename mpl::begin::type T0; + typedef typename mpl::next::type T1; + typedef typename mpl::next::type T2; + switch (index) { + case 0: return op(reinterpret_cast::type&>(bits)); + case 1: return op(reinterpret_cast::type&>(bits)); + case 2: return op(reinterpret_cast::type&>(bits)); + } + throw; + } + }; +*/ + +#define GIL_FWD_TYPEDEFS(z, N, text) T##N; typedef typename mpl::next::type +#define GIL_FWD_CASE(z, N, SUM) case N: return op(*gil_reinterpret_cast::type*>(&bits)); +#define GIL_FWD_CONST_CASE(z, N, SUM) case N: return op(*gil_reinterpret_cast_c::type*>(&bits)); + +#define GIL_APPLY_FWD_OP(z, N, text) \ + template <> struct apply_operation_fwd_fn { \ + template \ + typename UnaryOp::result_type apply(Bits& bits, std::size_t index, UnaryOp op) const { \ + typedef typename mpl::begin::type \ + BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY) \ + T##N; \ + switch (index) { \ + BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CASE, BOOST_PP_EMPTY) \ + } \ + throw; \ + } \ + template \ + typename UnaryOp::result_type applyc(const Bits& bits, std::size_t index, UnaryOp op) const { \ + typedef typename mpl::begin::type \ + BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY) \ + T##N; \ + switch (index) { \ + BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CONST_CASE,BOOST_PP_EMPTY) \ + } \ + throw; \ + } \ + }; + +#define GIL_GENERATE_APPLY_FWD_OPS(N) BOOST_PP_REPEAT(N, GIL_APPLY_FWD_OP, BOOST_PP_EMPTY) + +namespace detail { +template struct apply_operation_fwd_fn {}; + +// Create specializations of apply_operation_fn for each N 0..100 +GIL_GENERATE_APPLY_FWD_OPS(99) +} // namespace detail + +// unary application +template +typename Op::result_type GIL_FORCEINLINE apply_operation_basec(const Bits& bits, std::size_t index, Op op) { + return detail::apply_operation_fwd_fn::value>().template applyc(bits,index,op); +} + +// unary application +template +typename Op::result_type GIL_FORCEINLINE apply_operation_base( Bits& bits, std::size_t index, Op op) { + return detail::apply_operation_fwd_fn::value>().template apply(bits,index,op); +} + +namespace detail { + template + struct reduce_bind1 { + const T2& _t2; + mutable Op& _op; + + typedef typename Op::result_type result_type; + + reduce_bind1(const T2& t2, Op& op) : _t2(t2), _op(op) {} + + template GIL_FORCEINLINE result_type operator()(const T1& t1) { return _op(t1, _t2); } + }; + + template + struct reduce_bind2 { + const Bits1& _bits1; + std::size_t _index1; + mutable Op& _op; + + typedef typename Op::result_type result_type; + + reduce_bind2(const Bits1& bits1, std::size_t index1, Op& op) : _bits1(bits1), _index1(index1), _op(op) {} + + template GIL_FORCEINLINE result_type operator()(const T2& t2) { + return apply_operation_basec(_bits1, _index1, reduce_bind1(t2, _op)); + } + }; +} // namespace detail + +// Binary application by applying on each dimension separately +template +static typename Op::result_type GIL_FORCEINLINE apply_operation_base(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) { + return apply_operation_basec(bits2,index2,detail::reduce_bind2(bits1,index1,op)); +} + +#undef GIL_FWD_TYPEDEFS +#undef GIL_FWD_CASE +#undef GIL_FWD_CONST_CASE +#undef GIL_APPLY_FWD_OP +#undef GIL_GENERATE_APPLY_FWD_OPS +#undef BHS + +} } // namespace boost::gil + + +#endif diff --git a/win32/include/boost/gil/extension/dynamic_image/dynamic_at_c.hpp b/win32/include/boost/gil/extension/dynamic_image/dynamic_at_c.hpp new file mode 100755 index 000000000..9a87bc496 --- /dev/null +++ b/win32/include/boost/gil/extension/dynamic_image/dynamic_at_c.hpp @@ -0,0 +1,130 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_DYNAMIC_AT_C_HPP +#define GIL_DYNAMIC_AT_C_HPP + +#include "../../gil_config.hpp" +#include +#include +#include +#include + + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Constructs for static-to-dynamic integer convesion +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on May 4, 2006 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +namespace boost { namespace gil { + +#define GIL_AT_C_VALUE(z, N, text) mpl::at_c::type::value, +#define GIL_DYNAMIC_AT_C_LIMIT 226 // size of the maximum vector to handle + +#define GIL_AT_C_LOOKUP(z, NUM, text) \ + template \ + struct at_c_fn { \ + template inline \ + static ValueType apply(std::size_t index) { \ + static ValueType table[] = { \ + BOOST_PP_REPEAT(NUM, GIL_AT_C_VALUE, BOOST_PP_EMPTY) \ + }; \ + return table[index]; \ + } \ + }; + +namespace detail { + namespace at_c { + template struct at_c_fn; + BOOST_PP_REPEAT(GIL_DYNAMIC_AT_C_LIMIT, GIL_AT_C_LOOKUP, BOOST_PP_EMPTY) + + template struct at_c_impl; + + template <> + struct at_c_impl<0> { + template inline + static ValueType apply(std::size_t index) { + return at_c_fn<0,mpl::size::value>::template apply(index); + } + }; + + template <> + struct at_c_impl<1> { + template inline + static ValueType apply(std::size_t index) { + const std::size_t SIZE=mpl::size::value; + const std::size_t REM = SIZE % GIL_DYNAMIC_AT_C_LIMIT; + switch (index / GIL_DYNAMIC_AT_C_LIMIT) { + case 0: return at_c_fn<0 ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply(index); + case 1: return at_c_fn::template apply(index - GIL_DYNAMIC_AT_C_LIMIT); + }; + throw; + } + }; + + template <> + struct at_c_impl<2> { + template inline + static ValueType apply(std::size_t index) { + const std::size_t SIZE=mpl::size::value; + const std::size_t REM = SIZE % GIL_DYNAMIC_AT_C_LIMIT; + switch (index / GIL_DYNAMIC_AT_C_LIMIT) { + case 0: return at_c_fn<0 ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply(index); + case 1: return at_c_fn::template apply(index - GIL_DYNAMIC_AT_C_LIMIT); + case 2: return at_c_fn::template apply(index - GIL_DYNAMIC_AT_C_LIMIT*2); + }; + throw; + } + }; + + template <> + struct at_c_impl<3> { + template inline + static ValueType apply(std::size_t index) { + const std::size_t SIZE=mpl::size::value; + const std::size_t REM = SIZE % GIL_DYNAMIC_AT_C_LIMIT; + switch (index / GIL_DYNAMIC_AT_C_LIMIT) { + case 0: return at_c_fn<0 ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply(index); + case 1: return at_c_fn::template apply(index - GIL_DYNAMIC_AT_C_LIMIT); + case 2: return at_c_fn::template apply(index - GIL_DYNAMIC_AT_C_LIMIT*2); + case 3: return at_c_fn::template apply(index - GIL_DYNAMIC_AT_C_LIMIT*3); + }; + throw; + } + }; + } +} + +//////////////////////////////////////////////////////////////////////////////////// +/// +/// \brief Given an MPL Random Access Sequence and a dynamic index n, returns the value of the n-th element +/// It constructs a lookup table at compile time +/// +//////////////////////////////////////////////////////////////////////////////////// + +template inline +ValueType at_c(std::size_t index) { + const std::size_t Size=mpl::size::value; + return detail::at_c::at_c_impl::template apply(index); +} + +#undef GIL_AT_C_VALUE +#undef GIL_DYNAMIC_AT_C_LIMIT +#undef GIL_AT_C_LOOKUP + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/extension/dynamic_image/dynamic_image_all.hpp b/win32/include/boost/gil/extension/dynamic_image/dynamic_image_all.hpp new file mode 100755 index 000000000..9979a43b1 --- /dev/null +++ b/win32/include/boost/gil/extension/dynamic_image/dynamic_image_all.hpp @@ -0,0 +1,32 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_DYNAMICIMAGE_ALL_HPP +#define GIL_DYNAMICIMAGE_ALL_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Includes all of the GIL dynamic image extension files, for convenience +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on May 8, 2006 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include "../../gil_all.hpp" +#include "algorithm.hpp" +#include "any_image.hpp" +#include "apply_operation.hpp" +#include "variant.hpp" +#include "image_view_factory.hpp" + +#endif diff --git a/win32/include/boost/gil/extension/dynamic_image/image_view_factory.hpp b/win32/include/boost/gil/extension/dynamic_image/image_view_factory.hpp new file mode 100755 index 000000000..1253f0bd9 --- /dev/null +++ b/win32/include/boost/gil/extension/dynamic_image/image_view_factory.hpp @@ -0,0 +1,212 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_DYNAMICIMAGE_IMAGE_VIEWS_HPP +#define GIL_DYNAMICIMAGE_IMAGE_VIEWS_HPP + +/*! +/// \file +/// \brief Methods for constructing any image views from other any image views +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on January 31, 2007 +/// Extends image view factory to runtime type-specified views (any_image_view) +*/ + +#include "any_image_view.hpp" +#include "../../image_view_factory.hpp" + +namespace boost { namespace gil { + +namespace detail { +template struct flipped_up_down_view_fn { + typedef Result result_type; + template result_type operator()(const View& src) const { return result_type(flipped_up_down_view(src)); } +}; +template struct flipped_left_right_view_fn { + typedef Result result_type; + template result_type operator()(const View& src) const { return result_type(flipped_left_right_view(src)); } +}; +template struct rotated90cw_view_fn { + typedef Result result_type; + template result_type operator()(const View& src) const { return result_type(rotated90cw_view(src)); } +}; +template struct rotated90ccw_view_fn { + typedef Result result_type; + template result_type operator()(const View& src) const { return result_type(rotated90ccw_view(src)); } +}; +template struct tranposed_view_fn { + typedef Result result_type; + template result_type operator()(const View& src) const { return result_type(tranposed_view(src)); } +}; +template struct rotated180_view_fn { + typedef Result result_type; + template result_type operator()(const View& src) const { return result_type(rotated180_view(src)); } +}; +template struct subimage_view_fn { + typedef Result result_type; + subimage_view_fn(const point2& topleft, const point2& dimensions) : _topleft(topleft), _size2(dimensions) {} + point2 _topleft,_size2; + template result_type operator()(const View& src) const { return result_type(subimage_view(src,_topleft,_size2)); } +}; +template struct subsampled_view_fn { + typedef Result result_type; + subsampled_view_fn(const point2& step) : _step(step) {} + point2 _step; + template result_type operator()(const View& src) const { return result_type(subsampled_view(src,_step)); } +}; +template struct nth_channel_view_fn { + typedef Result result_type; + nth_channel_view_fn(int n) : _n(n) {} + int _n; + template result_type operator()(const View& src) const { return result_type(nth_channel_view(src,_n)); } +}; +template struct color_converted_view_fn { + typedef Result result_type; + template result_type operator()(const View& src) const { return result_type(color_converted_view(src)); } +}; +} // namespace detail + + +/// \ingroup ImageViewTransformationsFlipUD +template inline // Models MPL Random Access Container of models of ImageViewConcept +typename dynamic_y_step_type >::type flipped_up_down_view(const any_image_view& src) { + return apply_operation(src,detail::flipped_up_down_view_fn >::type>()); +} + +/// \ingroup ImageViewTransformationsFlipLR +template inline // Models MPL Random Access Container of models of ImageViewConcept +typename dynamic_x_step_type >::type flipped_left_right_view(const any_image_view& src) { + return apply_operation(src,detail::flipped_left_right_view_fn >::type>()); +} + +/// \ingroup ImageViewTransformationsTransposed +template inline // Models MPL Random Access Container of models of ImageViewConcept +typename dynamic_xy_step_transposed_type >::type transposed_view(const any_image_view& src) { + return apply_operation(src,detail::tranposed_view_fn >::type>()); +} + +/// \ingroup ImageViewTransformations90CW +template inline // Models MPL Random Access Container of models of ImageViewConcept +typename dynamic_xy_step_transposed_type >::type rotated90cw_view(const any_image_view& src) { + return apply_operation(src,detail::rotated90cw_view_fn >::type>()); +} + +/// \ingroup ImageViewTransformations90CCW +template inline // Models MPL Random Access Container of models of ImageViewConcept +typename dynamic_xy_step_transposed_type >::type rotated90ccw_view(const any_image_view& src) { + return apply_operation(src,detail::rotated90ccw_view_fn >::type>()); +} + +/// \ingroup ImageViewTransformations180 +template inline // Models MPL Random Access Container of models of ImageViewConcept +typename dynamic_xy_step_type >::type rotated180_view(const any_image_view& src) { + return apply_operation(src,detail::rotated180_view_fn >::type>()); +} + +/// \ingroup ImageViewTransformationsSubimage +template inline // Models MPL Random Access Container of models of ImageViewConcept +any_image_view subimage_view(const any_image_view& src, const point2& topleft, const point2& dimensions) { + return apply_operation(src,detail::subimage_view_fn >(topleft,dimensions)); +} + +/// \ingroup ImageViewTransformationsSubimage +template inline // Models MPL Random Access Container of models of ImageViewConcept +any_image_view subimage_view(const any_image_view& src, int xMin, int yMin, int width, int height) { + return apply_operation(src,detail::subimage_view_fn >(point2(xMin,yMin),point2(width,height))); +} + +/// \ingroup ImageViewTransformationsSubsampled +template inline // Models MPL Random Access Container of models of ImageViewConcept +typename dynamic_xy_step_type >::type subsampled_view(const any_image_view& src, const point2& step) { + return apply_operation(src,detail::subsampled_view_fn >::type>(step)); +} + +/// \ingroup ImageViewTransformationsSubsampled +template inline // Models MPL Random Access Container of models of ImageViewConcept +typename dynamic_xy_step_type >::type subsampled_view(const any_image_view& src, int xStep, int yStep) { + return apply_operation(src,detail::subsampled_view_fn >::type>(point2(xStep,yStep))); +} + +namespace detail { + template struct get_nthchannel_type { typedef typename nth_channel_view_type::type type; }; + template struct views_get_nthchannel_type : public mpl::transform > {}; +} + +/// \ingroup ImageViewTransformationsNthChannel +/// \brief Given a runtime source image view, returns the type of a runtime image view over a single channel of the source view +template +struct nth_channel_view_type > { + typedef any_image_view::type> type; +}; + +/// \ingroup ImageViewTransformationsNthChannel +template inline // Models MPL Random Access Container of models of ImageViewConcept +typename nth_channel_view_type >::type nth_channel_view(const any_image_view& src, int n) { + return apply_operation(src,detail::nth_channel_view_fn >::type>(n)); +} + +namespace detail { + template struct get_ccv_type : public color_converted_view_type {}; + template struct views_get_ccv_type : public mpl::transform > {}; +} + +/// \ingroup ImageViewTransformationsColorConvert +/// \brief Returns the type of a runtime-specified view, color-converted to a given pixel type with user specified color converter +template +struct color_converted_view_type,DstP,CC> { + typedef any_image_view::type> type; +}; + +/// \ingroup ImageViewTransformationsColorConvert +/// \brief overload of generic color_converted_view with user defined color-converter +template inline // Models MPL Random Access Container of models of ImageViewConcept +typename color_converted_view_type, DstP, CC>::type color_converted_view(const any_image_view& src,CC cc) { + return apply_operation(src,detail::color_converted_view_fn, DstP, CC>::type >()); +} + +/// \ingroup ImageViewTransformationsColorConvert +/// \brief Returns the type of a runtime-specified view, color-converted to a given pixel type with the default coor converter +template +struct color_converted_view_type,DstP> { + typedef any_image_view::type> type; +}; + +/// \ingroup ImageViewTransformationsColorConvert +/// \brief overload of generic color_converted_view with the default color-converter +template inline // Models MPL Random Access Container of models of ImageViewConcept +typename color_converted_view_type, DstP>::type color_converted_view(const any_image_view& src) { + return apply_operation(src,detail::color_converted_view_fn, DstP>::type >()); +} + + +/// \ingroup ImageViewTransformationsColorConvert +/// \brief overload of generic color_converted_view with user defined color-converter +/// These are workarounds for GCC 3.4, which thinks color_converted_view is ambiguous with the same method for templated views (in gil/image_view_factory.hpp) +template inline // Models MPL Random Access Container of models of ImageViewConcept +typename color_converted_view_type, DstP, CC>::type any_color_converted_view(const any_image_view& src,CC cc) { + return apply_operation(src,detail::color_converted_view_fn, DstP, CC>::type >()); +} + +/// \ingroup ImageViewTransformationsColorConvert +/// \brief overload of generic color_converted_view with the default color-converter +/// These are workarounds for GCC 3.4, which thinks color_converted_view is ambiguous with the same method for templated views (in gil/image_view_factory.hpp) +template inline // Models MPL Random Access Container of models of ImageViewConcept +typename color_converted_view_type, DstP>::type any_color_converted_view(const any_image_view& src) { + return apply_operation(src,detail::color_converted_view_fn, DstP>::type >()); +} + +/// \} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/extension/dynamic_image/reduce.hpp b/win32/include/boost/gil/extension/dynamic_image/reduce.hpp new file mode 100755 index 000000000..b1fbb2d04 --- /dev/null +++ b/win32/include/boost/gil/extension/dynamic_image/reduce.hpp @@ -0,0 +1,789 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ +/*************************************************************************************************/ + +#ifndef GIL_REDUCE_HPP +#define GIL_REDUCE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../metafunctions.hpp" +#include "../../typedefs.hpp" +#include "dynamic_at_c.hpp" + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Constructs for static-to-dynamic integer convesion +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on May 4, 2006 +/// +//////////////////////////////////////////////////////////////////////////////////////// + + +#ifdef GIL_REDUCE_CODE_BLOAT + + +// Max number of cases in the cross-expension of binary operation for it to be reduced as unary +#define GIL_BINARY_REDUCE_LIMIT 226 + +namespace boost { namespace mpl { + +/////////////////////////////////////////////////////// +/// Mapping vector - represents the mapping of one type vector to another +/// It is not a full-blown MPL Random Access Type sequence; just has at_c and size implemented +/// +/// SrcTypes, DstTypes: MPL Random Access Type Sequences +/// +/// Implements size and at_c to behave as if this is an MPL vector of integers +/////////////////////////////////////////////////////// + +template +struct mapping_vector {}; + +template +struct at_c, K> { + static const std::size_t value=size::value - order::type>::type::value +1; + typedef size_t type; +}; + +template +struct size > { + typedef typename size::type type; + static const std::size_t value=type::value; +}; + +/////////////////////////////////////////////////////// +/// copy_to_vector - copies a sequence (mpl::set) to vector. +/// +/// Temporary solution because I couldn't get mpl::copy to do this. +/// This is what I tried: +/// mpl::copy > >::type; +/// It works when SET is mpl::vector, but not when SET is mpl::set... +/////////////////////////////////////////////////////// + +namespace detail { + template + struct copy_to_vector_impl { + private: + typedef typename deref::type T; + typedef typename next::type next; + typedef typename copy_to_vector_impl::type rest; + public: + typedef typename push_front::type type; + }; + + template + struct copy_to_vector_impl { + typedef vector::type> type; + }; +} + +template +struct copy_to_vector { + typedef typename detail::copy_to_vector_impl::type, size::value>::type type; +}; + +template <> +struct copy_to_vector > { + typedef vector0<> type; +}; + +} } // boost::mpl + +namespace boost { namespace gil { + + +/////////////////////////////////////////////////////// +/// +/// unary_reduce, binary_reduce - given an MPL Random Access Sequence, +/// dynamically specified index to that container, the bits of an instance of the corresponding type and +/// a generic operation, invokes the operation on the given type +/// +/////////////////////////////////////////////////////// + + + + +/////////////////////////////////////////////////////// +/// +/// \brief Unary reduce. +/// +/// Given a set of types and an operation, reduces each type in the set (to reduced_t), then removes duplicates (to unique_t) +/// To apply the operation, first constructs a lookup table that maps each element from Types to its place in unique_t and uses it to map +/// the index to anther index (in map_index). Then invokes apply_operation_base on the unique types with the new index. +/// +/////////////////////////////////////////////////////// + +template +struct unary_reduce_impl { + typedef typename mpl::transform >::type reduced_t; + typedef typename mpl::copy, mpl::insert > >::type unique_t; + static const bool is_single=mpl::size::value==1; +}; + +template ::is_single> +struct unary_reduce : public unary_reduce_impl { + typedef typename unary_reduce_impl::reduced_t reduced_t; + typedef typename unary_reduce_impl::unique_t unique_t; + + static unsigned short inline map_index(std::size_t index) { + typedef typename mpl::mapping_vector indices_t; + return gil::at_c(index); + } + template GIL_FORCEINLINE static typename Op::result_type applyc(const Bits& bits, std::size_t index, Op op) { + return apply_operation_basec(bits,map_index(index),op); + } + + template GIL_FORCEINLINE static typename Op::result_type apply(Bits& bits, std::size_t index, Op op) { + return apply_operation_base(bits,map_index(index),op); + } +}; + +template +struct unary_reduce : public unary_reduce_impl { + typedef typename unary_reduce_impl::unique_t unique_t; + static unsigned short inline map_index(std::size_t index) { return 0; } + + template GIL_FORCEINLINE static typename Op::result_type applyc(const Bits& bits, std::size_t index, Op op) { + return op(*gil_reinterpret_cast_c::type*>(&bits)); + } + + template GIL_FORCEINLINE static typename Op::result_type apply(Bits& bits, std::size_t index, Op op) { + return op(*gil_reinterpret_cast::type*>(&bits)); + } +}; + + +/////////////////////////////////////////////////////// +/// +/// \brief Binary reduce. +/// +/// Given two sets of types, Types1 and Types2, first performs unary reduction on each. Then checks if the product of their sizes is above +/// the GIL_BINARY_REDUCE_LIMIT limit. If so, the operation is too complex to be binary-reduced and uses a specialization of binary_reduce_impl +/// to simply call the binary apply_operation_base (which performs two nested 1D apply operations) +/// If the operation is not too complex, uses the other specialization of binary_reduce_impl to create a cross-product of the input types +/// and performs unary reduction on the result (bin_reduced_t). To apply the binary operation, it simply invokes a unary apply_operation_base +/// on the reduced cross-product types +/// +/////////////////////////////////////////////////////// + +namespace detail { + struct pair_generator { + template struct apply { + typedef std::pair::type*, const typename mpl::at_c::type*> type; + }; + }; + + // When the types are not too large, applies reduce on their cross product + template + struct binary_reduce_impl { + //private: + typedef typename mpl::copy_to_vector::type vec1_types; + typedef typename mpl::copy_to_vector::type vec2_types; + + typedef mpl::cross_vector, pair_generator> BIN_TYPES; + typedef unary_reduce bin_reduced_t; + + static unsigned short inline map_index(std::size_t index1, std::size_t index2) { + unsigned short r1=Unary1::map_index(index1); + unsigned short r2=Unary2::map_index(index2); + return bin_reduced_t::map_index(r2*mpl::size::value + r1); + } + public: + typedef typename bin_reduced_t::unique_t unique_t; + + template + static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) { + std::pair pr(&bits1, &bits2); + return apply_operation_basec(pr, map_index(index1,index2),op); + } + }; + + // When the types are large performs a double-dispatch. Binary reduction is not done. + template + struct binary_reduce_impl { + template + static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) { + return apply_operation_base(bits1, index1, bits2, index2, op); + } + }; +} + + +template +struct binary_reduce { +//private: + typedef unary_reduce unary1_t; + typedef unary_reduce unary2_t; + + static const std::size_t CROSS_SIZE = mpl::size::value * + mpl::size::value; + + typedef detail::binary_reduce_implGIL_BINARY_REDUCE_LIMIT)> impl; +public: + template + static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) { + return impl::apply(bits1,index1,bits2,index2,op); + } +}; + +template +GIL_FORCEINLINE typename UnaryOp::result_type apply_operation(variant& arg, UnaryOp op) { + return unary_reduce::template apply(arg._bits, arg._index ,op); +} + +template +GIL_FORCEINLINE typename UnaryOp::result_type apply_operation(const variant& arg, UnaryOp op) { + return unary_reduce::template applyc(arg._bits, arg._index ,op); +} + +template +GIL_FORCEINLINE typename BinaryOp::result_type apply_operation(const variant& arg1, const variant& arg2, BinaryOp op) { + return binary_reduce::template apply(arg1._bits, arg1._index, arg2._bits, arg2._index, op); +} + +#undef GIL_BINARY_REDUCE_LIMIT + +} } // namespace gil + + +namespace boost { namespace mpl { +/////////////////////////////////////////////////////// +/// \brief Represents the virtual cross-product of the types generated from VecOfVecs. +/// \ingroup CrossVector +/// INPUT: +/// VecOfVecs - a vector of vector types. For example [ [A1,A2,A3], [B1,B2], [C1,C2,C3,C4] ] +/// Each element must be a non-empty mpl vector +/// TypeGen - a metafunction that generates a type from a vector of types, each of which can be +/// selected from the corresponding vector in VecOfVecs. For example, [A1, B2, C4] +/// +/// Represents the virtual cross-product of the types generated from VecOfVecs. +/// For example, [ TypeGen[A1,B1,C1], TypeGen[A2,B1,C1], TypeGen[A3,B1,C1], +/// TypeGen[A1,B2,C1], TypeGen[A2,B2,C1], TypeGen[A3,B2,C1], +/// TypeGen[A1,B1,C2], TypeGen[A2,B1,C2], TypeGen[A3,B1,C2], ... ] +/// +/// Models an immutable MPL Random Access Sequence +/// Traversal, random-access, etc, is defined, but mutable operations, +/// such as push_back and pop_front are not supported +/////////////////////////////////////////////////////// + +template +struct cross_vector {}; + +/// \brief Iterator of cross_vector +/// \ingroup CrossVectorIterator +template +struct cross_iterator { + typedef mpl::random_access_iterator_tag category; +}; + +/////////////////////////////////////////////////////// +/// Implementation of the iterator functions of cross vector +/////////////////////////////////////////////////////// + +/// \brief Dereferences a cross-vector iterator +/// \ingroup CrossVectorIterator +/// Creates a vector of the sizes of each type vector in VecOfVecs, then uses it as a basis +/// to represent the iterator's position K as a vector of indices. Extracts the corresponding type of +/// each input vector and passes the element types to the type generation function, which returns the dereferenced type +template +struct deref > { +private: + typedef typename detail::select_subvector_c::type DerefTypes; +public: + typedef typename TypeGen::template apply::type type; +}; + +/// \brief Increments a cross-vector iterator. +/// \ingroup CrossVectorIterator +template +struct next > { + typedef cross_iterator type; +}; + +/// \brief Decrements a cross-vector iterator. +/// \ingroup CrossVectorIterator +template +struct prior > { + typedef cross_iterator type; +}; + +/// \brief Advances a cross-vector iterator. +/// \ingroup CrossVectorIterator +template +struct advance, Distance > { + typedef cross_iterator type; +}; + +/// \brief Computes the distance between two cross-vector iterator-s. +/// \ingroup CrossVectorIterator +// (shortened the names of the template arguments - otherwise doxygen cannot parse this...) +template +struct distance, cross_iterator > { + typedef size_t type; +}; + +/////////////////////////////////////////////////////// +/// Implementation of cross vector +/////////////////////////////////////////////////////// +/// \brief Computes the size of a cross vector as the product of the sizes of all vectors in VecOfVecs +/// \ingroup CrossVector +template +struct size > { + typedef typename fold, times<_1, size<_2> > >::type type; + static const std::size_t value=type::value; +}; + +/// \brief Determines whether a cross vector is empty +/// \ingroup CrossVector +template +struct empty > { + typedef typename empty::type type; +}; + +/// \brief Returns the K-th element of a cross vector +/// \ingroup CrossVector +template +struct at, K> { +private: + typedef cross_iterator KthIterator; +public: + typedef typename deref::type type; +}; + +/// \brief Returns an iterator to the first element of a cross vector +/// \ingroup CrossVector +template +struct begin > { + typedef cross_iterator type; +}; + +/// \brief Returns an iterator to the last element of a cross vector +/// \ingroup CrossVector +template +struct end > { +private: + typedef cross_vector this_t; +public: + typedef cross_iterator::value> type; +}; + +/// \brief Returns the first element of a cross vector +/// \ingroup CrossVector +template +struct front > { +private: + typedef cross_vector this_t; +public: + typedef typename deref::type>::type type; +}; + +/// \brief Returns the last element of a cross vector +/// \ingroup CrossVector +template +struct back > { +private: + typedef cross_vector this_t; + typedef typename size::type size; + typedef typename minus >::type last_index; +public: + typedef typename at::type type; +}; + +/// \brief Transforms the elements of a cross vector +/// \ingroup CrossVector +template +struct transform, OPP > { + typedef typename lambda::type Op; + struct adapter { + template + struct apply { + typedef typename TypeGen::template apply::type orig_t; + typedef typename Op::template apply::type type; + }; + }; + typedef cross_vector type; +}; + +} } // boost::mpl + +namespace boost { namespace gil { + +template struct type_to_index; +template struct view_is_basic; +struct rgb_t; +struct lab_t; +struct hsb_t; +struct cmyk_t; +struct rgba_t; +struct error_t; + + +namespace detail { + //////////////////////////////////////////////////////// + //// + //// Generic reduce operation + //// + //////////////////////////////////////////////////////// + template + struct reduce { + typedef T type; + }; + + //////////////////////////////////////////////////////// + //// + //// Unary reduce_view operation. Splits into basic and non-basic views. + //// Algorithm-specific reduce should specialize for basic views + //// + //////////////////////////////////////////////////////// + + template + struct reduce_view_basic { + typedef View type; + }; + + template + struct reduce > + : public reduce_view_basic,view_is_basic >::value> {}; + + //////////////////////////////////////////////////////// + //// + //// Unary reduce_image operation. Splits into basic and non-basic images. + //// Algorithm-specific reduce should specialize for basic images + //// + //////////////////////////////////////////////////////// + + template + struct reduce_image_basic { + typedef Img type; + }; + + template + struct reduce > : public reduce_image_basic,image_is_basic >::value > {}; + + //////////////////////////////////////////////////////// + //// + //// Binary reduce_view operation. Splits into basic and non-basic views. + //// Algorithm-specific reduce should specialize for basic views + //// + //////////////////////////////////////////////////////// + + template + struct reduce_views_basic { + typedef std::pair type; + }; + + template + struct reduce*, const image_view*> > + : public reduce_views_basic,image_view, + mpl::and_ >, view_is_basic > >::value > + {}; + + + //////////////////////////////////////////////////////// + //// + //// Color space unary reduce operation. Reduce a color space to a base with the same number of channels + //// + //////////////////////////////////////////////////////// + + template + struct reduce_color_space { + typedef Cs type; + }; + + template <> struct reduce_color_space { typedef rgb_t type; }; + template <> struct reduce_color_space { typedef rgb_t type; }; + template <> struct reduce_color_space { typedef rgba_t type; }; + + /* + //////////////////////////////////////////////////////// + //// + //// Color space binary reduce operation. Given a source and destination color spaces, + //// returns a reduced source and destination color spaces that have the same mapping of channels + //// + //// Precondition: The two color spaces must be compatible (i.e. must have the same set of channels) + //////////////////////////////////////////////////////// + + template + struct type_vec_to_integer_impl { + typedef typename mpl::back::type last; + typedef typename mpl::pop_back::type rest; + static const int value = type_vec_to_integer_impl::value * Basis + last::value; + }; + + template + struct type_vec_to_integer_impl { + static const int value=0; + }; + + template + struct type_vec_to_integer { + static const int value = type_vec_to_integer_impl::value>::value; + }; + + // Given two color spaces and the mapping of the channels between them, returns the reduced pair of color spaces + // The default version performs no reduction + template + struct reduce_color_spaces_impl { + typedef SrcColorSpace first_t; + typedef DstColorSpace second_t; + }; + + // 012: RGB-RGB, bgr-bgr, lab-lab, hsb-hsb + template + struct reduce_color_spaces_impl { + typedef rgb_t first_t; + typedef rgb_t second_t; + }; + + // 210: RGB-bgr, bgr-RGB + template + struct reduce_color_spaces_impl { + typedef rgb_t first_t; + typedef bgr_t second_t; + }; + + // 0123: RGBA-RGBA, bgra-bgra, argb-argb, abgr-abgr cmyk-cmyk + template + struct reduce_color_spaces_impl { + typedef rgba_t first_t; + typedef rgba_t second_t; + }; + + // 3210: RGBA-abgr, bgra-argb, argb-bgra, abgr-RGBA + template + struct reduce_color_spaces_impl { + typedef rgba_t first_t; + typedef abgr_t second_t; + }; + + // 1230: RGBA-argb, bgra-abgr + template + struct reduce_color_spaces_impl { + typedef rgba_t first_t; + typedef argb_t second_t; + }; + + // 2103: RGBA-bgra, bgra-RGBA (uses subclass to ensure that base color space is not reduced to derived) + template + struct reduce_color_spaces_impl { + typedef rgba_t first_t; + typedef bgra_t second_t; + }; + + // 3012: argb-RGBA, abgr-bgra + template + struct reduce_color_spaces_impl { + typedef argb_t first_t; + typedef rgba_t second_t; + }; + + // 0321: argb-abgr, abgr-argb + template + struct reduce_color_spaces_impl { + typedef argb_t first_t; + typedef abgr_t second_t; + }; + + template + struct reduce_color_spaces { + typedef typename channel_order::type src_order_t; + typedef typename channel_order::type dst_order_t; + typedef typename mpl::transform >::type mapping; + static const int mapping_val = type_vec_to_integer::value; + + typedef typename reduce_color_spaces_impl::first_t _first_t; + typedef typename reduce_color_spaces_impl::second_t _second_t; + typedef typename mpl::and_, mpl::not_< color_space_is_base<_second_t> > > swap_t; + public: + typedef typename mpl::if_::type first_t; + typedef typename mpl::if_::type second_t; + }; +*/ +// TODO: Use the old code for reduce_color_spaces above to do color layout reduction + template + struct reduce_color_layouts { + typedef SrcLayout first_t; + typedef DstLayout second_t; + }; + + //////////////////////////////////////////////////////// + //// + //// Reduce for copy_pixels + //// + //////////////////////////////////////////////////////// + + struct copy_pixels_fn; + + /* + // 1D reduce for copy_pixels reduces the channel to mutable and the color space to its base with same dimensions + template + struct reduce_view_basic { + private: + typedef typename reduce_color_space::type Cs; // reduce the color space + typedef layout layout_t; + public: + typedef typename derived_view_type::type type; + }; +*/ + // Incompatible views cannot be used in copy_pixels - will throw std::bad_cast + template + struct reduce_copy_pixop_compat { + typedef error_t type; + }; + + // For compatible basic views, reduce their color spaces based on their channel mapping. + // Make the source immutable and the destination mutable (they should already be that way) + template + struct reduce_copy_pixop_compat { + typedef layout layout1; + typedef layout layout2; + + typedef typename reduce_color_layouts::first_t L1; + typedef typename reduce_color_layouts::second_t L2; + + typedef typename derived_view_type::type DV1; + typedef typename derived_view_type::type DV2; + + typedef std::pair type; + }; + + // The general 2D version branches into compatible and incompatible views + template + struct reduce_views_basic + : public reduce_copy_pixop_compat, view_is_mutable >::value > { + }; + + //////////////////////////////////////////////////////// + //// + //// Reduce for variant destructor (basic views have no destructor) + //// + //////////////////////////////////////////////////////// + + struct destructor_op; + template struct reduce_view_basic { typedef gray8_view_t type; }; + + //////////////////////////////////////////////////////// + //// + //// Reduce for get_dimensions (basic views and images have the same structure and the dimensions are contained at the beginning) + //// + //////////////////////////////////////////////////////// + + struct any_type_get_dimensions; + template struct reduce_view_basic { typedef gray8_view_t type; }; + template struct reduce_image_basic { typedef gray8_image_t type; }; + + //////////////////////////////////////////////////////// + //// + //// Reduce for get_num_channels (only color space matters) + //// + //////////////////////////////////////////////////////// + + struct any_type_get_num_channels; + template struct reduce_view_basic { + typedef typename View::color_space_t::base Cs; + typedef typename view_type::type>::type type; + }; + template struct reduce_image_basic { + typedef typename Img::color_space_t::base Cs; + typedef typename image_type::type>::type type; + }; + + //////////////////////////////////////////////////////// + //// + //// Reduce for resample_pixels (same as copy_pixels) + //// + //////////////////////////////////////////////////////// + + template struct resample_pixels_fn; + + template + struct reduce_view_basic, V, IsBasic> : public reduce_view_basic {}; + + template + struct reduce_views_basic, V1, V2, IsBasic> : public reduce_views_basic {}; + + //////////////////////////////////////////////////////// + //// + //// Reduce for copy_and_convert_pixels + //// (the only reduction could be made when views are compatible and have the same mapping, planarity and stepness) + //// + //////////////////////////////////////////////////////// + + + template class copy_and_convert_pixels_fn; + + // the only thing for 1D reduce is making them all mutable... + template + struct reduce_view_basic, View, IsBasic> + : public derived_view_type { + }; + + // For 2D reduce, if they have the same channels and color spaces (i.e. the same pixels) then copy_and_convert is just copy. + // In this case, reduce their common color space. In general make the first immutable and the second mutable + template + struct reduce_views_basic, V1, V2, AreBasic> { + typedef is_same Same; + + typedef reduce_color_space CsR; + typedef typename mpl::if_::type Cs1; + typedef typename mpl::if_::type Cs2; + + typedef typename derived_view_type, use_default, use_default, mpl::false_>::type DV1; + typedef typename derived_view_type, use_default, use_default, mpl::true_ >::type DV2; + + typedef std::pair type; + }; + + + //integral_image_generator + //resize_clobber_image_fnobj + //image_default_construct_fnobj + //fill_converted_pixels_fn + //bind(gil::detail::copy_pixels_fn(), _1, dst) + //bind(gil::detail::copy_pixels_fn(), src,_1) + + //bind(detail::copy_and_convert_pixels_fn(), _1, dst) + //bind(detail::copy_and_convert_pixels_fn(), src, _1) + //gil::detail::fill_pixels_fn(val) + + //detail::copy_construct_in_place_fn + //detail::equal_to_fn::base_t> + + //detail::any_image_get_view::view_t> + //detail::any_image_get_const_view::view_t> + //detail::flipped_up_down_view_fn > + //detail::flipped_left_right_view_fn::dynamic_step_t> + //detail::tranposed_view_fn::dynamic_step_t> + //detail::rotated90cw_view_fn::dynamic_step_t> + //detail::rotated90ccw_view_fn::dynamic_step_t> + //detail::rotated180_view_fn::dynamic_step_t> + //detail::subimage_view_fn > + //detail::subsampled_view_fn::dynamic_step_t> + //detail::nth_channel_view_fn > + //detail::color_converted_view_fn, DstP>::type > +} + +} } // namespace boost::gil + +#endif // GIL_REDUCE_CODE_BLOAT + + +#endif diff --git a/win32/include/boost/gil/extension/dynamic_image/variant.hpp b/win32/include/boost/gil/extension/dynamic_image/variant.hpp new file mode 100755 index 000000000..414818a3c --- /dev/null +++ b/win32/include/boost/gil/extension/dynamic_image/variant.hpp @@ -0,0 +1,194 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_DYNAMICIMAGE_VARIANT_HPP +#define GIL_DYNAMICIMAGE_VARIANT_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Support for run-time instantiated types +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on September 18, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include "../../gil_config.hpp" +#include "../../utilities.hpp" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace gil { + +namespace detail { + template struct type_to_index; + template struct reduce; + struct destructor_op { + typedef void result_type; + template result_type operator()(const T& t) const { t.~T(); } + }; + template void copy_construct_in_place(const T& t, Bits& bits); + template struct copy_construct_in_place_fn; +} +/** +\brief Represents a concrete instance of a run-time specified type from a set of types +\class variant +\ingroup Variant + +A concept is typically modeled by a collection of different types. They may be instantiations +of a templated type with different template parameters or even completely unrelated types. + +We call the type with which the concept is instantiated in a given place in the code "the concrete type". +The concrete type must be chosen at compile time, which sometimes is a severe limitation. +Consider, for example, having an image concept modeled by an image class templated over the color space. +It would be difficult to write a function that reads an image from file preserving its native color space, since the +type of the return value is only available at run time. It would be difficult to store images of different color +spaces in the same container or apply operations on them uniformly. + +The variant class addresses this deficiency. It allows for run-time instantiation of a class from a given set of allowed classes +specified at compile time. For example, the set of allowed classes may include 8-bit and 16-bit RGB and CMYK images. Such a variant +can be constructed with rgb8_image_t and then assigned a cmyk16_image_t. + +The variant has a templated constructor, which allows us to construct it with any concrete type instantiation. It can also perform a generic +operation on the concrete type via a call to apply_operation. The operation must be provided as a function object whose application +operator has a single parameter which can be instantiated with any of the allowed types of the variant. + +variant breaks down the instantiated type into a non-templated underlying base type and a unique instantiation +type identifier. In the most common implementation the concrete instantiation in stored 'in-place' - in 'bits_t'. +bits_t contains sufficient space to fit the largest of the instantiated objects. + +GIL's variant is similar to boost::variant in spirit (hence we borrow the name from there) but it differs in several ways from the current boost +implementation. Most notably, it does not take a variable number of template parameters but a single parameter defining the type enumeration. As +such it can be used more effectively in generic code. + +The Types parameter specifies the set of allowable types. It models MPL Random Access Container +*/ + +template // models MPL Random Access Container +class variant { + // size in bytes of the largest type in Types + static const std::size_t MAX_SIZE = mpl::fold, mpl::max > >::type::value; + static const std::size_t NUM_TYPES = mpl::size::value; +public: + typedef Types types_t; + + typedef struct { char data[MAX_SIZE]; } base_t; // empty space equal to the size of the largest type in Types + + // Default constructor - default construct the first type + variant() : _index(0) { new(&_bits) typename mpl::at_c::type(); } + virtual ~variant() { apply_operation(*this, detail::destructor_op()); } + + // Throws std::bad_cast if T is not in Types + template explicit variant(const T& obj){ _index=type_id(); if (_index==NUM_TYPES) throw std::bad_cast(); detail::copy_construct_in_place(obj, _bits); } + + // When doSwap is true, swaps obj with the contents of the variant. obj will contain default-constructed instance after the call + template explicit variant(T& obj, bool do_swap); + + template variant& operator=(const T& obj) { variant tmp(obj); swap(*this,tmp); return *this; } + variant& operator=(const variant& v) { variant tmp(v ); swap(*this,tmp); return *this; } + + variant(const variant& v) : _index(v._index) { apply_operation(v, detail::copy_construct_in_place_fn(_bits)); } + template void move_in(T& obj) { variant tmp(obj, true); swap(*this,tmp); } + + template friend bool operator==(const variant& x, const variant& y); + template friend bool operator!=(const variant& x, const variant& y); + + template static bool has_type() { return type_id()!=NUM_TYPES; } + + template const T& _dynamic_cast() const { if (!current_type_is()) throw std::bad_cast(); return *gil_reinterpret_cast_c(&_bits); } + template T& _dynamic_cast() { if (!current_type_is()) throw std::bad_cast(); return *gil_reinterpret_cast < T*>(&_bits); } + + template bool current_type_is() const { return type_id()==_index; } + +private: + template static std::size_t type_id() { return detail::type_to_index::value; } + + template friend void swap(variant& x, variant& y); + template friend typename UnaryOp::result_type apply_operation(variant& var, UnaryOp op); + template friend typename UnaryOp::result_type apply_operation(const variant& var, UnaryOp op); + template friend typename BinaryOp::result_type apply_operation(const variant& arg1, const variant& arg2, BinaryOp op); + + base_t _bits; + std::size_t _index; +}; + +namespace detail { + + template + void copy_construct_in_place(const T& t, Bits& bits) { + T& b=*gil_reinterpret_cast(&bits); + new(&b)T(t); // default-construct + } + + template + struct copy_construct_in_place_fn { + typedef void result_type; + Bits& _dst; + copy_construct_in_place_fn(Bits& dst) : _dst(dst) {} + + template void operator()(const T& src) const { copy_construct_in_place(src,_dst); } + }; + + template + struct equal_to_fn { + const Bits& _dst; + equal_to_fn(const Bits& dst) : _dst(dst) {} + + typedef bool result_type; + template result_type operator()(const T& x) const { + return x==*gil_reinterpret_cast_c(&_dst); + } + }; +} + +// When doSwap is true, swaps obj with the contents of the variant. obj will contain default-constructed instance after the call +template +template variant::variant(T& obj, bool do_swap) { + _index=type_id(); + if (_index==NUM_TYPES) throw std::bad_cast(); + + if (do_swap) { + new(&_bits) T(); // default construct + swap(obj, *gil_reinterpret_cast(&_bits)); + } else + detail::copy_construct_in_place(const_cast(obj), _bits); +} + +template +void swap(variant& x, variant& y) { + std::swap(x._bits,y._bits); + std::swap(x._index, y._index); +} + +template +inline bool operator==(const variant& x, const variant& y) { + return x._index==y._index && apply_operation(x,detail::equal_to_fn::base_t>(y._bits)); +} + +template +inline bool operator!=(const variant& x, const variant& y) { + return !(x==y); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/extension/io/dynamic_io.hpp b/win32/include/boost/gil/extension/io/dynamic_io.hpp new file mode 100755 index 000000000..5a913e1e7 --- /dev/null +++ b/win32/include/boost/gil/extension/io/dynamic_io.hpp @@ -0,0 +1,79 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ +/*************************************************************************************************/ + +#ifndef GIL_DYNAMIC_IO_H +#define GIL_DYNAMIC_IO_H + +/// \file +/// \brief Generic io functions for dealing with dynamic images +// +/// \author Hailin Jin and Lubomir Bourdev \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated May 30, 2006 + +#include +#include +#include "../../gil_config.hpp" +#include "../dynamic_image/any_image.hpp" + +namespace boost { namespace gil { + +namespace detail { + +template +struct construct_matched_t { + template + static bool apply(any_image& im,Pred pred) { + if (pred.template apply::type>()) { + typename mpl::at_c::type x; + im.move_in(x); + return true; + } else return construct_matched_t::apply(im,pred); + } +}; +template <> +struct construct_matched_t<0> { + template + static bool apply(any_image&,Pred) {return false;} +}; + +// A function object that can be passed to apply_operation. +// Given a predicate IsSupported taking a view type and returning an MPL boolean, +// calls the apply method of OpClass with the view if the given view IsSupported, or throws an exception otherwise +template +class dynamic_io_fnobj { + OpClass* _op; + + template + void apply(const View& view,mpl::true_ ) {_op->apply(view);} + template + void apply(const View& view,mpl::false_) {io_error("dynamic_io: unsupported view type for the given file format");} +public: + dynamic_io_fnobj(OpClass* op) : _op(op) {} + + typedef void result_type; + + template + void operator()(const View& view) {apply(view,typename IsSupported::template apply::type());} +}; + +} // namespace detail + +/// \brief Within the any_image, constructs an image with the given dimensions +/// and a type that satisfies the given predicate +template +inline bool construct_matched(any_image& im,Pred pred) { + return detail::construct_matched_t::value>::apply(im,pred); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/extension/io/io_error.hpp b/win32/include/boost/gil/extension/io/io_error.hpp new file mode 100755 index 000000000..29e1842bf --- /dev/null +++ b/win32/include/boost/gil/extension/io/io_error.hpp @@ -0,0 +1,51 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ +/*************************************************************************************************/ + +#ifndef GIL_IO_ERROR_H +#define GIL_IO_ERROR_H + +/// \file +/// \brief Handle input-output errors +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on May 30, 2006 + +#include +#include "../../gil_config.hpp" +#include + +namespace boost { namespace gil { + +inline void io_error(const char* descr) { throw std::ios_base::failure(descr); } +inline void io_error_if(bool expr, const char* descr="") { if (expr) io_error(descr); } + +namespace detail { + class file_mgr { + protected: + shared_ptr _fp; + + struct null_deleter { void operator()(void const*) const {} }; + file_mgr(FILE* file) : _fp(file, null_deleter()) {} + + file_mgr(const char* filename, const char* flags) { + FILE* fp; + io_error_if((fp=fopen(filename,flags))==NULL, "file_mgr: failed to open file"); + _fp=shared_ptr(fp,fclose); + } + + public: + FILE* get() { return _fp.get(); } + }; +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/extension/io/jpeg_dynamic_io.hpp b/win32/include/boost/gil/extension/io/jpeg_dynamic_io.hpp new file mode 100755 index 000000000..a996361f8 --- /dev/null +++ b/win32/include/boost/gil/extension/io/jpeg_dynamic_io.hpp @@ -0,0 +1,130 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_JPEG_DYNAMIC_IO_H +#define GIL_JPEG_DYNAMIC_IO_H + +/// \file +/// \brief Support for reading and writing JPEG files +/// Requires libjpeg +/// +/// \author Hailin Jin and Lubomir Bourdev \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated June 10, 2006 + +#include +#include +#include +#include +#include "../dynamic_image/dynamic_image_all.hpp" +#include "io_error.hpp" + +#include "jpeg_io.hpp" +#include "jpeg_io_private.hpp" +#include "dynamic_io.hpp" + +namespace boost { namespace gil { + +namespace detail { + +struct jpeg_write_is_supported { + template struct apply + : public mpl::bool_::is_supported> {}; +}; + +class jpeg_writer_dynamic : public jpeg_writer { + int _quality; +public: + jpeg_writer_dynamic(FILE* file, int quality=100) : jpeg_writer(file) , _quality(quality) {} + jpeg_writer_dynamic(const char* filename, int quality=100) : jpeg_writer(filename), _quality(quality) {} + + template + void write_view(const any_image_view& runtime_view) { + dynamic_io_fnobj op(this); + apply_operation(runtime_view,op); + } +}; + +class jpeg_type_format_checker { + J_COLOR_SPACE _color_type; +public: + jpeg_type_format_checker(J_COLOR_SPACE color_type_in) : + _color_type(color_type_in) {} + template + bool apply() { + return jpeg_read_support::color_type==_color_type; + } +}; + +struct jpeg_read_is_supported { + template struct apply + : public mpl::bool_::is_supported> {}; +}; + +class jpeg_reader_dynamic : public jpeg_reader { +public: + jpeg_reader_dynamic(FILE* file) : jpeg_reader(file) {} + jpeg_reader_dynamic(const char* filename) : jpeg_reader(filename){} + + template + void read_image(any_image& im) { + if (!construct_matched(im,detail::jpeg_type_format_checker(_cinfo.out_color_space))) { + io_error("jpeg_reader_dynamic::read_image(): no matching image type between those of the given any_image and that of the file"); + } else { + im.recreate(get_dimensions()); + dynamic_io_fnobj op(this); + apply_operation(view(im),op); + } + } +}; + +} // namespace detail + + +/// \ingroup JPEG_IO +/// \brief reads a JPEG image into a run-time instantiated image +/// Opens the given JPEG file name, selects the first type in Images whose color space and channel are compatible to those of the image file +/// and creates a new image of that type with the dimensions specified by the image file. +/// Throws std::ios_base::failure if none of the types in Images are compatible with the type on disk. +template +inline void jpeg_read_image(const char* filename,any_image& im) { + detail::jpeg_reader_dynamic m(filename); + m.read_image(im); +} + +/// \ingroup JPEG_IO +/// \brief reads a JPEG image into a run-time instantiated image +template +inline void jpeg_read_image(const std::string& filename,any_image& im) { + jpeg_read_image(filename.c_str(),im); +} + +/// \ingroup JPEG_IO +/// \brief Saves the currently instantiated view to a jpeg file specified by the given jpeg image file name. +/// Throws std::ios_base::failure if the currently instantiated view type is not supported for writing by the I/O extension +/// or if it fails to create the file. +template +inline void jpeg_write_view(const char* filename,const any_image_view& runtime_view) { + detail::jpeg_writer_dynamic m(filename); + m.write_view(runtime_view); +} + +/// \ingroup JPEG_IO +/// \brief Saves the currently instantiated view to a jpeg file specified by the given jpeg image file name. +template +inline void jpeg_write_view(const std::string& filename,const any_image_view& runtime_view) { + jpeg_write_view(filename.c_str(),runtime_view); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/extension/io/jpeg_io.hpp b/win32/include/boost/gil/extension/io/jpeg_io.hpp new file mode 100755 index 000000000..207afef80 --- /dev/null +++ b/win32/include/boost/gil/extension/io/jpeg_io.hpp @@ -0,0 +1,202 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_JPEG_IO_H +#define GIL_JPEG_IO_H + +/// \file +/// \brief Support for reading and writing JPEG files +/// Requires libjpeg +/// \author Hailin Jin and Lubomir Bourdev \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated September 24, 2006 + +#include +#include +#include +#include +#include +extern "C" { +#include +} +#include "io_error.hpp" +#include "jpeg_io_private.hpp" + +namespace boost { namespace gil { + +/// \ingroup JPEG_IO +/// \brief Determines whether the given view type is supported for reading +template +struct jpeg_read_support { + BOOST_STATIC_CONSTANT(bool,is_supported= + (detail::jpeg_read_support_private::type, + typename color_space_type::type>::is_supported)); + BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type= + (detail::jpeg_read_support_private::type, + typename color_space_type::type>::color_type)); + BOOST_STATIC_CONSTANT(bool, value=is_supported); +}; + +/// \ingroup JPEG_IO +/// \brief Returns the width and height of the JPEG file at the specified location. +/// Throws std::ios_base::failure if the location does not correspond to a valid JPEG file +inline point2 jpeg_read_dimensions(const char* filename) { + detail::jpeg_reader m(filename); + return m.get_dimensions(); +} + +/// \ingroup JPEG_IO +/// \brief Returns the width and height of the JPEG file at the specified location. +/// Throws std::ios_base::failure if the location does not correspond to a valid JPEG file +inline point2 jpeg_read_dimensions(const std::string& filename) { + return jpeg_read_dimensions(filename.c_str()); +} + +/// \ingroup JPEG_IO +/// \brief Loads the image specified by the given jpeg image file name into the given view. +/// Triggers a compile assert if the view color space and channel depth are not supported by the JPEG library or by the I/O extension. +/// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its color space or channel depth are not +/// compatible with the ones specified by View, or if its dimensions don't match the ones of the view. +template +inline void jpeg_read_view(const char* filename,const View& view) { + BOOST_STATIC_ASSERT(jpeg_read_support::is_supported); + + detail::jpeg_reader m(filename); + m.apply(view); +} + +/// \ingroup JPEG_IO +/// \brief Loads the image specified by the given jpeg image file name into the given view. +template +inline void jpeg_read_view(const std::string& filename,const View& view) { + jpeg_read_view(filename.c_str(),view); +} + +/// \ingroup JPEG_IO +/// \brief Allocates a new image whose dimensions are determined by the given jpeg image file, and loads the pixels into it. +/// Triggers a compile assert if the image color space or channel depth are not supported by the JPEG library or by the I/O extension. +/// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its color space or channel depth are not +/// compatible with the ones specified by Image +template +inline void jpeg_read_image(const char* filename,Image& im) { + BOOST_STATIC_ASSERT(jpeg_read_support::is_supported); + + detail::jpeg_reader m(filename); + m.read_image(im); +} + +/// \ingroup JPEG_IO +/// \brief Allocates a new image whose dimensions are determined by the given jpeg image file, and loads the pixels into it. +template +inline void jpeg_read_image(const std::string& filename,Image& im) { + jpeg_read_image(filename.c_str(),im); +} + +/// \ingroup JPEG_IO +/// \brief Loads and color-converts the image specified by the given jpeg image file name into the given view. +/// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its dimensions don't match the ones of the view. +template +inline void jpeg_read_and_convert_view(const char* filename,const View& view,CC cc) { + detail::jpeg_reader_color_convert m(filename,cc); + m.apply(view); +} + +/// \ingroup JPEG_IO +/// \brief Loads and color-converts the image specified by the given jpeg image file name into the given view. +/// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its dimensions don't match the ones of the view. +template +inline void jpeg_read_and_convert_view(const char* filename,const View& view) { + detail::jpeg_reader_color_convert m(filename,default_color_converter()); + m.apply(view); +} + +/// \ingroup JPEG_IO +/// \brief Loads and color-converts the image specified by the given jpeg image file name into the given view. +template +inline void jpeg_read_and_convert_view(const std::string& filename,const View& view,CC cc) { + jpeg_read_and_convert_view(filename.c_str(),view); +} + +/// \ingroup JPEG_IO +/// \brief Loads and color-converts the image specified by the given jpeg image file name into the given view. +template +inline void jpeg_read_and_convert_view(const std::string& filename,const View& view) { + jpeg_read_and_convert_view(filename.c_str(),view); +} + +/// \ingroup JPEG_IO +/// \brief Allocates a new image whose dimensions are determined by the given jpeg image file, loads and color-converts the pixels into it. +/// Throws std::ios_base::failure if the file is not a valid JPEG file +template +inline void jpeg_read_and_convert_image(const char* filename,Image& im,CC cc) { + detail::jpeg_reader_color_convert m(filename,cc); + m.read_image(im); +} + +/// \ingroup JPEG_IO +/// \brief Allocates a new image whose dimensions are determined by the given jpeg image file, loads and color-converts the pixels into it. +/// Throws std::ios_base::failure if the file is not a valid JPEG file +template +inline void jpeg_read_and_convert_image(const char* filename,Image& im) { + detail::jpeg_reader_color_convert m(filename,default_color_converter()); + m.read_image(im); +} + +/// \ingroup JPEG_IO +/// \brief Allocates a new image whose dimensions are determined by the given jpeg image file, loads and color-converts the pixels into it. +template +inline void jpeg_read_and_convert_image(const std::string& filename,Image& im,CC cc) { + jpeg_read_and_convert_image(filename.c_str(),im); +} + +/// \ingroup JPEG_IO +/// \brief Allocates a new image whose dimensions are determined by the given jpeg image file, loads and color-converts the pixels into it. +template +inline void jpeg_read_and_convert_image(const std::string& filename,Image& im) { + jpeg_read_and_convert_image(filename.c_str(),im); +} + +/// \ingroup JPEG_IO +/// \brief Determines whether the given view type is supported for writing +template +struct jpeg_write_support { + BOOST_STATIC_CONSTANT(bool,is_supported= + (detail::jpeg_write_support_private::type, + typename color_space_type::type>::is_supported)); + BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type= + (detail::jpeg_write_support_private::type, + typename color_space_type::type>::color_type)); + BOOST_STATIC_CONSTANT(bool, value=is_supported); +}; + +/// \ingroup JPEG_IO +/// \brief Saves the view to a jpeg file specified by the given jpeg image file name. +/// Triggers a compile assert if the view color space and channel depth are not supported by the JPEG library or by the I/O extension. +/// Throws std::ios_base::failure if it fails to create the file. +template +inline void jpeg_write_view(const char* filename,const View& view,int quality=100) { + BOOST_STATIC_ASSERT(jpeg_write_support::is_supported); + + detail::jpeg_writer m(filename); + m.apply(view,quality); +} + +/// \ingroup JPEG_IO +/// \brief Saves the view to a jpeg file specified by the given jpeg image file name. +template +inline void jpeg_write_view(const std::string& filename,const View& view,int quality=100) { + jpeg_write_view(filename.c_str(),view,quality); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/extension/io/jpeg_io_private.hpp b/win32/include/boost/gil/extension/io/jpeg_io_private.hpp new file mode 100755 index 000000000..063e46562 --- /dev/null +++ b/win32/include/boost/gil/extension/io/jpeg_io_private.hpp @@ -0,0 +1,225 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_JPEG_IO_PRIVATE_H +#define GIL_JPEG_IO_PRIVATE_H + +/// \file +/// \brief Internal support for reading and writing JPEG files +/// \author Hailin Jin and Lubomir Bourdev \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated September 24, 2006 + +#include +#include +#include +#include "../../gil_all.hpp" +#include "io_error.hpp" + +namespace boost { namespace gil { + +namespace detail { + +// lbourdev: What is the advantage of having channel and colorspace together? Are there cases where they are interrelated? + +template +struct jpeg_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=false); + BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_UNKNOWN); +}; +template <> +struct jpeg_read_support_private { + BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8); + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_GRAYSCALE); +}; +template <> +struct jpeg_read_support_private { + BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8); + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_RGB); +}; +template <> +struct jpeg_read_support_private { + BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8); + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_CMYK); +}; +template +struct jpeg_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=false); + BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_UNKNOWN); +}; +template <> +struct jpeg_write_support_private { + BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8); + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_GRAYSCALE); +}; +template <> +struct jpeg_write_support_private { + BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8); + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_RGB); +}; +template <> +struct jpeg_write_support_private { + BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8); + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_CMYK); +}; + + +class jpeg_reader : public file_mgr { +protected: + jpeg_decompress_struct _cinfo; + jpeg_error_mgr _jerr; + + void init() { + _cinfo.err=jpeg_std_error(&_jerr); + jpeg_create_decompress(&_cinfo); + jpeg_stdio_src(&_cinfo,_fp.get()); + jpeg_read_header(&_cinfo,TRUE); + } +public: + jpeg_reader(FILE* file) : file_mgr(file) { init(); } + jpeg_reader(const char* filename) : file_mgr(filename, "rb") { init(); } + + ~jpeg_reader() { jpeg_destroy_decompress(&_cinfo); } + + template + void apply(const View& view) { + jpeg_start_decompress(&_cinfo); // lbourdev: Can this return an error? You need to check and throw. Check all other library methods that can return an error state... + io_error_if(_cinfo.data_precision!=8,"jpeg_reader::apply(): this image file is not supported"); + io_error_if(_cinfo.out_color_space!=jpeg_read_support_private::type, + typename color_space_type::type>::color_type, + "jpeg_reader::apply(): input view type does not match the image file"); + io_error_if(view.dimensions() != get_dimensions(), "jpeg_reader::apply(): input view dimensions do not match the image file"); + std::vector::type> > > row(view.width()); + JSAMPLE* row_address=(JSAMPLE*)&row.front(); + for(int y=0;y + void read_image(Image& im) { + im.recreate(get_dimensions()); + apply(view(im)); + } + + point2 get_dimensions() const { + return point2(_cinfo.image_width,_cinfo.image_height); + } +}; + +// This code will be simplified... +template +class jpeg_reader_color_convert : public jpeg_reader { +private: + CC _cc; +public: + jpeg_reader_color_convert(FILE* file,CC cc_in) : jpeg_reader(file),_cc(cc_in) {} + jpeg_reader_color_convert(FILE* file) : jpeg_reader(file) {} + jpeg_reader_color_convert(const char* filename,CC cc_in) : jpeg_reader(filename),_cc(cc_in) {} + jpeg_reader_color_convert(const char* filename) : jpeg_reader(filename) {} + template + void apply(const View& view) { + jpeg_start_decompress(&_cinfo); // lbourdev: Can this return an error? You need to check and throw. Check all other library methods that can return an error state... + io_error_if(_cinfo.data_precision!=8,"jpeg_reader_color_covert::apply(): this image file is not supported"); + io_error_if(view.dimensions() != get_dimensions(), "jpeg_reader_color_covert::apply(): input view dimensions don't match the image file"); + switch (_cinfo.out_color_space) { + case JCS_GRAYSCALE: { + std::vector row(view.width()); + JSAMPLE* row_address=(JSAMPLE*)&row.front(); + for(int y=0;y(_cc)); + } + break; + } + case JCS_RGB: { + std::vector row(view.width()); + JSAMPLE* row_address=(JSAMPLE*)&row.front(); + for(int y=0;y(_cc)); + } + break; + } + case JCS_CMYK: { + std::vector row(view.width()); + JSAMPLE* row_address=(JSAMPLE*)&row.front(); + for(int y=0;y(_cc)); + } + break; + } + default: + io_error("jpeg_reader_color_covert::apply(): unknown color type"); + } + jpeg_finish_decompress(&_cinfo); + } + template + void read_image(Image& im) { + im.recreate(get_dimensions()); + apply(view(im)); + } +}; + +class jpeg_writer : public file_mgr { + jpeg_compress_struct _cinfo; + jpeg_error_mgr _jerr; + + void init() { + _cinfo.err=jpeg_std_error(&_jerr); + jpeg_create_compress(&_cinfo); + jpeg_stdio_dest(&_cinfo,_fp.get()); + } +public: + jpeg_writer(FILE* file) : file_mgr(file) { init(); } + jpeg_writer(const char* filename) : file_mgr(filename, "wb") { init(); } + ~jpeg_writer() { jpeg_destroy_compress(&_cinfo); } + + template + void apply(const View& view,int quality=100) { + _cinfo.image_width = (JDIMENSION)view.width(); + _cinfo.image_height = (JDIMENSION)view.height(); + _cinfo.input_components=num_channels::value; + _cinfo.in_color_space = jpeg_write_support_private::type, + typename color_space_type::type>::color_type; + jpeg_set_defaults(&_cinfo); + jpeg_set_quality(&_cinfo, quality, TRUE); + jpeg_start_compress(&_cinfo, TRUE); + std::vector::type> > > row(view.width()); + JSAMPLE* row_address=(JSAMPLE*)&row.front(); + for (int y=0;y void png_read_image(const char*,any_image&) +// template void png_read_image(FILE*,any_image&,std::size_t) +// template void png_write_view(const char*,const any_image_view&) +// template void png_write_view(FILE*,const any_image_view&) + + +#include +#include +#include +#include +#include "../dynamic_image/dynamic_image_all.hpp" +#include "io_error.hpp" +#include "png_io.hpp" +#include "png_io_private.hpp" +#include "dynamic_io.hpp" + +namespace boost { namespace gil { + +namespace detail { + +struct png_write_is_supported { + template struct apply + : public mpl::bool_::is_supported> {}; +}; + +class png_writer_dynamic : public png_writer { +public: + png_writer_dynamic(FILE* file ) : png_writer(file) {} + png_writer_dynamic(const char* filename) : png_writer(filename){} + + template + void write_view(const any_image_view& runtime_view) { + dynamic_io_fnobj op(this); + apply_operation(runtime_view,op); + } +}; + +class png_type_format_checker { + int _bit_depth; + int _color_type; +public: + png_type_format_checker(int bit_depth_in,int color_type_in) : + _bit_depth(bit_depth_in),_color_type(color_type_in) {} + template + bool apply() { + return png_read_support::bit_depth==_bit_depth && + png_read_support::color_type==_color_type; + } +}; + +struct png_read_is_supported { + template struct apply + : public mpl::bool_::is_supported> {}; +}; + +class png_reader_dynamic : public png_reader { +public: + png_reader_dynamic(FILE* file) : png_reader(file) {} + png_reader_dynamic(const char* filename) : png_reader(filename){} + + template + void read_image(any_image& im) { + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; + png_get_IHDR(_png_ptr, _info_ptr, + &width, &height,&bit_depth,&color_type,&interlace_type, + int_p_NULL, int_p_NULL); + if (!construct_matched(im,png_type_format_checker(bit_depth,color_type))) { + io_error("png_reader_dynamic::read_image(): no matching image type between those of the given any_image and that of the file"); + } else { + im.recreate(width,height); + dynamic_io_fnobj op(this); + apply_operation(view(im),op); + } + } +}; + +} // namespace detail + +/// \ingroup PNG_IO +/// \brief reads a PNG image into a run-time instantiated image +/// Opens the given png file name, selects the first type in Images whose color space and channel are compatible to those of the image file +/// and creates a new image of that type with the dimensions specified by the image file. +/// Throws std::ios_base::failure if none of the types in Images are compatible with the type on disk. +template +inline void png_read_image(const char* filename,any_image& im) { + detail::png_reader_dynamic m(filename); + m.read_image(im); +} + +/// \ingroup PNG_IO +/// \brief reads a PNG image into a run-time instantiated image +template +inline void png_read_image(const std::string& filename,any_image& im) { + png_read_image(filename.c_str(),im); +} + +/// \ingroup PNG_IO +/// \brief Saves the currently instantiated view to a png file specified by the given png image file name. +/// Throws std::ios_base::failure if the currently instantiated view type is not supported for writing by the I/O extension +/// or if it fails to create the file. +template +inline void png_write_view(const char* filename,const any_image_view& runtime_view) { + detail::png_writer_dynamic m(filename); + m.write_view(runtime_view); +} + +/// \ingroup PNG_IO +/// \brief Saves the currently instantiated view to a png file specified by the given png image file name. +template +inline void png_write_view(const std::string& filename,const any_image_view& runtime_view) { + png_write_view(filename.c_str(),runtime_view); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/extension/io/png_io.hpp b/win32/include/boost/gil/extension/io/png_io.hpp new file mode 100755 index 000000000..3ab02f9a5 --- /dev/null +++ b/win32/include/boost/gil/extension/io/png_io.hpp @@ -0,0 +1,214 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_PNG_IO_H +#define GIL_PNG_IO_H + +/// \file +/// \brief Support for reading and writing PNG files +/// Requires libpng and zlib! +// +// We are currently providing the following functions: +// point2 png_read_dimensions(const char*) +// template void png_read_view(const char*,const View&) +// template void png_read_image(const char*,image&) +// template void png_write_view(const char*,const View&) +// template struct png_read_support; +// template struct png_write_support; +// +/// \author Hailin Jin and Lubomir Bourdev \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated September 24, 2006 + +#include +#include +extern "C" { +#include "png.h" +} +#include +#include "../../gil_config.hpp" +#include "../../utilities.hpp" +#include "io_error.hpp" +#include "png_io_private.hpp" + +namespace boost { namespace gil { + +/// \ingroup PNG_IO +/// \brief Returns the width and height of the PNG file at the specified location. +/// Throws std::ios_base::failure if the location does not correspond to a valid PNG file +inline point2 png_read_dimensions(const char *filename) { + detail::png_reader m(filename); + return m.get_dimensions(); +} + +/// \ingroup PNG_IO +/// \brief Returns the width and height of the PNG file at the specified location. +/// Throws std::ios_base::failure if the location does not correspond to a valid PNG file +inline point2 png_read_dimensions(const std::string& filename) { + return png_read_dimensions(filename.c_str()); +} + +/// \ingroup PNG_IO +/// \brief Determines whether the given view type is supported for reading +template +struct png_read_support { + BOOST_STATIC_CONSTANT(bool,is_supported= + (detail::png_read_support_private::type, + typename color_space_type::type>::is_supported)); + BOOST_STATIC_CONSTANT(int,bit_depth= + (detail::png_read_support_private::type, + typename color_space_type::type>::bit_depth)); + BOOST_STATIC_CONSTANT(int,color_type= + (detail::png_read_support_private::type, + typename color_space_type::type>::color_type)); + BOOST_STATIC_CONSTANT(bool, value=is_supported); +}; + +/// \ingroup PNG_IO +/// \brief Loads the image specified by the given png image file name into the given view. +/// Triggers a compile assert if the view color space and channel depth are not supported by the PNG library or by the I/O extension. +/// Throws std::ios_base::failure if the file is not a valid PNG file, or if its color space or channel depth are not +/// compatible with the ones specified by View, or if its dimensions don't match the ones of the view. +template +inline void png_read_view(const char* filename,const View& view) { + BOOST_STATIC_ASSERT(png_read_support::is_supported); + detail::png_reader m(filename); + m.apply(view); +} + +/// \ingroup PNG_IO +/// \brief Loads the image specified by the given png image file name into the given view. +template +inline void png_read_view(const std::string& filename,const View& view) { + png_read_view(filename.c_str(),view); +} + +/// \ingroup PNG_IO +/// \brief Allocates a new image whose dimensions are determined by the given png image file, and loads the pixels into it. +/// Triggers a compile assert if the image color space or channel depth are not supported by the PNG library or by the I/O extension. +/// Throws std::ios_base::failure if the file is not a valid PNG file, or if its color space or channel depth are not +/// compatible with the ones specified by Image +template +inline void png_read_image(const char* filename,Image& im) { + BOOST_STATIC_ASSERT(png_read_support::is_supported); + detail::png_reader m(filename); + m.read_image(im); +} + +/// \ingroup PNG_IO +/// \brief Allocates a new image whose dimensions are determined by the given png image file, and loads the pixels into it. +template +inline void png_read_image(const std::string& filename,Image& im) { + png_read_image(filename.c_str(),im); +} + +/// \ingroup PNG_IO +/// \brief Loads the image specified by the given png image file name and color-converts it into the given view. +/// Throws std::ios_base::failure if the file is not a valid PNG file, or if its dimensions don't match the ones of the view. +template +inline void png_read_and_convert_view(const char* filename,const View& view,CC cc) { + detail::png_reader_color_convert m(filename,cc); + m.apply(view); +} + +/// \ingroup PNG_IO +/// \brief Loads the image specified by the given png image file name and color-converts it into the given view. +/// Throws std::ios_base::failure if the file is not a valid PNG file, or if its dimensions don't match the ones of the view. +template +inline void png_read_and_convert_view(const char* filename,const View& view) { + detail::png_reader_color_convert m(filename,default_color_converter()); + m.apply(view); +} + +/// \ingroup PNG_IO +/// \brief Loads the image specified by the given png image file name and color-converts it into the given view. +template +inline void png_read_and_convert_view(const std::string& filename,const View& view,CC cc) { + png_read_and_convert_view(filename.c_str(),view,cc); +} + +/// \ingroup PNG_IO +/// \brief Loads the image specified by the given png image file name and color-converts it into the given view. +template +inline void png_read_and_convert_view(const std::string& filename,const View& view) { + png_read_and_convert_view(filename.c_str(),view); +} + +/// \ingroup PNG_IO +/// \brief Allocates a new image whose dimensions are determined by the given png image file, loads and color-converts the pixels into it. +/// Throws std::ios_base::failure if the file is not a valid PNG file +template +inline void png_read_and_convert_image(const char* filename,Image& im,CC cc) { + detail::png_reader_color_convert m(filename,cc); + m.read_image(im); +} + +/// \ingroup PNG_IO +/// \brief Allocates a new image whose dimensions are determined by the given png image file, loads and color-converts the pixels into it. +/// Throws std::ios_base::failure if the file is not a valid PNG file +template +inline void png_read_and_convert_image(const char* filename,Image& im) { + detail::png_reader_color_convert m(filename,default_color_converter()); + m.read_image(im); +} + +/// \ingroup PNG_IO +/// \brief Allocates a new image whose dimensions are determined by the given png image file, loads and color-converts the pixels into it. +template +inline void png_read_and_convert_image(const std::string& filename,Image& im,CC cc) { + png_read_and_convert_image(filename.c_str(),im,cc); +} + +/// \ingroup PNG_IO +/// \brief Allocates a new image whose dimensions are determined by the given png image file, loads and color-converts the pixels into it. +template +inline void png_read_and_convert_image(const std::string& filename,Image& im) { + png_read_and_convert_image(filename.c_str(),im); +} + +/// \ingroup PNG_IO +/// \brief Determines whether the given view type is supported for writing +template +struct png_write_support { + BOOST_STATIC_CONSTANT(bool,is_supported= + (detail::png_write_support_private::type, + typename color_space_type::type>::is_supported)); + BOOST_STATIC_CONSTANT(int,bit_depth= + (detail::png_write_support_private::type, + typename color_space_type::type>::bit_depth)); + BOOST_STATIC_CONSTANT(int,color_type= + (detail::png_write_support_private::type, + typename color_space_type::type>::color_type)); + BOOST_STATIC_CONSTANT(bool, value=is_supported); +}; + +/// \ingroup PNG_IO +/// \brief Saves the view to a png file specified by the given png image file name. +/// Triggers a compile assert if the view color space and channel depth are not supported by the PNG library or by the I/O extension. +/// Throws std::ios_base::failure if it fails to create the file. +template +inline void png_write_view(const char* filename,const View& view) { + BOOST_STATIC_ASSERT(png_write_support::is_supported); + detail::png_writer m(filename); + m.apply(view); +} + +/// \ingroup PNG_IO +/// \brief Saves the view to a png file specified by the given png image file name. +template +inline void png_write_view(const std::string& filename,const View& view) { + png_write_view(filename.c_str(),view); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/extension/io/png_io_private.hpp b/win32/include/boost/gil/extension/io/png_io_private.hpp new file mode 100755 index 000000000..8ded9009b --- /dev/null +++ b/win32/include/boost/gil/extension/io/png_io_private.hpp @@ -0,0 +1,359 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://stlab.adobe.com/gil for most recent version including documentation. +*/ +/*************************************************************************************************/ + +#ifndef GIL_PNG_IO_PRIVATE_H +#define GIL_PNG_IO_PRIVATE_H + +/// \file +/// \brief Internal support for reading and writing PNG files +/// \author Hailin Jin and Lubomir Bourdev \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated August 14, 2007 + +#include +#include +#include +#include "../../gil_all.hpp" +#include "io_error.hpp" + +namespace boost { namespace gil { + +namespace detail { + +static const std::size_t PNG_BYTES_TO_CHECK = 4; + +// lbourdev: These can be greatly simplified, for example: +template struct png_color_type {BOOST_STATIC_CONSTANT(int,color_type=0);}; +template<> struct png_color_type { BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); }; +template<> struct png_color_type { BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); }; +template<> struct png_color_type { BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA); }; + +template struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=false);}; +template <> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=true);}; +template <> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=true);}; +template <> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=true);}; +template <> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=true);}; +template <> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=true);}; +template <> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=true);}; + +template struct png_bit_depth {BOOST_STATIC_CONSTANT(int,bit_depth=sizeof(Channel)*8);}; + +template +struct png_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=false); + BOOST_STATIC_CONSTANT(int,bit_depth=0); + BOOST_STATIC_CONSTANT(int,color_type=0); +}; +template <> +struct png_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=8); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); +}; +template <> +struct png_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=8); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); +}; +template <> +struct png_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=8); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA); +}; +template <> +struct png_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=16); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); +}; +template <> +struct png_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=16); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); +}; +template <> +struct png_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=16); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA); +}; + +template +struct png_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=false); + BOOST_STATIC_CONSTANT(int,bit_depth=0); + BOOST_STATIC_CONSTANT(int,color_type=0); +}; +template <> +struct png_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=8); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); +}; +template <> +struct png_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=8); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); +}; +template <> +struct png_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=8); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA); +}; +template <> +struct png_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=16); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); +}; +template <> +struct png_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=16); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); +}; +template <> +struct png_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=16); + BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA); +}; + +class png_reader : public file_mgr { +protected: + png_structp _png_ptr; + png_infop _info_ptr; + + void init() { + char buf[PNG_BYTES_TO_CHECK]; + // read in some of the signature bytes + io_error_if(fread(buf, 1, PNG_BYTES_TO_CHECK, get()) != detail::PNG_BYTES_TO_CHECK, + "png_check_validity: fail to read file"); + // compare the first PNG_BYTES_TO_CHECK bytes of the signature. + io_error_if(png_sig_cmp((png_bytep)buf, (png_size_t)0, detail::PNG_BYTES_TO_CHECK)!=0, + "png_check_validity: invalid png file"); + + _png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); + io_error_if(_png_ptr==NULL,"png_get_file_size: fail to call png_create_write_struct()"); + // allocate/initialize the image information data + _info_ptr = png_create_info_struct(_png_ptr); + if (_info_ptr == NULL) { + png_destroy_read_struct(&_png_ptr,png_infopp_NULL,png_infopp_NULL); + io_error("png_get_file_size: fail to call png_create_info_struct()"); + } + if (setjmp(png_jmpbuf(_png_ptr))) { + //free all of the memory associated with the png_ptr and info_ptr + png_destroy_read_struct(&_png_ptr, &_info_ptr, png_infopp_NULL); + io_error("png_get_file_size: fail to call setjmp()"); + } + png_init_io(_png_ptr, get()); + png_set_sig_bytes(_png_ptr,PNG_BYTES_TO_CHECK); + png_read_info(_png_ptr, _info_ptr); + if (little_endian() && png_get_bit_depth(_png_ptr,_info_ptr)>8) + png_set_swap(_png_ptr); + } +public: + png_reader(FILE* file ) : file_mgr(file) { init(); } + png_reader(const char* filename) : file_mgr(filename, "rb") { init(); } + + ~png_reader() { + png_destroy_read_struct(&_png_ptr,&_info_ptr,png_infopp_NULL); + } + point2 get_dimensions() { + return point2(png_get_image_width(_png_ptr,_info_ptr), + png_get_image_height(_png_ptr,_info_ptr)); + } + template + void apply(const View& view) { + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; + png_get_IHDR(_png_ptr, _info_ptr, + &width, &height,&bit_depth,&color_type,&interlace_type, + int_p_NULL, int_p_NULL); + io_error_if(((png_uint_32)view.width()!=width || (png_uint_32)view.height()!= height), + "png_read_view: input view size does not match PNG file size"); + + if(png_read_support_private::type, + typename color_space_type::type>::bit_depth!=bit_depth || + png_read_support_private::type, + typename color_space_type::type>::color_type!=color_type) + io_error("png_read_view: input view type is incompatible with the image type"); + + std::vector::type, + layout::type> > > row(width); + for(png_uint_32 y=0;y + void read_image(Image& im) { + im.recreate(get_dimensions()); + apply(view(im)); + } +}; + +// This code will be simplified... +template +class png_reader_color_convert : public png_reader { +private: + CC _cc; +public: + png_reader_color_convert(FILE* file ,CC cc_in) : png_reader(file),_cc(cc_in) {} + png_reader_color_convert(FILE* file ) : png_reader(file) {} + png_reader_color_convert(const char* filename,CC cc_in) : png_reader(filename),_cc(cc_in) {} + png_reader_color_convert(const char* filename) : png_reader(filename) {} + template + void apply(const View& view) { + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; + png_get_IHDR(_png_ptr, _info_ptr, + &width, &height,&bit_depth,&color_type,&interlace_type, + int_p_NULL, int_p_NULL); + io_error_if(((png_uint_32)view.width()!=width || (png_uint_32)view.height()!= height), + "png_reader_color_convert::apply(): input view size does not match PNG file size"); + switch (color_type) { + case PNG_COLOR_TYPE_GRAY: + switch (bit_depth) { + case 8: { + std::vector row(width); + for(png_uint_32 y=0;y(_cc)); + } + break; + } + case 16: { + std::vector row(width); + for(png_uint_32 y=0;y(_cc)); + } + break; + } + default: io_error("png_reader_color_convert::apply(): unknown combination of color type and bit depth"); + } + break; + case PNG_COLOR_TYPE_RGB: + switch (bit_depth) { + case 8: { + std::vector row(width); + for(png_uint_32 y=0;y(_cc)); + } + break; + } + case 16: { + std::vector row(width); + for(png_uint_32 y=0;y(_cc)); + } + break; + } + default: io_error("png_reader_color_convert::apply(): unknown combination of color type and bit depth"); + } + break; + case PNG_COLOR_TYPE_RGBA: + switch (bit_depth) { + case 8: { + std::vector row(width); + for(png_uint_32 y=0;y(_cc)); + } + break; + } + case 16: { + std::vector row(width); + for(png_uint_32 y=0;y(_cc)); + } + break; + } + default: io_error("png_reader_color_convert::apply(): unknown combination of color type and bit depth"); + } + break; + default: io_error("png_reader_color_convert::apply(): unknown color type"); + } + png_read_end(_png_ptr,NULL); + } + template + void read_image(Image& im) { + im.recreate(get_dimensions()); + apply(view(im)); + } +}; + + +class png_writer : public file_mgr { +protected: + png_structp _png_ptr; + png_infop _info_ptr; + + void init() { + _png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); + io_error_if(!_png_ptr,"png_write_initialize: fail to call png_create_write_struct()"); + _info_ptr = png_create_info_struct(_png_ptr); + if (!_info_ptr) { + png_destroy_write_struct(&_png_ptr,png_infopp_NULL); + io_error("png_write_initialize: fail to call png_create_info_struct()"); + } + if (setjmp(png_jmpbuf(_png_ptr))) { + png_destroy_write_struct(&_png_ptr, &_info_ptr); + io_error("png_write_initialize: fail to call setjmp(png_jmpbuf())"); + } + png_init_io(_png_ptr,get()); + } +public: + png_writer(FILE* file ) : file_mgr(file) { init(); } + png_writer(const char* filename) : file_mgr(filename, "wb") { init(); } + + ~png_writer() { + png_destroy_write_struct(&_png_ptr,&_info_ptr); + } + template + void apply(const View& view) { + png_set_IHDR(_png_ptr, _info_ptr, view.width(), view.height(), + png_write_support_private::type, + typename color_space_type::type>::bit_depth, + png_write_support_private::type, + typename color_space_type::type>::color_type, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT); + png_write_info(_png_ptr,_info_ptr); + if (little_endian() && + png_write_support_private::type, + typename color_space_type::type>::bit_depth>8) + png_set_swap(_png_ptr); + std::vector::type, + layout::type> > > row(view.width()); + for(int y=0;y void tiff_read_image(const char*,any_image) +// template void tiff_write_view(const char*,any_image_view) +// + +#include +#include +#include "../dynamic_image/dynamic_image_all.hpp" +#include "io_error.hpp" +#include "tiff_io.hpp" +#include "dynamic_io.hpp" + +namespace boost { namespace gil { + +namespace detail { + +struct tiff_write_is_supported { + template struct apply + : public mpl::bool_::is_supported> {}; +}; + +class tiff_writer_dynamic : public tiff_writer { +public: + typedef void result_type; + tiff_writer_dynamic(const char* filename) : tiff_writer(filename) {} + + template + void write_view(const any_image_view& runtime_view) { + dynamic_io_fnobj op(this); + apply_operation(runtime_view,op); + } +}; + +class tiff_type_format_checker { + int _bit_depth; + int _color_type; +public: + tiff_type_format_checker(int bit_depth_in,int color_type_in) : + _bit_depth(bit_depth_in),_color_type(color_type_in) {} + template + bool apply() { + return tiff_read_support::bit_depth==_bit_depth && + tiff_read_support::color_type==_color_type; + } +}; + +struct tiff_read_is_supported { + template struct apply + : public mpl::bool_::is_supported> {}; +}; + +class tiff_reader_dynamic : public tiff_reader { +public: + tiff_reader_dynamic(const char* filename) : tiff_reader(filename) {} + + template + void read_image(any_image& im) { + int width,height; + unsigned short bps,photometric; + TIFFGetField(_tp,TIFFTAG_IMAGEWIDTH,&width); + TIFFGetField(_tp,TIFFTAG_IMAGELENGTH,&height); + TIFFGetField(_tp,TIFFTAG_BITSPERSAMPLE,&bps); + TIFFGetField(_tp,TIFFTAG_PHOTOMETRIC,&photometric); + if (!construct_matched(im,tiff_type_format_checker(bps,photometric))) { + io_error("tiff_reader_dynamic::read_image(): no matching image type between those of the given any_image and that of the file"); + } else { + im.recreate(width,height); + dynamic_io_fnobj op(this); + apply_operation(view(im),op); + } + } +}; + +} // namespace detail + +/// \ingroup TIFF_IO +/// \brief reads a TIFF image into a run-time instantiated image +/// Opens the given tiff file name, selects the first type in Images whose color space and channel are compatible to those of the image file +/// and creates a new image of that type with the dimensions specified by the image file. +/// Throws std::ios_base::failure if none of the types in Images are compatible with the type on disk. +template +inline void tiff_read_image(const char* filename,any_image& im) { + detail::tiff_reader_dynamic m(filename); + m.read_image(im); +} + +/// \ingroup TIFF_IO +/// \brief reads a TIFF image into a run-time instantiated image +template +inline void tiff_read_image(const std::string& filename,any_image& im) { + tiff_read_image(filename.c_str(),im); +} + +/// \ingroup TIFF_IO +/// \brief Saves the currently instantiated view to a tiff file specified by the given tiff image file name. +/// Throws std::ios_base::failure if the currently instantiated view type is not supported for writing by the I/O extension +/// or if it fails to create the file. +template +inline void tiff_write_view(const char* filename,const any_image_view& runtime_view) { + detail::tiff_writer_dynamic m(filename); + m.write_view(runtime_view); +} + +/// \ingroup TIFF_IO +/// \brief Saves the currently instantiated view to a tiff file specified by the given tiff image file name. +template +inline void tiff_write_view(const std::string& filename,const any_image_view& runtime_view) { + tiff_write_view(filename.c_str(),runtime_view); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/extension/io/tiff_io.hpp b/win32/include/boost/gil/extension/io/tiff_io.hpp new file mode 100755 index 000000000..2195d0010 --- /dev/null +++ b/win32/include/boost/gil/extension/io/tiff_io.hpp @@ -0,0 +1,491 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_TIFF_IO_H +#define GIL_TIFF_IO_H + +/// \file +/// \brief Support for reading and writing TIFF files +/// Requires libtiff! +/// \author Hailin Jin and Lubomir Bourdev \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated September 24, 2006 + +#include +#include +#include +#include +#include +#include "../../gil_all.hpp" +#include "io_error.hpp" + +namespace boost { namespace gil { + +namespace detail { + +template +struct tiff_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=false); + BOOST_STATIC_CONSTANT(int,bit_depth=0); + BOOST_STATIC_CONSTANT(int,color_type=0); +}; +template <> +struct tiff_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=8); + BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK); +}; +template <> +struct tiff_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=8); + BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB); +}; +template <> +struct tiff_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=16); + BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK); +}; +template <> +struct tiff_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=16); + BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB); +}; +template <> +struct tiff_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=32); + BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK); +}; +template <> +struct tiff_read_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=32); + BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB); +}; + +template +struct tiff_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=false); + BOOST_STATIC_CONSTANT(int,bit_depth=0); + BOOST_STATIC_CONSTANT(int,color_type=0); +}; +template <> +struct tiff_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=8); + BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK); +}; +template <> +struct tiff_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=8); + BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB); +}; +template <> +struct tiff_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=16); + BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK); +}; +template <> +struct tiff_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=16); + BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB); +}; +template <> +struct tiff_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=32); + BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK); +}; +template <> +struct tiff_write_support_private { + BOOST_STATIC_CONSTANT(bool,is_supported=true); + BOOST_STATIC_CONSTANT(int,bit_depth=32); + BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB); +}; + +class tiff_reader { +protected: + TIFF *_tp; +public: + tiff_reader(const char* filename) { + io_error_if((_tp=TIFFOpen(filename,"r"))==NULL, + "tiff_reader: fail to open file"); + } + ~tiff_reader() { TIFFClose(_tp); } + template + void apply(const View& view) { + unsigned short bps,photometric; + point2 dims=get_dimensions(); + io_error_if(TIFFGetField(_tp,TIFFTAG_BITSPERSAMPLE,&bps)!=1); + io_error_if(TIFFGetField(_tp,TIFFTAG_PHOTOMETRIC,&photometric)!=1); + io_error_if(dims!=view.dimensions(), + "tiff_read_view: input view size does not match TIFF file size"); + io_error_if(tiff_read_support_private::type, + typename color_space_type::type>::bit_depth!=bps || + tiff_read_support_private::type, + typename color_space_type::type>::color_type!=photometric, + "tiff_read_view: input view type is incompatible with the image type"); + std::size_t element_size=sizeof(pixel::type, + layout::type> >); + std::size_t size_to_allocate = (std::max)((std::size_t)view.width(), + (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size); + std::vector::type, + layout::type> > > row(size_to_allocate); + for (int y=0;y get_dimensions() { + int w,h; + io_error_if(TIFFGetField(_tp,TIFFTAG_IMAGEWIDTH, &w)!=1); + io_error_if(TIFFGetField(_tp,TIFFTAG_IMAGELENGTH,&h)!=1); + return point2(w,h); + } + + template + void read_image(Image& im) { + im.recreate(get_dimensions()); + apply(view(im)); + } +}; + +// This code will be simplified... +template +class tiff_reader_color_convert : public tiff_reader { +private: + CC _cc; +public: + tiff_reader_color_convert(const char* filename) : + tiff_reader(filename) {} + tiff_reader_color_convert(const char* filename,CC cc_in) : + tiff_reader(filename),_cc(cc_in) {} + template + void apply(const View& view) { + point2 dims=get_dimensions(); + unsigned short bps,photometric; + io_error_if(TIFFGetField(_tp,TIFFTAG_BITSPERSAMPLE,&bps)!=1); + io_error_if(TIFFGetField(_tp,TIFFTAG_PHOTOMETRIC,&photometric)!=1); + io_error_if(dims!=view.dimensions(), + "tiff_reader_color_convert::apply(): input view size does not match TIFF file size"); + switch (photometric) { + case PHOTOMETRIC_MINISBLACK: { + switch (bps) { + case 8: { + std::size_t element_size=sizeof(gray8_pixel_t); + std::size_t size_to_allocate = (std::max)((std::size_t)view.width(), + (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size); + std::vector row(size_to_allocate); + for (int y=0;y(_cc)); + } + break; + } + case 16: { + std::size_t element_size=sizeof(gray16_pixel_t); + std::size_t size_to_allocate = (std::max)((std::size_t)view.width(), + (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size); + std::vector row(size_to_allocate); + for (int y=0;y(_cc)); + } + break; + } + case 32: { + std::size_t element_size=sizeof(gray32f_pixel_t); + std::size_t size_to_allocate = (std::max)((std::size_t)view.width(), + (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size); + std::vector row(size_to_allocate); + for (int y=0;y(_cc)); + } + break; + } + default: + io_error("tiff_reader_color_convert::apply(): unknown combination of color type and bit depth"); + } + break; + } + case PHOTOMETRIC_RGB: { + switch (bps) { + case 8: { + std::size_t element_size=sizeof(rgb8_pixel_t); + std::size_t size_to_allocate = (std::max)((std::size_t)view.width(), + (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size); + std::vector row(size_to_allocate); + for (int y=0;y(_cc)); + } + break; + } + case 16: { + std::size_t element_size=sizeof(rgb16_pixel_t); + std::size_t size_to_allocate = (std::max)((std::size_t)view.width(), + (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size); + std::vector row(size_to_allocate); + for (int y=0;y(_cc)); + } + break; + } + case 32: { + std::size_t element_size=sizeof(rgb32f_pixel_t); + std::size_t size_to_allocate = (std::max)((std::size_t)view.width(), + (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size); + std::vector row(size_to_allocate); + for (int y=0;y(_cc)); + } + break; + } + default: + io_error("tiff_reader_color_convert::apply(): unknown combination of color type and bit depth"); + } + break; + } + default: { + // reads an image in incompatible format via TIFFReadRGBAImage + rgba8_image_t rgbaImg(dims); + io_error_if(!TIFFReadRGBAImage(_tp, dims.x, dims.y, (uint32*)&gil::view(rgbaImg)(0,0), 0), + "tiff_reader_color_convert::unsupported image format"); + copy_and_convert_pixels(flipped_up_down_view(const_view(rgbaImg)), view, _cc); + } + } + } + template + void read_image(Image& im) { + im.recreate(get_dimensions()); + apply(view(im)); + } +}; + +class tiff_writer { +protected: + TIFF* _tp; +public: + tiff_writer(const char *filename) { + io_error_if((_tp=TIFFOpen(filename,"w"))==NULL, + "tiff_writer: fail to open file"); + } + ~tiff_writer() {TIFFClose(_tp);} + template + void apply(const View& view) { + io_error_if(TIFFSetField(_tp,TIFFTAG_IMAGELENGTH, view.height())!=1); + io_error_if(TIFFSetField(_tp,TIFFTAG_IMAGEWIDTH, view.width())!=1); + io_error_if(TIFFSetField(_tp,TIFFTAG_PHOTOMETRIC, tiff_write_support_private::type, + typename color_space_type::type>::color_type)!=1); + io_error_if(TIFFSetField(_tp,TIFFTAG_RESOLUTIONUNIT, RESUNIT_NONE)!=1); + io_error_if(TIFFSetField(_tp,TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)!=1); + io_error_if(TIFFSetField(_tp,TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT)!=1); + io_error_if(TIFFSetField(_tp,TIFFTAG_SAMPLESPERPIXEL,num_channels::value)!=1); + io_error_if(TIFFSetField(_tp,TIFFTAG_BITSPERSAMPLE, tiff_write_support_private::type, + typename color_space_type::type>::bit_depth)!=1); + io_error_if(TIFFSetField(_tp,TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(_tp, 0))!=1); + std::vector::type, + layout::type> > > row(view.width()); + for (int y=0;y +struct tiff_read_support { + BOOST_STATIC_CONSTANT(bool,is_supported= + (detail::tiff_read_support_private::type, + typename color_space_type::type>::is_supported)); + BOOST_STATIC_CONSTANT(int,bit_depth= + (detail::tiff_read_support_private::type, + typename color_space_type::type>::bit_depth)); + BOOST_STATIC_CONSTANT(int,color_type= + (detail::tiff_read_support_private::type, + typename color_space_type::type>::color_type)); +}; + +/// \ingroup TIFF_IO +/// \brief Returns the width and height of the TIFF file at the specified location. +/// Throws std::ios_base::failure if the location does not correspond to a valid TIFF file +inline point2 tiff_read_dimensions(const char* filename) { + detail::tiff_reader m(filename); + return m.get_dimensions(); +} + +/// \ingroup TIFF_IO +/// \brief Returns the width and height of the TIFF file at the specified location. +/// Throws std::ios_base::failure if the location does not correspond to a valid TIFF file +inline point2 tiff_read_dimensions(const std::string& filename) { + return tiff_read_dimensions(filename.c_str()); +} + +/// \ingroup TIFF_IO +/// \brief Loads the image specified by the given tiff image file name into the given view. +/// Triggers a compile assert if the view color space and channel depth are not supported by the TIFF library or by the I/O extension. +/// Throws std::ios_base::failure if the file is not a valid TIFF file, or if its color space or channel depth are not +/// compatible with the ones specified by View, or if its dimensions don't match the ones of the view. +template +inline void tiff_read_view(const char* filename,const View& view) { + BOOST_STATIC_ASSERT(tiff_read_support::is_supported); + detail::tiff_reader m(filename); + m.apply(view); +} + +/// \ingroup TIFF_IO +/// \brief Loads the image specified by the given tiff image file name into the given view. +template +inline void tiff_read_view(const std::string& filename,const View& view) { + tiff_read_view(filename.c_str(),view); +} + +/// \ingroup TIFF_IO +/// \brief Allocates a new image whose dimensions are determined by the given tiff image file, and loads the pixels into it. +/// Triggers a compile assert if the image color space or channel depth are not supported by the TIFF library or by the I/O extension. +/// Throws std::ios_base::failure if the file is not a valid TIFF file, or if its color space or channel depth are not +/// compatible with the ones specified by Image +template +void tiff_read_image(const char* filename,Image& im) { + BOOST_STATIC_ASSERT(tiff_read_support::is_supported); + detail::tiff_reader m(filename); + m.read_image(im); +} + +/// \ingroup TIFF_IO +/// \brief Allocates a new image whose dimensions are determined by the given tiff image file, and loads the pixels into it. +template +inline void tiff_read_image(const std::string& filename,Image& im) { + tiff_read_image(filename.c_str(),im); +} + +/// \ingroup TIFF_IO +/// \brief Loads and color-converts the image specified by the given tiff image file name into the given view. +/// Throws std::ios_base::failure if the file is not a valid TIFF file, or if its dimensions don't match the ones of the view. +template +inline void tiff_read_and_convert_view(const char* filename,const View& view,CC cc) { + detail::tiff_reader_color_convert m(filename,cc); + m.apply(view); +} + +/// \ingroup TIFF_IO +/// \brief Loads and color-converts the image specified by the given tiff image file name into the given view. +/// Throws std::ios_base::failure if the file is not a valid TIFF file, or if its dimensions don't match the ones of the view. +template +inline void tiff_read_and_convert_view(const char* filename,const View& view) { + detail::tiff_reader_color_convert m(filename,default_color_converter()); + m.apply(view); +} + +/// \ingroup TIFF_IO +/// \brief Loads and color-converts the image specified by the given tiff image file name into the given view. +template +inline void tiff_read_and_convert_view(const std::string& filename,const View& view,CC cc) { + tiff_read_and_convert_view(filename.c_str(),view,cc); +} + +/// \ingroup TIFF_IO +/// \brief Loads and color-converts the image specified by the given tiff image file name into the given view. +template +inline void tiff_read_and_convert_view(const std::string& filename,const View& view) { + tiff_read_and_convert_view(filename.c_str(),view); +} + +/// \ingroup TIFF_IO +/// \brief Allocates a new image whose dimensions are determined by the given tiff image file, loads and color-converts the pixels into it. +/// Throws std::ios_base::failure if the file is not a valid TIFF file +template +void tiff_read_and_convert_image(const char* filename,Image& im,CC cc) { + detail::tiff_reader_color_convert m(filename,cc); + m.read_image(im); +} + +/// \ingroup TIFF_IO +/// \brief Allocates a new image whose dimensions are determined by the given tiff image file, loads and color-converts the pixels into it. +/// Throws std::ios_base::failure if the file is not a valid TIFF file +template +void tiff_read_and_convert_image(const char* filename,Image& im) { + detail::tiff_reader_color_convert m(filename,default_color_converter()); + m.read_image(im); +} + +/// \ingroup TIFF_IO +/// \brief Allocates a new image whose dimensions are determined by the given tiff image file, loads and color-converts the pixels into it. +template +inline void tiff_read_and_convert_image(const std::string& filename,Image& im,CC cc) { + tiff_read_and_convert_image(filename.c_str(),im,cc); +} + +/// \ingroup TIFF_IO +/// \brief Allocates a new image whose dimensions are determined by the given tiff image file, loads and color-converts the pixels into it. +template +inline void tiff_read_and_convert_image(const std::string& filename,Image& im) { + tiff_read_and_convert_image(filename.c_str(),im); +} + +/// \ingroup TIFF_IO +/// \brief Determines whether the given view type is supported for writing +template +struct tiff_write_support { + BOOST_STATIC_CONSTANT(bool,is_supported= + (detail::tiff_write_support_private::type, + typename color_space_type::type>::is_supported)); + BOOST_STATIC_CONSTANT(int,bit_depth= + (detail::tiff_write_support_private::type, + typename color_space_type::type>::bit_depth)); + BOOST_STATIC_CONSTANT(int,color_type= + (detail::tiff_write_support_private::type, + typename color_space_type::type>::color_type)); + BOOST_STATIC_CONSTANT(bool, value=is_supported); +}; + +/// \ingroup TIFF_IO +/// \brief Saves the view to a tiff file specified by the given tiff image file name. +/// Triggers a compile assert if the view color space and channel depth are not supported by the TIFF library or by the I/O extension. +/// Throws std::ios_base::failure if it fails to create the file. +template +inline void tiff_write_view(const char* filename,const View& view) { + BOOST_STATIC_ASSERT(tiff_write_support::is_supported); + detail::tiff_writer m(filename); + m.apply(view); +} + +/// \ingroup TIFF_IO +/// \brief Saves the view to a tiff file specified by the given tiff image file name. +template +inline void tiff_write_view(const std::string& filename,const View& view) { + tiff_write_view(filename.c_str(),view); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/gil_all.hpp b/win32/include/boost/gil/gil_all.hpp new file mode 100755 index 000000000..cd336d744 --- /dev/null +++ b/win32/include/boost/gil/gil_all.hpp @@ -0,0 +1,46 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_ALL_HPP +#define GIL_ALL_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Includes all GIL files for convenience +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include "gil_config.hpp" +#include "channel_algorithm.hpp" +#include "algorithm.hpp" +#include "pixel.hpp" +#include "packed_pixel.hpp" +#include "planar_pixel_reference.hpp" +#include "planar_pixel_iterator.hpp" +#include "pixel_iterator_adaptor.hpp" +#include "step_iterator.hpp" +#include "iterator_from_2d.hpp" +#include "image.hpp" +#include "image_view_factory.hpp" +#include "typedefs.hpp" +#include "metafunctions.hpp" +#include "color_convert.hpp" +#include "device_n.hpp" +#include "virtual_locator.hpp" +#include "bit_aligned_pixel_iterator.hpp" +// Uncomment this line to help in porting your code from an older version of GIL +//#include "deprecated.hpp" + +#endif diff --git a/win32/include/boost/gil/gil_concept.hpp b/win32/include/boost/gil/gil_concept.hpp new file mode 100755 index 000000000..fe9d1464e --- /dev/null +++ b/win32/include/boost/gil/gil_concept.hpp @@ -0,0 +1,2187 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_CONCEPT_H +#define GIL_CONCEPT_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Concept check classes for GIL concepts +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on February 12, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include "gil_config.hpp" +#include +#include +#include +#include +#include +#include + +namespace boost { namespace gil { +template struct channel_traits; +template struct is_pixel; +template +typename channel_traits::value_type channel_convert(srcT val); +template class point2; +template const T& axis_value(const point2& p); +template T& axis_value( point2& p); +template struct kth_element_type; +template struct kth_element_reference_type; +template struct kth_element_const_reference_type; +template struct kth_semantic_element_reference_type; +template struct kth_semantic_element_const_reference_type; +template struct size; +template struct element_type; +template struct channel_type; +template struct color_space_type; +template struct channel_mapping_type; +template struct is_planar; +template struct num_channels; + +template struct const_iterator_type; +template struct iterator_is_mutable; +template struct is_iterator_adaptor; +template struct iterator_adaptor_rebind; +template struct iterator_adaptor_get_base; + + +// forward-declare at_c +namespace detail { template struct homogeneous_color_base; } +template +typename add_reference::type at_c( detail::homogeneous_color_base& p); + +template +typename add_reference::type>::type at_c(const detail::homogeneous_color_base& p); + +#if !defined(_MSC_VER) || _MSC_VER > 1310 +template struct packed_pixel; +template +typename kth_element_reference_type, K>::type +at_c(packed_pixel& p); + +template +typename kth_element_const_reference_type,K>::type +at_c(const packed_pixel& p); + +template struct bit_aligned_pixel_reference; + +template inline +typename kth_element_reference_type, K>::type +at_c(const bit_aligned_pixel_reference& p); +#endif + +// Forward-declare semantic_at_c +template +typename disable_if,typename kth_semantic_element_reference_type::type>::type semantic_at_c(ColorBase& p); +template +typename kth_semantic_element_const_reference_type::type semantic_at_c(const ColorBase& p); + +template struct dynamic_x_step_type; +template struct dynamic_y_step_type; +template struct transposed_type; + +namespace detail { +template +void initialize_it(T& x) {} +} // namespace detail + +template +struct remove_const_and_reference : public remove_const::type> {}; + +#ifdef BOOST_GIL_USE_CONCEPT_CHECK + #define GIL_CLASS_REQUIRE(type_var, ns, concept) BOOST_CLASS_REQUIRE(type_var, ns, concept); + template void gil_function_requires() { function_requires(); } +#else + #define GIL_CLASS_REQUIRE(T,NS,C) + template void gil_function_requires() {} +#endif + +/// \ingroup BasicConcepts +/** +\code +auto concept DefaultConstructible { + T::T(); +}; +\endcode +*/ +template +struct DefaultConstructible { + void constraints() { + function_requires >(); + } +}; + +/// \ingroup BasicConcepts +/** +\codeauto concept CopyConstructible { + T::T(T); + T::~T(); +}; +\endcode +*/ +template +struct CopyConstructible { + void constraints() { + function_requires >(); + } +}; + +/// \ingroup BasicConcepts +/** +\code +auto concept Assignable { + typename result_type; + result_type operator=(T&, U); +}; +\endcode +*/ +template +struct Assignable { + void constraints() { + function_requires >(); + } +}; +/// \ingroup BasicConcepts +/** +\code +auto concept EqualityComparable { + bool operator==(T x, T y); + bool operator!=(T x, T y) { return !(x==y); } +}; +\endcode +*/ +template +struct EqualityComparable { + void constraints() { + function_requires >(); + } +}; + +/// \ingroup BasicConcepts +/** +\code +concept SameType;// unspecified +\endcode +*/ + +template +struct SameType { + void constraints() { + BOOST_STATIC_ASSERT((boost::is_same::value_core)); + } +}; + +/// \ingroup BasicConcepts +/** +\code +auto concept Swappable { + void swap(T&,T&); +}; +\endcode +*/ +template +struct Swappable { + void constraints() { + using std::swap; + swap(x,y); + } + T x,y; +}; + +/// \ingroup BasicConcepts +/** +\code +auto concept Regular : DefaultConstructible, CopyConstructible, EqualityComparable, + Assignable, Swappable {}; +\endcode +*/ + +template +struct Regular { + void constraints() { + gil_function_requires< boost::DefaultConstructibleConcept >(); + gil_function_requires< boost::CopyConstructibleConcept >(); + gil_function_requires< boost::EqualityComparableConcept >(); // ==, != + gil_function_requires< boost::AssignableConcept >(); + gil_function_requires< Swappable >(); + } +}; + +/// \ingroup BasicConcepts +/** +\code +auto concept Metafunction { + typename type; +}; +\endcode +*/ +template +struct Metafunction { + void constraints() { + typedef typename T::type type; + } +}; +//////////////////////////////////////////////////////////////////////////////////////// +// +// POINT CONCEPTS +// +//////////////////////////////////////////////////////////////////////////////////////// + +/// \brief N-dimensional point concept +/// \ingroup PointConcept +/** +\code +concept PointNDConcept : Regular { + // the type of a coordinate along each axis + template struct axis; where Metafunction; + + const size_t num_dimensions; + + // accessor/modifier of the value of each axis. + template const typename axis::type& T::axis_value() const; + template typename axis::type& T::axis_value(); +}; +\endcode +*/ + +template +struct PointNDConcept { + void constraints() { + gil_function_requires< Regular

            >(); + + typedef typename P::value_type value_type; + static const std::size_t N=P::num_dimensions; ignore_unused_variable_warning(N); + typedef typename P::template axis<0>::coord_t FT; + typedef typename P::template axis::coord_t LT; + FT ft=gil::axis_value<0>(point); + axis_value<0>(point)=ft; + LT lt=axis_value(point); + axis_value(point)=lt; + + value_type v=point[0]; ignore_unused_variable_warning(v); + point[0]=point[0]; + } + P point; +}; + +/// \brief 2-dimensional point concept +/// \ingroup PointConcept +/** +\code +concept Point2DConcept : PointNDConcept { + where num_dimensions == 2; + where SameType::type, axis<1>::type>; + + typename value_type = axis<0>::type; + + const value_type& operator[](const T&, size_t i); + value_type& operator[]( T&, size_t i); + + value_type x,y; +}; +\endcode +*/ + +template +struct Point2DConcept { + void constraints() { + gil_function_requires< PointNDConcept

            >(); + BOOST_STATIC_ASSERT(P::num_dimensions == 2); + point.x=point.y; + point[0]=point[1]; + } + P point; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +// +// ITERATOR MUTABILITY CONCEPTS +// +// Taken from boost's concept_check.hpp. Isolating mutability to result in faster compile time +// +//////////////////////////////////////////////////////////////////////////////////////// + +namespace detail { + template // Preconditions: TT Models boost_concepts::ForwardTraversalConcept + struct ForwardIteratorIsMutableConcept { + void constraints() { + *i++ = *i; // require postincrement and assignment + } + TT i; + }; + + template // Preconditions: TT Models boost::BidirectionalIteratorConcept + struct BidirectionalIteratorIsMutableConcept { + void constraints() { + gil_function_requires< ForwardIteratorIsMutableConcept >(); + *i-- = *i; // require postdecrement and assignment + } + TT i; + }; + + template // Preconditions: TT Models boost_concepts::RandomAccessTraversalConcept + struct RandomAccessIteratorIsMutableConcept { + void constraints() { + gil_function_requires< BidirectionalIteratorIsMutableConcept >(); + typename std::iterator_traits::difference_type n=0; ignore_unused_variable_warning(n); + i[n] = *i; // require element access and assignment + } + TT i; + }; +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////////////// +// +// COLOR SPACE CONCEPTS +// +//////////////////////////////////////////////////////////////////////////////////////// + +/// \brief Color space type concept +/// \ingroup ColorSpaceAndLayoutConcept +/** +\code +concept ColorSpaceConcept { + // An MPL Random Access Sequence, whose elements are color tags +}; +\endcode +*/ +template +struct ColorSpaceConcept { + void constraints() { + // An MPL Random Access Sequence, whose elements are color tags + } +}; + +template // Models ColorSpaceConcept +struct color_spaces_are_compatible : public is_same {}; + +/// \brief Two color spaces are compatible if they are the same +/// \ingroup ColorSpaceAndLayoutConcept +/** +\code +concept ColorSpacesCompatibleConcept { + where SameType; +}; +\endcode +*/ +template +struct ColorSpacesCompatibleConcept { + void constraints() { + BOOST_STATIC_ASSERT((color_spaces_are_compatible::value)); + } +}; + +/// \brief Channel mapping concept +/// \ingroup ColorSpaceAndLayoutConcept +/** +\code +concept ChannelMappingConcept { + // An MPL Random Access Sequence, whose elements model MPLIntegralConstant representing a permutation +}; +\endcode +*/ +template +struct ChannelMappingConcept { + void constraints() { + // An MPL Random Access Sequence, whose elements model MPLIntegralConstant representing a permutation + } +}; + + + +//////////////////////////////////////////////////////////////////////////////////////// +/// +/// Channel CONCEPTS +/// +//////////////////////////////////////////////////////////////////////////////////////// + +/// \ingroup ChannelConcept +/// \brief A channel is the building block of a color. Color is defined as a mixture of primary colors and a channel defines the degree to which each primary color is used in the mixture. +/** +For example, in the RGB color space, using 8-bit unsigned channels, the color red is defined as [255 0 0], which means maximum of Red, and no Green and Blue. + +Built-in scalar types, such as \p int and \p float, are valid GIL channels. In more complex scenarios, channels may be represented as bit ranges or even individual bits. +In such cases special classes are needed to represent the value and reference to a channel. + +Channels have a traits class, \p channel_traits, which defines their associated types as well as their operating ranges. + +\code +concept ChannelConcept : EqualityComparable { + typename value_type = T; // use channel_traits::value_type to access it + typename reference = T&; // use channel_traits::reference to access it + typename pointer = T*; // use channel_traits::pointer to access it + typename const_reference = const T&; // use channel_traits::const_reference to access it + typename const_pointer = const T*; // use channel_traits::const_pointer to access it + static const bool is_mutable; // use channel_traits::is_mutable to access it + + static T min_value(); // use channel_traits::min_value to access it + static T max_value(); // use channel_traits::min_value to access it +}; +\endcode +*/ +template +struct ChannelConcept { + void constraints() { + gil_function_requires< boost::EqualityComparableConcept >(); + + typedef typename channel_traits::value_type v; + typedef typename channel_traits::reference r; + typedef typename channel_traits::pointer p; + typedef typename channel_traits::const_reference cr; + typedef typename channel_traits::const_pointer cp; + + channel_traits::min_value(); + channel_traits::max_value(); + } + + T c; +}; + +namespace detail { + // Preconditions: T models ChannelConcept + template + struct ChannelIsMutableConcept { + void constraints() { + c=c; + using std::swap; + swap(c,c); + } + T c; + }; +} + +/// \brief A channel that allows for modifying its value +/// \ingroup ChannelConcept +/** +\code +concept MutableChannelConcept : Assignable, Swappable {}; +\endcode +*/ +template +struct MutableChannelConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + } +}; + +/// \brief A channel that supports default construction. +/// \ingroup ChannelConcept +/** +\code +concept ChannelValueConcept : Regular {}; +\endcode +*/ +template +struct ChannelValueConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + } +}; + + +/// \brief Predicate metafunction returning whether two channels are compatible +/// \ingroup ChannelAlgorithm +/// +/// Channels are considered compatible if their value types (ignoring constness and references) are the same. +/** +Example: + +\code +BOOST_STATIC_ASSERT((channels_are_compatible::value)); +\endcode +*/ +template // Models GIL Pixel +struct channels_are_compatible + : public is_same::value_type, typename channel_traits::value_type> {}; + +/// \brief Channels are compatible if their associated value types (ignoring constness and references) are the same +/// \ingroup ChannelConcept +/** +\code +concept ChannelsCompatibleConcept { + where SameType; +}; +\endcode +*/ +template +struct ChannelsCompatibleConcept { + void constraints() { + BOOST_STATIC_ASSERT((channels_are_compatible::value)); + } +}; + +/// \brief A channel is convertible to another one if the \p channel_convert algorithm is defined for the two channels +/// +/// Convertibility is non-symmetric and implies that one channel can be converted to another. Conversion is explicit and often lossy operation. +/// \ingroup ChannelConcept +/** +\code +concept ChannelConvertibleConcept { + DstChannel channel_convert(const SrcChannel&); +}; +\endcode +*/ +template +struct ChannelConvertibleConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + dst=channel_convert(src); ignore_unused_variable_warning(dst); + } + SrcChannel src; + DstChannel dst; +}; + + + + + +//////////////////////////////////////////////////////////////////////////////////////// +/// +/// COLOR BASE CONCEPTS +/// +//////////////////////////////////////////////////////////////////////////////////////// + +/// \ingroup ColorBaseConcept +/// \brief A color base is a container of color elements (such as channels, channel references or channel pointers) +/** +The most common use of color base is in the implementation of a pixel, in which case the color +elements are channel values. The color base concept, however, can be used in other scenarios. For example, a planar pixel has channels that are not +contiguous in memory. Its reference is a proxy class that uses a color base whose elements are channel references. Its iterator uses a color base +whose elements are channel iterators. + +A color base must have an associated layout (which consists of a color space, as well as an ordering of the channels). +There are two ways to index the elements of a color base: A physical index corresponds to the way they are ordered in memory, and +a semantic index corresponds to the way the elements are ordered in their color space. +For example, in the RGB color space the elements are ordered as {red_t, green_t, blue_t}. For a color base with a BGR layout, the first element +in physical ordering is the blue element, whereas the first semantic element is the red one. +Models of \p ColorBaseConcept are required to provide the \p at_c(ColorBase) function, which allows for accessing the elements based on their +physical order. GIL provides a \p semantic_at_c(ColorBase) function (described later) which can operate on any model of ColorBaseConcept and returns +the corresponding semantic element. + +\code +concept ColorBaseConcept : CopyConstructible, EqualityComparable { + // a GIL layout (the color space and element permutation) + typename layout_t; + + // The type of K-th element + template struct kth_element_type; where Metafunction; + + // The result of at_c + template struct kth_element_const_reference_type; where Metafunction; + + template kth_element_const_reference_type::type at_c(T); + + // Copy-constructible and equality comparable with other compatible color bases + template where { ColorBasesCompatibleConcept } + T::T(T2); + template where { ColorBasesCompatibleConcept } + bool operator==(const T&, const T2&); + template where { ColorBasesCompatibleConcept } + bool operator!=(const T&, const T2&); + +}; +\endcode +*/ + +template +struct ColorBaseConcept { + void constraints() { + gil_function_requires< CopyConstructible >(); + gil_function_requires< EqualityComparable >(); + + typedef typename ColorBase::layout_t::color_space_t color_space_t; + gil_function_requires >(); + + typedef typename ColorBase::layout_t::channel_mapping_t channel_mapping_t; + // TODO: channel_mapping_t must be an MPL RandomAccessSequence + + static const std::size_t num_elements = size::value; + + typedef typename kth_element_type::type TN; + typedef typename kth_element_const_reference_type::type CR; + +#if !defined(_MSC_VER) || _MSC_VER > 1310 + CR cr=at_c(cb); ignore_unused_variable_warning(cr); +#endif + + // functions that work for every pixel (no need to require them) + semantic_at_c<0>(cb); + semantic_at_c(cb); + // also static_max(cb), static_min(cb), static_fill(cb,value), and all variations of static_for_each(), static_generate(), static_transform() + } + + ColorBase cb; +}; + +/// \ingroup ColorBaseConcept +/// \brief Color base which allows for modifying its elements +/** + +\code +concept MutableColorBaseConcept : Assignable, Swappable { + template struct kth_element_reference_type; where Metafunction; + + template kth_element_reference_type::type>::type at_c(T); + + template where { ColorBasesCompatibleConcept } + T& operator=(T&, const T2&); +}; +\endcode +*/ +template +struct MutableColorBaseConcept { + void constraints() { + gil_function_requires< ColorBaseConcept >(); + gil_function_requires< Assignable >(); + gil_function_requires< Swappable >(); + + typedef typename kth_element_reference_type::type CR; + +#if !defined(_MSC_VER) || _MSC_VER > 1310 + CR r=at_c<0>(cb); + at_c<0>(cb)=r; +#endif + } + + ColorBase cb; +}; + +/// \ingroup ColorBaseConcept +/// \brief Color base that also has a default-constructor. Refines Regular +/** +\code +concept ColorBaseValueConcept : MutableColorBaseConcept, Regular { +}; +\endcode +*/ +template +struct ColorBaseValueConcept { + void constraints() { + gil_function_requires< MutableColorBaseConcept >(); + gil_function_requires< Regular >(); + } +}; + +/// \ingroup ColorBaseConcept +/// \brief Color base whose elements all have the same type +/** +\code +concept HomogeneousColorBaseConcept { + // For all K in [0 ... size::value-1): + // where SameType::type, kth_element_type::type>; + kth_element_const_reference_type::type dynamic_at_c(const CB&, std::size_t n) const; +}; +\endcode +*/ + +template +struct HomogeneousColorBaseConcept { + void constraints() { + gil_function_requires< ColorBaseConcept >(); + + static const std::size_t num_elements = size::value; + + typedef typename kth_element_type::type T0; + typedef typename kth_element_type::type TN; + + BOOST_STATIC_ASSERT((is_same::value)); // better than nothing + typedef typename kth_element_const_reference_type::type CRef0; + CRef0 e0=dynamic_at_c(cb,0); + } + ColorBase cb; +}; + +/// \ingroup ColorBaseConcept +/// \brief Homogeneous color base that allows for modifying its elements +/** + +\code +concept MutableHomogeneousColorBaseConcept : HomogeneousColorBaseConcept { + kth_element_reference_type::type dynamic_at_c(CB&, std::size_t n); +}; +\endcode +*/ + +template +struct MutableHomogeneousColorBaseConcept { + void constraints() { + gil_function_requires< ColorBaseConcept >(); + gil_function_requires< HomogeneousColorBaseConcept >(); + typedef typename kth_element_reference_type::type R0; + R0 x=dynamic_at_c(cb,0); + dynamic_at_c(cb,0) = dynamic_at_c(cb,0); + } + ColorBase cb; +}; + +/// \ingroup ColorBaseConcept +/// \brief Homogeneous color base that also has a default constructor. Refines Regular. +/** + +\code +concept HomogeneousColorBaseValueConcept : MutableHomogeneousColorBaseConcept, Regular { +}; +\endcode +*/ + +template +struct HomogeneousColorBaseValueConcept { + void constraints() { + gil_function_requires< MutableHomogeneousColorBaseConcept >(); + gil_function_requires< Regular >(); + } +}; + + +/// \ingroup ColorBaseConcept +/// \brief Two color bases are compatible if they have the same color space and their elements are compatible, semantic-pairwise. +/** + +\code +concept ColorBasesCompatibleConcept { + where SameType; + // also, for all K in [0 ... size::value): + // where Convertible::type, kth_semantic_element_type::type>; + // where Convertible::type, kth_semantic_element_type::type>; +}; +\endcode +*/ +template +struct ColorBasesCompatibleConcept { + void constraints() { + BOOST_STATIC_ASSERT((is_same::value)); +// typedef typename kth_semantic_element_type::type e1; +// typedef typename kth_semantic_element_type::type e2; +// "e1 is convertible to e2" + } +}; + + + + + + + + + + + + + + + + + + + + + + +//////////////////////////////////////////////////////////////////////////////////////// +/// +/// PIXEL CONCEPTS +/// +//////////////////////////////////////////////////////////////////////////////////////// + +/// \brief Concept for all pixel-based GIL constructs, such as pixels, iterators, locators, views and images whose value type is a pixel +/// \ingroup PixelBasedConcept +/** +\code +concept PixelBasedConcept { + typename color_space_type; + where Metafunction >; + where ColorSpaceConcept::type>; + typename channel_mapping_type; + where Metafunction >; + where ChannelMappingConcept::type>; + typename is_planar; + where Metafunction >; + where SameType::type, bool>; +}; +\endcode +*/ +template +struct PixelBasedConcept { + void constraints() { + typedef typename color_space_type

            ::type color_space_t; + gil_function_requires >(); + typedef typename channel_mapping_type

            ::type channel_mapping_t; + gil_function_requires >(); + + static const bool planar = is_planar

            ::type::value; ignore_unused_variable_warning(planar); + + + // This is not part of the concept, but should still work + static const std::size_t nc = num_channels

            ::value; + ignore_unused_variable_warning(nc); + } +}; + +/// \brief Concept for homogeneous pixel-based GIL constructs +/// \ingroup PixelBasedConcept +/** +\code +concept HomogeneousPixelBasedConcept { + typename channel_type; + where Metafunction >; + where ChannelConcept::type>; +}; +\endcode +*/ +template +struct HomogeneousPixelBasedConcept { + void constraints() { + gil_function_requires >(); + typedef typename channel_type

            ::type channel_t; + gil_function_requires >(); + } +}; + + +/// \brief Pixel concept - A color base whose elements are channels +/// \ingroup PixelConcept +/** +\code +concept PixelConcept : ColorBaseConcept

            , PixelBasedConcept

            { + where is_pixel

            ::type::value==true; + // where for each K [0..size

            ::value-1]: + // ChannelConcept >; + + typename P::value_type; where PixelValueConcept; + typename P::reference; where PixelConcept; + typename P::const_reference; where PixelConcept; + static const bool P::is_mutable; + + template where { PixelConcept } + P::P(P2); + template where { PixelConcept } + bool operator==(const P&, const P2&); + template where { PixelConcept } + bool operator!=(const P&, const P2&); +}; +\endcode +*/ + +template +struct PixelConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + + BOOST_STATIC_ASSERT((is_pixel

            ::value)); + static const bool is_mutable = P::is_mutable; ignore_unused_variable_warning(is_mutable); + + typedef typename P::value_type value_type; +// gil_function_requires >(); + + typedef typename P::reference reference; + gil_function_requires::type> >(); + + typedef typename P::const_reference const_reference; + gil_function_requires::type> >(); + } +}; + + +/// \brief Pixel concept that allows for changing its channels +/// \ingroup PixelConcept +/** +\code +concept MutablePixelConcept : MutableColorBaseConcept

            { + where is_mutable==true; +}; +\endcode +*/ +template +struct MutablePixelConcept { + void constraints() { + gil_function_requires >(); + BOOST_STATIC_ASSERT(P::is_mutable); + } +}; +/// \brief Homogeneous pixel concept +/// \ingroup PixelConcept +/** +\code +concept HomogeneousPixelConcept : HomogeneousColorBaseConcept

            , HomogeneousPixelBasedConcept

            { + P::template element_const_reference_type

            ::type operator[](P p, std::size_t i) const { return dynamic_at_c(p,i); } +}; +\endcode +*/ +template +struct HomogeneousPixelConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + gil_function_requires >(); + p[0]; + } + P p; +}; + +/// \brief Homogeneous pixel concept that allows for changing its channels +/// \ingroup PixelConcept +/** +\code +concept MutableHomogeneousPixelConcept : MutableHomogeneousColorBaseConcept

            { + P::template element_reference_type

            ::type operator[](P p, std::size_t i) { return dynamic_at_c(p,i); } +}; +\endcode +*/ +template +struct MutableHomogeneousPixelConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + p[0]=p[0]; + } + P p; +}; + +/// \brief Pixel concept that is a Regular type +/// \ingroup PixelConcept +/** +\code +concept PixelValueConcept : Regular

            { + where SameType; +}; +\endcode +*/ +template +struct PixelValueConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + } +}; + +/// \brief Homogeneous pixel concept that is a Regular type +/// \ingroup PixelConcept +/** +\code +concept HomogeneousPixelValueConcept : Regular

            { + where SameType; +}; +\endcode +*/ +template +struct HomogeneousPixelValueConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + BOOST_STATIC_ASSERT((is_same::value)); + } +}; + +namespace detail { + template + struct channels_are_pairwise_compatible : public + mpl::and_, + channels_are_compatible::type, + typename kth_semantic_element_reference_type::type> > {}; + + template + struct channels_are_pairwise_compatible : public mpl::true_ {}; +} + +/// \brief Returns whether two pixels are compatible +/// +/// Pixels are compatible if their channels and color space types are compatible. Compatible pixels can be assigned and copy constructed from one another. +/// \ingroup PixelAlgorithm +template // Models GIL Pixel +struct pixels_are_compatible + : public mpl::and_::type, + typename color_space_type::type>::type, + detail::channels_are_pairwise_compatible::value-1> > {}; + +/// \brief Concept for pixel compatibility +/// Pixels are compatible if their channels and color space types are compatible. Compatible pixels can be assigned and copy constructed from one another. +/// \ingroup PixelConcept +/** +\code +concept PixelsCompatibleConcept : ColorBasesCompatibleConcept { + // where for each K [0..size::value): + // ChannelsCompatibleConcept::type, kth_semantic_element_type::type>; +}; +\endcode +*/ +template // precondition: P1 and P2 model PixelConcept +struct PixelsCompatibleConcept { + void constraints() { + BOOST_STATIC_ASSERT((pixels_are_compatible::value)); + } +}; + +/// \brief Pixel convertible concept +/// +/// Convertibility is non-symmetric and implies that one pixel can be converted to another, approximating the color. Conversion is explicit and sometimes lossy. +/// \ingroup PixelConcept +/** +\code +template +concept PixelConvertibleConcept { + void color_convert(const SrcPixel&, DstPixel&); +}; +\endcode +*/ +template +struct PixelConvertibleConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + color_convert(src,dst); + } + SrcP src; + DstP dst; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +/// +/// DEREFERENCE ADAPTOR CONCEPTS +/// +//////////////////////////////////////////////////////////////////////////////////////// + +/// \ingroup PixelDereferenceAdaptorConcept + +/// \brief Represents a unary function object that can be invoked upon dereferencing a pixel iterator. +/// +/// This can perform an arbitrary computation, such as color conversion or table lookup +/** +\code +concept PixelDereferenceAdaptorConcept + : DefaultConstructibleConcept, CopyConstructibleConcept, AssignableConcept { + typename const_t; where PixelDereferenceAdaptorConcept; + typename value_type; where PixelValueConcept; + typename reference; // may be mutable + typename const_reference; // must not be mutable + static const bool D::is_mutable; + + where Convertible; +}; +\endcode +*/ + +template +struct PixelDereferenceAdaptorConcept { + void constraints() { + gil_function_requires< boost::UnaryFunctionConcept::type, + typename D::argument_type> >(); + gil_function_requires< boost::DefaultConstructibleConcept >(); + gil_function_requires< boost::CopyConstructibleConcept >(); + gil_function_requires< boost::AssignableConcept >(); + + gil_function_requires::type> >(); + + typedef typename D::const_t const_t; + gil_function_requires >(); + typedef typename D::value_type value_type; + gil_function_requires >(); + typedef typename D::reference reference; // == PixelConcept (if you remove const and reference) + typedef typename D::const_reference const_reference; // == PixelConcept (if you remove const and reference) + + const bool is_mutable=D::is_mutable; ignore_unused_variable_warning(is_mutable); + } + D d; +}; + +template +struct PixelDereferenceAdaptorArchetype : public std::unary_function { + typedef PixelDereferenceAdaptorArchetype const_t; + typedef typename remove_reference

            ::type value_type; + typedef typename add_reference

            ::type reference; + typedef reference const_reference; + static const bool is_mutable=false; + P operator()(P x) const { throw; } +}; + +//////////////////////////////////////////////////////////////////////////////////////// +/// +/// Pixel ITERATOR CONCEPTS +/// +//////////////////////////////////////////////////////////////////////////////////////// + +/// \brief Concept for iterators, locators and views that can define a type just like the given iterator/locator/view, except it supports runtime specified step along the X navigation +/// \ingroup PixelIteratorConcept +/** +\code +concept HasDynamicXStepTypeConcept { + typename dynamic_x_step_type; + where Metafunction >; +}; +\endcode +*/ +template +struct HasDynamicXStepTypeConcept { + void constraints() { + typedef typename dynamic_x_step_type::type type; + } +}; + +/// \brief Concept for locators and views that can define a type just like the given locator or view, except it supports runtime specified step along the Y navigation +/// \ingroup PixelLocatorConcept +/** +\code +concept HasDynamicYStepTypeConcept { + typename dynamic_y_step_type; + where Metafunction >; +}; +\endcode +*/ +template +struct HasDynamicYStepTypeConcept { + void constraints() { + typedef typename dynamic_y_step_type::type type; + } +}; + + +/// \brief Concept for locators and views that can define a type just like the given locator or view, except X and Y is swapped +/// \ingroup PixelLocatorConcept +/** +\code +concept HasTransposedTypeConcept { + typename transposed_type; + where Metafunction >; +}; +\endcode +*/ +template +struct HasTransposedTypeConcept { + void constraints() { + typedef typename transposed_type::type type; + } +}; + +/// \defgroup PixelIteratorConceptPixelIterator PixelIteratorConcept +/// \ingroup PixelIteratorConcept +/// \brief STL iterator over pixels + +/// \ingroup PixelIteratorConceptPixelIterator +/// \brief An STL random access traversal iterator over a model of PixelConcept. +/** +GIL's iterators must also provide the following metafunctions: + - \p const_iterator_type: Returns a read-only equivalent of \p Iterator + - \p iterator_is_mutable: Returns whether the given iterator is read-only or mutable + - \p is_iterator_adaptor: Returns whether the given iterator is an adaptor over another iterator. See IteratorAdaptorConcept for additional requirements of adaptors. + + \code +concept PixelIteratorConcept : boost_concepts::RandomAccessTraversalConcept, PixelBasedConcept { + where PixelValueConcept; + typename const_iterator_type::type; + where PixelIteratorConcept::type>; + static const bool iterator_is_mutable::type::value; + static const bool is_iterator_adaptor::type::value; // is it an iterator adaptor +}; +\endcode +*/ +template +struct PixelIteratorConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + + typedef typename std::iterator_traits::value_type value_type; + gil_function_requires >(); + + typedef typename const_iterator_type::type const_t; + static const bool is_mut = iterator_is_mutable::type::value; ignore_unused_variable_warning(is_mut); + + const_t const_it(it); ignore_unused_variable_warning(const_it); // immutable iterator must be constructible from (possibly mutable) iterator + + check_base(typename is_iterator_adaptor::type()); + } + void check_base(mpl::false_) {} + void check_base(mpl::true_) { + typedef typename iterator_adaptor_get_base::type base_t; + gil_function_requires >(); + } + + Iterator it; +}; + +namespace detail { + template // Preconditions: Iterator Models PixelIteratorConcept + struct PixelIteratorIsMutableConcept { + void constraints() { + gil_function_requires >(); + typedef typename remove_reference::reference>::type ref; + typedef typename element_type::type channel_t; + gil_function_requires >(); + } + }; +} + +/// \brief Pixel iterator that allows for changing its pixel +/// \ingroup PixelIteratorConceptPixelIterator +/** +\code +concept MutablePixelIteratorConcept : MutableRandomAccessIteratorConcept {}; + +\endcode +*/ +template +struct MutablePixelIteratorConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + } +}; + +namespace detail { + // Iterators that can be used as the base of memory_based_step_iterator require some additional functions + template // Preconditions: Iterator Models boost_concepts::RandomAccessTraversalConcept + struct RandomAccessIteratorIsMemoryBasedConcept { + void constraints() { + std::ptrdiff_t bs=memunit_step(it); ignore_unused_variable_warning(bs); + it=memunit_advanced(it,3); + std::ptrdiff_t bd=memunit_distance(it,it); ignore_unused_variable_warning(bd); + memunit_advance(it,3); + // for performace you may also provide a customized implementation of memunit_advanced_ref + } + Iterator it; + }; +} + +/// \defgroup PixelIteratorConceptStepIterator StepIteratorConcept +/// \ingroup PixelIteratorConcept +/// \brief Iterator that advances by a specified step + +/// \brief Concept of a random-access iterator that can be advanced in memory units (bytes or bits) +/// \ingroup PixelIteratorConceptStepIterator +/** +\code +concept MemoryBasedIteratorConcept { + typename byte_to_memunit; where metafunction >; + std::ptrdiff_t memunit_step(const Iterator&); + std::ptrdiff_t memunit_distance(const Iterator& , const Iterator&); + void memunit_advance(Iterator&, std::ptrdiff_t diff); + Iterator memunit_advanced(const Iterator& p, std::ptrdiff_t diff) { Iterator tmp; memunit_advance(tmp,diff); return tmp; } + Iterator::reference memunit_advanced_ref(const Iterator& p, std::ptrdiff_t diff) { return *memunit_advanced(p,diff); } +}; +\endcode +*/ +template +struct MemoryBasedIteratorConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + } +}; + +/// \brief Step iterator concept +/// +/// Step iterators are iterators that have a set_step method +/// \ingroup PixelIteratorConceptStepIterator +/** +\code +concept StepIteratorConcept { + template void Iterator::set_step(D step); +}; +\endcode +*/ +template +struct StepIteratorConcept { + void constraints() { + gil_function_requires >(); + it.set_step(0); + } + Iterator it; +}; + + +/// \brief Step iterator that allows for modifying its current value +/// +/// \ingroup PixelIteratorConceptStepIterator +/** +\code +concept MutableStepIteratorConcept : StepIteratorConcept {}; +\endcode +*/ +template +struct MutableStepIteratorConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + } +}; + +/// \defgroup PixelIteratorConceptIteratorAdaptor IteratorAdaptorConcept +/// \ingroup PixelIteratorConcept +/// \brief Adaptor over another iterator + +/// \ingroup PixelIteratorConceptIteratorAdaptor +/// \brief Iterator adaptor is a forward iterator adapting another forward iterator. +/** +In addition to GIL iterator requirements, GIL iterator adaptors must provide the following metafunctions: + - \p is_iterator_adaptor: Returns \p mpl::true_ + - \p iterator_adaptor_get_base: Returns the base iterator type + - \p iterator_adaptor_rebind: Replaces the base iterator with the new one + +The adaptee can be obtained from the iterator via the "base()" method. + +\code +concept IteratorAdaptorConcept { + where SameType::type, mpl::true_>; + + typename iterator_adaptor_get_base; + where Metafunction >; + where boost_concepts::ForwardTraversalConcept::type>; + + typename another_iterator; + typename iterator_adaptor_rebind::type; + where boost_concepts::ForwardTraversalConcept; + where IteratorAdaptorConcept::type>; + + const iterator_adaptor_get_base::type& Iterator::base() const; +}; +\endcode +*/ +template +struct IteratorAdaptorConcept { + void constraints() { + gil_function_requires >(); + + typedef typename iterator_adaptor_get_base::type base_t; + gil_function_requires >(); + + BOOST_STATIC_ASSERT(is_iterator_adaptor::value); + typedef typename iterator_adaptor_rebind::type rebind_t; + + base_t base=it.base(); ignore_unused_variable_warning(base); + } + Iterator it; +}; + +/// \brief Iterator adaptor that is mutable +/// \ingroup PixelIteratorConceptIteratorAdaptor +/** +\code +concept MutableIteratorAdaptorConcept : IteratorAdaptorConcept {}; +\endcode +*/ +template +struct MutableIteratorAdaptorConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + } +}; + +//////////////////////////////////////////////////////////////////////////////////////// +/// +/// LOCATOR CONCEPTS +/// +//////////////////////////////////////////////////////////////////////////////////////// + +/// \defgroup LocatorNDConcept RandomAccessNDLocatorConcept +/// \ingroup PixelLocatorConcept +/// \brief N-dimensional locator + +/// \defgroup Locator2DConcept RandomAccess2DLocatorConcept +/// \ingroup PixelLocatorConcept +/// \brief 2-dimensional locator + +/// \defgroup PixelLocator2DConcept PixelLocatorConcept +/// \ingroup PixelLocatorConcept +/// \brief 2-dimensional locator over pixel data + +/// \ingroup LocatorNDConcept +/// \brief N-dimensional locator over immutable values +/** +\code +concept RandomAccessNDLocatorConcept { + typename value_type; // value over which the locator navigates + typename reference; // result of dereferencing + typename difference_type; where PointNDConcept; // return value of operator-. + typename const_t; // same as Loc, but operating over immutable values + typename cached_location_t; // type to store relative location (for efficient repeated access) + typename point_t = difference_type; + + static const size_t num_dimensions; // dimensionality of the locator + where num_dimensions = point_t::num_dimensions; + + // The difference_type and iterator type along each dimension. The iterators may only differ in + // difference_type. Their value_type must be the same as Loc::value_type + template struct axis { + typename coord_t = point_t::axis::coord_t; + typename iterator; where RandomAccessTraversalConcept; // iterator along D-th axis. + where iterator::value_type == value_type; + }; + + // Defines the type of a locator similar to this type, except it invokes Deref upon dereferencing + template struct add_deref { + typename type; where RandomAccessNDLocatorConcept; + static type make(const Loc& loc, const Deref& deref); + }; + + Loc& operator+=(Loc&, const difference_type&); + Loc& operator-=(Loc&, const difference_type&); + Loc operator+(const Loc&, const difference_type&); + Loc operator-(const Loc&, const difference_type&); + + reference operator*(const Loc&); + reference operator[](const Loc&, const difference_type&); + + // Storing relative location for faster repeated access and accessing it + cached_location_t Loc::cache_location(const difference_type&) const; + reference operator[](const Loc&,const cached_location_t&); + + // Accessing iterators along a given dimension at the current location or at a given offset + template axis::iterator& Loc::axis_iterator(); + template axis::iterator const& Loc::axis_iterator() const; + template axis::iterator Loc::axis_iterator(const difference_type&) const; +}; +\endcode +*/ +template +struct RandomAccessNDLocatorConcept { + void constraints() { + gil_function_requires< Regular >(); + + typedef typename Loc::value_type value_type; + typedef typename Loc::reference reference; // result of dereferencing + typedef typename Loc::difference_type difference_type; // result of operator-(pixel_locator, pixel_locator) + typedef typename Loc::cached_location_t cached_location_t; // type used to store relative location (to allow for more efficient repeated access) + typedef typename Loc::const_t const_t; // same as this type, but over const values + typedef typename Loc::point_t point_t; // same as difference_type + static const std::size_t N=Loc::num_dimensions; ignore_unused_variable_warning(N); + + typedef typename Loc::template axis<0>::iterator first_it_type; + typedef typename Loc::template axis::iterator last_it_type; + gil_function_requires >(); + gil_function_requires >(); + + // point_t must be an N-dimensional point, each dimension of which must have the same type as difference_type of the corresponding iterator + gil_function_requires >(); + BOOST_STATIC_ASSERT(point_t::num_dimensions==N); + BOOST_STATIC_ASSERT((is_same::difference_type, typename point_t::template axis<0>::coord_t>::value)); + BOOST_STATIC_ASSERT((is_same::difference_type, typename point_t::template axis::coord_t>::value)); + + difference_type d; + loc+=d; + loc-=d; + loc=loc+d; + loc=loc-d; + reference r1=loc[d]; ignore_unused_variable_warning(r1); + reference r2=*loc; ignore_unused_variable_warning(r2); + cached_location_t cl=loc.cache_location(d); ignore_unused_variable_warning(cl); + reference r3=loc[d]; ignore_unused_variable_warning(r3); + + first_it_type fi=loc.template axis_iterator<0>(); + fi=loc.template axis_iterator<0>(d); + last_it_type li=loc.template axis_iterator(); + li=loc.template axis_iterator(d); + + typedef PixelDereferenceAdaptorArchetype deref_t; + typedef typename Loc::template add_deref::type dtype; + //gil_function_requires >(); // infinite recursion + } + Loc loc; +}; + +/// \ingroup Locator2DConcept +/// \brief 2-dimensional locator over immutable values +/** +\code +concept RandomAccess2DLocatorConcept { + where num_dimensions==2; + where Point2DConcept; + + typename x_iterator = axis<0>::iterator; + typename y_iterator = axis<1>::iterator; + typename x_coord_t = axis<0>::coord_t; + typename y_coord_t = axis<1>::coord_t; + + // Only available to locators that have dynamic step in Y + //Loc::Loc(const Loc& loc, y_coord_t); + + // Only available to locators that have dynamic step in X and Y + //Loc::Loc(const Loc& loc, x_coord_t, y_coord_t, bool transposed=false); + + x_iterator& Loc::x(); + x_iterator const& Loc::x() const; + y_iterator& Loc::y(); + y_iterator const& Loc::y() const; + + x_iterator Loc::x_at(const difference_type&) const; + y_iterator Loc::y_at(const difference_type&) const; + Loc Loc::xy_at(const difference_type&) const; + + // x/y versions of all methods that can take difference type + x_iterator Loc::x_at(x_coord_t, y_coord_t) const; + y_iterator Loc::y_at(x_coord_t, y_coord_t) const; + Loc Loc::xy_at(x_coord_t, y_coord_t) const; + reference operator()(const Loc&, x_coord_t, y_coord_t); + cached_location_t Loc::cache_location(x_coord_t, y_coord_t) const; + + bool Loc::is_1d_traversable(x_coord_t width) const; + y_coord_t Loc::y_distance_to(const Loc& loc2, x_coord_t x_diff) const; +}; +\endcode +*/ +template +struct RandomAccess2DLocatorConcept { + void constraints() { + gil_function_requires >(); + BOOST_STATIC_ASSERT(Loc::num_dimensions==2); + + typedef typename dynamic_x_step_type::type dynamic_x_step_t; + typedef typename dynamic_y_step_type::type dynamic_y_step_t; + typedef typename transposed_type::type transposed_t; + + typedef typename Loc::cached_location_t cached_location_t; + gil_function_requires >(); + + typedef typename Loc::x_iterator x_iterator; + typedef typename Loc::y_iterator y_iterator; + typedef typename Loc::x_coord_t x_coord_t; + typedef typename Loc::y_coord_t y_coord_t; + + x_coord_t xd=0; ignore_unused_variable_warning(xd); + y_coord_t yd=0; ignore_unused_variable_warning(yd); + + typename Loc::difference_type d; + typename Loc::reference r=loc(xd,yd); ignore_unused_variable_warning(r); + + dynamic_x_step_t loc2(dynamic_x_step_t(), yd); + dynamic_x_step_t loc3(dynamic_x_step_t(), xd, yd); + + typedef typename dynamic_y_step_type::type>::type dynamic_xy_step_transposed_t; + dynamic_xy_step_transposed_t loc4(loc, xd,yd,true); + + bool is_contiguous=loc.is_1d_traversable(xd); ignore_unused_variable_warning(is_contiguous); + loc.y_distance_to(loc, xd); + + loc=loc.xy_at(d); + loc=loc.xy_at(xd,yd); + + x_iterator xit=loc.x_at(d); + xit=loc.x_at(xd,yd); + xit=loc.x(); + + y_iterator yit=loc.y_at(d); + yit=loc.y_at(xd,yd); + yit=loc.y(); + + cached_location_t cl=loc.cache_location(xd,yd); ignore_unused_variable_warning(cl); + } + Loc loc; +}; + +/// \ingroup PixelLocator2DConcept +/// \brief GIL's 2-dimensional locator over immutable GIL pixels +/** +\code +concept PixelLocatorConcept { + where PixelValueConcept; + where PixelIteratorConcept; + where PixelIteratorConcept; + where x_coord_t == y_coord_t; + + typename coord_t = x_coord_t; +}; +\endcode +*/ +template +struct PixelLocatorConcept { + void constraints() { + gil_function_requires< RandomAccess2DLocatorConcept >(); + gil_function_requires< PixelIteratorConcept >(); + gil_function_requires< PixelIteratorConcept >(); + typedef typename Loc::coord_t coord_t; + BOOST_STATIC_ASSERT((is_same::value)); + } + Loc loc; +}; + +namespace detail { + template // preconditions: Loc Models RandomAccessNDLocatorConcept + struct RandomAccessNDLocatorIsMutableConcept { + void constraints() { + gil_function_requires::iterator> >(); + gil_function_requires::iterator> >(); + + typename Loc::difference_type d; initialize_it(d); + typename Loc::value_type v;initialize_it(v); + typename Loc::cached_location_t cl=loc.cache_location(d); + *loc=v; + loc[d]=v; + loc[cl]=v; + } + Loc loc; + }; + + template // preconditions: Loc Models RandomAccess2DLocatorConcept + struct RandomAccess2DLocatorIsMutableConcept { + void constraints() { + gil_function_requires >(); + typename Loc::x_coord_t xd=0; ignore_unused_variable_warning(xd); + typename Loc::y_coord_t yd=0; ignore_unused_variable_warning(yd); + typename Loc::value_type v; initialize_it(v); + loc(xd,yd)=v; + } + Loc loc; + }; +} + +/// \ingroup LocatorNDConcept +/// \brief N-dimensional locator over mutable pixels +/** +\code +concept MutableRandomAccessNDLocatorConcept { + where Mutable; +}; +\endcode +*/ +template +struct MutableRandomAccessNDLocatorConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + } +}; + +/// \ingroup Locator2DConcept +/// \brief 2-dimensional locator over mutable pixels +/** +\code +concept MutableRandomAccess2DLocatorConcept : MutableRandomAccessNDLocatorConcept {}; +\endcode +*/ +template +struct MutableRandomAccess2DLocatorConcept { + void constraints() { + gil_function_requires< RandomAccess2DLocatorConcept >(); + gil_function_requires >(); + } +}; + +/// \ingroup PixelLocator2DConcept +/// \brief GIL's 2-dimensional locator over mutable GIL pixels +/** +\code +concept MutablePixelLocatorConcept : MutableRandomAccess2DLocatorConcept {}; +\endcode +*/ +template +struct MutablePixelLocatorConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + } +}; + +//////////////////////////////////////////////////////////////////////////////////////// +/// +/// IMAGE VIEW CONCEPTS +/// +//////////////////////////////////////////////////////////////////////////////////////// + +/// \defgroup ImageViewNDConcept ImageViewNDLocatorConcept +/// \ingroup ImageViewConcept +/// \brief N-dimensional range + +/// \defgroup ImageView2DConcept ImageView2DConcept +/// \ingroup ImageViewConcept +/// \brief 2-dimensional range + +/// \defgroup PixelImageViewConcept ImageViewConcept +/// \ingroup ImageViewConcept +/// \brief 2-dimensional range over pixel data + +/// \ingroup ImageViewNDConcept +/// \brief N-dimensional view over immutable values +/** +\code +concept RandomAccessNDImageViewConcept { + typename value_type; + typename reference; // result of dereferencing + typename difference_type; // result of operator-(iterator,iterator) (1-dimensional!) + typename const_t; where RandomAccessNDImageViewConcept; // same as View, but over immutable values + typename point_t; where PointNDConcept; // N-dimensional point + typename locator; where RandomAccessNDLocatorConcept; // N-dimensional locator. + typename iterator; where RandomAccessTraversalConcept; // 1-dimensional iterator over all values + typename reverse_iterator; where RandomAccessTraversalConcept; + typename size_type; // the return value of size() + + // Equivalent to RandomAccessNDLocatorConcept::axis + template struct axis { + typename coord_t = point_t::axis::coord_t; + typename iterator; where RandomAccessTraversalConcept; // iterator along D-th axis. + where SameType; + where SameType; + }; + + // Defines the type of a view similar to this type, except it invokes Deref upon dereferencing + template struct add_deref { + typename type; where RandomAccessNDImageViewConcept; + static type make(const View& v, const Deref& deref); + }; + + static const size_t num_dimensions = point_t::num_dimensions; + + // Create from a locator at the top-left corner and dimensions + View::View(const locator&, const point_type&); + + size_type View::size() const; // total number of elements + reference operator[](View, const difference_type&) const; // 1-dimensional reference + iterator View::begin() const; + iterator View::end() const; + reverse_iterator View::rbegin() const; + reverse_iterator View::rend() const; + iterator View::at(const point_t&); + point_t View::dimensions() const; // number of elements along each dimension + bool View::is_1d_traversable() const; // can an iterator over the first dimension visit each value? I.e. are there gaps between values? + + // iterator along a given dimension starting at a given point + template View::axis::iterator View::axis_iterator(const point_t&) const; + + reference operator()(View,const point_t&) const; +}; +\endcode +*/ +template +struct RandomAccessNDImageViewConcept { + void constraints() { + gil_function_requires< Regular >(); + + typedef typename View::value_type value_type; + typedef typename View::reference reference; // result of dereferencing + typedef typename View::difference_type difference_type; // result of operator-(1d_iterator,1d_iterator) + typedef typename View::const_t const_t; // same as this type, but over const values + typedef typename View::point_t point_t; // N-dimensional point + typedef typename View::locator locator; // N-dimensional locator + typedef typename View::iterator iterator; + typedef typename View::reverse_iterator reverse_iterator; + typedef typename View::size_type size_type; + static const std::size_t N=View::num_dimensions; + + gil_function_requires >(); + gil_function_requires >(); + gil_function_requires >(); + + typedef typename View::template axis<0>::iterator first_it_type; + typedef typename View::template axis::iterator last_it_type; + gil_function_requires >(); + gil_function_requires >(); + +// BOOST_STATIC_ASSERT((typename std::iterator_traits::difference_type, typename point_t::template axis<0>::coord_t>::value)); +// BOOST_STATIC_ASSERT((typename std::iterator_traits< last_it_type>::difference_type, typename point_t::template axis::coord_t>::value)); + + // point_t must be an N-dimensional point, each dimension of which must have the same type as difference_type of the corresponding iterator + gil_function_requires >(); + BOOST_STATIC_ASSERT(point_t::num_dimensions==N); + BOOST_STATIC_ASSERT((is_same::difference_type, typename point_t::template axis<0>::coord_t>::value)); + BOOST_STATIC_ASSERT((is_same::difference_type, typename point_t::template axis::coord_t>::value)); + + point_t p; + locator lc; + iterator it; + reverse_iterator rit; + difference_type d; detail::initialize_it(d); ignore_unused_variable_warning(d); + + View(p,lc); // view must be constructible from a locator and a point + + p=view.dimensions(); + lc=view.pixels(); + size_type sz=view.size(); ignore_unused_variable_warning(sz); + bool is_contiguous=view.is_1d_traversable(); ignore_unused_variable_warning(is_contiguous); + + it=view.begin(); + it=view.end(); + rit=view.rbegin(); + rit=view.rend(); + + reference r1=view[d]; ignore_unused_variable_warning(r1); // 1D access + reference r2=view(p); ignore_unused_variable_warning(r2); // 2D access + + // get 1-D iterator of any dimension at a given pixel location + first_it_type fi=view.template axis_iterator<0>(p); ignore_unused_variable_warning(fi); + last_it_type li=view.template axis_iterator(p); ignore_unused_variable_warning(li); + + typedef PixelDereferenceAdaptorArchetype deref_t; + typedef typename View::template add_deref::type dtype; + } + View view; +}; + +/// \ingroup ImageView2DConcept +/// \brief 2-dimensional view over immutable values +/** +\code +concept RandomAccess2DImageViewConcept { + where num_dimensions==2; + + typename x_iterator = axis<0>::iterator; + typename y_iterator = axis<1>::iterator; + typename x_coord_t = axis<0>::coord_t; + typename y_coord_t = axis<1>::coord_t; + typename xy_locator = locator; + + x_coord_t View::width() const; + y_coord_t View::height() const; + + // X-navigation + x_iterator View::x_at(const point_t&) const; + x_iterator View::row_begin(y_coord_t) const; + x_iterator View::row_end (y_coord_t) const; + + // Y-navigation + y_iterator View::y_at(const point_t&) const; + y_iterator View::col_begin(x_coord_t) const; + y_iterator View::col_end (x_coord_t) const; + + // navigating in 2D + xy_locator View::xy_at(const point_t&) const; + + // (x,y) versions of all methods taking point_t + View::View(x_coord_t,y_coord_t,const locator&); + iterator View::at(x_coord_t,y_coord_t) const; + reference operator()(View,x_coord_t,y_coord_t) const; + xy_locator View::xy_at(x_coord_t,y_coord_t) const; + x_iterator View::x_at(x_coord_t,y_coord_t) const; + y_iterator View::y_at(x_coord_t,y_coord_t) const; +}; +\endcode +*/ +template +struct RandomAccess2DImageViewConcept { + void constraints() { + gil_function_requires >(); + BOOST_STATIC_ASSERT(View::num_dimensions==2); + + // TODO: This executes the requirements for RandomAccessNDLocatorConcept again. Fix it to improve compile time + gil_function_requires >(); + + typedef typename dynamic_x_step_type::type dynamic_x_step_t; + typedef typename dynamic_y_step_type::type dynamic_y_step_t; + typedef typename transposed_type::type transposed_t; + + typedef typename View::x_iterator x_iterator; + typedef typename View::y_iterator y_iterator; + typedef typename View::x_coord_t x_coord_t; + typedef typename View::y_coord_t y_coord_t; + typedef typename View::xy_locator xy_locator; + + x_coord_t xd=0; ignore_unused_variable_warning(xd); + y_coord_t yd=0; ignore_unused_variable_warning(yd); + x_iterator xit; + y_iterator yit; + typename View::point_t d; + + View(xd,yd,xy_locator()); // constructible with width, height, 2d_locator + + xy_locator lc=view.xy_at(xd,yd); + lc=view.xy_at(d); + + typename View::reference r=view(xd,yd); ignore_unused_variable_warning(r); + xd=view.width(); + yd=view.height(); + + xit=view.x_at(d); + xit=view.x_at(xd,yd); + xit=view.row_begin(xd); + xit=view.row_end(xd); + + yit=view.y_at(d); + yit=view.y_at(xd,yd); + yit=view.col_begin(xd); + yit=view.col_end(xd); + } + View view; +}; + + +/// \ingroup PixelImageViewConcept +/// \brief GIL's 2-dimensional view over immutable GIL pixels +/** +\code +concept ImageViewConcept { + where PixelValueConcept; + where PixelIteratorConcept; + where PixelIteratorConcept; + where x_coord_t == y_coord_t; + + typename coord_t = x_coord_t; + + std::size_t View::num_channels() const; +}; +\endcode +*/ +template +struct ImageViewConcept { + void constraints() { + gil_function_requires >(); + + // TODO: This executes the requirements for RandomAccess2DLocatorConcept again. Fix it to improve compile time + gil_function_requires >(); + + BOOST_STATIC_ASSERT((is_same::value)); + + typedef typename View::coord_t coord_t; // 1D difference type (same for all dimensions) + std::size_t num_chan = view.num_channels(); ignore_unused_variable_warning(num_chan); + } + View view; +}; + + +namespace detail { + template // Preconditions: View Models RandomAccessNDImageViewConcept + struct RandomAccessNDImageViewIsMutableConcept { + void constraints() { + gil_function_requires >(); + + gil_function_requires >(); + gil_function_requires >(); + gil_function_requires::iterator> >(); + gil_function_requires::iterator> >(); + + typename View::difference_type diff; initialize_it(diff); ignore_unused_variable_warning(diff); + typename View::point_t pt; + typename View::value_type v; initialize_it(v); + + view[diff]=v; + view(pt)=v; + } + View view; + }; + + template // preconditions: View Models RandomAccessNDImageViewConcept + struct RandomAccess2DImageViewIsMutableConcept { + void constraints() { + gil_function_requires >(); + typename View::x_coord_t xd=0; ignore_unused_variable_warning(xd); + typename View::y_coord_t yd=0; ignore_unused_variable_warning(yd); + typename View::value_type v; initialize_it(v); + view(xd,yd)=v; + } + View view; + }; + + template // preconditions: View Models ImageViewConcept + struct PixelImageViewIsMutableConcept { + void constraints() { + gil_function_requires >(); + } + }; +} + +/// \ingroup ImageViewNDConcept +/// \brief N-dimensional view over mutable values +/** +\code +concept MutableRandomAccessNDImageViewConcept { + where Mutable; +}; +\endcode +*/ +template +struct MutableRandomAccessNDImageViewConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + } +}; + +/// \ingroup ImageView2DConcept +/// \brief 2-dimensional view over mutable values +/** +\code +concept MutableRandomAccess2DImageViewConcept : MutableRandomAccessNDImageViewConcept {}; +\endcode +*/ +template +struct MutableRandomAccess2DImageViewConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + } +}; + +/// \ingroup PixelImageViewConcept +/// \brief GIL's 2-dimensional view over mutable GIL pixels +/** +\code +concept MutableImageViewConcept : MutableRandomAccess2DImageViewConcept {}; +\endcode +*/ +template +struct MutableImageViewConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + } +}; + +/// \brief Returns whether two views are compatible +/// +/// Views are compatible if their pixels are compatible. Compatible views can be assigned and copy constructed from one another. +template // Model ImageViewConcept +struct views_are_compatible : public pixels_are_compatible {}; + +/// \brief Views are compatible if they have the same color spaces and compatible channel values. Constness and layout are not important for compatibility +/// \ingroup ImageViewConcept +/** +\code +concept ViewsCompatibleConcept { + where PixelsCompatibleConcept; +}; +\endcode +*/ +template +struct ViewsCompatibleConcept { + void constraints() { + BOOST_STATIC_ASSERT((views_are_compatible::value)); + } +}; + + +//////////////////////////////////////////////////////////////////////////////////////// +/// +/// IMAGE CONCEPTS +/// +//////////////////////////////////////////////////////////////////////////////////////// + + +/// \ingroup ImageConcept +/// \brief N-dimensional container of values +/** +\code +concept RandomAccessNDImageConcept : Regular { + typename view_t; where MutableRandomAccessNDImageViewConcept; + typename const_view_t = view_t::const_t; + typename point_t = view_t::point_t; + typename value_type = view_t::value_type; + typename allocator_type; + + Img::Img(point_t dims, std::size_t alignment=1); + Img::Img(point_t dims, value_type fill_value, std::size_t alignment); + + void Img::recreate(point_t new_dims, std::size_t alignment=1); + void Img::recreate(point_t new_dims, value_type fill_value, std::size_t alignment); + + const point_t& Img::dimensions() const; + const const_view_t& const_view(const Img&); + const view_t& view(Img&); +}; +\endcode +*/ +template +struct RandomAccessNDImageConcept { + void constraints() { + gil_function_requires >(); + + typedef typename Img::view_t view_t; + gil_function_requires >(); + + typedef typename Img::const_view_t const_view_t; + typedef typename Img::value_type pixel_t; + + typedef typename Img::point_t point_t; + gil_function_requires >(); + + const_view_t cv = const_view(img); ignore_unused_variable_warning(cv); + view_t v = view(img); ignore_unused_variable_warning(v); + + pixel_t fill_value; + point_t pt=img.dimensions(); + Img im1(pt); + Img im2(pt,1); + Img im3(pt,fill_value,1); + img.recreate(pt); + img.recreate(pt,1); + img.recreate(pt,fill_value,1); + } + Img img; +}; + + +/// \ingroup ImageConcept +/// \brief 2-dimensional container of values +/** +\code +concept RandomAccess2DImageConcept { + typename x_coord_t = const_view_t::x_coord_t; + typename y_coord_t = const_view_t::y_coord_t; + + Img::Img(x_coord_t width, y_coord_t height, std::size_t alignment=1); + Img::Img(x_coord_t width, y_coord_t height, value_type fill_value, std::size_t alignment); + + x_coord_t Img::width() const; + y_coord_t Img::height() const; + + void Img::recreate(x_coord_t width, y_coord_t height, std::size_t alignment=1); + void Img::recreate(x_coord_t width, y_coord_t height, value_type fill_value, std::size_t alignment); +}; +\endcode +*/ +template +struct RandomAccess2DImageConcept { + void constraints() { + gil_function_requires >(); + typedef typename Img::x_coord_t x_coord_t; + typedef typename Img::y_coord_t y_coord_t; + typedef typename Img::value_type value_t; + + gil_function_requires >(); + + x_coord_t w=img.width(); + y_coord_t h=img.height(); + value_t fill_value; + Img im1(w,h); + Img im2(w,h,1); + Img im3(w,h,fill_value,1); + img.recreate(w,h); + img.recreate(w,h,1); + img.recreate(w,h,fill_value,1); + } + Img img; +}; + +/// \ingroup ImageConcept +/// \brief 2-dimensional image whose value type models PixelValueConcept +/** +\code +concept ImageConcept { + where MutableImageViewConcept; + typename coord_t = view_t::coord_t; +}; +\endcode +*/ +template +struct ImageConcept { + void constraints() { + gil_function_requires >(); + gil_function_requires >(); + typedef typename Img::coord_t coord_t; + BOOST_STATIC_ASSERT(num_channels::value == mpl::size::type>::value); + + BOOST_STATIC_ASSERT((is_same::value)); + BOOST_STATIC_ASSERT((is_same::value)); + } + Img img; +}; + + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/gil_config.hpp b/win32/include/boost/gil/gil_config.hpp new file mode 100755 index 000000000..3922b523f --- /dev/null +++ b/win32/include/boost/gil/gil_config.hpp @@ -0,0 +1,50 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_CONFIG_HPP +#define GIL_CONFIG_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief GIL configuration file +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include + +#define GIL_VERSION "2.1.2" + +#ifdef _DEBUG +# define GIL_FORCEINLINE inline +#else +#ifdef NDEBUG +#if defined(_MSC_VER) +# define GIL_FORCEINLINE __forceinline +#elif defined(__GNUC__) && __GNUC__ > 3 +# define GIL_FORCEINLINE inline __attribute__ ((always_inline)) +#else +# define GIL_FORCEINLINE inline +#endif +#else +# define GIL_FORCEINLINE inline +#endif +#endif + +// Enable GIL_NONWORD_POINTER_ALIGNMENT_SUPPORTED if your platform supports dereferencing on non-word memory boundary. +// Enabling the flag results in performance improvement +#if !defined(__hpux) && !defined(sun) && !defined(__sun) && !defined(__osf__) + #define GIL_NONWORD_POINTER_ALIGNMENT_SUPPORTED +#endif + +#endif diff --git a/win32/include/boost/gil/gray.hpp b/win32/include/boost/gil/gray.hpp new file mode 100755 index 000000000..af32d2935 --- /dev/null +++ b/win32/include/boost/gil/gray.hpp @@ -0,0 +1,45 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_GRAY_H +#define GIL_GRAY_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Support for grayscale color space and variants +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on March 8, 2006 +//////////////////////////////////////////////////////////////////////////////////////// + +#include "gil_config.hpp" +#include "utilities.hpp" +#include +#include +#include + +namespace boost { namespace gil { + +/// \ingroup ColorNameModel +/// \brief Gray +struct gray_color_t {}; + +/// \ingroup ColorSpaceModel +typedef mpl::vector1 gray_t; + +/// \ingroup LayoutModel +typedef layout gray_layout_t; + +} } // namespace boost::gil + +#endif + diff --git a/win32/include/boost/gil/image.hpp b/win32/include/boost/gil/image.hpp new file mode 100755 index 000000000..7e72473df --- /dev/null +++ b/win32/include/boost/gil/image.hpp @@ -0,0 +1,288 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ +/*************************************************************************************************/ + +#ifndef GIL_IMAGE_H +#define GIL_IMAGE_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Templated image +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on February 12, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "gil_config.hpp" +#include "image_view.hpp" +#include "metafunctions.hpp" +#include "algorithm.hpp" + +namespace boost { namespace gil { + +//#ifdef _MSC_VER +//#pragma warning(push) +//#pragma warning(disable : 4244) // conversion from 'gil::image::coord_t' to 'int', possible loss of data (visual studio compiler doesn't realize that the two types are the same) +//#endif + +//////////////////////////////////////////////////////////////////////////////////////// +/// \ingroup ImageModel PixelBasedModel +/// \brief container interface over image view. Models ImageConcept, PixelBasedConcept +/// +/// A 2D container whose elements are pixels. It is templated over the pixel type, a boolean +/// indicating whether it should be planar, and an optional allocator. +/// +/// Note that its element type does not have to be a pixel. \p image can be instantiated with any Regular element, +/// in which case it models the weaker RandomAccess2DImageConcept and does not model PixelBasedConcept +/// +//////////////////////////////////////////////////////////////////////////////////////// + +template > +class image { +public: + typedef typename Alloc::template rebind::other allocator_type; + typedef typename view_type_from_pixel::type view_t; + typedef typename view_t::const_t const_view_t; + typedef typename view_t::point_t point_t; + typedef typename view_t::coord_t coord_t; + typedef typename view_t::value_type value_type; + typedef coord_t x_coord_t; + typedef coord_t y_coord_t; + + const point_t& dimensions() const { return _view.dimensions(); } + x_coord_t width() const { return _view.width(); } + y_coord_t height() const { return _view.height(); } + + explicit image(std::size_t alignment=0, + const Alloc alloc_in = Alloc()) : + _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) {} + + // Create with dimensions and optional initial value and alignment + image(const point_t& dimensions, + std::size_t alignment=0, + const Alloc alloc_in = Alloc()) : _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) { + allocate_and_default_construct(dimensions); + } + image(x_coord_t width, y_coord_t height, + std::size_t alignment=0, + const Alloc alloc_in = Alloc()) : _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) { + allocate_and_default_construct(point_t(width,height)); + } + image(const point_t& dimensions, + const Pixel& p_in, + std::size_t alignment, + const Alloc alloc_in = Alloc()) : + _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) { + allocate_and_fill(dimensions, p_in); + } + image(x_coord_t width, y_coord_t height, + const Pixel& p_in, + std::size_t alignment, + const Alloc alloc_in = Alloc()) : + _memory(0), _align_in_bytes(alignment), _alloc(alloc_in) { + allocate_and_fill(point_t(width,height),p_in); + } + + image(const image& img) : + _memory(0), _align_in_bytes(img._align_in_bytes), _alloc(img._alloc) { + allocate_and_copy(img.dimensions(),img._view); + } + + template + image(const image& img) : + _memory(0), _align_in_bytes(img._align_in_bytes), _alloc(img._alloc) { + allocate_and_copy(img.dimensions(),img._view); + } + image& operator=(const image& img) { + if (dimensions() == img.dimensions()) + copy_pixels(img._view,_view); + else { + image tmp(img); + swap(tmp); + } + return *this; + } + + template + image& operator=(const Img& img) { + if (dimensions() == img.dimensions()) + copy_pixels(img._view,_view); + else { + image tmp(img); + swap(tmp); + } + return *this; + } + + ~image() { + destruct_pixels(_view); + deallocate(_view.dimensions()); + } + + Alloc& allocator() { return _alloc; } + Alloc const& allocator() const { return _alloc; } + + void swap(image& img) { // required by MutableContainerConcept + using std::swap; + swap(_align_in_bytes, img._align_in_bytes); + swap(_memory, img._memory); + swap(_view, img._view); + swap(_alloc, img._alloc); + } + + void recreate(const point_t& dims, std::size_t alignment=0, const Alloc alloc_in = Alloc()) { + if (dims!=_view.dimensions() || _align_in_bytes!=alignment || alloc_in!=_alloc) { + image tmp(dims, alignment, alloc_in); + swap(tmp); + } + } + void recreate(x_coord_t width, y_coord_t height, std::size_t alignment=0, const Alloc alloc_in = Alloc()) { + recreate(point_t(width,height),alignment,alloc_in); + } + void recreate(const point_t& dims, + const Pixel& p_in, std::size_t alignment, const Alloc alloc_in = Alloc()) { + if (dims!=_view.dimensions() || _align_in_bytes!=alignment || alloc_in!=_alloc) { + image tmp(dims, p_in, alignment, alloc_in); + swap(tmp); + } + } + void recreate(x_coord_t width, y_coord_t height, + const Pixel& p_in, std::size_t alignment, const Alloc alloc_in = Alloc()) { + recreate(point_t(width,height),p_in,alignment,alloc_in); + } + + view_t _view; // contains pointer to the pixels, the image size and ways to navigate pixels +private: + unsigned char* _memory; + std::size_t _align_in_bytes; + allocator_type _alloc; + + void allocate_and_default_construct(const point_t& dimensions) { + try { + allocate_(dimensions,mpl::bool_()); + default_construct_pixels(_view); + } catch(...) { deallocate(dimensions); throw; } + } + + void allocate_and_fill(const point_t& dimensions, const Pixel& p_in) { + try { + allocate_(dimensions,mpl::bool_()); + uninitialized_fill_pixels(_view, p_in); + } catch(...) { deallocate(dimensions); throw; } + } + + template + void allocate_and_copy(const point_t& dimensions, const View& v) { + try { + allocate_(dimensions,mpl::bool_()); + uninitialized_copy_pixels(v,_view); + } catch(...) { deallocate(dimensions); throw; } + } + + void deallocate(const point_t& dimensions) { + if (_memory) _alloc.deallocate(_memory, total_allocated_size_in_bytes(dimensions)); + } + + std::size_t total_allocated_size_in_bytes(const point_t& dimensions) const { + std::size_t size_in_units = get_row_size_in_memunits(dimensions.x)*dimensions.y; + if (IsPlanar) + size_in_units = size_in_units*num_channels::value; + + // return the size rounded up to the nearest byte + return (size_in_units + byte_to_memunit::value - 1) / byte_to_memunit::value + + (_align_in_bytes>0 ? _align_in_bytes-1:0); // add extra padding in case we need to align the first image pixel + } + + std::size_t get_row_size_in_memunits(x_coord_t width) const { // number of units per row + std::size_t size_in_memunits = width*memunit_step(typename view_t::x_iterator()); + if (_align_in_bytes>0) { + std::size_t alignment_in_memunits=_align_in_bytes*byte_to_memunit::value; + return align(size_in_memunits, alignment_in_memunits); + } + return size_in_memunits; + } + + void allocate_(const point_t& dimensions, mpl::false_) { // if it throws and _memory!=0 the client must deallocate _memory + _memory=_alloc.allocate(total_allocated_size_in_bytes(dimensions)); + unsigned char* tmp=(_align_in_bytes>0) ? (unsigned char*)align((std::size_t)_memory,_align_in_bytes) : _memory; + _view=view_t(dimensions,typename view_t::locator(typename view_t::x_iterator(tmp),get_row_size_in_memunits(dimensions.x))); + } + + void allocate_(const point_t& dimensions, mpl::true_) { // if it throws and _memory!=0 the client must deallocate _memory + std::size_t row_size=get_row_size_in_memunits(dimensions.x); + std::size_t plane_size=row_size*dimensions.y; + _memory=_alloc.allocate(total_allocated_size_in_bytes(dimensions)); + unsigned char* tmp=(_align_in_bytes>0) ? (unsigned char*)align((std::size_t)_memory,_align_in_bytes) : _memory; + typename view_t::x_iterator first; + for (int i=0; i::value; ++i) { + dynamic_at_c(first,i) = (typename channel_type::type*)tmp; + memunit_advance(dynamic_at_c(first,i), plane_size*i); + } + _view=view_t(dimensions, typename view_t::locator(first, row_size)); + } +}; + +template +void swap(image& im1,image& im2) { + im1.swap(im2); +} + +template +bool operator==(const image& im1,const image& im2) { + if ((void*)(&im1)==(void*)(&im2)) return true; + if (const_view(im1).dimensions()!=const_view(im2).dimensions()) return false; + return equal_pixels(const_view(im1),const_view(im2)); +} +template +bool operator!=(const image& im1,const image& im2) {return !(im1==im2);} + +///@{ +/// \name view, const_view +/// \brief Get an image view from an image + +/// \ingroup ImageModel + +/// \brief Returns the non-constant-pixel view of an image +template inline +const typename image::view_t& view(image& img) { return img._view; } + +/// \brief Returns the constant-pixel view of an image +template inline +const typename image::const_view_t const_view(const image& img) { + return static_cast::const_view_t>(img._view); +} +///@} + +///////////////////////////// +// PixelBasedConcept +///////////////////////////// + +template +struct channel_type > : public channel_type {}; + +template +struct color_space_type > : public color_space_type {}; + +template +struct channel_mapping_type > : public channel_mapping_type {}; + +template +struct is_planar > : public mpl::bool_ {}; + +//#ifdef _MSC_VER +//#pragma warning(pop) +//#endif + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/image_view.hpp b/win32/include/boost/gil/image_view.hpp new file mode 100755 index 000000000..fb4e13201 --- /dev/null +++ b/win32/include/boost/gil/image_view.hpp @@ -0,0 +1,223 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ +/*************************************************************************************************/ + +#ifndef GIL_IMAGE_VIEW_H +#define GIL_IMAGE_VIEW_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief image view class +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on February 12, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "gil_config.hpp" +#include "iterator_from_2d.hpp" + +//#ifdef _MSC_VER +//#pragma warning(push) +//#pragma warning(disable : 4244) // conversion from 'gil::image::coord_t' to 'int', possible loss of data (visual studio compiler doesn't realize that the two types are the same) +//#endif + +namespace boost { namespace gil { + +//////////////////////////////////////////////////////////////////////////////////////// +/// \class image_view +/// \ingroup ImageViewModel PixelBasedModel +/// \brief A lightweight object that interprets memory as a 2D array of pixels. Models ImageViewConcept,PixelBasedConcept,HasDynamicXStepTypeConcept,HasDynamicYStepTypeConcept,HasTransposedTypeConcept +/// +/// Image view consists of a pixel 2D locator (defining the mechanism for navigating in 2D) +/// and the image dimensions. +/// +/// Image views to images are what ranges are to STL containers. They are lightweight objects, +/// that don't own the pixels. It is the user's responsibility that the underlying data remains +/// valid for the lifetime of the image view. +/// +/// Similar to iterators and ranges, constness of views does not extend to constness of pixels. +/// A const \p image_view does not allow changing its location in memory (resizing, moving) but does +/// not prevent one from changing the pixels. The latter requires an image view whose value_type +/// is const. +/// +/// Images have interfaces consistent with STL 1D random access containers, so they can be used +/// directly in STL algorithms like: +/// \code +/// std::fill(img.begin(), img.end(), red_pixel); +/// \endcode +/// +/// In addition, horizontal, vertical and 2D random access iterators are provided. +/// +/// Note also that \p image_view does not require that its element type be a pixel. It could be +/// instantiated with a locator whose \p value_type models only \p Regular. In this case the image +/// view models the weaker RandomAccess2DImageViewConcept, and does not model PixelBasedConcept. +/// Many generic algorithms don't require the elements to be pixels. +/// +//////////////////////////////////////////////////////////////////////////////////////// +template // Models 2D Pixel Locator +class image_view { +public: + +// typedefs required by ConstRandomAccessNDImageViewConcept + static const std::size_t num_dimensions=2; + typedef typename Loc::value_type value_type; + typedef typename Loc::reference reference; // result of dereferencing + typedef typename Loc::coord_t coord_t; // 1D difference type (same for all dimensions) + typedef coord_t difference_type; // result of operator-(1d_iterator,1d_iterator) + typedef typename Loc::point_t point_t; + typedef Loc locator; + typedef image_view const_t; // same as this type, but over const values + template struct axis { + typedef typename Loc::template axis::coord_t coord_t; // difference_type along each dimension + typedef typename Loc::template axis::iterator iterator; // 1D iterator type along each dimension + }; + typedef iterator_from_2d iterator; // 1D iterator type for each pixel left-to-right inside top-to-bottom + typedef std::reverse_iterator reverse_iterator; + typedef std::size_t size_type; + +// typedefs required by ConstRandomAccess2DImageViewConcept + typedef locator xy_locator; + typedef typename xy_locator::x_iterator x_iterator; // pixel iterator along a row + typedef typename xy_locator::y_iterator y_iterator; // pixel iterator along a column + typedef typename xy_locator::x_coord_t x_coord_t; + typedef typename xy_locator::y_coord_t y_coord_t; + + template struct add_deref { + typedef image_view::type> type; + static type make(const image_view& iv, const Deref& d) { return type(iv.dimensions(), Loc::template add_deref::make(iv.pixels(),d)); } + }; + + image_view() : _dimensions(0,0) {} + template image_view(const View& iv) : _dimensions(iv.dimensions()), _pixels(iv.pixels()) {} + + template image_view(const point_t& sz , const L2& loc) : _dimensions(sz), _pixels(loc) {} + template image_view(coord_t width, coord_t height, const L2& loc) : _dimensions(x_coord_t(width),y_coord_t(height)), _pixels(loc) {} + + template image_view& operator=(const View& iv) { _pixels=iv.pixels(); _dimensions=iv.dimensions(); return *this; } + image_view& operator=(const image_view& iv) { _pixels=iv.pixels(); _dimensions=iv.dimensions(); return *this; } + + template bool operator==(const View& v) const { return pixels()==v.pixels() && dimensions()==v.dimensions(); } + template bool operator!=(const View& v) const { return !(*this==v); } + + template friend void swap(image_view& x, image_view& y); + + const point_t& dimensions() const { return _dimensions; } + const locator& pixels() const { return _pixels; } + x_coord_t width() const { return dimensions().x; } + y_coord_t height() const { return dimensions().y; } + std::size_t num_channels() const { return gil::num_channels::value; } + bool is_1d_traversable() const { return _pixels.is_1d_traversable(width()); } + + //\{@ + /// \name 1D navigation + size_type size() const { return width()*height(); } + iterator begin() const { return iterator(_pixels,_dimensions.x); } + iterator end() const { return begin()+(difference_type)size(); } // potential performance problem! + reverse_iterator rbegin() const { return reverse_iterator(end()); } + reverse_iterator rend() const { return reverse_iterator(begin()); } + reference operator[](difference_type i) const { return begin()[i]; } // potential performance problem! + iterator at(difference_type i)const { return begin()+i; } + iterator at(const point_t& p) const { return begin()+p.y*width()+p.x; } + iterator at(x_coord_t x, y_coord_t y)const { return begin()+y*width()+x; } + + //\}@ + + //\{@ + /// \name 2-D navigation + reference operator()(const point_t& p) const { return _pixels(p.x,p.y); } + reference operator()(x_coord_t x, y_coord_t y)const { return _pixels(x,y); } + template typename axis::iterator axis_iterator(const point_t& p) const { return _pixels.axis_iterator(p); } + xy_locator xy_at(x_coord_t x, y_coord_t y) const { return _pixels+point_t(x_coord_t(x),y_coord_t(y)); } + locator xy_at(const point_t& p) const { return _pixels+p; } + //\}@ + + //\{@ + /// \name X navigation + x_iterator x_at(x_coord_t x, y_coord_t y) const { return _pixels.x_at(x,y); } + x_iterator x_at(const point_t& p) const { return _pixels.x_at(p); } + x_iterator row_begin(y_coord_t y) const { return x_at(0,y); } + x_iterator row_end(y_coord_t y) const { return x_at(width(),y); } + //\}@ + + //\{@ + /// \name Y navigation + y_iterator y_at(x_coord_t x, y_coord_t y) const { return xy_at(x,y).y(); } + y_iterator y_at(const point_t& p) const { return xy_at(p).y(); } + y_iterator col_begin(x_coord_t x) const { return y_at(x,0); } + y_iterator col_end(x_coord_t x) const { return y_at(x,height()); } + //\}@ + +private: + template friend class image_view; + + point_t _dimensions; + xy_locator _pixels; +}; + +template +inline void swap(image_view& x, image_view& y) { + using std::swap; + swap(x._dimensions,y._dimensions); + swap(x._pixels, y._pixels); // TODO: Extend further +} + +///////////////////////////// +// PixelBasedConcept +///////////////////////////// + +template +struct channel_type > : public channel_type {}; + +template +struct color_space_type > : public color_space_type {}; + +template +struct channel_mapping_type > : public channel_mapping_type {}; + +template +struct is_planar > : public is_planar {}; + +///////////////////////////// +// HasDynamicXStepTypeConcept +///////////////////////////// + +template +struct dynamic_x_step_type > { + typedef image_view::type> type; +}; + +///////////////////////////// +// HasDynamicYStepTypeConcept +///////////////////////////// + +template +struct dynamic_y_step_type > { + typedef image_view::type> type; +}; + +///////////////////////////// +// HasTransposedTypeConcept +///////////////////////////// + +template +struct transposed_type > { + typedef image_view::type> type; +}; + +} } // namespace boost::gil + +//#ifdef _MSC_VER +//#pragma warning(pop) +//#endif + +#endif diff --git a/win32/include/boost/gil/image_view_factory.hpp b/win32/include/boost/gil/image_view_factory.hpp new file mode 100755 index 000000000..e8e533a04 --- /dev/null +++ b/win32/include/boost/gil/image_view_factory.hpp @@ -0,0 +1,537 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_IMAGE_VIEW_FACTORY_HPP +#define GIL_IMAGE_VIEW_FACTORY_HPP + +/*! +/// \file +/// \brief Methods for constructing image views from raw data or other image views +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on March 9, 2007 +/// Methods for creating shallow image views from raw pixel data or from other image views - +/// flipping horizontally or vertically, axis-aligned rotation, a subimage, subsampled +/// or n-th channel image view. Derived image views are shallow copies and are fast to construct. +*/ + +#include +#include +#include "gil_config.hpp" +#include "metafunctions.hpp" +#include "gray.hpp" +#include "color_convert.hpp" + +/// \defgroup ImageViewConstructors Image View From Raw Data +/// \ingroup ImageViewAlgorithm +/// \brief Methods for constructing image views from raw data and for getting raw data from views + +/// \defgroup ImageViewTransformations Image View Transformations +/// \ingroup ImageViewAlgorithm +/// \brief Methods for constructing one image view from another + +namespace boost { namespace gil { +struct default_color_converter; + +template struct dynamic_x_step_type; +template struct dynamic_y_step_type; +template struct transposed_type; + +/// \brief Returns the type of a view that has a dynamic step along both X and Y +/// \ingroup ImageViewTransformations +template +struct dynamic_xy_step_type : public dynamic_y_step_type::type> {}; + +/// \brief Returns the type of a transposed view that has a dynamic step along both X and Y +/// \ingroup ImageViewTransformations +template +struct dynamic_xy_step_transposed_type : public dynamic_xy_step_type::type> {}; + + +/// \ingroup ImageViewConstructors +/// \brief Constructing image views from raw interleaved pixel data +template +typename type_from_x_iterator::view_t +interleaved_view(std::size_t width, std::size_t height, + Iterator pixels, std::ptrdiff_t rowsize_in_bytes) { + typedef typename type_from_x_iterator::view_t RView; + return RView(width, height, typename RView::locator(pixels, rowsize_in_bytes)); +} + +/// \ingroup ImageViewConstructors +/// \brief Constructing image views from raw interleaved pixel data +template +typename type_from_x_iterator::view_t +interleaved_view(point2 dim, + Iterator pixels, std::ptrdiff_t rowsize_in_bytes) { + typedef typename type_from_x_iterator::view_t RView; + return RView(dim, typename RView::locator(pixels, rowsize_in_bytes)); +} + +///////////////////////////// +// interleaved_view_get_raw_data, planar_view_get_raw_data - return pointers to the raw data (the channels) of a basic homogeneous view. +///////////////////////////// + +namespace detail { + template struct channel_pointer_type_impl; + + template struct channel_pointer_type_impl { + typedef typename channel_type::type* type; + }; + template struct channel_pointer_type_impl { + typedef const typename channel_type::type* type; + }; + + template struct channel_pointer_type + : public channel_pointer_type_impl::value> {}; +} // namespace detail + +/// \ingroup ImageViewConstructors +/// \brief Returns C pointer to the the channels of an interleaved homogeneous view. +template +typename detail::channel_pointer_type::type interleaved_view_get_raw_data(const HomogeneousView& view) { + BOOST_STATIC_ASSERT((!is_planar::value && view_is_basic::value)); + BOOST_STATIC_ASSERT((boost::is_pointer::value)); + + return &at_c<0>(view(0,0)); +} + +/// \ingroup ImageViewConstructors +/// \brief Returns C pointer to the the channels of a given color plane of a planar homogeneous view. +template +typename detail::channel_pointer_type::type planar_view_get_raw_data(const HomogeneousView& view, int plane_index) { + BOOST_STATIC_ASSERT((is_planar::value && view_is_basic::value)); + return dynamic_at_c(view.row_begin(0),plane_index); +} + + +/// \defgroup ImageViewTransformationsColorConvert color_converted_view +/// \ingroup ImageViewTransformations +/// \brief Color converted view of another view + +/// \ingroup ImageViewTransformationsColorConvert PixelDereferenceAdaptorModel +/// \brief Function object that given a source pixel, returns it converted to a given color space and channel depth. Models: PixelDereferenceAdaptorConcept +/// +/// Useful in constructing a color converted view over a given image view +template // const_reference to the source pixel and destination pixel value +class color_convert_deref_fn : public deref_base, DstP, DstP, const DstP&, SrcConstRefP, DstP, false> { +private: + CC _cc; // color-converter +public: + color_convert_deref_fn() {} + color_convert_deref_fn(CC cc_in) : _cc(cc_in) {} + + DstP operator()(SrcConstRefP srcP) const { + DstP dstP; + _cc(srcP,dstP); + return dstP; + } +}; + +namespace detail { + // Add color converter upon dereferencing + template + struct _color_converted_view_type { + private: + typedef color_convert_deref_fn deref_t; + typedef typename SrcView::template add_deref add_ref_t; + public: + typedef typename add_ref_t::type type; + static type make(const SrcView& sv,CC cc) {return add_ref_t::make(sv,deref_t(cc));} + }; + + // If the Src view has the same pixel type as the target, there is no need for color conversion + template + struct _color_converted_view_type { + typedef SrcView type; + static type make(const SrcView& sv,CC) {return sv;} + }; +} // namespace detail + + +/// \brief Returns the type of a view that does color conversion upon dereferencing its pixels +/// \ingroup ImageViewTransformationsColorConvert +template +struct color_converted_view_type : public detail::_color_converted_view_type { + GIL_CLASS_REQUIRE(DstP, boost::gil, MutablePixelConcept)//why does it have to be mutable??? +}; + + +/// \ingroup ImageViewTransformationsColorConvert +/// \brief view of a different color space with a user defined color-converter +template +inline typename color_converted_view_type::type color_converted_view(const View& src,CC cc) { + return color_converted_view_type::make(src,cc); +} + +/// \ingroup ImageViewTransformationsColorConvert +/// \brief overload of generic color_converted_view with the default color-converter +template +inline typename color_converted_view_type::type +color_converted_view(const View& src) { + return color_converted_view(src,default_color_converter()); +} + +/// \defgroup ImageViewTransformationsFlipUD flipped_up_down_view +/// \ingroup ImageViewTransformations +/// \brief view of a view flipped up-to-down + +/// \ingroup ImageViewTransformationsFlipUD +template +inline typename dynamic_y_step_type::type flipped_up_down_view(const View& src) { + typedef typename dynamic_y_step_type::type RView; + return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(0,src.height()-1),-1)); +} + +/// \defgroup ImageViewTransformationsFlipLR flipped_left_right_view +/// \ingroup ImageViewTransformations +/// \brief view of a view flipped left-to-right + +/// \ingroup ImageViewTransformationsFlipLR +template +inline typename dynamic_x_step_type::type flipped_left_right_view(const View& src) { + typedef typename dynamic_x_step_type::type RView; + return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(src.width()-1,0),-1,1)); +} + +/// \defgroup ImageViewTransformationsTransposed transposed_view +/// \ingroup ImageViewTransformations +/// \brief view of a view transposed + +/// \ingroup ImageViewTransformationsTransposed +template +inline typename dynamic_xy_step_transposed_type::type transposed_view(const View& src) { + typedef typename dynamic_xy_step_transposed_type::type RView; + return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(0,0),1,1,true)); +} + +/// \defgroup ImageViewTransformations90CW rotated90cw_view +/// \ingroup ImageViewTransformations +/// \brief view of a view rotated 90 degrees clockwise + +/// \ingroup ImageViewTransformations90CW +template +inline typename dynamic_xy_step_transposed_type::type rotated90cw_view(const View& src) { + typedef typename dynamic_xy_step_transposed_type::type RView; + return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(0,src.height()-1),-1,1,true)); +} + +/// \defgroup ImageViewTransformations90CCW rotated90ccw_view +/// \ingroup ImageViewTransformations +/// \brief view of a view rotated 90 degrees counter-clockwise + +/// \ingroup ImageViewTransformations90CCW +template +inline typename dynamic_xy_step_transposed_type::type rotated90ccw_view(const View& src) { + typedef typename dynamic_xy_step_transposed_type::type RView; + return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(src.width()-1,0),1,-1,true)); +} + +/// \defgroup ImageViewTransformations180 rotated180_view +/// \ingroup ImageViewTransformations +/// \brief view of a view rotated 180 degrees + +/// \ingroup ImageViewTransformations180 +template +inline typename dynamic_xy_step_type::type rotated180_view(const View& src) { + typedef typename dynamic_xy_step_type::type RView; + return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(src.width()-1,src.height()-1),-1,-1)); +} + +/// \defgroup ImageViewTransformationsSubimage subimage_view +/// \ingroup ImageViewTransformations +/// \brief view of an axis-aligned rectangular area within an image_view + +/// \ingroup ImageViewTransformationsSubimage +template +inline View subimage_view(const View& src, const typename View::point_t& topleft, const typename View::point_t& dimensions) { + return View(dimensions,src.xy_at(topleft)); +} + +/// \ingroup ImageViewTransformationsSubimage +template +inline View subimage_view(const View& src, int xMin, int yMin, int width, int height) { + return View(width,height,src.xy_at(xMin,yMin)); +} + +/// \defgroup ImageViewTransformationsSubsampled subsampled_view +/// \ingroup ImageViewTransformations +/// \brief view of a subsampled version of an image_view, stepping over a number of channels in X and number of rows in Y + +/// \ingroup ImageViewTransformationsSubsampled +template +inline typename dynamic_xy_step_type::type subsampled_view(const View& src, typename View::coord_t xStep, typename View::coord_t yStep) { + assert(xStep>0 && yStep>0); + typedef typename dynamic_xy_step_type::type RView; + return RView((src.width()+(xStep-1))/xStep,(src.height()+(yStep-1))/yStep, + typename RView::xy_locator(src.xy_at(0,0),xStep,yStep)); +} + +/// \ingroup ImageViewTransformationsSubsampled +template +inline typename dynamic_xy_step_type::type subsampled_view(const View& src, const typename View::point_t& step) { + return subsampled_view(src,step.x,step.y); +} + +/// \defgroup ImageViewTransformationsNthChannel nth_channel_view +/// \ingroup ImageViewTransformations +/// \brief single-channel (grayscale) view of the N-th channel of a given image_view + +namespace detail { + template struct __nth_channel_view_basic; + + // nth_channel_view when the channels are not adjacent in memory. This can happen for multi-channel interleaved images + // or images with a step + template + struct __nth_channel_view_basic { + typedef typename view_type::type, gray_layout_t, false, true, view_is_mutable::value>::type type; + + static type make(const View& src, int n) { + typedef typename type::xy_locator locator_t; + typedef typename type::x_iterator x_iterator_t; + typedef typename iterator_adaptor_get_base::type x_iterator_base_t; + x_iterator_t sit(x_iterator_base_t(&(src(0,0)[n])),src.pixels().pixel_size()); + return type(src.dimensions(),locator_t(sit, src.pixels().row_size())); + } + }; + + // nth_channel_view when the channels are together in memory (true for simple grayscale or planar images) + template + struct __nth_channel_view_basic { + typedef typename view_type::type, gray_layout_t, false, false, view_is_mutable::value>::type type; + static type make(const View& src, int n) { + typedef typename type::x_iterator x_iterator_t; + return interleaved_view(src.width(),src.height(),(x_iterator_t)&(src(0,0)[n]), src.pixels().row_size()); + } + }; + + template struct __nth_channel_view; + + // For basic (memory-based) views dispatch to __nth_channel_view_basic + template struct __nth_channel_view { + private: + typedef typename View::x_iterator src_x_iterator; + + // Determines whether the channels of a given pixel iterator are adjacent in memory. + // Planar and grayscale iterators have channels adjacent in memory, whereas multi-channel interleaved and iterators with non-fundamental step do not. + BOOST_STATIC_CONSTANT(bool, adjacent= + !iterator_is_step::value && + (is_planar::value || + num_channels::value==1)); + public: + typedef typename __nth_channel_view_basic::type type; + + static type make(const View& src, int n) { + return __nth_channel_view_basic::make(src,n); + } + }; + + /// \brief Function object that returns a grayscale reference of the N-th channel of a given reference. Models: PixelDereferenceAdaptorConcept. + /// \ingroup PixelDereferenceAdaptorModel + /// + /// If the input is a pixel value or constant reference, the function object is immutable. Otherwise it is mutable (and returns non-const reference to the n-th channel) + template // SrcP is a reference to PixelConcept (could be pixel value or const/non-const reference) + // Examples: pixel, pixel&, const pixel&, planar_pixel_reference, planar_pixel_reference + struct nth_channel_deref_fn { + BOOST_STATIC_CONSTANT(bool, is_mutable=pixel_is_reference::value && pixel_reference_is_mutable::value); + private: + typedef typename remove_reference::type src_pixel_t; + typedef typename channel_type::type channel_t; + typedef typename src_pixel_t::const_reference const_ref_t; + typedef typename pixel_reference_type::type ref_t; + public: + typedef nth_channel_deref_fn const_t; + typedef typename pixel_value_type::type value_type; + typedef typename pixel_reference_type::type const_reference; + typedef SrcP argument_type; + typedef typename mpl::if_c::type reference; + typedef reference result_type; + + nth_channel_deref_fn(int n=0) : _n(n) {} + template nth_channel_deref_fn(const nth_channel_deref_fn

            & d) : _n(d._n) {} + + int _n; // the channel to use + + result_type operator()(argument_type srcP) const { + return result_type(srcP[_n]); + } + }; + + template struct __nth_channel_view { + private: + typedef nth_channel_deref_fn deref_t; + typedef typename View::template add_deref AD; + public: + typedef typename AD::type type; + static type make(const View& src, int n) { + return AD::make(src, deref_t(n)); + } + }; +} // namespace detail + +/// \brief Given a source image view type View, returns the type of an image view over a single channel of View +/// \ingroup ImageViewTransformationsNthChannel +/// +/// If the channels in the source view are adjacent in memory (such as planar non-step view or single-channel view) then the +/// return view is a single-channel non-step view. +/// If the channels are non-adjacent (interleaved and/or step view) then the return view is a single-channel step view. +template +struct nth_channel_view_type { +private: + GIL_CLASS_REQUIRE(View, boost::gil, ImageViewConcept) + typedef detail::__nth_channel_view::value> VB; +public: + typedef typename VB::type type; + static type make(const View& src, int n) { return VB::make(src,n); } +}; + + +/// \ingroup ImageViewTransformationsNthChannel +template +typename nth_channel_view_type::type nth_channel_view(const View& src, int n) { + return nth_channel_view_type::make(src,n); +} + + + + + + + +/// \defgroup ImageViewTransformationsKthChannel kth_channel_view +/// \ingroup ImageViewTransformations +/// \brief single-channel (grayscale) view of the K-th channel of a given image_view. The channel index is a template parameter + +namespace detail { + template struct __kth_channel_view_basic; + + // kth_channel_view when the channels are not adjacent in memory. This can happen for multi-channel interleaved images + // or images with a step + template + struct __kth_channel_view_basic { + private: + typedef typename kth_element_type::type channel_t; + public: + typedef typename view_type::value>::type type; + + static type make(const View& src) { + typedef typename type::xy_locator locator_t; + typedef typename type::x_iterator x_iterator_t; + typedef typename iterator_adaptor_get_base::type x_iterator_base_t; + x_iterator_t sit(x_iterator_base_t(&at_c(src(0,0))),src.pixels().pixel_size()); + return type(src.dimensions(),locator_t(sit, src.pixels().row_size())); + } + }; + + // kth_channel_view when the channels are together in memory (true for simple grayscale or planar images) + template + struct __kth_channel_view_basic { + private: + typedef typename kth_element_type::type channel_t; + public: + typedef typename view_type::value>::type type; + static type make(const View& src) { + typedef typename type::x_iterator x_iterator_t; + return interleaved_view(src.width(),src.height(),(x_iterator_t)&at_c(src(0,0)), src.pixels().row_size()); + } + }; + + template struct __kth_channel_view; + + // For basic (memory-based) views dispatch to __kth_channel_view_basic + template struct __kth_channel_view { + private: + typedef typename View::x_iterator src_x_iterator; + + // Determines whether the channels of a given pixel iterator are adjacent in memory. + // Planar and grayscale iterators have channels adjacent in memory, whereas multi-channel interleaved and iterators with non-fundamental step do not. + BOOST_STATIC_CONSTANT(bool, adjacent= + !iterator_is_step::value && + (is_planar::value || + num_channels::value==1)); + public: + typedef typename __kth_channel_view_basic::type type; + + static type make(const View& src) { + return __kth_channel_view_basic::make(src); + } + }; + + /// \brief Function object that returns a grayscale reference of the K-th channel (specified as a template parameter) of a given reference. Models: PixelDereferenceAdaptorConcept. + /// \ingroup PixelDereferenceAdaptorModel + /// + /// If the input is a pixel value or constant reference, the function object is immutable. Otherwise it is mutable (and returns non-const reference to the k-th channel) + template // SrcP is a reference to PixelConcept (could be pixel value or const/non-const reference) + // Examples: pixel, pixel&, const pixel&, planar_pixel_reference, planar_pixel_reference + struct kth_channel_deref_fn { + BOOST_STATIC_CONSTANT(bool, is_mutable=pixel_is_reference::value && pixel_reference_is_mutable::value); + private: + typedef typename remove_reference::type src_pixel_t; + typedef typename kth_element_type::type channel_t; + typedef typename src_pixel_t::const_reference const_ref_t; + typedef typename pixel_reference_type::type ref_t; + public: + typedef kth_channel_deref_fn const_t; + typedef typename pixel_value_type::type value_type; + typedef typename pixel_reference_type::type const_reference; + typedef SrcP argument_type; + typedef typename mpl::if_c::type reference; + typedef reference result_type; + + kth_channel_deref_fn() {} + template kth_channel_deref_fn(const kth_channel_deref_fn&) {} + + result_type operator()(argument_type srcP) const { + return result_type(at_c(srcP)); + } + }; + + template struct __kth_channel_view { + private: + typedef kth_channel_deref_fn deref_t; + typedef typename View::template add_deref AD; + public: + typedef typename AD::type type; + static type make(const View& src) { + return AD::make(src, deref_t()); + } + }; +} // namespace detail + +/// \brief Given a source image view type View, returns the type of an image view over a given channel of View. +/// \ingroup ImageViewTransformationsKthChannel +/// +/// If the channels in the source view are adjacent in memory (such as planar non-step view or single-channel view) then the +/// return view is a single-channel non-step view. +/// If the channels are non-adjacent (interleaved and/or step view) then the return view is a single-channel step view. +template +struct kth_channel_view_type { +private: + GIL_CLASS_REQUIRE(View, boost::gil, ImageViewConcept) + typedef detail::__kth_channel_view::value> VB; +public: + typedef typename VB::type type; + static type make(const View& src) { return VB::make(src); } +}; + +/// \ingroup ImageViewTransformationsKthChannel +template +typename kth_channel_view_type::type kth_channel_view(const View& src) { + return kth_channel_view_type::make(src); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/iterator_from_2d.hpp b/win32/include/boost/gil/iterator_from_2d.hpp new file mode 100755 index 000000000..cfb634493 --- /dev/null +++ b/win32/include/boost/gil/iterator_from_2d.hpp @@ -0,0 +1,175 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ +/*************************************************************************************************/ + +#ifndef GIL_ITERATOR_FROM_2D_H +#define GIL_ITERATOR_FROM_2D_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief pixel step iterator, pixel image iterator and pixel dereference iterator +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on September 18, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "gil_concept.hpp" +#include "gil_config.hpp" +#include "pixel_iterator.hpp" +#include "locator.hpp" + +namespace boost { namespace gil { + +//////////////////////////////////////////////////////////////////////////////////////// +/// +/// ITERATOR FROM 2D ADAPTOR +/// +//////////////////////////////////////////////////////////////////////////////////////// + + +/// \defgroup PixelIteratorModelFromLocator iterator_from_2d +/// \ingroup PixelIteratorModel +/// \brief An iterator over two-dimensional locator. Useful for iterating over the pixels of an image view. Models PixelIteratorConcept, PixelBasedConcept, HasDynamicXStepTypeConcept + + +/// \ingroup PixelIteratorModelFromLocator PixelBasedModel +/// \brief Provides 1D random-access navigation to the pixels of the image. Models: PixelIteratorConcept, PixelBasedConcept, HasDynamicXStepTypeConcept +/// +/// Pixels are traversed from the top to the bottom row and from the left to the right +/// within each row + +template // Models PixelLocatorConcept +class iterator_from_2d : public iterator_facade, + typename Loc2::value_type, + random_access_traversal_tag, + typename Loc2::reference, + typename Loc2::coord_t> { + GIL_CLASS_REQUIRE(Loc2, boost::gil, PixelLocatorConcept) +public: + typedef iterator_facade, + typename Loc2::value_type, + random_access_traversal_tag, + typename Loc2::reference, + typename Loc2::coord_t> parent_t; + typedef typename parent_t::reference reference; + typedef typename parent_t::difference_type difference_type; + typedef typename Loc2::x_iterator x_iterator; + typedef typename Loc2::point_t point_t; + + std::ptrdiff_t width() const { return _width; } // number of pixels per image row + std::ptrdiff_t x_pos() const { return _coords.x; } // current x position + std::ptrdiff_t y_pos() const { return _coords.y; } // current y position + + /// For some reason operator[] provided by iterator_adaptor returns a custom class that is convertible to reference + /// We require our own reference because it is registered in iterator_traits + reference operator[](difference_type d) const { return *(*this+d); } + + bool is_1d_traversable() const { return _p.is_1d_traversable(width()); } // is there no gap at the end of each row? + x_iterator& x() { return _p.x(); } + + iterator_from_2d(){} + iterator_from_2d(const Loc2& p, std::ptrdiff_t width, std::ptrdiff_t x=0, std::ptrdiff_t y=0) : _coords(x,y), _width(width), _p(p) {} + iterator_from_2d(const iterator_from_2d& pit) : _coords(pit._coords), _width(pit._width), _p(pit._p) {} + template iterator_from_2d(const iterator_from_2d& pit) : _coords(pit._coords), _width(pit._width), _p(pit._p) {} + +private: + template friend class iterator_from_2d; + friend class boost::iterator_core_access; + reference dereference() const { return *_p; } + void increment() { + ++_coords.x; + ++_p.x(); + if (_coords.x>=_width) { + _coords.x=0; + ++_coords.y; + _p+=point_t(-_width,1); + } + } + void decrement() { + --_coords.x; + --_p.x(); + if (_coords.x<0) { + _coords.x=_width-1; + --_coords.y; + _p+=point_t(_width,-1); + } + } + + GIL_FORCEINLINE void advance(difference_type d) { + if (_width==0) return; // unfortunately we need to check for that. Default-constructed images have width of 0 and the code below will throw if executed. + point_t delta; + if (_coords.x+d>=0) { // not going back to a previous row? + delta.x=(_coords.x+(std::ptrdiff_t)d)%_width - _coords.x; + delta.y=(_coords.x+(std::ptrdiff_t)d)/_width; + } else { + delta.x=(_coords.x+(std::ptrdiff_t)d*(1-_width))%_width -_coords.x; + delta.y=-(_width-_coords.x-(std::ptrdiff_t)d-1)/_width; + } + _p+=delta; + _coords.x+=delta.x; + _coords.y+=delta.y; + } + + difference_type distance_to(const iterator_from_2d& it) const { + if (_width==0) return 0; + return (it.y_pos()-_coords.y)*_width + (it.x_pos()-_coords.x); + } + + bool equal(const iterator_from_2d& it) const { + assert(_width==it.width()); // they must belong to the same image + return _coords==it._coords && _p==it._p; + } + + point2 _coords; + std::ptrdiff_t _width; + Loc2 _p; +}; + +template // Models PixelLocatorConcept +struct const_iterator_type > { + typedef iterator_from_2d type; +}; + +template // Models PixelLocatorConcept +struct iterator_is_mutable > : public iterator_is_mutable {}; + + +///////////////////////////// +// HasDynamicXStepTypeConcept +///////////////////////////// + +template +struct dynamic_x_step_type > { + typedef iterator_from_2d::type> type; +}; + + +///////////////////////////// +// PixelBasedConcept +///////////////////////////// + +template // Models PixelLocatorConcept +struct color_space_type > : public color_space_type {}; + +template // Models PixelLocatorConcept +struct channel_mapping_type > : public channel_mapping_type {}; + +template // Models PixelLocatorConcept +struct is_planar > : public is_planar {}; + +template // Models PixelLocatorConcept +struct channel_type > : public channel_type {}; + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/locator.hpp b/win32/include/boost/gil/locator.hpp new file mode 100755 index 000000000..413235127 --- /dev/null +++ b/win32/include/boost/gil/locator.hpp @@ -0,0 +1,362 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_LOCATOR_H +#define GIL_LOCATOR_H + + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief pixel 2D locator +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n September 20, 2006 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "pixel_iterator.hpp" + +//////////////////////////////////////////////////////////////////////////////////////// +/// Pixel 2D LOCATOR +//////////////////////////////////////////////////////////////////////////////////////// + + +namespace boost { namespace gil { + +//forward declarations +template ptrdiff_t memunit_step(const P*); +template P* memunit_advanced(const P* p, ptrdiff_t diff); +template P& memunit_advanced_ref(P* p, ptrdiff_t diff); +template struct iterator_add_deref; +template class point2; +namespace detail { + // helper class specialized for each axis of pixel_2d_locator + template class locator_axis; +} +template struct dynamic_x_step_type; +template struct dynamic_y_step_type; + +template struct channel_type; +template struct color_space_type; +template struct channel_mapping_type; +template struct is_planar; +template struct num_channels; + +// The type of a locator or a view that has X and Y swapped. By default it is the same +template struct transposed_type { + typedef T type; +}; + +/// \class pixel_2d_locator_base +/// \brief base class for models of PixelLocatorConcept +/// \ingroup PixelLocatorModel PixelBasedModel +/// +/// Pixel locator is similar to a pixel iterator, but allows for 2D navigation of pixels within an image view. +/// It has a 2D difference_type and supports random access operations like: +/// \code +/// difference_type offset2(2,3); +/// locator+=offset2; +/// locator[offset2]=my_pixel; +/// \endcode +/// +/// In addition, each coordinate acts as a random-access iterator that can be modified separately: +/// "++locator.x()" or "locator.y()+=10" thereby moving the locator horizontally or vertically. +/// +/// It is called a locator because it doesn't implement the complete interface of a random access iterator. +/// For example, increment and decrement operations don't make sense (no way to specify dimension). +/// Also 2D difference between two locators cannot be computed without knowledge of the X position within the image. +/// +/// This base class provides most of the methods and typedefs needed to create a model of a locator. GIL provides two +/// locator models as subclasses of \p pixel_2d_locator_base. A memory-based locator, \p memory_based_2d_locator and a virtual +/// locator, \p virtual_2d_locator. +/// The minimum functionality a subclass must provide is this: +/// \code +/// class my_locator : public pixel_2d_locator_base { // supply the types for x-iterator and y-iterator +/// typedef ... const_t; // read-only locator +/// +/// template struct add_deref { +/// typedef ... type; // locator that invokes the Deref dereference object upon pixel access +/// static type make(const my_locator& loc, const Deref& d); +/// }; +/// +/// my_locator(); +/// my_locator(const my_locator& pl); +/// +/// // constructors with dynamic step in y (and x). Only valid for locators with dynamic steps +/// my_locator(const my_locator& loc, coord_t y_step); +/// my_locator(const my_locator& loc, coord_t x_step, coord_t y_step, bool transpose); +/// +/// bool operator==(const my_locator& p) const; +/// +/// // return _references_ to horizontal/vertical iterators. Advancing them moves this locator +/// x_iterator& x(); +/// y_iterator& y(); +/// x_iterator const& x() const; +/// y_iterator const& y() const; +/// +/// // return the vertical distance to another locator. Some models need the horizontal distance to compute it +/// y_coord_t y_distance_to(const my_locator& loc2, x_coord_t xDiff) const; +/// +/// // return true iff incrementing an x-iterator located at the last column will position it at the first +/// // column of the next row. Some models need the image width to determine that. +/// bool is_1d_traversable(x_coord_t width) const; +/// }; +/// \endcode +/// +/// Models may choose to override some of the functions in the base class with more efficient versions. +/// + +template // The concrete subclass, the X-iterator and the Y-iterator +class pixel_2d_locator_base { +public: + typedef XIterator x_iterator; + typedef YIterator y_iterator; + + // typedefs required by ConstRandomAccessNDLocatorConcept + static const std::size_t num_dimensions=2; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::reference reference; // result of dereferencing + typedef typename std::iterator_traits::difference_type coord_t; // 1D difference type (same for all dimensions) + typedef point2 difference_type; // result of operator-(locator,locator) + typedef difference_type point_t; + template struct axis { + typedef typename detail::locator_axis::coord_t coord_t; + typedef typename detail::locator_axis::iterator iterator; + }; + +// typedefs required by ConstRandomAccess2DLocatorConcept + typedef typename point_t::template axis<0>::coord_t x_coord_t; + typedef typename point_t::template axis<1>::coord_t y_coord_t; + + bool operator!=(const Loc& p) const { return !(concrete()==p); } + + x_iterator x_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp.x(); } + x_iterator x_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp.x(); } + y_iterator y_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp.y(); } + y_iterator y_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp.y(); } + Loc xy_at(x_coord_t dx, y_coord_t dy) const { Loc tmp=concrete(); tmp+=point_t(dx,dy); return tmp; } + Loc xy_at(const difference_type& d) const { Loc tmp=concrete(); tmp+=d; return tmp; } + + template typename axis::iterator& axis_iterator() { return detail::locator_axis()(concrete()); } + template typename axis::iterator const& axis_iterator() const { return detail::locator_axis()(concrete()); } + template typename axis::iterator axis_iterator(const point_t& p) const { return detail::locator_axis()(concrete(),p); } + + reference operator()(x_coord_t dx, y_coord_t dy) const { return *x_at(dx,dy); } + reference operator[](const difference_type& d) const { return *x_at(d.x,d.y); } + + reference operator*() const { return *concrete().x(); } + + Loc& operator+=(const difference_type& d) { concrete().x()+=d.x; concrete().y()+=d.y; return concrete(); } + Loc& operator-=(const difference_type& d) { concrete().x()-=d.x; concrete().y()-=d.y; return concrete(); } + + Loc operator+(const difference_type& d) const { return xy_at(d); } + Loc operator-(const difference_type& d) const { return xy_at(-d); } + + // Some locators can cache 2D coordinates for faster subsequent access. By default there is no caching + typedef difference_type cached_location_t; + cached_location_t cache_location(const difference_type& d) const { return d; } + cached_location_t cache_location(x_coord_t dx, y_coord_t dy)const { return difference_type(dx,dy); } + +private: + Loc& concrete() { return (Loc&)*this; } + const Loc& concrete() const { return (const Loc&)*this; } + + template friend class pixel_2d_locator; +}; + +// helper classes for each axis of pixel_2d_locator_base +namespace detail { + template + class locator_axis<0,Loc> { + typedef typename Loc::point_t point_t; + public: + typedef typename point_t::template axis<0>::coord_t coord_t; + typedef typename Loc::x_iterator iterator; + + inline iterator& operator()( Loc& loc) const { return loc.x(); } + inline iterator const& operator()(const Loc& loc) const { return loc.x(); } + inline iterator operator()( Loc& loc, const point_t& d) const { return loc.x_at(d); } + inline iterator operator()(const Loc& loc, const point_t& d) const { return loc.x_at(d); } + }; + + template + class locator_axis<1,Loc> { + typedef typename Loc::point_t point_t; + public: + typedef typename point_t::template axis<1>::coord_t coord_t; + typedef typename Loc::y_iterator iterator; + + inline iterator& operator()( Loc& loc) const { return loc.y(); } + inline iterator const& operator()(const Loc& loc) const { return loc.y(); } + inline iterator operator()( Loc& loc, const point_t& d) const { return loc.y_at(d); } + inline iterator operator()(const Loc& loc, const point_t& d) const { return loc.y_at(d); } + }; +} + +template +struct channel_type > : public channel_type {}; + +template +struct color_space_type > : public color_space_type {}; + +template +struct channel_mapping_type > : public channel_mapping_type {}; + +template +struct is_planar > : public is_planar {}; + +/// \class memory_based_2d_locator +/// \brief Memory-based pixel locator. Models: PixelLocatorConcept,HasDynamicXStepTypeConcept,HasDynamicYStepTypeConcept,HasTransposedTypeConcept +/// \ingroup PixelLocatorModel PixelBasedModel +/// +/// The class takes a step iterator as a parameter. The step iterator provides navigation along the vertical axis +/// while its base iterator provides horizontal navigation. +/// +/// Each instantiation is optimal in terms of size and efficiency. +/// For example, xy locator over interleaved rgb image results in a step iterator consisting of +/// one std::ptrdiff_t for the row size and one native pointer (8 bytes total). ++locator.x() resolves to pointer +/// increment. At the other extreme, a 2D navigation of the even pixels of a planar CMYK image results in a step +/// iterator consisting of one std::ptrdiff_t for the doubled row size, and one step iterator consisting of +/// one std::ptrdiff_t for the horizontal step of two and a CMYK planar_pixel_iterator consisting of 4 pointers (24 bytes). +/// In this case ++locator.x() results in four native pointer additions. +/// +/// Note also that \p memory_based_2d_locator does not require that its element type be a pixel. It could be +/// instantiated with an iterator whose \p value_type models only \p Regular. In this case the locator +/// models the weaker RandomAccess2DLocatorConcept, and does not model PixelBasedConcept. +/// Many generic algorithms don't require the elements to be pixels. +//////////////////////////////////////////////////////////////////////////////////////// + +template +class memory_based_2d_locator : public pixel_2d_locator_base, typename iterator_adaptor_get_base::type, StepIterator> { + typedef memory_based_2d_locator this_t; + GIL_CLASS_REQUIRE(StepIterator, boost::gil, StepIteratorConcept) +public: + typedef pixel_2d_locator_base, typename iterator_adaptor_get_base::type, StepIterator> parent_t; + typedef memory_based_2d_locator::type> const_t; // same as this type, but over const values + + typedef typename parent_t::coord_t coord_t; + typedef typename parent_t::x_coord_t x_coord_t; + typedef typename parent_t::y_coord_t y_coord_t; + typedef typename parent_t::x_iterator x_iterator; + typedef typename parent_t::y_iterator y_iterator; + typedef typename parent_t::difference_type difference_type; + typedef typename parent_t::reference reference; + + template struct add_deref { + typedef memory_based_2d_locator::type> type; + static type make(const memory_based_2d_locator& loc, const Deref& nderef) { + return type(iterator_add_deref::make(loc.y(),nderef)); + } + }; + + memory_based_2d_locator() {} + memory_based_2d_locator(const StepIterator& yit) : _p(yit) {} + template memory_based_2d_locator(const memory_based_2d_locator& loc, coord_t y_step) : _p(loc.x(), loc.row_size()*y_step) {} + template memory_based_2d_locator(const memory_based_2d_locator& loc, coord_t x_step, coord_t y_step, bool transpose=false) + : _p(make_step_iterator(loc.x(),(transpose ? loc.row_size() : loc.pixel_size())*x_step), + (transpose ? loc.pixel_size() : loc.row_size())*y_step ) {} + + memory_based_2d_locator(x_iterator xit, std::ptrdiff_t row_bytes) : _p(xit,row_bytes) {} + template memory_based_2d_locator(const memory_based_2d_locator& pl) : _p(pl._p) {} + memory_based_2d_locator(const memory_based_2d_locator& pl) : _p(pl._p) {} + + bool operator==(const this_t& p) const { return _p==p._p; } + + x_iterator const& x() const { return _p.base(); } + y_iterator const& y() const { return _p; } + x_iterator& x() { return _p.base(); } + y_iterator& y() { return _p; } + + // These are faster versions of functions already provided in the superclass + x_iterator x_at (x_coord_t dx, y_coord_t dy) const { return memunit_advanced(x(), offset(dx,dy)); } + x_iterator x_at (const difference_type& d) const { return memunit_advanced(x(), offset(d.x,d.y)); } + this_t xy_at (x_coord_t dx, y_coord_t dy) const { return this_t(x_at( dx , dy ), row_size()); } + this_t xy_at (const difference_type& d) const { return this_t(x_at( d.x, d.y), row_size()); } + reference operator()(x_coord_t dx, y_coord_t dy) const { return memunit_advanced_ref(x(),offset(dx,dy)); } + reference operator[](const difference_type& d) const { return memunit_advanced_ref(x(),offset(d.x,d.y)); } + this_t& operator+=(const difference_type& d) { memunit_advance(x(),offset(d.x,d.y)); return *this; } + this_t& operator-=(const difference_type& d) { memunit_advance(x(),offset(-d.x,-d.y)); return *this; } + + // Memory-based locators can have 1D caching of 2D relative coordinates + typedef std::ptrdiff_t cached_location_t; // type used to store relative location (to allow for more efficient repeated access) + cached_location_t cache_location(const difference_type& d) const { return offset(d.x,d.y); } + cached_location_t cache_location(x_coord_t dx, y_coord_t dy)const { return offset(dx,dy); } + reference operator[](const cached_location_t& loc) const { return memunit_advanced_ref(x(),loc); } + + // Only make sense for memory-based locators + std::ptrdiff_t row_size() const { return memunit_step(y()); } // distance in mem units (bytes or bits) between adjacent rows + std::ptrdiff_t pixel_size() const { return memunit_step(x()); } // distance in mem units (bytes or bits) between adjacent pixels on the same row + + bool is_1d_traversable(x_coord_t width) const { return row_size()-pixel_size()*width==0; } // is there no gap at the end of each row? + + // Returns the vertical distance (it2.y-it1.y) between two x_iterators given the difference of their x positions + std::ptrdiff_t y_distance_to(const this_t& p2, x_coord_t xDiff) const { + std::ptrdiff_t rowDiff=memunit_distance(x(),p2.x())-pixel_size()*xDiff; + assert(( rowDiff % row_size())==0); + return rowDiff / row_size(); + } + +private: + template friend class memory_based_2d_locator; + std::ptrdiff_t offset(x_coord_t x, y_coord_t y) const { return y*row_size() + x*pixel_size(); } + StepIterator _p; +}; + +///////////////////////////// +// PixelBasedConcept +///////////////////////////// + +template +struct color_space_type > : public color_space_type::parent_t> { +}; + +template +struct channel_mapping_type > : public channel_mapping_type::parent_t> { +}; + +template +struct is_planar > : public is_planar::parent_t> { +}; + +template +struct channel_type > : public channel_type::parent_t> { +}; + +///////////////////////////// +// HasDynamicXStepTypeConcept +///////////////////////////// + +// Take the base iterator of SI (which is typically a step iterator) and change it to have a step in x +template +struct dynamic_x_step_type > { +private: + typedef typename iterator_adaptor_get_base::type base_iterator_t; + typedef typename dynamic_x_step_type::type base_iterator_step_t; + typedef typename iterator_adaptor_rebind::type dynamic_step_base_t; +public: + typedef memory_based_2d_locator type; +}; + +///////////////////////////// +// HasDynamicYStepTypeConcept +///////////////////////////// + +template +struct dynamic_y_step_type > { + typedef memory_based_2d_locator type; +}; + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/metafunctions.hpp b/win32/include/boost/gil/metafunctions.hpp new file mode 100755 index 000000000..714b4ba34 --- /dev/null +++ b/win32/include/boost/gil/metafunctions.hpp @@ -0,0 +1,494 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_METAFUNCTIONS_HPP +#define GIL_METAFUNCTIONS_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief metafunctions that construct types or return type properties +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// +/// \date 2005-2007 \n Last updated on February 6, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gil_config.hpp" +#include "gil_concept.hpp" +#include "channel.hpp" + +namespace boost { namespace gil { + +// forward declarations +template struct pixel; +template struct packed_pixel; +template struct planar_pixel_reference; +template struct planar_pixel_iterator; +template class memory_based_step_iterator; +template class memory_based_2d_locator; +template class image_view; +template class image; +template struct channel_type; +template struct color_space_type; +template struct channel_mapping_type; +template struct is_iterator_adaptor; +template struct iterator_adaptor_get_base; +template struct bit_aligned_pixel_reference; + +////////////////////////////////////////////////// +/// +/// TYPE ANALYSIS METAFUNCTIONS +/// Predicate metafunctions determining properties of GIL types +/// +////////////////////////////////////////////////// + + +/// \defgroup GILIsBasic xxx_is_basic +/// \ingroup TypeAnalysis +/// \brief Determines if GIL constructs are basic. +/// Basic constructs are the ones that can be generated with the type +/// factory methods pixel_reference_type, iterator_type, locator_type, view_type and image_type +/// They can be mutable/immutable, planar/interleaved, step/nonstep. They must use GIL-provided models. + +/// \brief Determines if a given pixel reference is basic +/// Basic references must use gil::pixel& (if interleaved), gil::planar_pixel_reference (if planar). They must use the standard constness rules. +/// \ingroup GILIsBasic +template struct pixel_reference_is_basic : public mpl::false_ {}; +template struct pixel_reference_is_basic< pixel&> : public mpl::true_ {}; +template struct pixel_reference_is_basic&> : public mpl::true_ {}; +template struct pixel_reference_is_basic > : public mpl::true_ {}; +template struct pixel_reference_is_basic > : public mpl::true_ {}; + + +/// \brief Determines if a given pixel iterator is basic +/// Basic iterators must use gil::pixel (if interleaved), gil::planar_pixel_iterator (if planar) and gil::memory_based_step_iterator (if step). They must use the standard constness rules. +/// \ingroup GILIsBasic +template +struct iterator_is_basic : public mpl::false_ {}; +template // mutable interleaved +struct iterator_is_basic< pixel* > : public mpl::true_ {}; +template // immutable interleaved +struct iterator_is_basic* > : public mpl::true_ {}; +template // mutable planar +struct iterator_is_basic > : public mpl::true_ {}; +template // immutable planar +struct iterator_is_basic > : public mpl::true_ {}; +template // mutable interleaved step +struct iterator_is_basic*> > : public mpl::true_ {}; +template // immutable interleaved step +struct iterator_is_basic*> > : public mpl::true_ {}; +template // mutable planar step +struct iterator_is_basic > > : public mpl::true_ {}; +template // immutable planar step +struct iterator_is_basic > > : public mpl::true_ {}; + + +/// \ingroup GILIsBasic +/// \brief Determines if a given locator is basic. A basic locator is memory-based and has basic x_iterator and y_iterator +template struct locator_is_basic : public mpl::false_ {}; +template struct locator_is_basic > > : public iterator_is_basic {}; + +/// \ingroup GILIsBasic +/// \brief Basic views must be over basic locators +template struct view_is_basic : public mpl::false_ {}; +template struct view_is_basic > : public locator_is_basic {}; + +/// \ingroup GILIsBasic +/// \brief Basic images must use basic views and std::allocator of char +template struct image_is_basic : public mpl::false_ {}; +template struct image_is_basic > : public mpl::true_ {}; + + +/// \defgroup GILIsStep xxx_is_step +/// \ingroup TypeAnalysis +/// \brief Determines if the given iterator/locator/view has a step that could be set dynamically + +template struct iterator_is_step; +namespace detail { + template struct iterator_is_step_impl; + // iterator that has the same type as its dynamic_x_step_type must be a step iterator + template struct iterator_is_step_impl : public mpl::true_{}; + + // base iterator can never be a step iterator + template struct iterator_is_step_impl : public mpl::false_{}; + + // for an iterator adaptor, see if its base is step + template struct iterator_is_step_impl + : public iterator_is_step::type>{}; +} + +/// \ingroup GILIsStep +/// \brief Determines if the given iterator has a step that could be set dynamically +template struct iterator_is_step + : public detail::iterator_is_step_impl::type::value, + is_same::type>::value >{}; + +/// \ingroup GILIsStep +/// \brief Determines if the given locator has a horizontal step that could be set dynamically +template struct locator_is_step_in_x : public iterator_is_step {}; + +/// \ingroup GILIsStep +/// \brief Determines if the given locator has a vertical step that could be set dynamically +template struct locator_is_step_in_y : public iterator_is_step {}; + +/// \ingroup GILIsStep +/// \brief Determines if the given view has a horizontal step that could be set dynamically +template struct view_is_step_in_x : public locator_is_step_in_x {}; + +/// \ingroup GILIsStep +/// \brief Determines if the given view has a vertical step that could be set dynamically +template struct view_is_step_in_y : public locator_is_step_in_y {}; + +/// \brief Determines whether the given pixel reference is a proxy class or a native C++ reference +/// \ingroup TypeAnalysis +template +struct pixel_reference_is_proxy + : public mpl::not_::type, + typename remove_const_and_reference::type::value_type> > {}; + +/// \brief Given a model of a pixel, determines whether the model represents a pixel reference (as opposed to pixel value) +/// \ingroup TypeAnalysis +template +struct pixel_is_reference : public mpl::or_, pixel_reference_is_proxy > {}; + +/// \defgroup GILIsMutable xxx_is_mutable +/// \ingroup TypeAnalysis +/// \brief Determines if the given pixel reference/iterator/locator/view is mutable (i.e. its pixels can be changed) + +/// \ingroup GILIsMutable +/// \brief Determines if the given pixel reference is mutable (i.e. its channels can be changed) +/// +/// Note that built-in C++ references obey the const qualifier but reference proxy classes do not. +template struct pixel_reference_is_mutable : public mpl::bool_::type::is_mutable> {}; +template struct pixel_reference_is_mutable + : public mpl::and_, pixel_reference_is_mutable > {}; + +/// \ingroup GILIsMutable +/// \brief Determines if the given locator is mutable (i.e. its pixels can be changed) +template struct locator_is_mutable : public iterator_is_mutable {}; +/// \ingroup GILIsMutable +/// \brief Determines if the given view is mutable (i.e. its pixels can be changed) +template struct view_is_mutable : public iterator_is_mutable {}; + + +////////////////////////////////////////////////// +/// +/// TYPE FACTORY METAFUNCTIONS +/// Metafunctions returning GIL types from other GIL types +/// +////////////////////////////////////////////////// + +/// \defgroup TypeFactoryFromElements xxx_type +/// \ingroup TypeFactory +/// \brief Returns the type of a homogeneous GIL construct given its elements (channel, layout, whether it is planar, step, mutable, etc.) + +/// \defgroup TypeFactoryFromPixel xxx_type_from_pixel +/// \ingroup TypeFactory +/// \brief Returns the type of a GIL construct given its pixel type, whether it is planar, step, mutable, etc. + +/// \defgroup TypeFactoryDerived derived_xxx_type +/// \ingroup TypeFactory +/// \brief Returns the type of a homogeneous GIL construct given a related construct by changing some of its properties + +/// \ingroup TypeFactoryFromElements +/// \brief Returns the type of a homogeneous pixel reference given the channel type, layout, whether it operates on planar data and whether it is mutable +template struct pixel_reference_type{}; +template struct pixel_reference_type { typedef pixel& type; }; +template struct pixel_reference_type { typedef const pixel& type; }; +template struct pixel_reference_type { typedef const planar_pixel_reference::reference,typename color_space_type::type> type; }; // TODO: Assert M=identity +template struct pixel_reference_type { typedef const planar_pixel_reference::const_reference,typename color_space_type::type> type; };// TODO: Assert M=identity + +/// \ingroup TypeFactoryFromPixel +/// \brief Returns the type of a pixel iterator given the pixel type, whether it operates on planar data, whether it is a step iterator, and whether it is mutable +template struct iterator_type_from_pixel{}; +template struct iterator_type_from_pixel { typedef Pixel* type; }; +template struct iterator_type_from_pixel { typedef const Pixel* type; }; +template struct iterator_type_from_pixel { + typedef planar_pixel_iterator::type>::pointer,typename color_space_type::type> type; +}; +template struct iterator_type_from_pixel { + typedef planar_pixel_iterator::type>::const_pointer,typename color_space_type::type> type; +}; +template struct iterator_type_from_pixel { + typedef memory_based_step_iterator::type> type; +}; + +/// \ingroup TypeFactoryFromElements +/// \brief Returns the type of a homogeneous iterator given the channel type, layout, whether it operates on planar data, whether it is a step iterator, and whether it is mutable +template struct iterator_type{}; +template struct iterator_type { typedef pixel* type; }; +template struct iterator_type { typedef const pixel* type; }; +template struct iterator_type { typedef planar_pixel_iterator type; }; // TODO: Assert M=identity +template struct iterator_type { typedef planar_pixel_iterator type; }; // TODO: Assert M=identity +template struct iterator_type { + typedef memory_based_step_iterator::type> type; +}; + +/// \brief Given a pixel iterator defining access to pixels along a row, returns the types of the corresponding built-in step_iterator, xy_locator, image_view +/// \ingroup TypeFactory +template +struct type_from_x_iterator { + typedef memory_based_step_iterator step_iterator_t; + typedef memory_based_2d_locator xy_locator_t; + typedef image_view view_t; +}; + +namespace detail { + template + struct packed_channel_reference_type { + typedef const packed_channel_reference type; + }; + + template + class packed_channel_references_vector_type { + // If ChannelBitSizesVector is mpl::vector + // Then first_bits_vector will be mpl::vector + typedef typename mpl::accumulate >, + mpl::push_back, mpl::_2> > >::type first_bits_vector; + public: + typedef typename mpl::transform::type, ChannelBitSizesVector, + packed_channel_reference_type >::type type; + }; + +} + +/// \ingroup TypeFactoryFromElements +/// \brief Returns the type of a packed pixel given its bitfield type, the bit size of its channels and its layout. +/// +/// A packed pixel has channels that cover bit ranges but itself is byte aligned. RGB565 pixel is an example. +/// +/// The size of ChannelBitSizeVector must equal the number of channels in the given layout +/// The sum of bit sizes for all channels must be less than or equal to the number of bits in BitField (and cannot exceed 64). +/// If it is less than the number of bits in BitField, the last bits will be unused. +template +struct packed_pixel_type { + typedef packed_pixel::type, Layout> type; +}; + +/// \defgroup TypeFactoryPacked packed_image_type,bit_aligned_image_type +/// \ingroup TypeFactoryFromElements +/// \brief Returns the type of an image whose channels are not byte-aligned. +/// +/// A packed image is an image whose pixels are byte aligned, such as "rgb565".
            +/// A bit-aligned image is an image whose pixels are not byte aligned, such as "rgb222".
            +/// +/// The sum of the bit sizes of all channels cannot exceed 64. + +/// \ingroup TypeFactoryPacked +/// \brief Returns the type of an interleaved packed image: an image whose channels may not be byte-aligned, but whose pixels are byte aligned. +template > +struct packed_image_type { + typedef image::type,false,Alloc> type; +}; + +/// \ingroup TypeFactoryPacked +/// \brief Returns the type of a single-channel image given its bitfield type, the bit size of its channel and its layout +template > +struct packed_image1_type : public packed_image_type, Layout, Alloc> {}; + +/// \ingroup TypeFactoryPacked +/// \brief Returns the type of a two channel image given its bitfield type, the bit size of its channels and its layout +template > +struct packed_image2_type : public packed_image_type, Layout, Alloc> {}; + +/// \ingroup TypeFactoryPacked +/// \brief Returns the type of a three channel image given its bitfield type, the bit size of its channels and its layout +template > +struct packed_image3_type : public packed_image_type, Layout, Alloc> {}; + +/// \ingroup TypeFactoryPacked +/// \brief Returns the type of a four channel image given its bitfield type, the bit size of its channels and its layout +template > +struct packed_image4_type : public packed_image_type, Layout, Alloc> {}; + +/// \ingroup TypeFactoryPacked +/// \brief Returns the type of a five channel image given its bitfield type, the bit size of its channels and its layout +template > +struct packed_image5_type : public packed_image_type, Layout, Alloc> {}; + + +/// \ingroup TypeFactoryPacked +/// \brief Returns the type of a packed image whose pixels may not be byte aligned. For example, an "rgb222" image is bit-aligned because its pixel spans six bits. +/// +/// Note that the alignment parameter in the constructor of bit-aligned images is in bit units. For example, if you want to construct a bit-aligned +/// image whose rows are byte-aligned, use 8 as the alignment parameter, not 1. + +template > +struct bit_aligned_image_type { +private: + BOOST_STATIC_CONSTANT(int, bit_size = (mpl::accumulate, mpl::plus >::type::value)); + typedef typename detail::min_fast_uint::type bitfield_t; + typedef const bit_aligned_pixel_reference bit_alignedref_t; +public: + typedef image type; +}; + +/// \ingroup TypeFactoryPacked +/// \brief Returns the type of a single-channel bit-aligned image given the bit size of its channel and its layout +template > +struct bit_aligned_image1_type : public bit_aligned_image_type, Layout, Alloc> {}; + +/// \ingroup TypeFactoryPacked +/// \brief Returns the type of a two channel bit-aligned image given the bit size of its channels and its layout +template > +struct bit_aligned_image2_type : public bit_aligned_image_type, Layout, Alloc> {}; + +/// \ingroup TypeFactoryPacked +/// \brief Returns the type of a three channel bit-aligned image given the bit size of its channels and its layout +template > +struct bit_aligned_image3_type : public bit_aligned_image_type, Layout, Alloc> {}; + +/// \ingroup TypeFactoryPacked +/// \brief Returns the type of a four channel bit-aligned image given the bit size of its channels and its layout +template > +struct bit_aligned_image4_type : public bit_aligned_image_type, Layout, Alloc> {}; + +/// \ingroup TypeFactoryPacked +/// \brief Returns the type of a five channel bit-aligned image given the bit size of its channels and its layout +template > +struct bit_aligned_image5_type : public bit_aligned_image_type, Layout, Alloc> {}; + + + +/// \ingroup TypeFactoryFromElements +/// \brief Returns the type of a homogeneous pixel given the channel type and layout +template +struct pixel_value_type { + typedef pixel type; // by default use gil::pixel. Specializations are provided for +}; + +// Specializations for packed channels +template +struct pixel_value_type< packed_dynamic_channel_reference,Layout> : + public packed_pixel_type, Layout> {}; +template +struct pixel_value_type,Layout> : + public packed_pixel_type, Layout> {}; + +template +struct pixel_value_type< packed_channel_reference,Layout> : + public packed_pixel_type, Layout> {}; +template +struct pixel_value_type,Layout> : + public packed_pixel_type, Layout> {}; + +template +struct pixel_value_type,Layout> : + public packed_pixel_type::type, mpl::vector1_c, Layout> {}; + + +/// \ingroup TypeFactoryFromElements +/// \brief Returns the type of a homogeneous locator given the channel type, layout, whether it operates on planar data and whether it has a step horizontally +template +struct locator_type { + typedef typename type_from_x_iterator::type>::xy_locator_type type; +}; + +/// \ingroup TypeFactoryFromElements +/// \brief Returns the type of a homogeneous view given the channel type, layout, whether it operates on planar data and whether it has a step horizontally +template +struct view_type { + typedef typename type_from_x_iterator::type>::view_t type; +}; + +/// \ingroup TypeFactoryFromElements +/// \brief Returns the type of a homogeneous image given the channel type, layout, and whether it operates on planar data +template > +struct image_type { + typedef image, IsPlanar, Alloc> type; +}; + +/// \ingroup TypeFactoryFromPixel +/// \brief Returns the type of a view the pixel type, whether it operates on planar data and whether it has a step horizontally +template +struct view_type_from_pixel { + typedef typename type_from_x_iterator::type>::view_t type; +}; + + +/// \brief Constructs a pixel reference type from a source pixel reference type by changing some of the properties. +/// \ingroup TypeFactoryDerived +/// Use use_default for the properties of the source view that you want to keep +template +class derived_pixel_reference_type { + typedef typename remove_reference::type pixel_t; + typedef typename mpl::if_, typename channel_type::type, T >::type channel_t; + typedef typename mpl::if_, + layout::type, typename channel_mapping_type::type>, L>::type layout_t; + static const bool mut =mpl::if_, pixel_reference_is_mutable, IsMutable>::type::value; + static const bool planar=mpl::if_, is_planar, IsPlanar>::type::value; +public: + typedef typename pixel_reference_type::type type; +}; + +/// \brief Constructs a pixel iterator type from a source pixel iterator type by changing some of the properties. +/// \ingroup TypeFactoryDerived +/// Use use_default for the properties of the source view that you want to keep +template +class derived_iterator_type { + typedef typename mpl::if_, typename channel_type::type, T >::type channel_t; + typedef typename mpl::if_, + layout::type, typename channel_mapping_type::type>, L>::type layout_t; + + static const bool mut =mpl::if_, iterator_is_mutable, IsMutable>::type::value; + static const bool planar=mpl::if_, is_planar, IsPlanar>::type::value; + static const bool step =mpl::if_, iterator_is_step, IsStep>::type::value; +public: + typedef typename iterator_type::type type; +}; + +/// \brief Constructs an image view type from a source view type by changing some of the properties. +/// \ingroup TypeFactoryDerived +/// Use use_default for the properties of the source view that you want to keep +template +class derived_view_type { + typedef typename mpl::if_, typename channel_type::type, T>::type channel_t; + typedef typename mpl::if_, + layout::type, typename channel_mapping_type::type>, L>::type layout_t; + static const bool mut =mpl::if_, view_is_mutable, IsMutable>::type::value; + static const bool planar=mpl::if_, is_planar, IsPlanar>::type::value; + static const bool step =mpl::if_, view_is_step_in_x,StepX>::type::value; +public: + typedef typename view_type::type type; +}; + +/// \brief Constructs a homogeneous image type from a source image type by changing some of the properties. +/// \ingroup TypeFactoryDerived +/// Use use_default for the properties of the source image that you want to keep +template +class derived_image_type { + typedef typename mpl::if_, typename channel_type::type, T >::type channel_t; + typedef typename mpl::if_, + layout::type, typename channel_mapping_type::type>, L>::type layout_t; + static const bool planar=mpl::if_, is_planar, IsPlanar>::type::value; +public: + typedef typename image_type::type type; +}; + + + + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/packed_pixel.hpp b/win32/include/boost/gil/packed_pixel.hpp new file mode 100755 index 000000000..428b2fbb9 --- /dev/null +++ b/win32/include/boost/gil/packed_pixel.hpp @@ -0,0 +1,193 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_PACKED_PIXEL_H +#define GIL_PACKED_PIXEL_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief A model of a heterogeneous pixel whose channels are bit ranges. For example 16-bit RGB in '565' format +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on September 28, 2006 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "gil_config.hpp" +#include "pixel.hpp" + +namespace boost { namespace gil { + +/// \defgroup ColorBaseModelPackedPixel packed_pixel +/// \ingroup ColorBaseModel +/// \brief A heterogeneous color base whose elements are reference proxies to channels in a pixel. Models ColorBaseValueConcept. This class is used to model packed pixels, such as 16-bit packed RGB. + +/** +\defgroup PixelModelPackedPixel packed_pixel +\ingroup PixelModel +\brief A heterogeneous pixel used to represent packed pixels with non-byte-aligned channels. Models PixelValueConcept + +Example: +\code +typedef packed_pixel_type, rgb_layout_t>::type rgb565_pixel_t; +BOOST_STATIC_ASSERT((sizeof(rgb565_pixel_t)==2)); + +rgb565_pixel_t r565; +get_color(r565,red_t()) = 31; +get_color(r565,green_t()) = 63; +get_color(r565,blue_t()) = 31; +assert(r565 == rgb565_pixel_t((uint16_t)0xFFFF)); +\endcode +*/ + +/// \ingroup ColorBaseModelPackedPixel PixelModelPackedPixel PixelBasedModel +/// \brief Heterogeneous pixel value whose channel references can be constructed from the pixel bitfield and their index. Models ColorBaseValueConcept, PixelValueConcept, PixelBasedConcept +/// Typical use for this is a model of a packed pixel (like 565 RGB) +template // Layout defining the color space and ordering of the channels. Example value: rgb_layout_t +struct packed_pixel { + BitField _bitfield; + + typedef Layout layout_t; + typedef packed_pixel value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + + BOOST_STATIC_CONSTANT(bool, is_mutable = channel_traits::type>::is_mutable); + + packed_pixel(){} + explicit packed_pixel(const BitField& bitfield) : _bitfield(bitfield) {} + + // Construct from another compatible pixel type + packed_pixel(const packed_pixel& p) : _bitfield(p._bitfield) {} + template packed_pixel(const P& p, typename enable_if_c::value>::type* d=0) { check_compatible

            (); static_copy(p,*this); } + packed_pixel(int chan0, int chan1) : _bitfield(0) { + BOOST_STATIC_ASSERT((num_channels::value==2)); + at_c<0>(*this)=chan0; at_c<1>(*this)=chan1; + } + packed_pixel(int chan0, int chan1, int chan2) : _bitfield(0) { + BOOST_STATIC_ASSERT((num_channels::value==3)); + at_c<0>(*this)=chan0; at_c<1>(*this)=chan1; at_c<2>(*this)=chan2; + } + packed_pixel(int chan0, int chan1, int chan2, int chan3) : _bitfield(0) { + BOOST_STATIC_ASSERT((num_channels::value==4)); + at_c<0>(*this)=chan0; at_c<1>(*this)=chan1; at_c<2>(*this)=chan2; at_c<2>(*this)=chan3; + } + packed_pixel(int chan0, int chan1, int chan2, int chan3, int chan4) : _bitfield(0) { + BOOST_STATIC_ASSERT((num_channels::value==5)); + at_c<0>(*this)=chan0; at_c<1>(*this)=chan1; at_c<2>(*this)=chan2; at_c<2>(*this)=chan3; at_c<3>(*this)=chan4; + } + + packed_pixel& operator=(const packed_pixel& p) { _bitfield=p._bitfield; return *this; } + + template packed_pixel& operator=(const P& p) { assign(p, mpl::bool_::value>()); return *this; } + template bool operator==(const P& p) const { return equal(p, mpl::bool_::value>()); } + + template bool operator!=(const P& p) const { return !(*this==p); } + +private: + template static void check_compatible() { gil_function_requires >(); } + template void assign(const Pixel& p, mpl::true_) { check_compatible(); static_copy(p,*this); } + template bool equal(const Pixel& p, mpl::true_) const { check_compatible(); return static_equal(*this,p); } + +// Support for assignment/equality comparison of a channel with a grayscale pixel + static void check_gray() { BOOST_STATIC_ASSERT((is_same::value)); } + template void assign(const Channel& chan, mpl::false_) { check_gray(); at_c<0>(*this)=chan; } + template bool equal (const Channel& chan, mpl::false_) const { check_gray(); return at_c<0>(*this)==chan; } +public: + packed_pixel& operator= (int chan) { check_gray(); at_c<0>(*this)=chan; return *this; } + bool operator==(int chan) const { check_gray(); return at_c<0>(*this)==chan; } +}; + +///////////////////////////// +// ColorBasedConcept +///////////////////////////// + +template +struct kth_element_type,K> : public mpl::at_c {}; + +template +struct kth_element_reference_type,K> : public mpl::at_c {}; + +template +struct kth_element_const_reference_type,K> { + typedef typename channel_traits::type>::const_reference type; +}; + +template inline +typename kth_element_reference_type, K>::type +at_c(packed_pixel& p) { + return typename kth_element_reference_type, K>::type(&p._bitfield); +} + +template inline +typename kth_element_const_reference_type, K>::type +at_c(const packed_pixel& p) { + return typename kth_element_const_reference_type, K>::type(&p._bitfield); +} + +///////////////////////////// +// PixelConcept +///////////////////////////// + +// Metafunction predicate that flags packed_pixel as a model of PixelConcept. Required by PixelConcept +template +struct is_pixel > : public mpl::true_{}; + +///////////////////////////// +// PixelBasedConcept +///////////////////////////// + +template +struct color_space_type > { + typedef typename Layout::color_space_t type; +}; + +template +struct channel_mapping_type > { + typedef typename Layout::channel_mapping_t type; +}; + +template +struct is_planar > : mpl::false_ {}; + + +//////////////////////////////////////////////////////////////////////////////// +/// +/// Support for interleaved iterators over packed pixel +/// +//////////////////////////////////////////////////////////////////////////////// + +/// \defgroup PixelIteratorModelPackedInterleavedPtr Pointer to packed_pixel +/// \ingroup PixelIteratorModel +/// \brief Iterators over interleaved pixels. +/// The pointer packed_pixel* is used as an iterator over interleaved pixels of packed format. Models PixelIteratorConcept, HasDynamicXStepTypeConcept, MemoryBasedIteratorConcept + +template +struct iterator_is_mutable*> : public mpl::bool_::is_mutable> {}; +template +struct iterator_is_mutable*> : public mpl::false_ {}; + + + +} } // namespace boost::gil + +namespace boost { + template + struct has_trivial_constructor > : public has_trivial_constructor

            {}; +} +#endif diff --git a/win32/include/boost/gil/pixel.hpp b/win32/include/boost/gil/pixel.hpp new file mode 100755 index 000000000..ba2e04b13 --- /dev/null +++ b/win32/include/boost/gil/pixel.hpp @@ -0,0 +1,212 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ +/*************************************************************************************************/ + +#ifndef GIL_PIXEL_H +#define GIL_PIXEL_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief pixel class and related utilities +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on September 28, 2006 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "gil_config.hpp" +#include "color_base.hpp" +#include "gil_concept.hpp" +#include "channel.hpp" +#include "metafunctions.hpp" +#include "utilities.hpp" +#include "color_base_algorithm.hpp" + +namespace boost { namespace gil { + +// Forward-declare gray_t +struct gray_color_t; +typedef mpl::vector1 gray_t; +template struct color_space_type; +template struct channel_mapping_type; +template struct channel_type; +template struct is_planar; + +template struct color_space_type : public color_space_type {}; +template struct channel_mapping_type : public channel_mapping_type {}; +template struct channel_type : public channel_type {}; +template struct is_planar : public is_planar {}; + + +template struct is_pixel : public mpl::false_{}; +template struct is_pixel : public is_pixel {}; + +/// \ingroup PixelBasedAlgorithm +/// \brief Returns the number of channels of a pixel-based GIL construct +template +struct num_channels : public mpl::size::type> {}; + +/** +\addtogroup PixelBasedAlgorithm + +Example: +\code +BOOST_STATIC_ASSERT((num_channels::value==3)); +BOOST_STATIC_ASSERT((num_channels::value==4)); + +BOOST_STATIC_ASSERT((is_planar::value)); +BOOST_STATIC_ASSERT((is_same::type, rgb_t>::value)); +BOOST_STATIC_ASSERT((is_same::type, + channel_mapping_type::type>::value)); +BOOST_STATIC_ASSERT((is_same::type, bits8>::value)); +\endcode +*/ + +/// \defgroup ColorBaseModelPixel pixel +/// \ingroup ColorBaseModel +/// \brief A homogeneous color base whose element is a channel value. Models HomogeneousColorBaseValueConcept + +/// \defgroup PixelModelPixel pixel +/// \ingroup PixelModel +/// \brief A homogeneous pixel value. Models HomogeneousPixelValueConcept + +/// \ingroup PixelModelPixel ColorBaseModelPixel PixelBasedModel +/// \brief Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept, PixelValueConcept, HomogeneousPixelBasedConcept +/// +/// A pixel is a set of channels defining the color at a given point in an image. Conceptually, a pixel is little more than a color base whose elements +/// model \p ChannelConcept. The class \p pixel defines a simple, homogeneous pixel value. It is used to store +/// the value of a color. The built-in C++ references to \p pixel, \p pixel& and \p const \p pixel& are used to represent a reference to a pixel +/// inside an interleaved image view (a view in which all channels are together in memory). Similarly, built-in pointer types \p pixel* and \p const \p pixel* +/// are used as the standard iterator over a row of interleaved homogeneous pixels. +/// +/// Since \p pixel inherits the properties of color base, assigning, equality comparison and copy-construcion are allowed between compatible pixels. +/// This means that an 8-bit RGB pixel may be assigned to an 8-bit BGR pixel, or to an 8-bit planar reference. The channels are properly paired semantically. +/// +/// The single-channel (grayscale) instantiation of the class pixel, (i.e. \p pixel) is also convertible to/from a channel value. +/// This allows grayscale pixels to be used in simpler expressions like *gray_pix1 = *gray_pix2 instead of more complicated at_c<0>(gray_pix1) = at_c<0>(gray_pix2) +/// or get_color(gray_pix1) = get_color(gray_pix2) + +template // = mpl::range_c > +struct pixel : public detail::homogeneous_color_base::value> { +private: + typedef ChannelValue channel_t; + typedef detail::homogeneous_color_base::value> parent_t; +public: + typedef pixel value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + BOOST_STATIC_CONSTANT(bool, is_mutable = channel_traits::is_mutable); + + pixel(){} + explicit pixel(channel_t v) : parent_t(v) {} // sets all channels to v + pixel(channel_t v0, channel_t v1) : parent_t(v0,v1) {} + pixel(channel_t v0, channel_t v1, channel_t v2) : parent_t(v0,v1,v2) {} + pixel(channel_t v0, channel_t v1, channel_t v2, channel_t v3) : parent_t(v0,v1,v2,v3) {} + pixel(channel_t v0, channel_t v1, channel_t v2, channel_t v3, channel_t v4) : parent_t(v0,v1,v2,v3,v4) {} + pixel(channel_t v0, channel_t v1, channel_t v2, channel_t v3, channel_t v4, channel_t v5) : parent_t(v0,v1,v2,v3,v4,v5) {} + + pixel(const pixel& p) : parent_t(p) {} + pixel& operator=(const pixel& p) { static_copy(p,*this); return *this; } + + // Construct from another compatible pixel type + template pixel(const Pixel& p, typename enable_if_c::value>::type* dummy = 0) : parent_t(p) { + check_compatible(); + } + + template pixel& operator=(const P& p) { assign(p, mpl::bool_::value>()); return *this; } + template bool operator==(const P& p) const { return equal(p, mpl::bool_::value>()); } + + template bool operator!=(const P& p) const { return !(*this==p); } + + // homogeneous pixels have operator[] + typename channel_traits::reference operator[](std::size_t i) { return dynamic_at_c(*this,i); } + typename channel_traits::const_reference operator[](std::size_t i) const { return dynamic_at_c(*this,i); } +private: + template void assign(const Pixel& p, mpl::true_) { check_compatible(); static_copy(p,*this); } + template bool equal(const Pixel& p, mpl::true_) const { check_compatible(); return static_equal(*this,p); } + + template void check_compatible() const { gil_function_requires >(); } + +// Support for assignment/equality comparison of a channel with a grayscale pixel + +private: + static void check_gray() { BOOST_STATIC_ASSERT((is_same::value)); } + template void assign(const Channel& chan, mpl::false_) { check_gray(); at_c<0>(*this)=chan; } + template bool equal (const Channel& chan, mpl::false_) const { check_gray(); return at_c<0>(*this)==chan; } +public: + pixel& operator= (channel_t chan) { check_gray(); at_c<0>(*this)=chan; return *this; } + bool operator==(channel_t chan) const { check_gray(); return at_c<0>(*this)==chan; } +}; + +///////////////////////////// +// ColorBasedConcept +///////////////////////////// + +template +struct kth_element_type, K> { + typedef ChannelValue type; +}; + +template +struct kth_element_reference_type, K> { + typedef typename channel_traits::reference type; +}; + +template +struct kth_element_reference_type, K> { + typedef typename channel_traits::const_reference type; +}; + +template +struct kth_element_const_reference_type, K> { + typedef typename channel_traits::const_reference type; +}; + +///////////////////////////// +// PixelConcept +///////////////////////////// + +template +struct is_pixel > : public mpl::true_{}; + +///////////////////////////// +// HomogeneousPixelBasedConcept +///////////////////////////// + +template +struct color_space_type > { + typedef typename Layout::color_space_t type; +}; + +template +struct channel_mapping_type > { + typedef typename Layout::channel_mapping_t type; +}; + +template +struct is_planar > : public mpl::false_ {}; + +template +struct channel_type > { + typedef ChannelValue type; +}; + +} } // namespace boost::gil + +namespace boost { + template + struct has_trivial_constructor > : public has_trivial_constructor {}; +} +#endif diff --git a/win32/include/boost/gil/pixel_iterator.hpp b/win32/include/boost/gil/pixel_iterator.hpp new file mode 100755 index 000000000..b0d0dd0c1 --- /dev/null +++ b/win32/include/boost/gil/pixel_iterator.hpp @@ -0,0 +1,156 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_PIXEL_ITERATOR_H +#define GIL_PIXEL_ITERATOR_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief pixel iterator support +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n May 16, 2006 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "gil_config.hpp" +#include "gil_concept.hpp" +#include "utilities.hpp" +#include "pixel.hpp" + +namespace boost { namespace gil { + +//forwarded declaration (as this file is included in step_iterator.hpp) +template +class memory_based_step_iterator; + +template struct dynamic_x_step_type; + +/// \brief metafunction predicate determining whether the given iterator is a plain one or an adaptor over another iterator. +/// Examples of adaptors are the step iterator and the dereference iterator adaptor. +template +struct is_iterator_adaptor : public mpl::false_{}; + +/// \brief returns the base iterator for a given iterator adaptor. Provide an specialization when introducing new iterator adaptors +template +struct iterator_adaptor_get_base; + +/// \brief Changes the base iterator of an iterator adaptor. Provide an specialization when introducing new iterator adaptors +template +struct iterator_adaptor_rebind; + +/// \brief Returns the type of an iterator just like the input iterator, except operating over immutable values +template +struct const_iterator_type; + +// The default implementation when the iterator is a C pointer is to use the standard constness semantics +template struct const_iterator_type< T*> { typedef const T* type; }; +template struct const_iterator_type { typedef const T* type; }; + +/// \brief Metafunction predicate returning whether the given iterator allows for changing its values +/// \ingroup GILIsMutable +template +struct iterator_is_mutable{}; + +// The default implementation when the iterator is a C pointer is to use the standard constness semantics +template struct iterator_is_mutable< T*> : public mpl::true_{}; +template struct iterator_is_mutable : public mpl::false_{}; + +/// \defgroup PixelIteratorModelInterleavedPtr C pointer to a pixel +/// \ingroup PixelIteratorModel +/// \brief Iterators over interleaved pixels. +/// A C pointer to a model of PixelValueConcept is used as an iterator over interleaved pixels. Models PixelIteratorConcept, HomogeneousPixelBasedConcept, HasDynamicXStepTypeConcept, MemoryBasedIteratorConcept + + + +///////////////////////////// +// HasDynamicXStepTypeConcept +///////////////////////////// + +/// \ingroup PixelIteratorModelInterleavedPtr +template +struct dynamic_x_step_type { + typedef memory_based_step_iterator type; +}; + +/// \ingroup PixelIteratorModelInterleavedPtr +template +struct dynamic_x_step_type { + typedef memory_based_step_iterator type; +}; + + +///////////////////////////// +// PixelBasedConcept +///////////////////////////// + +template struct color_space_type< Pixel*> : public color_space_type {}; +template struct color_space_type : public color_space_type {}; + +template struct channel_mapping_type< Pixel*> : public channel_mapping_type {}; +template struct channel_mapping_type : public channel_mapping_type {}; + +template struct is_planar< Pixel*> : public is_planar {}; +template struct is_planar : public is_planar {}; + +///////////////////////////// +// HomogeneousPixelBasedConcept +///////////////////////////// + +template struct channel_type : public channel_type {}; +template struct channel_type : public channel_type {}; + +//////////////////////////////////////////////////////////////////////////////////////// +/// +/// Support for pixel iterator movement measured in memory units (bytes or bits) as opposed to pixel type. \n +/// Necessary to handle image row alignment and channel plane alignment. +/// +//////////////////////////////////////////////////////////////////////////////////////// + +///////////////////////////// +// MemoryBasedIteratorConcept +///////////////////////////// + +template +struct byte_to_memunit : public mpl::int_<1> {}; + +template +inline std::ptrdiff_t memunit_step(const P*) { return sizeof(P); } + +template +inline std::ptrdiff_t memunit_distance(const P* p1, const P* p2) { + return (gil_reinterpret_cast_c(p2)-gil_reinterpret_cast_c(p1)); +} + +template +inline void memunit_advance(P* &p, std::ptrdiff_t diff) { + p=(P*)((unsigned char*)(p)+diff); +} + +template +inline P* memunit_advanced(const P* p, std::ptrdiff_t diff) { + return (P*)((char*)(p)+diff); +} + +// memunit_advanced_ref +// (shortcut to advancing a pointer by a given number of memunits and taking the reference in case the compiler is not smart enough) + +template +inline P& memunit_advanced_ref(P* p, std::ptrdiff_t diff) { + return *memunit_advanced(p,diff); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/pixel_iterator_adaptor.hpp b/win32/include/boost/gil/pixel_iterator_adaptor.hpp new file mode 100755 index 000000000..b0d477af1 --- /dev/null +++ b/win32/include/boost/gil/pixel_iterator_adaptor.hpp @@ -0,0 +1,208 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_PIXEL_ITERATOR_ADAPTOR_H +#define GIL_PIXEL_ITERATOR_ADAPTOR_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief pixel step iterator, pixel image iterator and pixel dereference iterator +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on February 16, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "gil_config.hpp" +#include "gil_concept.hpp" +#include "pixel_iterator.hpp" + +namespace boost { namespace gil { + + +/// \defgroup PixelIteratorModelDerefPtr dereference_iterator_adaptor +/// \ingroup PixelIteratorModel +/// \brief An iterator that invokes a provided function object upon dereference. Models: IteratorAdaptorConcept, PixelIteratorConcept + + +/// \ingroup PixelIteratorModelDerefPtr PixelBasedModel +/// \brief An adaptor over an existing iterator that provides for custom filter on dereferencing the object. Models: IteratorAdaptorConcept, PixelIteratorConcept + +template // Models Returns the result of dereferencing a given iterator of type Iterator +class dereference_iterator_adaptor : public iterator_adaptor, + Iterator, + typename DFn::value_type, + use_default, + typename DFn::reference, + use_default> { + DFn _deref_fn; +public: + typedef iterator_adaptor, + Iterator, + typename DFn::value_type, + use_default, + typename DFn::reference, + use_default> parent_t; + typedef typename DFn::result_type reference; + typedef typename std::iterator_traits::difference_type difference_type; + typedef DFn dereference_fn; + + dereference_iterator_adaptor() {} + template + dereference_iterator_adaptor(const dereference_iterator_adaptor& dit) : parent_t(dit.base()), _deref_fn(dit._deref_fn) {} + dereference_iterator_adaptor(Iterator it, DFn deref_fn=DFn()) : parent_t(it), _deref_fn(deref_fn) {} + template + dereference_iterator_adaptor(const dereference_iterator_adaptor& it) : parent_t(it.base()), _deref_fn(it._deref_fn) {} + /// For some reason operator[] provided by iterator_facade returns a custom class that is convertible to reference + /// We require our own reference because it is registered in iterator_traits + reference operator[](difference_type d) const { return *(*this+d);} + + // although iterator_adaptor defines these, the default implementation computes distance and compares for zero. + // it is often faster to just apply the relation operator to the base + bool operator> (const dereference_iterator_adaptor& p) const { return this->base_reference()> p.base_reference(); } + bool operator< (const dereference_iterator_adaptor& p) const { return this->base_reference()< p.base_reference(); } + bool operator>=(const dereference_iterator_adaptor& p) const { return this->base_reference()>=p.base_reference(); } + bool operator<=(const dereference_iterator_adaptor& p) const { return this->base_reference()<=p.base_reference(); } + bool operator==(const dereference_iterator_adaptor& p) const { return this->base_reference()==p.base_reference(); } + bool operator!=(const dereference_iterator_adaptor& p) const { return this->base_reference()!=p.base_reference(); } + + Iterator& base() { return this->base_reference(); } + const Iterator& base() const { return this->base_reference(); } + const DFn& deref_fn() const { return _deref_fn; } +private: + template + friend class dereference_iterator_adaptor; + friend class boost::iterator_core_access; + + reference dereference() const { return _deref_fn(*(this->base_reference())); } +}; + +template +struct const_iterator_type > { + typedef dereference_iterator_adaptor::type,typename DFn::const_t> type; +}; + +template +struct iterator_is_mutable > : public mpl::bool_ {}; + + +template +struct is_iterator_adaptor > : public mpl::true_{}; + +template +struct iterator_adaptor_get_base > { + typedef I type; +}; + +template +struct iterator_adaptor_rebind,NewBaseIterator> { + typedef dereference_iterator_adaptor type; +}; + +///////////////////////////// +// PixelBasedConcept +///////////////////////////// + +template +struct color_space_type > : public color_space_type {}; + +template +struct channel_mapping_type > : public channel_mapping_type {}; + +template +struct is_planar > : public is_planar {}; + +template +struct channel_type > : public channel_type {}; + + +///////////////////////////// +// MemoryBasedIteratorConcept +///////////////////////////// + +template +struct byte_to_memunit > : public byte_to_memunit {}; + +template +inline typename std::iterator_traits::difference_type +memunit_step(const dereference_iterator_adaptor& p) { + return memunit_step(p.base()); +} + +template +inline typename std::iterator_traits::difference_type +memunit_distance(const dereference_iterator_adaptor& p1, + const dereference_iterator_adaptor& p2) { + return memunit_distance(p1.base(),p2.base()); +} + +template +inline void memunit_advance(dereference_iterator_adaptor& p, + typename std::iterator_traits::difference_type diff) { + memunit_advance(p.base(), diff); +} + +template +inline dereference_iterator_adaptor +memunit_advanced(const dereference_iterator_adaptor& p, + typename std::iterator_traits::difference_type diff) { + return dereference_iterator_adaptor(memunit_advanced(p.base(), diff), p.deref_fn()); +} + + +template +inline +typename std::iterator_traits >::reference +memunit_advanced_ref(const dereference_iterator_adaptor& p, + typename std::iterator_traits::difference_type diff) { + return *memunit_advanced(p, diff); +} + +///////////////////////////// +// HasDynamicXStepTypeConcept +///////////////////////////// + +template +struct dynamic_x_step_type > { + typedef dereference_iterator_adaptor::type,DFn> type; +}; + +/// \brief Returns the type (and creates an instance) of an iterator that invokes the given dereference adaptor upon dereferencing +/// \ingroup PixelIteratorModelDerefPtr +template +struct iterator_add_deref { + GIL_CLASS_REQUIRE(Deref, boost::gil, PixelDereferenceAdaptorConcept) + + typedef dereference_iterator_adaptor type; + + static type make(const Iterator& it, const Deref& d) { return type(it,d); } +}; + +/// \ingroup PixelIteratorModelDerefPtr +/// \brief For dereference iterator adaptors, compose the new function object after the old one +template +struct iterator_add_deref,Deref> { +// GIL_CLASS_REQUIRE(Deref, boost::gil, PixelDereferenceAdaptorConcept) + + typedef dereference_iterator_adaptor > type; + + static type make(const dereference_iterator_adaptor& it, const Deref& d) { + return type(it.base(),deref_compose(d,it.deref_fn())); + } +}; + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/planar_pixel_iterator.hpp b/win32/include/boost/gil/planar_pixel_iterator.hpp new file mode 100755 index 000000000..34acab17b --- /dev/null +++ b/win32/include/boost/gil/planar_pixel_iterator.hpp @@ -0,0 +1,227 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_PLANAR_PTR_H +#define GIL_PLANAR_PTR_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief planar pixel pointer class +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on February 12, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "gil_config.hpp" +#include "pixel.hpp" +#include "step_iterator.hpp" + +namespace boost { namespace gil { + +//forward declaration (as this file is included in planar_pixel_reference.hpp) +template +struct planar_pixel_reference; + +/// \defgroup ColorBaseModelPlanarPtr planar_pixel_iterator +/// \ingroup ColorBaseModel +/// \brief A homogeneous color base whose element is a channel iterator. Models HomogeneousColorBaseValueConcept +/// This class is used as an iterator to a planar pixel. + +/// \defgroup PixelIteratorModelPlanarPtr planar_pixel_iterator +/// \ingroup PixelIteratorModel +/// \brief An iterator over planar pixels. Models PixelIteratorConcept, HomogeneousPixelBasedConcept, MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept + +//////////////////////////////////////////////////////////////////////////////////////// +/// \brief An iterator over planar pixels. Models HomogeneousColorBaseConcept, PixelIteratorConcept, HomogeneousPixelBasedConcept, MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept +/// +/// Planar pixels have channel data that is not consecutive in memory. +/// To abstract this we use classes to represent references and pointers to planar pixels. +/// +/// \ingroup PixelIteratorModelPlanarPtr ColorBaseModelPlanarPtr PixelBasedModel +template +struct planar_pixel_iterator : public iterator_facade, + pixel::value_type,layout >, + random_access_traversal_tag, + const planar_pixel_reference::reference,ColorSpace> >, + public detail::homogeneous_color_base,mpl::size::value > { +private: + typedef iterator_facade, + pixel::value_type,layout >, + random_access_traversal_tag, + const planar_pixel_reference::reference,ColorSpace> > parent_t; + typedef detail::homogeneous_color_base,mpl::size::value> color_base_parent_t; + typedef typename std::iterator_traits::value_type channel_t; +public: + typedef typename parent_t::value_type value_type; + typedef typename parent_t::reference reference; + typedef typename parent_t::difference_type difference_type; + + planar_pixel_iterator() : color_base_parent_t(0) {} + planar_pixel_iterator(bool) {} // constructor that does not fill with zero (for performance) + + planar_pixel_iterator(const ChannelPtr& v0, const ChannelPtr& v1) : color_base_parent_t(v0,v1) {} + planar_pixel_iterator(const ChannelPtr& v0, const ChannelPtr& v1, const ChannelPtr& v2) : color_base_parent_t(v0,v1,v2) {} + planar_pixel_iterator(const ChannelPtr& v0, const ChannelPtr& v1, const ChannelPtr& v2, const ChannelPtr& v3) : color_base_parent_t(v0,v1,v2,v3) {} + planar_pixel_iterator(const ChannelPtr& v0, const ChannelPtr& v1, const ChannelPtr& v2, const ChannelPtr& v3, const ChannelPtr& v4) : color_base_parent_t(v0,v1,v2,v3,v4) {} + + template + planar_pixel_iterator(const planar_pixel_iterator& ptr) : color_base_parent_t(ptr) {} + + + /// Copy constructor and operator= from pointers to compatible planar pixels or planar pixel references. + /// That allow constructs like pointer = &value or pointer = &reference + /// Since we should not override operator& that's the best we can do. + template + planar_pixel_iterator(P* pix) : color_base_parent_t(pix, true) { + function_requires >(); + } + + struct address_of { template T* operator()(T& t) { return &t; } }; + template + planar_pixel_iterator& operator=(P* pix) { + function_requires >(); + static_transform(*pix,*this, address_of()); + + // PERFORMANCE_CHECK: Compare to this: + //this->template semantic_at_c<0>()=&pix->template semantic_at_c<0>(); + //this->template semantic_at_c<1>()=&pix->template semantic_at_c<1>(); + //this->template semantic_at_c<2>()=&pix->template semantic_at_c<2>(); + return *this; + } + + /// For some reason operator[] provided by iterator_facade returns a custom class that is convertible to reference + /// We require our own reference because it is registered in iterator_traits + reference operator[](difference_type d) const { return memunit_advanced_ref(*this,d*sizeof(channel_t));} + + reference operator->() const { return **this; } + + // PERFORMANCE_CHECK: Remove? + bool operator< (const planar_pixel_iterator& ptr) const { return at_c<0>(*this)< at_c<0>(ptr); } + bool operator!=(const planar_pixel_iterator& ptr) const { return at_c<0>(*this)!=at_c<0>(ptr); } +private: + friend class boost::iterator_core_access; + + void increment() { static_transform(*this,*this,detail::inc()); } + void decrement() { static_transform(*this,*this,detail::dec()); } + void advance(ptrdiff_t d) { static_transform(*this,*this,std::bind2nd(detail::plus_asymmetric(),d)); } + reference dereference() const { return this->template deref(); } + + ptrdiff_t distance_to(const planar_pixel_iterator& it) const { return at_c<0>(it)-at_c<0>(*this); } + bool equal(const planar_pixel_iterator& it) const { return at_c<0>(*this)==at_c<0>(it); } +}; + +namespace detail { + template struct channel_iterator_is_mutable : public mpl::true_ {}; + template struct channel_iterator_is_mutable : public mpl::false_ {}; +} + +template +struct const_iterator_type > { +private: + typedef typename std::iterator_traits::value_type channel_t; +public: + typedef planar_pixel_iterator::const_pointer,C> type; +}; + +// The default implementation when the iterator is a C pointer is to use the standard constness semantics +template +struct iterator_is_mutable > : public detail::channel_iterator_is_mutable {}; + +///////////////////////////// +// ColorBasedConcept +///////////////////////////// + +template +struct kth_element_type, K> { + typedef IC type; +}; + +template +struct kth_element_reference_type, K> : public add_reference {}; + +template +struct kth_element_const_reference_type, K> : public add_reference::type> {}; + +///////////////////////////// +// HomogeneousPixelBasedConcept +///////////////////////////// + +template +struct color_space_type > { + typedef C type; +}; + +template +struct channel_mapping_type > : public channel_mapping_type::value_type> {}; + +template +struct is_planar > : public mpl::true_ {}; + +template +struct channel_type > { + typedef typename std::iterator_traits::value_type type; +}; + +///////////////////////////// +// MemoryBasedIteratorConcept +///////////////////////////// + +template +inline std::ptrdiff_t memunit_step(const planar_pixel_iterator&) { return sizeof(typename std::iterator_traits::value_type); } + +template +inline std::ptrdiff_t memunit_distance(const planar_pixel_iterator& p1, const planar_pixel_iterator& p2) { + return memunit_distance(at_c<0>(p1),at_c<0>(p2)); +} + +template +struct memunit_advance_fn { + memunit_advance_fn(std::ptrdiff_t diff) : _diff(diff) {} + IC operator()(const IC& p) const { return memunit_advanced(p,_diff); } + + std::ptrdiff_t _diff; +}; + +template +inline void memunit_advance(planar_pixel_iterator& p, std::ptrdiff_t diff) { + static_transform(p, p, memunit_advance_fn(diff)); +} + +template +inline planar_pixel_iterator memunit_advanced(const planar_pixel_iterator& p, std::ptrdiff_t diff) { + planar_pixel_iterator ret=p; + memunit_advance(ret, diff); + return ret; +} + +template +inline planar_pixel_reference::reference,ColorSpace> + memunit_advanced_ref(const planar_pixel_iterator& ptr, std::ptrdiff_t diff) { + return planar_pixel_reference::reference,ColorSpace>(ptr, diff); +} + +///////////////////////////// +// HasDynamicXStepTypeConcept +///////////////////////////// + +template +struct dynamic_x_step_type > { + typedef memory_based_step_iterator > type; +}; + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/planar_pixel_reference.hpp b/win32/include/boost/gil/planar_pixel_reference.hpp new file mode 100755 index 000000000..76845361f --- /dev/null +++ b/win32/include/boost/gil/planar_pixel_reference.hpp @@ -0,0 +1,186 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://stlab.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_PLANAR_REF_H +#define GIL_PLANAR_REF_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief planar pixel reference class +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on September 28, 2006 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include "gil_config.hpp" +#include "gil_concept.hpp" +#include "color_base.hpp" +#include "channel.hpp" +#include "pixel.hpp" +#include "planar_pixel_iterator.hpp" + +namespace boost { namespace gil { + +/// \defgroup ColorBaseModelPlanarRef planar_pixel_reference +/// \ingroup ColorBaseModel +/// \brief A homogeneous color base whose element is a channel reference. Models HomogeneousColorBaseConcept, HomogeneousPixelConcept. +/// This class is used as a reference proxy to a planar pixel. + +/// \defgroup PixelModelPlanarRef planar_pixel_reference +/// \ingroup PixelModel +/// \brief A reference proxy to a planar pixel. Models HomogeneousColorBaseConcept, HomogeneousPixelConcept. + + +/// \ingroup PixelModelPlanarRef ColorBaseModelPlanarRef PixelBasedModel +/// \brief A reference proxy to a planar pixel. Models: HomogeneousColorBaseConcept, HomogeneousPixelConcept +/// +/// A reference to a planar pixel is a proxy class containing references to each of the corresponding channels. +/// +template // ChannelReference is a channel reference (const or mutable) +struct planar_pixel_reference + : public detail::homogeneous_color_base,mpl::size::value> { + typedef detail::homogeneous_color_base,mpl::size::value> parent_t; +private: + // These three are only defined for homogeneous pixels + typedef typename channel_traits::value_type channel_t; + typedef typename channel_traits::const_reference channel_const_reference; +public: + BOOST_STATIC_CONSTANT(bool, is_mutable = channel_traits::is_mutable); + typedef pixel > value_type; + typedef planar_pixel_reference reference; + typedef planar_pixel_reference const_reference; + + planar_pixel_reference(ChannelReference v0, ChannelReference v1) : parent_t(v0,v1) {} + planar_pixel_reference(ChannelReference v0, ChannelReference v1, ChannelReference v2) : parent_t(v0,v1,v2) {} + planar_pixel_reference(ChannelReference v0, ChannelReference v1, ChannelReference v2, ChannelReference v3) : parent_t(v0,v1,v2,v3) {} + planar_pixel_reference(ChannelReference v0, ChannelReference v1, ChannelReference v2, ChannelReference v3, ChannelReference v4) : parent_t(v0,v1,v2,v3,v4) {} + planar_pixel_reference(ChannelReference v0, ChannelReference v1, ChannelReference v2, ChannelReference v3, ChannelReference v4, ChannelReference v5) : parent_t(v0,v1,v2,v3,v4,v5) {} + + template planar_pixel_reference(const P& p) : parent_t(p) { check_compatible

            ();} + + // PERFORMANCE_CHECK: Is this constructor necessary? + template + planar_pixel_reference(pixel >& p) : parent_t(p) { check_compatible > >();} + + // Construct at offset from a given location + template planar_pixel_reference(const planar_pixel_iterator& p, std::ptrdiff_t diff) : parent_t(p,diff) {} + + const planar_pixel_reference& operator=(const planar_pixel_reference& p) const { static_copy(p,*this); return *this; } + template const planar_pixel_reference& operator=(const P& p) const { check_compatible

            (); static_copy(p,*this); return *this; } + + template bool operator==(const P& p) const { check_compatible

            (); return static_equal(*this,p); } + template bool operator!=(const P& p) const { return !(*this==p); } + + ChannelReference operator[](std::size_t i) const { return this->at_c_dynamic(i); } + + const planar_pixel_reference* operator->() const { return this; } +private: + template static void check_compatible() { gil_function_requires >(); } +}; + +///////////////////////////// +// ColorBasedConcept +///////////////////////////// + +template +struct kth_element_type, K> { + typedef ChannelReference type; +}; + +template +struct kth_element_reference_type, K> { + typedef ChannelReference type; +}; + +template +struct kth_element_const_reference_type, K> + : public add_reference::type> +{ +// typedef typename channel_traits::const_reference type; +}; + +///////////////////////////// +// PixelConcept +///////////////////////////// + +/// \brief Metafunction predicate that flags planar_pixel_reference as a model of PixelConcept. Required by PixelConcept +/// \ingroup PixelModelPlanarRef +template +struct is_pixel< planar_pixel_reference > : public mpl::true_{}; + +///////////////////////////// +// HomogeneousPixelBasedConcept +///////////////////////////// + +/// \brief Specifies the color space type of a planar pixel reference. Required by PixelBasedConcept +/// \ingroup PixelModelPlanarRef +template +struct color_space_type > { + typedef ColorSpace type; +}; + +/// \brief Specifies the color space type of a planar pixel reference. Required by PixelBasedConcept +/// \ingroup PixelModelPlanarRef +template +struct channel_mapping_type > { + typedef typename layout::channel_mapping_t type; +}; + +/// \brief Specifies that planar_pixel_reference represents a planar construct. Required by PixelBasedConcept +/// \ingroup PixelModelPlanarRef +template +struct is_planar > : mpl::true_ {}; + +/// \brief Specifies the color space type of a planar pixel reference. Required by HomogeneousPixelBasedConcept +/// \ingroup PixelModelPlanarRef +template +struct channel_type > { + typedef typename channel_traits::value_type type; +}; + +} } // namespace boost::gil + +namespace std { +// We are forced to define swap inside std namespace because on some platforms (Visual Studio 8) STL calls swap qualified. +// swap with 'left bias': +// - swap between proxy and anything +// - swap between value type and proxy +// - swap between proxy and proxy +// Having three overloads allows us to swap between different (but compatible) models of PixelConcept + +/// \brief swap for planar_pixel_reference +/// \ingroup PixelModelPlanarRef +template inline +void swap(const boost::gil::planar_pixel_reference x, R& y) { + boost::gil::swap_proxy::value_type>(x,y); +} + + +/// \brief swap for planar_pixel_reference +/// \ingroup PixelModelPlanarRef +template inline +void swap(typename boost::gil::planar_pixel_reference::value_type& x, const boost::gil::planar_pixel_reference y) { + boost::gil::swap_proxy::value_type>(x,y); +} + + +/// \brief swap for planar_pixel_reference +/// \ingroup PixelModelPlanarRef +template inline +void swap(const boost::gil::planar_pixel_reference x, const boost::gil::planar_pixel_reference y) { + boost::gil::swap_proxy::value_type>(x,y); +} +} // namespace std + +#endif diff --git a/win32/include/boost/gil/position_iterator.hpp b/win32/include/boost/gil/position_iterator.hpp new file mode 100755 index 000000000..f2c780b61 --- /dev/null +++ b/win32/include/boost/gil/position_iterator.hpp @@ -0,0 +1,121 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_POSITION_ITERATOR_HPP +#define GIL_POSITION_ITERATOR_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Locator for virtual image views +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on February 12, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include "locator.hpp" + +namespace boost { namespace gil { + +/// \defgroup PixelIteratorModelVirtual position_iterator +/// \ingroup PixelIteratorModel +/// \brief An iterator that remembers its current X,Y position and invokes a function object with it upon dereferencing. Models PixelIteratorConcept, PixelBasedConcept, HasDynamicXStepTypeConcept. Used to create virtual image views. + + +/// \brief An iterator that remembers its current X,Y position and invokes a function object with it upon dereferencing. Models PixelIteratorConcept. Used to create virtual image views. +/// Models: StepIteratorConcept, PixelIteratorConcept, PixelBasedConcept, HasDynamicXStepTypeConcept +/// \ingroup PixelIteratorModelVirtual PixelBasedModel +template // the dimension to advance along +struct position_iterator : public iterator_facade, + typename Deref::value_type, + random_access_traversal_tag, + typename Deref::reference, + typename Deref::argument_type::template axis::coord_t> { + typedef iterator_facade, + typename Deref::value_type, + random_access_traversal_tag, + typename Deref::reference, + typename Deref::argument_type::template axis::coord_t> parent_t; + typedef typename parent_t::difference_type difference_type; + typedef typename parent_t::reference reference; + typedef typename Deref::argument_type point_t; + + position_iterator() {} + position_iterator(const point_t& p, const point_t& step, const Deref& d) : _p(p), _step(step), _d(d) {} + + position_iterator(const position_iterator& p) : _p(p._p), _step(p._step), _d(p._d) {} + template position_iterator(const position_iterator& p) : _p(p._p), _step(p._step), _d(p._d) {} + position_iterator& operator=(const position_iterator& p) { _p=p._p; _d=p._d; _step=p._step; return *this; } + + const point_t& pos() const { return _p; } + const point_t& step() const { return _step; } + const Deref& deref_fn() const { return _d; } + + void set_step(difference_type s) { _step[Dim]=s; } + /// For some reason operator[] provided by iterator_adaptor returns a custom class that is convertible to reference + /// We require our own reference because it is registered in iterator_traits + reference operator[](difference_type d) const { point_t p=_p; p[Dim]+=d*_step[Dim]; return _d(p); } + +private: + point_t _p, _step; + Deref _d; + + template friend struct position_iterator; + friend class boost::iterator_core_access; + reference dereference() const { return _d(_p); } + void increment() { _p[Dim]+=_step[Dim]; } + void decrement() { _p[Dim]-=_step[Dim]; } + void advance(difference_type d) { _p[Dim]+=d*_step[Dim]; } + + difference_type distance_to(const position_iterator& it) const { return (it._p[Dim]-_p[Dim])/_step[Dim]; } + bool equal(const position_iterator& it) const { return _p==it._p; } +}; + +template +struct const_iterator_type > { + typedef position_iterator type; +}; + +template +struct iterator_is_mutable > : public mpl::bool_ { +}; + +///////////////////////////// +// PixelBasedConcept +///////////////////////////// + +template +struct color_space_type > : public color_space_type {}; + +template +struct channel_mapping_type > : public channel_mapping_type {}; + +template +struct is_planar > : public mpl::false_ {}; + +template +struct channel_type > : public channel_type {}; + +///////////////////////////// +// HasDynamicXStepTypeConcept +///////////////////////////// + +template +struct dynamic_x_step_type > { + typedef position_iterator type; +}; + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/rgb.hpp b/win32/include/boost/gil/rgb.hpp new file mode 100755 index 000000000..843e1ce22 --- /dev/null +++ b/win32/include/boost/gil/rgb.hpp @@ -0,0 +1,70 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_RGB_H +#define GIL_RGB_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Support for RGB color space and variants +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on October 10, 2007 +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "gil_config.hpp" +#include "metafunctions.hpp" +#include "planar_pixel_iterator.hpp" + +namespace boost { namespace gil { + +/// \addtogroup ColorNameModel +/// \{ + +/// \brief Red +struct red_t {}; + +/// \brief Green +struct green_t {}; + +/// \brief Blue +struct blue_t {}; +/// \} + +/// \ingroup ColorSpaceModel +typedef mpl::vector3 rgb_t; + +/// \ingroup LayoutModel +typedef layout rgb_layout_t; +/// \ingroup LayoutModel +typedef layout > bgr_layout_t; + +/// \ingroup ImageViewConstructors +/// \brief from raw RGB planar data +template +inline +typename type_from_x_iterator >::view_t +planar_rgb_view(std::size_t width, std::size_t height, + IC r, IC g, IC b, + std::ptrdiff_t rowsize_in_bytes) { + typedef typename type_from_x_iterator >::view_t RView; + return RView(width, height, + typename RView::locator(planar_pixel_iterator(r,g,b), + rowsize_in_bytes)); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/rgba.hpp b/win32/include/boost/gil/rgba.hpp new file mode 100755 index 000000000..b2a832d6d --- /dev/null +++ b/win32/include/boost/gil/rgba.hpp @@ -0,0 +1,63 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ +/*************************************************************************************************/ + +#ifndef GIL_RGBA_H +#define GIL_RGBA_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Support for RGBA color space and variants +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on October 10, 2007 +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include "gil_config.hpp" +#include +#include "rgb.hpp" +#include "planar_pixel_iterator.hpp" + +namespace boost { namespace gil { + +/// \ingroup ColorNameModel +/// \brief Alpha +struct alpha_t {}; + +/// \ingroup ColorSpaceModel +typedef mpl::vector4 rgba_t; + +/// \ingroup LayoutModel +typedef layout rgba_layout_t; +/// \ingroup LayoutModel +typedef layout > bgra_layout_t; +/// \ingroup LayoutModel +typedef layout > argb_layout_t; +/// \ingroup LayoutModel +typedef layout > abgr_layout_t; + +/// \ingroup ImageViewConstructors +/// \brief from raw RGBA planar data +template +inline +typename type_from_x_iterator >::view_t +planar_rgba_view(std::size_t width, std::size_t height, + IC r, IC g, IC b, IC a, + std::ptrdiff_t rowsize_in_bytes) { + typedef typename type_from_x_iterator >::view_t RView; + return RView(width, height, + typename RView::locator(planar_pixel_iterator(r,g,b,a), + rowsize_in_bytes)); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/step_iterator.hpp b/win32/include/boost/gil/step_iterator.hpp new file mode 100755 index 000000000..a84812d97 --- /dev/null +++ b/win32/include/boost/gil/step_iterator.hpp @@ -0,0 +1,320 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_STEP_ITERATOR_H +#define GIL_STEP_ITERATOR_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief pixel step iterator +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on September 18, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include "gil_config.hpp" +#include "utilities.hpp" +#include "pixel_iterator.hpp" +#include "pixel_iterator_adaptor.hpp" + +namespace boost { namespace gil { + +/// \defgroup PixelIteratorModelStepPtr step iterators +/// \ingroup PixelIteratorModel +/// \brief Iterators that allow for specifying the step between two adjacent values + + +namespace detail { + +/// \ingroup PixelIteratorModelStepPtr +/// \brief An adaptor over an existing iterator that changes the step unit +/// +/// (i.e. distance(it,it+1)) by a given predicate. Instead of calling base's +/// operators ++, --, +=, -=, etc. the adaptor is using the passed policy object SFn +/// for advancing and for computing the distance between iterators. + +template // A policy object that can compute the distance between two iterators of type Iterator + // and can advance an iterator of type Iterator a given number of Iterator's units +class step_iterator_adaptor : public iterator_adaptor { +public: + typedef iterator_adaptor parent_t; + typedef typename std::iterator_traits::difference_type base_difference_type; + typedef typename SFn::difference_type difference_type; + typedef typename std::iterator_traits::reference reference; + + step_iterator_adaptor() {} + step_iterator_adaptor(const Iterator& it, SFn step_fn=SFn()) : parent_t(it), _step_fn(step_fn) {} + + difference_type step() const { return _step_fn.step(); } + +protected: + SFn _step_fn; +private: + friend class boost::iterator_core_access; + + void increment() { _step_fn.advance(this->base_reference(),1); } + void decrement() { _step_fn.advance(this->base_reference(),-1); } + void advance(base_difference_type d) { _step_fn.advance(this->base_reference(),d); } + difference_type distance_to(const step_iterator_adaptor& it) const { return _step_fn.difference(this->base_reference(),it.base_reference()); } +}; + +// although iterator_adaptor defines these, the default implementation computes distance and compares for zero. +// it is often faster to just apply the relation operator to the base +template inline +bool operator>(const step_iterator_adaptor& p1, const step_iterator_adaptor& p2) { + return p1.step()>0 ? p1.base()> p2.base() : p1.base()< p2.base(); +} + +template inline +bool operator<(const step_iterator_adaptor& p1, const step_iterator_adaptor& p2) { + return p1.step()>0 ? p1.base()< p2.base() : p1.base()> p2.base(); +} + +template inline +bool operator>=(const step_iterator_adaptor& p1, const step_iterator_adaptor& p2) { + return p1.step()>0 ? p1.base()>=p2.base() : p1.base()<=p2.base(); +} + +template inline +bool operator<=(const step_iterator_adaptor& p1, const step_iterator_adaptor& p2) { + return p1.step()>0 ? p1.base()<=p2.base() : p1.base()>=p2.base(); +} + +template inline +bool operator==(const step_iterator_adaptor& p1, const step_iterator_adaptor& p2) { + return p1.base()==p2.base(); +} + +template inline +bool operator!=(const step_iterator_adaptor& p1, const step_iterator_adaptor& p2) { + return p1.base()!=p2.base(); +} + +} // namespace detail + +//////////////////////////////////////////////////////////////////////////////////////// +/// MEMORY-BASED STEP ITERATOR +//////////////////////////////////////////////////////////////////////////////////////// + +/// \class memory_based_step_iterator +/// \ingroup PixelIteratorModelStepPtr PixelBasedModel +/// \brief Iterator with dynamically specified step in memory units (bytes or bits). Models StepIteratorConcept, IteratorAdaptorConcept, MemoryBasedIteratorConcept, PixelIteratorConcept, HasDynamicXStepTypeConcept +/// +/// A refinement of step_iterator_adaptor that uses a dynamic parameter for the step +/// which is specified in memory units, such as bytes or bits +/// +/// Pixel step iterators are used to provide iteration over non-adjacent pixels. +/// Common use is a vertical traversal, where the step is the row stride. +/// +/// Another application is as a sub-channel view. For example, a red intensity image over +/// interleaved RGB data would use a step iterator adaptor with step sizeof(channel_t)*3 +/// In the latter example the step size could be fixed at compile time for efficiency. +/// Compile-time fixed step can be implemented by providing a step function object that takes the step as a template +//////////////////////////////////////////////////////////////////////////////////////// + +/// \ingroup PixelIteratorModelStepPtr +/// \brief function object that returns the memory unit distance between two iterators and advances a given iterator a given number of mem units (bytes or bits) +template +struct memunit_step_fn { + typedef std::ptrdiff_t difference_type; + + memunit_step_fn(difference_type step=memunit_step(Iterator())) : _step(step) {} + + difference_type difference(const Iterator& it1, const Iterator& it2) const { return memunit_distance(it1,it2)/_step; } + void advance(Iterator& it, difference_type d) const { memunit_advance(it,d*_step); } + difference_type step() const { return _step; } + + void set_step(std::ptrdiff_t step) { _step=step; } +private: + GIL_CLASS_REQUIRE(Iterator, boost::gil, MemoryBasedIteratorConcept) + difference_type _step; +}; + +template +class memory_based_step_iterator : public detail::step_iterator_adaptor, + Iterator, + memunit_step_fn > { + GIL_CLASS_REQUIRE(Iterator, boost::gil, MemoryBasedIteratorConcept) +public: + typedef detail::step_iterator_adaptor, + Iterator, + memunit_step_fn > parent_t; + typedef typename parent_t::reference reference; + typedef typename parent_t::difference_type difference_type; + typedef Iterator x_iterator; + + memory_based_step_iterator() : parent_t(Iterator()) {} + memory_based_step_iterator(Iterator it, std::ptrdiff_t memunit_step) : parent_t(it, memunit_step_fn(memunit_step)) {} + template + memory_based_step_iterator(const memory_based_step_iterator& it) + : parent_t(it.base(), memunit_step_fn(it.step())) {} + + /// For some reason operator[] provided by iterator_adaptor returns a custom class that is convertible to reference + /// We require our own reference because it is registered in iterator_traits + reference operator[](difference_type d) const { return *(*this+d); } + + void set_step(std::ptrdiff_t memunit_step) { this->_step_fn.set_step(memunit_step); } + + x_iterator& base() { return parent_t::base_reference(); } + x_iterator const& base() const { return parent_t::base_reference(); } +}; + +template +struct const_iterator_type > { + typedef memory_based_step_iterator::type> type; +}; + +template +struct iterator_is_mutable > : public iterator_is_mutable {}; + + +///////////////////////////// +// IteratorAdaptorConcept +///////////////////////////// + +template +struct is_iterator_adaptor > : public mpl::true_{}; + +template +struct iterator_adaptor_get_base > { + typedef Iterator type; +}; + +template +struct iterator_adaptor_rebind,NewBaseIterator> { + typedef memory_based_step_iterator type; +}; + +///////////////////////////// +// PixelBasedConcept +///////////////////////////// + +template +struct color_space_type > : public color_space_type {}; + +template +struct channel_mapping_type > : public channel_mapping_type {}; + +template +struct is_planar > : public is_planar {}; + +template +struct channel_type > : public channel_type {}; + +///////////////////////////// +// MemoryBasedIteratorConcept +///////////////////////////// +template +struct byte_to_memunit > : public byte_to_memunit {}; + +template +inline std::ptrdiff_t memunit_step(const memory_based_step_iterator& p) { return p.step(); } + +template +inline std::ptrdiff_t memunit_distance(const memory_based_step_iterator& p1, + const memory_based_step_iterator& p2) { + return memunit_distance(p1.base(),p2.base()); +} + +template +inline void memunit_advance(memory_based_step_iterator& p, + std::ptrdiff_t diff) { + memunit_advance(p.base(), diff); +} + +template +inline memory_based_step_iterator +memunit_advanced(const memory_based_step_iterator& p, + std::ptrdiff_t diff) { + return memory_based_step_iterator(memunit_advanced(p.base(), diff),p.step()); +} + +template +inline typename std::iterator_traits::reference +memunit_advanced_ref(const memory_based_step_iterator& p, + std::ptrdiff_t diff) { + return memunit_advanced_ref(p.base(), diff); +} + +///////////////////////////// +// HasDynamicXStepTypeConcept +///////////////////////////// + +template +struct dynamic_x_step_type > { + typedef memory_based_step_iterator type; +}; + +// For step iterators, pass the function object to the base +template +struct iterator_add_deref,Deref> { + GIL_CLASS_REQUIRE(Deref, boost::gil, PixelDereferenceAdaptorConcept) + + typedef memory_based_step_iterator::type> type; + + static type make(const memory_based_step_iterator& it, const Deref& d) { return type(iterator_add_deref::make(it.base(),d),it.step()); } +}; + +//////////////////////////////////////////////////////////////////////////////////////// +/// make_step_iterator +//////////////////////////////////////////////////////////////////////////////////////// + +template typename dynamic_x_step_type::type make_step_iterator(const I& it, std::ptrdiff_t step); + +namespace detail { + +// if the iterator is a plain base iterator (non-adaptor), wraps it in memory_based_step_iterator +template +typename dynamic_x_step_type::type make_step_iterator_impl(const I& it, std::ptrdiff_t step, mpl::false_) { + return memory_based_step_iterator(it, step); +} + +// If the iterator is compound, put the step in its base +template +typename dynamic_x_step_type::type make_step_iterator_impl(const I& it, std::ptrdiff_t step, mpl::true_) { + return make_step_iterator(it.base(), step); +} + +// If the iterator is memory_based_step_iterator, change the step +template +memory_based_step_iterator make_step_iterator_impl(const memory_based_step_iterator& it, std::ptrdiff_t step, mpl::true_) { + return memory_based_step_iterator(it.base(), step); +} +} + +/// \brief Constructs a step iterator from a base iterator and a step. +/// +/// To construct a step iterator from a given iterator Iterator and a given step, if Iterator does not +/// already have a dynamic step, we wrap it in a memory_based_step_iterator. Otherwise we +/// do a compile-time traversal of the chain of iterator adaptors to locate the step iterator +/// and then set it step to the new one. +/// +/// The step iterator of Iterator is not always memory_based_step_iterator. For example, Iterator may +/// already be a memory_based_step_iterator, in which case it will be inefficient to stack them; +/// we can obtain the same result by multiplying their steps. Note that for Iterator to be a +/// step iterator it does not necessarily have to have the form memory_based_step_iterator. +/// The step iterator can be wrapped inside another iterator. Also, it may not have the +/// type memory_based_step_iterator, but it could be a user-provided type. +template // Models MemoryBasedIteratorConcept, HasDynamicXStepTypeConcept +typename dynamic_x_step_type::type make_step_iterator(const I& it, std::ptrdiff_t step) { + return detail::make_step_iterator_impl(it, step, typename is_iterator_adaptor::type()); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/typedefs.hpp b/win32/include/boost/gil/typedefs.hpp new file mode 100755 index 000000000..d3d233f8d --- /dev/null +++ b/win32/include/boost/gil/typedefs.hpp @@ -0,0 +1,196 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_TYPEDEFS_H +#define GIL_TYPEDEFS_H + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Useful typedefs +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on March 8, 2006 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include "gil_config.hpp" +#include +#include "gray.hpp" +#include "rgb.hpp" +#include "rgba.hpp" +#include "cmyk.hpp" +#include "device_n.hpp" +#include + +// CS = 'bgr' LAYOUT='bgr_layout_t' +#define GIL_DEFINE_BASE_TYPEDEFS_INTERNAL(T,CS,LAYOUT) \ + template struct pixel; \ + template struct planar_pixel_reference; \ + template struct planar_pixel_iterator; \ + template class memory_based_step_iterator; \ + template class point2; \ + template class memory_based_2d_locator; \ + template class image_view; \ + template class image; \ + typedef pixel CS##T##_pixel_t; \ + typedef const pixel CS##T##c_pixel_t; \ + typedef pixel& CS##T##_ref_t; \ + typedef const pixel& CS##T##c_ref_t; \ + typedef CS##T##_pixel_t* CS##T##_ptr_t; \ + typedef CS##T##c_pixel_t* CS##T##c_ptr_t; \ + typedef memory_based_step_iterator CS##T##_step_ptr_t; \ + typedef memory_based_step_iterator CS##T##c_step_ptr_t; \ + typedef memory_based_2d_locator > CS##T##_loc_t; \ + typedef memory_based_2d_locator > CS##T##c_loc_t; \ + typedef memory_based_2d_locator > CS##T##_step_loc_t; \ + typedef memory_based_2d_locator > CS##T##c_step_loc_t; \ + typedef image_view CS##T##_view_t; \ + typedef image_view CS##T##c_view_t; \ + typedef image_view CS##T##_step_view_t; \ + typedef image_view CS##T##c_step_view_t; \ + typedef image > CS##T##_image_t; + +// CS = 'bgr' CS_FULL = 'rgb_t' LAYOUT='bgr_layout_t' +#define GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(T,CS,CS_FULL,LAYOUT) \ + GIL_DEFINE_BASE_TYPEDEFS_INTERNAL(T,CS,LAYOUT) \ + typedef planar_pixel_reference CS##T##_planar_ref_t; \ + typedef planar_pixel_reference CS##T##c_planar_ref_t; \ + typedef planar_pixel_iterator CS##T##_planar_ptr_t; \ + typedef planar_pixel_iterator CS##T##c_planar_ptr_t; \ + typedef memory_based_step_iterator CS##T##_planar_step_ptr_t; \ + typedef memory_based_step_iterator CS##T##c_planar_step_ptr_t; \ + typedef memory_based_2d_locator > CS##T##_planar_loc_t; \ + typedef memory_based_2d_locator > CS##T##c_planar_loc_t; \ + typedef memory_based_2d_locator > CS##T##_planar_step_loc_t; \ + typedef memory_based_2d_locator > CS##T##c_planar_step_loc_t; \ + typedef image_view CS##T##_planar_view_t; \ + typedef image_view CS##T##c_planar_view_t; \ + typedef image_view CS##T##_planar_step_view_t; \ + typedef image_view CS##T##c_planar_step_view_t;\ + typedef image > CS##T##_planar_image_t; + +#define GIL_DEFINE_BASE_TYPEDEFS(T,CS) \ + GIL_DEFINE_BASE_TYPEDEFS_INTERNAL(T,CS,CS##_layout_t) + +#define GIL_DEFINE_ALL_TYPEDEFS(T,CS) \ + GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(T,CS,CS##_t,CS##_layout_t) + +namespace boost { namespace gil { + +// forward declarations +template struct scoped_channel_value; +struct float_zero; +struct float_one; +typedef scoped_channel_value bits32f; +typedef uint8_t bits8; +typedef uint16_t bits16; +typedef uint32_t bits32; +typedef int8_t bits8s; +typedef int16_t bits16s; +typedef int32_t bits32s; + +GIL_DEFINE_BASE_TYPEDEFS(8, gray) +GIL_DEFINE_BASE_TYPEDEFS(8s, gray) +GIL_DEFINE_BASE_TYPEDEFS(16, gray) +GIL_DEFINE_BASE_TYPEDEFS(16s,gray) +GIL_DEFINE_BASE_TYPEDEFS(32 ,gray) +GIL_DEFINE_BASE_TYPEDEFS(32s,gray) +GIL_DEFINE_BASE_TYPEDEFS(32f,gray) +GIL_DEFINE_BASE_TYPEDEFS(8, bgr) +GIL_DEFINE_BASE_TYPEDEFS(8s, bgr) +GIL_DEFINE_BASE_TYPEDEFS(16, bgr) +GIL_DEFINE_BASE_TYPEDEFS(16s,bgr) +GIL_DEFINE_BASE_TYPEDEFS(32 ,bgr) +GIL_DEFINE_BASE_TYPEDEFS(32s,bgr) +GIL_DEFINE_BASE_TYPEDEFS(32f,bgr) +GIL_DEFINE_BASE_TYPEDEFS(8, argb) +GIL_DEFINE_BASE_TYPEDEFS(8s, argb) +GIL_DEFINE_BASE_TYPEDEFS(16, argb) +GIL_DEFINE_BASE_TYPEDEFS(16s,argb) +GIL_DEFINE_BASE_TYPEDEFS(32, argb) +GIL_DEFINE_BASE_TYPEDEFS(32s,argb) +GIL_DEFINE_BASE_TYPEDEFS(32f,argb) +GIL_DEFINE_BASE_TYPEDEFS(8, abgr) +GIL_DEFINE_BASE_TYPEDEFS(8s, abgr) +GIL_DEFINE_BASE_TYPEDEFS(16, abgr) +GIL_DEFINE_BASE_TYPEDEFS(16s,abgr) +GIL_DEFINE_BASE_TYPEDEFS(32 ,abgr) +GIL_DEFINE_BASE_TYPEDEFS(32s,abgr) +GIL_DEFINE_BASE_TYPEDEFS(32f,abgr) +GIL_DEFINE_BASE_TYPEDEFS(8, bgra) +GIL_DEFINE_BASE_TYPEDEFS(8s, bgra) +GIL_DEFINE_BASE_TYPEDEFS(16, bgra) +GIL_DEFINE_BASE_TYPEDEFS(16s,bgra) +GIL_DEFINE_BASE_TYPEDEFS(32 ,bgra) +GIL_DEFINE_BASE_TYPEDEFS(32s,bgra) +GIL_DEFINE_BASE_TYPEDEFS(32f,bgra) + +GIL_DEFINE_ALL_TYPEDEFS(8, rgb) +GIL_DEFINE_ALL_TYPEDEFS(8s, rgb) +GIL_DEFINE_ALL_TYPEDEFS(16, rgb) +GIL_DEFINE_ALL_TYPEDEFS(16s,rgb) +GIL_DEFINE_ALL_TYPEDEFS(32 ,rgb) +GIL_DEFINE_ALL_TYPEDEFS(32s,rgb) +GIL_DEFINE_ALL_TYPEDEFS(32f,rgb) +GIL_DEFINE_ALL_TYPEDEFS(8, rgba) +GIL_DEFINE_ALL_TYPEDEFS(8s, rgba) +GIL_DEFINE_ALL_TYPEDEFS(16, rgba) +GIL_DEFINE_ALL_TYPEDEFS(16s,rgba) +GIL_DEFINE_ALL_TYPEDEFS(32 ,rgba) +GIL_DEFINE_ALL_TYPEDEFS(32s,rgba) +GIL_DEFINE_ALL_TYPEDEFS(32f,rgba) +GIL_DEFINE_ALL_TYPEDEFS(8, cmyk) +GIL_DEFINE_ALL_TYPEDEFS(8s, cmyk) +GIL_DEFINE_ALL_TYPEDEFS(16, cmyk) +GIL_DEFINE_ALL_TYPEDEFS(16s,cmyk) +GIL_DEFINE_ALL_TYPEDEFS(32 ,cmyk) +GIL_DEFINE_ALL_TYPEDEFS(32s,cmyk) +GIL_DEFINE_ALL_TYPEDEFS(32f,cmyk) + + +template struct devicen_t; +template struct devicen_layout_t; +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(8, dev2n, devicen_t<2>, devicen_layout_t<2>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(8s, dev2n, devicen_t<2>, devicen_layout_t<2>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(16, dev2n, devicen_t<2>, devicen_layout_t<2>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(16s,dev2n, devicen_t<2>, devicen_layout_t<2>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32 ,dev2n, devicen_t<2>, devicen_layout_t<2>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32s,dev2n, devicen_t<2>, devicen_layout_t<2>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32f,dev2n, devicen_t<2>, devicen_layout_t<2>) + +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(8, dev3n, devicen_t<3>, devicen_layout_t<3>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(8s, dev3n, devicen_t<3>, devicen_layout_t<3>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(16, dev3n, devicen_t<3>, devicen_layout_t<3>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(16s,dev3n, devicen_t<3>, devicen_layout_t<3>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32 ,dev3n, devicen_t<3>, devicen_layout_t<3>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32s,dev3n, devicen_t<3>, devicen_layout_t<3>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32f,dev3n, devicen_t<3>, devicen_layout_t<3>) + +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(8, dev4n, devicen_t<4>, devicen_layout_t<4>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(8s, dev4n, devicen_t<4>, devicen_layout_t<4>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(16, dev4n, devicen_t<4>, devicen_layout_t<4>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(16s,dev4n, devicen_t<4>, devicen_layout_t<4>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32 ,dev4n, devicen_t<4>, devicen_layout_t<4>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32s,dev4n, devicen_t<4>, devicen_layout_t<4>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32f,dev4n, devicen_t<4>, devicen_layout_t<4>) + +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(8, dev5n, devicen_t<5>, devicen_layout_t<5>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(8s, dev5n, devicen_t<5>, devicen_layout_t<5>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(16, dev5n, devicen_t<5>, devicen_layout_t<5>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(16s,dev5n, devicen_t<5>, devicen_layout_t<5>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32 ,dev5n, devicen_t<5>, devicen_layout_t<5>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32s,dev5n, devicen_t<5>, devicen_layout_t<5>) +GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(32f,dev5n, devicen_t<5>, devicen_layout_t<5>) + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/utilities.hpp b/win32/include/boost/gil/utilities.hpp new file mode 100755 index 000000000..38df8da4a --- /dev/null +++ b/win32/include/boost/gil/utilities.hpp @@ -0,0 +1,331 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_UTILITIES_H +#define GIL_UTILITIES_H + +#include "gil_config.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Various utilities not specific to the image library. Some are non-standard STL extensions or generic iterator adaptors +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on September 18, 2007 +/// +/// +//////////////////////////////////////////////////////////////////////////////////////// + +namespace boost { namespace gil { + +/** +\addtogroup PointModel + +Example: +\code +point2 p(3,2); +assert((p[0] == p.x) && (p[1] == p.y)); +assert(axis_value<0>(p) == 3); +assert(axis_value<1>(p) == 2); +\endcode +*/ + +//////////////////////////////////////////////////////////////////////////////////////// +// CLASS point2 +/// +/// \brief 2D point both axes of which have the same dimension type +/// \ingroup PointModel +/// Models: Point2DConcept +/// +//////////////////////////////////////////////////////////////////////////////////////// + +template +class point2 { +public: + typedef T value_type; + template struct axis { typedef value_type coord_t; }; + static const std::size_t num_dimensions=2; + + point2() : x(0), y(0) {} + point2(T newX, T newY) : x(newX), y(newY) {} + point2(const point2& p) : x(p.x), y(p.y) {} + ~point2() {} + + point2& operator=(const point2& p) { x=p.x; y=p.y; return *this; } + + point2 operator<<(std::ptrdiff_t shift) const { return point2(x<>(std::ptrdiff_t shift) const { return point2(x>>shift,y>>shift); } + point2& operator+=(const point2& p) { x+=p.x; y+=p.y; return *this; } + point2& operator-=(const point2& p) { x-=p.x; y-=p.y; return *this; } + point2& operator/=(double t) { x/=t; y/=t; return *this; } + + const T& operator[](std::size_t i) const { return this->*mem_array[i]; } + T& operator[](std::size_t i) { return this->*mem_array[i]; } + + T x,y; +private: + // this static array of pointers to member variables makes operator[] safe and doesn't seem to exhibit any performance penalty + static T point2::* const mem_array[num_dimensions]; +}; + +template +T point2::* const point2::mem_array[point2::num_dimensions] = { &point2::x, &point2::y }; + +/// \ingroup PointModel +template GIL_FORCEINLINE +bool operator==(const point2& p1, const point2& p2) { return (p1.x==p2.x && p1.y==p2.y); } +/// \ingroup PointModel +template GIL_FORCEINLINE +bool operator!=(const point2& p1, const point2& p2) { return p1.x!=p2.x || p1.y!=p2.y; } +/// \ingroup PointModel +template GIL_FORCEINLINE +point2 operator+(const point2& p1, const point2& p2) { return point2(p1.x+p2.x,p1.y+p2.y); } +/// \ingroup PointModel +template GIL_FORCEINLINE +point2 operator-(const point2& p) { return point2(-p.x,-p.y); } +/// \ingroup PointModel +template GIL_FORCEINLINE +point2 operator-(const point2& p1, const point2& p2) { return point2(p1.x-p2.x,p1.y-p2.y); } +/// \ingroup PointModel +template GIL_FORCEINLINE +point2 operator/(const point2& p, double t) { return t==0 ? point2(0,0):point2(p.x/t,p.y/t); } +/// \ingroup PointModel +template GIL_FORCEINLINE +point2 operator*(const point2& p, std::ptrdiff_t t) { return point2(p.x*t,p.y*t); } +/// \ingroup PointModel +template GIL_FORCEINLINE +point2 operator*(std::ptrdiff_t t, const point2& p) { return point2(p.x*t,p.y*t); } + +/// \ingroup PointModel +template GIL_FORCEINLINE +const T& axis_value(const point2& p) { return p[K]; } + +/// \ingroup PointModel +template GIL_FORCEINLINE + T& axis_value( point2& p) { return p[K]; } + +//////////////////////////////////////////////////////////////////////////////////////// +/// +/// Rounding of real numbers / points to integers / integer points +/// +//////////////////////////////////////////////////////////////////////////////////////// + +inline std::ptrdiff_t iround(float x ) { return static_cast(x + (x < 0.0f ? -0.5f : 0.5f)); } +inline std::ptrdiff_t iround(double x) { return static_cast(x + (x < 0.0 ? -0.5 : 0.5)); } +inline std::ptrdiff_t ifloor(float x ) { return static_cast(std::floor(x)); } +inline std::ptrdiff_t ifloor(double x) { return static_cast(std::floor(x)); } +inline std::ptrdiff_t iceil(float x ) { return static_cast(std::ceil(x)); } +inline std::ptrdiff_t iceil(double x) { return static_cast(std::ceil(x)); } + +/** +\addtogroup PointAlgorithm + +Example: +\code +assert(iround(point2(3.1, 3.9)) == point2(3,4)); +\endcode +*/ + +/// \ingroup PointAlgorithm +inline point2 iround(const point2& p) { return point2(iround(p.x),iround(p.y)); } +/// \ingroup PointAlgorithm +inline point2 iround(const point2& p) { return point2(iround(p.x),iround(p.y)); } +/// \ingroup PointAlgorithm +inline point2 ifloor(const point2& p) { return point2(ifloor(p.x),ifloor(p.y)); } +/// \ingroup PointAlgorithm +inline point2 ifloor(const point2& p) { return point2(ifloor(p.x),ifloor(p.y)); } +/// \ingroup PointAlgorithm +inline point2 iceil (const point2& p) { return point2(iceil(p.x), iceil(p.y)); } +/// \ingroup PointAlgorithm +inline point2 iceil (const point2& p) { return point2(iceil(p.x), iceil(p.y)); } + +//////////////////////////////////////////////////////////////////////////////////////// +/// +/// computing size with alignment +/// +//////////////////////////////////////////////////////////////////////////////////////// + +template +inline T align(T val, std::size_t alignment) { + return val+(alignment - val%alignment)%alignment; +} + +/// \brief Helper base class for pixel dereference adaptors. +/// \ingroup PixelDereferenceAdaptorModel +/// +template +struct deref_base : public std::unary_function { + typedef ConstT const_t; + typedef Value value_type; + typedef Reference reference; + typedef ConstReference const_reference; + BOOST_STATIC_CONSTANT(bool, is_mutable = IsMutable); +}; + +/// \brief Composes two dereference function objects. Similar to std::unary_compose but needs to pull some typedefs from the component types. Models: PixelDereferenceAdaptorConcept +/// \ingroup PixelDereferenceAdaptorModel +/// +template +class deref_compose : public deref_base< + deref_compose, + typename D1::value_type, typename D1::reference, typename D1::const_reference, + typename D2::argument_type, typename D1::result_type, D1::is_mutable && D2::is_mutable> +{ +public: + D1 _fn1; + D2 _fn2; + + typedef typename D2::argument_type argument_type; + typedef typename D1::result_type result_type; + + deref_compose() {} + deref_compose(const D1& x, const D2& y) : _fn1(x), _fn2(y) {} + deref_compose(const deref_compose& dc) : _fn1(dc._fn1), _fn2(dc._fn2) {} + template deref_compose(const deref_compose<_D1,_D2>& dc) : _fn1(dc._fn1), _fn2(dc._fn2) {} + + result_type operator()(argument_type x) const { return _fn1(_fn2(x)); } + result_type operator()(argument_type x) { return _fn1(_fn2(x)); } +}; + +// reinterpret_cast is implementation-defined. Static cast is not. +template GIL_FORCEINLINE + OutPtr gil_reinterpret_cast( In* p) { return static_cast(static_cast(p)); } + +template GIL_FORCEINLINE +const OutPtr gil_reinterpret_cast_c(const In* p) { return static_cast(static_cast(p)); } + +namespace detail { + +//////////////////////////////////////////////////////////////////////////////////////// +/// +/// \brief copy_n taken from SGI STL. +/// +//////////////////////////////////////////////////////////////////////////////////////// + +template +std::pair _copy_n(InputIter first, Size count, + OutputIter result, + std::input_iterator_tag) { + for ( ; count > 0; --count) { + *result = *first; + ++first; + ++result; + } + return std::pair(first, result); +} + +template +inline std::pair +_copy_n(RAIter first, Size count, OutputIter result, std::random_access_iterator_tag) { + RAIter last = first + count; + return std::pair(last, std::copy(first, last, result)); +} + +template +inline std::pair +_copy_n(InputIter first, Size count, OutputIter result) { + return _copy_n(first, count, result, typename std::iterator_traits::iterator_category()); +} + +template +inline std::pair +copy_n(InputIter first, Size count, OutputIter result) { + return detail::_copy_n(first, count, result); +} + +/// \brief identity taken from SGI STL. +template +struct identity : public std::unary_function { + const T& operator()(const T& val) const { return val; } +}; + +/*************************************************************************************************/ + +/// \brief plus function object whose arguments may be of different type. +template +struct plus_asymmetric : public std::binary_function { + T1 operator()(T1 f1, T2 f2) const { + return f1+f2; + } +}; + +/*************************************************************************************************/ + +/// \brief operator++ wrapped in a function object +template +struct inc : public std::unary_function { + T operator()(T x) const { return ++x; } +}; + +/*************************************************************************************************/ + +/// \brief operator-- wrapped in a function object +template +struct dec : public std::unary_function { + T operator()(T x) const { return --x; } +}; + +/// \brief Returns the index corresponding to the first occurrance of a given given type in +// a given MPL RandomAccessSequence (or size if the type is not present) +template +struct type_to_index + : public mpl::distance::type, + typename mpl::find::type>::type {}; +} // namespace detail + + + +/// \ingroup ColorSpaceAndLayoutModel +/// \brief Represents a color space and ordering of channels in memory +template ::value> > +struct layout { + typedef ColorSpace color_space_t; + typedef ChannelMapping channel_mapping_t; +}; + +/// \brief A version of swap that also works with reference proxy objects +template // where value_type == value_type == Value +void swap_proxy(T1& left, T2& right) { + Value tmp = left; + left = right; + right = tmp; +} + +/// \brief Run-time detection of whether the underlying architecture is little endian +inline bool little_endian() { + short tester = 0x0001; + return *(char*)&tester!=0; +} +/// \brief Run-time detection of whether the underlying architecture is big endian +inline bool big_endian() { + return !little_endian(); +} + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/gil/virtual_locator.hpp b/win32/include/boost/gil/virtual_locator.hpp new file mode 100755 index 000000000..782a4a537 --- /dev/null +++ b/win32/include/boost/gil/virtual_locator.hpp @@ -0,0 +1,136 @@ +/* + Copyright 2005-2007 Adobe Systems Incorporated + + Use, modification and distribution are subject to 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). + + See http://opensource.adobe.com/gil for most recent version including documentation. +*/ + +/*************************************************************************************************/ + +#ifndef GIL_VIRTUAL_LOCATOR_HPP +#define GIL_VIRTUAL_LOCATOR_HPP + +//////////////////////////////////////////////////////////////////////////////////////// +/// \file +/// \brief Locator for virtual image views +/// \author Lubomir Bourdev and Hailin Jin \n +/// Adobe Systems Incorporated +/// \date 2005-2007 \n Last updated on February 12, 2007 +/// +//////////////////////////////////////////////////////////////////////////////////////// + +#include +#include "position_iterator.hpp" + +namespace boost { namespace gil { + +/// \brief A 2D locator over a virtual image. Upon dereferencing, invokes a given function object passing it its coordinates. Models: PixelLocatorConcept, HasDynamicXStepTypeConcept, HasDynamicYStepTypeConcept, HasTransposedTypeConcept +/// \ingroup PixelLocatorModel PixelBasedModel +/// +template // A function object that given a point returns a reference. Models PixelDereferenceAdaptorConcept +class virtual_2d_locator : public pixel_2d_locator_base, position_iterator, position_iterator > { + typedef virtual_2d_locator this_t; +public: + typedef pixel_2d_locator_base, position_iterator, position_iterator > parent_t; + typedef virtual_2d_locator const_t; + + typedef Deref deref_fn_t; + typedef typename parent_t::point_t point_t; + + typedef typename parent_t::coord_t coord_t; + typedef typename parent_t::x_coord_t x_coord_t; + typedef typename parent_t::y_coord_t y_coord_t; + typedef typename parent_t::x_iterator x_iterator; + typedef typename parent_t::y_iterator y_iterator; + + template struct add_deref { + typedef virtual_2d_locator,IsTransposed > type; + static type make(const virtual_2d_locator& loc, const NewDeref& nderef) { + return type(loc.pos(), loc.step(), deref_compose(nderef,loc.deref_fn())); + } + }; + + virtual_2d_locator(const point_t& p=point_t(0,0), const point_t& step=point_t(1,1), const deref_fn_t& d=deref_fn_t()) : _p(p,step,d) {} + template virtual_2d_locator(const virtual_2d_locator& loc, coord_t y_step) + : _p(loc.pos(), point_t(loc.step().x,loc.step().y*y_step), loc.deref_fn()) {} + template virtual_2d_locator(const virtual_2d_locator& loc, coord_t x_step, coord_t y_step, bool transpose=false) + : _p(loc.pos(), transpose ? + point_t(loc.step().x*y_step,loc.step().y*x_step) : + point_t(loc.step().x*x_step,loc.step().y*y_step), loc.deref_fn()) { assert(transpose==(IsTransposed!=TR));} + + template virtual_2d_locator(const virtual_2d_locator& pl) : _p(pl._p) {} + virtual_2d_locator(const virtual_2d_locator& pl) : _p(pl._p) {} + + bool operator==(const this_t& p) const { return _p==p._p; } + + x_iterator& x() { return *gil_reinterpret_cast(this); } + y_iterator& y() { return _p; } + x_iterator const& x() const { return *gil_reinterpret_cast_c(this); } + y_iterator const& y() const { return _p; } + + // Returns the y distance between two x_iterators given the difference of their x positions + y_coord_t y_distance_to(const this_t& it2, x_coord_t xDiff) const { return (it2.pos()[1-IsTransposed] - pos()[1-IsTransposed])/step()[1-IsTransposed]; } + bool is_1d_traversable(x_coord_t) const { return false; } // is there no gap at the end of each row? I.e. can we use x_iterator to visit every pixel instead of nested loops? + + // Methods specific for virtual 2D locator + const point_t& pos() const { return _p.pos(); } + const point_t& step() const { return _p.step(); } + const deref_fn_t& deref_fn() const { return _p.deref_fn(); } +private: + template friend class virtual_2d_locator; + y_iterator _p; // contains the current position, the step and the dereference object +}; + +///////////////////////////// +// PixelBasedConcept +///////////////////////////// + +template +struct channel_type > : public channel_type::parent_t> { +}; + +template +struct color_space_type > : public color_space_type::parent_t> { +}; + +template +struct channel_mapping_type > : public channel_mapping_type::parent_t> { +}; + +template +struct is_planar > : public is_planar::parent_t> { +}; + +///////////////////////////// +// HasDynamicXStepTypeConcept +///////////////////////////// + +template +struct dynamic_x_step_type > { + typedef virtual_2d_locator type; +}; + +///////////////////////////// +// HasDynamicYStepTypeConcept +///////////////////////////// + +template +struct dynamic_y_step_type > { + typedef virtual_2d_locator type; +}; + +///////////////////////////// +// HasTransposedTypeConcept +///////////////////////////// + +template +struct transposed_type > { + typedef virtual_2d_locator type; +}; + +} } // namespace boost::gil + +#endif diff --git a/win32/include/boost/graph/adj_list_serialize.hpp b/win32/include/boost/graph/adj_list_serialize.hpp new file mode 100755 index 000000000..a9c5f1cd4 --- /dev/null +++ b/win32/include/boost/graph/adj_list_serialize.hpp @@ -0,0 +1,114 @@ +//======================================================================= +// Copyright 2005 Jeremy G. Siek +// Authors: Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef ADJ_LIST_SERIALIZE_HPP +#define ADJ_LIST_SERIALIZE_HPP + +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { + +namespace serialization { + +// Turn off tracking for adjacency_list. It's not polymorphic, and we +// need to do this to enable saving of non-const adjacency lists. +template +struct tracking_level > { + typedef mpl::integral_c_tag tag; + typedef mpl::int_ type; + BOOST_STATIC_CONSTANT(int, value = tracking_level::type::value); +}; + +template +inline void save( + Archive & ar, + const boost::adjacency_list &graph, + const unsigned int /* file_version */ +){ + typedef adjacency_list Graph; + typedef typename graph_traits::vertex_descriptor Vertex; + + int V = num_vertices(graph); + int E = num_edges(graph); + ar << BOOST_SERIALIZATION_NVP(V); + ar << BOOST_SERIALIZATION_NVP(E); + + // assign indices to vertices + std::map indices; + int num = 0; + typename graph_traits::vertex_iterator vi; + for (vi = vertices(graph).first; vi != vertices(graph).second; ++vi) { + indices[*vi] = num++; + ar << serialization::make_nvp("vertex_property", get(vertex_all_t(), graph, *vi) ); + } + + // write edges + typename graph_traits::edge_iterator ei; + for (ei = edges(graph).first; ei != edges(graph).second; ++ei){ + ar << serialization::make_nvp("u" , indices[source(*ei,graph)]); + ar << serialization::make_nvp("v" , indices[target(*ei,graph)]); + ar << serialization::make_nvp("edge_property", get(edge_all_t(), graph, *ei) ); + } +} + + +template +inline void load( + Archive & ar, + boost::adjacency_list &graph, + const unsigned int /* file_version */ +){ + typedef adjacency_list Graph; + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::edge_descriptor Edge; + + unsigned int V; + ar >> BOOST_SERIALIZATION_NVP(V); + unsigned int E; + ar >> BOOST_SERIALIZATION_NVP(E); + + std::vector verts(V); + int i = 0; + while(V-- > 0){ + Vertex v = add_vertex(graph); + verts[i++] = v; + ar >> serialization::make_nvp("vertex_property", get(vertex_all_t(), graph, v) ); + } + while(E-- > 0){ + int u; int v; + ar >> BOOST_SERIALIZATION_NVP(u); + ar >> BOOST_SERIALIZATION_NVP(v); + Edge e; bool inserted; + tie(e,inserted) = add_edge(verts[u], verts[v], graph); + ar >> serialization::make_nvp("edge_property", get(edge_all_t(), graph, e) ); + } +} + +template +inline void serialize( + Archive & ar, + boost::adjacency_list &graph, + const unsigned int file_version +){ + boost::serialization::split_free(ar, graph, file_version); +} + +}//serialization +}//boost + + +#endif // ADJ_LIST_SERIALIZE_HPP diff --git a/win32/include/boost/graph/adjacency_iterator.hpp b/win32/include/boost/graph/adjacency_iterator.hpp new file mode 100755 index 000000000..8eb24dd46 --- /dev/null +++ b/win32/include/boost/graph/adjacency_iterator.hpp @@ -0,0 +1,102 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_ADJACENCY_ITERATOR_HPP +#define BOOST_ADJACENCY_ITERATOR_HPP + +#include +#include + +namespace boost +{ + + template + struct adjacency_iterator + : iterator_adaptor< + adjacency_iterator + , OutEdgeIter + , Vertex + , use_default + , Vertex + , Difference + > + { + typedef iterator_adaptor< + adjacency_iterator + , OutEdgeIter + , Vertex + , use_default + , Vertex + , Difference + > super_t; + + inline adjacency_iterator() {} + inline adjacency_iterator(OutEdgeIter const& i, const Graph* g) : super_t(i), m_g(g) { } + + inline Vertex + dereference() const + { return target(*this->base(), *m_g); } + + const Graph* m_g; + }; + + template ::vertex_descriptor, + class OutEdgeIter=typename graph_traits::out_edge_iterator> + class adjacency_iterator_generator + { + typedef typename boost::detail::iterator_traits + ::difference_type difference_type; + public: + typedef adjacency_iterator type; + }; + + template + struct inv_adjacency_iterator + : iterator_adaptor< + inv_adjacency_iterator + , InEdgeIter + , Vertex + , use_default + , Vertex + , Difference + > + { + typedef iterator_adaptor< + inv_adjacency_iterator + , InEdgeIter + , Vertex + , use_default + , Vertex + , Difference + > super_t; + + inline inv_adjacency_iterator() { } + inline inv_adjacency_iterator(InEdgeIter const& i, const Graph* g) : super_t(i), m_g(g) { } + + inline Vertex + dereference() const + { return source(*this->base(), *m_g); } + + const Graph* m_g; + }; + + template ::vertex_descriptor, + class InEdgeIter = typename graph_traits::in_edge_iterator> + class inv_adjacency_iterator_generator { + typedef typename boost::detail::iterator_traits + ::difference_type difference_type; + public: + typedef inv_adjacency_iterator type; + }; + +} // namespace boost + +#endif // BOOST_DETAIL_ADJACENCY_ITERATOR_HPP diff --git a/win32/include/boost/graph/adjacency_list.hpp b/win32/include/boost/graph/adjacency_list.hpp new file mode 100755 index 000000000..d75550dac --- /dev/null +++ b/win32/include/boost/graph/adjacency_list.hpp @@ -0,0 +1,564 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_ADJACENCY_LIST_HPP +#define BOOST_GRAPH_ADJACENCY_LIST_HPP + + +#include + +#include +#include +#include + +#if !defined BOOST_NO_HASH +# ifdef BOOST_HASH_SET_HEADER +# include BOOST_HASH_SET_HEADER +# else +# include +# endif +#endif + +#if !defined BOOST_NO_SLIST +# ifdef BOOST_SLIST_HEADER +# include BOOST_SLIST_HEADER +# else +# include +# endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + //=========================================================================== + // Selectors for the VertexList and EdgeList template parameters of + // adjacency_list, and the container_gen traits class which is used + // to map the selectors to the container type used to implement the + // graph. + // + // The main container_gen traits class uses partial specialization, + // so we also include a workaround. + +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#if !defined BOOST_NO_SLIST + struct slistS {}; +#endif + + struct vecS { }; + struct listS { }; + struct setS { }; + struct multisetS { }; + struct mapS { }; +#if !defined BOOST_NO_HASH + struct hash_mapS { }; + struct hash_setS { }; +#endif + + template + struct container_gen { }; + + template + struct container_gen { + typedef std::list type; + }; +#if !defined BOOST_NO_SLIST + template + struct container_gen { + typedef BOOST_STD_EXTENSION_NAMESPACE::slist type; + }; +#endif + template + struct container_gen { + typedef std::vector type; + }; + + template + struct container_gen { + typedef std::set type; + }; + + template + struct container_gen { + typedef std::set type; + }; + + template + struct container_gen { + typedef std::multiset type; + }; + +#if !defined BOOST_NO_HASH + template + struct container_gen { + typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set type; + }; + + template + struct container_gen { + typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set type; + }; +#endif + +#else // !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#if !defined BOOST_NO_SLIST + struct slistS { + template + struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::slist type; }; + }; +#endif + + struct vecS { + template + struct bind_ { typedef std::vector type; }; + }; + + struct listS { + template + struct bind_ { typedef std::list type; }; + }; + + struct setS { + template + struct bind_ { typedef std::set > type; }; + }; + + struct multisetS { + template + struct bind_ { typedef std::multiset > type; }; + }; + +#if !defined BOOST_NO_HASH + struct hash_setS { + template + struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set > type; }; + }; +#endif + + struct mapS { + template + struct bind_ { typedef std::set > type; }; + }; + +#if !defined BOOST_NO_HASH + struct hash_mapS { + template + struct bind_ { typedef BOOST_STD_EXTENSION_NAMESPACE::hash_set > type; }; + }; +#endif + + template struct container_selector { + typedef vecS type; + }; + +#define BOOST_CONTAINER_SELECTOR(NAME) \ + template <> struct container_selector { \ + typedef NAME type; \ + } + + BOOST_CONTAINER_SELECTOR(vecS); + BOOST_CONTAINER_SELECTOR(listS); + BOOST_CONTAINER_SELECTOR(mapS); + BOOST_CONTAINER_SELECTOR(setS); + BOOST_CONTAINER_SELECTOR(multisetS); +#if !defined BOOST_NO_HASH + BOOST_CONTAINER_SELECTOR(hash_mapS); +#endif +#if !defined BOOST_NO_SLIST + BOOST_CONTAINER_SELECTOR(slistS); +#endif + + template + struct container_gen { + typedef typename container_selector::type Select; + typedef typename Select:: template bind_::type type; + }; + +#endif // !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + template + struct parallel_edge_traits { }; + + template <> + struct parallel_edge_traits { + typedef allow_parallel_edge_tag type; }; + + template <> + struct parallel_edge_traits { + typedef allow_parallel_edge_tag type; }; + +#if !defined BOOST_NO_SLIST + template <> + struct parallel_edge_traits { + typedef allow_parallel_edge_tag type; }; +#endif + + template <> + struct parallel_edge_traits { + typedef disallow_parallel_edge_tag type; }; + + template <> + struct parallel_edge_traits { + typedef allow_parallel_edge_tag type; }; + +#if !defined BOOST_NO_HASH + template <> + struct parallel_edge_traits { + typedef disallow_parallel_edge_tag type; + }; +#endif + + // mapS is obsolete, replaced with setS + template <> + struct parallel_edge_traits { + typedef disallow_parallel_edge_tag type; }; + +#if !defined BOOST_NO_HASH + template <> + struct parallel_edge_traits { + typedef disallow_parallel_edge_tag type; + }; +#endif + + namespace detail { + template struct is_random_access { + enum { value = false}; + typedef mpl::false_ type; + }; + template <> + struct is_random_access { + enum { value = true }; + typedef mpl::true_ type; + }; + + } // namespace detail + + + + //=========================================================================== + // The adjacency_list_traits class, which provides a way to access + // some of the associated types of an adjacency_list type without + // having to first create the adjacency_list type. This is useful + // when trying to create interior vertex or edge properties who's + // value type is a vertex or edge descriptor. + + template + struct adjacency_list_traits + { + typedef typename detail::is_random_access::type + is_rand_access; + typedef typename DirectedS::is_bidir_t is_bidir; + typedef typename DirectedS::is_directed_t is_directed; + + typedef typename mpl::if_::type + >::type directed_category; + + typedef typename parallel_edge_traits::type + edge_parallel_category; + + typedef void* vertex_ptr; + typedef typename mpl::if_::type vertex_descriptor; + typedef detail::edge_desc_impl + edge_descriptor; + + typedef std::size_t vertices_size_type; + + private: + // Logic to figure out the edges_size_type + struct dummy {}; + typedef typename container_gen::type EdgeContainer; + typedef typename DirectedS::is_bidir_t BidirectionalT; + typedef typename DirectedS::is_directed_t DirectedT; + typedef typename mpl::and_::type >::type on_edge_storage; + public: + typedef typename mpl::if_::type edges_size_type; + + }; + +} // namespace boost + +#include + +namespace boost { + + //=========================================================================== + // The adjacency_list class. + // + + template + class adjacency_list + : public detail::adj_list_gen< + adjacency_list, + VertexListS, OutEdgeListS, DirectedS, +#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) + typename detail::retag_property_list::type, + typename detail::retag_property_list::type, +#else + VertexProperty, EdgeProperty, +#endif + GraphProperty, EdgeListS>::type + { +#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) + typedef typename detail::retag_property_list::retagged + maybe_vertex_bundled; + + typedef typename detail::retag_property_list::retagged + maybe_edge_bundled; +#endif + + public: +#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) + typedef typename detail::retag_property_list::type + vertex_property_type; + typedef typename detail::retag_property_list::type + edge_property_type; + + // The types that are actually bundled + typedef typename mpl::if_c<(is_same::value), + no_vertex_bundle, + maybe_vertex_bundled>::type vertex_bundled; + typedef typename mpl::if_c<(is_same::value), + no_edge_bundle, + maybe_edge_bundled>::type edge_bundled; +#else + typedef VertexProperty vertex_property_type; + typedef EdgeProperty edge_property_type; + typedef no_vertex_bundle vertex_bundled; + typedef no_edge_bundle edge_bundled; +#endif + + private: + typedef adjacency_list self; + typedef typename detail::adj_list_gen< + self, VertexListS, OutEdgeListS, DirectedS, + vertex_property_type, edge_property_type, GraphProperty, EdgeListS + >::type Base; + + public: + typedef typename Base::stored_vertex stored_vertex; + typedef typename Base::vertices_size_type vertices_size_type; + typedef typename Base::edges_size_type edges_size_type; + typedef typename Base::degree_size_type degree_size_type; + typedef typename Base::vertex_descriptor vertex_descriptor; + typedef typename Base::edge_descriptor edge_descriptor; + typedef OutEdgeListS out_edge_list_selector; + typedef VertexListS vertex_list_selector; + typedef DirectedS directed_selector; + typedef EdgeListS edge_list_selector; + + typedef GraphProperty graph_property_type; + + inline adjacency_list(const GraphProperty& p = GraphProperty()) + : m_property(p) { } + + inline adjacency_list(const adjacency_list& x) + : Base(x), m_property(x.m_property) { } + + inline adjacency_list& operator=(const adjacency_list& x) { + // TBD: probably should give the strong guarantee + if (&x != this) { + Base::operator=(x); + m_property = x.m_property; + } + return *this; + } + + // Required by Mutable Graph + inline adjacency_list(vertices_size_type num_vertices, + const GraphProperty& p = GraphProperty()) + : Base(num_vertices), m_property(p) { } + +#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300 + // Required by Iterator Constructible Graph + template + inline adjacency_list(EdgeIterator first, EdgeIterator last, + vertices_size_type n, + edges_size_type = 0, + const GraphProperty& p = GraphProperty()) + : Base(n, first, last), m_property(p) { } + + template + inline adjacency_list(EdgeIterator first, EdgeIterator last, + EdgePropertyIterator ep_iter, + vertices_size_type n, + edges_size_type = 0, + const GraphProperty& p = GraphProperty()) + : Base(n, first, last, ep_iter), m_property(p) { } +#endif + + void swap(adjacency_list& x) { + // Is there a more efficient way to do this? + adjacency_list tmp(x); + x = *this; + *this = tmp; + } + +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + // Directly access a vertex or edge bundle + vertex_bundled& operator[](vertex_descriptor v) + { return get(vertex_bundle, *this)[v]; } + + const vertex_bundled& operator[](vertex_descriptor v) const + { return get(vertex_bundle, *this)[v]; } + + edge_bundled& operator[](edge_descriptor e) + { return get(edge_bundle, *this)[e]; } + + const edge_bundled& operator[](edge_descriptor e) const + { return get(edge_bundle, *this)[e]; } +#endif + + // protected: (would be protected if friends were more portable) + GraphProperty m_property; + }; + + template + inline void + set_property(adjacency_list& g, Tag, + const Value& value) { + get_property_value(g.m_property, Tag()) = value;; + } + + template + inline + typename graph_property, Tag>::type& + get_property(adjacency_list& g, Tag) { + return get_property_value(g.m_property, Tag()); + } + + template + inline + const + typename graph_property, Tag>::type& + get_property(const adjacency_list& g, Tag) { + return get_property_value(g.m_property, Tag()); + } + + // dwa 09/25/00 - needed to be more explicit so reverse_graph would work. + template + inline Vertex + source(const detail::edge_base& e, + const adjacency_list&) + { + return e.m_source; + } + + template + inline Vertex + target(const detail::edge_base& e, + const adjacency_list&) + { + return e.m_target; + } + + // Support for bundled properties +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + template + inline + typename property_map, T Bundle::*>::type + get(T Bundle::* p, adjacency_list& g) + { + typedef typename property_map, T Bundle::*>::type + result_type; + return result_type(&g, p); + } + + template + inline + typename property_map, T Bundle::*>::const_type + get(T Bundle::* p, adjacency_list const & g) + { + typedef typename property_map, T Bundle::*>::const_type + result_type; + return result_type(&g, p); + } + + template + inline T + get(T Bundle::* p, adjacency_list const & g, const Key& key) + { + return get(get(p, g), key); + } + + template + inline void + put(T Bundle::* p, adjacency_list& g, const Key& key, const T& value) + { + put(get(p, g), key, value); + } + +#endif + + +} // namespace boost + + +#endif // BOOST_GRAPH_ADJACENCY_LIST_HPP diff --git a/win32/include/boost/graph/adjacency_list_io.hpp b/win32/include/boost/graph/adjacency_list_io.hpp new file mode 100755 index 000000000..16b0dee2a --- /dev/null +++ b/win32/include/boost/graph/adjacency_list_io.hpp @@ -0,0 +1,408 @@ +//======================================================================= +// Copyright 2001 Universite Joseph Fourier, Grenoble. +// Author: François Faure +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_ADJACENCY_LIST_IO_HPP +#define BOOST_GRAPH_ADJACENCY_LIST_IO_HPP + +#include +#include +#include +#include + +// Method read to parse an adjacency list from an input stream. Examples: +// cin >> read( G ); +// cin >> read( G, NodePropertySubset(), EdgepropertySubset() ); +// +// Method write to print an adjacency list to an output stream. Examples: +// cout << write( G ); +// cout << write( G, NodePropertySubset(), EdgepropertySubset() ); + +namespace boost { + +/* outline + - basic property input + - get property subset + - graph parser + - property printer + - graph printer + - user methods +*/ + +//=========================================================================== +// basic property input + +template +std::istream& operator >> ( std::istream& in, property& p ) +{ + in >> p.m_value >> *(static_cast(&p)); // houpla !! + return in; +} + +template +std::istream& operator >> ( std::istream& in, property& p ) +{ + in >> p.m_value; + return in; +} + +inline std::istream& operator >> ( std::istream& in, no_property& ) +{ + return in; +} + +// basic property input +//=========================================================================== +// get property subsets + +// get a single property tagged Stag +template +void get +( property& p, const V& v, Stag s ) +{ + get( *(static_cast(&p)),v,s ); +} + +template +void get +( property& p, const V& v, Stag ) +{ + p.m_value = v; +} + +// get a subset of properties tagged Stag +template +void getSubset +( property& p, const property& s ) +{ + get( p, s.m_value, Stag() ); + getSubset( p, Snext(s) ); +} + +template +void getSubset +( property& p, const property& s) +{ + get( p, s.m_value, Stag() ); +} + +inline void getSubset +( no_property& p, const no_property& s ) +{ +} + +#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) +template +void getSubset(T& p, const U& s) +{ + p = s; +} + +template +void getSubset(T&, const no_property&) +{ +} + + +#endif + +// get property subset +//=========================================================================== +// graph parser +typedef enum{ PARSE_NUM_NODES, PARSE_VERTEX, PARSE_EDGE } GraphParserState; + +template +struct GraphParser +{ + + typedef Graph_t Graph; + + GraphParser( Graph* g ): graph(g) + {} + + GraphParser& operator () ( std::istream& in ) + { + typedef typename graph_traits::vertex_descriptor Vertex; + std::vector nodes; + + GraphParserState state = PARSE_VERTEX; + + unsigned int numLine = 1; + char c; + while ( in.get(c) ) + { + if( c== '#' ) skip(in); + else if( c== 'n' ) state = PARSE_NUM_NODES; + else if( c== 'v' ) state = PARSE_VERTEX; + else if( c== 'e' ) state = PARSE_EDGE; + else if( c== '\n' ) numLine++; + else if( !std::isspace(c) ){ + in.putback(c); + if( state == PARSE_VERTEX ){ + VertexPropertySubset readProp; + if( in >> readProp ) + { + VertexProperty vp; + getSubset( vp, readProp ); + nodes.push_back( add_vertex(vp, *graph) ); + } + else + std::cerr<<"read vertex, parse error at line"<> source >> target; + if( in >> readProp ) + { + EdgeProperty ep; + getSubset( ep, readProp ); + add_edge(nodes[source], nodes[target], ep, *graph); + } + else + std::cerr<<"read edge, parse error at line"<> n ){ + for( int i=0; i +struct PropertyPrinter +{ + typedef typename Property::value_type Value; + typedef typename Property::tag_type Tag; + typedef typename Property::next_type Next; + + PropertyPrinter( const Graph& g ):graph(&g){} + + template + PropertyPrinter& operator () ( std::ostream& out, Iterator it ) + { + typename property_map::type ps = get(Tag(), *graph); + out << ps[ *it ] <<" "; + PropertyPrinter print(*graph); + print(out, it); + return (*this); + } +private: + const Graph* graph; +}; +#else +template +struct PropertyPrinter +{ + PropertyPrinter( const Graph& g ):graph(&g){} + + template + PropertyPrinter& operator () ( std::ostream& out, Iterator it ) + { + out << (*graph)[ *it ] <<" "; + return (*this); + } +private: + const Graph* graph; +}; + +template +struct PropertyPrinter > +{ + PropertyPrinter( const Graph& g ):graph(&g){} + + template + PropertyPrinter& operator () ( std::ostream& out, Iterator it ) + { + typename property_map::type ps = get(Tag(), *graph); + out << ps[ *it ] <<" "; + PropertyPrinter print(*graph); + print(out, it); + return (*this); + } +private: + const Graph* graph; +}; +#endif + +template +struct PropertyPrinter +{ + PropertyPrinter( const Graph& ){} + + template + PropertyPrinter& operator () ( std::ostream&, Iterator it ){ return *this; } +}; + +// property printer +//========================================================================= +// graph printer + +template +struct EdgePrinter +{ + + typedef Graph_t Graph; + typedef typename graph_traits::vertex_descriptor Vertex; + + EdgePrinter( const Graph& g ) + : graph(g) + {} + + const EdgePrinter& operator () ( std::ostream& out ) const + { + // assign indices to vertices + std::map indices; + int num = 0; + typename graph_traits::vertex_iterator vi; + for (vi = vertices(graph).first; vi != vertices(graph).second; ++vi){ + indices[*vi] = num++; + } + + // write edges + PropertyPrinter print_Edge(graph); + out << "e" << std::endl; + typename graph_traits::edge_iterator ei; + for (ei = edges(graph).first; ei != edges(graph).second; ++ei){ + out << indices[source(*ei,graph)] << " " << indices[target(*ei,graph)] << " "; + print_Edge(out,ei); + out << std::endl; + } + out << std::endl; + return (*this); + } + +protected: + + const Graph& graph; + +}; + +template +struct GraphPrinter: public EdgePrinter +{ + GraphPrinter( const Graph& g ) + : EdgePrinter(g) + {} + + const GraphPrinter& operator () ( std::ostream& out ) const + { + PropertyPrinter printNode(this->graph); + out << "v"<::vertex_iterator vi; + for (vi = vertices(this->graph).first; vi != vertices(this->graph).second; ++vi){ + printNode(out,vi); + out << std::endl; + } + + EdgePrinter::operator ()( out ); + return (*this); + } +}; + +template +struct GraphPrinter + : public EdgePrinter +{ + GraphPrinter( const Graph& g ) + : EdgePrinter(g) + {} + + const GraphPrinter& operator () ( std::ostream& out ) const + { + out << "n "<< num_vertices(this->graph) << std::endl; + EdgePrinter::operator ()( out ); + return (*this); + } +}; + +// graph printer +//========================================================================= +// user methods + +/// input stream for reading a graph +template +std::istream& operator >> ( std::istream& in, GraphParser gp ) +{ + gp(in); + return in; +} + +/// graph parser for given subsets of internal vertex and edge properties +template +GraphParser,VP,EP,VPS,EPS> +read( adjacency_list& g, VPS vps, EPS eps ) +{ + return GraphParser,VP,EP,VPS,EPS>(&g); +} + +/// graph parser for all internal vertex and edge properties +template +GraphParser,VP,EP,VP,EP> +read( adjacency_list& g ) +{ + return GraphParser,VP,EP,VP,EP>(&g); +} + + +/// output stream for writing a graph +template +std::ostream& operator << ( std::ostream& out, const GraphPrinter& gp ) +{ + gp(out); + return out; +} + +/// write the graph with given property subsets +template +GraphPrinter,VPS,EPS> +write( const adjacency_list& g, VPS, EPS ) +{ + return GraphPrinter,VPS,EPS>(g); +} + +/// write the graph with all internal vertex and edge properties +template +GraphPrinter,VP,EP> +write( const adjacency_list& g ) +{ + return GraphPrinter,VP,EP>(g); +} + +// user methods +//========================================================================= +}// boost +#endif diff --git a/win32/include/boost/graph/adjacency_matrix.hpp b/win32/include/boost/graph/adjacency_matrix.hpp new file mode 100755 index 000000000..a97b32b74 --- /dev/null +++ b/win32/include/boost/graph/adjacency_matrix.hpp @@ -0,0 +1,1278 @@ +//======================================================================= +// Copyright 2001 University of Notre Dame. +// Copyright 2006 Trustees of Indiana University +// Authors: Jeremy G. Siek and Douglas Gregor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_ADJACENCY_MATRIX_HPP +#define BOOST_ADJACENCY_MATRIX_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + namespace detail { + + template + class matrix_edge_desc_impl : public edge_desc_impl + { + typedef edge_desc_impl Base; + public: + matrix_edge_desc_impl() { } + matrix_edge_desc_impl(bool exists, Vertex s, Vertex d, + const void* ep = 0) + : Base(s, d, ep), m_exists(exists) { } + bool exists() const { return m_exists; } + private: + bool m_exists; + }; + + struct does_edge_exist { + template + bool operator()(const Edge& e) const { return e.exists(); } + }; + + template + bool get_edge_exists(const std::pair& stored_edge, int) { + return stored_edge.first; + } + template + void set_edge_exists( + std::pair& stored_edge, + bool flag, + int + ) { + stored_edge.first = flag; + } + + template + bool get_edge_exists(const EdgeProxy& edge_proxy, ...) { + return edge_proxy; + } + template + EdgeProxy& set_edge_exists(EdgeProxy& edge_proxy, bool flag, ...) { + edge_proxy = flag; + return edge_proxy; // just to avoid never used warning + } + + + + template + const EdgeProperty& + get_property(const std::pair& stored_edge) { + return stored_edge.second; + } + template + EdgeProperty& + get_property(std::pair& stored_edge) { + return stored_edge.second; + } + + template + inline void + set_property(std::pair& stored_edge, + const EdgeProperty& ep, int) { + stored_edge.second = ep; + } + + inline const no_property& get_property(const char&) { + static no_property s_prop; + return s_prop; + } + inline no_property& get_property(char&) { + static no_property s_prop; + return s_prop; + } + template + inline void + set_property(EdgeProxy, const EdgeProperty&, ...) {} + + //======================================================================= + // Directed Out Edge Iterator + + template < + typename VertexDescriptor, typename MatrixIter + , typename VerticesSizeType, typename EdgeDescriptor + > + struct dir_adj_matrix_out_edge_iter + : iterator_adaptor< + dir_adj_matrix_out_edge_iter + , MatrixIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , std::ptrdiff_t + > + { + typedef iterator_adaptor< + dir_adj_matrix_out_edge_iter + , MatrixIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , std::ptrdiff_t + > super_t; + + dir_adj_matrix_out_edge_iter() { } + + dir_adj_matrix_out_edge_iter( + const MatrixIter& i + , const VertexDescriptor& src + , const VerticesSizeType& n + ) + : super_t(i), m_src(src), m_targ(0), m_n(n) + { } + + void increment() { + ++this->base_reference(); + ++m_targ; + } + + inline EdgeDescriptor + dereference() const + { + return EdgeDescriptor(get_edge_exists(*this->base(), 0), m_src, m_targ, + &get_property(*this->base())); + } + VertexDescriptor m_src, m_targ; + VerticesSizeType m_n; + }; + + //======================================================================= + // Directed In Edge Iterator + + template < + typename VertexDescriptor, typename MatrixIter + , typename VerticesSizeType, typename EdgeDescriptor + > + struct dir_adj_matrix_in_edge_iter + : iterator_adaptor< + dir_adj_matrix_in_edge_iter + , MatrixIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , std::ptrdiff_t + > + { + typedef iterator_adaptor< + dir_adj_matrix_in_edge_iter + , MatrixIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , std::ptrdiff_t + > super_t; + + dir_adj_matrix_in_edge_iter() { } + + dir_adj_matrix_in_edge_iter( + const MatrixIter& i + , const MatrixIter& last + , const VertexDescriptor& tgt + , const VerticesSizeType& n + ) + : super_t(i), m_last(last), m_src(0), m_targ(tgt), m_n(n) + { } + + void increment() { + if (VerticesSizeType(m_last - this->base_reference()) >= m_n) { + this->base_reference() += m_n; + ++m_src; + } else { + this->base_reference() = m_last; + } + } + + inline EdgeDescriptor + dereference() const + { + return EdgeDescriptor(get_edge_exists(*this->base(), 0), m_src, m_targ, + &get_property(*this->base())); + } + MatrixIter m_last; + VertexDescriptor m_src, m_targ; + VerticesSizeType m_n; + }; + + //======================================================================= + // Undirected Out Edge Iterator + + template < + typename VertexDescriptor, typename MatrixIter + , typename VerticesSizeType, typename EdgeDescriptor + > + struct undir_adj_matrix_out_edge_iter + : iterator_adaptor< + undir_adj_matrix_out_edge_iter + , MatrixIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , std::ptrdiff_t + > + { + typedef iterator_adaptor< + undir_adj_matrix_out_edge_iter + , MatrixIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , std::ptrdiff_t + > super_t; + + undir_adj_matrix_out_edge_iter() { } + + undir_adj_matrix_out_edge_iter( + const MatrixIter& i + , const VertexDescriptor& src + , const VerticesSizeType& n + ) + : super_t(i), m_src(src), m_inc(src), m_targ(0), m_n(n) + {} + + void increment() + { + if (m_targ < m_src) // first half + { + ++this->base_reference(); + } + else if (m_targ < m_n - 1) + { // second half + ++m_inc; + this->base_reference() += m_inc; + } + else + { // past-the-end + this->base_reference() += m_n - m_src; + } + ++m_targ; + } + + inline EdgeDescriptor + dereference() const + { + return EdgeDescriptor( + get_edge_exists(*this->base(), 0), m_src, m_targ + , &get_property(*this->base()) + ); + } + + VertexDescriptor m_src, m_inc, m_targ; + VerticesSizeType m_n; + }; + + //======================================================================= + // Undirected In Edge Iterator + + template < + typename VertexDescriptor, typename MatrixIter + , typename VerticesSizeType, typename EdgeDescriptor + > + struct undir_adj_matrix_in_edge_iter + : iterator_adaptor< + undir_adj_matrix_in_edge_iter + , MatrixIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , std::ptrdiff_t + > + { + typedef iterator_adaptor< + undir_adj_matrix_in_edge_iter + , MatrixIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , std::ptrdiff_t + > super_t; + + undir_adj_matrix_in_edge_iter() { } + + undir_adj_matrix_in_edge_iter( + const MatrixIter& i + , const VertexDescriptor& src + , const VerticesSizeType& n + ) + : super_t(i), m_src(src), m_inc(src), m_targ(0), m_n(n) + {} + + void increment() + { + if (m_targ < m_src) // first half + { + ++this->base_reference(); + } + else if (m_targ < m_n - 1) + { // second half + ++m_inc; + this->base_reference() += m_inc; + } + else + { // past-the-end + this->base_reference() += m_n - m_src; + } + ++m_targ; + } + + inline EdgeDescriptor + dereference() const + { + return EdgeDescriptor( + get_edge_exists(*this->base(), 0), m_targ, m_src + , &get_property(*this->base()) + ); + } + + VertexDescriptor m_src, m_inc, m_targ; + VerticesSizeType m_n; + }; + + //======================================================================= + // Edge Iterator + + template + struct adj_matrix_edge_iter + : iterator_adaptor< + adj_matrix_edge_iter + , MatrixIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , std::ptrdiff_t + > + { + typedef iterator_adaptor< + adj_matrix_edge_iter + , MatrixIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , std::ptrdiff_t + > super_t; + + adj_matrix_edge_iter() { } + + adj_matrix_edge_iter(const MatrixIter& i, const MatrixIter& start, const VerticesSizeType& n) + : super_t(i), m_start(start), m_src(0), m_targ(0), m_n(n) { } + + void increment() + { + increment_dispatch(this->base_reference(), Directed()); + } + + void increment_dispatch(MatrixIter& i, directedS) + { + ++i; + if (m_targ == m_n - 1) + { + m_targ = 0; + ++m_src; + } + else + { + ++m_targ; + } + } + + void increment_dispatch(MatrixIter& i, undirectedS) + { + ++i; + if (m_targ == m_src) + { + m_targ = 0; + ++m_src; + } + else + { + ++m_targ; + } + } + + inline EdgeDescriptor + dereference() const + { + return EdgeDescriptor( + get_edge_exists( + *this->base(), 0), m_src, m_targ, &get_property(*this->base()) + ); + } + + MatrixIter m_start; + VerticesSizeType m_src, m_targ, m_n; + }; + + } // namespace detail + + //========================================================================= + // Adjacency Matrix Traits + template + class adjacency_matrix_traits { + typedef typename Directed::is_directed_t is_directed; + public: + // The bidirectionalS tag is not allowed with the adjacency_matrix + // graph type. Instead, use directedS, which also provides the + // functionality required for a Bidirectional Graph (in_edges, + // in_degree, etc.). +#if !defined(_MSC_VER) || _MSC_VER > 1300 + BOOST_STATIC_ASSERT(type_traits::ice_not<(is_same::value)>::value); +#endif + + typedef typename mpl::if_::type + directed_category; + + typedef disallow_parallel_edge_tag edge_parallel_category; + + typedef std::size_t vertex_descriptor; + + typedef detail::matrix_edge_desc_impl edge_descriptor; + }; + + struct adjacency_matrix_class_tag { }; + + struct adj_matrix_traversal_tag : + public virtual adjacency_matrix_tag, + public virtual vertex_list_graph_tag, + public virtual incidence_graph_tag, + public virtual adjacency_graph_tag, + public virtual edge_list_graph_tag { }; + + //========================================================================= + // Adjacency Matrix Class + template > + class adjacency_matrix { + typedef adjacency_matrix self; + typedef adjacency_matrix_traits Traits; + + public: +#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + // The bidirectionalS tag is not allowed with the adjacency_matrix + // graph type. Instead, use directedS, which also provides the + // functionality required for a Bidirectional Graph (in_edges, + // in_degree, etc.). + BOOST_STATIC_ASSERT(!(is_same::value)); +#endif + +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + typedef typename detail::retag_property_list::type + vertex_property_type; + typedef typename detail::retag_property_list::type + edge_property_type; + + private: + typedef typename detail::retag_property_list::retagged + maybe_vertex_bundled; + + typedef typename detail::retag_property_list::retagged + maybe_edge_bundled; + + public: + // The types that are actually bundled + typedef typename mpl::if_c<(is_same::value), + no_vertex_bundle, + maybe_vertex_bundled>::type vertex_bundled; + typedef typename mpl::if_c<(is_same::value), + no_edge_bundle, + maybe_edge_bundled>::type edge_bundled; +#else + typedef EdgeProperty edge_property_type; + typedef VertexProperty vertex_property_type; + typedef no_vertex_bundle vertex_bundled; + typedef no_edge_bundle edge_bundled; +#endif + + public: // should be private + typedef typename mpl::if_::type, + std::pair, char>::type StoredEdge; +#if (defined(BOOST_MSVC) && BOOST_MSVC <= 1300) || defined(BOOST_NO_STD_ALLOCATOR) + typedef std::vector Matrix; +#else + // This causes internal compiler error for MSVC + typedef typename Allocator::template rebind::other Alloc; + typedef std::vector Matrix; +#endif + typedef typename Matrix::iterator MatrixIter; + typedef typename Matrix::size_type size_type; + public: + // Graph concept required types + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::edge_descriptor edge_descriptor; + typedef typename Traits::directed_category directed_category; + typedef typename Traits::edge_parallel_category edge_parallel_category; + typedef adj_matrix_traversal_tag traversal_category; + + static vertex_descriptor null_vertex() + { + return (std::numeric_limits::max)(); + } + + //private: if friends worked, these would be private + + typedef detail::dir_adj_matrix_out_edge_iter< + vertex_descriptor, MatrixIter, size_type, edge_descriptor + > DirOutEdgeIter; + + typedef detail::undir_adj_matrix_out_edge_iter< + vertex_descriptor, MatrixIter, size_type, edge_descriptor + > UnDirOutEdgeIter; + + typedef typename mpl::if_< + typename Directed::is_directed_t, DirOutEdgeIter, UnDirOutEdgeIter + >::type unfiltered_out_edge_iter; + + typedef detail::dir_adj_matrix_in_edge_iter< + vertex_descriptor, MatrixIter, size_type, edge_descriptor + > DirInEdgeIter; + + typedef detail::undir_adj_matrix_in_edge_iter< + vertex_descriptor, MatrixIter, size_type, edge_descriptor + > UnDirInEdgeIter; + + typedef typename mpl::if_< + typename Directed::is_directed_t, DirInEdgeIter, UnDirInEdgeIter + >::type unfiltered_in_edge_iter; + + typedef detail::adj_matrix_edge_iter< + Directed, MatrixIter, size_type, edge_descriptor + > unfiltered_edge_iter; + + public: + + // IncidenceGraph concept required types + typedef filter_iterator + out_edge_iterator; + + typedef size_type degree_size_type; + + // BidirectionalGraph required types + typedef filter_iterator + in_edge_iterator; + + // AdjacencyGraph required types + typedef typename adjacency_iterator_generator::type adjacency_iterator; + + // VertexListGraph required types + typedef size_type vertices_size_type; + typedef integer_range VertexList; + typedef typename VertexList::iterator vertex_iterator; + + // EdgeListGraph required types + typedef size_type edges_size_type; + typedef filter_iterator< + detail::does_edge_exist, unfiltered_edge_iter + > edge_iterator; + + // PropertyGraph required types + typedef adjacency_matrix_class_tag graph_tag; + + // Constructor required by MutableGraph + adjacency_matrix(vertices_size_type n_vertices) + : m_matrix(Directed::is_directed ? + (n_vertices * n_vertices) + : (n_vertices * (n_vertices + 1) / 2)), + m_vertex_set(0, n_vertices), + m_vertex_properties(n_vertices), + m_num_edges(0) { } + +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + // Directly access a vertex or edge bundle + vertex_bundled& operator[](vertex_descriptor v) + { return get(vertex_bundle, *this)[v]; } + + const vertex_bundled& operator[](vertex_descriptor v) const + { return get(vertex_bundle, *this)[v]; } + + edge_bundled& operator[](edge_descriptor e) + { return get(edge_bundle, *this)[e]; } + + const edge_bundled& operator[](edge_descriptor e) const + { return get(edge_bundle, *this)[e]; } +#endif + + //private: if friends worked, these would be private + + typename Matrix::const_reference + get_edge(vertex_descriptor u, vertex_descriptor v) const { + if (Directed::is_directed) + return m_matrix[u * m_vertex_set.size() + v]; + else { + if (v > u) + std::swap(u, v); + return m_matrix[u * (u + 1)/2 + v]; + } + } + typename Matrix::reference + get_edge(vertex_descriptor u, vertex_descriptor v) { + if (Directed::is_directed) + return m_matrix[u * m_vertex_set.size() + v]; + else { + if (v > u) + std::swap(u, v); + return m_matrix[u * (u + 1)/2 + v]; + } + } + + Matrix m_matrix; + VertexList m_vertex_set; + std::vector m_vertex_properties; + size_type m_num_edges; + }; + + //========================================================================= + // Functions required by the AdjacencyMatrix concept + + template + std::pair::edge_descriptor, + bool> + edge(typename adjacency_matrix::vertex_descriptor u, + typename adjacency_matrix::vertex_descriptor v, + const adjacency_matrix& g) + { + bool exists = detail::get_edge_exists(g.get_edge(u,v), 0); + typename adjacency_matrix::edge_descriptor + e(exists, u, v, &detail::get_property(g.get_edge(u,v))); + return std::make_pair(e, exists); + } + + //========================================================================= + // Functions required by the IncidenceGraph concept + + // O(1) + template + std::pair::out_edge_iterator, + typename adjacency_matrix::out_edge_iterator> + out_edges + (typename adjacency_matrix::vertex_descriptor u, + const adjacency_matrix& g_) + { + typedef adjacency_matrix Graph; + Graph& g = const_cast(g_); + typename Graph::vertices_size_type offset = u * g.m_vertex_set.size(); + typename Graph::MatrixIter f = g.m_matrix.begin() + offset; + typename Graph::MatrixIter l = f + g.m_vertex_set.size(); + typename Graph::unfiltered_out_edge_iter + first(f, u, g.m_vertex_set.size()) + , last(l, u, g.m_vertex_set.size()); + detail::does_edge_exist pred; + typedef typename Graph::out_edge_iterator out_edge_iterator; + return std::make_pair(out_edge_iterator(pred, first, last), + out_edge_iterator(pred, last, last)); + } + + // O(1) + template + std::pair< + typename adjacency_matrix::out_edge_iterator, + typename adjacency_matrix::out_edge_iterator> + out_edges + (typename adjacency_matrix::vertex_descriptor u, + const adjacency_matrix& g_) + { + typedef adjacency_matrix Graph; + Graph& g = const_cast(g_); + typename Graph::vertices_size_type offset = u * (u + 1) / 2; + typename Graph::MatrixIter f = g.m_matrix.begin() + offset; + typename Graph::MatrixIter l = g.m_matrix.end(); + + typename Graph::unfiltered_out_edge_iter + first(f, u, g.m_vertex_set.size()) + , last(l, u, g.m_vertex_set.size()); + + detail::does_edge_exist pred; + typedef typename Graph::out_edge_iterator out_edge_iterator; + return std::make_pair(out_edge_iterator(pred, first, last), + out_edge_iterator(pred, last, last)); + } + + // O(N) + template + typename adjacency_matrix::degree_size_type + out_degree(typename adjacency_matrix::vertex_descriptor u, + const adjacency_matrix& g) + { + typename adjacency_matrix::degree_size_type n = 0; + typename adjacency_matrix::out_edge_iterator f, l; + for (tie(f, l) = out_edges(u, g); f != l; ++f) + ++n; + return n; + } + + // O(1) + template + typename adjacency_matrix::vertex_descriptor + source(const detail::matrix_edge_desc_impl& e, + const adjacency_matrix&) + { + return e.m_source; + } + + // O(1) + template + typename adjacency_matrix::vertex_descriptor + target(const detail::matrix_edge_desc_impl& e, + const adjacency_matrix&) + { + return e.m_target; + } + + //========================================================================= + // Functions required by the BidirectionalGraph concept + + // O(1) + template + std::pair::in_edge_iterator, + typename adjacency_matrix::in_edge_iterator> + in_edges + (typename adjacency_matrix::vertex_descriptor u, + const adjacency_matrix& g_) + { + typedef adjacency_matrix Graph; + Graph& g = const_cast(g_); + typename Graph::MatrixIter f = g.m_matrix.begin() + u; + typename Graph::MatrixIter l = g.m_matrix.end(); + typename Graph::unfiltered_in_edge_iter + first(f, l, u, g.m_vertex_set.size()) + , last(l, l, u, g.m_vertex_set.size()); + detail::does_edge_exist pred; + typedef typename Graph::in_edge_iterator in_edge_iterator; + return std::make_pair(in_edge_iterator(pred, first, last), + in_edge_iterator(pred, last, last)); + } + + // O(1) + template + std::pair< + typename adjacency_matrix::in_edge_iterator, + typename adjacency_matrix::in_edge_iterator> + in_edges + (typename adjacency_matrix::vertex_descriptor u, + const adjacency_matrix& g_) + { + typedef adjacency_matrix Graph; + Graph& g = const_cast(g_); + typename Graph::vertices_size_type offset = u * (u + 1) / 2; + typename Graph::MatrixIter f = g.m_matrix.begin() + offset; + typename Graph::MatrixIter l = g.m_matrix.end(); + + typename Graph::unfiltered_in_edge_iter + first(f, u, g.m_vertex_set.size()) + , last(l, u, g.m_vertex_set.size()); + + detail::does_edge_exist pred; + typedef typename Graph::in_edge_iterator in_edge_iterator; + return std::make_pair(in_edge_iterator(pred, first, last), + in_edge_iterator(pred, last, last)); + } + + // O(N) + template + typename adjacency_matrix::degree_size_type + in_degree(typename adjacency_matrix::vertex_descriptor u, + const adjacency_matrix& g) + { + typename adjacency_matrix::degree_size_type n = 0; + typename adjacency_matrix::in_edge_iterator f, l; + for (tie(f, l) = in_edges(u, g); f != l; ++f) + ++n; + return n; + } + + //========================================================================= + // Functions required by the AdjacencyGraph concept + + template + std::pair::adjacency_iterator, + typename adjacency_matrix::adjacency_iterator> + adjacent_vertices + (typename adjacency_matrix::vertex_descriptor u, + const adjacency_matrix& g_) + { + typedef adjacency_matrix Graph; + const Graph& cg = static_cast(g_); + Graph& g = const_cast(cg); + typedef typename Graph::adjacency_iterator adjacency_iterator; + typename Graph::out_edge_iterator first, last; + boost::tie(first, last) = out_edges(u, g); + return std::make_pair(adjacency_iterator(first, &g), + adjacency_iterator(last, &g)); + } + + //========================================================================= + // Functions required by the VertexListGraph concept + + template + std::pair::vertex_iterator, + typename adjacency_matrix::vertex_iterator> + vertices(const adjacency_matrix& g_) { + typedef adjacency_matrix Graph; + Graph& g = const_cast(g_); + return std::make_pair(g.m_vertex_set.begin(), g.m_vertex_set.end()); + } + + template + typename adjacency_matrix::vertices_size_type + num_vertices(const adjacency_matrix& g) { + return g.m_vertex_set.size(); + } + + //========================================================================= + // Functions required by the EdgeListGraph concept + + template + std::pair::edge_iterator, + typename adjacency_matrix::edge_iterator> + edges(const adjacency_matrix& g_) + { + typedef adjacency_matrix Graph; + Graph& g = const_cast(g_); + + typename Graph::unfiltered_edge_iter + first(g.m_matrix.begin(), g.m_matrix.begin(), + g.m_vertex_set.size()), + last(g.m_matrix.end(), g.m_matrix.begin(), + g.m_vertex_set.size()); + detail::does_edge_exist pred; + typedef typename Graph::edge_iterator edge_iterator; + return std::make_pair(edge_iterator(pred, first, last), + edge_iterator(pred, last, last)); + } + + // O(1) + template + typename adjacency_matrix::edges_size_type + num_edges(const adjacency_matrix& g) + { + return g.m_num_edges; + } + + //========================================================================= + // Functions required by the MutableGraph concept + + // O(1) + template + std::pair::edge_descriptor, bool> + add_edge(typename adjacency_matrix::vertex_descriptor u, + typename adjacency_matrix::vertex_descriptor v, + const EP& ep, + adjacency_matrix& g) + { + typedef typename adjacency_matrix::edge_descriptor + edge_descriptor; + if (detail::get_edge_exists(g.get_edge(u,v), 0) == false) { + ++(g.m_num_edges); + detail::set_property(g.get_edge(u,v), ep, 0); + detail::set_edge_exists(g.get_edge(u,v), true, 0); + return std::make_pair + (edge_descriptor(true, u, v, &detail::get_property(g.get_edge(u,v))), + true); + } else + return std::make_pair + (edge_descriptor(true, u, v, &detail::get_property(g.get_edge(u,v))), + false); + } + // O(1) + template + std::pair::edge_descriptor, bool> + add_edge(typename adjacency_matrix::vertex_descriptor u, + typename adjacency_matrix::vertex_descriptor v, + adjacency_matrix& g) + { + EP ep; + return add_edge(u, v, ep, g); + } + + // O(1) + template + void + remove_edge(typename adjacency_matrix::vertex_descriptor u, + typename adjacency_matrix::vertex_descriptor v, + adjacency_matrix& g) + { + --(g.m_num_edges); + detail::set_edge_exists(g.get_edge(u,v), false, 0); + } + + // O(1) + template + void + remove_edge(typename adjacency_matrix::edge_descriptor e, + adjacency_matrix& g) + { + remove_edge(source(e, g), target(e, g), g); + } + + + template + inline typename adjacency_matrix::vertex_descriptor + add_vertex(adjacency_matrix& g) { + // UNDER CONSTRUCTION + assert(false); + return *vertices(g).first; + } + + template + inline typename adjacency_matrix::vertex_descriptor + add_vertex(const VP& vp, adjacency_matrix& g) { + // UNDER CONSTRUCTION + assert(false); + return *vertices(g).first; + } + + template + inline void + remove_vertex(typename adjacency_matrix::vertex_descriptor u, + adjacency_matrix& g) + { + // UNDER CONSTRUCTION + assert(false); + } + + // O(V) + template + void + clear_vertex + (typename adjacency_matrix::vertex_descriptor u, + adjacency_matrix& g) + { + typename adjacency_matrix::vertex_iterator + vi, vi_end; + for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + remove_edge(u, *vi, g); + for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + remove_edge(*vi, u, g); + } + + // O(V) + template + void + clear_vertex + (typename adjacency_matrix::vertex_descriptor u, + adjacency_matrix& g) + { + typename adjacency_matrix::vertex_iterator + vi, vi_end; + for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + remove_edge(u, *vi, g); + } + + //========================================================================= + // Vertex Property Map + + template + class adj_matrix_vertex_property_map + : public put_get_helper > + { + public: + typedef T value_type; + typedef R reference; + typedef Vertex key_type; + typedef boost::lvalue_property_map_tag category; + adj_matrix_vertex_property_map() { } + adj_matrix_vertex_property_map(GraphPtr g) : m_g(g) { } + inline reference operator[](key_type v) const { + return get_property_value(m_g->m_vertex_properties[v], Tag()); + } + GraphPtr m_g; + }; + + template + struct adj_matrix_vertex_id_map + : public boost::put_get_helper > + { + typedef Vertex value_type; + typedef Vertex reference; + typedef Vertex key_type; + typedef boost::readable_property_map_tag category; + adj_matrix_vertex_id_map() { } + template + inline adj_matrix_vertex_id_map(const Graph&) { } + inline value_type operator[](key_type v) const { return v; } + }; + + namespace detail { + + struct adj_matrix_any_vertex_pa { + template + struct bind_ { + typedef typename property_value::type Value; + typedef typename boost::graph_traits::vertex_descriptor Vertex; + + typedef adj_matrix_vertex_property_map type; + typedef adj_matrix_vertex_property_map const_type; + }; + }; + struct adj_matrix_id_vertex_pa { + template + struct bind_ { + typedef typename Graph::vertex_descriptor Vertex; + typedef adj_matrix_vertex_id_map type; + typedef adj_matrix_vertex_id_map const_type; + }; + }; + + template + struct adj_matrix_choose_vertex_pa_helper { + typedef adj_matrix_any_vertex_pa type; + }; + template <> + struct adj_matrix_choose_vertex_pa_helper { + typedef adj_matrix_id_vertex_pa type; + }; + + template + struct adj_matrix_choose_vertex_pa { + typedef typename adj_matrix_choose_vertex_pa_helper::type Helper; + typedef typename Helper::template bind_ Bind; + typedef typename Bind::type type; + typedef typename Bind::const_type const_type; + }; + + struct adj_matrix_vertex_property_selector { + template + struct bind_ { + typedef adj_matrix_choose_vertex_pa Choice; + typedef typename Choice::type type; + typedef typename Choice::const_type const_type; + }; + }; + + } // namespace detail + + template <> + struct vertex_property_selector { + typedef detail::adj_matrix_vertex_property_selector type; + }; + + //========================================================================= + // Edge Property Map + + + template + class adj_matrix_edge_property_map + : public put_get_helper > + { + public: + typedef T value_type; + typedef R reference; + typedef detail::matrix_edge_desc_impl key_type; + typedef boost::lvalue_property_map_tag category; + inline reference operator[](key_type e) const { + Property& p = *(Property*)e.get_property(); + return get_property_value(p, Tag()); + } + }; + struct adj_matrix_edge_property_selector { + template + struct bind_ { + typedef typename property_value::type T; + typedef typename Graph::vertex_descriptor Vertex; + typedef adj_matrix_edge_property_map type; + typedef adj_matrix_edge_property_map const_type; + }; + }; + template <> + struct edge_property_selector { + typedef adj_matrix_edge_property_selector type; + }; + + //========================================================================= + // Functions required by PropertyGraph + + namespace detail { + + template + typename boost::property_map, + Property>::type + get_dispatch(adjacency_matrix& g, Property, + vertex_property_tag) + { + typedef adjacency_matrix Graph; + typedef typename boost::property_map, + Property>::type PA; + return PA(&g); + } + template + typename boost::property_map, + Property>::type + get_dispatch(adjacency_matrix&, Property, + edge_property_tag) + { + typedef typename boost::property_map, + Property>::type PA; + return PA(); + } + template + typename boost::property_map, + Property>::const_type + get_dispatch(const adjacency_matrix& g, Property, + vertex_property_tag) + { + typedef adjacency_matrix Graph; + typedef typename boost::property_map, + Property>::const_type PA; + return PA(&g); + } + template + typename boost::property_map, + Property>::const_type + get_dispatch(const adjacency_matrix&, Property, + edge_property_tag) + { + typedef typename boost::property_map, + Property>::const_type PA; + return PA(); + } + + } // namespace detail + + template + inline + typename property_map, Property>::type + get(Property p, adjacency_matrix& g) + { + typedef typename property_kind::type Kind; + return detail::get_dispatch(g, p, Kind()); + } + + template + inline + typename property_map, Property>::const_type + get(Property p, const adjacency_matrix& g) + { + typedef typename property_kind::type Kind; + return detail::get_dispatch(g, p, Kind()); + } + + template + inline + typename property_traits< + typename property_map, Property>::const_type + >::value_type + get(Property p, const adjacency_matrix& g, + const Key& key) + { + return get(get(p, g), key); + } + + template + inline void + put(Property p, adjacency_matrix& g, + const Key& key, const Value& value) + { + typedef adjacency_matrix Graph; + typedef typename boost::property_map::type Map; + Map pmap = get(p, g); + put(pmap, key, value); + } + + //========================================================================= + // Other Functions + + template + typename adjacency_matrix::vertex_descriptor + vertex(typename adjacency_matrix::vertices_size_type n, + const adjacency_matrix& g) + { + return n; + } + + // Support for bundled properties +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + template + inline + typename property_map, + T Bundle::*>::type + get(T Bundle::* p, adjacency_matrix& g) + { + typedef typename property_map, + T Bundle::*>::type + result_type; + return result_type(&g, p); + } + + template + inline + typename property_map, + T Bundle::*>::const_type + get(T Bundle::* p, adjacency_matrix const & g) + { + typedef typename property_map, + T Bundle::*>::const_type + result_type; + return result_type(&g, p); + } + + template + inline T + get(T Bundle::* p, adjacency_matrix const & g, + const Key& key) + { + return get(get(p, g), key); + } + + template + inline void + put(T Bundle::* p, adjacency_matrix& g, + const Key& key, const T& value) + { + put(get(p, g), key, value); + } + +#endif + +} // namespace boost + +#endif // BOOST_ADJACENCY_MATRIX_HPP diff --git a/win32/include/boost/graph/astar_search.hpp b/win32/include/boost/graph/astar_search.hpp new file mode 100755 index 000000000..aa8b490a5 --- /dev/null +++ b/win32/include/boost/graph/astar_search.hpp @@ -0,0 +1,407 @@ + + +// +//======================================================================= +// Copyright (c) 2004 Kristopher Beevers +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +#ifndef BOOST_GRAPH_ASTAR_SEARCH_HPP +#define BOOST_GRAPH_ASTAR_SEARCH_HPP + + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { + + + template + struct AStarHeuristicConcept { + void constraints() + { + function_requires< CopyConstructibleConcept >(); + h(u); + } + Heuristic h; + typename graph_traits::vertex_descriptor u; + }; + + + template + class astar_heuristic : public std::unary_function< + typename graph_traits::vertex_descriptor, CostType> + { + public: + typedef typename graph_traits::vertex_descriptor Vertex; + astar_heuristic() {} + CostType operator()(Vertex u) { return static_cast(0); } + }; + + + + template + struct AStarVisitorConcept { + void constraints() + { + function_requires< CopyConstructibleConcept >(); + vis.initialize_vertex(u, g); + vis.discover_vertex(u, g); + vis.examine_vertex(u, g); + vis.examine_edge(e, g); + vis.edge_relaxed(e, g); + vis.edge_not_relaxed(e, g); + vis.black_target(e, g); + vis.finish_vertex(u, g); + } + Visitor vis; + Graph g; + typename graph_traits::vertex_descriptor u; + typename graph_traits::edge_descriptor e; + }; + + + template + class astar_visitor : public bfs_visitor { + public: + astar_visitor() {} + astar_visitor(Visitors vis) + : bfs_visitor(vis) {} + + template + void edge_relaxed(Edge e, Graph& g) { + invoke_visitors(this->m_vis, e, g, on_edge_relaxed()); + } + template + void edge_not_relaxed(Edge e, Graph& g) { + invoke_visitors(this->m_vis, e, g, on_edge_not_relaxed()); + } + private: + template + void tree_edge(Edge e, Graph& g) {} + template + void non_tree_edge(Edge e, Graph& g) {} + }; + template + astar_visitor + make_astar_visitor(Visitors vis) { + return astar_visitor(vis); + } + typedef astar_visitor<> default_astar_visitor; + + + namespace detail { + + template + struct astar_bfs_visitor + { + + typedef typename property_traits::value_type C; + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + typedef typename property_traits::value_type distance_type; + + astar_bfs_visitor(AStarHeuristic h, UniformCostVisitor vis, + UpdatableQueue& Q, PredecessorMap p, + CostMap c, DistanceMap d, WeightMap w, + ColorMap col, BinaryFunction combine, + BinaryPredicate compare, C zero) + : m_h(h), m_vis(vis), m_Q(Q), m_predecessor(p), m_cost(c), + m_distance(d), m_weight(w), m_color(col), + m_combine(combine), m_compare(compare), m_zero(zero) {} + + + template + void initialize_vertex(Vertex u, Graph& g) { + m_vis.initialize_vertex(u, g); + } + template + void discover_vertex(Vertex u, Graph& g) { + m_vis.discover_vertex(u, g); + } + template + void examine_vertex(Vertex u, Graph& g) { + m_vis.examine_vertex(u, g); + } + template + void finish_vertex(Vertex u, Graph& g) { + m_vis.finish_vertex(u, g); + } + template + void examine_edge(Edge e, Graph& g) { + if (m_compare(get(m_weight, e), m_zero)) + throw negative_edge(); + m_vis.examine_edge(e, g); + } + template + void non_tree_edge(Edge, Graph&) {} + + + + template + void tree_edge(Edge e, Graph& g) { + m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); + + if(m_decreased) { + m_vis.edge_relaxed(e, g); + put(m_cost, target(e, g), + m_combine(get(m_distance, target(e, g)), + m_h(target(e, g)))); + } else + m_vis.edge_not_relaxed(e, g); + } + + + template + void gray_target(Edge e, Graph& g) { + distance_type old_distance = get(m_distance, target(e, g)); + + m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); + + /* On x86 Linux with optimization, we sometimes get into a + horrible case where m_decreased is true but the distance hasn't + actually changed. This occurs when the comparison inside + relax() occurs with the 80-bit precision of the x87 floating + point unit, but the difference is lost when the resulting + values are written back to lower-precision memory (e.g., a + double). With the eager Dijkstra's implementation, this results + in looping. */ + if(m_decreased && old_distance != get(m_distance, target(e, g))) { + put(m_cost, target(e, g), + m_combine(get(m_distance, target(e, g)), + m_h(target(e, g)))); + m_Q.update(target(e, g)); + m_vis.edge_relaxed(e, g); + } else + m_vis.edge_not_relaxed(e, g); + } + + + template + void black_target(Edge e, Graph& g) { + distance_type old_distance = get(m_distance, target(e, g)); + + m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); + + /* See comment in gray_target */ + if(m_decreased && old_distance != get(m_distance, target(e, g))) { + m_vis.edge_relaxed(e, g); + put(m_cost, target(e, g), + m_combine(get(m_distance, target(e, g)), + m_h(target(e, g)))); + m_Q.push(target(e, g)); + put(m_color, target(e, g), Color::gray()); + m_vis.black_target(e, g); + } else + m_vis.edge_not_relaxed(e, g); + } + + + + AStarHeuristic m_h; + UniformCostVisitor m_vis; + UpdatableQueue& m_Q; + PredecessorMap m_predecessor; + CostMap m_cost; + DistanceMap m_distance; + WeightMap m_weight; + ColorMap m_color; + BinaryFunction m_combine; + BinaryPredicate m_compare; + bool m_decreased; + C m_zero; + + }; + + } // namespace detail + + + + template + inline void + astar_search_no_init + (VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, + PredecessorMap predecessor, CostMap cost, + DistanceMap distance, WeightMap weight, + ColorMap color, VertexIndexMap index_map, + CompareFunction compare, CombineFunction combine, + CostInf inf, CostZero zero) + { + typedef indirect_cmp IndirectCmp; + IndirectCmp icmp(cost, compare); + + typedef typename graph_traits::vertex_descriptor + Vertex; + typedef mutable_queue, + IndirectCmp, VertexIndexMap> + MutableQueue; + MutableQueue Q(num_vertices(g), icmp, index_map); + + detail::astar_bfs_visitor + bfs_vis(h, vis, Q, predecessor, cost, distance, weight, + color, combine, compare, zero); + + breadth_first_visit(g, s, Q, bfs_vis, color); + } + + + // Non-named parameter interface + template + inline void + astar_search + (VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, + PredecessorMap predecessor, CostMap cost, + DistanceMap distance, WeightMap weight, + VertexIndexMap index_map, ColorMap color, + CompareFunction compare, CombineFunction combine, + CostInf inf, CostZero zero) + { + + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + typename graph_traits::vertex_iterator ui, ui_end; + for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) { + put(color, *ui, Color::white()); + put(distance, *ui, inf); + put(cost, *ui, inf); + put(predecessor, *ui, *ui); + vis.initialize_vertex(*ui, g); + } + put(distance, s, zero); + put(cost, s, h(s)); + + astar_search_no_init + (g, s, h, vis, predecessor, cost, distance, weight, + color, index_map, compare, combine, inf, zero); + + } + + + + namespace detail { + template + inline void + astar_dispatch2 + (VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, CostMap cost, DistanceMap distance, + WeightMap weight, IndexMap index_map, ColorMap color, + const Params& params) + { + dummy_property_map p_map; + typedef typename property_traits::value_type C; + astar_search + (g, s, h, + choose_param(get_param(params, graph_visitor), + make_astar_visitor(null_visitor())), + choose_param(get_param(params, vertex_predecessor), p_map), + cost, distance, weight, index_map, color, + choose_param(get_param(params, distance_compare_t()), + std::less()), + choose_param(get_param(params, distance_combine_t()), + closed_plus()), + choose_param(get_param(params, distance_inf_t()), + std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION ()), + choose_param(get_param(params, distance_zero_t()), + C())); + } + + template + inline void + astar_dispatch1 + (VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, CostMap cost, DistanceMap distance, + WeightMap weight, IndexMap index_map, ColorMap color, + const Params& params) + { + typedef typename property_traits::value_type D; + typename std::vector::size_type + n = is_default_param(distance) ? num_vertices(g) : 1; + std::vector distance_map(n); + n = is_default_param(cost) ? num_vertices(g) : 1; + std::vector cost_map(n); + std::vector color_map(num_vertices(g)); + default_color_type c = white_color; + + detail::astar_dispatch2 + (g, s, h, + choose_param(cost, make_iterator_property_map + (cost_map.begin(), index_map, + cost_map[0])), + choose_param(distance, make_iterator_property_map + (distance_map.begin(), index_map, + distance_map[0])), + weight, index_map, + choose_param(color, make_iterator_property_map + (color_map.begin(), index_map, c)), + params); + } + } // namespace detail + + + // Named parameter interface + template + void + astar_search + (VertexListGraph &g, + typename graph_traits::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params& params) + { + + detail::astar_dispatch1 + (g, s, h, + get_param(params, vertex_rank), + get_param(params, vertex_distance), + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index), + get_param(params, vertex_color), + params); + + } + +} // namespace boost + +#endif // BOOST_GRAPH_ASTAR_SEARCH_HPP diff --git a/win32/include/boost/graph/bandwidth.hpp b/win32/include/boost/graph/bandwidth.hpp new file mode 100755 index 000000000..97fd2c644 --- /dev/null +++ b/win32/include/boost/graph/bandwidth.hpp @@ -0,0 +1,83 @@ +// Copyright (c) Jeremy Siek 2001, Marc Wintermantel 2002 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_BANDWIDTH_HPP +#define BOOST_GRAPH_BANDWIDTH_HPP + +#include // for std::min and std::max +#include +#include +#include + +namespace boost { + + template + typename graph_traits::vertices_size_type + ith_bandwidth(typename graph_traits::vertex_descriptor i, + const Graph& g, + VertexIndexMap index) + { + BOOST_USING_STD_MAX(); + typedef typename graph_traits::vertices_size_type size_type; + size_type b = 0; + typename graph_traits::out_edge_iterator e, end; + for (tie(e, end) = out_edges(i, g); e != end; ++e) { + int f_i = get(index, i); + int f_j = get(index, target(*e, g)); + using namespace std; // to call abs() unqualified + if(f_i > f_j) + b = max BOOST_PREVENT_MACRO_SUBSTITUTION (b, size_type(f_i - f_j)); + } + return b; + } + + template + typename graph_traits::vertices_size_type + ith_bandwidth(typename graph_traits::vertex_descriptor i, + const Graph& g) + { + return ith_bandwidth(i, g, get(vertex_index, g)); + } + + template + typename graph_traits::vertices_size_type + bandwidth(const Graph& g, VertexIndexMap index) + { + BOOST_USING_STD_MAX(); + typename graph_traits::vertices_size_type b = 0; + typename graph_traits::vertex_iterator i, end; + for (tie(i, end) = vertices(g); i != end; ++i) + b = max BOOST_PREVENT_MACRO_SUBSTITUTION (b, ith_bandwidth(*i, g, index)); + return b; + } + + template + typename graph_traits::vertices_size_type + bandwidth(const Graph& g) + { + return bandwidth(g, get(vertex_index, g)); + } + + template + typename graph_traits::vertices_size_type + edgesum(const Graph& g, VertexIndexMap index_map) + { + typedef typename graph_traits::vertices_size_type size_type; + typedef typename detail::numeric_traits::difference_type diff_t; + size_type sum = 0; + typename graph_traits::edge_iterator i, end; + for (tie(i, end) = edges(g); i != end; ++i) { + diff_t f_u = get(index_map, source(*i, g)); + diff_t f_v = get(index_map, target(*i, g)); + using namespace std; // to call abs() unqualified + sum += abs(f_u - f_v); + } + return sum; + } + +} // namespace boost + +#endif // BOOST_GRAPH_BANDWIDTH_HPP diff --git a/win32/include/boost/graph/bc_clustering.hpp b/win32/include/boost/graph/bc_clustering.hpp new file mode 100755 index 000000000..b84e7de7b --- /dev/null +++ b/win32/include/boost/graph/bc_clustering.hpp @@ -0,0 +1,164 @@ +// Copyright 2004 The Trustees of Indiana University. + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_BETWEENNESS_CENTRALITY_CLUSTERING_HPP +#define BOOST_GRAPH_BETWEENNESS_CENTRALITY_CLUSTERING_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { + +/** Threshold termination function for the betweenness centrality + * clustering algorithm. + */ +template +struct bc_clustering_threshold +{ + typedef T centrality_type; + + /// Terminate clustering when maximum absolute edge centrality is + /// below the given threshold. + explicit bc_clustering_threshold(T threshold) + : threshold(threshold), dividend(1.0) {} + + /** + * Terminate clustering when the maximum edge centrality is below + * the given threshold. + * + * @param threshold the threshold value + * + * @param g the graph on which the threshold will be calculated + * + * @param normalize when true, the threshold is compared against the + * normalized edge centrality based on the input graph; otherwise, + * the threshold is compared against the absolute edge centrality. + */ + template + bc_clustering_threshold(T threshold, const Graph& g, bool normalize = true) + : threshold(threshold), dividend(1.0) + { + if (normalize) { + typename graph_traits::vertices_size_type n = num_vertices(g); + dividend = T((n - 1) * (n - 2)) / T(2); + } + } + + /** Returns true when the given maximum edge centrality (potentially + * normalized) falls below the threshold. + */ + template + bool operator()(T max_centrality, Edge, const Graph&) + { + return (max_centrality / dividend) < threshold; + } + + protected: + T threshold; + T dividend; +}; + +/** Graph clustering based on edge betweenness centrality. + * + * This algorithm implements graph clustering based on edge + * betweenness centrality. It is an iterative algorithm, where in each + * step it compute the edge betweenness centrality (via @ref + * brandes_betweenness_centrality) and removes the edge with the + * maximum betweenness centrality. The @p done function object + * determines when the algorithm terminates (the edge found when the + * algorithm terminates will not be removed). + * + * @param g The graph on which clustering will be performed. The type + * of this parameter (@c MutableGraph) must be a model of the + * VertexListGraph, IncidenceGraph, EdgeListGraph, and Mutable Graph + * concepts. + * + * @param done The function object that indicates termination of the + * algorithm. It must be a ternary function object thats accepts the + * maximum centrality, the descriptor of the edge that will be + * removed, and the graph @p g. + * + * @param edge_centrality (UTIL/OUT) The property map that will store + * the betweenness centrality for each edge. When the algorithm + * terminates, it will contain the edge centralities for the + * graph. The type of this property map must model the + * ReadWritePropertyMap concept. Defaults to an @c + * iterator_property_map whose value type is + * @c Done::centrality_type and using @c get(edge_index, g) for the + * index map. + * + * @param vertex_index (IN) The property map that maps vertices to + * indices in the range @c [0, num_vertices(g)). This type of this + * property map must model the ReadablePropertyMap concept and its + * value type must be an integral type. Defaults to + * @c get(vertex_index, g). + */ +template +void +betweenness_centrality_clustering(MutableGraph& g, Done done, + EdgeCentralityMap edge_centrality, + VertexIndexMap vertex_index) +{ + typedef typename property_traits::value_type + centrality_type; + typedef typename graph_traits::edge_iterator edge_iterator; + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename graph_traits::vertices_size_type + vertices_size_type; + + if (edges(g).first == edges(g).second) return; + + // Function object that compares the centrality of edges + indirect_cmp > + cmp(edge_centrality); + + bool is_done; + do { + brandes_betweenness_centrality(g, + edge_centrality_map(edge_centrality) + .vertex_index_map(vertex_index)); + edge_descriptor e = *max_element(edges(g).first, edges(g).second, cmp); + is_done = done(get(edge_centrality, e), e, g); + if (!is_done) remove_edge(e, g); + } while (!is_done && edges(g).first != edges(g).second); +} + +/** + * \overload + */ +template +void +betweenness_centrality_clustering(MutableGraph& g, Done done, + EdgeCentralityMap edge_centrality) +{ + betweenness_centrality_clustering(g, done, edge_centrality, + get(vertex_index, g)); +} + +/** + * \overload + */ +template +void +betweenness_centrality_clustering(MutableGraph& g, Done done) +{ + typedef typename Done::centrality_type centrality_type; + std::vector edge_centrality(num_edges(g)); + betweenness_centrality_clustering(g, done, + make_iterator_property_map(edge_centrality.begin(), get(edge_index, g)), + get(vertex_index, g)); +} + +} // end namespace boost + +#endif // BOOST_GRAPH_BETWEENNESS_CENTRALITY_CLUSTERING_HPP diff --git a/win32/include/boost/graph/bellman_ford_shortest_paths.hpp b/win32/include/boost/graph/bellman_ford_shortest_paths.hpp new file mode 100755 index 000000000..91ba9d198 --- /dev/null +++ b/win32/include/boost/graph/bellman_ford_shortest_paths.hpp @@ -0,0 +1,241 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// 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) +//======================================================================= +// + +/* + This file implements the function + + template + bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N, + const bgl_named_params& params) + + */ + + +#ifndef BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP +#define BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + template + struct BellmanFordVisitorConcept { + void constraints() { + function_requires< CopyConstructibleConcept >(); + vis.examine_edge(e, g); + vis.edge_relaxed(e, g); + vis.edge_not_relaxed(e, g); + vis.edge_minimized(e, g); + vis.edge_not_minimized(e, g); + } + Visitor vis; + Graph g; + typename graph_traits::edge_descriptor e; + }; + + template + class bellman_visitor { + public: + bellman_visitor() { } + bellman_visitor(Visitors vis) : m_vis(vis) { } + + template + void examine_edge(Edge u, Graph& g) { + invoke_visitors(m_vis, u, g, on_examine_edge()); + } + template + void edge_relaxed(Edge u, Graph& g) { + invoke_visitors(m_vis, u, g, on_edge_relaxed()); + } + template + void edge_not_relaxed(Edge u, Graph& g) { + invoke_visitors(m_vis, u, g, on_edge_not_relaxed()); + } + template + void edge_minimized(Edge u, Graph& g) { + invoke_visitors(m_vis, u, g, on_edge_minimized()); + } + template + void edge_not_minimized(Edge u, Graph& g) { + invoke_visitors(m_vis, u, g, on_edge_not_minimized()); + } + protected: + Visitors m_vis; + }; + template + bellman_visitor + make_bellman_visitor(Visitors vis) { + return bellman_visitor(vis); + } + typedef bellman_visitor<> default_bellman_visitor; + + template + bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N, + WeightMap weight, + PredecessorMap pred, + DistanceMap distance, + BinaryFunction combine, + BinaryPredicate compare, + BellmanFordVisitor v) + { + function_requires >(); + typedef graph_traits GTraits; + typedef typename GTraits::edge_descriptor Edge; + typedef typename GTraits::vertex_descriptor Vertex; + function_requires >(); + function_requires >(); + typedef typename property_traits::value_type D_value; + typedef typename property_traits::value_type W_value; + + typename GTraits::edge_iterator i, end; + + for (Size k = 0; k < N; ++k) { + bool at_least_one_edge_relaxed = false; + for (tie(i, end) = edges(g); i != end; ++i) { + v.examine_edge(*i, g); + if (relax(*i, g, weight, pred, distance, combine, compare)) { + at_least_one_edge_relaxed = true; + v.edge_relaxed(*i, g); + } else + v.edge_not_relaxed(*i, g); + } + if (!at_least_one_edge_relaxed) + break; + } + + for (tie(i, end) = edges(g); i != end; ++i) + if (compare(combine(get(distance, source(*i, g)), get(weight, *i)), + get(distance, target(*i,g)))) + { + v.edge_not_minimized(*i, g); + return false; + } else + v.edge_minimized(*i, g); + + return true; + } + + namespace detail { + + template + bool + bellman_dispatch2 + (VertexAndEdgeListGraph& g, + typename graph_traits::vertex_descriptor s, + Size N, WeightMap weight, PredecessorMap pred, DistanceMap distance, + const bgl_named_params& params) + { + typedef typename property_traits::value_type D; + bellman_visitor<> null_vis; + typedef typename property_traits::value_type weight_type; + typename graph_traits::vertex_iterator v, v_end; + for (tie(v, v_end) = vertices(g); v != v_end; ++v) { + put(distance, *v, (std::numeric_limits::max)()); + put(pred, *v, *v); + } + put(distance, s, weight_type(0)); + return bellman_ford_shortest_paths + (g, N, weight, pred, distance, + choose_param(get_param(params, distance_combine_t()), + closed_plus()), + choose_param(get_param(params, distance_compare_t()), + std::less()), + choose_param(get_param(params, graph_visitor), + null_vis) + ); + } + + template + bool + bellman_dispatch2 + (VertexAndEdgeListGraph& g, + detail::error_property_not_found, + Size N, WeightMap weight, PredecessorMap pred, DistanceMap distance, + const bgl_named_params& params) + { + typedef typename property_traits::value_type D; + bellman_visitor<> null_vis; + return bellman_ford_shortest_paths + (g, N, weight, pred, distance, + choose_param(get_param(params, distance_combine_t()), + closed_plus()), + choose_param(get_param(params, distance_compare_t()), + std::less()), + choose_param(get_param(params, graph_visitor), + null_vis) + ); + } + + template + bool bellman_dispatch(EdgeListGraph& g, Size N, + WeightMap weight, DistanceMap distance, + const bgl_named_params& params) + { + dummy_property_map dummy_pred; + return + detail::bellman_dispatch2 + (g, + get_param(params, root_vertex_t()), + N, weight, + choose_param(get_param(params, vertex_predecessor), dummy_pred), + distance, + params); + } + } // namespace detail + + template + bool bellman_ford_shortest_paths + (EdgeListGraph& g, Size N, + const bgl_named_params& params) + { + return detail::bellman_dispatch + (g, N, + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + choose_pmap(get_param(params, vertex_distance), g, vertex_distance), + params); + } + + template + bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N) + { + bgl_named_params params(0); + return bellman_ford_shortest_paths(g, N, params); + } + + template + bool bellman_ford_shortest_paths + (VertexAndEdgeListGraph& g, + const bgl_named_params& params) + { + function_requires >(); + return detail::bellman_dispatch + (g, num_vertices(g), + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + choose_pmap(get_param(params, vertex_distance), g, vertex_distance), + params); + } +} // namespace boost + +#endif // BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP diff --git a/win32/include/boost/graph/betweenness_centrality.hpp b/win32/include/boost/graph/betweenness_centrality.hpp new file mode 100755 index 000000000..68961558e --- /dev/null +++ b/win32/include/boost/graph/betweenness_centrality.hpp @@ -0,0 +1,597 @@ +// Copyright 2004 The Trustees of Indiana University. + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP +#define BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + +namespace detail { namespace graph { + + /** + * Customized visitor passed to Dijkstra's algorithm by Brandes' + * betweenness centrality algorithm. This visitor is responsible for + * keeping track of the order in which vertices are discovered, the + * predecessors on the shortest path(s) to a vertex, and the number + * of shortest paths. + */ + template + struct brandes_dijkstra_visitor : public bfs_visitor<> + { + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::edge_descriptor edge_descriptor; + + brandes_dijkstra_visitor(std::stack& ordered_vertices, + WeightMap weight, + IncomingMap incoming, + DistanceMap distance, + PathCountMap path_count) + : ordered_vertices(ordered_vertices), weight(weight), + incoming(incoming), distance(distance), + path_count(path_count) + { } + + /** + * Whenever an edge e = (v, w) is relaxed, the incoming edge list + * for w is set to {(v, w)} and the shortest path count of w is set to + * the number of paths that reach {v}. + */ + void edge_relaxed(edge_descriptor e, const Graph& g) + { + vertex_descriptor v = source(e, g), w = target(e, g); + incoming[w].clear(); + incoming[w].push_back(e); + put(path_count, w, get(path_count, v)); + } + + /** + * If an edge e = (v, w) was not relaxed, it may still be the case + * that we've found more equally-short paths, so include {(v, w)} in the + * incoming edges of w and add all of the shortest paths to v to the + * shortest path count of w. + */ + void edge_not_relaxed(edge_descriptor e, const Graph& g) + { + typedef typename property_traits::value_type weight_type; + typedef typename property_traits::value_type distance_type; + vertex_descriptor v = source(e, g), w = target(e, g); + distance_type d_v = get(distance, v), d_w = get(distance, w); + weight_type w_e = get(weight, e); + + closed_plus combine; + if (d_w == combine(d_v, w_e)) { + put(path_count, w, get(path_count, w) + get(path_count, v)); + incoming[w].push_back(e); + } + } + + /// Keep track of vertices as they are reached + void examine_vertex(vertex_descriptor w, const Graph&) + { + ordered_vertices.push(w); + } + + private: + std::stack& ordered_vertices; + WeightMap weight; + IncomingMap incoming; + DistanceMap distance; + PathCountMap path_count; + }; + + /** + * Function object that calls Dijkstra's shortest paths algorithm + * using the Dijkstra visitor for the Brandes betweenness centrality + * algorithm. + */ + template + struct brandes_dijkstra_shortest_paths + { + brandes_dijkstra_shortest_paths(WeightMap weight_map) + : weight_map(weight_map) { } + + template + void + operator()(Graph& g, + typename graph_traits::vertex_descriptor s, + std::stack::vertex_descriptor>& ov, + IncomingMap incoming, + DistanceMap distance, + PathCountMap path_count, + VertexIndexMap vertex_index) + { + typedef brandes_dijkstra_visitor visitor_type; + visitor_type visitor(ov, weight_map, incoming, distance, path_count); + + dijkstra_shortest_paths(g, s, + boost::weight_map(weight_map) + .vertex_index_map(vertex_index) + .distance_map(distance) + .visitor(visitor)); + } + + private: + WeightMap weight_map; + }; + + /** + * Function object that invokes breadth-first search for the + * unweighted form of the Brandes betweenness centrality algorithm. + */ + struct brandes_unweighted_shortest_paths + { + /** + * Customized visitor passed to breadth-first search, which + * records predecessor and the number of shortest paths to each + * vertex. + */ + template + struct visitor_type : public bfs_visitor<> + { + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename graph_traits::vertex_descriptor + vertex_descriptor; + + visitor_type(IncomingMap incoming, DistanceMap distance, + PathCountMap path_count, + std::stack& ordered_vertices) + : incoming(incoming), distance(distance), + path_count(path_count), ordered_vertices(ordered_vertices) { } + + /// Keep track of vertices as they are reached + void examine_vertex(vertex_descriptor v, Graph&) + { + ordered_vertices.push(v); + } + + /** + * Whenever an edge e = (v, w) is labelled a tree edge, the + * incoming edge list for w is set to {(v, w)} and the shortest + * path count of w is set to the number of paths that reach {v}. + */ + void tree_edge(edge_descriptor e, Graph& g) + { + vertex_descriptor v = source(e, g); + vertex_descriptor w = target(e, g); + put(distance, w, get(distance, v) + 1); + + put(path_count, w, get(path_count, v)); + incoming[w].push_back(e); + } + + /** + * If an edge e = (v, w) is not a tree edge, it may still be the + * case that we've found more equally-short paths, so include (v, w) + * in the incoming edge list of w and add all of the shortest + * paths to v to the shortest path count of w. + */ + void non_tree_edge(edge_descriptor e, Graph& g) + { + vertex_descriptor v = source(e, g); + vertex_descriptor w = target(e, g); + if (get(distance, w) == get(distance, v) + 1) { + put(path_count, w, get(path_count, w) + get(path_count, v)); + incoming[w].push_back(e); + } + } + + private: + IncomingMap incoming; + DistanceMap distance; + PathCountMap path_count; + std::stack& ordered_vertices; + }; + + template + void + operator()(Graph& g, + typename graph_traits::vertex_descriptor s, + std::stack::vertex_descriptor>& ov, + IncomingMap incoming, + DistanceMap distance, + PathCountMap path_count, + VertexIndexMap vertex_index) + { + typedef typename graph_traits::vertex_descriptor + vertex_descriptor; + + visitor_type + visitor(incoming, distance, path_count, ov); + + std::vector + colors(num_vertices(g), color_traits::white()); + boost::queue Q; + breadth_first_visit(g, s, Q, visitor, + make_iterator_property_map(colors.begin(), + vertex_index)); + } + }; + + // When the edge centrality map is a dummy property map, no + // initialization is needed. + template + inline void + init_centrality_map(std::pair, dummy_property_map) { } + + // When we have a real edge centrality map, initialize all of the + // centralities to zero. + template + void + init_centrality_map(std::pair keys, Centrality centrality_map) + { + typedef typename property_traits::value_type + centrality_type; + while (keys.first != keys.second) { + put(centrality_map, *keys.first, centrality_type(0)); + ++keys.first; + } + } + + // When the edge centrality map is a dummy property map, no update + // is performed. + template + inline void + update_centrality(dummy_property_map, const Key&, const T&) { } + + // When we have a real edge centrality map, add the value to the map + template + inline void + update_centrality(CentralityMap centrality_map, Key k, const T& x) + { put(centrality_map, k, get(centrality_map, k) + x); } + + template + inline void + divide_centrality_by_two(std::pair, dummy_property_map) {} + + template + inline void + divide_centrality_by_two(std::pair keys, + CentralityMap centrality_map) + { + typename property_traits::value_type two(2); + while (keys.first != keys.second) { + put(centrality_map, *keys.first, get(centrality_map, *keys.first) / two); + ++keys.first; + } + } + + template + void + brandes_betweenness_centrality_impl(const Graph& g, + CentralityMap centrality, // C_B + EdgeCentralityMap edge_centrality_map, + IncomingMap incoming, // P + DistanceMap distance, // d + DependencyMap dependency, // delta + PathCountMap path_count, // sigma + VertexIndexMap vertex_index, + ShortestPaths shortest_paths) + { + typedef typename graph_traits::vertex_iterator vertex_iterator; + typedef typename graph_traits::edge_iterator edge_iterator; + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + + // Initialize centrality + init_centrality_map(vertices(g), centrality); + init_centrality_map(edges(g), edge_centrality_map); + + std::stack ordered_vertices; + vertex_iterator s, s_end; + for (tie(s, s_end) = vertices(g); s != s_end; ++s) { + // Initialize for this iteration + vertex_iterator w, w_end; + for (tie(w, w_end) = vertices(g); w != w_end; ++w) { + incoming[*w].clear(); + put(path_count, *w, 0); + put(dependency, *w, 0); + } + put(path_count, *s, 1); + + // Execute the shortest paths algorithm. This will be either + // Dijkstra's algorithm or a customized breadth-first search, + // depending on whether the graph is weighted or unweighted. + shortest_paths(g, *s, ordered_vertices, incoming, distance, + path_count, vertex_index); + + while (!ordered_vertices.empty()) { + vertex_descriptor w = ordered_vertices.top(); + ordered_vertices.pop(); + + typedef typename property_traits::value_type + incoming_type; + typedef typename incoming_type::iterator incoming_iterator; + typedef typename property_traits::value_type + dependency_type; + + for (incoming_iterator vw = incoming[w].begin(); + vw != incoming[w].end(); ++vw) { + vertex_descriptor v = source(*vw, g); + dependency_type factor = dependency_type(get(path_count, v)) + / dependency_type(get(path_count, w)); + factor *= (dependency_type(1) + get(dependency, w)); + put(dependency, v, get(dependency, v) + factor); + update_centrality(edge_centrality_map, *vw, factor); + } + + if (w != *s) { + update_centrality(centrality, w, get(dependency, w)); + } + } + } + + typedef typename graph_traits::directed_category directed_category; + const bool is_undirected = + is_convertible::value; + if (is_undirected) { + divide_centrality_by_two(vertices(g), centrality); + divide_centrality_by_two(edges(g), edge_centrality_map); + } + } + +} } // end namespace detail::graph + +template +void +brandes_betweenness_centrality(const Graph& g, + CentralityMap centrality, // C_B + EdgeCentralityMap edge_centrality_map, + IncomingMap incoming, // P + DistanceMap distance, // d + DependencyMap dependency, // delta + PathCountMap path_count, // sigma + VertexIndexMap vertex_index) +{ + detail::graph::brandes_unweighted_shortest_paths shortest_paths; + + detail::graph::brandes_betweenness_centrality_impl(g, centrality, + edge_centrality_map, + incoming, distance, + dependency, path_count, + vertex_index, + shortest_paths); +} + +template +void +brandes_betweenness_centrality(const Graph& g, + CentralityMap centrality, // C_B + EdgeCentralityMap edge_centrality_map, + IncomingMap incoming, // P + DistanceMap distance, // d + DependencyMap dependency, // delta + PathCountMap path_count, // sigma + VertexIndexMap vertex_index, + WeightMap weight_map) +{ + detail::graph::brandes_dijkstra_shortest_paths + shortest_paths(weight_map); + + detail::graph::brandes_betweenness_centrality_impl(g, centrality, + edge_centrality_map, + incoming, distance, + dependency, path_count, + vertex_index, + shortest_paths); +} + +namespace detail { namespace graph { + template + void + brandes_betweenness_centrality_dispatch2(const Graph& g, + CentralityMap centrality, + EdgeCentralityMap edge_centrality_map, + WeightMap weight_map, + VertexIndexMap vertex_index) + { + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename mpl::if_c<(is_same::value), + EdgeCentralityMap, + CentralityMap>::type a_centrality_map; + typedef typename property_traits::value_type + centrality_type; + + typename graph_traits::vertices_size_type V = num_vertices(g); + + std::vector > incoming(V); + std::vector distance(V); + std::vector dependency(V); + std::vector path_count(V); + + brandes_betweenness_centrality( + g, centrality, edge_centrality_map, + make_iterator_property_map(incoming.begin(), vertex_index), + make_iterator_property_map(distance.begin(), vertex_index), + make_iterator_property_map(dependency.begin(), vertex_index), + make_iterator_property_map(path_count.begin(), vertex_index), + vertex_index, + weight_map); + } + + + template + void + brandes_betweenness_centrality_dispatch2(const Graph& g, + CentralityMap centrality, + EdgeCentralityMap edge_centrality_map, + VertexIndexMap vertex_index) + { + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename mpl::if_c<(is_same::value), + EdgeCentralityMap, + CentralityMap>::type a_centrality_map; + typedef typename property_traits::value_type + centrality_type; + + typename graph_traits::vertices_size_type V = num_vertices(g); + + std::vector > incoming(V); + std::vector distance(V); + std::vector dependency(V); + std::vector path_count(V); + + brandes_betweenness_centrality( + g, centrality, edge_centrality_map, + make_iterator_property_map(incoming.begin(), vertex_index), + make_iterator_property_map(distance.begin(), vertex_index), + make_iterator_property_map(dependency.begin(), vertex_index), + make_iterator_property_map(path_count.begin(), vertex_index), + vertex_index); + } + + template + struct brandes_betweenness_centrality_dispatch1 + { + template + static void + run(const Graph& g, CentralityMap centrality, + EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index, + WeightMap weight_map) + { + brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, + weight_map, vertex_index); + } + }; + + template<> + struct brandes_betweenness_centrality_dispatch1 + { + template + static void + run(const Graph& g, CentralityMap centrality, + EdgeCentralityMap edge_centrality_map, VertexIndexMap vertex_index, + error_property_not_found) + { + brandes_betweenness_centrality_dispatch2(g, centrality, edge_centrality_map, + vertex_index); + } + }; + +} } // end namespace detail::graph + +template +void +brandes_betweenness_centrality(const Graph& g, + const bgl_named_params& params) +{ + typedef bgl_named_params named_params; + + typedef typename property_value::type ew; + detail::graph::brandes_betweenness_centrality_dispatch1::run( + g, + choose_param(get_param(params, vertex_centrality), + dummy_property_map()), + choose_param(get_param(params, edge_centrality), + dummy_property_map()), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index), + get_param(params, edge_weight)); +} + +template +void +brandes_betweenness_centrality(const Graph& g, CentralityMap centrality) +{ + detail::graph::brandes_betweenness_centrality_dispatch2( + g, centrality, dummy_property_map(), get(vertex_index, g)); +} + +template +void +brandes_betweenness_centrality(const Graph& g, CentralityMap centrality, + EdgeCentralityMap edge_centrality_map) +{ + detail::graph::brandes_betweenness_centrality_dispatch2( + g, centrality, edge_centrality_map, get(vertex_index, g)); +} + +/** + * Converts "absolute" betweenness centrality (as computed by the + * brandes_betweenness_centrality algorithm) in the centrality map + * into "relative" centrality. The result is placed back into the + * given centrality map. + */ +template +void +relative_betweenness_centrality(const Graph& g, CentralityMap centrality) +{ + typedef typename graph_traits::vertex_iterator vertex_iterator; + typedef typename property_traits::value_type centrality_type; + + typename graph_traits::vertices_size_type n = num_vertices(g); + centrality_type factor = centrality_type(2)/centrality_type(n*n - 3*n + 2); + vertex_iterator v, v_end; + for (tie(v, v_end) = vertices(g); v != v_end; ++v) { + put(centrality, *v, factor * get(centrality, *v)); + } +} + +// Compute the central point dominance of a graph. +template +typename property_traits::value_type +central_point_dominance(const Graph& g, CentralityMap centrality) +{ + using std::max; + + typedef typename graph_traits::vertex_iterator vertex_iterator; + typedef typename property_traits::value_type centrality_type; + + typename graph_traits::vertices_size_type n = num_vertices(g); + + // Find max centrality + centrality_type max_centrality(0); + vertex_iterator v, v_end; + for (tie(v, v_end) = vertices(g); v != v_end; ++v) { + max_centrality = (max)(max_centrality, get(centrality, *v)); + } + + // Compute central point dominance + centrality_type sum(0); + for (tie(v, v_end) = vertices(g); v != v_end; ++v) { + sum += (max_centrality - get(centrality, *v)); + } + return sum/(n-1); +} + +} // end namespace boost + +#endif // BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP diff --git a/win32/include/boost/graph/biconnected_components.hpp b/win32/include/boost/graph/biconnected_components.hpp new file mode 100755 index 000000000..ca9d8bf1f --- /dev/null +++ b/win32/include/boost/graph/biconnected_components.hpp @@ -0,0 +1,415 @@ +// Copyright (c) Jeremy Siek 2001 +// Copyright (c) Douglas Gregor 2004 +// +// 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) + +// NOTE: this final is generated by libs/graph/doc/biconnected_components.w + +#ifndef BOOST_GRAPH_BICONNECTED_COMPONENTS_HPP +#define BOOST_GRAPH_BICONNECTED_COMPONENTS_HPP + +#include +#include +#include // for std::min and std::max +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace detail + { + template + struct biconnected_components_visitor : public dfs_visitor<> + { + biconnected_components_visitor + (ComponentMap comp, std::size_t& c, DiscoverTimeMap dtm, + std::size_t& dfs_time, LowPointMap lowpt, PredecessorMap pred, + OutputIterator out, Stack& S, DFSVisitor vis) + : comp(comp), c(c), dtm(dtm), dfs_time(dfs_time), lowpt(lowpt), + pred(pred), out(out), S(S), vis(vis) { } + + template + void initialize_vertex(const Vertex& u, Graph& g) + { + vis.initialize_vertex(u, g); + } + + template + void start_vertex(const Vertex& u, Graph& g) + { + put(pred, u, u); + vis.start_vertex(u, g); + } + + template + void discover_vertex(const Vertex& u, Graph& g) + { + put(dtm, u, ++dfs_time); + put(lowpt, u, get(dtm, u)); + vis.discover_vertex(u, g); + } + + template + void examine_edge(const Edge& e, Graph& g) + { + vis.examine_edge(e, g); + } + + template + void tree_edge(const Edge& e, Graph& g) + { + S.push(e); + put(pred, target(e, g), source(e, g)); + vis.tree_edge(e, g); + } + + template + void back_edge(const Edge& e, Graph& g) + { + BOOST_USING_STD_MIN(); + + if ( target(e, g) != get(pred, source(e, g)) ) { + S.push(e); + put(lowpt, source(e, g), + min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, source(e, g)), + get(dtm, target(e, g)))); + vis.back_edge(e, g); + } + } + + template + void forward_or_cross_edge(const Edge& e, Graph& g) + { + vis.forward_or_cross_edge(e, g); + } + + template + void finish_vertex(const Vertex& u, Graph& g) + { + BOOST_USING_STD_MIN(); + Vertex parent = get(pred, u); + const std::size_t dtm_of_dubious_parent = get(dtm, parent); + bool is_art_point = false; + if ( dtm_of_dubious_parent > get(dtm, u) ) { + parent = get(pred, parent); + is_art_point = true; + put(pred, get(pred, u), u); + put(pred, u, parent); + } + + if ( parent == u ) { // at top + if ( get(dtm, u) + 1 == dtm_of_dubious_parent ) + is_art_point = false; + } else { + put(lowpt, parent, + min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, parent), + get(lowpt, u))); + + if (get(lowpt, u) >= get(dtm, parent)) { + if ( get(dtm, parent) > get(dtm, get(pred, parent)) ) { + put(pred, u, get(pred, parent)); + put(pred, parent, u); + } + + while ( get(dtm, source(S.top(), g)) >= get(dtm, u) ) { + put(comp, S.top(), c); + S.pop(); + } + put(comp, S.top(), c); + S.pop(); + ++c; + if ( S.empty() ) { + put(pred, u, parent); + put(pred, parent, u); + } + } + } + if ( is_art_point ) + *out++ = u; + vis.finish_vertex(u, g); + } + + ComponentMap comp; + std::size_t& c; + DiscoverTimeMap dtm; + std::size_t& dfs_time; + LowPointMap lowpt; + PredecessorMap pred; + OutputIterator out; + Stack& S; + DFSVisitor vis; + }; + + template + std::pair + biconnected_components_impl(const Graph & g, ComponentMap comp, + OutputIterator out, VertexIndexMap index_map, DiscoverTimeMap dtm, + LowPointMap lowpt, PredecessorMap pred, DFSVisitor dfs_vis) + { + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::edge_descriptor edge_t; + function_requires >(); + function_requires >(); + function_requires >(); + function_requires >(); + function_requires >(); + function_requires >(); + + std::size_t num_components = 0; + std::size_t dfs_time = 0; + std::stack S; + + biconnected_components_visitor, + DFSVisitor> + vis(comp, num_components, dtm, dfs_time, lowpt, pred, out, + S, dfs_vis); + + depth_first_search(g, visitor(vis).vertex_index_map(index_map)); + + return std::pair(num_components, vis.out); + } + + template + struct bicomp_dispatch3 + { + template + static std::pair apply (const Graph & g, + ComponentMap comp, OutputIterator out, VertexIndexMap index_map, + DiscoverTimeMap dtm, LowPointMap lowpt, + const bgl_named_params& params, PredecessorMap pred) + { + return biconnected_components_impl + (g, comp, out, index_map, dtm, lowpt, pred, + choose_param(get_param(params, graph_visitor), + make_dfs_visitor(null_visitor()))); + } + }; + + template <> + struct bicomp_dispatch3 + { + template + static std::pair apply (const Graph & g, + ComponentMap comp, OutputIterator out, VertexIndexMap index_map, + DiscoverTimeMap dtm, LowPointMap lowpt, + const bgl_named_params& params, + error_property_not_found) + { + typedef typename graph_traits::vertex_descriptor vertex_t; + std::vector pred(num_vertices(g)); + vertex_t vert = graph_traits::null_vertex(); + + return biconnected_components_impl + (g, comp, out, index_map, dtm, lowpt, + make_iterator_property_map(pred.begin(), index_map, vert), + choose_param(get_param(params, graph_visitor), + make_dfs_visitor(null_visitor()))); + } + }; + + template + struct bicomp_dispatch2 + { + template + static std::pair apply (const Graph& g, + ComponentMap comp, OutputIterator out, VertexIndexMap index_map, + DiscoverTimeMap dtm, const bgl_named_params& params, + LowPointMap lowpt) + { + typedef typename property_value< bgl_named_params, + vertex_predecessor_t>::type dispatch_type; + + return bicomp_dispatch3::apply + (g, comp, out, index_map, dtm, lowpt, params, + get_param(params, vertex_predecessor)); + } + }; + + + template <> + struct bicomp_dispatch2 + { + template + static std::pair apply (const Graph& g, + ComponentMap comp, OutputIterator out, VertexIndexMap index_map, + DiscoverTimeMap dtm, const bgl_named_params& params, + error_property_not_found) + { + typedef typename graph_traits::vertices_size_type + vertices_size_type; + std::vector lowpt(num_vertices(g)); + vertices_size_type vst(0); + + typedef typename property_value< bgl_named_params, + vertex_predecessor_t>::type dispatch_type; + + return bicomp_dispatch3::apply + (g, comp, out, index_map, dtm, + make_iterator_property_map(lowpt.begin(), index_map, vst), + params, get_param(params, vertex_predecessor)); + } + }; + + template + struct bicomp_dispatch1 + { + template + static std::pair apply(const Graph& g, + ComponentMap comp, OutputIterator out, VertexIndexMap index_map, + const bgl_named_params& params, DiscoverTimeMap dtm) + { + typedef typename property_value< bgl_named_params, + vertex_lowpoint_t>::type dispatch_type; + + return bicomp_dispatch2::apply + (g, comp, out, index_map, dtm, params, + get_param(params, vertex_lowpoint)); + } + }; + + template <> + struct bicomp_dispatch1 + { + template + static std::pair apply(const Graph& g, + ComponentMap comp, OutputIterator out, VertexIndexMap index_map, + const bgl_named_params& params, error_property_not_found) + { + typedef typename graph_traits::vertices_size_type + vertices_size_type; + std::vector discover_time(num_vertices(g)); + vertices_size_type vst(0); + + typedef typename property_value< bgl_named_params, + vertex_lowpoint_t>::type dispatch_type; + + return bicomp_dispatch2::apply + (g, comp, out, index_map, + make_iterator_property_map(discover_time.begin(), index_map, vst), + params, get_param(params, vertex_lowpoint)); + } + }; + + } + + template + std::pair + biconnected_components(const Graph& g, ComponentMap comp, + OutputIterator out, DiscoverTimeMap dtm, LowPointMap lowpt) + { + typedef detail::error_property_not_found dispatch_type; + + return detail::bicomp_dispatch3::apply + (g, comp, out, + get(vertex_index, g), + dtm, lowpt, + bgl_named_params(0), + detail::error_property_not_found()); + } + + template + std::pair + biconnected_components(const Graph& g, ComponentMap comp, OutputIterator out, + const bgl_named_params& params) + { + typedef typename property_value< bgl_named_params, + vertex_discover_time_t>::type dispatch_type; + + return detail::bicomp_dispatch1::apply(g, comp, out, + choose_const_pmap(get_param(params, vertex_index), g, vertex_index), + params, get_param(params, vertex_discover_time)); + } + + template < typename Graph, typename ComponentMap, typename OutputIterator> + std::pair + biconnected_components(const Graph& g, ComponentMap comp, OutputIterator out) + { + return biconnected_components(g, comp, out, + bgl_named_params(0)); + } + + namespace graph_detail { + struct dummy_output_iterator + { + typedef std::output_iterator_tag iterator_category; + typedef void value_type; + typedef void pointer; + typedef void difference_type; + + struct reference { + template + reference& operator=(const T&) { return *this; } + }; + + reference operator*() const { return reference(); } + dummy_output_iterator& operator++() { return *this; } + dummy_output_iterator operator++(int) { return *this; } + }; + } // end namespace graph_detail + + template + std::size_t + biconnected_components(const Graph& g, ComponentMap comp, + const bgl_named_params& params) + { + return biconnected_components(g, comp, + graph_detail::dummy_output_iterator(), params).first; + } + + template + std::size_t + biconnected_components(const Graph& g, ComponentMap comp) + { + return biconnected_components(g, comp, + graph_detail::dummy_output_iterator()).first; + } + + template + OutputIterator + articulation_points(const Graph& g, OutputIterator out, + const bgl_named_params& params) + { + return biconnected_components(g, dummy_property_map(), out, + params).second; + } + + template + OutputIterator + articulation_points(const Graph& g, OutputIterator out) + { + return biconnected_components(g, dummy_property_map(), out, + bgl_named_params(0)).second; + } + +} // namespace boost + +#endif /* BOOST_GRAPH_BICONNECTED_COMPONENTS_HPP */ diff --git a/win32/include/boost/graph/boyer_myrvold_planar_test.hpp b/win32/include/boost/graph/boyer_myrvold_planar_test.hpp new file mode 100755 index 000000000..899ef3c22 --- /dev/null +++ b/win32/include/boost/graph/boyer_myrvold_planar_test.hpp @@ -0,0 +1,322 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef __BOYER_MYRVOLD_PLANAR_TEST_HPP__ +#define __BOYER_MYRVOLD_PLANAR_TEST_HPP__ + +#include +#include +#include +#include + + +namespace boost +{ + + struct no_kuratowski_subgraph_isolation {}; + struct no_planar_embedding {}; + + namespace boyer_myrvold_params + { + + BOOST_PARAMETER_KEYWORD(tag, graph) + BOOST_PARAMETER_KEYWORD(tag, embedding) + BOOST_PARAMETER_KEYWORD(tag, kuratowski_subgraph) + BOOST_PARAMETER_KEYWORD(tag, vertex_index_map) + BOOST_PARAMETER_KEYWORD(tag, edge_index_map) + + typedef parameter::parameters< parameter::required, + tag::embedding, + tag::kuratowski_subgraph, + tag::vertex_index_map, + tag::edge_index_map + > boyer_myrvold_params_t; + + namespace core + { + + template + bool dispatched_boyer_myrvold(ArgumentPack const& args, + mpl::true_, + mpl::true_ + ) + { + //Dispatch for no planar embedding, no kuratowski subgraph isolation + + typedef typename remove_const + < + typename remove_reference + < typename parameter::binding + < ArgumentPack, tag::graph>::type + >::type + >::type graph_t; + + typedef typename parameter::binding + < ArgumentPack, + tag::vertex_index_map, + typename property_map + < typename remove_reference::type, + vertex_index_t>::const_type + >::type vertex_index_map_t; + + boyer_myrvold_impl + + planarity_tester(args[graph], + args[vertex_index_map | + get(vertex_index, args[graph]) + ] + ); + + return planarity_tester.is_planar() ? true : false; + } + + + + template + bool dispatched_boyer_myrvold(ArgumentPack const& args, + mpl::true_, + mpl::false_ + ) + { + //Dispatch for no planar embedding, kuratowski subgraph isolation + typedef typename remove_const + < + typename remove_reference + < typename parameter::binding + < ArgumentPack, tag::graph>::type + >::type + >::type graph_t; + + typedef typename parameter::binding + < ArgumentPack, + tag::vertex_index_map, + typename property_map::type + >::type vertex_index_map_t; + + boyer_myrvold_impl + + planarity_tester(args[graph], + args[vertex_index_map | + get(vertex_index, args[graph]) + ] + ); + + if (planarity_tester.is_planar()) + return true; + else + { + planarity_tester.extract_kuratowski_subgraph + (args[kuratowski_subgraph], + args[edge_index_map|get(edge_index, args[graph])] + ); + return false; + } + } + + + + + template + bool dispatched_boyer_myrvold(ArgumentPack const& args, + mpl::false_, + mpl::true_ + ) + { + //Dispatch for planar embedding, no kuratowski subgraph isolation + typedef typename remove_const + < + typename remove_reference + < typename parameter::binding + < ArgumentPack, tag::graph>::type + >::type + >::type graph_t; + + typedef typename parameter::binding + < ArgumentPack, + tag::vertex_index_map, + typename property_map::type + >::type vertex_index_map_t; + + boyer_myrvold_impl + + planarity_tester(args[graph], + args[vertex_index_map | + get(vertex_index, args[graph]) + ] + ); + + if (planarity_tester.is_planar()) + { + planarity_tester.make_edge_permutation(args[embedding]); + return true; + } + else + return false; + } + + + + template + bool dispatched_boyer_myrvold(ArgumentPack const& args, + mpl::false_, + mpl::false_ + ) + { + //Dispatch for planar embedding, kuratowski subgraph isolation + typedef typename remove_const + < + typename remove_reference + < typename parameter::binding + < ArgumentPack, tag::graph>::type + >::type + >::type graph_t; + + typedef typename parameter::binding + < ArgumentPack, + tag::vertex_index_map, + typename property_map::type + >::type vertex_index_map_t; + + boyer_myrvold_impl + + planarity_tester(args[graph], + args[vertex_index_map | + get(vertex_index, args[graph]) + ] + ); + + if (planarity_tester.is_planar()) + { + planarity_tester.make_edge_permutation(args[embedding]); + return true; + } + else + { + planarity_tester.extract_kuratowski_subgraph + (args[kuratowski_subgraph], + args[edge_index_map | get(edge_index, args[graph])] + ); + return false; + } + } + + + + + template + bool boyer_myrvold_planarity_test(ArgumentPack const& args) + { + + typedef typename parameter::binding + < ArgumentPack, + tag::kuratowski_subgraph, + const no_kuratowski_subgraph_isolation& + >::type + kuratowski_arg_t; + + typedef typename parameter::binding + < ArgumentPack, + tag::embedding, + const no_planar_embedding& + >::type + embedding_arg_t; + + return dispatched_boyer_myrvold + (args, + boost::is_same + (), + boost::is_same + () + ); + } + + + + } //namespace core + + } //namespace boyer_myrvold_params + + + template + bool boyer_myrvold_planarity_test(A0 const& arg0) + { + return boyer_myrvold_params::core::boyer_myrvold_planarity_test + (boyer_myrvold_params::boyer_myrvold_params_t()(arg0)); + } + + template + // bool boyer_myrvold_planarity_test(A0 const& arg0, A1 const& arg1) + bool boyer_myrvold_planarity_test(A0 const& arg0, A1 const& arg1) + { + return boyer_myrvold_params::core::boyer_myrvold_planarity_test + (boyer_myrvold_params::boyer_myrvold_params_t()(arg0,arg1)); + } + + template + bool boyer_myrvold_planarity_test(A0 const& arg0, + A1 const& arg1, + A2 const& arg2 + ) + { + return boyer_myrvold_params::core::boyer_myrvold_planarity_test + (boyer_myrvold_params::boyer_myrvold_params_t()(arg0,arg1,arg2)); + } + + template + bool boyer_myrvold_planarity_test(A0 const& arg0, + A1 const& arg1, + A2 const& arg2, + A3 const& arg3 + ) + { + return boyer_myrvold_params::core::boyer_myrvold_planarity_test + (boyer_myrvold_params::boyer_myrvold_params_t()(arg0,arg1,arg2,arg3)); + } + + template + bool boyer_myrvold_planarity_test(A0 const& arg0, + A1 const& arg1, + A2 const& arg2, + A3 const& arg3, + A4 const& arg4 + ) + { + return boyer_myrvold_params::core::boyer_myrvold_planarity_test + (boyer_myrvold_params::boyer_myrvold_params_t() + (arg0,arg1,arg2,arg3,arg4) + ); + } + + +} + +#endif //__BOYER_MYRVOLD_PLANAR_TEST_HPP__ diff --git a/win32/include/boost/graph/breadth_first_search.hpp b/win32/include/boost/graph/breadth_first_search.hpp new file mode 100755 index 000000000..b9c95c56e --- /dev/null +++ b/win32/include/boost/graph/breadth_first_search.hpp @@ -0,0 +1,293 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_BREADTH_FIRST_SEARCH_HPP +#define BOOST_GRAPH_BREADTH_FIRST_SEARCH_HPP + +/* + Breadth First Search Algorithm (Cormen, Leiserson, and Rivest p. 470) +*/ +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + template + struct BFSVisitorConcept { + void constraints() { + function_requires< CopyConstructibleConcept >(); + vis.initialize_vertex(u, g); + vis.discover_vertex(u, g); + vis.examine_vertex(u, g); + vis.examine_edge(e, g); + vis.tree_edge(e, g); + vis.non_tree_edge(e, g); + vis.gray_target(e, g); + vis.black_target(e, g); + vis.finish_vertex(u, g); + } + Visitor vis; + Graph g; + typename graph_traits::vertex_descriptor u; + typename graph_traits::edge_descriptor e; + }; + + + template + void breadth_first_visit + (const IncidenceGraph& g, + typename graph_traits::vertex_descriptor s, + Buffer& Q, BFSVisitor vis, ColorMap color) + { + function_requires< IncidenceGraphConcept >(); + typedef graph_traits GTraits; + typedef typename GTraits::vertex_descriptor Vertex; + typedef typename GTraits::edge_descriptor Edge; + function_requires< BFSVisitorConcept >(); + function_requires< ReadWritePropertyMapConcept >(); + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + typename GTraits::out_edge_iterator ei, ei_end; + + put(color, s, Color::gray()); vis.discover_vertex(s, g); + Q.push(s); + while (! Q.empty()) { + Vertex u = Q.top(); Q.pop(); vis.examine_vertex(u, g); + for (tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) { + Vertex v = target(*ei, g); vis.examine_edge(*ei, g); + ColorValue v_color = get(color, v); + if (v_color == Color::white()) { vis.tree_edge(*ei, g); + put(color, v, Color::gray()); vis.discover_vertex(v, g); + Q.push(v); + } else { vis.non_tree_edge(*ei, g); + if (v_color == Color::gray()) vis.gray_target(*ei, g); + else vis.black_target(*ei, g); + } + } // end for + put(color, u, Color::black()); vis.finish_vertex(u, g); + } // end while + } // breadth_first_visit + + + template + void breadth_first_search + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + Buffer& Q, BFSVisitor vis, ColorMap color) + { + // Initialization + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + typename boost::graph_traits::vertex_iterator i, i_end; + for (tie(i, i_end) = vertices(g); i != i_end; ++i) { + vis.initialize_vertex(*i, g); + put(color, *i, Color::white()); + } + breadth_first_visit(g, s, Q, vis, color); + } + + + template + class bfs_visitor { + public: + bfs_visitor() { } + bfs_visitor(Visitors vis) : m_vis(vis) { } + + template + void initialize_vertex(Vertex u, Graph& g) { + invoke_visitors(m_vis, u, g, ::boost::on_initialize_vertex()); + } + template + void discover_vertex(Vertex u, Graph& g) { + invoke_visitors(m_vis, u, g, ::boost::on_discover_vertex()); + } + template + void examine_vertex(Vertex u, Graph& g) { + invoke_visitors(m_vis, u, g, ::boost::on_examine_vertex()); + } + template + void examine_edge(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, ::boost::on_examine_edge()); + } + template + void tree_edge(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, ::boost::on_tree_edge()); + } + template + void non_tree_edge(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, ::boost::on_non_tree_edge()); + } + template + void gray_target(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, ::boost::on_gray_target()); + } + template + void black_target(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, ::boost::on_black_target()); + } + template + void finish_vertex(Vertex u, Graph& g) { + invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex()); + } + + BOOST_GRAPH_EVENT_STUB(on_initialize_vertex,bfs) + BOOST_GRAPH_EVENT_STUB(on_discover_vertex,bfs) + BOOST_GRAPH_EVENT_STUB(on_examine_vertex,bfs) + BOOST_GRAPH_EVENT_STUB(on_examine_edge,bfs) + BOOST_GRAPH_EVENT_STUB(on_tree_edge,bfs) + BOOST_GRAPH_EVENT_STUB(on_non_tree_edge,bfs) + BOOST_GRAPH_EVENT_STUB(on_gray_target,bfs) + BOOST_GRAPH_EVENT_STUB(on_black_target,bfs) + BOOST_GRAPH_EVENT_STUB(on_finish_vertex,bfs) + + protected: + Visitors m_vis; + }; + template + bfs_visitor + make_bfs_visitor(Visitors vis) { + return bfs_visitor(vis); + } + typedef bfs_visitor<> default_bfs_visitor; + + + namespace detail { + + template + void bfs_helper + (VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + ColorMap color, + BFSVisitor vis, + const bgl_named_params& params) + { + typedef graph_traits Traits; + // Buffer default + typedef typename Traits::vertex_descriptor Vertex; + typedef boost::queue queue_t; + queue_t Q; + detail::wrap_ref Qref(Q); + breadth_first_search + (g, s, + choose_param(get_param(params, buffer_param_t()), Qref).ref, + vis, color); + } + + //------------------------------------------------------------------------- + // Choose between default color and color parameters. Using + // function dispatching so that we don't require vertex index if + // the color default is not being used. + + template + struct bfs_dispatch { + template + static void apply + (VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + const bgl_named_params& params, + ColorMap color) + { + bfs_helper + (g, s, color, + choose_param(get_param(params, graph_visitor), + make_bfs_visitor(null_visitor())), + params); + } + }; + + template <> + struct bfs_dispatch { + template + static void apply + (VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + const bgl_named_params& params, + detail::error_property_not_found) + { + std::vector color_vec(num_vertices(g)); + default_color_type c = white_color; + null_visitor null_vis; + + bfs_helper + (g, s, + make_iterator_property_map + (color_vec.begin(), + choose_const_pmap(get_param(params, vertex_index), + g, vertex_index), c), + choose_param(get_param(params, graph_visitor), + make_bfs_visitor(null_vis)), + params); + } + }; + + } // namespace detail + + + // Named Parameter Variant + template + void breadth_first_search + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + const bgl_named_params& params) + { + // The graph is passed by *const* reference so that graph adaptors + // (temporaries) can be passed into this function. However, the + // graph is not really const since we may write to property maps + // of the graph. + VertexListGraph& ng = const_cast(g); + typedef typename property_value< bgl_named_params, + vertex_color_t>::type C; + detail::bfs_dispatch::apply(ng, s, params, + get_param(params, vertex_color)); + } + + + // This version does not initialize colors, user has to. + + template + void breadth_first_visit + (const IncidenceGraph& g, + typename graph_traits::vertex_descriptor s, + const bgl_named_params& params) + { + // The graph is passed by *const* reference so that graph adaptors + // (temporaries) can be passed into this function. However, the + // graph is not really const since we may write to property maps + // of the graph. + IncidenceGraph& ng = const_cast(g); + + typedef graph_traits Traits; + // Buffer default + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef boost::queue queue_t; + queue_t Q; + detail::wrap_ref Qref(Q); + + breadth_first_visit + (ng, s, + choose_param(get_param(params, buffer_param_t()), Qref).ref, + choose_param(get_param(params, graph_visitor), + make_bfs_visitor(null_visitor())), + choose_pmap(get_param(params, vertex_color), ng, vertex_color) + ); + } + +} // namespace boost + +#endif // BOOST_GRAPH_BREADTH_FIRST_SEARCH_HPP + diff --git a/win32/include/boost/graph/chrobak_payne_drawing.hpp b/win32/include/boost/graph/chrobak_payne_drawing.hpp new file mode 100755 index 000000000..872b7b8b0 --- /dev/null +++ b/win32/include/boost/graph/chrobak_payne_drawing.hpp @@ -0,0 +1,270 @@ +//======================================================================= +// Copyright (c) Aaron Windsor 2007 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef __CHROBAK_PAYNE_DRAWING_HPP__ +#define __CHROBAK_PAYNE_DRAWING_HPP__ + +#include +#include +#include +#include //for next and prior +#include +#include + + +namespace boost +{ + + namespace graph { namespace detail + { + + template + void accumulate_offsets(typename graph_traits::vertex_descriptor v, + std::size_t offset, + const Graph& g, + VertexTo1DCoordMap x, + VertexTo1DCoordMap delta_x, + VertexToVertexMap left, + VertexToVertexMap right) + { + if (v != graph_traits::null_vertex()) + { + x[v] += delta_x[v] + offset; + accumulate_offsets(left[v], x[v], g, x, delta_x, left, right); + accumulate_offsets(right[v], x[v], g, x, delta_x, left, right); + } + } + + } /*namespace detail*/ } /*namespace graph*/ + + + + + + template + void chrobak_payne_straight_line_drawing(const Graph& g, + PlanarEmbedding embedding, + ForwardIterator ordering_begin, + ForwardIterator ordering_end, + GridPositionMap drawing, + VertexIndexMap vm + ) + { + + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::edge_descriptor edge_t; + typedef typename graph_traits::vertex_iterator vertex_iterator_t; + typedef typename PlanarEmbedding::value_type::const_iterator + edge_permutation_iterator_t; + typedef typename graph_traits::vertices_size_type v_size_t; + typedef std::vector vertex_vector_t; + typedef std::vector vsize_vector_t; + typedef std::vector bool_vector_t; + typedef boost::iterator_property_map + + vertex_to_vertex_map_t; + typedef boost::iterator_property_map + + vertex_to_vsize_map_t; + typedef boost::iterator_property_map + + vertex_to_bool_map_t; + + vertex_vector_t left_vector(num_vertices(g), + graph_traits::null_vertex() + ); + vertex_vector_t right_vector(num_vertices(g), + graph_traits::null_vertex() + ); + vsize_vector_t seen_as_right_vector(num_vertices(g), 0); + vsize_vector_t seen_vector(num_vertices(g), 0); + vsize_vector_t delta_x_vector(num_vertices(g),0); + vsize_vector_t y_vector(num_vertices(g)); + vsize_vector_t x_vector(num_vertices(g),0); + bool_vector_t installed_vector(num_vertices(g),false); + + vertex_to_vertex_map_t left(left_vector.begin(), vm); + vertex_to_vertex_map_t right(right_vector.begin(), vm); + vertex_to_vsize_map_t seen_as_right(seen_as_right_vector.begin(), vm); + vertex_to_vsize_map_t seen(seen_vector.begin(), vm); + vertex_to_vsize_map_t delta_x(delta_x_vector.begin(), vm); + vertex_to_vsize_map_t y(y_vector.begin(), vm); + vertex_to_vsize_map_t x(x_vector.begin(), vm); + vertex_to_bool_map_t installed(installed_vector.begin(), vm); + + v_size_t timestamp = 1; + vertex_vector_t installed_neighbors; + + ForwardIterator itr = ordering_begin; + vertex_t v1 = *itr; ++itr; + vertex_t v2 = *itr; ++itr; + vertex_t v3 = *itr; ++itr; + + delta_x[v2] = 1; + delta_x[v3] = 1; + + y[v1] = 0; + y[v2] = 0; + y[v3] = 1; + + right[v1] = v3; + right[v3] = v2; + + installed[v1] = installed[v2] = installed[v3] = true; + + for(ForwardIterator itr_end = ordering_end; itr != itr_end; ++itr) + { + vertex_t v = *itr; + + // First, find the leftmost and rightmost neighbor of v on the outer + // cycle of the embedding. + // Note: since we're moving clockwise through the edges adjacent to v, + // we're actually moving from right to left among v's neighbors on the + // outer face (since v will be installed above them all) looking for + // the leftmost and rightmost installed neigbhors + + vertex_t leftmost = graph_traits::null_vertex(); + vertex_t rightmost = graph_traits::null_vertex(); + + installed_neighbors.clear(); + + vertex_t prev_vertex = graph_traits::null_vertex(); + edge_permutation_iterator_t pi, pi_end; + pi_end = embedding[v].end(); + for(pi = embedding[v].begin(); pi != pi_end; ++pi) + { + vertex_t curr_vertex = source(*pi,g) == v ? + target(*pi,g) : source(*pi,g); + + // Skip any self-loops or parallel edges + if (curr_vertex == v || curr_vertex == prev_vertex) + continue; + + if (installed[curr_vertex]) + { + seen[curr_vertex] = timestamp; + + if (right[curr_vertex] != graph_traits::null_vertex()) + { + seen_as_right[right[curr_vertex]] = timestamp; + } + installed_neighbors.push_back(curr_vertex); + } + + prev_vertex = curr_vertex; + } + + typename vertex_vector_t::iterator vi, vi_end; + vi_end = installed_neighbors.end(); + for(vi = installed_neighbors.begin(); vi != vi_end; ++vi) + { + if (right[*vi] == graph_traits::null_vertex() || + seen[right[*vi]] != timestamp + ) + rightmost = *vi; + if (seen_as_right[*vi] != timestamp) + leftmost = *vi; + } + + ++timestamp; + + //stretch gaps + ++delta_x[right[leftmost]]; + ++delta_x[rightmost]; + + //adjust offsets + std::size_t delta_p_q = 0; + vertex_t stopping_vertex = right[rightmost]; + for(vertex_t temp = right[leftmost]; temp != stopping_vertex; + temp = right[temp] + ) + { + delta_p_q += delta_x[temp]; + } + + delta_x[v] = (y[rightmost] - y[leftmost] + delta_p_q)/2; + y[v] = (y[rightmost] + y[leftmost] + delta_p_q)/2; + delta_x[rightmost] = delta_p_q - delta_x[v]; + + bool leftmost_and_rightmost_adjacent = right[leftmost] == rightmost; + if (!leftmost_and_rightmost_adjacent) + delta_x[right[leftmost]] -= delta_x[v]; + + //install v + if (!leftmost_and_rightmost_adjacent) + { + left[v] = right[leftmost]; + vertex_t next_to_rightmost; + for(vertex_t temp = leftmost; temp != rightmost; + temp = right[temp] + ) + { + next_to_rightmost = temp; + } + + right[next_to_rightmost] = graph_traits::null_vertex(); + } + else + { + left[v] = graph_traits::null_vertex(); + } + + right[leftmost] = v; + right[v] = rightmost; + installed[v] = true; + + } + + graph::detail::accumulate_offsets + (*ordering_begin,0,g,x,delta_x,left,right); + + vertex_iterator_t vi, vi_end; + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_t v(*vi); + drawing[v].x = x[v]; + drawing[v].y = y[v]; + } + + } + + + + + template + inline void chrobak_payne_straight_line_drawing(const Graph& g, + PlanarEmbedding embedding, + ForwardIterator ord_begin, + ForwardIterator ord_end, + GridPositionMap drawing + ) + { + chrobak_payne_straight_line_drawing(g, + embedding, + ord_begin, + ord_end, + drawing, + get(vertex_index,g) + ); + } + + + + +} // namespace boost + +#endif //__CHROBAK_PAYNE_DRAWING_HPP__ diff --git a/win32/include/boost/graph/circle_layout.hpp b/win32/include/boost/graph/circle_layout.hpp new file mode 100755 index 000000000..5b6f05dfc --- /dev/null +++ b/win32/include/boost/graph/circle_layout.hpp @@ -0,0 +1,55 @@ +// Copyright 2004 The Trustees of Indiana University. + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_CIRCLE_LAYOUT_HPP +#define BOOST_GRAPH_CIRCLE_LAYOUT_HPP +#include +#include +#include + +namespace boost { + /** + * \brief Layout the graph with the vertices at the points of a regular + * n-polygon. + * + * The distance from the center of the polygon to each point is + * determined by the @p radius parameter. The @p position parameter + * must be an Lvalue Property Map whose value type is a class type + * containing @c x and @c y members that will be set to the @c x and + * @c y coordinates. + */ + template + void + circle_graph_layout(const VertexListGraph& g, PositionMap position, + Radius radius) + { + const double pi = 3.14159; + +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sin; + using std::cos; +#endif // BOOST_NO_STDC_NAMESPACE + + typedef typename graph_traits::vertices_size_type + vertices_size_type; + + vertices_size_type n = num_vertices(g); + + typedef typename graph_traits::vertex_iterator + vertex_iterator; + + vertices_size_type i = 0; + for(std::pair v = vertices(g); + v.first != v.second; ++v.first, ++i) { + position[*v.first].x = radius * cos(i * 2 * pi / n); + position[*v.first].y = radius * sin(i * 2 * pi / n); + } + } +} // end namespace boost + +#endif // BOOST_GRAPH_CIRCLE_LAYOUT_HPP diff --git a/win32/include/boost/graph/compressed_sparse_row_graph.hpp b/win32/include/boost/graph/compressed_sparse_row_graph.hpp new file mode 100755 index 000000000..df809dd12 --- /dev/null +++ b/win32/include/boost/graph/compressed_sparse_row_graph.hpp @@ -0,0 +1,801 @@ +// Copyright 2005-2006 The Trustees of Indiana University. + +// 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) + +// Authors: Jeremiah Willcock +// Douglas Gregor +// Andrew Lumsdaine + +// Compressed sparse row graph type + +#ifndef BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP +#define BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_GRAPH_NO_BUNDLED_PROPERTIES +# error The Compressed Sparse Row graph only supports bundled properties. +# error You will need a compiler that conforms better to the C++ standard. +#endif + +namespace boost { + +// A tag type indicating that the graph in question is a compressed +// sparse row graph. This is an internal detail of the BGL. +struct csr_graph_tag; + +/**************************************************************************** + * Local helper macros to reduce typing and clutter later on. * + ****************************************************************************/ +#define BOOST_CSR_GRAPH_TEMPLATE_PARMS \ + typename Directed, typename VertexProperty, typename EdgeProperty, \ + typename GraphProperty, typename Vertex, typename EdgeIndex +#define BOOST_CSR_GRAPH_TYPE \ + compressed_sparse_row_graph + +// Forward declaration of CSR edge descriptor type, needed to pass to +// indexed_edge_properties. +template +class csr_edge_descriptor; + +/** Compressed sparse row graph. + * + * Vertex and EdgeIndex should be unsigned integral types and should + * specialize numeric_limits. + */ +template +class compressed_sparse_row_graph + : public detail::indexed_vertex_properties, + public detail::indexed_edge_properties > + +{ + typedef detail::indexed_vertex_properties + inherited_vertex_properties; + + typedef detail::indexed_edge_properties > + inherited_edge_properties; + + public: + // For Property Graph + typedef GraphProperty graph_property_type; + + protected: + template + void + maybe_reserve_edge_list_storage(InputIterator, InputIterator, + std::input_iterator_tag) + { + // Do nothing: we have no idea how much storage to reserve. + } + + template + void + maybe_reserve_edge_list_storage(InputIterator first, InputIterator last, + std::forward_iterator_tag) + { + using std::distance; + typename std::iterator_traits::difference_type n = + distance(first, last); + m_column.reserve(n); + inherited_edge_properties::reserve(n); + } + + public: + /* At this time, the compressed sparse row graph can only be used to + * create a directed graph. In the future, bidirectional and + * undirected CSR graphs will also be supported. + */ + BOOST_STATIC_ASSERT((is_same::value)); + + // Concept requirements: + // For Graph + typedef Vertex vertex_descriptor; + typedef csr_edge_descriptor edge_descriptor; + typedef directed_tag directed_category; + typedef allow_parallel_edge_tag edge_parallel_category; + + class traversal_category: public incidence_graph_tag, + public adjacency_graph_tag, + public vertex_list_graph_tag, + public edge_list_graph_tag {}; + + static vertex_descriptor null_vertex() { return vertex_descriptor(-1); } + + // For VertexListGraph + typedef counting_iterator vertex_iterator; + typedef Vertex vertices_size_type; + + // For EdgeListGraph + typedef EdgeIndex edges_size_type; + + // For IncidenceGraph + class out_edge_iterator; + typedef EdgeIndex degree_size_type; + + // For AdjacencyGraph + typedef typename std::vector::const_iterator adjacency_iterator; + + // For EdgeListGraph + class edge_iterator; + + // For BidirectionalGraph (not implemented) + typedef void in_edge_iterator; + + // For internal use + typedef csr_graph_tag graph_tag; + + // Constructors + + // Default constructor: an empty graph. + compressed_sparse_row_graph() + : m_rowstart(1, EdgeIndex(0)), m_column(0), m_property(), + m_last_source(0) {} + + // From number of vertices and sorted list of edges + template + compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end, + vertices_size_type numverts, + edges_size_type numedges = 0, + const GraphProperty& prop = GraphProperty()) + : inherited_vertex_properties(numverts), m_rowstart(numverts + 1), + m_column(0), m_property(prop), m_last_source(numverts) + { + // Reserving storage in advance can save us lots of time and + // memory, but it can only be done if we have forward iterators or + // the user has supplied the number of edges. + if (numedges == 0) { + typedef typename std::iterator_traits::iterator_category + category; + maybe_reserve_edge_list_storage(edge_begin, edge_end, category()); + } else { + m_column.reserve(numedges); + } + + EdgeIndex current_edge = 0; + Vertex current_vertex_plus_one = 1; + m_rowstart[0] = 0; + for (InputIterator ei = edge_begin; ei != edge_end; ++ei) { + Vertex src = ei->first; + Vertex tgt = ei->second; + for (; current_vertex_plus_one != src + 1; ++current_vertex_plus_one) + m_rowstart[current_vertex_plus_one] = current_edge; + m_column.push_back(tgt); + ++current_edge; + } + + // The remaining vertices have no edges + for (; current_vertex_plus_one != numverts + 1; ++current_vertex_plus_one) + m_rowstart[current_vertex_plus_one] = current_edge; + + // Default-construct properties for edges + inherited_edge_properties::resize(m_column.size()); + } + + // From number of vertices and sorted list of edges + template + compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end, + EdgePropertyIterator ep_iter, + vertices_size_type numverts, + edges_size_type numedges = 0, + const GraphProperty& prop = GraphProperty()) + : inherited_vertex_properties(numverts), m_rowstart(numverts + 1), + m_column(0), m_property(prop), m_last_source(numverts) + { + // Reserving storage in advance can save us lots of time and + // memory, but it can only be done if we have forward iterators or + // the user has supplied the number of edges. + if (numedges == 0) { + typedef typename std::iterator_traits::iterator_category + category; + maybe_reserve_edge_list_storage(edge_begin, edge_end, category()); + } else { + m_column.reserve(numedges); + } + + EdgeIndex current_edge = 0; + Vertex current_vertex_plus_one = 1; + m_rowstart[0] = 0; + for (InputIterator ei = edge_begin; ei != edge_end; ++ei, ++ep_iter) { + Vertex src = ei->first; + Vertex tgt = ei->second; + for (; current_vertex_plus_one != src + 1; ++current_vertex_plus_one) + m_rowstart[current_vertex_plus_one] = current_edge; + m_column.push_back(tgt); + inherited_edge_properties::push_back(*ep_iter); + ++current_edge; + } + + // The remaining vertices have no edges + for (; current_vertex_plus_one != numverts + 1; ++current_vertex_plus_one) + m_rowstart[current_vertex_plus_one] = current_edge; + } + + // Requires IncidenceGraph, a vertex index map, and a vertex(n, g) function + template + compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi, + vertices_size_type numverts, + edges_size_type numedges) + : m_property(), m_last_source(0) + { + assign(g, vi, numverts, numedges); + } + + // Requires VertexListGraph and EdgeListGraph + template + compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi) + : m_property(), m_last_source(0) + { + assign(g, vi, num_vertices(g), num_edges(g)); + } + + // Requires vertex index map plus requirements of previous constructor + template + explicit compressed_sparse_row_graph(const Graph& g) + : m_property(), m_last_source(0) + { + assign(g, get(vertex_index, g), num_vertices(g), num_edges(g)); + } + + // From any graph (slow and uses a lot of memory) + // Requires IncidenceGraph, a vertex index map, and a vertex(n, g) function + // Internal helper function + template + void + assign(const Graph& g, const VertexIndexMap& vi, + vertices_size_type numverts, edges_size_type numedges) + { + inherited_vertex_properties::resize(numverts); + m_rowstart.resize(numverts + 1); + m_column.resize(numedges); + EdgeIndex current_edge = 0; + typedef typename boost::graph_traits::vertex_descriptor g_vertex; + typedef typename boost::graph_traits::edge_descriptor g_edge; + typedef typename boost::graph_traits::out_edge_iterator + g_out_edge_iter; + + for (Vertex i = 0; i != numverts; ++i) { + m_rowstart[i] = current_edge; + g_vertex v = vertex(i, g); + EdgeIndex num_edges_before_this_vertex = current_edge; + g_out_edge_iter ei, ei_end; + for (tie(ei, ei_end) = out_edges(v, g); ei != ei_end; ++ei) { + m_column[current_edge++] = get(vi, target(*ei, g)); + } + std::sort(m_column.begin() + num_edges_before_this_vertex, + m_column.begin() + current_edge); + } + m_rowstart[numverts] = current_edge; + m_last_source = numverts; + } + + // Requires the above, plus VertexListGraph and EdgeListGraph + template + void assign(const Graph& g, const VertexIndexMap& vi) + { + assign(g, vi, num_vertices(g), num_edges(g)); + } + + // Requires the above, plus a vertex_index map. + template + void assign(const Graph& g) + { + assign(g, get(vertex_index, g), num_vertices(g), num_edges(g)); + } + + using inherited_vertex_properties::operator[]; + using inherited_edge_properties::operator[]; + + // private: non-portable, requires friend templates + inherited_vertex_properties& vertex_properties() {return *this;} + const inherited_vertex_properties& vertex_properties() const {return *this;} + inherited_edge_properties& edge_properties() { return *this; } + const inherited_edge_properties& edge_properties() const { return *this; } + + std::vector m_rowstart; + std::vector m_column; + GraphProperty m_property; + Vertex m_last_source; // Last source of added edge, plus one +}; + +template +class csr_edge_descriptor +{ + public: + Vertex src; + EdgeIndex idx; + + csr_edge_descriptor(Vertex src, EdgeIndex idx): src(src), idx(idx) {} + csr_edge_descriptor(): src(0), idx(0) {} + + bool operator==(const csr_edge_descriptor& e) const {return idx == e.idx;} + bool operator!=(const csr_edge_descriptor& e) const {return idx != e.idx;} + bool operator<(const csr_edge_descriptor& e) const {return idx < e.idx;} + bool operator>(const csr_edge_descriptor& e) const {return idx > e.idx;} + bool operator<=(const csr_edge_descriptor& e) const {return idx <= e.idx;} + bool operator>=(const csr_edge_descriptor& e) const {return idx >= e.idx;} +}; + +// Construction functions +template +inline Vertex +add_vertex(BOOST_CSR_GRAPH_TYPE& g) { + Vertex old_num_verts_plus_one = g.m_rowstart.size(); + g.m_rowstart.push_back(EdgeIndex(0)); + g.vertex_properties().resize(num_vertices(g)); + return old_num_verts_plus_one - 1; +} + +template +inline Vertex +add_vertices(typename BOOST_CSR_GRAPH_TYPE::vertices_size_type count, BOOST_CSR_GRAPH_TYPE& g) { + Vertex old_num_verts_plus_one = g.m_rowstart.size(); + g.m_rowstart.resize(old_num_verts_plus_one + count, EdgeIndex(0)); + g.vertex_properties().resize(num_vertices(g)); + return old_num_verts_plus_one - 1; +} + +// This function requires that (src, tgt) be lexicographically at least as +// large as the largest edge in the graph so far +template +inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor +add_edge(Vertex src, Vertex tgt, BOOST_CSR_GRAPH_TYPE& g) { + assert ((g.m_last_source == 0 || src >= g.m_last_source - 1) && + src < num_vertices(g)); + EdgeIndex num_edges_orig = g.m_column.size(); + for (; g.m_last_source <= src; ++g.m_last_source) + g.m_rowstart[g.m_last_source] = num_edges_orig; + g.m_rowstart[src + 1] = num_edges_orig + 1; + g.m_column.push_back(tgt); + typedef typename BOOST_CSR_GRAPH_TYPE::edge_push_back_type push_back_type; + g.edge_properties().push_back(push_back_type()); + return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, num_edges_orig); +} + +// This function requires that (src, tgt) be lexicographically at least as +// large as the largest edge in the graph so far +template +inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor +add_edge(Vertex src, Vertex tgt, + typename BOOST_CSR_GRAPH_TYPE::edge_bundled const& p, + BOOST_CSR_GRAPH_TYPE& g) { + assert ((g.m_last_source == 0 || src >= g.m_last_source - 1) && + src < num_vertices(g)); + EdgeIndex num_edges_orig = g.m_column.size(); + for (; g.m_last_source <= src; ++g.m_last_source) + g.m_rowstart[g.m_last_source] = num_edges_orig; + g.m_rowstart[src + 1] = num_edges_orig + 1; + g.m_column.push_back(tgt); + g.edge_properties().push_back(p); + return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, num_edges_orig); +} + + +// From VertexListGraph +template +inline Vertex +num_vertices(const BOOST_CSR_GRAPH_TYPE& g) { + return g.m_rowstart.size() - 1; +} + +template +std::pair, counting_iterator > +inline vertices(const BOOST_CSR_GRAPH_TYPE& g) { + return std::make_pair(counting_iterator(0), + counting_iterator(num_vertices(g))); +} + +// From IncidenceGraph +template +class BOOST_CSR_GRAPH_TYPE::out_edge_iterator + : public iterator_facade::fast> +{ + public: + typedef typename int_t::fast difference_type; + + out_edge_iterator() {} + // Implicit copy constructor OK + explicit out_edge_iterator(edge_descriptor edge) : m_edge(edge) { } + + private: + // iterator_facade requirements + const edge_descriptor& dereference() const { return m_edge; } + + bool equal(const out_edge_iterator& other) const + { return m_edge == other.m_edge; } + + void increment() { ++m_edge.idx; } + void decrement() { ++m_edge.idx; } + void advance(difference_type n) { m_edge.idx += n; } + + difference_type distance_to(const out_edge_iterator& other) const + { return other.m_edge.idx - m_edge.idx; } + + edge_descriptor m_edge; + + friend class iterator_core_access; +}; + +template +inline Vertex +source(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e, + const BOOST_CSR_GRAPH_TYPE&) +{ + return e.src; +} + +template +inline Vertex +target(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e, + const BOOST_CSR_GRAPH_TYPE& g) +{ + return g.m_column[e.idx]; +} + +template +inline std::pair +out_edges(Vertex v, const BOOST_CSR_GRAPH_TYPE& g) +{ + typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor ed; + typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator it; + EdgeIndex v_row_start = g.m_rowstart[v]; + EdgeIndex next_row_start = g.m_rowstart[v + 1]; + return std::make_pair(it(ed(v, v_row_start)), + it(ed(v, (std::max)(v_row_start, next_row_start)))); +} + +template +inline EdgeIndex +out_degree(Vertex v, const BOOST_CSR_GRAPH_TYPE& g) +{ + EdgeIndex v_row_start = g.m_rowstart[v]; + EdgeIndex next_row_start = g.m_rowstart[v + 1]; + return (std::max)(v_row_start, next_row_start) - v_row_start; +} + +// From AdjacencyGraph +template +inline std::pair +adjacent_vertices(Vertex v, const BOOST_CSR_GRAPH_TYPE& g) +{ + EdgeIndex v_row_start = g.m_rowstart[v]; + EdgeIndex next_row_start = g.m_rowstart[v + 1]; + return std::make_pair(g.m_column.begin() + v_row_start, + g.m_column.begin() + + (std::max)(v_row_start, next_row_start)); +} + +// Extra, common functions +template +inline typename graph_traits::vertex_descriptor +vertex(typename graph_traits::vertex_descriptor i, + const BOOST_CSR_GRAPH_TYPE&) +{ + return i; +} + +// Unlike for an adjacency_matrix, edge_range and edge take lg(out_degree(i)) +// time +template +inline std::pair +edge_range(Vertex i, Vertex j, const BOOST_CSR_GRAPH_TYPE& g) +{ + typedef typename std::vector::const_iterator adj_iter; + typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator out_edge_iter; + typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edge_desc; + std::pair raw_adjacencies = adjacent_vertices(i, g); + std::pair adjacencies = + std::equal_range(raw_adjacencies.first, raw_adjacencies.second, j); + EdgeIndex idx_begin = adjacencies.first - g.m_column.begin(); + EdgeIndex idx_end = adjacencies.second - g.m_column.begin(); + return std::make_pair(out_edge_iter(edge_desc(i, idx_begin)), + out_edge_iter(edge_desc(i, idx_end))); +} + +template +inline std::pair +edge(Vertex i, Vertex j, const BOOST_CSR_GRAPH_TYPE& g) +{ + typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator out_edge_iter; + std::pair range = edge_range(i, j, g); + if (range.first == range.second) + return std::make_pair(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(), + false); + else + return std::make_pair(*range.first, true); +} + +// Find an edge given its index in the graph +template +inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor +edge_from_index(EdgeIndex idx, const BOOST_CSR_GRAPH_TYPE& g) +{ + typedef typename std::vector::const_iterator row_start_iter; + assert (idx < num_edges(g)); + row_start_iter src_plus_1 = + std::upper_bound(g.m_rowstart.begin(), + g.m_rowstart.begin() + g.m_last_source + 1, + idx); + // Get last source whose rowstart is at most idx + // upper_bound returns this position plus 1 + Vertex src = (src_plus_1 - g.m_rowstart.begin()) - 1; + return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, idx); +} + +// From EdgeListGraph +template +class BOOST_CSR_GRAPH_TYPE::edge_iterator +{ + public: + typedef std::forward_iterator_tag iterator_category; + typedef edge_descriptor value_type; + + typedef const edge_descriptor* pointer; + + typedef edge_descriptor reference; + typedef typename int_t::fast difference_type; + + edge_iterator() : rowstart_array(0), current_edge(), end_of_this_vertex(0) {} + + edge_iterator(const compressed_sparse_row_graph& graph, + edge_descriptor current_edge, + EdgeIndex end_of_this_vertex) + : rowstart_array(&graph.m_rowstart[0]), current_edge(current_edge), + end_of_this_vertex(end_of_this_vertex) {} + + // From InputIterator + reference operator*() const { return current_edge; } + pointer operator->() const { return ¤t_edge; } + + bool operator==(const edge_iterator& o) const { + return current_edge == o.current_edge; + } + bool operator!=(const edge_iterator& o) const { + return current_edge != o.current_edge; + } + + edge_iterator& operator++() { + ++current_edge.idx; + while (current_edge.idx == end_of_this_vertex) { + ++current_edge.src; + end_of_this_vertex = rowstart_array[current_edge.src + 1]; + } + return *this; + } + + edge_iterator operator++(int) { + edge_iterator temp = *this; + ++*this; + return temp; + } + + private: + const EdgeIndex* rowstart_array; + edge_descriptor current_edge; + EdgeIndex end_of_this_vertex; +}; + +template +inline EdgeIndex +num_edges(const BOOST_CSR_GRAPH_TYPE& g) +{ + return g.m_column.size(); +} + +template +std::pair +edges(const BOOST_CSR_GRAPH_TYPE& g) +{ + typedef typename BOOST_CSR_GRAPH_TYPE::edge_iterator ei; + typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edgedesc; + if (g.m_rowstart.size() == 1 || g.m_column.empty()) { + return std::make_pair(ei(), ei()); + } else { + // Find the first vertex that has outgoing edges + Vertex src = 0; + while (g.m_rowstart[src + 1] == 0) ++src; + return std::make_pair(ei(g, edgedesc(src, 0), g.m_rowstart[src + 1]), + ei(g, edgedesc(num_vertices(g), g.m_column.size()), 0)); + } +} + +// For Property Graph + +// Graph properties +template +inline void +set_property(BOOST_CSR_GRAPH_TYPE& g, Tag, const Value& value) +{ + get_property_value(g.m_property, Tag()) = value; +} + +template +inline +typename graph_property::type& +get_property(BOOST_CSR_GRAPH_TYPE& g, Tag) +{ + return get_property_value(g.m_property, Tag()); +} + +template +inline +const +typename graph_property::type& +get_property(const BOOST_CSR_GRAPH_TYPE& g, Tag) +{ + return get_property_value(g.m_property, Tag()); +} + +// Add edge_index property map +template +struct csr_edge_index_map +{ + typedef Index value_type; + typedef Index reference; + typedef Descriptor key_type; + typedef readable_property_map_tag category; +}; + +template +inline Index +get(const csr_edge_index_map&, + const typename csr_edge_index_map::key_type& key) +{ + return key.idx; +} + +// Doing the right thing here (by unifying with vertex_index_t and +// edge_index_t) breaks GCC. +template +struct property_map +{ +private: + typedef identity_property_map vertex_index_type; + typedef typename graph_traits::edge_descriptor + edge_descriptor; + typedef csr_edge_index_map edge_index_type; + + typedef typename mpl::if_, + edge_index_type, + detail::error_property_not_found>::type + edge_or_none; + +public: + typedef typename mpl::if_, + vertex_index_type, + edge_or_none>::type type; + + typedef type const_type; +}; + +template +inline identity_property_map +get(vertex_index_t, const BOOST_CSR_GRAPH_TYPE&) +{ + return identity_property_map(); +} + +template +inline Vertex +get(vertex_index_t, + const BOOST_CSR_GRAPH_TYPE&, Vertex v) +{ + return v; +} + +template +inline typename property_map::const_type +get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&) +{ + typedef typename property_map::const_type + result_type; + return result_type(); +} + +template +inline EdgeIndex +get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&, + typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e) +{ + return e.idx; +} + +// Support for bundled properties +template +struct property_map +{ +private: + typedef graph_traits traits; + typedef VertexProperty vertex_bundled; + typedef EdgeProperty edge_bundled; + typedef typename mpl::if_c<(detail::is_vertex_bundle::value), + typename traits::vertex_descriptor, + typename traits::edge_descriptor>::type + descriptor; + +public: + typedef bundle_property_map + type; + typedef bundle_property_map const_type; +}; + +template +inline +typename property_map::type +get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE& g) +{ + typedef typename property_map::type + result_type; + return result_type(&g, p); +} + +template +inline +typename property_map::const_type +get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE const & g) +{ + typedef typename property_map::const_type + result_type; + return result_type(&g, p); +} + +template +inline T +get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE const & g, + const Key& key) +{ + return get(get(p, g), key); +} + +template +inline void +put(T Bundle::* p, BOOST_CSR_GRAPH_TYPE& g, + const Key& key, const T& value) +{ + put(get(p, g), key, value); +} + +#undef BOOST_CSR_GRAPH_TYPE +#undef BOOST_CSR_GRAPH_TEMPLATE_PARMS + +} // end namespace boost + +#endif // BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP diff --git a/win32/include/boost/graph/connected_components.hpp b/win32/include/boost/graph/connected_components.hpp new file mode 100755 index 000000000..c4395a109 --- /dev/null +++ b/win32/include/boost/graph/connected_components.hpp @@ -0,0 +1,101 @@ +// +//======================================================================= +// Copyright 1997-2001 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_CONNECTED_COMPONENTS_HPP +#define BOOST_GRAPH_CONNECTED_COMPONENTS_HPP + +#include +#include +#include +#include + +#include + +namespace boost { + + namespace detail { + + // This visitor is used both in the connected_components algorithm + // and in the kosaraju strong components algorithm during the + // second DFS traversal. + template + class components_recorder : public dfs_visitor<> + { + typedef typename property_traits::value_type comp_type; + public: + components_recorder(ComponentsMap c, + comp_type& c_count) + : m_component(c), m_count(c_count) {} + + template + void start_vertex(Vertex, Graph&) { + if (m_count == (std::numeric_limits::max)()) + m_count = 0; // start counting components at zero + else + ++m_count; + } + template + void discover_vertex(Vertex u, Graph&) { + put(m_component, u, m_count); + } + protected: + ComponentsMap m_component; + comp_type& m_count; + }; + + } // namespace detail + + // This function computes the connected components of an undirected + // graph using a single application of depth first search. + + template + inline typename property_traits::value_type + connected_components(const Graph& g, ComponentMap c, + const bgl_named_params& params) + { + if (num_vertices(g) == 0) return 0; + + typedef typename graph_traits::vertex_descriptor Vertex; + function_requires< WritablePropertyMapConcept >(); + typedef typename boost::graph_traits::directed_category directed; + BOOST_STATIC_ASSERT((boost::is_same::value)); + + typedef typename property_traits::value_type comp_type; + // c_count initialized to "nil" (with nil represented by (max)()) + comp_type c_count((std::numeric_limits::max)()); + detail::components_recorder vis(c, c_count); + depth_first_search(g, params.visitor(vis)); + return c_count + 1; + } + + template + inline typename property_traits::value_type + connected_components(const Graph& g, ComponentMap c) + { + if (num_vertices(g) == 0) return 0; + + typedef typename graph_traits::vertex_descriptor Vertex; + function_requires< WritablePropertyMapConcept >(); + typedef typename boost::graph_traits::directed_category directed; + BOOST_STATIC_ASSERT((boost::is_same::value)); + + typedef typename property_traits::value_type comp_type; + // c_count initialized to "nil" (with nil represented by (max)()) + comp_type c_count((std::numeric_limits::max)()); + detail::components_recorder vis(c, c_count); + depth_first_search(g, visitor(vis)); + return c_count + 1; + } + + +} // namespace boost + + +#endif // BOOST_GRAPH_CONNECTED_COMPONENTS_HPP diff --git a/win32/include/boost/graph/copy.hpp b/win32/include/boost/graph/copy.hpp new file mode 100755 index 000000000..11b65b504 --- /dev/null +++ b/win32/include/boost/graph/copy.hpp @@ -0,0 +1,450 @@ +// +//======================================================================= +// Copyright 1997-2001 University of Notre Dame. +// Authors: Jeremy G. Siek, Lie-Quan Lee, Andrew Lumsdaine +// +// 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) +//======================================================================= +// + +/* + This file implements the following functions: + + + template + void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out) + + template + void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out, + const bgl_named_params& params) + + + template + typename graph_traits::vertex_descriptor + copy_component(IncidenceGraph& g_in, + typename graph_traits::vertex_descriptor src, + MutableGraph& g_out) + + template + typename graph_traits::vertex_descriptor + copy_component(IncidenceGraph& g_in, + typename graph_traits::vertex_descriptor src, + MutableGraph& g_out, + const bgl_named_params& params) + */ + + +#ifndef BOOST_GRAPH_COPY_HPP +#define BOOST_GRAPH_COPY_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + namespace detail { + + // Default edge and vertex property copiers + + template + struct edge_copier { + edge_copier(const Graph1& g1, Graph2& g2) + : edge_all_map1(get(edge_all, g1)), + edge_all_map2(get(edge_all, g2)) { } + + template + void operator()(const Edge1& e1, Edge2& e2) const { + put(edge_all_map2, e2, get(edge_all_map1, e1)); + } + typename property_map::const_type edge_all_map1; + mutable typename property_map::type edge_all_map2; + }; + template + inline edge_copier + make_edge_copier(const Graph1& g1, Graph2& g2) + { + return edge_copier(g1, g2); + } + + template + struct vertex_copier { + vertex_copier(const Graph1& g1, Graph2& g2) + : vertex_all_map1(get(vertex_all, g1)), + vertex_all_map2(get(vertex_all, g2)) { } + + template + void operator()(const Vertex1& v1, Vertex2& v2) const { + put(vertex_all_map2, v2, get(vertex_all_map1, v1)); + } + typename property_map::const_type vertex_all_map1; + mutable typename property_map::type + vertex_all_map2; + }; + template + inline vertex_copier + make_vertex_copier(const Graph1& g1, Graph2& g2) + { + return vertex_copier(g1, g2); + } + + // Copy all the vertices and edges of graph g_in into graph g_out. + // The copy_vertex and copy_edge function objects control how vertex + // and edge properties are copied. + + template + struct copy_graph_impl { }; + + template <> struct copy_graph_impl<0> + { + template + static void apply(const Graph& g_in, MutableGraph& g_out, + CopyVertex copy_vertex, CopyEdge copy_edge, + Orig2CopyVertexIndexMap orig2copy, IndexMap) + { + typename graph_traits::vertex_iterator vi, vi_end; + for (tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) { + typename graph_traits::vertex_descriptor + new_v = add_vertex(g_out); + put(orig2copy, *vi, new_v); + copy_vertex(*vi, new_v); + } + typename graph_traits::edge_iterator ei, ei_end; + for (tie(ei, ei_end) = edges(g_in); ei != ei_end; ++ei) { + typename graph_traits::edge_descriptor new_e; + bool inserted; + tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei, g_in)), + get(orig2copy, target(*ei, g_in)), + g_out); + copy_edge(*ei, new_e); + } + } + }; + + // for directed graphs + template <> struct copy_graph_impl<1> + { + template + static void apply(const Graph& g_in, MutableGraph& g_out, + CopyVertex copy_vertex, CopyEdge copy_edge, + Orig2CopyVertexIndexMap orig2copy, IndexMap) + { + typename graph_traits::vertex_iterator vi, vi_end; + for (tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) { + typename graph_traits::vertex_descriptor + new_v = add_vertex(g_out); + put(orig2copy, *vi, new_v); + copy_vertex(*vi, new_v); + } + for (tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) { + typename graph_traits::out_edge_iterator ei, ei_end; + for (tie(ei, ei_end) = out_edges(*vi, g_in); ei != ei_end; ++ei) { + typename graph_traits::edge_descriptor new_e; + bool inserted; + tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei, g_in)), + get(orig2copy, target(*ei, g_in)), + g_out); + copy_edge(*ei, new_e); + } + } + } + }; + + // for undirected graphs + template <> struct copy_graph_impl<2> + { + template + static void apply(const Graph& g_in, MutableGraph& g_out, + CopyVertex copy_vertex, CopyEdge copy_edge, + Orig2CopyVertexIndexMap orig2copy, + IndexMap index_map) + { + typedef color_traits Color; + std::vector + color(num_vertices(g_in), Color::white()); + typename graph_traits::vertex_iterator vi, vi_end; + for (tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) { + typename graph_traits::vertex_descriptor + new_v = add_vertex(g_out); + put(orig2copy, *vi, new_v); + copy_vertex(*vi, new_v); + } + for (tie(vi, vi_end) = vertices(g_in); vi != vi_end; ++vi) { + typename graph_traits::out_edge_iterator ei, ei_end; + for (tie(ei, ei_end) = out_edges(*vi, g_in); ei != ei_end; ++ei) { + typename graph_traits::edge_descriptor new_e; + bool inserted; + if (color[get(index_map, target(*ei, g_in))] == Color::white()) { + tie(new_e, inserted) = add_edge(get(orig2copy, source(*ei,g_in)), + get(orig2copy, target(*ei,g_in)), + g_out); + copy_edge(*ei, new_e); + } + } + color[get(index_map, *vi)] = Color::black(); + } + } + }; + + template + struct choose_graph_copy { + typedef typename Graph::traversal_category Trv; + typedef typename Graph::directed_category Dr; + enum { algo = + (is_convertible::value + && is_convertible::value) + ? 0 : is_convertible::value ? 1 : 2 }; + typedef copy_graph_impl type; + }; + + //------------------------------------------------------------------------- + struct choose_copier_parameter { + template + struct bind_ { + typedef const P& result_type; + static result_type apply(const P& p, const G1&, G2&) + { return p; } + }; + }; + struct choose_default_edge_copier { + template + struct bind_ { + typedef edge_copier result_type; + static result_type apply(const P&, const G1& g1, G2& g2) { + return result_type(g1, g2); + } + }; + }; + template + struct choose_edge_copy { + typedef choose_copier_parameter type; + }; + template <> + struct choose_edge_copy { + typedef choose_default_edge_copier type; + }; + template + struct choose_edge_copier_helper { + typedef typename choose_edge_copy::type Selector; + typedef typename Selector:: template bind_ Bind; + typedef Bind type; + typedef typename Bind::result_type result_type; + }; + template + typename detail::choose_edge_copier_helper::result_type + choose_edge_copier(const Param& params, const G1& g_in, G2& g_out) + { + typedef typename + detail::choose_edge_copier_helper::type Choice; + return Choice::apply(params, g_in, g_out); + } + + + struct choose_default_vertex_copier { + template + struct bind_ { + typedef vertex_copier result_type; + static result_type apply(const P&, const G1& g1, G2& g2) { + return result_type(g1, g2); + } + }; + }; + template + struct choose_vertex_copy { + typedef choose_copier_parameter type; + }; + template <> + struct choose_vertex_copy { + typedef choose_default_vertex_copier type; + }; + template + struct choose_vertex_copier_helper { + typedef typename choose_vertex_copy::type Selector; + typedef typename Selector:: template bind_ Bind; + typedef Bind type; + typedef typename Bind::result_type result_type; + }; + template + typename detail::choose_vertex_copier_helper::result_type + choose_vertex_copier(const Param& params, const G1& g_in, G2& g_out) + { + typedef typename + detail::choose_vertex_copier_helper::type Choice; + return Choice::apply(params, g_in, g_out); + } + + } // namespace detail + + + template + void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out) + { + if (num_vertices(g_in) == 0) + return; + typedef typename graph_traits::vertex_descriptor vertex_t; + std::vector orig2copy(num_vertices(g_in)); + typedef typename detail::choose_graph_copy::type + copy_impl; + copy_impl::apply + (g_in, g_out, + detail::make_vertex_copier(g_in, g_out), + detail::make_edge_copier(g_in, g_out), + make_iterator_property_map(orig2copy.begin(), + get(vertex_index, g_in), orig2copy[0]), + get(vertex_index, g_in) + ); + } + + template + void copy_graph(const VertexListGraph& g_in, MutableGraph& g_out, + const bgl_named_params& params) + { + typename std::vector::size_type n; + n = is_default_param(get_param(params, orig_to_copy_t())) + ? num_vertices(g_in) : 1; + if (n == 0) + return; + std::vector::vertex_descriptor> + orig2copy(n); + + typedef typename detail::choose_graph_copy::type + copy_impl; + copy_impl::apply + (g_in, g_out, + detail::choose_vertex_copier(get_param(params, vertex_copy_t()), + g_in, g_out), + detail::choose_edge_copier(get_param(params, edge_copy_t()), + g_in, g_out), + choose_param(get_param(params, orig_to_copy_t()), + make_iterator_property_map + (orig2copy.begin(), + choose_const_pmap(get_param(params, vertex_index), + g_in, vertex_index), orig2copy[0])), + choose_const_pmap(get_param(params, vertex_index), g_in, vertex_index) + ); + } + + namespace detail { + + template + struct graph_copy_visitor : public bfs_visitor<> + { + graph_copy_visitor(NewGraph& graph, Copy2OrigIndexMap c, + CopyVertex cv, CopyEdge ce) + : g_out(graph), orig2copy(c), copy_vertex(cv), copy_edge(ce) { } + + template + void examine_vertex(Vertex u, const Graph& g_in) const { + typename graph_traits::vertex_descriptor + new_u = add_vertex(g_out); + put(orig2copy, u, new_u); + copy_vertex(u, new_u); + } + + template + void examine_edge(Edge e, const Graph& g_in) const { + typename graph_traits::edge_descriptor new_e; + bool inserted; + tie(new_e, inserted) = add_edge(get(orig2copy, source(e, g_in)), + get(orig2copy, target(e, g_in)), + g_out); + copy_edge(e, new_e); + } + private: + NewGraph& g_out; + Copy2OrigIndexMap orig2copy; + CopyVertex copy_vertex; + CopyEdge copy_edge; + }; + + template + typename graph_traits::vertex_descriptor + copy_component_impl + (const Graph& g_in, + typename graph_traits::vertex_descriptor src, + MutableGraph& g_out, + CopyVertex copy_vertex, CopyEdge copy_edge, + Orig2CopyVertexIndexMap orig2copy, + const Params& params) + { + graph_copy_visitor vis(g_out, orig2copy, copy_vertex, copy_edge); + breadth_first_search(g_in, src, params.visitor(vis)); + return get(orig2copy, src); + } + + } // namespace detail + + + // Copy all the vertices and edges of graph g_in that are reachable + // from the source vertex into graph g_out. Return the vertex + // in g_out that matches the source vertex of g_in. + template + typename graph_traits::vertex_descriptor + copy_component(IncidenceGraph& g_in, + typename graph_traits::vertex_descriptor src, + MutableGraph& g_out, + const bgl_named_params& params) + { + typename std::vector::size_type n; + n = is_default_param(get_param(params, orig_to_copy_t())) + ? num_vertices(g_in) : 1; + std::vector::vertex_descriptor> + orig2copy(n); + + return detail::copy_component_impl + (g_in, src, g_out, + detail::choose_vertex_copier(get_param(params, vertex_copy_t()), + g_in, g_out), + detail::choose_edge_copier(get_param(params, edge_copy_t()), + g_in, g_out), + choose_param(get_param(params, orig_to_copy_t()), + make_iterator_property_map + (orig2copy.begin(), + choose_pmap(get_param(params, vertex_index), + g_in, vertex_index), orig2copy[0])), + params + ); + } + + template + typename graph_traits::vertex_descriptor + copy_component(IncidenceGraph& g_in, + typename graph_traits::vertex_descriptor src, + MutableGraph& g_out) + { + std::vector::vertex_descriptor> + orig2copy(num_vertices(g_in)); + + return detail::copy_component_impl + (g_in, src, g_out, + make_vertex_copier(g_in, g_out), + make_edge_copier(g_in, g_out), + make_iterator_property_map(orig2copy.begin(), + get(vertex_index, g_in), orig2copy[0]), + bgl_named_params('x') // dummy param object + ); + } + +} // namespace boost + +#endif // BOOST_GRAPH_COPY_HPP diff --git a/win32/include/boost/graph/create_condensation_graph.hpp b/win32/include/boost/graph/create_condensation_graph.hpp new file mode 100755 index 000000000..92ab0c322 --- /dev/null +++ b/win32/include/boost/graph/create_condensation_graph.hpp @@ -0,0 +1,83 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_CREATE_CONDENSATION_GRAPH_HPP +#define BOOST_CREATE_CONDENSATION_GRAPH_HPP + +#include +#include + +namespace boost { + + template + void create_condensation_graph(const Graph& g, + const ComponentLists& components, + ComponentNumberMap component_number, + CondensationGraph& cg, + EdgeMultiplicityMap edge_mult_map) + { + typedef typename graph_traits::vertex_descriptor vertex; + typedef typename graph_traits::vertices_size_type size_type; + typedef typename graph_traits::vertex_descriptor + cg_vertex; + std::vector to_cg_vertex(components.size()); + for (size_type s = 0; s < components.size(); ++s) + to_cg_vertex[s] = add_vertex(cg); + + for (size_type si = 0; si < components.size(); ++si) { + cg_vertex s = to_cg_vertex[si]; + std::vector adj; + for (size_type i = 0; i < components[si].size(); ++i) { + vertex u = components[s][i]; + typename graph_traits::adjacency_iterator v, v_end; + for (tie(v, v_end) = adjacent_vertices(u, g); v != v_end; ++v) { + cg_vertex t = to_cg_vertex[component_number[*v]]; + if (s != t) // Avoid loops in the condensation graph + adj.push_back(t); + } + } + std::sort(adj.begin(), adj.end()); + if (! adj.empty()) { + size_type i = 0; + cg_vertex t = adj[i]; + typename graph_traits::edge_descriptor e; + bool inserted; + tie(e, inserted) = add_edge(s, t, cg); + put(edge_mult_map, e, 1); + ++i; + while (i < adj.size()) { + if (adj[i] == t) + put(edge_mult_map, e, get(edge_mult_map, e) + 1); + else { + t = adj[i]; + tie(e, inserted) = add_edge(s, t, cg); + put(edge_mult_map, e, 1); + } + ++i; + } + } + } + } + + template + void create_condensation_graph(const Graph& g, + const ComponentLists& components, + ComponentNumberMap component_number, + CondensationGraph& cg) + { + create_condensation_graph(g, components, component_number, cg, + dummy_property_map()); + } + +} // namespace boost + +#endif // BOOST_CREATE_CONDENSATION_GRAPH_HPP diff --git a/win32/include/boost/graph/cuthill_mckee_ordering.hpp b/win32/include/boost/graph/cuthill_mckee_ordering.hpp new file mode 100755 index 000000000..efb9cf0e2 --- /dev/null +++ b/win32/include/boost/graph/cuthill_mckee_ordering.hpp @@ -0,0 +1,190 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2004, 2005 Trustees of Indiana University +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, +// Doug Gregor, D. Kevin McGrath +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_CUTHILL_MCKEE_HPP +#define BOOST_GRAPH_CUTHILL_MCKEE_HPP + +#include +#include +#include + + +/* + (Reverse) Cuthill-McKee Algorithm for matrix reordering +*/ + +namespace boost { + + namespace detail { + + + + template < typename OutputIterator, typename Buffer, typename DegreeMap > + class bfs_rcm_visitor:public default_bfs_visitor + { + public: + bfs_rcm_visitor(OutputIterator *iter, Buffer *b, DegreeMap deg): + permutation(iter), Qptr(b), degree(deg) { } + template + void examine_vertex(Vertex u, Graph&) { + *(*permutation)++ = u; + index_begin = Qptr->size(); + } + template + void finish_vertex(Vertex, Graph&) { + using std::sort; + + typedef typename property_traits::value_type ds_type; + + typedef indirect_cmp > Compare; + Compare comp(degree); + + sort(Qptr->begin()+index_begin, Qptr->end(), comp); + } + protected: + OutputIterator *permutation; + int index_begin; + Buffer *Qptr; + DegreeMap degree; + }; + + } // namespace detail + + + // Reverse Cuthill-McKee algorithm with a given starting Vertex. + // + // If user provides a reverse iterator, this will be a reverse-cuthill-mckee + // algorithm, otherwise it will be a standard CM algorithm + + template + OutputIterator + cuthill_mckee_ordering(const Graph& g, + std::deque< typename + graph_traits::vertex_descriptor > vertex_queue, + OutputIterator permutation, + ColorMap color, DegreeMap degree) + { + + //create queue, visitor...don't forget namespaces! + typedef typename property_traits::value_type ds_type; + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename boost::sparse::sparse_ordering_queue queue; + typedef typename detail::bfs_rcm_visitor Visitor; + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + + + queue Q; + + //create a bfs_rcm_visitor as defined above + Visitor vis(&permutation, &Q, degree); + + typename graph_traits::vertex_iterator ui, ui_end; + + // Copy degree to pseudo_degree + // initialize the color map + for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui){ + put(color, *ui, Color::white()); + } + + + while( !vertex_queue.empty() ) { + Vertex s = vertex_queue.front(); + vertex_queue.pop_front(); + + //call BFS with visitor + breadth_first_visit(g, s, Q, vis, color); + } + return permutation; + } + + + // This is the case where only a single starting vertex is supplied. + template + OutputIterator + cuthill_mckee_ordering(const Graph& g, + typename graph_traits::vertex_descriptor s, + OutputIterator permutation, + ColorMap color, DegreeMap degree) + { + + std::deque< typename graph_traits::vertex_descriptor > vertex_queue; + vertex_queue.push_front( s ); + + return cuthill_mckee_ordering(g, vertex_queue, permutation, color, degree); + + } + + + // This is the version of CM which selects its own starting vertex + template < class Graph, class OutputIterator, + class ColorMap, class DegreeMap> + OutputIterator + cuthill_mckee_ordering(const Graph& G, OutputIterator permutation, + ColorMap color, DegreeMap degree) + { + if (vertices(G).first == vertices(G).second) + return permutation; + + typedef typename boost::graph_traits::vertex_descriptor Vertex; + typedef typename boost::graph_traits::vertex_iterator VerIter; + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + + std::deque vertex_queue; + + // Mark everything white + BGL_FORALL_VERTICES_T(v, G, Graph) put(color, v, Color::white()); + + // Find one vertex from each connected component + BGL_FORALL_VERTICES_T(v, G, Graph) { + if (get(color, v) == Color::white()) { + depth_first_visit(G, v, dfs_visitor<>(), color); + vertex_queue.push_back(v); + } + } + + // Find starting nodes for all vertices + // TBD: How to do this with a directed graph? + for (typename std::deque::iterator i = vertex_queue.begin(); + i != vertex_queue.end(); ++i) + *i = find_starting_node(G, *i, color, degree); + + return cuthill_mckee_ordering(G, vertex_queue, permutation, + color, degree); + } + + template + OutputIterator + cuthill_mckee_ordering(const Graph& G, OutputIterator permutation, + VertexIndexMap index_map) + { + if (vertices(G).first == vertices(G).second) + return permutation; + + typedef out_degree_property_map DegreeMap; + std::vector colors(num_vertices(G)); + return cuthill_mckee_ordering(G, permutation, + make_iterator_property_map(&colors[0], + index_map, + colors[0]), + make_out_degree_map(G)); + } + + template + inline OutputIterator + cuthill_mckee_ordering(const Graph& G, OutputIterator permutation) + { return cuthill_mckee_ordering(G, permutation, get(vertex_index, G)); } +} // namespace boost + + +#endif // BOOST_GRAPH_CUTHILL_MCKEE_HPP diff --git a/win32/include/boost/graph/dag_shortest_paths.hpp b/win32/include/boost/graph/dag_shortest_paths.hpp new file mode 100755 index 000000000..347330073 --- /dev/null +++ b/win32/include/boost/graph/dag_shortest_paths.hpp @@ -0,0 +1,157 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_DAG_SHORTEST_PATHS_HPP +#define BOOST_GRAPH_DAG_SHORTEST_PATHS_HPP + +#include +#include + +// single-source shortest paths for a Directed Acyclic Graph (DAG) + +namespace boost { + + // Initalize distances and call depth first search + template + inline void + dag_shortest_paths + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + DistanceMap distance, WeightMap weight, ColorMap color, + PredecessorMap pred, + DijkstraVisitor vis, Compare compare, Combine combine, + DistInf inf, DistZero zero) + { + typedef typename graph_traits::vertex_descriptor Vertex; + std::vector rev_topo_order; + rev_topo_order.reserve(num_vertices(g)); + + // Call 'depth_first_visit', not 'topological_sort', because we don't + // want to traverse the entire graph, only vertices reachable from 's', + // and 'topological_sort' will traverse everything. The logic below + // is the same as for 'topological_sort', only we call 'depth_first_visit' + // and 'topological_sort' calls 'depth_first_search'. + topo_sort_visitor > > + topo_visitor(std::back_inserter(rev_topo_order)); + depth_first_visit(g, s, topo_visitor, color); + + typename graph_traits::vertex_iterator ui, ui_end; + for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) { + put(distance, *ui, inf); + put(pred, *ui, *ui); + } + + put(distance, s, zero); + vis.discover_vertex(s, g); + typename std::vector::reverse_iterator i; + for (i = rev_topo_order.rbegin(); i != rev_topo_order.rend(); ++i) { + Vertex u = *i; + vis.examine_vertex(u, g); + typename graph_traits::out_edge_iterator e, e_end; + for (tie(e, e_end) = out_edges(u, g); e != e_end; ++e) { + vis.discover_vertex(target(*e, g), g); + bool decreased = relax(*e, g, weight, pred, distance, + combine, compare); + if (decreased) + vis.edge_relaxed(*e, g); + else + vis.edge_not_relaxed(*e, g); + } + vis.finish_vertex(u, g); + } + } + + namespace detail { + + // Defaults are the same as Dijkstra's algorithm + + // Handle Distance Compare, Combine, Inf and Zero defaults + template + inline void + dag_sp_dispatch2 + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + DistanceMap distance, WeightMap weight, ColorMap color, IndexMap id, + DijkstraVisitor vis, const Params& params) + { + typedef typename property_traits::value_type D; + dummy_property_map p_map; + dag_shortest_paths + (g, s, distance, weight, color, + choose_param(get_param(params, vertex_predecessor), p_map), + vis, + choose_param(get_param(params, distance_compare_t()), std::less()), + choose_param(get_param(params, distance_combine_t()), closed_plus()), + choose_param(get_param(params, distance_inf_t()), + (std::numeric_limits::max)()), + choose_param(get_param(params, distance_zero_t()), + D())); + } + + // Handle DistanceMap and ColorMap defaults + template + inline void + dag_sp_dispatch1 + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + DistanceMap distance, WeightMap weight, ColorMap color, IndexMap id, + DijkstraVisitor vis, const Params& params) + { + typedef typename property_traits::value_type T; + typename std::vector::size_type n; + n = is_default_param(distance) ? num_vertices(g) : 1; + std::vector distance_map(n); + n = is_default_param(color) ? num_vertices(g) : 1; + std::vector color_map(n); + + dag_sp_dispatch2 + (g, s, + choose_param(distance, + make_iterator_property_map(distance_map.begin(), id, + distance_map[0])), + weight, + choose_param(color, + make_iterator_property_map(color_map.begin(), id, + color_map[0])), + id, vis, params); + } + + } // namespace detail + + template + inline void + dag_shortest_paths + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + const bgl_named_params& params) + { + // assert that the graph is directed... + null_visitor null_vis; + detail::dag_sp_dispatch1 + (g, s, + get_param(params, vertex_distance), + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + get_param(params, vertex_color), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index), + choose_param(get_param(params, graph_visitor), + make_dijkstra_visitor(null_vis)), + params); + } + +} // namespace boost + +#endif // BOOST_GRAPH_DAG_SHORTEST_PATHS_HPP diff --git a/win32/include/boost/graph/depth_first_search.hpp b/win32/include/boost/graph/depth_first_search.hpp new file mode 100755 index 000000000..423af7b8e --- /dev/null +++ b/win32/include/boost/graph/depth_first_search.hpp @@ -0,0 +1,365 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2003 Bruce Barr +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// 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) +//======================================================================= + +// Nonrecursive implementation of depth_first_visit_impl submitted by +// Bruce Barr, schmoost yahoo.com, May/June 2003. +#ifndef BOOST_GRAPH_RECURSIVE_DFS_HPP +#define BOOST_GRAPH_RECURSIVE_DFS_HPP + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace boost { + + template + class DFSVisitorConcept { + public: + void constraints() { + function_requires< CopyConstructibleConcept >(); + vis.initialize_vertex(u, g); + vis.start_vertex(u, g); + vis.discover_vertex(u, g); + vis.examine_edge(e, g); + vis.tree_edge(e, g); + vis.back_edge(e, g); + vis.forward_or_cross_edge(e, g); + vis.finish_vertex(u, g); + } + private: + Visitor vis; + Graph g; + typename graph_traits::vertex_descriptor u; + typename graph_traits::edge_descriptor e; + }; + + namespace detail { + + struct nontruth2 { + template + bool operator()(const T&, const T2&) const { return false; } + }; + + +// Define BOOST_RECURSIVE_DFS to use older, recursive version. +// It is retained for a while in order to perform performance +// comparison. +#ifndef BOOST_RECURSIVE_DFS + + // If the vertex u and the iterators ei and ei_end are thought of as the + // context of the algorithm, each push and pop from the stack could + // be thought of as a context shift. + // Each pass through "while (ei != ei_end)" may refer to the out-edges of + // an entirely different vertex, because the context of the algorithm + // shifts every time a white adjacent vertex is discovered. + // The corresponding context shift back from the adjacent vertex occurs + // after all of its out-edges have been examined. + // + // See http://lists.boost.org/MailArchives/boost/msg48752.php for FAQ. + + template + void depth_first_visit_impl + (const IncidenceGraph& g, + typename graph_traits::vertex_descriptor u, + DFSVisitor& vis, + ColorMap color, TerminatorFunc func = TerminatorFunc()) + { + function_requires >(); + function_requires >(); + typedef typename graph_traits::vertex_descriptor Vertex; + function_requires< ReadWritePropertyMapConcept >(); + typedef typename property_traits::value_type ColorValue; + function_requires< ColorValueConcept >(); + typedef color_traits Color; + typedef typename graph_traits::out_edge_iterator Iter; + typedef std::pair > VertexInfo; + + Iter ei, ei_end; + std::vector stack; + + // Possible optimization for vector + //stack.reserve(num_vertices(g)); + + typedef typename unwrap_reference::type TF; + + put(color, u, Color::gray()); + vis.discover_vertex(u, g); + tie(ei, ei_end) = out_edges(u, g); + // Variable is needed to workaround a borland bug. + TF& fn = static_cast(func); + if (fn(u, g)) { + // If this vertex terminates the search, we push empty range + stack.push_back(std::make_pair(u, std::make_pair(ei_end, ei_end))); + } else { + stack.push_back(std::make_pair(u, std::make_pair(ei, ei_end))); + } + while (!stack.empty()) { + VertexInfo& back = stack.back(); + u = back.first; + tie(ei, ei_end) = back.second; + stack.pop_back(); + while (ei != ei_end) { + Vertex v = target(*ei, g); + vis.examine_edge(*ei, g); + ColorValue v_color = get(color, v); + if (v_color == Color::white()) { + vis.tree_edge(*ei, g); + stack.push_back(std::make_pair(u, std::make_pair(++ei, ei_end))); + u = v; + put(color, u, Color::gray()); + vis.discover_vertex(u, g); + tie(ei, ei_end) = out_edges(u, g); + if (fn(u, g)) { + ei = ei_end; + } + } else if (v_color == Color::gray()) { + vis.back_edge(*ei, g); + ++ei; + } else { + vis.forward_or_cross_edge(*ei, g); + ++ei; + } + } + put(color, u, Color::black()); + vis.finish_vertex(u, g); + } + } + +#else // BOOST_RECURSIVE_DFS is defined + + template + void depth_first_visit_impl + (const IncidenceGraph& g, + typename graph_traits::vertex_descriptor u, + DFSVisitor& vis, // pass-by-reference here, important! + ColorMap color, TerminatorFunc func) + { + function_requires >(); + function_requires >(); + typedef typename graph_traits::vertex_descriptor Vertex; + function_requires< ReadWritePropertyMapConcept >(); + typedef typename property_traits::value_type ColorValue; + function_requires< ColorValueConcept >(); + typedef color_traits Color; + typename graph_traits::out_edge_iterator ei, ei_end; + + put(color, u, Color::gray()); vis.discover_vertex(u, g); + + typedef typename unwrap_reference::type TF; + // Variable is needed to workaround a borland bug. + TF& fn = static_cast(func); + if (!fn(u, g)) + for (tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) { + Vertex v = target(*ei, g); vis.examine_edge(*ei, g); + ColorValue v_color = get(color, v); + if (v_color == Color::white()) { vis.tree_edge(*ei, g); + depth_first_visit_impl(g, v, vis, color, func); + } else if (v_color == Color::gray()) vis.back_edge(*ei, g); + else vis.forward_or_cross_edge(*ei, g); + } + put(color, u, Color::black()); vis.finish_vertex(u, g); + } + +#endif + + } // namespace detail + + template + void + depth_first_search(const VertexListGraph& g, DFSVisitor vis, ColorMap color, + typename graph_traits::vertex_descriptor start_vertex) + { + typedef typename graph_traits::vertex_descriptor Vertex; + function_requires >(); + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + + typename graph_traits::vertex_iterator ui, ui_end; + for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) { + put(color, *ui, Color::white()); vis.initialize_vertex(*ui, g); + } + + if (start_vertex != implicit_cast(*vertices(g).first)){ vis.start_vertex(start_vertex, g); + detail::depth_first_visit_impl(g, start_vertex, vis, color, + detail::nontruth2()); + } + + for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) { + ColorValue u_color = get(color, *ui); + if (u_color == Color::white()) { vis.start_vertex(*ui, g); + detail::depth_first_visit_impl(g, *ui, vis, color, detail::nontruth2()); + } + } + } + + template + void + depth_first_search(const VertexListGraph& g, DFSVisitor vis, ColorMap color) + { + if (vertices(g).first == vertices(g).second) + return; + + depth_first_search(g, vis, color, *vertices(g).first); + } + + namespace detail { + template + struct dfs_dispatch { + + template + static void + apply(const VertexListGraph& g, DFSVisitor vis, Vertex start_vertex, + const bgl_named_params&, + ColorMap color) + { + depth_first_search(g, vis, color, start_vertex); + } + }; + + template <> + struct dfs_dispatch { + template + static void + apply(const VertexListGraph& g, DFSVisitor vis, Vertex start_vertex, + const bgl_named_params& params, + detail::error_property_not_found) + { + std::vector color_vec(num_vertices(g)); + default_color_type c = white_color; // avoid warning about un-init + depth_first_search + (g, vis, make_iterator_property_map + (color_vec.begin(), + choose_const_pmap(get_param(params, vertex_index), + g, vertex_index), c), + start_vertex); + } + }; + } // namespace detail + + + template + class dfs_visitor { + public: + dfs_visitor() { } + dfs_visitor(Visitors vis) : m_vis(vis) { } + + template + void initialize_vertex(Vertex u, const Graph& g) { + invoke_visitors(m_vis, u, g, ::boost::on_initialize_vertex()); + } + template + void start_vertex(Vertex u, const Graph& g) { + invoke_visitors(m_vis, u, g, ::boost::on_start_vertex()); + } + template + void discover_vertex(Vertex u, const Graph& g) { + invoke_visitors(m_vis, u, g, ::boost::on_discover_vertex()); + } + template + void examine_edge(Edge u, const Graph& g) { + invoke_visitors(m_vis, u, g, ::boost::on_examine_edge()); + } + template + void tree_edge(Edge u, const Graph& g) { + invoke_visitors(m_vis, u, g, ::boost::on_tree_edge()); + } + template + void back_edge(Edge u, const Graph& g) { + invoke_visitors(m_vis, u, g, ::boost::on_back_edge()); + } + template + void forward_or_cross_edge(Edge u, const Graph& g) { + invoke_visitors(m_vis, u, g, ::boost::on_forward_or_cross_edge()); + } + template + void finish_vertex(Vertex u, const Graph& g) { + invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex()); + } + + BOOST_GRAPH_EVENT_STUB(on_initialize_vertex,dfs) + BOOST_GRAPH_EVENT_STUB(on_start_vertex,dfs) + BOOST_GRAPH_EVENT_STUB(on_discover_vertex,dfs) + BOOST_GRAPH_EVENT_STUB(on_examine_edge,dfs) + BOOST_GRAPH_EVENT_STUB(on_tree_edge,dfs) + BOOST_GRAPH_EVENT_STUB(on_back_edge,dfs) + BOOST_GRAPH_EVENT_STUB(on_forward_or_cross_edge,dfs) + BOOST_GRAPH_EVENT_STUB(on_finish_vertex,dfs) + + protected: + Visitors m_vis; + }; + template + dfs_visitor + make_dfs_visitor(Visitors vis) { + return dfs_visitor(vis); + } + typedef dfs_visitor<> default_dfs_visitor; + + + // Named Parameter Variant + template + void + depth_first_search(const VertexListGraph& g, + const bgl_named_params& params) + { + typedef typename property_value< bgl_named_params, + vertex_color_t>::type C; + if (vertices(g).first == vertices(g).second) + return; + detail::dfs_dispatch::apply + (g, + choose_param(get_param(params, graph_visitor), + make_dfs_visitor(null_visitor())), + choose_param(get_param(params, root_vertex_t()), + *vertices(g).first), + params, + get_param(params, vertex_color) + ); + } + + template + void depth_first_visit + (const IncidenceGraph& g, + typename graph_traits::vertex_descriptor u, + DFSVisitor vis, ColorMap color) + { + vis.start_vertex(u, g); + detail::depth_first_visit_impl(g, u, vis, color, detail::nontruth2()); + } + + template + void depth_first_visit + (const IncidenceGraph& g, + typename graph_traits::vertex_descriptor u, + DFSVisitor vis, ColorMap color, TerminatorFunc func = TerminatorFunc()) + { + vis.start_vertex(u, g); + detail::depth_first_visit_impl(g, u, vis, color, func); + } + + +} // namespace boost + + +#endif diff --git a/win32/include/boost/graph/detail/adj_list_edge_iterator.hpp b/win32/include/boost/graph/detail/adj_list_edge_iterator.hpp new file mode 100755 index 000000000..ad3ebe186 --- /dev/null +++ b/win32/include/boost/graph/detail/adj_list_edge_iterator.hpp @@ -0,0 +1,117 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_DETAIL_ADJ_LIST_EDGE_ITERATOR_HPP +#define BOOST_GRAPH_DETAIL_ADJ_LIST_EDGE_ITERATOR_HPP + +#include +#include +#include + +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) +# define BOOST_GRAPH_NO_OPTIONAL +#endif + +#ifdef BOOST_GRAPH_NO_OPTIONAL +# define BOOST_GRAPH_MEMBER . +#else +# define BOOST_GRAPH_MEMBER -> +# include +#endif // ndef BOOST_GRAPH_NO_OPTIONAL + +namespace boost { + + namespace detail { + + template + class adj_list_edge_iterator { + typedef adj_list_edge_iterator self; + public: + typedef std::forward_iterator_tag iterator_category; + typedef typename OutEdgeIterator::value_type value_type; + typedef typename OutEdgeIterator::reference reference; + typedef typename OutEdgeIterator::pointer pointer; + typedef typename OutEdgeIterator::difference_type difference_type; + typedef difference_type distance_type; + + inline adj_list_edge_iterator() {} + + inline adj_list_edge_iterator(const self& x) + : vBegin(x.vBegin), vCurr(x.vCurr), vEnd(x.vEnd), + edges(x.edges), m_g(x.m_g) { } + + template + inline adj_list_edge_iterator(VertexIterator b, + VertexIterator c, + VertexIterator e, + const G& g) + : vBegin(b), vCurr(c), vEnd(e), m_g(&g) { + if ( vCurr != vEnd ) { + while ( vCurr != vEnd && out_degree(*vCurr, *m_g) == 0 ) + ++vCurr; + if ( vCurr != vEnd ) + edges = out_edges(*vCurr, *m_g); + } + } + + /*Note: + In the directed graph cases, it is fine. + For undirected graphs, one edge go through twice. + */ + inline self& operator++() { + ++edges BOOST_GRAPH_MEMBER first; + if (edges BOOST_GRAPH_MEMBER first == edges BOOST_GRAPH_MEMBER second) + { + ++vCurr; + while ( vCurr != vEnd && out_degree(*vCurr, *m_g) == 0 ) + ++vCurr; + if ( vCurr != vEnd ) + edges = out_edges(*vCurr, *m_g); + } + return *this; + } + inline self operator++(int) { + self tmp = *this; + ++(*this); + return tmp; + } + inline value_type operator*() const + { return *edges BOOST_GRAPH_MEMBER first; } + inline bool operator==(const self& x) const { + return vCurr == x.vCurr + && (vCurr == vEnd + || edges BOOST_GRAPH_MEMBER first == x.edges BOOST_GRAPH_MEMBER first); + } + inline bool operator!=(const self& x) const { + return vCurr != x.vCurr + || (vCurr != vEnd + && edges BOOST_GRAPH_MEMBER first != x.edges BOOST_GRAPH_MEMBER first); + } + protected: + VertexIterator vBegin; + VertexIterator vCurr; + VertexIterator vEnd; + +#ifdef BOOST_GRAPH_NO_OPTIONAL + std::pair edges; +#else + boost::optional > + edges; +#endif // ndef BOOST_GRAPH_NO_OPTIONAL + const Graph* m_g; + }; + + } // namespace detail + +} + +#undef BOOST_GRAPH_MEMBER + +#endif // BOOST_GRAPH_DETAIL_ADJ_LIST_EDGE_ITERATOR_HPP diff --git a/win32/include/boost/graph/detail/adjacency_list.hpp b/win32/include/boost/graph/detail/adjacency_list.hpp new file mode 100755 index 000000000..1871d5743 --- /dev/null +++ b/win32/include/boost/graph/detail/adjacency_list.hpp @@ -0,0 +1,2844 @@ +// -*- c++ -*- +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_DETAIL_ADJACENCY_LIST_HPP +#define BOOST_GRAPH_DETAIL_ADJACENCY_LIST_HPP + +#include // for vertex_map in copy_impl +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Symbol truncation problems with MSVC, trying to shorten names. +#define stored_edge se_ +#define stored_edge_property sep_ +#define stored_edge_iter sei_ + +/* + Outline for this file: + + out_edge_iterator and in_edge_iterator implementation + edge_iterator for undirected graph + stored edge types (these object live in the out-edge/in-edge lists) + directed edges helper class + directed graph helper class + undirected graph helper class + bidirectional graph helper class + bidirectional graph helper class (without edge properties) + bidirectional graph helper class (with edge properties) + adjacency_list helper class + adj_list_impl class + vec_adj_list_impl class + adj_list_gen class + vertex property map + edge property map + + + Note: it would be nice to merge some of the undirected and + bidirectional code... it is awful similar. + */ + + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +// Stay out of the way of the concept checking class +# define Graph Graph_ +#endif + +namespace boost { + + namespace detail { + + template + struct directed_category_traits { + typedef directed_tag directed_category; + }; + + template <> + struct directed_category_traits { + typedef directed_tag directed_category; + }; + template <> + struct directed_category_traits { + typedef undirected_tag directed_category; + }; + template <> + struct directed_category_traits { + typedef bidirectional_tag directed_category; + }; + + template + struct target_is { + target_is(const Vertex& v) : m_target(v) { } + template + bool operator()(const StoredEdge& e) const { + return e.get_target() == m_target; + } + Vertex m_target; + }; + + // O(E/V) + template + void erase_from_incidence_list(EdgeList& el, vertex_descriptor v, + allow_parallel_edge_tag) + { + boost::graph_detail::erase_if(el, detail::target_is(v)); + } + // O(log(E/V)) + template + void erase_from_incidence_list(EdgeList& el, vertex_descriptor v, + disallow_parallel_edge_tag) + { + typedef typename EdgeList::value_type StoredEdge; + el.erase(StoredEdge(v)); + } + + //========================================================================= + // Out-Edge and In-Edge Iterator Implementation + + template + struct out_edge_iter + : iterator_adaptor< + out_edge_iter + , BaseIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , Difference + > + { + typedef iterator_adaptor< + out_edge_iter + , BaseIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , Difference + > super_t; + + inline out_edge_iter() { } + inline out_edge_iter(const BaseIter& i, const VertexDescriptor& src) + : super_t(i), m_src(src) { } + + inline EdgeDescriptor + dereference() const + { + return EdgeDescriptor(m_src, (*this->base()).get_target(), + &(*this->base()).get_property()); + } + VertexDescriptor m_src; + }; + + template + struct in_edge_iter + : iterator_adaptor< + in_edge_iter + , BaseIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , Difference + > + { + typedef iterator_adaptor< + in_edge_iter + , BaseIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , Difference + > super_t; + + inline in_edge_iter() { } + inline in_edge_iter(const BaseIter& i, const VertexDescriptor& src) + : super_t(i), m_src(src) { } + + inline EdgeDescriptor + dereference() const + { + return EdgeDescriptor((*this->base()).get_target(), m_src, + &this->base()->get_property()); + } + VertexDescriptor m_src; + }; + + //========================================================================= + // Undirected Edge Iterator Implementation + + template + struct undirected_edge_iter + : iterator_adaptor< + undirected_edge_iter + , EdgeIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , Difference + > + { + typedef iterator_adaptor< + undirected_edge_iter + , EdgeIter + , EdgeDescriptor + , use_default + , EdgeDescriptor + , Difference + > super_t; + + undirected_edge_iter() {} + + explicit undirected_edge_iter(EdgeIter i) + : super_t(i) {} + + inline EdgeDescriptor + dereference() const { + return EdgeDescriptor( + (*this->base()).m_source + , (*this->base()).m_target + , &this->base()->get_property()); + } + }; + + //========================================================================= + // Edge Storage Types (stored in the out-edge/in-edge lists) + + template + class stored_edge + : public boost::equality_comparable1< stored_edge, + boost::less_than_comparable1< stored_edge > > + { + public: + typedef no_property property_type; + inline stored_edge() { } + inline stored_edge(Vertex target, const no_property& = no_property()) + : m_target(target) { } + // Need to write this explicitly so stored_edge_property can + // invoke Base::operator= (at least, for SGI MIPSPro compiler) + inline stored_edge& operator=(const stored_edge& x) { + m_target = x.m_target; + return *this; + } + inline Vertex& get_target() const { return m_target; } + inline const no_property& get_property() const { return s_prop; } + inline bool operator==(const stored_edge& x) const + { return m_target == x.get_target(); } + inline bool operator<(const stored_edge& x) const + { return m_target < x.get_target(); } + //protected: need to add hash<> as a friend + static no_property s_prop; + // Sometimes target not used as key in the set, and in that case + // it is ok to change the target. + mutable Vertex m_target; + }; + template + no_property stored_edge::s_prop; + + template + class stored_edge_property : public stored_edge { + typedef stored_edge_property self; + typedef stored_edge Base; + public: + typedef Property property_type; + inline stored_edge_property() { } + inline stored_edge_property(Vertex target, + const Property& p = Property()) + : stored_edge(target), m_property(new Property(p)) { } + stored_edge_property(const self& x) + : Base(x), m_property(const_cast(x).m_property) { } + self& operator=(const self& x) { + Base::operator=(x); + m_property = const_cast(x).m_property; + return *this; + } + inline Property& get_property() { return *m_property; } + inline const Property& get_property() const { return *m_property; } + protected: + // Holding the property by-value causes edge-descriptor + // invalidation for add_edge() with EdgeList=vecS. Instead we + // hold a pointer to the property. std::auto_ptr is not + // a perfect fit for the job, but it is darn close. + std::auto_ptr m_property; + }; + + + template + class stored_edge_iter + : public stored_edge + { + public: + typedef Property property_type; + inline stored_edge_iter() { } + inline stored_edge_iter(Vertex v) + : stored_edge(v) { } + inline stored_edge_iter(Vertex v, Iter i, void* = 0) + : stored_edge(v), m_iter(i) { } + inline Property& get_property() { return m_iter->get_property(); } + inline const Property& get_property() const { + return m_iter->get_property(); + } + inline Iter get_iter() const { return m_iter; } + protected: + Iter m_iter; + }; + + // For when the EdgeList is a std::vector. + // Want to make the iterator stable, so use an offset + // instead of an iterator into a std::vector + template + class stored_ra_edge_iter + : public stored_edge + { + typedef typename EdgeVec::iterator Iter; + public: + typedef Property property_type; + inline stored_ra_edge_iter() { } + inline stored_ra_edge_iter(Vertex v, Iter i = Iter(), + EdgeVec* edge_vec = 0) + : stored_edge(v), m_i(i - edge_vec->begin()), m_vec(edge_vec){ } + inline Property& get_property() { return (*m_vec)[m_i].get_property(); } + inline const Property& get_property() const { + return (*m_vec)[m_i].get_property(); + } + inline Iter get_iter() const { return m_vec->begin() + m_i; } + protected: + std::size_t m_i; + EdgeVec* m_vec; + }; + + } // namespace detail + + template + const typename property_value::type& + get(Tag property_tag, + const detail::stored_edge_property& e) + { + return get_property_value(e.get_property(), property_tag); + } + + template + const typename property_value::type& + get(Tag property_tag, + const detail::stored_edge_iter& e) + { + return get_property_value(e.get_property(), property_tag); + } + + template + const typename property_value::type& + get(Tag property_tag, + const detail::stored_ra_edge_iter& e) + { + return get_property_value(e.get_property(), property_tag); + } + + //========================================================================= + // Directed Edges Helper Class + + namespace detail { + + // O(E/V) + template + inline void + remove_directed_edge_dispatch(edge_descriptor, EdgeList& el, + StoredProperty& p) + { + for (typename EdgeList::iterator i = el.begin(); + i != el.end(); ++i) + if (&(*i).get_property() == &p) { + el.erase(i); + return; + } + } + + template + inline void + remove_directed_edge_if_dispatch(incidence_iterator first, + incidence_iterator last, + EdgeList& el, Predicate pred, + boost::allow_parallel_edge_tag) + { + // remove_if + while (first != last && !pred(*first)) + ++first; + incidence_iterator i = first; + if (first != last) + for (; i != last; ++i) + if (!pred(*i)) { + *first.base() = *i.base(); + ++first; + } + el.erase(first.base(), el.end()); + } + template + inline void + remove_directed_edge_if_dispatch(incidence_iterator first, + incidence_iterator last, + EdgeList& el, + Predicate pred, + boost::disallow_parallel_edge_tag) + { + for (incidence_iterator next = first; + first != last; first = next) { + ++next; + if (pred(*first)) + el.erase( first.base() ); + } + } + + template + inline void + undirected_remove_out_edge_if_dispatch(Graph& g, + incidence_iterator first, + incidence_iterator last, + EdgeList& el, Predicate pred, + boost::allow_parallel_edge_tag) + { + typedef typename Graph::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + // remove_if + while (first != last && !pred(*first)) + ++first; + incidence_iterator i = first; + bool self_loop_removed = false; + if (first != last) + for (; i != last; ++i) { + if (self_loop_removed) { + /* With self loops, the descriptor will show up + * twice. The first time it will be removed, and now it + * will be skipped. + */ + self_loop_removed = false; + } + else if (!pred(*i)) { + *first.base() = *i.base(); + ++first; + } else { + if (source(*i, g) == target(*i, g)) self_loop_removed = true; + else { + // Remove the edge from the target + detail::remove_directed_edge_dispatch + (*i, + g.out_edge_list(target(*i, g)), + *(PropT*)(*i).get_property()); + } + + // Erase the edge property + g.m_edges.erase( (*i.base()).get_iter() ); + } + } + el.erase(first.base(), el.end()); + } + template + inline void + undirected_remove_out_edge_if_dispatch(Graph& g, + incidence_iterator first, + incidence_iterator last, + EdgeList& el, + Predicate pred, + boost::disallow_parallel_edge_tag) + { + typedef typename Graph::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + for (incidence_iterator next = first; + first != last; first = next) { + ++next; + if (pred(*first)) { + if (source(*first, g) != target(*first, g)) { + // Remove the edge from the target + detail::remove_directed_edge_dispatch + (*first, + g.out_edge_list(target(*first, g)), + *(PropT*)(*first).get_property()); + } + + // Erase the edge property + g.m_edges.erase( (*first.base()).get_iter() ); + + // Erase the edge in the source + el.erase( first.base() ); + } + } + } + + // O(E/V) + template + inline void + remove_directed_edge_dispatch(edge_descriptor e, EdgeList& el, + no_property&) + { + for (typename EdgeList::iterator i = el.begin(); + i != el.end(); ++i) + if ((*i).get_target() == e.m_target) { + el.erase(i); + return; + } + } + + } // namespace detail + + template + struct directed_edges_helper { + + // Placement of these overloaded remove_edge() functions + // inside the class avoids a VC++ bug. + + // O(E/V) + inline void + remove_edge(typename Config::edge_descriptor e) + { + typedef typename Config::graph_type graph_type; + graph_type& g = static_cast(*this); + typename Config::OutEdgeList& el = g.out_edge_list(source(e, g)); + typedef typename Config::OutEdgeList::value_type::property_type PType; + detail::remove_directed_edge_dispatch(e, el, + *(PType*)e.get_property()); + } + + // O(1) + inline void + remove_edge(typename Config::out_edge_iterator iter) + { + typedef typename Config::graph_type graph_type; + graph_type& g = static_cast(*this); + typename Config::edge_descriptor e = *iter; + typename Config::OutEdgeList& el = g.out_edge_list(source(e, g)); + el.erase(iter.base()); + } + + }; + + // O(1) + template + inline std::pair + edges(const directed_edges_helper& g_) + { + typedef typename Config::graph_type graph_type; + typedef typename Config::edge_iterator edge_iterator; + const graph_type& cg = static_cast(g_); + graph_type& g = const_cast(cg); + return std::make_pair( edge_iterator(g.vertex_set().begin(), + g.vertex_set().begin(), + g.vertex_set().end(), g), + edge_iterator(g.vertex_set().begin(), + g.vertex_set().end(), + g.vertex_set().end(), g) ); + } + + //========================================================================= + // Directed Graph Helper Class + + struct adj_list_dir_traversal_tag : + public virtual vertex_list_graph_tag, + public virtual incidence_graph_tag, + public virtual adjacency_graph_tag, + public virtual edge_list_graph_tag { }; + + template + struct directed_graph_helper + : public directed_edges_helper { + typedef typename Config::edge_descriptor edge_descriptor; + typedef adj_list_dir_traversal_tag traversal_category; + }; + + // O(E/V) + template + inline void + remove_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, + directed_graph_helper& g_) + { + typedef typename Config::graph_type graph_type; + typedef typename Config::edge_parallel_category Cat; + graph_type& g = static_cast(g_); + detail::erase_from_incidence_list(g.out_edge_list(u), v, Cat()); + } + + template + inline void + remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred, + directed_graph_helper& g_) + { + typedef typename Config::graph_type graph_type; + graph_type& g = static_cast(g_); + typename Config::out_edge_iterator first, last; + tie(first, last) = out_edges(u, g); + typedef typename Config::edge_parallel_category edge_parallel_category; + detail::remove_directed_edge_if_dispatch + (first, last, g.out_edge_list(u), pred, edge_parallel_category()); + } + + template + inline void + remove_edge_if(Predicate pred, directed_graph_helper& g_) + { + typedef typename Config::graph_type graph_type; + graph_type& g = static_cast(g_); + + typename Config::vertex_iterator vi, vi_end; + for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + remove_out_edge_if(*vi, pred, g); + } + + template + inline void + remove_edge(EdgeOrIter e_or_iter, directed_graph_helper& g_) + { + g_.remove_edge(e_or_iter); + } + + // O(V + E) for allow_parallel_edges + // O(V * log(E/V)) for disallow_parallel_edges + template + inline void + clear_vertex(typename Config::vertex_descriptor u, + directed_graph_helper& g_) + { + typedef typename Config::graph_type graph_type; + typedef typename Config::edge_parallel_category Cat; + graph_type& g = static_cast(g_); + typename Config::vertex_iterator vi, viend; + for (boost::tie(vi, viend) = vertices(g); vi != viend; ++vi) + detail::erase_from_incidence_list(g.out_edge_list(*vi), u, Cat()); + g.out_edge_list(u).clear(); + // clear() should be a req of Sequence and AssociativeContainer, + // or maybe just Container + } + + template + inline void + clear_out_edges(typename Config::vertex_descriptor u, + directed_graph_helper& g_) + { + typedef typename Config::graph_type graph_type; + typedef typename Config::edge_parallel_category Cat; + graph_type& g = static_cast(g_); + g.out_edge_list(u).clear(); + // clear() should be a req of Sequence and AssociativeContainer, + // or maybe just Container + } + + // O(V), could do better... + template + inline typename Config::edges_size_type + num_edges(const directed_graph_helper& g_) + { + typedef typename Config::graph_type graph_type; + const graph_type& g = static_cast(g_); + typename Config::edges_size_type num_e = 0; + typename Config::vertex_iterator vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + num_e += out_degree(*vi, g); + return num_e; + } + // O(1) for allow_parallel_edge_tag + // O(log(E/V)) for disallow_parallel_edge_tag + template + inline std::pair::edge_descriptor, bool> + add_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, + const typename Config::edge_property_type& p, + directed_graph_helper& g_) + { + typedef typename Config::edge_descriptor edge_descriptor; + typedef typename Config::graph_type graph_type; + typedef typename Config::StoredEdge StoredEdge; + graph_type& g = static_cast(g_); + typename Config::OutEdgeList::iterator i; + bool inserted; + boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), + StoredEdge(v, p)); + return std::make_pair(edge_descriptor(u, v, &(*i).get_property()), + inserted); + } + // Did not use default argument here because that + // causes Visual C++ to get confused. + template + inline std::pair + add_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, + directed_graph_helper& g_) + { + typename Config::edge_property_type p; + return add_edge(u, v, p, g_); + } + //========================================================================= + // Undirected Graph Helper Class + + template + struct undirected_graph_helper; + + struct undir_adj_list_traversal_tag : + public virtual vertex_list_graph_tag, + public virtual incidence_graph_tag, + public virtual adjacency_graph_tag, + public virtual edge_list_graph_tag, + public virtual bidirectional_graph_tag { }; + + namespace detail { + + // using class with specialization for dispatch is a VC++ workaround. + template + struct remove_undirected_edge_dispatch { + + // O(E/V) + template + static void + apply(edge_descriptor e, + undirected_graph_helper& g_, + StoredProperty& p) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::graph_type graph_type; + graph_type& g = static_cast(g_); + + typename Config::OutEdgeList& out_el = g.out_edge_list(source(e, g)); + typename Config::OutEdgeList::iterator out_i = out_el.begin(); + for (; out_i != out_el.end(); ++out_i) + if (&(*out_i).get_property() == &p) { + out_el.erase(out_i); + break; + } + typename Config::OutEdgeList& in_el = g.out_edge_list(target(e, g)); + typename Config::OutEdgeList::iterator in_i = in_el.begin(); + for (; in_i != in_el.end(); ++in_i) + if (&(*in_i).get_property() == &p) { + g.m_edges.erase((*in_i).get_iter()); + in_el.erase(in_i); + return; + } + } + }; + + template <> + struct remove_undirected_edge_dispatch { + // O(E/V) + template + static void + apply(edge_descriptor e, + undirected_graph_helper& g_, + no_property&) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::graph_type graph_type; + graph_type& g = static_cast(g_); + no_property* p = (no_property*)e.get_property(); + typename Config::OutEdgeList& out_el = g.out_edge_list(source(e, g)); + typename Config::OutEdgeList::iterator out_i = out_el.begin(); + for (; out_i != out_el.end(); ++out_i) + if (&(*out_i).get_property() == p) { + out_el.erase(out_i); + break; + } + typename Config::OutEdgeList& in_el = g.out_edge_list(target(e, g)); + typename Config::OutEdgeList::iterator in_i = in_el.begin(); + for (; in_i != in_el.end(); ++in_i) + if (&(*in_i).get_property() == p) { + g.m_edges.erase((*in_i).get_iter()); + in_el.erase(in_i); + return; + } + } + }; + + // O(E/V) + template + inline void + remove_edge_and_property(Graph& g, EdgeList& el, Vertex v, + boost::allow_parallel_edge_tag cat) + { + typedef typename Graph::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename EdgeList::value_type StoredEdge; + typename EdgeList::iterator i = el.begin(), end = el.end(); + for (; i != end; ++i) + if ((*i).get_target() == v) + g.m_edges.erase((*i).get_iter()); + detail::erase_from_incidence_list(el, v, cat); + } + // O(log(E/V)) + template + inline void + remove_edge_and_property(Graph& g, EdgeList& el, Vertex v, + boost::disallow_parallel_edge_tag) + { + typedef typename Graph::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename EdgeList::value_type StoredEdge; + typename EdgeList::iterator i = el.find(StoredEdge(v)), end = el.end(); + if (i != end) { + g.m_edges.erase((*i).get_iter()); + el.erase(i); + } + } + + } // namespace detail + + template + struct list_edge // short name due to VC++ truncation and linker problems + : public boost::detail::edge_base + { + typedef EdgeProperty property_type; + typedef boost::detail::edge_base Base; + list_edge(Vertex u, Vertex v, const EdgeProperty& p = EdgeProperty()) + : Base(u, v), m_property(p) { } + EdgeProperty& get_property() { return m_property; } + const EdgeProperty& get_property() const { return m_property; } + // the following methods should never be used, but are needed + // to make SGI MIPSpro C++ happy + list_edge() { } + bool operator==(const list_edge&) const { return false; } + bool operator<(const list_edge&) const { return false; } + EdgeProperty m_property; + }; + + template + struct undirected_graph_helper { + + typedef undir_adj_list_traversal_tag traversal_category; + + // Placement of these overloaded remove_edge() functions + // inside the class avoids a VC++ bug. + + // O(E/V) + inline void + remove_edge(typename Config::edge_descriptor e) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::OutEdgeList::value_type::property_type PType; + detail::remove_undirected_edge_dispatch::apply + (e, *this, *(PType*)e.get_property()); + } + // O(E/V) + inline void + remove_edge(typename Config::out_edge_iterator iter) + { + this->remove_edge(*iter); + } + }; + + // Had to make these non-members to avoid accidental instantiation + // on SGI MIPSpro C++ + template + inline typename C::InEdgeList& + in_edge_list(undirected_graph_helper&, + typename C::vertex_descriptor v) + { + typename C::stored_vertex* sv = (typename C::stored_vertex*)v; + return sv->m_out_edges; + } + template + inline const typename C::InEdgeList& + in_edge_list(const undirected_graph_helper&, + typename C::vertex_descriptor v) { + typename C::stored_vertex* sv = (typename C::stored_vertex*)v; + return sv->m_out_edges; + } + + // O(E/V) + template + inline void + remove_edge(EdgeOrIter e, undirected_graph_helper& g_) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + g_.remove_edge(e); + } + + // O(E/V) or O(log(E/V)) + template + void + remove_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, + undirected_graph_helper& g_) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::graph_type graph_type; + graph_type& g = static_cast(g_); + typedef typename Config::edge_parallel_category Cat; + detail::remove_edge_and_property(g, g.out_edge_list(u), v, Cat()); + detail::erase_from_incidence_list(g.out_edge_list(v), u, Cat()); + } + + template + void + remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred, + undirected_graph_helper& g_) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::graph_type graph_type; + typedef typename Config::OutEdgeList::value_type::property_type PropT; + graph_type& g = static_cast(g_); + typename Config::out_edge_iterator first, last; + tie(first, last) = out_edges(u, g); + typedef typename Config::edge_parallel_category Cat; + detail::undirected_remove_out_edge_if_dispatch + (g, first, last, g.out_edge_list(u), pred, Cat()); + } + template + void + remove_in_edge_if(typename Config::vertex_descriptor u, Predicate pred, + undirected_graph_helper& g_) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + remove_out_edge_if(u, pred, g_); + } + + // O(E/V * E) or O(log(E/V) * E) + template + void + remove_edge_if(Predicate pred, undirected_graph_helper& g_) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::graph_type graph_type; + graph_type& g = static_cast(g_); + typename Config::edge_iterator ei, ei_end, next; + tie(ei, ei_end) = edges(g); + for (next = ei; ei != ei_end; ei = next) { + ++next; + if (pred(*ei)) + remove_edge(*ei, g); + } + } + + // O(1) + template + inline std::pair + edges(const undirected_graph_helper& g_) + { + typedef typename Config::graph_type graph_type; + typedef typename Config::edge_iterator edge_iterator; + const graph_type& cg = static_cast(g_); + graph_type& g = const_cast(cg); + return std::make_pair( edge_iterator(g.m_edges.begin()), + edge_iterator(g.m_edges.end()) ); + } + // O(1) + template + inline typename Config::edges_size_type + num_edges(const undirected_graph_helper& g_) + { + typedef typename Config::graph_type graph_type; + const graph_type& g = static_cast(g_); + return g.m_edges.size(); + } + // O(E/V * E/V) + template + inline void + clear_vertex(typename Config::vertex_descriptor u, + undirected_graph_helper& g_) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::graph_type graph_type; + typedef typename Config::edge_parallel_category Cat; + graph_type& g = static_cast(g_); + typename Config::OutEdgeList& el = g.out_edge_list(u); + typename Config::OutEdgeList::iterator + ei = el.begin(), ei_end = el.end(); + for (; ei != ei_end; ++ei) { + detail::erase_from_incidence_list + (g.out_edge_list((*ei).get_target()), u, Cat()); + g.m_edges.erase((*ei).get_iter()); + } + g.out_edge_list(u).clear(); + } + // O(1) for allow_parallel_edge_tag + // O(log(E/V)) for disallow_parallel_edge_tag + template + inline std::pair + add_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, + const typename Config::edge_property_type& p, + undirected_graph_helper& g_) + { + typedef typename Config::StoredEdge StoredEdge; + typedef typename Config::edge_descriptor edge_descriptor; + typedef typename Config::graph_type graph_type; + graph_type& g = static_cast(g_); + + bool inserted; + typename Config::EdgeContainer::value_type e(u, v, p); + typename Config::EdgeContainer::iterator p_iter + = graph_detail::push(g.m_edges, e).first; + + typename Config::OutEdgeList::iterator i; + boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), + StoredEdge(v, p_iter, &g.m_edges)); + if (inserted) { + boost::graph_detail::push(g.out_edge_list(v), StoredEdge(u, p_iter, &g.m_edges)); + return std::make_pair(edge_descriptor(u, v, &p_iter->get_property()), + true); + } else { + g.m_edges.erase(p_iter); + return std::make_pair + (edge_descriptor(u, v, &i->get_iter()->get_property()), false); + } + } + template + inline std::pair + add_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, + undirected_graph_helper& g_) + { + typename Config::edge_property_type p; + return add_edge(u, v, p, g_); + } + + // O(1) + template + inline typename Config::degree_size_type + degree(typename Config::vertex_descriptor u, + const undirected_graph_helper& g_) + { + typedef typename Config::graph_type Graph; + const Graph& g = static_cast(g_); + return out_degree(u, g); + } + + template + inline std::pair + in_edges(typename Config::vertex_descriptor u, + const undirected_graph_helper& g_) + { + typedef typename Config::graph_type Graph; + const Graph& cg = static_cast(g_); + Graph& g = const_cast(cg); + typedef typename Config::in_edge_iterator in_edge_iterator; + return + std::make_pair(in_edge_iterator(g.out_edge_list(u).begin(), u), + in_edge_iterator(g.out_edge_list(u).end(), u)); + } + + template + inline typename Config::degree_size_type + in_degree(typename Config::vertex_descriptor u, + const undirected_graph_helper& g_) + { return degree(u, g_); } + + //========================================================================= + // Bidirectional Graph Helper Class + + struct bidir_adj_list_traversal_tag : + public virtual vertex_list_graph_tag, + public virtual incidence_graph_tag, + public virtual adjacency_graph_tag, + public virtual edge_list_graph_tag, + public virtual bidirectional_graph_tag { }; + + template + struct bidirectional_graph_helper + : public directed_edges_helper { + typedef bidir_adj_list_traversal_tag traversal_category; + }; + + // Had to make these non-members to avoid accidental instantiation + // on SGI MIPSpro C++ + template + inline typename C::InEdgeList& + in_edge_list(bidirectional_graph_helper&, + typename C::vertex_descriptor v) + { + typename C::stored_vertex* sv = (typename C::stored_vertex*)v; + return sv->m_in_edges; + } + template + inline const typename C::InEdgeList& + in_edge_list(const bidirectional_graph_helper&, + typename C::vertex_descriptor v) { + typename C::stored_vertex* sv = (typename C::stored_vertex*)v; + return sv->m_in_edges; + } + + template + inline void + remove_edge_if(Predicate pred, bidirectional_graph_helper& g_) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::graph_type graph_type; + graph_type& g = static_cast(g_); + typename Config::edge_iterator ei, ei_end, next; + tie(ei, ei_end) = edges(g); + for (next = ei; ei != ei_end; ei = next) { + ++next; + if (pred(*ei)) + remove_edge(*ei, g); + } + } + + template + inline std::pair + in_edges(typename Config::vertex_descriptor u, + const bidirectional_graph_helper& g_) + { + typedef typename Config::graph_type graph_type; + const graph_type& cg = static_cast(g_); + graph_type& g = const_cast(cg); + typedef typename Config::in_edge_iterator in_edge_iterator; + return + std::make_pair(in_edge_iterator(in_edge_list(g, u).begin(), u), + in_edge_iterator(in_edge_list(g, u).end(), u)); + } + + // O(1) + template + inline std::pair + edges(const bidirectional_graph_helper& g_) + { + typedef typename Config::graph_type graph_type; + typedef typename Config::edge_iterator edge_iterator; + const graph_type& cg = static_cast(g_); + graph_type& g = const_cast(cg); + return std::make_pair( edge_iterator(g.m_edges.begin()), + edge_iterator(g.m_edges.end()) ); + } + + //========================================================================= + // Bidirectional Graph Helper Class (with edge properties) + + + template + struct bidirectional_graph_helper_with_property + : public bidirectional_graph_helper + { + typedef typename Config::graph_type graph_type; + typedef typename Config::out_edge_iterator out_edge_iterator; + + std::pair + get_parallel_edge_sublist(typename Config::edge_descriptor e, + const graph_type& g, + void*) + { return out_edges(source(e, g), g); } + + std::pair + get_parallel_edge_sublist(typename Config::edge_descriptor e, + const graph_type& g, + setS*) + { return edge_range(source(e, g), target(e, g), g); } + + std::pair + get_parallel_edge_sublist(typename Config::edge_descriptor e, + const graph_type& g, + multisetS*) + { return edge_range(source(e, g), target(e, g), g); } + +#if !defined BOOST_NO_HASH + std::pair + get_parallel_edge_sublist(typename Config::edge_descriptor e, + const graph_type& g, + hash_setS*) + { return edge_range(source(e, g), target(e, g), g); } +#endif + + // Placement of these overloaded remove_edge() functions + // inside the class avoids a VC++ bug. + + // O(E/V) or O(log(E/V)) + void + remove_edge(typename Config::edge_descriptor e) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + graph_type& g = static_cast(*this); + + typedef typename Config::edgelist_selector OutEdgeListS; + + std::pair rng = + get_parallel_edge_sublist(e, g, (OutEdgeListS*)(0)); + rng.first = std::find(rng.first, rng.second, e); + assert(rng.first != rng.second); + remove_edge(rng.first); + } + + inline void + remove_edge(typename Config::out_edge_iterator iter) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::graph_type graph_type; + graph_type& g = static_cast(*this); + typename Config::edge_descriptor e = *iter; + typename Config::OutEdgeList& oel = g.out_edge_list(source(e, g)); + typename Config::InEdgeList& iel = in_edge_list(g, target(e, g)); + typedef typename Config::OutEdgeList::value_type::property_type PType; + PType& p = *(PType*)e.get_property(); + detail::remove_directed_edge_dispatch(*iter, iel, p); + g.m_edges.erase(iter.base()->get_iter()); + oel.erase(iter.base()); + } + }; + + // O(E/V) for allow_parallel_edge_tag + // O(log(E/V)) for disallow_parallel_edge_tag + template + inline void + remove_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, + bidirectional_graph_helper_with_property& g_) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::graph_type graph_type; + graph_type& g = static_cast(g_); + typedef typename Config::edge_parallel_category Cat; + detail::remove_edge_and_property(g, g.out_edge_list(u), v, Cat()); + detail::erase_from_incidence_list(in_edge_list(g, v), u, Cat()); + } + + // O(E/V) or O(log(E/V)) + template + inline void + remove_edge(EdgeOrIter e, + bidirectional_graph_helper_with_property& g_) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + g_.remove_edge(e); + } + + template + inline void + remove_out_edge_if(typename Config::vertex_descriptor u, Predicate pred, + bidirectional_graph_helper_with_property& g_) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::graph_type graph_type; + typedef typename Config::OutEdgeList::value_type::property_type PropT; + graph_type& g = static_cast(g_); + + typedef typename Config::EdgeIter EdgeIter; + typedef std::vector Garbage; + Garbage garbage; + + // First remove the edges from the targets' in-edge lists and + // from the graph's edge set list. + typename Config::out_edge_iterator out_i, out_end; + for (tie(out_i, out_end) = out_edges(u, g); out_i != out_end; ++out_i) + if (pred(*out_i)) { + detail::remove_directed_edge_dispatch + (*out_i, in_edge_list(g, target(*out_i, g)), + *(PropT*)(*out_i).get_property()); + // Put in garbage to delete later. Will need the properties + // for the remove_if of the out-edges. + garbage.push_back((*out_i.base()).get_iter()); + } + + // Now remove the edges from this out-edge list. + typename Config::out_edge_iterator first, last; + tie(first, last) = out_edges(u, g); + typedef typename Config::edge_parallel_category Cat; + detail::remove_directed_edge_if_dispatch + (first, last, g.out_edge_list(u), pred, Cat()); + + // Now delete the edge properties from the g.m_edges list + for (typename Garbage::iterator i = garbage.begin(); + i != garbage.end(); ++i) + g.m_edges.erase(*i); + } + template + inline void + remove_in_edge_if(typename Config::vertex_descriptor v, Predicate pred, + bidirectional_graph_helper_with_property& g_) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::graph_type graph_type; + typedef typename Config::OutEdgeList::value_type::property_type PropT; + graph_type& g = static_cast(g_); + + typedef typename Config::EdgeIter EdgeIter; + typedef std::vector Garbage; + Garbage garbage; + + // First remove the edges from the sources' out-edge lists and + // from the graph's edge set list. + typename Config::in_edge_iterator in_i, in_end; + for (tie(in_i, in_end) = in_edges(v, g); in_i != in_end; ++in_i) + if (pred(*in_i)) { + typename Config::vertex_descriptor u = source(*in_i, g); + detail::remove_directed_edge_dispatch + (*in_i, g.out_edge_list(u), *(PropT*)(*in_i).get_property()); + // Put in garbage to delete later. Will need the properties + // for the remove_if of the out-edges. + garbage.push_back((*in_i.base()).get_iter()); + } + // Now remove the edges from this in-edge list. + typename Config::in_edge_iterator first, last; + tie(first, last) = in_edges(v, g); + typedef typename Config::edge_parallel_category Cat; + detail::remove_directed_edge_if_dispatch + (first, last, in_edge_list(g, v), pred, Cat()); + + // Now delete the edge properties from the g.m_edges list + for (typename Garbage::iterator i = garbage.begin(); + i != garbage.end(); ++i) + g.m_edges.erase(*i); + } + + // O(1) + template + inline typename Config::edges_size_type + num_edges(const bidirectional_graph_helper_with_property& g_) + { + typedef typename Config::graph_type graph_type; + const graph_type& g = static_cast(g_); + return g.m_edges.size(); + } + // O(E/V * E/V) for allow_parallel_edge_tag + // O(E/V * log(E/V)) for disallow_parallel_edge_tag + template + inline void + clear_vertex(typename Config::vertex_descriptor u, + bidirectional_graph_helper_with_property& g_) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::graph_type graph_type; + typedef typename Config::edge_parallel_category Cat; + graph_type& g = static_cast(g_); + typename Config::OutEdgeList& el = g.out_edge_list(u); + typename Config::OutEdgeList::iterator + ei = el.begin(), ei_end = el.end(); + for (; ei != ei_end; ++ei) { + detail::erase_from_incidence_list + (in_edge_list(g, (*ei).get_target()), u, Cat()); + g.m_edges.erase((*ei).get_iter()); + } + typename Config::InEdgeList& in_el = in_edge_list(g, u); + typename Config::InEdgeList::iterator + in_ei = in_el.begin(), in_ei_end = in_el.end(); + for (; in_ei != in_ei_end; ++in_ei) { + detail::erase_from_incidence_list + (g.out_edge_list((*in_ei).get_target()), u, Cat()); + g.m_edges.erase((*in_ei).get_iter()); + } + g.out_edge_list(u).clear(); + in_edge_list(g, u).clear(); + } + + template + inline void + clear_out_edges(typename Config::vertex_descriptor u, + bidirectional_graph_helper_with_property& g_) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::graph_type graph_type; + typedef typename Config::edge_parallel_category Cat; + graph_type& g = static_cast(g_); + typename Config::OutEdgeList& el = g.out_edge_list(u); + typename Config::OutEdgeList::iterator + ei = el.begin(), ei_end = el.end(); + for (; ei != ei_end; ++ei) { + detail::erase_from_incidence_list + (in_edge_list(g, (*ei).get_target()), u, Cat()); + g.m_edges.erase((*ei).get_iter()); + } + g.out_edge_list(u).clear(); + } + + template + inline void + clear_in_edges(typename Config::vertex_descriptor u, + bidirectional_graph_helper_with_property& g_) + { + typedef typename Config::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Config::graph_type graph_type; + typedef typename Config::edge_parallel_category Cat; + graph_type& g = static_cast(g_); + typename Config::InEdgeList& in_el = in_edge_list(g, u); + typename Config::InEdgeList::iterator + in_ei = in_el.begin(), in_ei_end = in_el.end(); + for (; in_ei != in_ei_end; ++in_ei) { + detail::erase_from_incidence_list + (g.out_edge_list((*in_ei).get_target()), u, Cat()); + g.m_edges.erase((*in_ei).get_iter()); + } + in_edge_list(g, u).clear(); + } + + // O(1) for allow_parallel_edge_tag + // O(log(E/V)) for disallow_parallel_edge_tag + template + inline std::pair + add_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, + const typename Config::edge_property_type& p, + bidirectional_graph_helper_with_property& g_) + { + typedef typename Config::graph_type graph_type; + graph_type& g = static_cast(g_); + typedef typename Config::edge_descriptor edge_descriptor; + typedef typename Config::StoredEdge StoredEdge; + bool inserted; + typename Config::EdgeContainer::value_type e(u, v, p); + typename Config::EdgeContainer::iterator p_iter + = graph_detail::push(g.m_edges, e).first; + typename Config::OutEdgeList::iterator i; + boost::tie(i, inserted) = boost::graph_detail::push(g.out_edge_list(u), + StoredEdge(v, p_iter, &g.m_edges)); + if (inserted) { + boost::graph_detail::push(in_edge_list(g, v), StoredEdge(u, p_iter, &g.m_edges)); + return std::make_pair(edge_descriptor(u, v, &p_iter->m_property), + true); + } else { + g.m_edges.erase(p_iter); + return std::make_pair(edge_descriptor(u, v, + &i->get_iter()->get_property()), + false); + } + } + + template + inline std::pair + add_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, + bidirectional_graph_helper_with_property& g_) + { + typename Config::edge_property_type p; + return add_edge(u, v, p, g_); + } + // O(1) + template + inline typename Config::degree_size_type + degree(typename Config::vertex_descriptor u, + const bidirectional_graph_helper_with_property& g_) + { + typedef typename Config::graph_type graph_type; + const graph_type& g = static_cast(g_); + return in_degree(u, g) + out_degree(u, g); + } + + //========================================================================= + // Adjacency List Helper Class + + template + struct adj_list_helper : public Base + { + typedef typename Config::graph_type AdjList; + typedef typename Config::vertex_descriptor vertex_descriptor; + typedef typename Config::edge_descriptor edge_descriptor; + typedef typename Config::out_edge_iterator out_edge_iterator; + typedef typename Config::in_edge_iterator in_edge_iterator; + typedef typename Config::adjacency_iterator adjacency_iterator; + typedef typename Config::inv_adjacency_iterator inv_adjacency_iterator; + typedef typename Config::vertex_iterator vertex_iterator; + typedef typename Config::edge_iterator edge_iterator; + typedef typename Config::directed_category directed_category; + typedef typename Config::edge_parallel_category edge_parallel_category; + typedef typename Config::vertices_size_type vertices_size_type; + typedef typename Config::edges_size_type edges_size_type; + typedef typename Config::degree_size_type degree_size_type; + typedef typename Config::StoredEdge StoredEdge; + typedef typename Config::edge_property_type edge_property_type; + + typedef typename Config::global_edgelist_selector + global_edgelist_selector; + + // protected: + + // The edge_dispatch() functions should be static, but + // Borland gets confused about constness. + + // O(E/V) + inline std::pair + edge_dispatch(const AdjList& g, + vertex_descriptor u, vertex_descriptor v, + boost::allow_parallel_edge_tag) const + { + bool found; + const typename Config::OutEdgeList& el = g.out_edge_list(u); + typename Config::OutEdgeList::const_iterator + i = std::find_if(el.begin(), el.end(), + detail::target_is(v)); + found = (i != g.out_edge_list(u).end()); + if (found) + return std::make_pair(edge_descriptor(u, v, &(*i).get_property()), + true); + else + return std::make_pair(edge_descriptor(u, v, 0), false); + } + // O(log(E/V)) + inline std::pair + edge_dispatch(const AdjList& g, + vertex_descriptor u, vertex_descriptor v, + boost::disallow_parallel_edge_tag) const + { + bool found; + /* According to the standard, this should be iterator, not const_iterator, + but the VC++ std::set::find() const returns const_iterator. + And since iterator should be convertible to const_iterator, the + following should work everywhere. -Jeremy */ + typename Config::OutEdgeList::const_iterator + i = g.out_edge_list(u).find(StoredEdge(v)), + end = g.out_edge_list(u).end(); + found = (i != end); + if (found) + return std::make_pair(edge_descriptor(u, v, &(*i).get_property()), + true); + else + return std::make_pair(edge_descriptor(u, v, 0), false); + } + }; + + template + inline std::pair + adjacent_vertices(typename Config::vertex_descriptor u, + const adj_list_helper& g_) + { + typedef typename Config::graph_type AdjList; + const AdjList& cg = static_cast(g_); + AdjList& g = const_cast(cg); + typedef typename Config::adjacency_iterator adjacency_iterator; + typename Config::out_edge_iterator first, last; + boost::tie(first, last) = out_edges(u, g); + return std::make_pair(adjacency_iterator(first, &g), + adjacency_iterator(last, &g)); + } + template + inline std::pair + inv_adjacent_vertices(typename Config::vertex_descriptor u, + const adj_list_helper& g_) + { + typedef typename Config::graph_type AdjList; + const AdjList& cg = static_cast(g_); + AdjList& g = const_cast(cg); + typedef typename Config::inv_adjacency_iterator inv_adjacency_iterator; + typename Config::in_edge_iterator first, last; + boost::tie(first, last) = in_edges(u, g); + return std::make_pair(inv_adjacency_iterator(first, &g), + inv_adjacency_iterator(last, &g)); + } + template + inline std::pair + out_edges(typename Config::vertex_descriptor u, + const adj_list_helper& g_) + { + typedef typename Config::graph_type AdjList; + typedef typename Config::out_edge_iterator out_edge_iterator; + const AdjList& cg = static_cast(g_); + AdjList& g = const_cast(cg); + return + std::make_pair(out_edge_iterator(g.out_edge_list(u).begin(), u), + out_edge_iterator(g.out_edge_list(u).end(), u)); + } + template + inline std::pair + vertices(const adj_list_helper& g_) + { + typedef typename Config::graph_type AdjList; + const AdjList& cg = static_cast(g_); + AdjList& g = const_cast(cg); + return std::make_pair( g.vertex_set().begin(), g.vertex_set().end() ); + } + template + inline typename Config::vertices_size_type + num_vertices(const adj_list_helper& g_) + { + typedef typename Config::graph_type AdjList; + const AdjList& g = static_cast(g_); + return g.vertex_set().size(); + } + template + inline typename Config::degree_size_type + out_degree(typename Config::vertex_descriptor u, + const adj_list_helper& g_) + { + typedef typename Config::graph_type AdjList; + const AdjList& g = static_cast(g_); + return g.out_edge_list(u).size(); + } + template + inline std::pair + edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, + const adj_list_helper& g_) + { + typedef typename Config::graph_type Graph; + typedef typename Config::edge_parallel_category Cat; + const Graph& g = static_cast(g_); + return g_.edge_dispatch(g, u, v, Cat()); + } + template + inline std::pair + edge_range(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, + const adj_list_helper& g_) + { + typedef typename Config::graph_type Graph; + typedef typename Config::StoredEdge StoredEdge; + const Graph& cg = static_cast(g_); + Graph& g = const_cast(cg); + typedef typename Config::out_edge_iterator out_edge_iterator; + typename Config::OutEdgeList& el = g.out_edge_list(u); + typename Config::OutEdgeList::iterator first, last; + typename Config::EdgeContainer fake_edge_container; + tie(first, last) = + std::equal_range(el.begin(), el.end(), + StoredEdge(v, fake_edge_container.end(), + &fake_edge_container)); + return std::make_pair(out_edge_iterator(first, u), + out_edge_iterator(last, u)); + } + + template + inline typename Config::degree_size_type + in_degree(typename Config::vertex_descriptor u, + const directed_edges_helper& g_) + { + typedef typename Config::graph_type Graph; + const Graph& cg = static_cast(g_); + Graph& g = const_cast(cg); + return in_edge_list(g, u).size(); + } + + namespace detail { + template + inline + typename boost::property_map::type + get_dispatch(adj_list_helper&, Property, + boost::edge_property_tag) { + typedef typename Config::graph_type Graph; + typedef typename boost::property_map::type PA; + return PA(); + } + template + inline + typename boost::property_map::const_type + get_dispatch(const adj_list_helper&, Property, + boost::edge_property_tag) { + typedef typename Config::graph_type Graph; + typedef typename boost::property_map::const_type PA; + return PA(); + } + + template + inline + typename boost::property_map::type + get_dispatch(adj_list_helper& g, Property, + boost::vertex_property_tag) { + typedef typename Config::graph_type Graph; + typedef typename boost::property_map::type PA; + return PA(&static_cast(g)); + } + template + inline + typename boost::property_map::const_type + get_dispatch(const adj_list_helper& g, Property, + boost::vertex_property_tag) { + typedef typename Config::graph_type Graph; + typedef typename boost::property_map::const_type PA; + const Graph& cg = static_cast(g); + return PA(&cg); + } + + } // namespace detail + + // Implementation of the PropertyGraph interface + template + inline + typename boost::property_map::type + get(Property p, adj_list_helper& g) { + typedef typename property_kind::type Kind; + return detail::get_dispatch(g, p, Kind()); + } + template + inline + typename boost::property_map::const_type + get(Property p, const adj_list_helper& g) { + typedef typename property_kind::type Kind; + return detail::get_dispatch(g, p, Kind()); + } + + template + inline + typename boost::property_traits< + typename boost::property_map::type + >::reference + get(Property p, adj_list_helper& g, const Key& key) { + return get(get(p, g), key); + } + + template + inline + typename boost::property_traits< + typename boost::property_map::const_type + >::reference + get(Property p, const adj_list_helper& g, const Key& key) { + return get(get(p, g), key); + } + + template + inline void + put(Property p, adj_list_helper& g, + const Key& key, const Value& value) + { + typedef typename Config::graph_type Graph; + typedef typename boost::property_map::type Map; + Map pmap = get(p, static_cast(g)); + put(pmap, key, value); + } + + + //========================================================================= + // Generalize Adjacency List Implementation + + struct adj_list_tag { }; + + template + class adj_list_impl + : public adj_list_helper + { + typedef typename Config::OutEdgeList OutEdgeList; + typedef typename Config::InEdgeList InEdgeList; + typedef typename Config::StoredVertexList StoredVertexList; + public: + typedef typename Config::stored_vertex stored_vertex; + typedef typename Config::EdgeContainer EdgeContainer; + typedef typename Config::vertex_descriptor vertex_descriptor; + typedef typename Config::edge_descriptor edge_descriptor; + typedef typename Config::vertex_iterator vertex_iterator; + typedef typename Config::edge_iterator edge_iterator; + typedef typename Config::edge_parallel_category edge_parallel_category; + typedef typename Config::vertices_size_type vertices_size_type; + typedef typename Config::edges_size_type edges_size_type; + typedef typename Config::degree_size_type degree_size_type; + typedef typename Config::edge_property_type edge_property_type; + typedef adj_list_tag graph_tag; + + static vertex_descriptor null_vertex() + { + return 0; + } + + inline adj_list_impl() { } + + inline adj_list_impl(const adj_list_impl& x) { + copy_impl(x); + } + inline adj_list_impl& operator=(const adj_list_impl& x) { + this->clear(); + copy_impl(x); + return *this; + } + inline void clear() { + for (typename StoredVertexList::iterator i = m_vertices.begin(); + i != m_vertices.end(); ++i) + delete (stored_vertex*)*i; + m_vertices.clear(); + m_edges.clear(); + } + inline adj_list_impl(vertices_size_type num_vertices) { + for (vertices_size_type i = 0; i < num_vertices; ++i) + add_vertex(static_cast(*this)); + } + template + inline adj_list_impl(vertices_size_type num_vertices, + EdgeIterator first, EdgeIterator last) + { + vertex_descriptor* v = new vertex_descriptor[num_vertices]; + for (vertices_size_type i = 0; i < num_vertices; ++i) + v[i] = add_vertex(static_cast(*this)); + + while (first != last) { + add_edge(v[(*first).first], v[(*first).second], *this); + ++first; + } + delete [] v; + } + template + inline adj_list_impl(vertices_size_type num_vertices, + EdgeIterator first, EdgeIterator last, + EdgePropertyIterator ep_iter) + { + vertex_descriptor* v = new vertex_descriptor[num_vertices]; + for (vertices_size_type i = 0; i < num_vertices; ++i) + v[i] = add_vertex(static_cast(*this)); + + while (first != last) { + add_edge(v[(*first).first], v[(*first).second], *ep_iter, *this); + ++first; + ++ep_iter; + } + delete [] v; + } + ~adj_list_impl() { + for (typename StoredVertexList::iterator i = m_vertices.begin(); + i != m_vertices.end(); ++i) + delete (stored_vertex*)*i; + } + // protected: + inline OutEdgeList& out_edge_list(vertex_descriptor v) { + stored_vertex* sv = (stored_vertex*)v; + return sv->m_out_edges; + } + inline const OutEdgeList& out_edge_list(vertex_descriptor v) const { + stored_vertex* sv = (stored_vertex*)v; + return sv->m_out_edges; + } + inline StoredVertexList& vertex_set() { return m_vertices; } + inline const StoredVertexList& vertex_set() const { return m_vertices; } + + inline void copy_impl(const adj_list_impl& x_) + { + const Derived& x = static_cast(x_); + + // Would be better to have a constant time way to get from + // vertices in x to the corresponding vertices in *this. + std::map vertex_map; + + // Copy the stored vertex objects by adding each vertex + // and copying its property object. + vertex_iterator vi, vi_end; + for (tie(vi, vi_end) = vertices(x); vi != vi_end; ++vi) { + stored_vertex* v = (stored_vertex*)add_vertex(*this); + v->m_property = ((stored_vertex*)*vi)->m_property; + vertex_map[(stored_vertex*)*vi] = v; + } + // Copy the edges by adding each edge and copying its + // property object. + edge_iterator ei, ei_end; + for (tie(ei, ei_end) = edges(x); ei != ei_end; ++ei) { + edge_descriptor e; + bool inserted; + vertex_descriptor s = source(*ei,x), t = target(*ei,x); + tie(e, inserted) = add_edge(vertex_map[(stored_vertex*)s], + vertex_map[(stored_vertex*)t], *this); + *((edge_property_type*)e.m_eproperty) + = *((edge_property_type*)(*ei).m_eproperty); + } + } + + + typename Config::EdgeContainer m_edges; + StoredVertexList m_vertices; + }; + + // O(1) + template + inline typename Config::vertex_descriptor + add_vertex(adj_list_impl& g_) + { + Derived& g = static_cast(g_); + typedef typename Config::stored_vertex stored_vertex; + stored_vertex* v = new stored_vertex; + typename Config::StoredVertexList::iterator pos; + bool inserted; + boost::tie(pos,inserted) = boost::graph_detail::push(g.m_vertices, v); + v->m_position = pos; + return v; + } + // O(1) + template + inline typename Config::vertex_descriptor + add_vertex(const typename Config::vertex_property_type& p, + adj_list_impl& g_) + { + Derived& g = static_cast(g_); + typedef typename Config::stored_vertex stored_vertex; + stored_vertex* v = new stored_vertex(p); + typename Config::StoredVertexList::iterator pos; + bool inserted; + boost::tie(pos,inserted) = boost::graph_detail::push(g.m_vertices, v); + v->m_position = pos; + return v; + } + // O(1) + template + inline void remove_vertex(typename Config::vertex_descriptor u, + adj_list_impl& g_) + { + typedef typename Config::stored_vertex stored_vertex; + Derived& g = static_cast(g_); + stored_vertex* su = (stored_vertex*)u; + g.m_vertices.erase(su->m_position); + delete su; + } + // O(V) + template + inline typename Config::vertex_descriptor + vertex(typename Config::vertices_size_type n, + const adj_list_impl& g_) + { + const Derived& g = static_cast(g_); + typename Config::vertex_iterator i = vertices(g).first; + while (n--) ++i; // std::advance(i, n); (not VC++ portable) + return *i; + } + + //========================================================================= + // Vector-Backbone Adjacency List Implementation + + namespace detail { + + template + inline void + remove_vertex_dispatch(Graph& g, vertex_descriptor u, + boost::directed_tag) + { + typedef typename Graph::edge_parallel_category edge_parallel_category; + g.m_vertices.erase(g.m_vertices.begin() + u); + vertex_descriptor V = num_vertices(g); + if (u != V) { + for (vertex_descriptor v = 0; v < V; ++v) + reindex_edge_list(g.out_edge_list(v), u, edge_parallel_category()); + } + } + + template + inline void + remove_vertex_dispatch(Graph& g, vertex_descriptor u, + boost::undirected_tag) + { + typedef typename Graph::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Graph::edge_parallel_category edge_parallel_category; + g.m_vertices.erase(g.m_vertices.begin() + u); + vertex_descriptor V = num_vertices(g); + for (vertex_descriptor v = 0; v < V; ++v) + reindex_edge_list(g.out_edge_list(v), u, + edge_parallel_category()); + typedef typename Graph::EdgeContainer Container; + typedef typename Container::iterator Iter; + Iter ei = g.m_edges.begin(), ei_end = g.m_edges.end(); + for (; ei != ei_end; ++ei) { + if (ei->m_source > u) + --ei->m_source; + if (ei->m_target > u) + --ei->m_target; + } + } + template + inline void + remove_vertex_dispatch(Graph& g, vertex_descriptor u, + boost::bidirectional_tag) + { + typedef typename Graph::global_edgelist_selector EdgeListS; + BOOST_STATIC_ASSERT((!is_same::value)); + + typedef typename Graph::edge_parallel_category edge_parallel_category; + g.m_vertices.erase(g.m_vertices.begin() + u); + vertex_descriptor V = num_vertices(g); + vertex_descriptor v; + if (u != V) { + for (v = 0; v < V; ++v) + reindex_edge_list(g.out_edge_list(v), u, + edge_parallel_category()); + for (v = 0; v < V; ++v) + reindex_edge_list(in_edge_list(g, v), u, + edge_parallel_category()); + + typedef typename Graph::EdgeContainer Container; + typedef typename Container::iterator Iter; + Iter ei = g.m_edges.begin(), ei_end = g.m_edges.end(); + for (; ei != ei_end; ++ei) { + if (ei->m_source > u) + --ei->m_source; + if (ei->m_target > u) + --ei->m_target; + } + } + } + + template + inline void + reindex_edge_list(EdgeList& el, vertex_descriptor u, + boost::allow_parallel_edge_tag) + { + typename EdgeList::iterator ei = el.begin(), e_end = el.end(); + for (; ei != e_end; ++ei) + if ((*ei).get_target() > u) + --(*ei).get_target(); + } + template + inline void + reindex_edge_list(EdgeList& el, vertex_descriptor u, + boost::disallow_parallel_edge_tag) + { + typename EdgeList::iterator ei = el.begin(), e_end = el.end(); + while (ei != e_end) { + typename EdgeList::value_type ce = *ei; + ++ei; + if (ce.get_target() > u) { + el.erase(ce); + --ce.get_target(); + el.insert(ce); + } + } + } + } // namespace detail + + struct vec_adj_list_tag { }; + + template + class vec_adj_list_impl + : public adj_list_helper + { + typedef typename Config::OutEdgeList OutEdgeList; + typedef typename Config::InEdgeList InEdgeList; + typedef typename Config::StoredVertexList StoredVertexList; + public: + typedef typename Config::vertex_descriptor vertex_descriptor; + typedef typename Config::edge_descriptor edge_descriptor; + typedef typename Config::out_edge_iterator out_edge_iterator; + typedef typename Config::edge_iterator edge_iterator; + typedef typename Config::directed_category directed_category; + typedef typename Config::vertices_size_type vertices_size_type; + typedef typename Config::edges_size_type edges_size_type; + typedef typename Config::degree_size_type degree_size_type; + typedef typename Config::StoredEdge StoredEdge; + typedef typename Config::stored_vertex stored_vertex; + typedef typename Config::EdgeContainer EdgeContainer; + typedef typename Config::edge_property_type edge_property_type; + typedef vec_adj_list_tag graph_tag; + + static vertex_descriptor null_vertex() + { + return (std::numeric_limits::max)(); + } + + inline vec_adj_list_impl() { } + + inline vec_adj_list_impl(const vec_adj_list_impl& x) { + copy_impl(x); + } + inline vec_adj_list_impl& operator=(const vec_adj_list_impl& x) { + this->clear(); + copy_impl(x); + return *this; + } + inline void clear() { + m_vertices.clear(); + m_edges.clear(); + } + + inline vec_adj_list_impl(vertices_size_type _num_vertices) + : m_vertices(_num_vertices) { } + + template + inline vec_adj_list_impl(vertices_size_type num_vertices, + EdgeIterator first, EdgeIterator last) + : m_vertices(num_vertices) + { + while (first != last) { + add_edge((*first).first, (*first).second, + static_cast(*this)); + ++first; + } + } + template + inline vec_adj_list_impl(vertices_size_type num_vertices, + EdgeIterator first, EdgeIterator last, + EdgePropertyIterator ep_iter) + : m_vertices(num_vertices) + { + while (first != last) { + add_edge((*first).first, (*first).second, *ep_iter, + static_cast(*this)); + ++first; + ++ep_iter; + } + } + + // protected: + inline boost::integer_range vertex_set() const { + return boost::integer_range(0, m_vertices.size()); + } + inline OutEdgeList& out_edge_list(vertex_descriptor v) { + return m_vertices[v].m_out_edges; + } + inline const OutEdgeList& out_edge_list(vertex_descriptor v) const { + return m_vertices[v].m_out_edges; + } + inline void copy_impl(const vec_adj_list_impl& x_) + { + const Graph& x = static_cast(x_); + // Copy the stored vertex objects by adding each vertex + // and copying its property object. + for (vertices_size_type i = 0; i < num_vertices(x); ++i) { + vertex_descriptor v = add_vertex(*this); + m_vertices[v].m_property = x.m_vertices[i].m_property; + } + // Copy the edges by adding each edge and copying its + // property object. + edge_iterator ei, ei_end; + for (tie(ei, ei_end) = edges(x); ei != ei_end; ++ei) { + edge_descriptor e; + bool inserted; + tie(e, inserted) = add_edge(source(*ei,x), target(*ei,x) , *this); + *((edge_property_type*)e.m_eproperty) + = *((edge_property_type*)(*ei).m_eproperty); + } + } + typename Config::EdgeContainer m_edges; + StoredVertexList m_vertices; + }; + // Had to make these non-members to avoid accidental instantiation + // on SGI MIPSpro C++ + template + inline typename C::InEdgeList& + in_edge_list(vec_adj_list_impl& g, + typename C::vertex_descriptor v) { + return g.m_vertices[v].m_in_edges; + } + template + inline const typename C::InEdgeList& + in_edge_list(const vec_adj_list_impl& g, + typename C::vertex_descriptor v) { + return g.m_vertices[v].m_in_edges; + } + + // O(1) + template + inline typename Config::vertex_descriptor + add_vertex(vec_adj_list_impl& g_) { + Graph& g = static_cast(g_); + g.m_vertices.resize(g.m_vertices.size() + 1); + return g.m_vertices.size() - 1; + } + + template + inline typename Config::vertex_descriptor + add_vertex(const typename Config::vertex_property_type& p, + vec_adj_list_impl& g_) { + Graph& g = static_cast(g_); + typedef typename Config::stored_vertex stored_vertex; + g.m_vertices.push_back(stored_vertex(p)); + return g.m_vertices.size() - 1; + } + + // Here we override the directed_graph_helper add_edge() function + // so that the number of vertices is automatically changed if + // either u or v is greater than the number of vertices. + template + inline std::pair + add_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, + const typename Config::edge_property_type& p, + vec_adj_list_impl& g_) + { + BOOST_USING_STD_MAX(); + typename Config::vertex_descriptor x = max BOOST_PREVENT_MACRO_SUBSTITUTION(u, v); + if (x >= num_vertices(g_)) + g_.m_vertices.resize(x + 1); + adj_list_helper& g = g_; + return add_edge(u, v, p, g); + } + template + inline std::pair + add_edge(typename Config::vertex_descriptor u, + typename Config::vertex_descriptor v, + vec_adj_list_impl& g_) + { + typename Config::edge_property_type p; + return add_edge(u, v, p, g_); + } + + + // O(V + E) + template + inline void remove_vertex(typename Config::vertex_descriptor v, + vec_adj_list_impl& g_) + { + typedef typename Config::directed_category Cat; + Graph& g = static_cast(g_); + detail::remove_vertex_dispatch(g, v, Cat()); + } + // O(1) + template + inline typename Config::vertex_descriptor + vertex(typename Config::vertices_size_type n, + const vec_adj_list_impl&) + { + return n; + } + + + namespace detail { + + //========================================================================= + // Adjacency List Generator + + template + struct adj_list_gen + { + typedef typename detail::is_random_access::type + is_rand_access; + typedef typename has_property::type has_edge_property; + typedef typename DirectedS::is_directed_t DirectedT; + typedef typename DirectedS::is_bidir_t BidirectionalT; + + struct config + { + typedef OutEdgeListS edgelist_selector; + typedef EdgeListS global_edgelist_selector; + + typedef Graph graph_type; + typedef EdgeProperty edge_property_type; + typedef VertexProperty vertex_property_type; + typedef GraphProperty graph_property_type; + typedef std::size_t vertices_size_type; + + typedef adjacency_list_traits + Traits; + + typedef typename Traits::directed_category directed_category; + typedef typename Traits::edge_parallel_category edge_parallel_category; + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::edge_descriptor edge_descriptor; + + typedef void* vertex_ptr; + + // need to reorganize this to avoid instantiating stuff + // that doesn't get used -JGS + + // VertexList and vertex_iterator + typedef typename container_gen::type SeqVertexList; + typedef boost::integer_range RandVertexList; + typedef typename mpl::if_::type VertexList; + + typedef typename VertexList::iterator vertex_iterator; + + // EdgeContainer and StoredEdge + + typedef typename container_gen >::type EdgeContainer; + + typedef typename mpl::and_::type >::type on_edge_storage; + + typedef typename mpl::if_::type edges_size_type; + + typedef typename EdgeContainer::iterator EdgeIter; + + typedef typename detail::is_random_access::type is_edge_ra; + + typedef typename mpl::if_, + typename mpl::if_, + stored_edge_iter + >::type + >::type StoredEdge; + + // Adjacency Types + + typedef typename container_gen::type + OutEdgeList; + typedef typename OutEdgeList::size_type degree_size_type; + typedef typename OutEdgeList::iterator OutEdgeIter; + + typedef boost::detail::iterator_traits OutEdgeIterTraits; + typedef typename OutEdgeIterTraits::iterator_category OutEdgeIterCat; + typedef typename OutEdgeIterTraits::difference_type OutEdgeIterDiff; + + typedef out_edge_iter< + OutEdgeIter, vertex_descriptor, edge_descriptor, OutEdgeIterDiff + > out_edge_iterator; + + typedef typename adjacency_iterator_generator::type adjacency_iterator; + + typedef OutEdgeList InEdgeList; + typedef OutEdgeIter InEdgeIter; + typedef OutEdgeIterCat InEdgeIterCat; + typedef OutEdgeIterDiff InEdgeIterDiff; + + typedef in_edge_iter< + InEdgeIter, vertex_descriptor, edge_descriptor, InEdgeIterDiff + > in_edge_iterator; + + typedef typename inv_adjacency_iterator_generator::type inv_adjacency_iterator; + + // Edge Iterator + + typedef boost::detail::iterator_traits EdgeIterTraits; + typedef typename EdgeIterTraits::iterator_category EdgeIterCat; + typedef typename EdgeIterTraits::difference_type EdgeIterDiff; + + typedef undirected_edge_iter< + EdgeIter + , edge_descriptor + , EdgeIterDiff + > UndirectedEdgeIter; // also used for bidirectional + + typedef adj_list_edge_iterator DirectedEdgeIter; + + typedef typename mpl::if_::type edge_iterator; + + // stored_vertex and StoredVertexList + typedef typename container_gen::type + SeqStoredVertexList; + struct seq_stored_vertex { + seq_stored_vertex() { } + seq_stored_vertex(const VertexProperty& p) : m_property(p) { } + OutEdgeList m_out_edges; + VertexProperty m_property; + typename SeqStoredVertexList::iterator m_position; + }; + struct bidir_seq_stored_vertex { + bidir_seq_stored_vertex() { } + bidir_seq_stored_vertex(const VertexProperty& p) : m_property(p) { } + OutEdgeList m_out_edges; + InEdgeList m_in_edges; + VertexProperty m_property; + typename SeqStoredVertexList::iterator m_position; + }; + struct rand_stored_vertex { + rand_stored_vertex() { } + rand_stored_vertex(const VertexProperty& p) : m_property(p) { } + OutEdgeList m_out_edges; + VertexProperty m_property; + }; + struct bidir_rand_stored_vertex { + bidir_rand_stored_vertex() { } + bidir_rand_stored_vertex(const VertexProperty& p) : m_property(p) { } + OutEdgeList m_out_edges; + InEdgeList m_in_edges; + VertexProperty m_property; + }; + typedef typename mpl::if_::type, + typename mpl::if_::type + >::type StoredVertex; + struct stored_vertex : public StoredVertex { + stored_vertex() { } + stored_vertex(const VertexProperty& p) : StoredVertex(p) { } + }; + + typedef typename container_gen::type + RandStoredVertexList; + typedef typename mpl::if_< is_rand_access, + RandStoredVertexList, SeqStoredVertexList>::type StoredVertexList; + }; // end of config + + + typedef typename mpl::if_, + typename mpl::if_, + undirected_graph_helper + >::type + >::type DirectedHelper; + + typedef typename mpl::if_, + adj_list_impl + >::type type; + + }; + + } // namespace detail + + //========================================================================= + // Vertex Property Maps + + template + struct adj_list_vertex_property_map + : public boost::put_get_helper< + Reference, + adj_list_vertex_property_map + > + { + typedef typename Graph::stored_vertex StoredVertex; + typedef ValueType value_type; + typedef Reference reference; + typedef typename Graph::vertex_descriptor key_type; + typedef boost::lvalue_property_map_tag category; + inline adj_list_vertex_property_map() { } + inline adj_list_vertex_property_map(const Graph*) { } + inline Reference operator[](key_type v) const { + StoredVertex* sv = (StoredVertex*)v; + return get_property_value(sv->m_property, Tag()); + } + inline Reference operator()(key_type v) const { + return this->operator[](v); + } + }; + + template + struct adj_list_vertex_all_properties_map + : public boost::put_get_helper + > + { + typedef typename Graph::stored_vertex StoredVertex; + typedef Property value_type; + typedef PropRef reference; + typedef typename Graph::vertex_descriptor key_type; + typedef boost::lvalue_property_map_tag category; + inline adj_list_vertex_all_properties_map() { } + inline adj_list_vertex_all_properties_map(const Graph*) { } + inline PropRef operator[](key_type v) const { + StoredVertex* sv = (StoredVertex*)v; + return sv->m_property; + } + inline PropRef operator()(key_type v) const { + return this->operator[](v); + } + }; + + template + struct vec_adj_list_vertex_property_map + : public boost::put_get_helper< + Reference, + vec_adj_list_vertex_property_map + > + { + typedef ValueType value_type; + typedef Reference reference; + typedef typename boost::graph_traits::vertex_descriptor key_type; + typedef boost::lvalue_property_map_tag category; + vec_adj_list_vertex_property_map() { } + vec_adj_list_vertex_property_map(GraphPtr g) : m_g(g) { } + inline Reference operator[](key_type v) const { + return get_property_value(m_g->m_vertices[v].m_property, Tag()); + } + inline Reference operator()(key_type v) const { + return this->operator[](v); + } + GraphPtr m_g; + }; + + template + struct vec_adj_list_vertex_all_properties_map + : public boost::put_get_helper + > + { + typedef Property value_type; + typedef PropertyRef reference; + typedef typename boost::graph_traits::vertex_descriptor key_type; + typedef boost::lvalue_property_map_tag category; + vec_adj_list_vertex_all_properties_map() { } + vec_adj_list_vertex_all_properties_map(GraphPtr g) : m_g(g) { } + inline PropertyRef operator[](key_type v) const { + return m_g->m_vertices[v].m_property; + } + inline PropertyRef operator()(key_type v) const { + return this->operator[](v); + } + GraphPtr m_g; + }; + + struct adj_list_any_vertex_pa { + template + struct bind_ { + typedef typename property_value::type value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + + typedef adj_list_vertex_property_map + type; + typedef adj_list_vertex_property_map + const_type; + }; + }; + struct adj_list_all_vertex_pa { + template + struct bind_ { + typedef typename Graph::vertex_descriptor Vertex; + typedef adj_list_vertex_all_properties_map type; + typedef adj_list_vertex_all_properties_map const_type; + }; + }; + + template + struct vec_adj_list_vertex_id_map + : public boost::put_get_helper< + Vertex, vec_adj_list_vertex_id_map + > + { + typedef Vertex value_type; + typedef Vertex key_type; + typedef Vertex reference; + typedef boost::readable_property_map_tag category; + inline vec_adj_list_vertex_id_map() { } + template + inline vec_adj_list_vertex_id_map(const Graph&) { } + inline value_type operator[](key_type v) const { return v; } + inline value_type operator()(key_type v) const { return v; } + }; + + struct vec_adj_list_any_vertex_pa { + template + struct bind_ { + typedef typename property_value::type value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + + typedef vec_adj_list_vertex_property_map + type; + typedef vec_adj_list_vertex_property_map + const_type; + }; + }; + struct vec_adj_list_id_vertex_pa { + template + struct bind_ { + typedef typename Graph::vertex_descriptor Vertex; + typedef vec_adj_list_vertex_id_map type; + typedef vec_adj_list_vertex_id_map const_type; + }; + }; + struct vec_adj_list_all_vertex_pa { + template + struct bind_ { + typedef typename Graph::vertex_descriptor Vertex; + typedef vec_adj_list_vertex_all_properties_map + type; + typedef vec_adj_list_vertex_all_properties_map + const_type; + }; + }; + namespace detail { + template + struct adj_list_choose_vertex_pa_helper { + typedef adj_list_any_vertex_pa type; + }; + template <> + struct adj_list_choose_vertex_pa_helper { + typedef adj_list_all_vertex_pa type; + }; + template + struct adj_list_choose_vertex_pa { + typedef typename adj_list_choose_vertex_pa_helper::type Helper; + typedef typename Helper::template bind_ Bind; + typedef typename Bind::type type; + typedef typename Bind::const_type const_type; + }; + + + template + struct vec_adj_list_choose_vertex_pa_helper { + typedef vec_adj_list_any_vertex_pa type; + }; + template <> + struct vec_adj_list_choose_vertex_pa_helper { + typedef vec_adj_list_id_vertex_pa type; + }; + template <> + struct vec_adj_list_choose_vertex_pa_helper { + typedef vec_adj_list_all_vertex_pa type; + }; + template + struct vec_adj_list_choose_vertex_pa { + typedef typename vec_adj_list_choose_vertex_pa_helper::type Helper; + typedef typename Helper::template bind_ Bind; + typedef typename Bind::type type; + typedef typename Bind::const_type const_type; + }; + } // namespace detail + + //========================================================================= + // Edge Property Map + + template + struct adj_list_edge_property_map + : public put_get_helper< + Ref, + adj_list_edge_property_map + > + { + typedef Value value_type; + typedef Ref reference; + typedef detail::edge_desc_impl key_type; + typedef boost::lvalue_property_map_tag category; + inline Ref operator[](key_type e) const { + Property& p = *(Property*)e.get_property(); + return get_property_value(p, Tag()); + } + inline Ref operator()(key_type e) const { + return this->operator[](e); + } + }; + + template + struct adj_list_edge_all_properties_map + : public put_get_helper + > + { + typedef Property value_type; + typedef PropRef reference; + typedef detail::edge_desc_impl key_type; + typedef boost::lvalue_property_map_tag category; + inline PropRef operator[](key_type e) const { + return *(PropPtr)e.get_property(); + } + inline PropRef operator()(key_type e) const { + return this->operator[](e); + } + }; + + // Edge Property Maps + + namespace detail { + struct adj_list_any_edge_pmap { + template + struct bind_ { + typedef typename property_value::type value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + + typedef adj_list_edge_property_map + type; + typedef adj_list_edge_property_map + const_type; + }; + }; + struct adj_list_all_edge_pmap { + template + struct bind_ { + typedef adj_list_edge_all_properties_map + type; + typedef adj_list_edge_all_properties_map + const_type; + }; + }; + + template + struct adj_list_choose_edge_pmap_helper { + typedef adj_list_any_edge_pmap type; + }; + template <> + struct adj_list_choose_edge_pmap_helper { + typedef adj_list_all_edge_pmap type; + }; + template + struct adj_list_choose_edge_pmap { + typedef typename adj_list_choose_edge_pmap_helper::type Helper; + typedef typename Helper::template bind_ Bind; + typedef typename Bind::type type; + typedef typename Bind::const_type const_type; + }; + struct adj_list_edge_property_selector { + template + struct bind_ { + typedef adj_list_choose_edge_pmap Choice; + typedef typename Choice::type type; + typedef typename Choice::const_type const_type; + }; + }; + } // namespace detail + + template <> + struct edge_property_selector { + typedef detail::adj_list_edge_property_selector type; + }; + template <> + struct edge_property_selector { + typedef detail::adj_list_edge_property_selector type; + }; + + // Vertex Property Maps + + struct adj_list_vertex_property_selector { + template + struct bind_ { + typedef detail::adj_list_choose_vertex_pa Choice; + typedef typename Choice::type type; + typedef typename Choice::const_type const_type; + }; + }; + template <> + struct vertex_property_selector { + typedef adj_list_vertex_property_selector type; + }; + + struct vec_adj_list_vertex_property_selector { + template + struct bind_ { + typedef detail::vec_adj_list_choose_vertex_pa Choice; + typedef typename Choice::type type; + typedef typename Choice::const_type const_type; + }; + }; + template <> + struct vertex_property_selector { + typedef vec_adj_list_vertex_property_selector type; + }; + +} // namespace boost + +#if !defined(BOOST_NO_HASH) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +namespace BOOST_STD_EXTENSION_NAMESPACE { + + #if BOOST_WORKAROUND( _STLPORT_VERSION, >= 0x500 ) + // STLport 5 already defines a hash specialization. + #else + template <> + struct hash< void* > // Need this when vertex_descriptor=void* + { + std::size_t + operator()(void* v) const { return (std::size_t)v; } + }; + #endif + + template + struct hash< boost::detail::stored_edge > + { + std::size_t + operator()(const boost::detail::stored_edge& e) const + { + return hash()(e.m_target); + } + }; + + template + struct hash< boost::detail::stored_edge_property > + { + std::size_t + operator()(const boost::detail::stored_edge_property& e) const + { + return hash()(e.m_target); + } + }; + + template + struct hash< boost::detail::stored_edge_iter > + { + std::size_t + operator()(const boost::detail::stored_edge_iter& e) const + { + return hash()(e.m_target); + } + }; + +} +#endif + + +#undef stored_edge +#undef stored_edge_property +#undef stored_edge_iter + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +// Stay out of the way of the concept checking class +#undef Graph +#endif + +#endif // BOOST_GRAPH_DETAIL_DETAIL_ADJACENCY_LIST_CCT + +/* + Implementation Notes: + + Many of the public interface functions in this file would have been + more conveniently implemented as inline friend functions. + However there are a few compiler bugs that make that approach + non-portable. + + 1. g++ inline friend in namespace bug + 2. g++ using clause doesn't work with inline friends + 3. VC++ doesn't have Koenig lookup + + For these reasons, the functions were all written as non-inline free + functions, and static cast was used to convert from the helper + class to the adjacency_list derived class. + + Looking back, it might have been better to write out all functions + in terms of the adjacency_list, and then use a tag to dispatch + to the various helpers instead of using inheritance. + + */ diff --git a/win32/include/boost/graph/detail/array_binary_tree.hpp b/win32/include/boost/graph/detail/array_binary_tree.hpp new file mode 100755 index 000000000..9eb20201b --- /dev/null +++ b/win32/include/boost/graph/detail/array_binary_tree.hpp @@ -0,0 +1,182 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef ADSTL_ARRAY_BINARY_TREE_HPP +#define ADSTL_ARRAY_BINARY_TREE_HPP + +#include +#include +#include + +namespace adstl { + /* + Note: array_binary_tree is a completey balanced binary tree + */ + +#if !defined BOOST_NO_STD_ITERATOR_TRAITS + template +#else + template +#endif +class array_binary_tree_node { +public: + typedef array_binary_tree_node ArrayBinaryTreeNode; + typedef RandomAccessIterator rep_iterator; +#if !defined BOOST_NO_STD_ITERATOR_TRAITS + typedef typename std::iterator_traits::difference_type + difference_type; + typedef typename std::iterator_traits::value_type + value_type; +#else + typedef int difference_type; + typedef ValueType value_type; +#endif + typedef difference_type size_type; + + struct children_type { + struct iterator + : boost::iterator + { // replace with iterator_adaptor implementation -JGS + + inline iterator() : i(0), n(0) { } + inline iterator(const iterator& x) : r(x.r), i(x.i), n(x.n), id(x.id) { } + inline iterator& operator=(const iterator& x) { + r = x.r; i = x.i; n = x.n; + /*egcs generate a warning*/ + id = x.id; + return *this; + } + inline iterator(rep_iterator rr, + size_type ii, + size_type nn, + const ID& _id) : r(rr), i(ii), n(nn), id(_id) { } + inline array_binary_tree_node operator*() { + return ArrayBinaryTreeNode(r, i, n, id); } + inline iterator& operator++() { ++i; return *this; } + inline iterator operator++(int) + { iterator t = *this; ++(*this); return t; } + inline bool operator==(const iterator& x) const { return i == x.i; } + inline bool operator!=(const iterator& x) const + { return !(*this == x); } + rep_iterator r; + size_type i; + size_type n; + ID id; + }; + inline children_type() : i(0), n(0) { } + inline children_type(const children_type& x) + : r(x.r), i(x.i), n(x.n), id(x.id) { } + inline children_type& operator=(const children_type& x) { + r = x.r; i = x.i; n = x.n; + /*egcs generate a warning*/ + id = x.id; + return *this; + } + inline children_type(rep_iterator rr, + size_type ii, + size_type nn, + const ID& _id) : r(rr), i(ii), n(nn), id(_id) { } + inline iterator begin() { return iterator(r, 2 * i + 1, n, id); } + inline iterator end() { return iterator(r, 2 * i + 1 + size(), n, id); } + inline size_type size() const { + size_type c = 2 * i + 1; + size_type s; + if (c + 1 < n) s = 2; + else if (c < n) s = 1; + else s = 0; + return s; + } + rep_iterator r; + size_type i; + size_type n; + ID id; + }; + inline array_binary_tree_node() : i(0), n(0) { } + inline array_binary_tree_node(const array_binary_tree_node& x) + : r(x.r), i(x.i), n(x.n), id(x.id) { } + inline ArrayBinaryTreeNode& operator=(const ArrayBinaryTreeNode& x) { + r = x.r; + i = x.i; + n = x.n; + /*egcs generate a warning*/ + id = x.id; + return *this; + } + inline array_binary_tree_node(rep_iterator start, + rep_iterator end, + rep_iterator pos, const ID& _id) + : r(start), i(pos - start), n(end - start), id(_id) { } + inline array_binary_tree_node(rep_iterator rr, + size_type ii, + size_type nn, const ID& _id) + : r(rr), i(ii), n(nn), id(_id) { } + inline value_type& value() { return *(r + i); } + inline const value_type& value() const { return *(r + i); } + inline ArrayBinaryTreeNode parent() const { + return ArrayBinaryTreeNode(r, (i - 1) / 2, n, id); + } + inline bool has_parent() const { return i != 0; } + inline children_type children() { return children_type(r, i, n, id); } + /* + inline void swap(array_binary_tree_node x) { + value_type tmp = x.value(); + x.value() = value(); + value() = tmp; + i = x.i; + } + */ + template + inline void swap(ArrayBinaryTreeNode x, ExternalData& edata ) { + using boost::get; + + value_type tmp = x.value(); + + /*swap external data*/ + edata[ get(id, tmp) ] = i; + edata[ get(id, value()) ] = x.i; + + x.value() = value(); + value() = tmp; + i = x.i; + } + inline const children_type children() const { + return children_type(r, i, n); + } + inline size_type index() const { return i; } + rep_iterator r; + size_type i; + size_type n; + ID id; +}; + +template > +struct compare_array_node { + typedef typename RandomAccessContainer::value_type value_type; + compare_array_node(const Compare& x) : comp(x) {} + compare_array_node(const compare_array_node& x) : comp(x.comp) {} + + template< class node_type > + inline bool operator()(const node_type& x, const node_type& y) { + return comp(x.value(), y.value()); + } + + template< class node_type > + inline bool operator()(const node_type& x, const node_type& y) const { + return comp(x.value(), y.value()); + } + Compare comp; +}; + + +} /* namespace adstl */ + +#endif /* ADSTL_ARRAY_BINARY_TREE_H */ diff --git a/win32/include/boost/graph/detail/connected_components.hpp b/win32/include/boost/graph/detail/connected_components.hpp new file mode 100755 index 000000000..ae63aeaea --- /dev/null +++ b/win32/include/boost/graph/detail/connected_components.hpp @@ -0,0 +1,208 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_DETAIL_CONNECTED_COMPONENTS_HPP +#define BOOST_GRAPH_DETAIL_CONNECTED_COMPONENTS_HPP + +#if defined(__sgi) && !defined(__GNUC__) +#pragma set woff 1234 +#endif + +#include + +namespace boost { + + namespace detail { + + //========================================================================= + // Implementation details of connected_components + + // This is used both in the connected_components algorithm and in + // the kosaraju strong components algorithm during the second DFS + // traversal. + template + class components_recorder : public DFSVisitor + { + typedef typename property_traits::value_type comp_type; + public: + components_recorder(ComponentsPA c, + comp_type& c_count, + DFSVisitor v) + : DFSVisitor(v), m_component(c), m_count(c_count) {} + + template + void start_vertex(Vertex u, Graph& g) { + ++m_count; + DFSVisitor::start_vertex(u, g); + } + template + void discover_vertex(Vertex u, Graph& g) { + put(m_component, u, m_count); + DFSVisitor::discover_vertex(u, g); + } + protected: + ComponentsPA m_component; + comp_type& m_count; + }; + + template + class time_recorder : public DFSVisitor + { + public: + time_recorder(DiscoverTimeMap d, FinishTimeMap f, TimeT& t, DFSVisitor v) + : DFSVisitor(v), m_discover_time(d), m_finish_time(f), m_t(t) {} + + template + void discover_vertex(Vertex u, Graph& g) { + put(m_discover_time, u, ++m_t); + DFSVisitor::discover_vertex(u, g); + } + template + void finish_vertex(Vertex u, Graph& g) { + put(m_finish_time, u, ++m_t); + DFSVisitor::discover_vertex(u, g); + } + protected: + DiscoverTimeMap m_discover_time; + FinishTimeMap m_finish_time; + TimeT m_t; + }; + template + time_recorder + record_times(DiscoverTimeMap d, FinishTimeMap f, TimeT& t, DFSVisitor vis) + { + return time_recorder + (d, f, t, vis); + } + + //========================================================================= + // Implementation detail of dynamic_components + + + //------------------------------------------------------------------------- + // Helper functions for the component_index class + + // Record the representative vertices in the header array. + // Representative vertices now point to the component number. + + template + inline void + build_components_header(Parent p, + OutputIterator header, + Integer num_nodes) + { + Parent component = p; + Integer component_num = 0; + for (Integer v = 0; v != num_nodes; ++v) + if (p[v] == v) { + *header++ = v; + component[v] = component_num++; + } + } + + + // Pushes x onto the front of the list. The list is represented in + // an array. + template + inline void push_front(Next next, T& head, V x) + { + T tmp = head; + head = x; + next[x] = tmp; + } + + + // Create a linked list of the vertices in each component + // by reusing the representative array. + template + void + link_components(Parent1 component, Parent2 header, + Integer num_nodes, Integer num_components) + { + // Make the non-representative vertices point to their component + Parent1 representative = component; + for (Integer v = 0; v != num_nodes; ++v) + if (component[v] >= num_components || header[component[v]] != v) + component[v] = component[representative[v]]; + + // initialize the "head" of the lists to "NULL" + std::fill_n(header, num_components, num_nodes); + + // Add each vertex to the linked list for its component + Parent1 next = component; + for (Integer k = 0; k != num_nodes; ++k) + push_front(next, header[component[k]], k); + } + + + + template + void + construct_component_index(IndexContainer& index, HeaderContainer& header) + { + build_components_header(index.begin(), + std::back_inserter(header), + index.end() - index.begin()); + + link_components(index.begin(), header.begin(), + index.end() - index.begin(), + header.end() - header.begin()); + } + + + + template + class component_iterator + : boost::forward_iterator_helper< + component_iterator, + Integer, Distance,Integer*, Integer&> + { + public: + typedef component_iterator self; + + IndexIterator next; + Integer node; + + typedef std::forward_iterator_tag iterator_category; + typedef Integer value_type; + typedef Integer& reference; + typedef Integer* pointer; + typedef Distance difference_type; + + component_iterator() {} + component_iterator(IndexIterator x, Integer i) + : next(x), node(i) {} + Integer operator*() const { + return node; + } + self& operator++() { + node = next[node]; + return *this; + } + }; + + template + inline bool + operator==(const component_iterator& x, + const component_iterator& y) + { + return x.node == y.node; + } + + } // namespace detail + +} // namespace detail + +#if defined(__sgi) && !defined(__GNUC__) +#pragma reset woff 1234 +#endif + +#endif diff --git a/win32/include/boost/graph/detail/edge.hpp b/win32/include/boost/graph/detail/edge.hpp new file mode 100755 index 000000000..48274ecac --- /dev/null +++ b/win32/include/boost/graph/detail/edge.hpp @@ -0,0 +1,124 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_DETAIL_EDGE_HPP +#define BOOST_GRAPH_DETAIL_EDGE_HPP + +#if __GNUC__ < 3 +#include +#else +#include +#endif + +namespace boost { + + namespace detail { + + template + struct edge_base + { + inline edge_base() {} + inline edge_base(Vertex s, Vertex d) + : m_source(s), m_target(d) { } + Vertex m_source; + Vertex m_target; + }; + + template + class edge_desc_impl : public edge_base { + typedef edge_desc_impl self; + typedef edge_base Base; + public: + typedef void property_type; + + inline edge_desc_impl() : m_eproperty(0) {} + + inline edge_desc_impl(Vertex s, Vertex d, const property_type* eplug) + : Base(s,d), m_eproperty(const_cast(eplug)) { } + + property_type* get_property() { return m_eproperty; } + const property_type* get_property() const { return m_eproperty; } + + // protected: + property_type* m_eproperty; + }; + + template + inline bool + operator==(const detail::edge_desc_impl& a, + const detail::edge_desc_impl& b) + { + return a.get_property() == b.get_property(); + } + template + inline bool + operator!=(const detail::edge_desc_impl& a, + const detail::edge_desc_impl& b) + { + return ! (a.get_property() == b.get_property()); + } + + // Order edges according to the address of their property object + template + inline bool + operator<(const detail::edge_desc_impl& a, + const detail::edge_desc_impl& b) + { + return a.get_property() < b.get_property(); + } + template + inline bool + operator<=(const detail::edge_desc_impl& a, + const detail::edge_desc_impl& b) + { + return a.get_property() <= b.get_property(); + } + template + inline bool + operator>(const detail::edge_desc_impl& a, + const detail::edge_desc_impl& b) + { + return a.get_property() > b.get_property(); + } + template + inline bool + operator>=(const detail::edge_desc_impl& a, + const detail::edge_desc_impl& b) + { + return a.get_property() >= b.get_property(); + } + + } //namespace detail + +} // namespace boost + +namespace std { + +#if __GNUC__ < 3 + template + std::ostream& + operator<<(std::ostream& os, const boost::detail::edge_desc_impl& e) + { + return os << "(" << e.m_source << "," << e.m_target << ")"; + } +#else + template + std::basic_ostream& + operator<<(std::basic_ostream& os, + const boost::detail::edge_desc_impl& e) + { + return os << "(" << e.m_source << "," << e.m_target << ")"; + } +#endif + +} + + +#endif // BOOST_GRAPH_DETAIL_DETAIL_EDGE_HPP diff --git a/win32/include/boost/graph/detail/incidence_iterator.hpp b/win32/include/boost/graph/detail/incidence_iterator.hpp new file mode 100755 index 000000000..df73807db --- /dev/null +++ b/win32/include/boost/graph/detail/incidence_iterator.hpp @@ -0,0 +1,79 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_DETAIL_INCIDENCE_ITERATOR_HPP +#define BOOST_GRAPH_DETAIL_INCIDENCE_ITERATOR_HPP + +#include +#include + +// OBSOLETE + +namespace boost { + + namespace detail { + // EdgeDir tags + struct in_edge_tag { }; + struct out_edge_tag { }; + + template + struct bidir_incidence_iterator { + typedef bidir_incidence_iterator self; + typedef Edge edge_type; + typedef typename Edge::property_type EdgeProperty; + public: + typedef int difference_type; + typedef std::forward_iterator_tag iterator_category; + typedef edge_type reference; + typedef edge_type value_type; + typedef value_type* pointer; + inline bidir_incidence_iterator() {} + inline bidir_incidence_iterator(Iterator1D ii, Vertex src) + : i(ii), _src(src) { } + + inline self& operator++() { ++i; return *this; } + inline self operator++(int) { self tmp = *this; ++(*this); return tmp; } + + inline reference operator*() const { + return deref_helper(EdgeDir()); + } + inline self* operator->() { return this; } + + Iterator1D& iter() { return i; } + const Iterator1D& iter() const { return i; } + + Iterator1D i; + Vertex _src; + protected: + inline reference deref_helper(out_edge_tag) const { + return edge_type( _src, (*i).get_target(), &(*i).get_property() ); + } + inline reference deref_helper(in_edge_tag) const { + return edge_type((*i).get_target(), _src, &(*i).get_property() ); + } + }; + + template + inline bool operator==(const bidir_incidence_iterator& x, + const bidir_incidence_iterator& y) + { + return x.i == y.i; + } + template + inline bool operator!=(const bidir_incidence_iterator& x, + const bidir_incidence_iterator& y) + { + return x.i != y.i; + } + + + } +} +#endif diff --git a/win32/include/boost/graph/detail/incremental_components.hpp b/win32/include/boost/graph/detail/incremental_components.hpp new file mode 100755 index 000000000..00c2119f1 --- /dev/null +++ b/win32/include/boost/graph/detail/incremental_components.hpp @@ -0,0 +1,141 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_DETAIL_INCREMENTAL_COMPONENTS_HPP +#define BOOST_GRAPH_DETAIL_INCREMENTAL_COMPONENTS_HPP + +#include +#include + +namespace boost { + + namespace detail { + + //========================================================================= + // Implementation detail of incremental_components + + + //------------------------------------------------------------------------- + // Helper functions for the component_index class + + // Record the representative vertices in the header array. + // Representative vertices now point to the component number. + + template + inline void + build_components_header(Parent p, + OutputIterator header, + Integer num_nodes) + { + Parent component = p; + Integer component_num = 0; + for (Integer v = 0; v != num_nodes; ++v) + if (p[v] == v) { + *header++ = v; + component[v] = component_num++; + } + } + + + // Pushes x onto the front of the list. The list is represented in + // an array. + template + inline void array_push_front(Next next, T& head, V x) + { + T tmp = head; + head = x; + next[x] = tmp; + } + + + // Create a linked list of the vertices in each component + // by reusing the representative array. + template + void + link_components(Parent1 component, Parent2 header, + Integer num_nodes, Integer num_components) + { + // Make the non-representative vertices point to their component + Parent1 representative = component; + for (Integer v = 0; v != num_nodes; ++v) + if (component[v] >= num_components + || header[component[v]] != v) + component[v] = component[representative[v]]; + + // initialize the "head" of the lists to "NULL" + std::fill_n(header, num_components, num_nodes); + + // Add each vertex to the linked list for its component + Parent1 next = component; + for (Integer k = 0; k != num_nodes; ++k) + array_push_front(next, header[component[k]], k); + } + + + + template + void + construct_component_index(IndexContainer& index, HeaderContainer& header) + { + typedef typename IndexContainer::value_type Integer; + build_components_header(index.begin(), + std::back_inserter(header), + Integer(index.end() - index.begin())); + + link_components(index.begin(), header.begin(), + Integer(index.end() - index.begin()), + Integer(header.end() - header.begin())); + } + + + + template + class component_iterator + : boost::forward_iterator_helper< + component_iterator, + Integer, Distance,Integer*, Integer&> + { + public: + typedef component_iterator self; + + IndexIterator next; + Integer node; + + typedef std::forward_iterator_tag iterator_category; + typedef Integer value_type; + typedef Integer& reference; + typedef Integer* pointer; + typedef Distance difference_type; + + component_iterator() {} + component_iterator(IndexIterator x, Integer i) + : next(x), node(i) {} + Integer operator*() const { + return node; + } + self& operator++() { + node = next[node]; + return *this; + } + }; + + template + inline bool + operator==(const component_iterator& x, + const component_iterator& y) + { + return x.node == y.node; + } + + } // namespace detail + +} // namespace detail + +#endif // BOOST_GRAPH_DETAIL_INCREMENTAL_COMPONENTS_HPP diff --git a/win32/include/boost/graph/detail/indexed_properties.hpp b/win32/include/boost/graph/detail/indexed_properties.hpp new file mode 100755 index 000000000..53fcb1470 --- /dev/null +++ b/win32/include/boost/graph/detail/indexed_properties.hpp @@ -0,0 +1,180 @@ +// Copyright 2005 The Trustees of Indiana University. + +// 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) + +// Authors: Jeremiah Willcock +// Douglas Gregor +// Andrew Lumsdaine + +// Indexed properties -- used for CSR and CSR-like graphs + +#ifndef BOOST_GRAPH_INDEXED_PROPERTIES_HPP +#define BOOST_GRAPH_INDEXED_PROPERTIES_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace detail { + +template +class indexed_vertex_properties +{ +public: + typedef no_property vertex_property_type; + typedef Property vertex_bundled; + + // Directly access a vertex or edge bundle + Property& operator[](Descriptor v) + { return m_vertex_properties[get(vertex_index, derived(), v)]; } + + const Property& operator[](Descriptor v) const + { return m_vertex_properties[get(vertex_index, derived(), v)]; } + +protected: + // Default-construct with no property values + indexed_vertex_properties() {} + + // Initialize with n default-constructed property values + indexed_vertex_properties(std::size_t n) : m_vertex_properties(n) { } + +public: + // Resize the properties vector + void resize(std::size_t n) + { + m_vertex_properties.resize(n); + } + + // Reserve space in the vector of properties + void reserve(std::size_t n) + { + m_vertex_properties.reserve(n); + } + + // Add a new property value to the back + void push_back(const Property& prop) + { + m_vertex_properties.push_back(prop); + } + + // Access to the derived object + Derived& derived() { return *static_cast(this); } + + const Derived& derived() const + { return *static_cast(this); } + +public: // should be private, but friend templates not portable + std::vector m_vertex_properties; +}; + +template +class indexed_vertex_properties +{ + struct secret {}; + + public: + typedef no_property vertex_property_type; + typedef void vertex_bundled; + + secret operator[](secret) { return secret(); } + + protected: + // All operations do nothing. + indexed_vertex_properties() { } + indexed_vertex_properties(std::size_t) { } + +public: + void resize(std::size_t) { } + void reserve(std::size_t) { } +}; + +template +class indexed_edge_properties +{ +public: + typedef no_property edge_property_type; + typedef Property edge_bundled; + typedef Property edge_push_back_type; + + // Directly access a edge or edge bundle + Property& operator[](Descriptor v) + { return m_edge_properties[get(edge_index, derived(), v)]; } + + const Property& operator[](Descriptor v) const + { return m_edge_properties[get(edge_index, derived(), v)]; } + +protected: + // Default-construct with no property values + indexed_edge_properties() {} + + // Initialize with n default-constructed property values + indexed_edge_properties(std::size_t n) : m_edge_properties(n) { } + + // Resize the properties vector + void resize(std::size_t n) + { + m_edge_properties.resize(n); + } + + // Reserve space in the vector of properties + void reserve(std::size_t n) + { + m_edge_properties.reserve(n); + } + + public: + // Add a new property value to the back + void push_back(const Property& prop) + { + m_edge_properties.push_back(prop); + } + + private: + // Access to the derived object + Derived& derived() { return *static_cast(this); } + + const Derived& derived() const + { return *static_cast(this); } + +public: // should be private, but friend templates not portable + std::vector m_edge_properties; +}; + +template +class indexed_edge_properties +{ + struct secret {}; + + public: + typedef no_property edge_property_type; + typedef void edge_bundled; + typedef void* edge_push_back_type; + + secret operator[](secret) { return secret(); } + + protected: + // All operations do nothing. + indexed_edge_properties() { } + indexed_edge_properties(std::size_t) { } + void resize(std::size_t) { } + void reserve(std::size_t) { } + + public: + void push_back(const edge_push_back_type&) { } +}; + +} +} + +#endif // BOOST_GRAPH_INDEXED_PROPERTIES_HPP diff --git a/win32/include/boost/graph/detail/is_same.hpp b/win32/include/boost/graph/detail/is_same.hpp new file mode 100755 index 000000000..121231902 --- /dev/null +++ b/win32/include/boost/graph/detail/is_same.hpp @@ -0,0 +1,40 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_DETAIL_IS_SAME_HPP +#define BOOST_GRAPH_DETAIL_IS_SAME_HPP + +#include + +namespace boost { + struct false_tag; + struct true_tag; + + namespace graph_detail { + +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct is_same { + typedef boost::false_tag is_same_tag; + }; + template + struct is_same { + typedef boost::true_tag is_same_tag; + }; +#else + template + struct is_same { + enum { Unum = U::num, Vnum = V::num }; + typedef typename mpl::if_c< (Unum == Vnum), + boost::true_tag, boost::false_tag>::type is_same_tag; + }; +#endif + } // namespace graph_detail +} // namespace boost + +#endif diff --git a/win32/include/boost/graph/detail/list_base.hpp b/win32/include/boost/graph/detail/list_base.hpp new file mode 100755 index 000000000..7acd7d995 --- /dev/null +++ b/win32/include/boost/graph/detail/list_base.hpp @@ -0,0 +1,220 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_LIST_BASE_HPP +#define BOOST_LIST_BASE_HPP + +#include + +// Perhaps this should go through formal review, and move to . + +/* + An alternate interface idea: + Extend the std::list functionality by creating remove/insert + functions that do not require the container object! + */ + +namespace boost { + namespace detail { + + //========================================================================= + // Linked-List Generic Implementation Functions + + template + inline Node + slist_insert_after(Node pos, Node x, + Next next) + { + next(x) = next(pos); + next(pos) = x; + return x; + } + + // return next(pos) or next(next(pos)) ? + template + inline Node + slist_remove_after(Node pos, + Next next) + { + Node n = next(pos); + next(pos) = next(n); + return n; + } + + template + inline Node + slist_remove_range(Node before_first, Node last, + Next next) + { + next(before_first) = last; + return last; + } + + template + inline Node + slist_previous(Node head, Node x, Node nil, + Next next) + { + while (head != nil && next(head) != x) + head = next(head); + return head; + } + + template + inline void + slist_splice_after(Node pos, Node before_first, Node before_last, + Next next) + { + if (pos != before_first && pos != before_last) { + Node first = next(before_first); + Node after = next(pos); + next(before_first) = next(before_last); + next(pos) = first; + next(before_last) = after; + } + } + + template + inline Node + slist_reverse(Node node, Node nil, + Next next) + { + Node result = node; + node = next(node); + next(result) = nil; + while(node) { + Node next = next(node); + next(node) = result; + result = node; + node = next; + } + return result; + } + + template + inline std::size_t + slist_size(Node head, Node nil, + Next next) + { + std::size_t s = 0; + for ( ; head != nil; head = next(head)) + ++s; + return s; + } + + template + class slist_iterator_policies + { + public: + explicit slist_iterator_policies(const Next& n, const Data& d) + : m_next(n), m_data(d) { } + + template + Reference dereference(type, const Node& x) const + { return m_data(x); } + + template + void increment(Node& x) const + { x = m_next(x); } + + template + bool equal(Node& x, Node& y) const + { return x == y; } + + protected: + Next m_next; + Data m_data; + }; + + //=========================================================================== + // Doubly-Linked List Generic Implementation Functions + + template + inline void + dlist_insert_before(Node pos, Node x, + Next next, Prev prev) + { + next(x) = pos; + prev(x) = prev(pos); + next(prev(pos)) = x; + prev(pos) = x; + } + + template + void + dlist_remove(Node pos, + Next next, Prev prev) + { + Node next_node = next(pos); + Node prev_node = prev(pos); + next(prev_node) = next_node; + prev(next_node) = prev_node; + } + + // This deletes every node in the list except the + // sentinel node. + template + inline void + dlist_clear(Node sentinel, Delete del) + { + Node i, tmp; + i = next(sentinel); + while (i != sentinel) { + tmp = i; + i = next(i); + del(tmp); + } + } + + template + inline bool + dlist_empty(Node dummy) + { + return next(dummy) == dummy; + } + + template + void + dlist_transfer(Node pos, Node first, Node last, + Next next, Prev prev) + { + if (pos != last) { + // Remove [first,last) from its old position + next(prev(last)) = pos; + next(prev(first)) = last; + next(prev(pos)) = first; + + // Splice [first,last) into its new position + Node tmp = prev(pos); + prev(pos) = prev(last); + prev(last) = prev(first); + prev(first) = tmp; + } + } + + template + class dlist_iterator_policies + : public slist_iterator_policies + { + typedef slist_iterator_policies Base; + public: + template + void decrement(Node& x) const + { x = m_prev(x); } + + dlist_iterator_policies(Next n, Prev p, Data d) + : Base(n,d), m_prev(p) { } + protected: + Prev m_prev; + }; + + } // namespace detail +} // namespace boost + +#endif // BOOST_LIST_BASE_HPP diff --git a/win32/include/boost/graph/detail/permutation.hpp b/win32/include/boost/graph/detail/permutation.hpp new file mode 100755 index 000000000..ab288485b --- /dev/null +++ b/win32/include/boost/graph/detail/permutation.hpp @@ -0,0 +1,205 @@ +// (C) Copyright Jeremy Siek 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PERMUTATION_HPP +#define BOOST_PERMUTATION_HPP + +#include +#include +#include +#include +#include + +namespace boost { + +template +void permute_serial(Iter1 permuter, Iter1 last, Iter2 result) +{ +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + typedef std::ptrdiff_t D: +#else + typedef typename std::iterator_traits::difference_type D; +#endif + + D n = 0; + while (permuter != last) { + std::swap(result[n], result[*permuter]); + ++n; + ++permuter; + } +} + +template +void permute_copy(InIter first, InIter last, RandIterP p, RandIterR result) +{ +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + typedef std::ptrdiff_t i = 0; +#else + typename std::iterator_traits::difference_type i = 0; +#endif + for (; first != last; ++first, ++i) + result[p[i]] = *first; +} + +namespace detail { + +template +void permute_helper(RandIter first, RandIter last, RandIterPerm p, D, T) +{ + D i = 0, pi, n = last - first, cycle_start; + T tmp; + std::vector visited(n, false); + + while (i != n) { // continue until all elements have been processed + cycle_start = i; + tmp = first[i]; + do { // walk around a cycle + pi = p[i]; + visited[pi] = true; + std::swap(tmp, first[pi]); + i = pi; + } while (i != cycle_start); + + // find the next cycle + for (i = 0; i < n; ++i) + if (visited[i] == false) + break; + } +} + +} // namespace detail + +template +void permute(RandIter first, RandIter last, RandIterPerm p) +{ + detail::permute_helper(first, last, p, last - first, *first); +} + + +// Knuth 1.3.3, Vol. 1 p 176 +// modified for zero-based arrays +// time complexity? +// +// WARNING: T must be a signed integer! +template +void invert_permutation(PermIter X, PermIter Xend) +{ +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + typedef std::ptrdiff_t T: +#else + typedef typename std::iterator_traits::value_type T; +#endif + T n = Xend - X; + T m = n; + T j = -1; + + while (m > 0) { + T i = X[m-1] + 1; + if (i > 0) { + do { + X[m-1] = j - 1; + j = -m; + m = i; + i = X[m-1] + 1; + } while (i > 0); + i = j; + } + X[m-1] = -i - 1; + --m; + } +} + +// Takes a "normal" permutation array (and its inverse), and turns it +// into a BLAS-style permutation array (which can be thought of as a +// serialized permutation). +template +inline void serialize_permutation(Iter1 q, Iter1 q_end, Iter2 q_inv, Iter3 p) +{ +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + typedef std::ptrdiff_t P1; + typedef std::ptrdiff_t P2; + typedef std::ptrdiff_t D; +#else + typedef typename std::iterator_traits::value_type P1; + typedef typename std::iterator_traits::value_type P2; + typedef typename std::iterator_traits::difference_type D; +#endif + D n = q_end - q; + for (D i = 0; i < n; ++i) { + P1 qi = q[i]; + P2 qii = q_inv[i]; + *p++ = qii; + std::swap(q[i], q[qii]); + std::swap(q_inv[i], q_inv[qi]); + } +} + +// Not used anymore, leaving it here for future reference. +template +void merge_sort(Iter first, Iter last, Compare cmp) +{ + if (first + 1 < last) { + Iter mid = first + (last - first)/2; + merge_sort(first, mid, cmp); + merge_sort(mid, last, cmp); + std::inplace_merge(first, mid, last, cmp); + } +} + + +// time: N log N + 3N + ? +// space: 2N +template +inline void sortp(Iter first, Iter last, IterP p, Cmp cmp, Alloc alloc) +{ + typedef typename std::iterator_traits::value_type P; + typedef typename std::iterator_traits::difference_type D; + D n = last - first; + std::vector q(n); + for (D i = 0; i < n; ++i) + q[i] = i; + std::sort(make_shadow_iter(first, q.begin()), + make_shadow_iter(last, q.end()), + shadow_cmp(cmp)); + invert_permutation(q.begin(), q.end()); + std::copy(q.begin(), q.end(), p); +} + +template +inline void sortp(Iter first, Iter last, IterP p, Cmp cmp) +{ + typedef typename std::iterator_traits::value_type P; + sortp(first, last, p, cmp, std::allocator

            ()); +} + +template +inline void sortp(Iter first, Iter last, IterP p) +{ + typedef typename std::iterator_traits::value_type T; + typedef typename std::iterator_traits::value_type P; + sortp(first, last, p, std::less(), std::allocator

            ()); +} + +template +inline void sortv(Iter first, Iter last, IterP p, Cmp cmp, Alloc alloc) +{ + typedef typename std::iterator_traits::value_type P; + typedef typename std::iterator_traits::difference_type D; + D n = last - first; + std::vector q(n), q_inv(n); + for (D i = 0; i < n; ++i) + q_inv[i] = i; + std::sort(make_shadow_iter(first, q_inv.begin()), + make_shadow_iter(last, q_inv.end()), + shadow_cmp(cmp)); + std::copy(q_inv, q_inv.end(), q.begin()); + invert_permutation(q.begin(), q.end()); + serialize_permutation(q.begin(), q.end(), q_inv.end(), p); +} + + +} // namespace boost + +#endif // BOOST_PERMUTATION_HPP diff --git a/win32/include/boost/graph/detail/read_graphviz_spirit.hpp b/win32/include/boost/graph/detail/read_graphviz_spirit.hpp new file mode 100755 index 000000000..90bebe1d7 --- /dev/null +++ b/win32/include/boost/graph/detail/read_graphviz_spirit.hpp @@ -0,0 +1,611 @@ +// Copyright 2004-5 Trustees of Indiana University + +// 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) + +// +// read_graphviz_spirit.hpp - +// Initialize a model of the BGL's MutableGraph concept and an associated +// collection of property maps using a graph expressed in the GraphViz +// DOT Language. +// +// Based on the grammar found at: +// http://www.graphviz.org/cvs/doc/info/lang.html +// +// See documentation for this code at: +// http://www.boost.org/libs/graph/doc/read-graphviz.html +// + +// Author: Ronald Garcia +// + +#ifndef BOOST_READ_GRAPHVIZ_SPIRIT_HPP +#define BOOST_READ_GRAPHVIZ_SPIRIT_HPP + +// Phoenix/Spirit set these limits to 3, but I need more. +#define PHOENIX_LIMIT 6 +#define BOOST_SPIRIT_CLOSURE_LIMIT 6 + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for std::exception +#include +#include +#include +#include +#include +#include +#include + +namespace phoenix { +// Workaround: std::map::operator[] uses a different return type than all +// other standard containers. Phoenix doesn't account for that. +template +struct binary_operator, T1> +{ + typedef typename std::map::mapped_type& result_type; + static result_type eval(std::map& container, T1 const& index) + { return container[index]; } +}; +} // namespace phoenix + +namespace boost { +namespace detail { +namespace graph { + + +///////////////////////////////////////////////////////////////////////////// +// Application-specific type definitions +///////////////////////////////////////////////////////////////////////////// + +typedef std::set edges_t; +typedef std::set nodes_t; +typedef std::set ids_t; +typedef std::map edge_map_t; +typedef std::map node_map_t; +typedef std::map props_t; +typedef std::map subgraph_props_t; +typedef boost::function2 actor_t; +typedef std::vector edge_stack_t; +typedef std::map subgraph_nodes_t; +typedef std::map subgraph_edges_t; + + + +///////////////////////////////////////////////////////////////////////////// +// Stack frames used by semantic actions +///////////////////////////////////////////////////////////////////////////// +struct id_closure : boost::spirit::closure { + member1 name; +}; + + +struct node_id_closure : boost::spirit::closure { + member1 name; +}; + +struct attr_list_closure : boost::spirit::closure { + member1 prop_actor; +}; + +struct property_closure : boost::spirit::closure { + member1 key; + member2 value; +}; + +struct data_stmt_closure : boost::spirit::closure { + member1 sources; + member2 dests; + member3 edge_stack; + member4 saw_node; + member5 active_node; +}; + +struct subgraph_closure : boost::spirit::closure { + member1 nodes; + member2 edges; + member3 name; +}; + +///////////////////////////////////////////////////////////////////////////// +// Grammar and Actions for the DOT Language +///////////////////////////////////////////////////////////////////////////// + +// Grammar for a dot file. +struct dot_grammar : public boost::spirit::grammar { + mutate_graph& graph_; + explicit dot_grammar(mutate_graph& graph) : graph_(graph) { } + + template + struct definition { + + definition(dot_grammar const& self) : self(self), subgraph_depth(0), + keyword_p("0-9a-zA-Z_") { + using namespace boost::spirit; + using namespace phoenix; + + // RG - Future Work + // - Handle multi-line strings using \ line continuation + // - Make keywords case insensitive + ID + = ( lexeme_d[((alpha_p | ch_p('_')) >> *(alnum_p | ch_p('_')))] + | real_p + | lexeme_d[confix_p('"', *c_escape_ch_p, '"')] + | comment_nest_p('<', '>') + )[ID.name = construct_(arg1,arg2)] + ; + + a_list + = list_p( ID[(a_list.key = arg1), + (a_list.value = "true") + ] + >> !( ch_p('=') + >> ID[a_list.value = arg1]) + [phoenix::bind(&definition::call_prop_actor) + (var(*this),a_list.key,a_list.value)],!ch_p(',')); + + attr_list = +(ch_p('[') >> !a_list >> ch_p(']')); + + // RG - disregard port id's for now. + port_location + = (ch_p(':') >> ID) + | (ch_p(':') >> ch_p('(') >> ID >> ch_p(',') >> ID >> ch_p(')')) + ; + + port_angle = ch_p('@') >> ID; + + port + = port_location >> (!port_angle) + | port_angle >> (!port_location); + + + node_id + = ( ID[node_id.name = arg1] >> (!port) ) + [phoenix::bind(&definition::memoize_node)(var(*this))]; + + graph_stmt + = (ID[graph_stmt.key = arg1] >> + ch_p('=') >> + ID[graph_stmt.value = arg1]) + [phoenix::bind(&definition::call_graph_prop) + (var(*this),graph_stmt.key,graph_stmt.value)] + ; // Graph property. + + attr_stmt + = (as_lower_d[keyword_p("graph")] + >> attr_list(actor_t(phoenix::bind(&definition::default_graph_prop) + (var(*this),arg1,arg2)))) + | (as_lower_d[keyword_p("node")] + >> attr_list(actor_t(phoenix::bind(&definition::default_node_prop) + (var(*this),arg1,arg2)))) + | (as_lower_d[keyword_p("edge")] + >> attr_list(actor_t(phoenix::bind(&definition::default_edge_prop) + (var(*this),arg1,arg2)))) + ; + + // edge_head is set depending on the graph type (directed/undirected) + edgeop = ch_p('-') >> ch_p(boost::ref(edge_head)); + + edgeRHS + = +( edgeop[(data_stmt.sources = data_stmt.dests), + (data_stmt.dests = construct_())] + >> ( subgraph[data_stmt.dests = arg1] + | node_id[phoenix::bind(&definition::insert_node) + (var(*this),data_stmt.dests,arg1)] + ) + [phoenix::bind(&definition::activate_edge) + (var(*this),data_stmt.sources,data_stmt.dests, + var(edges), var(default_edge_props))] + ); + + + // To avoid backtracking, edge, node, and subgraph statements are + // processed as one nonterminal. + data_stmt + = ( subgraph[(data_stmt.dests = arg1),// will get moved in rhs + (data_stmt.saw_node = false)] + | node_id[(phoenix::bind(&definition::insert_node) + (var(*this),data_stmt.dests,arg1)), + (data_stmt.saw_node = true), +#ifdef BOOST_GRAPH_DEBUG + (std::cout << val("AcTive Node: ") << arg1 << "\n"), +#endif // BOOST_GRAPH_DEBUG + (data_stmt.active_node = arg1)] + ) >> if_p(edgeRHS)[ + !attr_list( + actor_t(phoenix::bind(&definition::edge_prop) + (var(*this),arg1,arg2))) + ].else_p[ + if_p(data_stmt.saw_node)[ + !attr_list( + actor_t(phoenix::bind(&definition::node_prop) + (var(*this),arg1,arg2))) + ] // otherwise it's a subgraph, nothing more to do. + ]; + + + stmt + = graph_stmt + | attr_stmt + | data_stmt + ; + + stmt_list = *( stmt >> !ch_p(';') ); + + subgraph + = !( as_lower_d[keyword_p("subgraph")] + >> (!ID[(subgraph.name = arg1), + (subgraph.nodes = (var(subgraph_nodes))[arg1]), + (subgraph.edges = (var(subgraph_edges))[arg1])]) + ) + >> ch_p('{')[++var(subgraph_depth)] + >> stmt_list + >> ch_p('}')[--var(subgraph_depth)] + [(var(subgraph_nodes))[subgraph.name] = subgraph.nodes] + [(var(subgraph_edges))[subgraph.name] = subgraph.edges] + + | as_lower_d[keyword_p("subgraph")] + >> ID[(subgraph.nodes = (var(subgraph_nodes))[arg1]), + (subgraph.edges = (var(subgraph_edges))[arg1])] + ; + + the_grammar + = (!as_lower_d[keyword_p("strict")]) + >> ( as_lower_d[keyword_p("graph")][ + (var(edge_head) = '-'), + (phoenix::bind(&definition::check_undirected)(var(*this)))] + | as_lower_d[keyword_p("digraph")][ + (var(edge_head) = '>'), + (phoenix::bind(&definition::check_directed)(var(*this)))] + ) + >> (!ID) >> ch_p('{') >> stmt_list >> ch_p('}'); + + } // definition() + + typedef boost::spirit::rule rule_t; + + rule_t const& start() const { return the_grammar; } + + + // + // Semantic actions + // + + void check_undirected() { + if(self.graph_.is_directed()) + boost::throw_exception(boost::undirected_graph_error()); + } + + void check_directed() { + if(!self.graph_.is_directed()) + boost::throw_exception(boost::directed_graph_error()); + } + + void memoize_node() { + id_t const& node = node_id.name(); + props_t& node_props = default_node_props; + + if(nodes.find(node) == nodes.end()) { + nodes.insert(node); + self.graph_.do_add_vertex(node); + + node_map.insert(std::make_pair(node,ids_t())); + +#ifdef BOOST_GRAPH_DEBUG + std::cout << "Add new node " << node << std::endl; +#endif // BOOST_GRAPH_DEBUG + // Set the default properties for this edge + // RG: Here I would actually set the properties + for(props_t::iterator i = node_props.begin(); + i != node_props.end(); ++i) { + set_node_property(node,i->first,i->second); + } + if(subgraph_depth > 0) { + subgraph.nodes().insert(node); + // Set the subgraph's default properties as well + props_t& props = subgraph_node_props[subgraph.name()]; + for(props_t::iterator i = props.begin(); i != props.end(); ++i) { + set_node_property(node,i->first,i->second); + } + } + } else { +#ifdef BOOST_GRAPH_DEBUG + std::cout << "See node " << node << std::endl; +#endif // BOOST_GRAPH_DEBUG + } + } + + void activate_edge(nodes_t& sources, nodes_t& dests, edges_t& edges, + props_t& edge_props) { + edge_stack_t& edge_stack = data_stmt.edge_stack(); + for(nodes_t::iterator i = sources.begin(); i != sources.end(); ++i) { + for(nodes_t::iterator j = dests.begin(); j != dests.end(); ++j) { + // Create the edge and push onto the edge stack. +#ifdef BOOST_GRAPH_DEBUG + std::cout << "Edge " << *i << " to " << *j << std::endl; +#endif // BOOST_GRAPH_DEBUG + + edge_t edge = edge_t::new_edge(); + edge_stack.push_back(edge); + edges.insert(edge); + edge_map.insert(std::make_pair(edge,ids_t())); + + // Add the real edge. + self.graph_.do_add_edge(edge, *i, *j); + + // Set the default properties for this edge + for(props_t::iterator k = edge_props.begin(); + k != edge_props.end(); ++k) { + set_edge_property(edge,k->first,k->second); + } + if(subgraph_depth > 0) { + subgraph.edges().insert(edge); + // Set the subgraph's default properties as well + props_t& props = subgraph_edge_props[subgraph.name()]; + for(props_t::iterator k = props.begin(); k != props.end(); ++k) { + set_edge_property(edge,k->first,k->second); + } + } + } + } + } + + // node_prop - Assign the property for the current active node. + void node_prop(id_t const& key, id_t const& value) { + node_t& active_object = data_stmt.active_node(); + set_node_property(active_object, key, value); + } + + // edge_prop - Assign the property for the current active edges. + void edge_prop(id_t const& key, id_t const& value) { + edge_stack_t const& active_edges_ = data_stmt.edge_stack(); + for (edge_stack_t::const_iterator i = active_edges_.begin(); + i != active_edges_.end(); ++i) { + set_edge_property(*i,key,value); + } + } + + // default_graph_prop - Store as a graph property. + void default_graph_prop(id_t const& key, id_t const& value) { +#ifdef BOOST_GRAPH_DEBUG + std::cout << key << " = " << value << std::endl; +#endif // BOOST_GRAPH_DEBUG + self.graph_.set_graph_property(key, value); + } + + // default_node_prop - declare default properties for any future new nodes + void default_node_prop(id_t const& key, id_t const& value) { + nodes_t& nodes_ = + subgraph_depth == 0 ? nodes : subgraph.nodes(); + props_t& node_props_ = + subgraph_depth == 0 ? + default_node_props : + subgraph_node_props[subgraph.name()]; + + // add this to the selected list of default node properties. + node_props_[key] = value; + // for each node, set its property to default-constructed value + // if it hasn't been set already. + // set the dynamic property map value + for(nodes_t::iterator i = nodes_.begin(); i != nodes_.end(); ++i) + if(node_map[*i].find(key) == node_map[*i].end()) { + set_node_property(*i,key,id_t()); + } + } + + // default_edge_prop - declare default properties for any future new edges + void default_edge_prop(id_t const& key, id_t const& value) { + edges_t& edges_ = + subgraph_depth == 0 ? edges : subgraph.edges(); + props_t& edge_props_ = + subgraph_depth == 0 ? + default_edge_props : + subgraph_edge_props[subgraph.name()]; + + // add this to the list of default edge properties. + edge_props_[key] = value; + // for each edge, set its property to be empty string + // set the dynamic property map value + for(edges_t::iterator i = edges_.begin(); i != edges_.end(); ++i) + if(edge_map[*i].find(key) == edge_map[*i].end()) + set_edge_property(*i,key,id_t()); + } + + // helper function + void insert_node(nodes_t& nodes, id_t const& name) { + nodes.insert(name); + } + + void call_prop_actor(std::string const& lhs, std::string const& rhs) { + actor_t& actor = attr_list.prop_actor(); + // If first and last characters of the rhs are double-quotes, + // remove them. + if (!rhs.empty() && rhs[0] == '"' && rhs[rhs.size() - 1] == '"') + actor(lhs, rhs.substr(1, rhs.size()-2)); + else + actor(lhs,rhs); + } + + void call_graph_prop(std::string const& lhs, std::string const& rhs) { + // If first and last characters of the rhs are double-quotes, + // remove them. + if (!rhs.empty() && rhs[0] == '"' && rhs[rhs.size() - 1] == '"') + this->default_graph_prop(lhs, rhs.substr(1, rhs.size()-2)); + else + this->default_graph_prop(lhs,rhs); + } + + void set_node_property(node_t const& node, id_t const& key, + id_t const& value) { + + // Add the property key to the "set" table to avoid default overwrite + node_map[node].insert(key); + // Set the user's property map + self.graph_.set_node_property(key, node, value); +#ifdef BOOST_GRAPH_DEBUG + // Tell the world + std::cout << node << ": " << key << " = " << value << std::endl; +#endif // BOOST_GRAPH_DEBUG + } + + void set_edge_property(edge_t const& edge, id_t const& key, + id_t const& value) { + + // Add the property key to the "set" table to avoid default overwrite + edge_map[edge].insert(key); + // Set the user's property map + self.graph_.set_edge_property(key, edge, value); +#ifdef BOOST_GRAPH_DEBUG + // Tell the world +#if 0 // RG - edge representation changed, + std::cout << "(" << edge.first << "," << edge.second << "): " +#else + std::cout << "an edge: " +#endif // 0 + << key << " = " << value << std::endl; +#endif // BOOST_GRAPH_DEBUG + } + + // Variables explicitly initialized + dot_grammar const& self; + // if subgraph_depth > 0, then we're processing a subgraph. + int subgraph_depth; + + // Keywords; + const boost::spirit::distinct_parser<> keyword_p; + // + // rules that make up the grammar + // + boost::spirit::rule ID; + boost::spirit::rule a_list; + boost::spirit::rule attr_list; + rule_t port_location; + rule_t port_angle; + rule_t port; + boost::spirit::rule node_id; + boost::spirit::rule graph_stmt; + rule_t attr_stmt; + boost::spirit::rule data_stmt; + boost::spirit::rule subgraph; + rule_t edgeop; + rule_t edgeRHS; + rule_t stmt; + rule_t stmt_list; + rule_t the_grammar; + + + // The grammar uses edge_head to dynamically set the syntax for edges + // directed graphs: edge_head = '>', and so edgeop = "->" + // undirected graphs: edge_head = '-', and so edgeop = "--" + char edge_head; + + + // + // Support data structures + // + + nodes_t nodes; // list of node names seen + edges_t edges; // list of edges seen + node_map_t node_map; // remember the properties set for each node + edge_map_t edge_map; // remember the properties set for each edge + + subgraph_nodes_t subgraph_nodes; // per-subgraph lists of nodes + subgraph_edges_t subgraph_edges; // per-subgraph lists of edges + + props_t default_node_props; // global default node properties + props_t default_edge_props; // global default edge properties + subgraph_props_t subgraph_node_props; // per-subgraph default node properties + subgraph_props_t subgraph_edge_props; // per-subgraph default edge properties + }; // struct definition +}; // struct dot_grammar + + + +// +// dot_skipper - GraphViz whitespace and comment skipper +// +struct dot_skipper : public boost::spirit::grammar +{ + dot_skipper() {} + + template + struct definition + { + definition(dot_skipper const& /*self*/) { + using namespace boost::spirit; + using namespace phoenix; + // comment forms + skip = eol_p >> comment_p("#") + | space_p + | comment_p("//") +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1400) + | confix_p(str_p("/*") ,*anychar_p, str_p("*/")) +#else + | confix_p("/*" ,*anychar_p, "*/") +#endif + ; + +#ifdef BOOST_SPIRIT_DEBUG + BOOST_SPIRIT_DEBUG_RULE(skip); +#endif + } + + boost::spirit::rule skip; + boost::spirit::rule const& + start() const { return skip; } + }; // definition +}; // dot_skipper + +} // namespace graph +} // namespace detail + +template +bool read_graphviz(MultiPassIterator begin, MultiPassIterator end, + MutableGraph& graph, dynamic_properties& dp, + std::string const& node_id = "node_id") { + using namespace boost; + using namespace boost::spirit; + + typedef MultiPassIterator iterator_t; + typedef skip_parser_iteration_policy< boost::detail::graph::dot_skipper> + iter_policy_t; + typedef scanner_policies scanner_policies_t; + typedef scanner scanner_t; + + ::boost::detail::graph::mutate_graph_impl + m_graph(graph, dp, node_id); + + ::boost::detail::graph::dot_grammar p(m_graph); + ::boost::detail::graph::dot_skipper skip_p; + + iter_policy_t iter_policy(skip_p); + scanner_policies_t policies(iter_policy); + + scanner_t scan(begin, end, policies); + + return p.parse(scan); +} + +} // namespace boost + +#endif // BOOST_READ_GRAPHVIZ_SPIRIT_HPP diff --git a/win32/include/boost/graph/detail/self_avoiding_walk.hpp b/win32/include/boost/graph/detail/self_avoiding_walk.hpp new file mode 100755 index 000000000..1ecb904c8 --- /dev/null +++ b/win32/include/boost/graph/detail/self_avoiding_walk.hpp @@ -0,0 +1,418 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_SELF_AVOIDING_WALK_HPP +#define BOOST_SELF_AVOIDING_WALK_HPP + +/* + This file defines necessary components for SAW. + + mesh language: (defined by myself to clearify what is what) + A triangle in mesh is called an triangle. + An edge in mesh is called an line. + A vertex in mesh is called a point. + + A triangular mesh corresponds to a graph in which a vertex is a + triangle and an edge(u, v) stands for triangle u and triangle v + share an line. + + After this point, a vertex always refers to vertex in graph, + therefore it is a traingle in mesh. + + */ + +#include +#include +#include +#include + +#define SAW_SENTINAL -1 + +namespace boost { + + template + struct triple { + T1 first; + T2 second; + T3 third; + triple(const T1& a, const T2& b, const T3& c) : first(a), second(b), third(c) {} + triple() : first(SAW_SENTINAL), second(SAW_SENTINAL), third(SAW_SENTINAL) {} + }; + + typedef triple Triple; + + /* Define a vertex property which has a triangle inside. Triangle is + represented by a triple. */ + struct triangle_tag { enum { num = 100 }; }; + typedef property triangle_property; + + /* Define an edge property with a line. A line is represented by a + pair. This is not required for SAW though. + */ + struct line_tag { enum { num = 101 }; }; + template struct line_property + : public property > { }; + + /*Precondition: Points in a Triangle are in order */ + template + inline void get_sharing(const Triangle& a, const Triangle& b, Line& l) + { + l.first = SAW_SENTINAL; + l.second = SAW_SENTINAL; + + if ( a.first == b.first ) { + l.first = a.first; + if ( a.second == b.second || a.second == b.third ) + l.second = a.second; + else if ( a.third == b.second || a.third == b.third ) + l.second = a.third; + + } else if ( a.first == b.second ) { + l.first = a.first; + if ( a.second == b.third ) + l.second = a.second; + else if ( a.third == b.third ) + l.second = a.third; + + } else if ( a.first == b.third ) { + l.first = a.first; + + + } else if ( a.second == b.first ) { + l.first = a.second; + if ( a.third == b.second || a.third == b.third ) + l.second = a.third; + + } else if ( a.second == b.second ) { + l.first = a.second; + if ( a.third == b.third ) + l.second = a.third; + + } else if ( a.second == b.third ) { + l.first = a.second; + + + } else if ( a.third == b.first + || a.third == b.second + || a.third == b.third ) + l.first = a.third; + + /*Make it in order*/ + if ( l.first > l.second ) { + typename Line::first_type i = l.first; + l.first = l.second; + l.second = i; + } + + } + + template + struct get_vertex_sharing { + typedef std::pair Pair; + get_vertex_sharing(const TriangleDecorator& _td) : td(_td) {} + inline Line operator()(const Vertex& u, const Vertex& v) const { + Line l; + get_sharing(td[u], td[v], l); + return l; + } + inline Line operator()(const Pair& u, const Vertex& v) const { + Line l; + get_sharing(td[u.first], td[v], l); + return l; + } + inline Line operator()(const Pair& u, const Pair& v) const { + Line l; + get_sharing(td[u.first], td[v.first], l); + return l; + } + TriangleDecorator td; + }; + + /* HList has to be a handle of data holder so that pass-by-value is + * in right logic. + * + * The element of HList is a pair of vertex and line. (remember a + * line is a pair of two ints.). That indicates the walk w from + * current vertex is across line. (If the first of line is -1, it is + * a point though. + */ + template < class TriangleDecorator, class HList, class IteratorD> + class SAW_visitor + : public bfs_visitor<>, public dfs_visitor<> + { + typedef typename boost::property_traits::value_type iter; + /*use boost shared_ptr*/ + typedef typename HList::element_type::value_type::second_type Line; + public: + + typedef tree_edge_tag category; + + inline SAW_visitor(TriangleDecorator _td, HList _hlist, IteratorD ia) + : td(_td), hlist(_hlist), iter_d(ia) {} + + template + inline void start_vertex(Vertex v, Graph&) { + Line l1; + l1.first = SAW_SENTINAL; + l1.second = SAW_SENTINAL; + hlist->push_front(std::make_pair(v, l1)); + iter_d[v] = hlist->begin(); + } + + /*Several symbols: + w(i): i-th triangle in walk w + w(i) |- w(i+1): w enter w(i+1) from w(i) over a line + w(i) ~> w(i+1): w enter w(i+1) from w(i) over a point + w(i) -> w(i+1): w enter w(i+1) from w(i) + w(i) ^ w(i+1): the line or point w go over from w(i) to w(i+1) + */ + template + bool tree_edge(Edge e, Graph& G) { + using std::make_pair; + typedef typename boost::graph_traits::vertex_descriptor Vertex; + Vertex tau = target(e, G); + Vertex i = source(e, G); + + get_vertex_sharing get_sharing_line(td); + + Line tau_i = get_sharing_line(tau, i); + + iter w_end = hlist->end(); + + iter w_i = iter_d[i]; + + iter w_i_m_1 = w_i; + iter w_i_p_1 = w_i; + + /*---------------------------------------------------------- + * true false + *========================================================== + *a w(i-1) |- w(i) w(i-1) ~> w(i) or w(i-1) is null + *---------------------------------------------------------- + *b w(i) |- w(i+1) w(i) ~> w(i+1) or no w(i+1) yet + *---------------------------------------------------------- + */ + + bool a = false, b = false; + + --w_i_m_1; + ++w_i_p_1; + b = ( w_i->second.first != SAW_SENTINAL ); + + if ( w_i_m_1 != w_end ) { + a = ( w_i_m_1->second.first != SAW_SENTINAL ); + } + + if ( a ) { + + if ( b ) { + /*Case 1: + + w(i-1) |- w(i) |- w(i+1) + */ + Line l1 = get_sharing_line(*w_i_m_1, tau); + + iter w_i_m_2 = w_i_m_1; + --w_i_m_2; + + bool c = true; + + if ( w_i_m_2 != w_end ) { + c = w_i_m_2->second != l1; + } + + if ( c ) { /* w(i-1) ^ tau != w(i-2) ^ w(i-1) */ + /*extension: w(i-1) -> tau |- w(i) */ + w_i_m_1->second = l1; + /*insert(pos, const T&) is to insert before pos*/ + iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i)); + + } else { /* w(i-1) ^ tau == w(i-2) ^ w(i-1) */ + /*must be w(i-2) ~> w(i-1) */ + + bool d = true; + //need to handle the case when w_i_p_1 is null + Line l3 = get_sharing_line(*w_i_p_1, tau); + if ( w_i_p_1 != w_end ) + d = w_i_p_1->second != l3; + if ( d ) { /* w(i+1) ^ tau != w(i+1) ^ w(i+2) */ + /*extension: w(i) |- tau -> w(i+1) */ + w_i->second = tau_i; + iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l3)); + } else { /* w(i+1) ^ tau == w(i+1) ^ w(i+2) */ + /*must be w(1+1) ~> w(i+2) */ + Line l5 = get_sharing_line(*w_i_m_1, *w_i_p_1); + if ( l5 != w_i_p_1->second ) { /* w(i-1) ^ w(i+1) != w(i+1) ^ w(i+2) */ + /*extension: w(i-2) -> tau |- w(i) |- w(i-1) -> w(i+1) */ + w_i_m_2->second = get_sharing_line(*w_i_m_2, tau); + iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i)); + w_i->second = w_i_m_1->second; + w_i_m_1->second = l5; + iter_d[w_i_m_1->first] = hlist->insert(w_i_p_1, *w_i_m_1); + hlist->erase(w_i_m_1); + } else { + /*mesh is tetrahedral*/ + // dont know what that means. + ; + } + } + + } + } else { + /*Case 2: + + w(i-1) |- w(i) ~> w(1+1) + */ + + if ( w_i->second.second == tau_i.first + || w_i->second.second == tau_i.second ) { /*w(i) ^ w(i+1) < w(i) ^ tau*/ + /*extension: w(i) |- tau -> w(i+1) */ + w_i->second = tau_i; + Line l1 = get_sharing_line(*w_i_p_1, tau); + iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l1)); + } else { /*w(i) ^ w(i+1) !< w(i) ^ tau*/ + Line l1 = get_sharing_line(*w_i_m_1, tau); + bool c = true; + iter w_i_m_2 = w_i_m_1; + --w_i_m_2; + if ( w_i_m_2 != w_end ) + c = l1 != w_i_m_2->second; + if (c) { /*w(i-1) ^ tau != w(i-2) ^ w(i-1)*/ + /*extension: w(i-1) -> tau |- w(i)*/ + w_i_m_1->second = l1; + iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i)); + } else { /*w(i-1) ^ tau == w(i-2) ^ w(i-1)*/ + /*must be w(i-2)~>w(i-1)*/ + /*extension: w(i-2) -> tau |- w(i) |- w(i-1) -> w(i+1)*/ + w_i_m_2->second = get_sharing_line(*w_i_m_2, tau); + iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i)); + w_i->second = w_i_m_1->second; + w_i_m_1->second = get_sharing_line(*w_i_m_1, *w_i_p_1); + iter_d[w_i_m_1->first] = hlist->insert(w_i_p_1, *w_i_m_1); + hlist->erase(w_i_m_1); + } + + } + + } + + } else { + + if ( b ) { + /*Case 3: + + w(i-1) ~> w(i) |- w(i+1) + */ + bool c = false; + if ( w_i_m_1 != w_end ) + c = ( w_i_m_1->second.second == tau_i.first) + || ( w_i_m_1->second.second == tau_i.second); + + if ( c ) { /*w(i-1) ^ w(i) < w(i) ^ tau*/ + /* extension: w(i-1) -> tau |- w(i) */ + if ( w_i_m_1 != w_end ) + w_i_m_1->second = get_sharing_line(*w_i_m_1, tau); + iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i)); + } else { + bool d = true; + Line l1; + l1.first = SAW_SENTINAL; + l1.second = SAW_SENTINAL; + if ( w_i_p_1 != w_end ) { + l1 = get_sharing_line(*w_i_p_1, tau); + d = l1 != w_i_p_1->second; + } + if (d) { /*w(i+1) ^ tau != w(i+1) ^ w(i+2)*/ + /*extension: w(i) |- tau -> w(i+1) */ + w_i->second = tau_i; + iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l1)); + } else { + /*must be w(i+1) ~> w(i+2)*/ + /*extension: w(i-1) -> w(i+1) |- w(i) |- tau -> w(i+2) */ + iter w_i_p_2 = w_i_p_1; + ++w_i_p_2; + + w_i_p_1->second = w_i->second; + iter_d[i] = hlist->insert(w_i_p_2, make_pair(i, tau_i)); + hlist->erase(w_i); + Line l2 = get_sharing_line(*w_i_p_2, tau); + iter_d[tau] = hlist->insert(w_i_p_2, make_pair(tau, l2)); + } + } + + } else { + /*Case 4: + + w(i-1) ~> w(i) ~> w(i+1) + + */ + bool c = false; + if ( w_i_m_1 != w_end ) { + c = (w_i_m_1->second.second == tau_i.first) + || (w_i_m_1->second.second == tau_i.second); + } + if ( c ) { /*w(i-1) ^ w(i) < w(i) ^ tau */ + /*extension: w(i-1) -> tau |- w(i) */ + if ( w_i_m_1 != w_end ) + w_i_m_1->second = get_sharing_line(*w_i_m_1, tau); + iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i)); + } else { + /*extension: w(i) |- tau -> w(i+1) */ + w_i->second = tau_i; + Line l1; + l1.first = SAW_SENTINAL; + l1.second = SAW_SENTINAL; + if ( w_i_p_1 != w_end ) + l1 = get_sharing_line(*w_i_p_1, tau); + iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l1)); + } + } + + } + + return true; + } + + protected: + TriangleDecorator td; /*a decorator for vertex*/ + HList hlist; + /*This must be a handle of list to record the SAW + The element type of the list is pair + */ + + IteratorD iter_d; + /*Problem statement: Need a fast access to w for triangle i. + *Possible solution: mantain an array to record. + iter_d[i] will return an iterator + which points to w(i), where i is a vertex + representing triangle i. + */ + }; + + template + inline + SAW_visitor + visit_SAW(Triangle t, HList hl, Iterator i) { + return SAW_visitor(t, hl, i); + } + + template + inline + SAW_visitor< random_access_iterator_property_map, + HList, random_access_iterator_property_map > + visit_SAW_ptr(Tri* t, HList hl, Iter* i) { + typedef random_access_iterator_property_map TriD; + typedef random_access_iterator_property_map IterD; + return SAW_visitor(t, hl, i); + } + + // should also have combo's of pointers, and also const :( + +} + +#endif /*BOOST_SAW_H*/ diff --git a/win32/include/boost/graph/detail/set_adaptor.hpp b/win32/include/boost/graph/detail/set_adaptor.hpp new file mode 100755 index 000000000..403593d26 --- /dev/null +++ b/win32/include/boost/graph/detail/set_adaptor.hpp @@ -0,0 +1,117 @@ +// (C) Copyright Jeremy Siek 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_SET_ADAPTOR_HPP +#define BOOST_SET_ADAPTOR_HPP + +#include + +namespace boost { + + template + bool set_contains(const std::set& s, const T& x) { + return s.find(x) != s.end(); + } + + template + bool set_equal(const std::set& x, + const std::set& y) + { + return x == y; + } + + // Not the same as lexicographical_compare_3way applied to std::set. + // this is equivalent semantically to bitset::operator<() + template + int set_lex_order(const std::set& x, + const std::set& y) + { + typename std::set::iterator + xi = x.begin(), yi = y.begin(), xend = x.end(), yend = y.end(); + for (; xi != xend && yi != yend; ++xi, ++yi) { + if (*xi < *yi) + return 1; + else if (*yi < *xi) + return -1; + } + if (xi == xend) + return (yi == yend) ? 0 : -1; + else + return 1; + } + + template + void set_clear(std::set& x) { + x.clear(); + } + + template + bool set_empty(const std::set& x) { + return x.empty(); + } + + template + void set_insert(std::set& x, const T& a) { + x.insert(a); + } + + template + void set_remove(std::set& x, const T& a) { + x.erase(a); + } + + template + void set_intersect(const std::set& x, + const std::set& y, + std::set& z) + { + z.clear(); + std::set_intersection(x.begin(), x.end(), + y.begin(), y.end(), + std::inserter(z)); + } + + template + void set_union(const std::set& x, + const std::set& y, + std::set& z) + { + z.clear(); + std::set_union(x.begin(), x.end(), + y.begin(), y.end(), + std::inserter(z)); + } + + template + void set_difference(const std::set& x, + const std::set& y, + std::set& z) + { + z.clear(); + std::set_difference(x.begin(), x.end(), + y.begin(), y.end(), + std::inserter(z, z.begin())); + } + + template + bool set_subset(const std::set& x, + const std::set& y) + { + return std::includes(x.begin(), x.end(), y.begin(), y.end()); + } + + // Shit, can't implement this without knowing the size of the + // universe. + template + void set_compliment(const std::set& x, + std::set& z) + { + z.clear(); + + } + +} // namespace boost + +#endif // BOOST_SET_ADAPTOR_HPP diff --git a/win32/include/boost/graph/detail/shadow_iterator.hpp b/win32/include/boost/graph/detail/shadow_iterator.hpp new file mode 100755 index 000000000..4ad2da3da --- /dev/null +++ b/win32/include/boost/graph/detail/shadow_iterator.hpp @@ -0,0 +1,139 @@ +// (C) Copyright Jeremy Siek 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_SHADOW_ITERATOR_HPP +#define BOOST_SHADOW_ITERATOR_HPP + +#include +#include + +namespace boost { + + namespace detail { + + template + class shadow_proxy + : boost::operators< shadow_proxy > + { + typedef shadow_proxy self; + public: + inline shadow_proxy(A aa, B bb) : a(aa), b(bb) { } + inline shadow_proxy(const self& x) : a(x.a), b(x.b) { } + template + inline shadow_proxy(Self x) : a(x.a), b(x.b) { } + inline self& operator=(const self& x) { a = x.a; b = x.b; return *this; } + inline self& operator++() { ++a; return *this; } + inline self& operator--() { --a; return *this; } + inline self& operator+=(const self& x) { a += x.a; return *this; } + inline self& operator-=(const self& x) { a -= x.a; return *this; } + inline self& operator*=(const self& x) { a *= x.a; return *this; } + inline self& operator/=(const self& x) { a /= x.a; return *this; } + inline self& operator%=(const self& x) { return *this; } // JGS + inline self& operator&=(const self& x) { return *this; } // JGS + inline self& operator|=(const self& x) { return *this; } // JGS + inline self& operator^=(const self& x) { return *this; } // JGS + inline friend D operator-(const self& x, const self& y) { + return x.a - y.a; + } + inline bool operator==(const self& x) const { return a == x.a; } + inline bool operator<(const self& x) const { return a < x.a; } + // protected: + A a; + B b; + }; + + struct shadow_iterator_policies + { + template + void initialize(const iter_pair&) { } + + template + typename Iter::reference dereference(const Iter& i) const { + typedef typename Iter::reference R; + return R(*i.base().first, *i.base().second); + } + template + bool equal(const Iter& p1, const Iter& p2) const { + return p1.base().first == p2.base().first; + } + template + void increment(Iter& i) { ++i.base().first; ++i.base().second; } + + template + void decrement(Iter& i) { --i.base().first; --i.base().second; } + + template + bool less(const Iter& x, const Iter& y) const { + return x.base().first < y.base().first; + } + template + typename Iter::difference_type + distance(const Iter& x, const Iter& y) const { + return y.base().first - x.base().first; + } + template + void advance(Iter& p, D n) { p.base().first += n; p.base().second += n; } + }; + + } // namespace detail + + template + struct shadow_iterator_generator { + + // To use the iterator_adaptor we can't derive from + // random_access_iterator because we don't have a real reference. + // However, we want the STL algorithms to treat the shadow + // iterator like a random access iterator. + struct shadow_iterator_tag : public std::input_iterator_tag { + operator std::random_access_iterator_tag() { + return std::random_access_iterator_tag(); + }; + }; + typedef typename std::iterator_traits::value_type Aval; + typedef typename std::iterator_traits::value_type Bval; + typedef typename std::iterator_traits::reference Aref; + typedef typename std::iterator_traits::reference Bref; + typedef typename std::iterator_traits::difference_type D; + typedef detail::shadow_proxy V; + typedef detail::shadow_proxy R; + typedef iterator_adaptor< std::pair, + detail::shadow_iterator_policies, + V, R, V*, shadow_iterator_tag, + D> type; + }; + + // short cut for creating a shadow iterator + template + inline typename shadow_iterator_generator::type + make_shadow_iter(IterA a, IterB b) { + typedef typename shadow_iterator_generator::type Iter; + return Iter(std::make_pair(a,b)); + } + + template + struct shadow_cmp { + inline shadow_cmp(const Cmp& c) : cmp(c) { } + template + inline bool operator()(const ShadowProxy1& x, const ShadowProxy2& y) const + { + return cmp(x.a, y.a); + } + Cmp cmp; + }; + +} // namespace boost + +namespace std { + template + void swap(boost::detail::shadow_proxy x, + boost::detail::shadow_proxy y) + { + std::swap(x.a, y.a); + std::swap(x.b, y.b); + } +} + +#endif // BOOST_SHADOW_ITERATOR_HPP diff --git a/win32/include/boost/graph/detail/sparse_ordering.hpp b/win32/include/boost/graph/detail/sparse_ordering.hpp new file mode 100755 index 000000000..a9c99bc29 --- /dev/null +++ b/win32/include/boost/graph/detail/sparse_ordering.hpp @@ -0,0 +1,198 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2004, 2005 Trustees of Indiana University +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, +// Doug Gregor, D. Kevin McGrath +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//=======================================================================// +#ifndef BOOST_GRAPH_DETAIL_SPARSE_ORDERING_HPP +#define BOOST_GRAPH_DETAIL_SPARSE_ORDERING_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + namespace sparse { + + // rcm_queue + // + // This is a custom queue type used in the + // *_ordering algorithms. + // In addition to the normal queue operations, the + // rcm_queue provides: + // + // int eccentricity() const; + // value_type spouse() const; + // + + // yes, it's a bad name...but it works, so use it + template < class Vertex, class DegreeMap, + class Container = std::deque > + class rcm_queue : public std::queue { + typedef std::queue base; + public: + typedef typename base::value_type value_type; + typedef typename base::size_type size_type; + + /* SGI queue has not had a contructor queue(const Container&) */ + inline rcm_queue(DegreeMap deg) + : _size(0), Qsize(1), eccen(-1), degree(deg) { } + + inline void pop() { + if ( !_size ) + Qsize = base::size(); + + base::pop(); + if ( _size == Qsize-1 ) { + _size = 0; + ++eccen; + } else + ++_size; + + } + + inline value_type& front() { + value_type& u = base::front(); + if ( _size == 0 ) + w = u; + else if (get(degree,u) < get(degree,w) ) + w = u; + return u; + } + + inline const value_type& front() const { + const value_type& u = base::front(); + if ( _size == 0 ) + w = u; + else if (get(degree,u) < get(degree,w) ) + w = u; + return u; + } + + inline value_type& top() { return front(); } + inline const value_type& top() const { return front(); } + + inline size_type size() const { return base::size(); } + + inline size_type eccentricity() const { return eccen; } + inline value_type spouse() const { return w; } + + protected: + size_type _size; + size_type Qsize; + int eccen; + mutable value_type w; + DegreeMap degree; + }; + + + template > + class sparse_ordering_queue : public boost::queue{ + public: + typedef typename Sequence::iterator iterator; + typedef typename Sequence::reverse_iterator reverse_iterator; + typedef queue base; + typedef typename Sequence::size_type size_type; + + inline iterator begin() { return this->c.begin(); } + inline reverse_iterator rbegin() { return this->c.rbegin(); } + inline iterator end() { return this->c.end(); } + inline reverse_iterator rend() { return this->c.rend(); } + inline Tp &operator[](int n) { return this->c[n]; } + inline size_type size() {return this->c.size(); } + protected: + //nothing + }; + + } // namespace sparse + + // Compute Pseudo peripheral + // + // To compute an approximated peripheral for a given vertex. + // Used in king_ordering algorithm. + // + template + Vertex + pseudo_peripheral_pair(Graph& G, const Vertex& u, int& ecc, + ColorMap color, DegreeMap degree) + { + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + + sparse::rcm_queue Q(degree); + + typename boost::graph_traits::vertex_iterator ui, ui_end; + for (tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) + if (get(color, *ui) != Color::red()) put(color, *ui, Color::white()); + breadth_first_visit(G, u, buffer(Q).color_map(color)); + + ecc = Q.eccentricity(); + return Q.spouse(); + } + + // Find a good starting node + // + // This is to find a good starting node for the + // king_ordering algorithm. "good" is in the sense + // of the ordering generated by RCM. + // + template + Vertex find_starting_node(Graph& G, Vertex r, Color color, Degree degree) + { + Vertex x, y; + int eccen_r, eccen_x; + + x = pseudo_peripheral_pair(G, r, eccen_r, color, degree); + y = pseudo_peripheral_pair(G, x, eccen_x, color, degree); + + while (eccen_x > eccen_r) { + r = x; + eccen_r = eccen_x; + x = y; + y = pseudo_peripheral_pair(G, x, eccen_x, color, degree); + } + return x; + } + +template +class out_degree_property_map + : public put_get_helper::degree_size_type, + out_degree_property_map > +{ +public: + typedef typename graph_traits::vertex_descriptor key_type; + typedef typename graph_traits::degree_size_type value_type; + typedef value_type reference; + typedef readable_property_map_tag category; + out_degree_property_map(const Graph& g) : m_g(g) { } + value_type operator[](const key_type& v) const { + return out_degree(v, m_g); + } +private: + const Graph& m_g; +}; +template +inline out_degree_property_map +make_out_degree_map(const Graph& g) { + return out_degree_property_map(g); +} + +} // namespace boost + + +#endif // BOOST_GRAPH_KING_HPP diff --git a/win32/include/boost/graph/dijkstra_shortest_paths.hpp b/win32/include/boost/graph/dijkstra_shortest_paths.hpp new file mode 100755 index 000000000..6509c0cd4 --- /dev/null +++ b/win32/include/boost/graph/dijkstra_shortest_paths.hpp @@ -0,0 +1,347 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_DIJKSTRA_HPP +#define BOOST_GRAPH_DIJKSTRA_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_GRAPH_DIJKSTRA_TESTING +# include +#endif // BOOST_GRAPH_DIJKSTRA_TESTING + +namespace boost { + +#ifdef BOOST_GRAPH_DIJKSTRA_TESTING + static bool dijkstra_relaxed_heap = true; +#endif + + template + struct DijkstraVisitorConcept { + void constraints() { + function_requires< CopyConstructibleConcept >(); + vis.initialize_vertex(u, g); + vis.discover_vertex(u, g); + vis.examine_vertex(u, g); + vis.examine_edge(e, g); + vis.edge_relaxed(e, g); + vis.edge_not_relaxed(e, g); + vis.finish_vertex(u, g); + } + Visitor vis; + Graph g; + typename graph_traits::vertex_descriptor u; + typename graph_traits::edge_descriptor e; + }; + + template + class dijkstra_visitor : public bfs_visitor { + public: + dijkstra_visitor() { } + dijkstra_visitor(Visitors vis) + : bfs_visitor(vis) { } + + template + void edge_relaxed(Edge e, Graph& g) { + invoke_visitors(this->m_vis, e, g, on_edge_relaxed()); + } + template + void edge_not_relaxed(Edge e, Graph& g) { + invoke_visitors(this->m_vis, e, g, on_edge_not_relaxed()); + } + private: + template + void tree_edge(Edge u, Graph& g) { } + }; + template + dijkstra_visitor + make_dijkstra_visitor(Visitors vis) { + return dijkstra_visitor(vis); + } + typedef dijkstra_visitor<> default_dijkstra_visitor; + + namespace detail { + + template + struct dijkstra_bfs_visitor + { + typedef typename property_traits::value_type D; + + dijkstra_bfs_visitor(UniformCostVisitor vis, UpdatableQueue& Q, + WeightMap w, PredecessorMap p, DistanceMap d, + BinaryFunction combine, BinaryPredicate compare, + D zero) + : m_vis(vis), m_Q(Q), m_weight(w), m_predecessor(p), m_distance(d), + m_combine(combine), m_compare(compare), m_zero(zero) { } + + template + void tree_edge(Edge e, Graph& g) { + m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); + if (m_decreased) + m_vis.edge_relaxed(e, g); + else + m_vis.edge_not_relaxed(e, g); + } + template + void gray_target(Edge e, Graph& g) { + m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); + if (m_decreased) { + m_Q.update(target(e, g)); + m_vis.edge_relaxed(e, g); + } else + m_vis.edge_not_relaxed(e, g); + } + + template + void initialize_vertex(Vertex /*u*/, Graph& /*g*/) { } + template + void non_tree_edge(Edge, Graph&) { } + template + void discover_vertex(Vertex u, Graph& g) { m_vis.discover_vertex(u, g); } + template + void examine_vertex(Vertex u, Graph& g) { m_vis.examine_vertex(u, g); } + template + void examine_edge(Edge e, Graph& g) { + if (m_compare(get(m_weight, e), m_zero)) + throw negative_edge(); + m_vis.examine_edge(e, g); + } + template + void black_target(Edge, Graph&) { } + template + void finish_vertex(Vertex u, Graph& g) { m_vis.finish_vertex(u, g); } + + UniformCostVisitor m_vis; + UpdatableQueue& m_Q; + WeightMap m_weight; + PredecessorMap m_predecessor; + DistanceMap m_distance; + BinaryFunction m_combine; + BinaryPredicate m_compare; + bool m_decreased; + D m_zero; + }; + + } // namespace detail + + // Call breadth first search with default color map. + template + inline void + dijkstra_shortest_paths_no_init + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistZero zero, + DijkstraVisitor vis) + { + std::vector color(num_vertices(g)); + default_color_type c = white_color; + dijkstra_shortest_paths_no_init( g, s, predecessor, distance, weight, + index_map, compare, combine, zero, vis, + make_iterator_property_map(&color[0], index_map, c)); + } + + // Call breadth first search + template + inline void + dijkstra_shortest_paths_no_init + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistZero zero, + DijkstraVisitor vis, ColorMap color) + { + typedef indirect_cmp IndirectCmp; + IndirectCmp icmp(distance, compare); + + typedef typename graph_traits::vertex_descriptor Vertex; + +#ifdef BOOST_GRAPH_DIJKSTRA_TESTING + if (!dijkstra_relaxed_heap) { + typedef mutable_queue, IndirectCmp, IndexMap> + MutableQueue; + + MutableQueue Q(num_vertices(g), icmp, index_map); + + detail::dijkstra_bfs_visitor + bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero); + + breadth_first_visit(g, s, Q, bfs_vis, color); + return; + } +#endif // BOOST_GRAPH_DIJKSTRA_TESTING + + typedef relaxed_heap MutableQueue; + + MutableQueue Q(num_vertices(g), icmp, index_map); + + detail::dijkstra_bfs_visitor + bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero); + + breadth_first_visit(g, s, Q, bfs_vis, color); + } + + // Initialize distances and call breadth first search with default color map + template + inline void + dijkstra_shortest_paths + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistInf inf, DistZero zero, + DijkstraVisitor vis) + { + std::vector color(num_vertices(g)); + default_color_type c = white_color; + dijkstra_shortest_paths(g, s, predecessor, distance, weight, index_map, + compare, combine, inf, zero, vis, + make_iterator_property_map(&color[0], index_map, + c)); + } + + // Initialize distances and call breadth first search + template + inline void + dijkstra_shortest_paths + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistInf inf, DistZero zero, + DijkstraVisitor vis, ColorMap color) + { + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + typename graph_traits::vertex_iterator ui, ui_end; + for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) { + vis.initialize_vertex(*ui, g); + put(distance, *ui, inf); + put(predecessor, *ui, *ui); + put(color, *ui, Color::white()); + } + put(distance, s, zero); + + dijkstra_shortest_paths_no_init(g, s, predecessor, distance, weight, + index_map, compare, combine, zero, vis, color); + } + + namespace detail { + + // Handle defaults for PredecessorMap and + // Distance Compare, Combine, Inf and Zero + template + inline void + dijkstra_dispatch2 + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + DistanceMap distance, WeightMap weight, IndexMap index_map, + const Params& params, ColorMap color) + { + // Default for predecessor map + dummy_property_map p_map; + + typedef typename property_traits::value_type D; + dijkstra_shortest_paths + (g, s, + choose_param(get_param(params, vertex_predecessor), p_map), + distance, weight, index_map, + choose_param(get_param(params, distance_compare_t()), + std::less()), + choose_param(get_param(params, distance_combine_t()), + closed_plus()), + choose_param(get_param(params, distance_inf_t()), + (std::numeric_limits::max)()), + choose_param(get_param(params, distance_zero_t()), + D()), + choose_param(get_param(params, graph_visitor), + make_dijkstra_visitor(null_visitor())), + color); + } + + template + inline void + dijkstra_dispatch1 + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + DistanceMap distance, WeightMap weight, IndexMap index_map, + const Params& params, ColorMap color) + { + // Default for distance map + typedef typename property_traits::value_type D; + typename std::vector::size_type + n = is_default_param(distance) ? num_vertices(g) : 1; + std::vector distance_map(n); + + // Default for color map + typename std::vector::size_type + m = is_default_param(color) ? num_vertices(g) : 1; + std::vector color_map(m); + + detail::dijkstra_dispatch2 + (g, s, choose_param(distance, make_iterator_property_map + (distance_map.begin(), index_map, + distance_map[0])), + weight, index_map, params, + choose_param(color, make_iterator_property_map + (color_map.begin(), index_map, + color_map[0]))); + } + } // namespace detail + + // Named Parameter Variant + template + inline void + dijkstra_shortest_paths + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + const bgl_named_params& params) + { + // Default for edge weight and vertex index map is to ask for them + // from the graph. Default for the visitor is null_visitor. + detail::dijkstra_dispatch1 + (g, s, + get_param(params, vertex_distance), + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index), + params, + get_param(params, vertex_color)); + } + +} // namespace boost + +#endif // BOOST_GRAPH_DIJKSTRA_HPP diff --git a/win32/include/boost/graph/dominator_tree.hpp b/win32/include/boost/graph/dominator_tree.hpp new file mode 100755 index 000000000..2c4277f99 --- /dev/null +++ b/win32/include/boost/graph/dominator_tree.hpp @@ -0,0 +1,488 @@ +//======================================================================= +// Copyright (C) 2005 Jong Soo Park +// +// 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) +//======================================================================= +// Dominator tree computation +#ifndef BOOST_GRAPH_DOMINATOR_HPP +#define BOOST_GRAPH_DOMINATOR_HPP + +#include +#include +#include +#include + +namespace boost { + namespace detail { + /** + * An extended time_stamper which also records vertices for each dfs number + */ + template + class time_stamper_with_vertex_vector + : public base_visitor< + time_stamper_with_vertex_vector > + { + public : + typedef Tag event_filter; + time_stamper_with_vertex_vector(TimeMap timeMap, VertexVector& v, + TimeT& t) + : timeStamper_(timeMap, t), v_(v) { } + + template + void + operator()(const typename property_traits::key_type& v, + const Graph& g) + { + timeStamper_(v, g); + v_[timeStamper_.m_time] = v; + } + + private : + time_stamper timeStamper_; + VertexVector& v_; + }; + + /** + * A convenient way to create a time_stamper_with_vertex_vector + */ + template + time_stamper_with_vertex_vector + stamp_times_with_vertex_vector(TimeMap timeMap, VertexVector& v, TimeT& t, + Tag) + { + return time_stamper_with_vertex_vector(timeMap, v, t); + } + + template + class dominator_visitor + { + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::vertices_size_type VerticesSizeType; + + public : + /** + * @param g [in] the target graph of the dominator tree + * @param entry [in] the entry node of g + * @param domTreePredMap [out] the immediate dominator map + * (parent map in dominator tree) + */ + dominator_visitor(const Graph& g, const Vertex& entry, + DomTreePredMap domTreePredMap) + : semi_(num_vertices(g)), + ancestor_(num_vertices(g), graph_traits::null_vertex()), + samedom_(ancestor_), + best_(semi_), + semiMap_(make_iterator_property_map(semi_.begin(), + get(vertex_index, g))), + ancestorMap_(make_iterator_property_map(ancestor_.begin(), + get(vertex_index, g))), + bestMap_(make_iterator_property_map(best_.begin(), + get(vertex_index, g))), + buckets_(num_vertices(g)), + bucketMap_(make_iterator_property_map(buckets_.begin(), + get(vertex_index, g))), + entry_(entry), + domTreePredMap_(domTreePredMap), + samedomMap(make_iterator_property_map(samedom_.begin(), + get(vertex_index, g))) + { + } + + void + operator()(const Vertex& n, const TimeMap& dfnumMap, + const PredMap& parentMap, const Graph& g) + { + if (n == entry_) return; + + const VerticesSizeType numOfVertices = num_vertices(g); + const Vertex p(get(parentMap, n)); + Vertex s(p); + + // 1. Calculate the semidominator of n, + // based on the semidominator thm. + // * Semidominator thm. : To find the semidominator of a node n, + // consider all predecessors v of n in the CFG (Control Flow Graph). + // - If v is a proper ancestor of n in the spanning tree + // (so dfnum(v) < dfnum(n)), then v is a candidate for semi(n) + // - If v is a non-ancestor of n (so dfnum(v) > dfnum(n)) + // then for each u that is an ancestor of v (or u = v), + // Let semi(u) be a candidate for semi(n) + // of all these candidates, the one with lowest dfnum is + // the semidominator of n. + + // For each predecessor of n + typename graph_traits::in_edge_iterator inItr, inEnd; + for (tie(inItr, inEnd) = in_edges(n, g); inItr != inEnd; ++inItr) + { + const Vertex v = source(*inItr, g); + // To deal with unreachable nodes + if (get(dfnumMap, v) < 0 || get(dfnumMap, v) >= numOfVertices) + continue; + + Vertex s2; + if (get(dfnumMap, v) <= get(dfnumMap, n)) + s2 = v; + else + s2 = get(semiMap_, ancestor_with_lowest_semi_(v, dfnumMap)); + + if (get(dfnumMap, s2) < get(dfnumMap, s)) + s = s2; + } + put(semiMap_, n, s); + + // 2. Calculation of n's dominator is deferred until + // the path from s to n has been linked into the forest + get(bucketMap_, s).push_back(n); + get(ancestorMap_, n) = p; + get(bestMap_, n) = n; + + // 3. Now that the path from p to v has been linked into + // the spanning forest, these lines calculate the dominator of v, + // based on the dominator thm., or else defer the calculation + // until y's dominator is known + // * Dominator thm. : On the spanning-tree path below semi(n) and + // above or including n, let y be the node + // with the smallest-numbered semidominator. Then, + // + // idom(n) = semi(n) if semi(y)=semi(n) or + // idom(y) if semi(y) != semi(n) + typename std::deque::iterator buckItr; + for (buckItr = get(bucketMap_, p).begin(); + buckItr != get(bucketMap_, p).end(); + ++buckItr) + { + const Vertex v(*buckItr); + const Vertex y(ancestor_with_lowest_semi_(v, dfnumMap)); + if (get(semiMap_, y) == get(semiMap_, v)) + put(domTreePredMap_, v, p); + else + put(samedomMap, v, y); + } + + get(bucketMap_, p).clear(); + } + + protected : + + /** + * Evaluate function in Tarjan's path compression + */ + const Vertex + ancestor_with_lowest_semi_(const Vertex& v, const TimeMap& dfnumMap) + { + const Vertex a(get(ancestorMap_, v)); + + if (get(ancestorMap_, a) != graph_traits::null_vertex()) + { + const Vertex b(ancestor_with_lowest_semi_(a, dfnumMap)); + + put(ancestorMap_, v, get(ancestorMap_, a)); + + if (get(dfnumMap, get(semiMap_, b)) < + get(dfnumMap, get(semiMap_, get(bestMap_, v)))) + put(bestMap_, v, b); + } + + return get(bestMap_, v); + } + + std::vector semi_, ancestor_, samedom_, best_; + PredMap semiMap_, ancestorMap_, bestMap_; + std::vector< std::deque > buckets_; + + iterator_property_map >::iterator, + IndexMap> bucketMap_; + + const Vertex& entry_; + DomTreePredMap domTreePredMap_; + + public : + + PredMap samedomMap; + }; + + } // namespace detail + + /** + * @brief Build dominator tree using Lengauer-Tarjan algorithm. + * It takes O((V+E)log(V+E)) time. + * + * @pre dfnumMap, parentMap and verticesByDFNum have dfs results corresponding + * indexMap. + * If dfs has already run before, + * this function would be good for saving computations. + * @pre Unreachable nodes must be masked as + * graph_traits::null_vertex in parentMap. + * @pre Unreachable nodes must be masked as + * (std::numeric_limits::max)() in dfnumMap. + * + * @param domTreePredMap [out] : immediate dominator map (parent map + * in dom. tree) + * + * @note reference Appel. p. 452~453. algorithm 19.9, 19.10. + * + * @todo : Optimization in Finding Dominators in Practice, Loukas Georgiadis + */ + template + void + lengauer_tarjan_dominator_tree_without_dfs + (const Graph& g, + const typename graph_traits::vertex_descriptor& entry, + const IndexMap& indexMap, + TimeMap dfnumMap, PredMap parentMap, VertexVector& verticesByDFNum, + DomTreePredMap domTreePredMap) + { + // Typedefs and concept check + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::vertices_size_type VerticesSizeType; + + function_requires< BidirectionalGraphConcept >(); + + const VerticesSizeType numOfVertices = num_vertices(g); + if (numOfVertices == 0) return; + + // 1. Visit each vertex in reverse post order and calculate sdom. + detail::dominator_visitor + visitor(g, entry, domTreePredMap); + + VerticesSizeType i; + for (i = 0; i < numOfVertices; ++i) + { + const Vertex u(verticesByDFNum[numOfVertices - 1 - i]); + if (u != graph_traits::null_vertex()) + visitor(u, dfnumMap, parentMap, g); + } + + // 2. Now all the deferred dominator calculations, + // based on the second clause of the dominator thm., are performed + for (i = 0; i < numOfVertices; ++i) + { + const Vertex n(verticesByDFNum[i]); + + if (n == entry || n == graph_traits::null_vertex()) + continue; + + Vertex u = get(visitor.samedomMap, n); + if (u != graph_traits::null_vertex()) + { + put(domTreePredMap, n, get(domTreePredMap, u)); + } + } + } + + /** + * Unlike lengauer_tarjan_dominator_tree_without_dfs, + * dfs is run in this function and + * the result is written to dfnumMap, parentMap, vertices. + * + * If the result of dfs required after this algorithm, + * this function can eliminate the need of rerunning dfs. + */ + template + void + lengauer_tarjan_dominator_tree + (const Graph& g, + const typename graph_traits::vertex_descriptor& entry, + const IndexMap& indexMap, + TimeMap dfnumMap, PredMap parentMap, VertexVector& verticesByDFNum, + DomTreePredMap domTreePredMap) + { + // Typedefs and concept check + typedef typename graph_traits::vertices_size_type VerticesSizeType; + + function_requires< BidirectionalGraphConcept >(); + + // 1. Depth first visit + const VerticesSizeType numOfVertices = num_vertices(g); + if (numOfVertices == 0) return; + + VerticesSizeType time = + (std::numeric_limits::max)(); + std::vector + colors(numOfVertices, color_traits::white()); + depth_first_visit + (g, entry, + make_dfs_visitor + (make_pair(record_predecessors(parentMap, on_tree_edge()), + detail::stamp_times_with_vertex_vector + (dfnumMap, verticesByDFNum, time, on_discover_vertex()))), + make_iterator_property_map(colors.begin(), indexMap)); + + // 2. Run main algorithm. + lengauer_tarjan_dominator_tree_without_dfs(g, entry, indexMap, dfnumMap, + parentMap, verticesByDFNum, + domTreePredMap); + } + + /** + * Use vertex_index as IndexMap and make dfnumMap, parentMap, verticesByDFNum + * internally. + * If we don't need the result of dfs (dfnumMap, parentMap, verticesByDFNum), + * this function would be more convenient one. + */ + template + void + lengauer_tarjan_dominator_tree + (const Graph& g, + const typename graph_traits::vertex_descriptor& entry, + DomTreePredMap domTreePredMap) + { + // typedefs + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::vertices_size_type VerticesSizeType; + typedef typename property_map::const_type IndexMap; + typedef + iterator_property_map::iterator, + IndexMap> TimeMap; + typedef + iterator_property_map::iterator, IndexMap> + PredMap; + + // Make property maps + const VerticesSizeType numOfVertices = num_vertices(g); + if (numOfVertices == 0) return; + + const IndexMap indexMap = get(vertex_index, g); + + std::vector dfnum(numOfVertices, 0); + TimeMap dfnumMap(make_iterator_property_map(dfnum.begin(), indexMap)); + + std::vector parent(numOfVertices, + graph_traits::null_vertex()); + PredMap parentMap(make_iterator_property_map(parent.begin(), indexMap)); + + std::vector verticesByDFNum(parent); + + // Run main algorithm + lengauer_tarjan_dominator_tree(g, entry, + indexMap, dfnumMap, parentMap, + verticesByDFNum, domTreePredMap); + } + + /** + * Muchnick. p. 182, 184 + * + * using iterative bit vector analysis + */ + template + void + iterative_bit_vector_dominator_tree + (const Graph& g, + const typename graph_traits::vertex_descriptor& entry, + const IndexMap& indexMap, + DomTreePredMap domTreePredMap) + { + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::vertex_iterator vertexItr; + typedef typename graph_traits::vertices_size_type VerticesSizeType; + typedef + iterator_property_map >::iterator, + IndexMap> vertexSetMap; + + function_requires >(); + + // 1. Finding dominator + // 1.1. Initialize + const VerticesSizeType numOfVertices = num_vertices(g); + if (numOfVertices == 0) return; + + vertexItr vi, viend; + tie(vi, viend) = vertices(g); + const std::set N(vi, viend); + + bool change = true; + + std::vector< std::set > dom(numOfVertices, N); + vertexSetMap domMap(make_iterator_property_map(dom.begin(), indexMap)); + get(domMap, entry).clear(); + get(domMap, entry).insert(entry); + + while (change) + { + change = false; + for (tie(vi, viend) = vertices(g); vi != viend; ++vi) + { + if (*vi == entry) continue; + + std::set T(N); + + typename graph_traits::in_edge_iterator inItr, inEnd; + for (tie(inItr, inEnd) = in_edges(*vi, g); inItr != inEnd; ++inItr) + { + const Vertex p = source(*inItr, g); + + std::set tempSet; + std::set_intersection(T.begin(), T.end(), + get(domMap, p).begin(), + get(domMap, p).end(), + std::inserter(tempSet, tempSet.begin())); + T.swap(tempSet); + } + + T.insert(*vi); + if (T != get(domMap, *vi)) + { + change = true; + get(domMap, *vi).swap(T); + } + } // end of for (tie(vi, viend) = vertices(g) + } // end of while(change) + + // 2. Build dominator tree + for (tie(vi, viend) = vertices(g); vi != viend; ++vi) + get(domMap, *vi).erase(*vi); + + Graph domTree(numOfVertices); + + for (tie(vi, viend) = vertices(g); vi != viend; ++vi) + { + if (*vi == entry) continue; + + // We have to iterate through copied dominator set + const std::set tempSet(get(domMap, *vi)); + typename std::set::const_iterator s; + for (s = tempSet.begin(); s != tempSet.end(); ++s) + { + typename std::set::iterator t; + for (t = get(domMap, *vi).begin(); t != get(domMap, *vi).end(); ) + { + typename std::set::iterator old_t = t; + ++t; // Done early because t may become invalid + if (*old_t == *s) continue; + if (get(domMap, *s).find(*old_t) != get(domMap, *s).end()) + get(domMap, *vi).erase(old_t); + } + } + } + + for (tie(vi, viend) = vertices(g); vi != viend; ++vi) + { + if (*vi != entry && get(domMap, *vi).size() == 1) + { + Vertex temp = *get(domMap, *vi).begin(); + put(domTreePredMap, *vi, temp); + } + } + } + + template + void + iterative_bit_vector_dominator_tree + (const Graph& g, + const typename graph_traits::vertex_descriptor& entry, + DomTreePredMap domTreePredMap) + { + typename property_map::const_type + indexMap = get(vertex_index, g); + + iterative_bit_vector_dominator_tree(g, entry, indexMap, domTreePredMap); + } +} // namespace boost + +#endif // BOOST_GRAPH_DOMINATOR_HPP diff --git a/win32/include/boost/graph/edge_connectivity.hpp b/win32/include/boost/graph/edge_connectivity.hpp new file mode 100755 index 000000000..730842c7e --- /dev/null +++ b/win32/include/boost/graph/edge_connectivity.hpp @@ -0,0 +1,181 @@ +//======================================================================= +// Copyright 2000 University of Notre Dame. +// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_EDGE_CONNECTIVITY +#define BOOST_EDGE_CONNECTIVITY + +// WARNING: not-yet fully tested! + +#include +#include +#include +#include +#include + +namespace boost { + + namespace detail { + + template + inline + std::pair::vertex_descriptor, + typename graph_traits::degree_size_type> + min_degree_vertex(Graph& g) + { + typedef graph_traits Traits; + typename Traits::vertex_descriptor p; + typedef typename Traits::degree_size_type size_type; + size_type delta = (std::numeric_limits::max)(); + + typename Traits::vertex_iterator i, iend; + for (tie(i, iend) = vertices(g); i != iend; ++i) + if (degree(*i, g) < delta) { + delta = degree(*i, g); + p = *i; + } + return std::make_pair(p, delta); + } + + template + void neighbors(const Graph& g, + typename graph_traits::vertex_descriptor u, + OutputIterator result) + { + typename graph_traits::adjacency_iterator ai, aend; + for (tie(ai, aend) = adjacent_vertices(u, g); ai != aend; ++ai) + *result++ = *ai; + } + + template + void neighbors(const Graph& g, + VertexIterator first, VertexIterator last, + OutputIterator result) + { + for (; first != last; ++first) + neighbors(g, *first, result); + } + + } // namespace detail + + // O(m n) + template + typename graph_traits::degree_size_type + edge_connectivity(VertexListGraph& g, OutputIterator disconnecting_set) + { + //------------------------------------------------------------------------- + // Type Definitions + typedef graph_traits Traits; + typedef typename Traits::vertex_iterator vertex_iterator; + typedef typename Traits::edge_iterator edge_iterator; + typedef typename Traits::out_edge_iterator out_edge_iterator; + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::degree_size_type degree_size_type; + typedef color_traits Color; + + typedef adjacency_list_traits Tr; + typedef typename Tr::edge_descriptor Tr_edge_desc; + typedef adjacency_list > > > + FlowGraph; + typedef typename graph_traits::edge_descriptor edge_descriptor; + + //------------------------------------------------------------------------- + // Variable Declarations + vertex_descriptor u, v, p, k; + edge_descriptor e1, e2; + bool inserted; + vertex_iterator vi, vi_end; + edge_iterator ei, ei_end; + degree_size_type delta, alpha_star, alpha_S_k; + std::set S, neighbor_S; + std::vector S_star, non_neighbor_S; + std::vector color(num_vertices(g)); + std::vector pred(num_vertices(g)); + + //------------------------------------------------------------------------- + // Create a network flow graph out of the undirected graph + FlowGraph flow_g(num_vertices(g)); + + typename property_map::type + cap = get(edge_capacity, flow_g); + typename property_map::type + res_cap = get(edge_residual_capacity, flow_g); + typename property_map::type + rev_edge = get(edge_reverse, flow_g); + + for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) { + u = source(*ei, g), v = target(*ei, g); + tie(e1, inserted) = add_edge(u, v, flow_g); + cap[e1] = 1; + tie(e2, inserted) = add_edge(v, u, flow_g); + cap[e2] = 1; // not sure about this + rev_edge[e1] = e2; + rev_edge[e2] = e1; + } + + //------------------------------------------------------------------------- + // The Algorithm + + tie(p, delta) = detail::min_degree_vertex(g); + S_star.push_back(p); + alpha_star = delta; + S.insert(p); + neighbor_S.insert(p); + detail::neighbors(g, S.begin(), S.end(), + std::inserter(neighbor_S, neighbor_S.begin())); + + std::set_difference(vertices(g).first, vertices(g).second, + neighbor_S.begin(), neighbor_S.end(), + std::back_inserter(non_neighbor_S)); + + while (!non_neighbor_S.empty()) { // at most n - 1 times + k = non_neighbor_S.front(); + + alpha_S_k = edmunds_karp_max_flow + (flow_g, p, k, cap, res_cap, rev_edge, &color[0], &pred[0]); + + if (alpha_S_k < alpha_star) { + alpha_star = alpha_S_k; + S_star.clear(); + for (tie(vi, vi_end) = vertices(flow_g); vi != vi_end; ++vi) + if (color[*vi] != Color::white()) + S_star.push_back(*vi); + } + S.insert(k); + neighbor_S.insert(k); + detail::neighbors(g, k, std::inserter(neighbor_S, neighbor_S.begin())); + non_neighbor_S.clear(); + std::set_difference(vertices(g).first, vertices(g).second, + neighbor_S.begin(), neighbor_S.end(), + std::back_inserter(non_neighbor_S)); + } + //------------------------------------------------------------------------- + // Compute edges of the cut [S*, ~S*] + std::vector in_S_star(num_vertices(g), false); + typename std::vector::iterator si; + for (si = S_star.begin(); si != S_star.end(); ++si) + in_S_star[*si] = true; + + degree_size_type c = 0; + for (si = S_star.begin(); si != S_star.end(); ++si) { + out_edge_iterator ei, ei_end; + for (tie(ei, ei_end) = out_edges(*si, g); ei != ei_end; ++ei) + if (!in_S_star[target(*ei, g)]) { + *disconnecting_set++ = *ei; + ++c; + } + } + return c; + } + +} // namespace boost + +#endif // BOOST_EDGE_CONNECTIVITY diff --git a/win32/include/boost/graph/edge_list.hpp b/win32/include/boost/graph/edge_list.hpp new file mode 100755 index 000000000..a9d6c6111 --- /dev/null +++ b/win32/include/boost/graph/edge_list.hpp @@ -0,0 +1,304 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +#ifndef BOOST_GRAPH_EDGE_LIST_HPP +#define BOOST_GRAPH_EDGE_LIST_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + // + // The edge_list class is an EdgeListGraph module that is constructed + // from a pair of iterators whose value type is a pair of vertex + // descriptors. + // + // For example: + // + // typedef std::pair E; + // list elist; + // ... + // typedef edge_list::iterator> Graph; + // Graph g(elist.begin(), elist.end()); + // + // If the iterators are random access, then Graph::edge_descriptor + // is of Integral type, otherwise it is a struct, though it is + // convertible to an Integral type. + // + + struct edge_list_tag { }; + + // The implementation class for edge_list. + template + class edge_list_impl + { + public: + typedef D edge_id; + typedef T Vpair; + typedef typename Vpair::first_type V; + typedef V vertex_descriptor; + typedef edge_list_tag graph_tag; + typedef void edge_property_type; + + struct edge_descriptor + { + edge_descriptor() { } + edge_descriptor(EdgeIter p, edge_id id) : _ptr(p), _id(id) { } + operator edge_id() { return _id; } + EdgeIter _ptr; + edge_id _id; + }; + typedef edge_descriptor E; + + struct edge_iterator + { + typedef edge_iterator self; + typedef E value_type; + typedef E& reference; + typedef E* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::input_iterator_tag iterator_category; + edge_iterator() { } + edge_iterator(EdgeIter iter) : _iter(iter), _i(0) { } + E operator*() { return E(_iter, _i); } + self& operator++() { ++_iter; ++_i; return *this; } + self operator++(int) { self t = *this; ++(*this); return t; } + bool operator==(const self& x) { return _iter == x._iter; } + bool operator!=(const self& x) { return _iter != x._iter; } + EdgeIter _iter; + edge_id _i; + }; + typedef void out_edge_iterator; + typedef void in_edge_iterator; + typedef void adjacency_iterator; + typedef void vertex_iterator; + }; + + template + std::pair::edge_iterator, + typename edge_list_impl::edge_iterator> + edges(const edge_list_impl& g_) { + const G& g = static_cast(g_); + typedef typename edge_list_impl::edge_iterator edge_iterator; + return std::make_pair(edge_iterator(g._first), edge_iterator(g._last)); + } + template + typename edge_list_impl::vertex_descriptor + source(typename edge_list_impl::edge_descriptor e, + const edge_list_impl&) { + return (*e._ptr).first; + } + template + typename edge_list_impl::vertex_descriptor + target(typename edge_list_impl::edge_descriptor e, + const edge_list_impl&) { + return (*e._ptr).second; + } + + template + class el_edge_property_map + : public put_get_helper >{ + public: + typedef E key_type; + typedef D value_type; + typedef D reference; + typedef readable_property_map_tag category; + + value_type operator[](key_type e) const { + return e._i; + } + }; + struct edge_list_edge_property_selector { + template + struct bind_ { + typedef el_edge_property_map type; + typedef type const_type; + }; + }; + template <> + struct edge_property_selector { + typedef edge_list_edge_property_selector type; + }; + + template + typename property_map< edge_list_impl, edge_index_t>::type + get(edge_index_t, const edge_list_impl&) { + typedef typename property_map< edge_list_impl, + edge_index_t>::type EdgeIndexMap; + return EdgeIndexMap(); + } + + template + inline D + get(edge_index_t, const edge_list_impl&, + typename edge_list_impl::edge_descriptor e) { + return e._i; + } + + // A specialized implementation for when the iterators are random access. + + struct edge_list_ra_tag { }; + + template + class edge_list_impl_ra + { + public: + typedef D edge_id; + typedef T Vpair; + typedef typename Vpair::first_type V; + typedef edge_list_ra_tag graph_tag; + typedef void edge_property_type; + + typedef edge_id edge_descriptor; + typedef V vertex_descriptor; + typedef typename boost::integer_range::iterator edge_iterator; + typedef void out_edge_iterator; + typedef void in_edge_iterator; + typedef void adjacency_iterator; + typedef void vertex_iterator; + }; + + template + std::pair::edge_iterator, + typename edge_list_impl_ra::edge_iterator> + edges(const edge_list_impl_ra& g_) + { + const G& g = static_cast(g_); + typedef typename edge_list_impl_ra::edge_iterator edge_iterator; + return std::make_pair(edge_iterator(0), edge_iterator(g._last - g._first)); + } + template + typename edge_list_impl_ra::vertex_descriptor + source(typename edge_list_impl_ra::edge_descriptor e, + const edge_list_impl_ra& g_) + { + const G& g = static_cast(g_); + return g._first[e].first; + } + template + typename edge_list_impl_ra::vertex_descriptor + target(typename edge_list_impl_ra::edge_descriptor e, + const edge_list_impl_ra& g_) + { + const G& g = static_cast(g_); + return g._first[e].second; + } + template + class el_ra_edge_property_map + : public put_get_helper >{ + public: + typedef E key_type; + typedef E value_type; + typedef E reference; + typedef readable_property_map_tag category; + + value_type operator[](key_type e) const { + return e; + } + }; + struct edge_list_ra_edge_property_selector { + template + struct bind_ { + typedef el_ra_edge_property_map type; + typedef type const_type; + }; + }; + template <> + struct edge_property_selector { + typedef edge_list_ra_edge_property_selector type; + }; + template + inline + typename property_map< edge_list_impl_ra, edge_index_t>::type + get(edge_index_t, const edge_list_impl_ra&) { + typedef typename property_map< edge_list_impl_ra, + edge_index_t>::type EdgeIndexMap; + return EdgeIndexMap(); + } + + template + inline D + get(edge_index_t, const edge_list_impl_ra&, + typename edge_list_impl_ra::edge_descriptor e) { + return e; + } + + + // Some helper classes for determining if the iterators are random access + template + struct is_random { + enum { RET = false }; + typedef mpl::false_ type; + }; + template <> + struct is_random { + enum { RET = true }; typedef mpl::true_ type; + }; + + // The edge_list class conditionally inherits from one of the + // above two classes. + + template ::value_type, + class D = typename std::iterator_traits::difference_type, + class Cat = typename std::iterator_traits::iterator_category> +#else + class T, + class D, + class Cat> +#endif + class edge_list + : public mpl::if_< typename is_random::type, + edge_list_impl_ra< edge_list, EdgeIter,T,D>, + edge_list_impl< edge_list, EdgeIter,T,D> + >::type + { + public: + typedef directed_tag directed_category; + typedef allow_parallel_edge_tag edge_parallel_category; + typedef edge_list_graph_tag traversal_category; + typedef std::size_t edges_size_type; + typedef std::size_t vertices_size_type; + typedef std::size_t degree_size_type; + edge_list(EdgeIter first, EdgeIter last) : _first(first), _last(last) { + m_num_edges = std::distance(first, last); + } + edge_list(EdgeIter first, EdgeIter last, edges_size_type E) + : _first(first), _last(last), m_num_edges(E) { } + + EdgeIter _first, _last; + edges_size_type m_num_edges; + }; + + template + std::size_t num_edges(const edge_list& el) { + return el.m_num_edges; + } + +#ifndef BOOST_NO_STD_ITERATOR_TRAITS + template + inline edge_list + make_edge_list(EdgeIter first, EdgeIter last) + { + return edge_list(first, last); + } +#endif + +} /* namespace boost */ + +#endif /* BOOST_GRAPH_EDGE_LIST_HPP */ diff --git a/win32/include/boost/graph/edmunds_karp_max_flow.hpp b/win32/include/boost/graph/edmunds_karp_max_flow.hpp new file mode 100755 index 000000000..40d888ac5 --- /dev/null +++ b/win32/include/boost/graph/edmunds_karp_max_flow.hpp @@ -0,0 +1,250 @@ +//======================================================================= +// Copyright 2000 University of Notre Dame. +// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef EDMUNDS_KARP_MAX_FLOW_HPP +#define EDMUNDS_KARP_MAX_FLOW_HPP + +#include +#include +#include // for std::min and std::max +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + // The "labeling" algorithm from "Network Flows" by Ahuja, Magnanti, + // Orlin. I think this is the same as or very similar to the original + // Edmunds-Karp algorithm. This solves the maximum flow problem. + + namespace detail { + + template + filtered_graph > + residual_graph(Graph& g, ResCapMap residual_capacity) { + return filtered_graph > + (g, is_residual_edge(residual_capacity)); + } + + template + inline void + augment(Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink, + PredEdgeMap p, + ResCapMap residual_capacity, + RevEdgeMap reverse_edge) + { + typename graph_traits::edge_descriptor e; + typename graph_traits::vertex_descriptor u; + typedef typename property_traits::value_type FlowValue; + + // find minimum residual capacity along the augmenting path + FlowValue delta = (std::numeric_limits::max)(); + e = p[sink]; + do { + BOOST_USING_STD_MIN(); + delta = min BOOST_PREVENT_MACRO_SUBSTITUTION(delta, residual_capacity[e]); + u = source(e, g); + e = p[u]; + } while (u != src); + + // push delta units of flow along the augmenting path + e = p[sink]; + do { + residual_capacity[e] -= delta; + residual_capacity[reverse_edge[e]] += delta; + u = source(e, g); + e = p[u]; + } while (u != src); + } + + } // namespace detail + + template + typename property_traits::value_type + edmunds_karp_max_flow + (Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink, + CapacityEdgeMap cap, + ResidualCapacityEdgeMap res, + ReverseEdgeMap rev, + ColorMap color, + PredEdgeMap pred) + { + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + + typename graph_traits::vertex_iterator u_iter, u_end; + typename graph_traits::out_edge_iterator ei, e_end; + for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) + for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei) + res[*ei] = cap[*ei]; + + color[sink] = Color::gray(); + while (color[sink] != Color::white()) { + boost::queue Q; + breadth_first_search + (detail::residual_graph(g, res), src, Q, + make_bfs_visitor(record_edge_predecessors(pred, on_tree_edge())), + color); + if (color[sink] != Color::white()) + detail::augment(g, src, sink, pred, res, rev); + } // while + + typename property_traits::value_type flow = 0; + for (tie(ei, e_end) = out_edges(src, g); ei != e_end; ++ei) + flow += (cap[*ei] - res[*ei]); + return flow; + } // edmunds_karp_max_flow() + + namespace detail { + //------------------------------------------------------------------------- + // Handle default for color property map + + // use of class here is a VC++ workaround + template + struct edmunds_karp_dispatch2 { + template + static typename edge_capacity_value::type + apply + (Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink, + PredMap pred, + const bgl_named_params& params, + ColorMap color) + { + return edmunds_karp_max_flow + (g, src, sink, + choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), + choose_pmap(get_param(params, edge_residual_capacity), + g, edge_residual_capacity), + choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), + color, pred); + } + }; + template<> + struct edmunds_karp_dispatch2 { + template + static typename edge_capacity_value::type + apply + (Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink, + PredMap pred, + const bgl_named_params& params, + detail::error_property_not_found) + { + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename graph_traits::vertices_size_type size_type; + size_type n = is_default_param(get_param(params, vertex_color)) ? + num_vertices(g) : 1; + std::vector color_vec(n); + return edmunds_karp_max_flow + (g, src, sink, + choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), + choose_pmap(get_param(params, edge_residual_capacity), + g, edge_residual_capacity), + choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), + make_iterator_property_map(color_vec.begin(), choose_const_pmap + (get_param(params, vertex_index), + g, vertex_index), color_vec[0]), + pred); + } + }; + + //------------------------------------------------------------------------- + // Handle default for predecessor property map + + // use of class here is a VC++ workaround + template + struct edmunds_karp_dispatch1 { + template + static typename edge_capacity_value::type + apply(Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink, + const bgl_named_params& params, + PredMap pred) + { + typedef typename property_value< bgl_named_params, vertex_color_t>::type C; + return edmunds_karp_dispatch2::apply + (g, src, sink, pred, params, get_param(params, vertex_color)); + } + }; + template<> + struct edmunds_karp_dispatch1 { + + template + static typename edge_capacity_value::type + apply + (Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink, + const bgl_named_params& params, + detail::error_property_not_found) + { + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename graph_traits::vertices_size_type size_type; + size_type n = is_default_param(get_param(params, vertex_predecessor)) ? + num_vertices(g) : 1; + std::vector pred_vec(n); + + typedef typename property_value< bgl_named_params, vertex_color_t>::type C; + return edmunds_karp_dispatch2::apply + (g, src, sink, + make_iterator_property_map(pred_vec.begin(), choose_const_pmap + (get_param(params, vertex_index), + g, vertex_index), pred_vec[0]), + params, + get_param(params, vertex_color)); + } + }; + + } // namespace detail + + template + typename detail::edge_capacity_value::type + edmunds_karp_max_flow + (Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink, + const bgl_named_params& params) + { + typedef typename property_value< bgl_named_params, vertex_predecessor_t>::type Pred; + return detail::edmunds_karp_dispatch1::apply + (g, src, sink, params, get_param(params, vertex_predecessor)); + } + + template + typename property_traits< + typename property_map::const_type + >::value_type + edmunds_karp_max_flow + (Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink) + { + bgl_named_params params(0); + return edmunds_karp_max_flow(g, src, sink, params); + } + +} // namespace boost + +#endif // EDMUNDS_KARP_MAX_FLOW_HPP diff --git a/win32/include/boost/graph/erdos_renyi_generator.hpp b/win32/include/boost/graph/erdos_renyi_generator.hpp new file mode 100755 index 000000000..bc86116bd --- /dev/null +++ b/win32/include/boost/graph/erdos_renyi_generator.hpp @@ -0,0 +1,228 @@ +// Copyright 2004, 2005 The Trustees of Indiana University. + +// 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) + +// Authors: Jeremiah Willcock +// Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP +#define BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + template + class erdos_renyi_iterator + { + typedef typename graph_traits::directed_category directed_category; + typedef typename graph_traits::vertices_size_type vertices_size_type; + typedef typename graph_traits::edges_size_type edges_size_type; + + BOOST_STATIC_CONSTANT + (bool, + is_undirected = (is_base_and_derived::value + || is_same::value)); + + public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef void difference_type; + + erdos_renyi_iterator() : gen(), n(0), edges(0), allow_self_loops(false) {} + erdos_renyi_iterator(RandomGenerator& gen, vertices_size_type n, + double fraction = 0.0, bool allow_self_loops = false) + : gen(&gen), n(n), edges(edges_size_type(fraction * n * n)), + allow_self_loops(allow_self_loops) + { + if (is_undirected) edges = edges / 2; + next(); + } + + erdos_renyi_iterator(RandomGenerator& gen, vertices_size_type n, + edges_size_type m, bool allow_self_loops = false) + : gen(&gen), n(n), edges(m), + allow_self_loops(allow_self_loops) + { + next(); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + erdos_renyi_iterator& operator++() + { + --edges; + next(); + return *this; + } + + erdos_renyi_iterator operator++(int) + { + erdos_renyi_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const erdos_renyi_iterator& other) const + { return edges == other.edges; } + + bool operator!=(const erdos_renyi_iterator& other) const + { return !(*this == other); } + + private: + void next() + { + uniform_int rand_vertex(0, n-1); + current.first = rand_vertex(*gen); + do { + current.second = rand_vertex(*gen); + } while (current.first == current.second && !allow_self_loops); + } + + RandomGenerator* gen; + vertices_size_type n; + edges_size_type edges; + bool allow_self_loops; + value_type current; + }; + + template + class sorted_erdos_renyi_iterator + { + typedef typename graph_traits::directed_category directed_category; + typedef typename graph_traits::vertices_size_type vertices_size_type; + typedef typename graph_traits::edges_size_type edges_size_type; + + BOOST_STATIC_CONSTANT + (bool, + is_undirected = (is_base_and_derived::value + || is_same::value)); + + public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef void difference_type; + + sorted_erdos_renyi_iterator() + : gen(), rand_vertex(0.5), n(0), allow_self_loops(false), + src((std::numeric_limits::max)()), tgt(0), prob(0) {} + sorted_erdos_renyi_iterator(RandomGenerator& gen, vertices_size_type n, + double prob = 0.0, + bool allow_self_loops = false) + : gen(), + // The "1.0 - prob" in the next line is to work around a Boost.Random + // (and TR1) bug in the specification of geometric_distribution. It + // should be replaced by "prob" when the issue is fixed. + rand_vertex(1.0 - prob), + n(n), allow_self_loops(allow_self_loops), src(0), tgt(0), prob(prob) + { + this->gen.reset(new uniform_01(gen)); + + if (prob == 0.0) {src = (std::numeric_limits::max)(); return;} + next(); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + sorted_erdos_renyi_iterator& operator++() + { + next(); + return *this; + } + + sorted_erdos_renyi_iterator operator++(int) + { + sorted_erdos_renyi_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const sorted_erdos_renyi_iterator& other) const + { return src == other.src && tgt == other.tgt; } + + bool operator!=(const sorted_erdos_renyi_iterator& other) const + { return !(*this == other); } + + private: + void next() + { + using std::sqrt; + using std::floor; + + // In order to get the edges from the generator in sorted order, one + // effective (but slow) procedure would be to use a + // bernoulli_distribution for each legal (src, tgt) pair. Because of the + // O(n^2) cost of that, a geometric distribution is used. The geometric + // distribution tells how many times the bernoulli_distribution would + // need to be run until it returns true. Thus, this distribution can be + // used to step through the edges which are actually present. Everything + // beyond "tgt += increment" is done to effectively convert linear + // indexing (the partial sums of the geometric distribution output) into + // graph edges. + assert (src != (std::numeric_limits::max)()); + vertices_size_type increment = rand_vertex(*gen); + tgt += increment; + if (is_undirected) { + // Update src and tgt based on position of tgt + // Basically, we want the greatest src_increment such that (in \bbQ): + // src_increment * (src + allow_self_loops + src_increment - 1/2) <= tgt + // The result of the LHS of this, evaluated with the computed + // src_increment, is then subtracted from tgt + double src_minus_half = (src + allow_self_loops) - 0.5; + double disc = src_minus_half * src_minus_half + 2 * tgt; + double src_increment_fp = floor(sqrt(disc) - src_minus_half); + vertices_size_type src_increment = vertices_size_type(src_increment_fp); + if (src + src_increment >= n) { + src = n; + } else { + tgt -= (src + allow_self_loops) * src_increment + + src_increment * (src_increment - 1) / 2; + src += src_increment; + } + } else { + // Number of out edge positions possible from each vertex in this graph + vertices_size_type possible_out_edges = n - (allow_self_loops ? 0 : 1); + src += (std::min)(n - src, tgt / possible_out_edges); + tgt %= possible_out_edges; + } + // Set end of graph code so (src, tgt) will be the same as for the end + // sorted_erdos_renyi_iterator + if (src >= n) {src = (std::numeric_limits::max)(); tgt = 0;} + // Copy (src, tgt) into current + current.first = src; + current.second = tgt; + // Adjust for (src, src) edge being forbidden + if (!allow_self_loops && tgt >= src) ++current.second; + } + + shared_ptr > gen; + geometric_distribution rand_vertex; + vertices_size_type n; + bool allow_self_loops; + vertices_size_type src, tgt; + value_type current; + double prob; + }; + +} // end namespace boost + +#endif // BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP diff --git a/win32/include/boost/graph/exception.hpp b/win32/include/boost/graph/exception.hpp new file mode 100755 index 000000000..f3432fcd9 --- /dev/null +++ b/win32/include/boost/graph/exception.hpp @@ -0,0 +1,44 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_EXCEPTION_HPP +#define BOOST_GRAPH_EXCEPTION_HPP + +#include +#include + +namespace boost { + + struct bad_graph : public std::invalid_argument { + bad_graph(const std::string& what_arg) + : std::invalid_argument(what_arg) { } + }; + + struct not_a_dag : public bad_graph { + not_a_dag() + : bad_graph("The graph must be a DAG.") { } + }; + + struct negative_edge : public bad_graph { + negative_edge() + : bad_graph("The graph may not contain an edge with negative weight."){ } + }; + + struct negative_cycle : public bad_graph { + negative_cycle() + : bad_graph("The graph may not contain negative cycles.") { } + }; + struct not_connected : public bad_graph { + not_connected() + : bad_graph("The graph must be connected.") { } + }; + +} // namespace boost + +#endif // BOOST_GRAPH_EXCEPTION_HPP diff --git a/win32/include/boost/graph/filtered_graph.hpp b/win32/include/boost/graph/filtered_graph.hpp new file mode 100755 index 000000000..ff0081526 --- /dev/null +++ b/win32/include/boost/graph/filtered_graph.hpp @@ -0,0 +1,507 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_FILTERED_GRAPH_HPP +#define BOOST_FILTERED_GRAPH_HPP + +#include +#include +#include +#include + +namespace boost { + + //========================================================================= + // Some predicate classes. + + struct keep_all { + template + bool operator()(const T&) const { return true; } + }; + + // Keep residual edges (used in maximum-flow algorithms). + template + struct is_residual_edge { + is_residual_edge() { } + is_residual_edge(ResidualCapacityEdgeMap rcap) : m_rcap(rcap) { } + template + bool operator()(const Edge& e) const { + return 0 < get(m_rcap, e); + } + ResidualCapacityEdgeMap m_rcap; + }; + + template + struct is_in_subset { + is_in_subset() : m_s(0) { } + is_in_subset(const Set& s) : m_s(&s) { } + + template + bool operator()(const Elt& x) const { + return set_contains(*m_s, x); + } + const Set* m_s; + }; + + template + struct is_not_in_subset { + is_not_in_subset() : m_s(0) { } + is_not_in_subset(const Set& s) : m_s(&s) { } + + template + bool operator()(const Elt& x) const { + return !set_contains(*m_s, x); + } + const Set* m_s; + }; + + namespace detail { + + template + struct out_edge_predicate { + out_edge_predicate() { } + out_edge_predicate(EdgePredicate ep, VertexPredicate vp, + const Graph& g) + : m_edge_pred(ep), m_vertex_pred(vp), m_g(&g) { } + + template + bool operator()(const Edge& e) const { + return m_edge_pred(e) && m_vertex_pred(target(e, *m_g)); + } + EdgePredicate m_edge_pred; + VertexPredicate m_vertex_pred; + const Graph* m_g; + }; + + template + struct in_edge_predicate { + in_edge_predicate() { } + in_edge_predicate(EdgePredicate ep, VertexPredicate vp, + const Graph& g) + : m_edge_pred(ep), m_vertex_pred(vp), m_g(&g) { } + + template + bool operator()(const Edge& e) const { + return m_edge_pred(e) && m_vertex_pred(source(e, *m_g)); + } + EdgePredicate m_edge_pred; + VertexPredicate m_vertex_pred; + const Graph* m_g; + }; + + template + struct edge_predicate { + edge_predicate() { } + edge_predicate(EdgePredicate ep, VertexPredicate vp, + const Graph& g) + : m_edge_pred(ep), m_vertex_pred(vp), m_g(&g) { } + + template + bool operator()(const Edge& e) const { + return m_edge_pred(e) + && m_vertex_pred(source(e, *m_g)) && m_vertex_pred(target(e, *m_g)); + } + EdgePredicate m_edge_pred; + VertexPredicate m_vertex_pred; + const Graph* m_g; + }; + + } // namespace detail + + + //=========================================================================== + // Filtered Graph + + struct filtered_graph_tag { }; + + // This base class is a stupid hack to change overload resolution + // rules for the source and target functions so that they are a + // worse match than the source and target functions defined for + // pairs in graph_traits.hpp. I feel dirty. -JGS + template + struct filtered_graph_base { + typedef graph_traits Traits; + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::edge_descriptor edge_descriptor; + filtered_graph_base(const G& g) : m_g(g) { } + //protected: + const G& m_g; + }; + + template + class filtered_graph : public filtered_graph_base { + typedef filtered_graph_base Base; + typedef graph_traits Traits; + typedef filtered_graph self; + public: + typedef Graph graph_type; + typedef detail::out_edge_predicate OutEdgePred; + typedef detail::in_edge_predicate InEdgePred; + typedef detail::edge_predicate EdgePred; + + // Constructors + filtered_graph(const Graph& g, EdgePredicate ep) + : Base(g), m_edge_pred(ep) { } + + filtered_graph(const Graph& g, EdgePredicate ep, VertexPredicate vp) + : Base(g), m_edge_pred(ep), m_vertex_pred(vp) { } + + // Graph requirements + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::edge_descriptor edge_descriptor; + typedef typename Traits::directed_category directed_category; + typedef typename Traits::edge_parallel_category edge_parallel_category; + typedef typename Traits::traversal_category traversal_category; + + // IncidenceGraph requirements + typedef filter_iterator< + OutEdgePred, typename Traits::out_edge_iterator + > out_edge_iterator; + + typedef typename Traits::degree_size_type degree_size_type; + + // AdjacencyGraph requirements + typedef typename adjacency_iterator_generator::type adjacency_iterator; + + // BidirectionalGraph requirements + typedef filter_iterator< + InEdgePred, typename Traits::in_edge_iterator + > in_edge_iterator; + + // VertexListGraph requirements + typedef filter_iterator< + VertexPredicate, typename Traits::vertex_iterator + > vertex_iterator; + typedef typename Traits::vertices_size_type vertices_size_type; + + // EdgeListGraph requirements + typedef filter_iterator< + EdgePred, typename Traits::edge_iterator + > edge_iterator; + typedef typename Traits::edges_size_type edges_size_type; + + typedef typename ::boost::edge_property_type::type edge_property_type; + typedef typename ::boost::vertex_property_type::type vertex_property_type; + typedef filtered_graph_tag graph_tag; + +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + // Bundled properties support + template + typename graph::detail::bundled_result::type& + operator[](Descriptor x) + { return const_cast(this->m_g)[x]; } + + template + typename graph::detail::bundled_result::type const& + operator[](Descriptor x) const + { return this->m_g[x]; } +#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES + + static vertex_descriptor null_vertex() + { + return Graph::null_vertex(); + } + + //private: + EdgePredicate m_edge_pred; + VertexPredicate m_vertex_pred; + }; + +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + template + struct vertex_bundle_type > + : vertex_bundle_type { }; + + template + struct edge_bundle_type > + : edge_bundle_type { }; +#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES + + //=========================================================================== + // Non-member functions for the Filtered Edge Graph + + // Helper functions + template + inline filtered_graph + make_filtered_graph(Graph& g, EdgePredicate ep) { + return filtered_graph(g, ep); + } + template + inline filtered_graph + make_filtered_graph(Graph& g, EdgePredicate ep, VertexPredicate vp) { + return filtered_graph(g, ep, vp); + } + + template + inline filtered_graph + make_filtered_graph(const Graph& g, EdgePredicate ep) { + return filtered_graph(g, ep); + } + template + inline filtered_graph + make_filtered_graph(const Graph& g, EdgePredicate ep, VertexPredicate vp) { + return filtered_graph(g, ep, vp); + } + + template + std::pair::vertex_iterator, + typename filtered_graph::vertex_iterator> + vertices(const filtered_graph& g) + { + typedef filtered_graph Graph; + typename graph_traits::vertex_iterator f, l; + tie(f, l) = vertices(g.m_g); + typedef typename Graph::vertex_iterator iter; + return std::make_pair(iter(g.m_vertex_pred, f, l), + iter(g.m_vertex_pred, l, l)); + } + + template + std::pair::edge_iterator, + typename filtered_graph::edge_iterator> + edges(const filtered_graph& g) + { + typedef filtered_graph Graph; + typename Graph::EdgePred pred(g.m_edge_pred, g.m_vertex_pred, g); + typename graph_traits::edge_iterator f, l; + tie(f, l) = edges(g.m_g); + typedef typename Graph::edge_iterator iter; + return std::make_pair(iter(pred, f, l), iter(pred, l, l)); + } + + // An alternative for num_vertices() and num_edges() would be to + // count the number in the filtered graph. This is problematic + // because of the interaction with the vertex indices... they would + // no longer go from 0 to num_vertices(), which would cause trouble + // for algorithms allocating property storage in an array. We could + // try to create a mapping to new recalibrated indices, but I don't + // see an efficient way to do this. + // + // However, the current solution is still unsatisfactory because + // the following semantic constraints no longer hold: + // tie(vi, viend) = vertices(g); + // assert(std::distance(vi, viend) == num_vertices(g)); + + template + typename filtered_graph::vertices_size_type + num_vertices(const filtered_graph& g) { + return num_vertices(g.m_g); + } + + template + typename filtered_graph::edges_size_type + num_edges(const filtered_graph& g) { + return num_edges(g.m_g); + } + + template + typename filtered_graph_base::vertex_descriptor + source(typename filtered_graph_base::edge_descriptor e, + const filtered_graph_base& g) + { + return source(e, g.m_g); + } + + template + typename filtered_graph_base::vertex_descriptor + target(typename filtered_graph_base::edge_descriptor e, + const filtered_graph_base& g) + { + return target(e, g.m_g); + } + + template + std::pair::out_edge_iterator, + typename filtered_graph::out_edge_iterator> + out_edges(typename filtered_graph::vertex_descriptor u, + const filtered_graph& g) + { + typedef filtered_graph Graph; + typename Graph::OutEdgePred pred(g.m_edge_pred, g.m_vertex_pred, g); + typedef typename Graph::out_edge_iterator iter; + typename graph_traits::out_edge_iterator f, l; + tie(f, l) = out_edges(u, g.m_g); + return std::make_pair(iter(pred, f, l), iter(pred, l, l)); + } + + template + typename filtered_graph::degree_size_type + out_degree(typename filtered_graph::vertex_descriptor u, + const filtered_graph& g) + { + typename filtered_graph::degree_size_type n = 0; + typename filtered_graph::out_edge_iterator f, l; + for (tie(f, l) = out_edges(u, g); f != l; ++f) + ++n; + return n; + } + + template + std::pair::adjacency_iterator, + typename filtered_graph::adjacency_iterator> + adjacent_vertices(typename filtered_graph::vertex_descriptor u, + const filtered_graph& g) + { + typedef filtered_graph Graph; + typedef typename Graph::adjacency_iterator adjacency_iterator; + typename Graph::out_edge_iterator f, l; + tie(f, l) = out_edges(u, g); + return std::make_pair(adjacency_iterator(f, const_cast(&g)), + adjacency_iterator(l, const_cast(&g))); + } + + template + std::pair::in_edge_iterator, + typename filtered_graph::in_edge_iterator> + in_edges(typename filtered_graph::vertex_descriptor u, + const filtered_graph& g) + { + typedef filtered_graph Graph; + typename Graph::InEdgePred pred(g.m_edge_pred, g.m_vertex_pred, g); + typedef typename Graph::in_edge_iterator iter; + typename graph_traits::in_edge_iterator f, l; + tie(f, l) = in_edges(u, g.m_g); + return std::make_pair(iter(pred, f, l), iter(pred, l, l)); + } + + template + typename filtered_graph::degree_size_type + in_degree(typename filtered_graph::vertex_descriptor u, + const filtered_graph& g) + { + typename filtered_graph::degree_size_type n = 0; + typename filtered_graph::in_edge_iterator f, l; + for (tie(f, l) = in_edges(u, g); f != l; ++f) + ++n; + return n; + } + + template + std::pair::edge_descriptor, bool> + edge(typename filtered_graph::vertex_descriptor u, + typename filtered_graph::vertex_descriptor v, + const filtered_graph& g) + { + typename graph_traits::edge_descriptor e; + bool exists; + tie(e, exists) = edge(u, v, g.m_g); + return std::make_pair(e, exists && g.m_edge_pred(e)); + } + + template + std::pair::out_edge_iterator, + typename filtered_graph::out_edge_iterator> + edge_range(typename filtered_graph::vertex_descriptor u, + typename filtered_graph::vertex_descriptor v, + const filtered_graph& g) + { + typedef filtered_graph Graph; + typename Graph::OutEdgePred pred(g.m_edge_pred, g.m_vertex_pred, g); + typedef typename Graph::out_edge_iterator iter; + typename graph_traits::out_edge_iterator f, l; + tie(f, l) = edge_range(u, v, g.m_g); + return std::make_pair(iter(pred, f, l), iter(pred, l, l)); + } + + + //=========================================================================== + // Property map + + namespace detail { + struct filtered_graph_property_selector { + template + struct bind_ { + typedef typename FilteredGraph::graph_type Graph; + typedef property_map Map; + typedef typename Map::type type; + typedef typename Map::const_type const_type; + }; + }; + } // namespace detail + + template <> + struct vertex_property_selector { + typedef detail::filtered_graph_property_selector type; + }; + template <> + struct edge_property_selector { + typedef detail::filtered_graph_property_selector type; + }; + + template + typename property_map::type + get(Property p, filtered_graph& g) + { + return get(p, const_cast(g.m_g)); + } + + template + typename property_map::const_type + get(Property p, const filtered_graph& g) + { + return get(p, (const G&)g.m_g); + } + + template + typename property_map_value::type + get(Property p, const filtered_graph& g, const Key& k) + { + return get(p, (const G&)g.m_g, k); + } + + template + void + put(Property p, const filtered_graph& g, const Key& k, + const Value& val) + { + put(p, const_cast(g.m_g), k, val); + } + + //=========================================================================== + // Some filtered subgraph specializations + + template + struct vertex_subset_filter { + typedef filtered_graph > type; + }; + template + inline typename vertex_subset_filter::type + make_vertex_subset_filter(Graph& g, const Set& s) { + typedef typename vertex_subset_filter::type Filter; + is_in_subset p(s); + return Filter(g, keep_all(), p); + } + + template + struct vertex_subset_compliment_filter { + typedef filtered_graph > type; + }; + template + inline typename vertex_subset_compliment_filter::type + make_vertex_subset_compliment_filter(Graph& g, const Set& s) { + typedef typename vertex_subset_compliment_filter::type Filter; + is_not_in_subset p(s); + return Filter(g, keep_all(), p); + } + + +} // namespace boost + + +#endif // BOOST_FILTERED_GRAPH_HPP diff --git a/win32/include/boost/graph/floyd_warshall_shortest.hpp b/win32/include/boost/graph/floyd_warshall_shortest.hpp new file mode 100755 index 000000000..27a6d406a --- /dev/null +++ b/win32/include/boost/graph/floyd_warshall_shortest.hpp @@ -0,0 +1,251 @@ +// Copyright 2002 Rensselaer Polytechnic Institute + +// 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) + +// Authors: Lauren Foutz +// Scott Hill + +/* + This file implements the functions + + template + bool floyd_warshall_initialized_all_pairs_shortest_paths( + const VertexListGraph& g, DistanceMatrix& d, + const bgl_named_params& params) + + AND + + template + bool floyd_warshall_all_pairs_shortest_paths( + const VertexAndEdgeListGraph& g, DistanceMatrix& d, + const bgl_named_params& params) +*/ + + +#ifndef BOOST_GRAPH_FLOYD_WARSHALL_HPP +#define BOOST_GRAPH_FLOYD_WARSHALL_HPP + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace detail { + template + T min_with_compare(const T& x, const T& y, const BinaryPredicate& compare) + { + if (compare(x, y)) return x; + else return y; + } + + template + bool floyd_warshall_dispatch(const VertexListGraph& g, + DistanceMatrix& d, const BinaryPredicate &compare, + const BinaryFunction &combine, const Infinity& inf, + const Zero& zero) + { + typename graph_traits::vertex_iterator + i, lasti, j, lastj, k, lastk; + + + for (tie(k, lastk) = vertices(g); k != lastk; k++) + for (tie(i, lasti) = vertices(g); i != lasti; i++) + for (tie(j, lastj) = vertices(g); j != lastj; j++) + { + d[*i][*j] = + detail::min_with_compare(d[*i][*j], + combine(d[*i][*k], d[*k][*j]), + compare); + } + + + for (tie(i, lasti) = vertices(g); i != lasti; i++) + if (compare(d[*i][*i], zero)) + return false; + return true; + } + } + + template + bool floyd_warshall_initialized_all_pairs_shortest_paths( + const VertexListGraph& g, DistanceMatrix& d, + const BinaryPredicate& compare, + const BinaryFunction& combine, const Infinity& inf, + const Zero& zero) + { + function_requires >(); + + return detail::floyd_warshall_dispatch(g, d, compare, combine, + inf, zero); + } + + + + template + bool floyd_warshall_all_pairs_shortest_paths( + const VertexAndEdgeListGraph& g, + DistanceMatrix& d, const WeightMap& w, + const BinaryPredicate& compare, const BinaryFunction& combine, + const Infinity& inf, const Zero& zero) + { + function_requires >(); + function_requires >(); + function_requires >(); + + typename graph_traits::vertex_iterator + firstv, lastv, firstv2, lastv2; + typename graph_traits::edge_iterator first, last; + + + for(tie(firstv, lastv) = vertices(g); firstv != lastv; firstv++) + for(tie(firstv2, lastv2) = vertices(g); firstv2 != lastv2; firstv2++) + d[*firstv][*firstv2] = inf; + + + for(tie(firstv, lastv) = vertices(g); firstv != lastv; firstv++) + d[*firstv][*firstv] = zero; + + + for(tie(first, last) = edges(g); first != last; first++) + { + if (d[source(*first, g)][target(*first, g)] != inf) { + d[source(*first, g)][target(*first, g)] = + detail::min_with_compare( + get(w, *first), + d[source(*first, g)][target(*first, g)], + compare); + } else + d[source(*first, g)][target(*first, g)] = get(w, *first); + } + + bool is_undirected = is_same::directed_category, + undirected_tag>::value; + if (is_undirected) + { + for(tie(first, last) = edges(g); first != last; first++) + { + if (d[target(*first, g)][source(*first, g)] != inf) + d[target(*first, g)][source(*first, g)] = + detail::min_with_compare( + get(w, *first), + d[target(*first, g)][source(*first, g)], + compare); + else + d[target(*first, g)][source(*first, g)] = get(w, *first); + } + } + + + return detail::floyd_warshall_dispatch(g, d, compare, combine, + inf, zero); + } + + + namespace detail { + template + bool floyd_warshall_init_dispatch(const VertexListGraph& g, + DistanceMatrix& d, WeightMap w, + const bgl_named_params& params) + { + typedef typename property_traits::value_type WM; + + return floyd_warshall_initialized_all_pairs_shortest_paths(g, d, + choose_param(get_param(params, distance_compare_t()), + std::less()), + choose_param(get_param(params, distance_combine_t()), + closed_plus()), + choose_param(get_param(params, distance_inf_t()), + std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()), + choose_param(get_param(params, distance_zero_t()), + WM())); + } + + + + template + bool floyd_warshall_noninit_dispatch(const VertexAndEdgeListGraph& g, + DistanceMatrix& d, WeightMap w, + const bgl_named_params& params) + { + typedef typename property_traits::value_type WM; + + return floyd_warshall_all_pairs_shortest_paths(g, d, w, + choose_param(get_param(params, distance_compare_t()), + std::less()), + choose_param(get_param(params, distance_combine_t()), + closed_plus()), + choose_param(get_param(params, distance_inf_t()), + std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()), + choose_param(get_param(params, distance_zero_t()), + WM())); + } + + + } // namespace detail + + + + template + bool floyd_warshall_initialized_all_pairs_shortest_paths( + const VertexListGraph& g, DistanceMatrix& d, + const bgl_named_params& params) + { + return detail::floyd_warshall_init_dispatch(g, d, + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + params); + } + + template + bool floyd_warshall_initialized_all_pairs_shortest_paths( + const VertexListGraph& g, DistanceMatrix& d) + { + bgl_named_params params(0); + return detail::floyd_warshall_init_dispatch(g, d, + get(edge_weight, g), params); + } + + + + + template + bool floyd_warshall_all_pairs_shortest_paths( + const VertexAndEdgeListGraph& g, DistanceMatrix& d, + const bgl_named_params& params) + { + return detail::floyd_warshall_noninit_dispatch(g, d, + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + params); + } + + template + bool floyd_warshall_all_pairs_shortest_paths( + const VertexAndEdgeListGraph& g, DistanceMatrix& d) + { + bgl_named_params params(0); + return detail::floyd_warshall_noninit_dispatch(g, d, + get(edge_weight, g), params); + } + + +} // namespace boost + +#endif + diff --git a/win32/include/boost/graph/fruchterman_reingold.hpp b/win32/include/boost/graph/fruchterman_reingold.hpp new file mode 100755 index 000000000..6f07a6a59 --- /dev/null +++ b/win32/include/boost/graph/fruchterman_reingold.hpp @@ -0,0 +1,420 @@ +// Copyright 2004 The Trustees of Indiana University. + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP +#define BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP + +#include +#include +#include +#include +#include +#include +#include // for std::min and std::max + +namespace boost { + +struct square_distance_attractive_force { + template + T + operator()(typename graph_traits::edge_descriptor, + T k, + T d, + const Graph&) const + { + return d * d / k; + } +}; + +struct square_distance_repulsive_force { + template + T + operator()(typename graph_traits::vertex_descriptor, + typename graph_traits::vertex_descriptor, + T k, + T d, + const Graph&) const + { + return k * k / d; + } +}; + +template +struct linear_cooling { + typedef T result_type; + + linear_cooling(std::size_t iterations) + : temp(T(iterations) / T(10)), step(0.1) { } + + linear_cooling(std::size_t iterations, T temp) + : temp(temp), step(temp / T(iterations)) { } + + T operator()() + { + T old_temp = temp; + temp -= step; + if (temp < T(0)) temp = T(0); + return old_temp; + } + + private: + T temp; + T step; +}; + +struct all_force_pairs +{ + template + void operator()(const Graph& g, ApplyForce apply_force) + { + typedef typename graph_traits::vertex_iterator vertex_iterator; + vertex_iterator v, end; + for (tie(v, end) = vertices(g); v != end; ++v) { + vertex_iterator u = v; + for (++u; u != end; ++u) { + apply_force(*u, *v); + apply_force(*v, *u); + } + } + } +}; + +template +struct grid_force_pairs +{ + template + explicit + grid_force_pairs(Dim width, Dim height, PositionMap position, const Graph& g) + : width(width), height(height), position(position) + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif // BOOST_NO_STDC_NAMESPACE + two_k = Dim(2) * sqrt(width*height / num_vertices(g)); + } + + template + void operator()(const Graph& g, ApplyForce apply_force) + { + typedef typename graph_traits::vertex_iterator vertex_iterator; + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef std::list bucket_t; + typedef std::vector buckets_t; + + std::size_t columns = std::size_t(width / two_k + Dim(1)); + std::size_t rows = std::size_t(height / two_k + Dim(1)); + buckets_t buckets(rows * columns); + vertex_iterator v, v_end; + for (tie(v, v_end) = vertices(g); v != v_end; ++v) { + std::size_t column = std::size_t((position[*v].x + width / 2) / two_k); + std::size_t row = std::size_t((position[*v].y + height / 2) / two_k); + + if (column >= columns) column = columns - 1; + if (row >= rows) row = rows - 1; + buckets[row * columns + column].push_back(*v); + } + + for (std::size_t row = 0; row < rows; ++row) + for (std::size_t column = 0; column < columns; ++column) { + bucket_t& bucket = buckets[row * columns + column]; + typedef typename bucket_t::iterator bucket_iterator; + for (bucket_iterator u = bucket.begin(); u != bucket.end(); ++u) { + // Repulse vertices in this bucket + bucket_iterator v = u; + for (++v; v != bucket.end(); ++v) { + apply_force(*u, *v); + apply_force(*v, *u); + } + + std::size_t adj_start_row = row == 0? 0 : row - 1; + std::size_t adj_end_row = row == rows - 1? row : row + 1; + std::size_t adj_start_column = column == 0? 0 : column - 1; + std::size_t adj_end_column = column == columns - 1? column : column + 1; + for (std::size_t other_row = adj_start_row; other_row <= adj_end_row; + ++other_row) + for (std::size_t other_column = adj_start_column; + other_column <= adj_end_column; ++other_column) + if (other_row != row || other_column != column) { + // Repulse vertices in this bucket + bucket_t& other_bucket + = buckets[other_row * columns + other_column]; + for (v = other_bucket.begin(); v != other_bucket.end(); ++v) + apply_force(*u, *v); + } + } + } + } + + private: + Dim width; + Dim height; + PositionMap position; + Dim two_k; +}; + +template +inline grid_force_pairs +make_grid_force_pairs(Dim width, Dim height, const PositionMap& position, + const Graph& g) +{ return grid_force_pairs(width, height, position, g); } + +template +void +scale_graph(const Graph& g, PositionMap position, + Dim left, Dim top, Dim right, Dim bottom) +{ + if (num_vertices(g) == 0) return; + + if (bottom > top) { + using std::swap; + swap(bottom, top); + } + + typedef typename graph_traits::vertex_iterator vertex_iterator; + + // Find min/max ranges + Dim minX = position[*vertices(g).first].x, maxX = minX; + Dim minY = position[*vertices(g).first].y, maxY = minY; + vertex_iterator vi, vi_end; + for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + minX = min BOOST_PREVENT_MACRO_SUBSTITUTION (minX, position[*vi].x); + maxX = max BOOST_PREVENT_MACRO_SUBSTITUTION (maxX, position[*vi].x); + minY = min BOOST_PREVENT_MACRO_SUBSTITUTION (minY, position[*vi].y); + maxY = max BOOST_PREVENT_MACRO_SUBSTITUTION (maxY, position[*vi].y); + } + + // Scale to bounding box provided + for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { + position[*vi].x = ((position[*vi].x - minX) / (maxX - minX)) + * (right - left) + left; + position[*vi].y = ((position[*vi].y - minY) / (maxY - minY)) + * (top - bottom) + bottom; + } +} + +namespace detail { + template + struct fr_apply_force + { + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + + fr_apply_force(const PositionMap& position, + const DisplacementMap& displacement, + RepulsiveForce repulsive_force, Dim k, const Graph& g) + : position(position), displacement(displacement), + repulsive_force(repulsive_force), k(k), g(g) + { } + + void operator()(vertex_descriptor u, vertex_descriptor v) + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif // BOOST_NO_STDC_NAMESPACE + if (u != v) { + Dim delta_x = position[v].x - position[u].x; + Dim delta_y = position[v].y - position[u].y; + Dim dist = sqrt(delta_x * delta_x + delta_y * delta_y); + Dim fr = repulsive_force(u, v, k, dist, g); + displacement[v].x += delta_x / dist * fr; + displacement[v].y += delta_y / dist * fr; + } + } + + private: + PositionMap position; + DisplacementMap displacement; + RepulsiveForce repulsive_force; + Dim k; + const Graph& g; + }; + +} // end namespace detail + +template +void +fruchterman_reingold_force_directed_layout + (const Graph& g, + PositionMap position, + Dim width, + Dim height, + AttractiveForce attractive_force, + RepulsiveForce repulsive_force, + ForcePairs force_pairs, + Cooling cool, + DisplacementMap displacement) +{ + typedef typename graph_traits::vertex_iterator vertex_iterator; + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::edge_iterator edge_iterator; + +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif // BOOST_NO_STDC_NAMESPACE + + Dim area = width * height; + // assume positions are initialized randomly + Dim k = sqrt(area / num_vertices(g)); + + detail::fr_apply_force + apply_force(position, displacement, repulsive_force, k, g); + + Dim temp = cool(); + if (temp) do { + // Calculate repulsive forces + vertex_iterator v, v_end; + for (tie(v, v_end) = vertices(g); v != v_end; ++v) { + displacement[*v].x = 0; + displacement[*v].y = 0; + } + force_pairs(g, apply_force); + + // Calculate attractive forces + edge_iterator e, e_end; + for (tie(e, e_end) = edges(g); e != e_end; ++e) { + vertex_descriptor v = source(*e, g); + vertex_descriptor u = target(*e, g); + Dim delta_x = position[v].x - position[u].x; + Dim delta_y = position[v].y - position[u].y; + Dim dist = sqrt(delta_x * delta_x + delta_y * delta_y); + Dim fa = attractive_force(*e, k, dist, g); + + displacement[v].x -= delta_x / dist * fa; + displacement[v].y -= delta_y / dist * fa; + displacement[u].x += delta_x / dist * fa; + displacement[u].y += delta_y / dist * fa; + } + + // Update positions + for (tie(v, v_end) = vertices(g); v != v_end; ++v) { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + Dim disp_size = sqrt(displacement[*v].x * displacement[*v].x + + displacement[*v].y * displacement[*v].y); + position[*v].x += displacement[*v].x / disp_size + * min BOOST_PREVENT_MACRO_SUBSTITUTION (disp_size, temp); + position[*v].y += displacement[*v].y / disp_size + * min BOOST_PREVENT_MACRO_SUBSTITUTION (disp_size, temp); + position[*v].x = min BOOST_PREVENT_MACRO_SUBSTITUTION + (width / 2, + max BOOST_PREVENT_MACRO_SUBSTITUTION(-width / 2, + position[*v].x)); + position[*v].y = min BOOST_PREVENT_MACRO_SUBSTITUTION + (height / 2, + max BOOST_PREVENT_MACRO_SUBSTITUTION(-height / 2, + position[*v].y)); + } + } while (temp = cool()); +} + +namespace detail { + template + struct fr_force_directed_layout + { + template + static void + run(const Graph& g, + PositionMap position, + Dim width, + Dim height, + AttractiveForce attractive_force, + RepulsiveForce repulsive_force, + ForcePairs force_pairs, + Cooling cool, + DisplacementMap displacement, + const bgl_named_params&) + { + fruchterman_reingold_force_directed_layout + (g, position, width, height, attractive_force, repulsive_force, + force_pairs, cool, displacement); + } + }; + + template<> + struct fr_force_directed_layout + { + template + static void + run(const Graph& g, + PositionMap position, + Dim width, + Dim height, + AttractiveForce attractive_force, + RepulsiveForce repulsive_force, + ForcePairs force_pairs, + Cooling cool, + error_property_not_found, + const bgl_named_params& params) + { + std::vector > displacements(num_vertices(g)); + fruchterman_reingold_force_directed_layout + (g, position, width, height, attractive_force, repulsive_force, + force_pairs, cool, + make_iterator_property_map + (displacements.begin(), + choose_const_pmap(get_param(params, vertex_index), g, + vertex_index), + simple_point())); + } + }; + +} // end namespace detail + +template +void +fruchterman_reingold_force_directed_layout + (const Graph& g, + PositionMap position, + Dim width, + Dim height, + const bgl_named_params& params) +{ + typedef typename property_value, + vertex_displacement_t>::type D; + + detail::fr_force_directed_layout::run + (g, position, width, height, + choose_param(get_param(params, attractive_force_t()), + square_distance_attractive_force()), + choose_param(get_param(params, repulsive_force_t()), + square_distance_repulsive_force()), + choose_param(get_param(params, force_pairs_t()), + make_grid_force_pairs(width, height, position, g)), + choose_param(get_param(params, cooling_t()), + linear_cooling(100)), + get_param(params, vertex_displacement_t()), + params); +} + +template +void +fruchterman_reingold_force_directed_layout(const Graph& g, + PositionMap position, + Dim width, + Dim height) +{ + fruchterman_reingold_force_directed_layout + (g, position, width, height, + attractive_force(square_distance_attractive_force())); +} + +} // end namespace boost + +#endif // BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP diff --git a/win32/include/boost/graph/graph_archetypes.hpp b/win32/include/boost/graph/graph_archetypes.hpp new file mode 100755 index 000000000..2d5197a81 --- /dev/null +++ b/win32/include/boost/graph/graph_archetypes.hpp @@ -0,0 +1,290 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_ARCHETYPES_HPP +#define BOOST_GRAPH_ARCHETYPES_HPP + +#include +#include + +namespace boost { // should use a different namespace for this + + namespace detail { + struct null_graph_archetype : public null_archetype<> { + struct traversal_category { }; + }; + } + + //=========================================================================== + template + struct incidence_graph_archetype : public Base + { + typedef typename Base::traversal_category base_trav_cat; + struct traversal_category + : public incidence_graph_tag, public base_trav_cat { }; +#if 0 + typedef immutable_graph_tag mutability_category; +#endif + typedef Vertex vertex_descriptor; + typedef unsigned int degree_size_type; + typedef unsigned int vertices_size_type; + typedef unsigned int edges_size_type; + struct edge_descriptor { + edge_descriptor() { } + edge_descriptor(const detail::dummy_constructor&) { } + bool operator==(const edge_descriptor&) const { return false; } + bool operator!=(const edge_descriptor&) const { return false; } + }; + typedef input_iterator_archetype out_edge_iterator; + + typedef Directed directed_category; + typedef ParallelCategory edge_parallel_category; + + typedef void adjacency_iterator; + typedef void in_edge_iterator; + typedef void vertex_iterator; + typedef void edge_iterator; + }; + template + V source(const typename incidence_graph_archetype::edge_descriptor&, + const incidence_graph_archetype& ) + { + return V(static_object::get()); + } + template + V target(const typename incidence_graph_archetype::edge_descriptor&, + const incidence_graph_archetype& ) + { + return V(static_object::get()); + } + + template + std::pair::out_edge_iterator, + typename incidence_graph_archetype::out_edge_iterator> + out_edges(const V&, const incidence_graph_archetype& ) + { + typedef typename incidence_graph_archetype::out_edge_iterator Iter; + return std::make_pair(Iter(), Iter()); + } + + template + typename incidence_graph_archetype::degree_size_type + out_degree(const V&, const incidence_graph_archetype& ) + { + return 0; + } + + //=========================================================================== + template + struct adjacency_graph_archetype : public Base + { + typedef typename Base::traversal_category base_trav_cat; + struct traversal_category + : public adjacency_graph_tag, public base_trav_cat { }; + typedef Vertex vertex_descriptor; + typedef unsigned int degree_size_type; + typedef unsigned int vertices_size_type; + typedef unsigned int edges_size_type; + typedef void edge_descriptor; + typedef input_iterator_archetype adjacency_iterator; + + typedef Directed directed_category; + typedef ParallelCategory edge_parallel_category; + + typedef void in_edge_iterator; + typedef void out_edge_iterator; + typedef void vertex_iterator; + typedef void edge_iterator; + }; + + template + std::pair::adjacency_iterator, + typename adjacency_graph_archetype::adjacency_iterator> + adjacent_vertices(const V&, const adjacency_graph_archetype& ) + { + typedef typename adjacency_graph_archetype::adjacency_iterator Iter; + return std::make_pair(Iter(), Iter()); + } + + template + typename adjacency_graph_archetype::degree_size_type + out_degree(const V&, const adjacency_graph_archetype& ) + { + return 0; + } + + //=========================================================================== + template + struct vertex_list_graph_archetype : public Base + { + typedef incidence_graph_archetype + Incidence; + typedef adjacency_graph_archetype + Adjacency; + + typedef typename Base::traversal_category base_trav_cat; + struct traversal_category + : public vertex_list_graph_tag, public base_trav_cat { }; +#if 0 + typedef immutable_graph_tag mutability_category; +#endif + typedef Vertex vertex_descriptor; + typedef unsigned int degree_size_type; + typedef typename Incidence::edge_descriptor edge_descriptor; + typedef typename Incidence::out_edge_iterator out_edge_iterator; + typedef typename Adjacency::adjacency_iterator adjacency_iterator; + + typedef input_iterator_archetype vertex_iterator; + typedef unsigned int vertices_size_type; + typedef unsigned int edges_size_type; + + typedef Directed directed_category; + typedef ParallelCategory edge_parallel_category; + + typedef void in_edge_iterator; + typedef void edge_iterator; + }; + + template + std::pair::vertex_iterator, + typename vertex_list_graph_archetype::vertex_iterator> + vertices(const vertex_list_graph_archetype& ) + { + typedef typename vertex_list_graph_archetype::vertex_iterator Iter; + return std::make_pair(Iter(), Iter()); + } + + template + typename vertex_list_graph_archetype::vertices_size_type + num_vertices(const vertex_list_graph_archetype& ) + { + return 0; + } + + // ambiguously inherited from incidence graph and adjacency graph + template + typename vertex_list_graph_archetype::degree_size_type + out_degree(const V&, const vertex_list_graph_archetype& ) + { + return 0; + } + + //=========================================================================== + + struct property_graph_archetype_tag { }; + + template + struct property_graph_archetype : public GraphArchetype + { + typedef property_graph_archetype_tag graph_tag; + typedef ValueArch vertex_property_type; + typedef ValueArch edge_property_type; + }; + + struct choose_edge_property_map_archetype { + template + struct bind_ { + typedef mutable_lvalue_property_map_archetype + type; + typedef lvalue_property_map_archetype + const_type; + }; + }; + template <> + struct edge_property_selector { + typedef choose_edge_property_map_archetype type; + }; + + struct choose_vertex_property_map_archetype { + template + struct bind_ { + typedef mutable_lvalue_property_map_archetype + type; + typedef lvalue_property_map_archetype + const_type; + }; + }; + + template <> + struct vertex_property_selector { + typedef choose_vertex_property_map_archetype type; + }; + + template + typename property_map, P>::type + get(P, property_graph_archetype&) { + typename property_map, P>::type pmap; + return pmap; + } + + template + typename property_map, P>::const_type + get(P, const property_graph_archetype&) { + typename property_map, P>::const_type pmap; + return pmap; + } + + template + typename property_traits, P>::const_type>::value_type + get(P p, const property_graph_archetype& g, K k) { + return get( get(p, g), k); + } + + template + void + put(P p, property_graph_archetype& g, + const Key& key, const V& value) + { + typedef typename boost::property_map, P>::type Map; + Map pmap = get(p, g); + put(pmap, key, value); + } + + struct color_value_archetype { + color_value_archetype() { } + color_value_archetype(detail::dummy_constructor) { } + bool operator==(const color_value_archetype& ) const { return true; } + bool operator!=(const color_value_archetype& ) const { return true; } + }; + template <> + struct color_traits { + static color_value_archetype white() + { + return color_value_archetype + (static_object::get()); + } + static color_value_archetype gray() + { + return color_value_archetype + (static_object::get()); + } + static color_value_archetype black() + { + return color_value_archetype + (static_object::get()); + } + }; + + template + class buffer_archetype { + public: + void push(const T&) {} + void pop() {} + T& top() { return static_object::get(); } + const T& top() const { return static_object::get(); } + bool empty() const { return true; } + }; + +} // namespace boost + + +#endif // BOOST_GRAPH_ARCHETYPES_HPP diff --git a/win32/include/boost/graph/graph_as_tree.hpp b/win32/include/boost/graph/graph_as_tree.hpp new file mode 100755 index 000000000..f5273b1ff --- /dev/null +++ b/win32/include/boost/graph/graph_as_tree.hpp @@ -0,0 +1,154 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_GRAPH_AS_TREE_HPP +#define BOOST_GRAPH_GRAPH_AS_TREE_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + template + class graph_as_tree_base + { + typedef Derived Tree; + public: + typedef Node node_descriptor; + typedef ChIt children_iterator; + + graph_as_tree_base(Graph& g, Node root) : _g(g), _root(root) { } + + friend Node root(const Tree& t) { return t._root; } + + template + friend std::pair + children(N n, const Tree& t) { return adjacent_vertices(n, t._g); } + + template + friend Node parent(N n, const Tree& t) { + return boost::get(t.parent_pa(), n); + } + + Graph& _g; + Node _root; + }; + + struct graph_as_tree_tag { }; + + template ::vertex_descriptor +#endif + , class ChIt +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + = typename graph_traits::adjacency_iterator +#endif + > + class graph_as_tree + : public graph_as_tree_base > + { + typedef graph_as_tree self; + typedef graph_as_tree_base super; + public: + graph_as_tree(Graph& g, Node root) : super(g, root) { } + + graph_as_tree(Graph& g, Node root, ParentMap p) : super(g, root), _p(p) { + breadth_first_search(g, root, + visitor(make_bfs_visitor + (record_predecessors(p, boost::on_tree_edge())))); + } + ParentMap parent_pa() const { return _p; } + typedef graph_as_tree_tag graph_tag; // for property_map + protected: + ParentMap _p; + }; + + + namespace detail { + + struct graph_as_tree_vertex_property_selector { + template + struct bind_ { + typedef typename GraphAsTree::base_type Graph; + typedef property_map PMap; + typedef typename PMap::type type; + typedef typename PMap::const_type const_type; + }; + }; + + struct graph_as_tree_edge_property_selector { + template + struct bind_ { + typedef typename GraphAsTree::base_type Graph; + typedef property_map PMap; + typedef typename PMap::type type; + typedef typename PMap::const_type const_type; + }; + }; + + } // namespace detail + + template <> + struct vertex_property_selector { + typedef detail::graph_as_tree_vertex_property_selector type; + }; + + template <> + struct edge_property_selector { + typedef detail::graph_as_tree_edge_property_selector type; + }; + + template + typename property_map::type + get(Property p, graph_as_tree& g) + { + return get(p, g._g); + } + + template + typename property_map::const_type + get(Property p, const graph_as_tree& g) + { + const Graph& gref = g._g; // in case GRef is non-const + return get(p, gref); + } + + template + typename property_traits< + typename property_map::const_type + >::value_type + get(Property p, const graph_as_tree& g, const Key& k) + { + return get(p, g._g, k); + } + + template + void + put(Property p, const graph_as_tree& g, const Key& k, + const Value& val) + { + put(p, g._g, k, val); + } + +} // namespace boost + +#endif // BOOST_GRAPH_GRAPH_AS_TREE_HPP diff --git a/win32/include/boost/graph/graph_concepts.hpp b/win32/include/boost/graph/graph_concepts.hpp new file mode 100755 index 000000000..9b3868f40 --- /dev/null +++ b/win32/include/boost/graph/graph_concepts.hpp @@ -0,0 +1,510 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_CONCEPTS_HPP +#define BOOST_GRAPH_CONCEPTS_HPP + +#include +#include +#include +#include +#include +#include + +#include + +namespace boost +{ +// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if +// you want to use vector_as_graph, it is! I'm sure the graph +// library leaves these out all over the place. Probably a +// redesign involving specializing a template with a static +// member function is in order :( +// +// It is needed in order to allow us to write using boost::vertices as +// needed for ADL when using vector_as_graph below. +#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) \ + && !BOOST_WORKAROUND(__GNUC__, <= 2) \ + && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +# define BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK +#endif + +#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK +template +typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&); +#endif + + namespace concepts { + BOOST_concept(MultiPassInputIterator,(T)) { + BOOST_CONCEPT_USAGE(MultiPassInputIterator) { + BOOST_CONCEPT_ASSERT((InputIterator)); + } + }; + + BOOST_concept(Graph,(G)) + { + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::directed_category directed_category; + typedef typename graph_traits::edge_parallel_category + edge_parallel_category; + + typedef typename graph_traits::traversal_category + traversal_category; + + BOOST_CONCEPT_USAGE(Graph) + { + BOOST_CONCEPT_ASSERT((DefaultConstructible)); + BOOST_CONCEPT_ASSERT((EqualityComparable)); + BOOST_CONCEPT_ASSERT((Assignable)); + } + G g; + }; + + BOOST_concept(IncidenceGraph,(G)) + : Graph + { + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename graph_traits::out_edge_iterator + out_edge_iterator; + + typedef typename graph_traits::traversal_category + traversal_category; + + BOOST_CONCEPT_USAGE(IncidenceGraph) { + BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); + BOOST_CONCEPT_ASSERT((DefaultConstructible)); + BOOST_CONCEPT_ASSERT((EqualityComparable)); + BOOST_CONCEPT_ASSERT((Assignable)); + BOOST_CONCEPT_ASSERT((Convertible)); + + p = out_edges(u, g); + n = out_degree(u, g); + e = *p.first; + u = source(e, g); + v = target(e, g); + const_constraints(g); + } + void const_constraints(const G& cg) { + p = out_edges(u, cg); + n = out_degree(u, cg); + e = *p.first; + u = source(e, cg); + v = target(e, cg); + } + std::pair p; + typename graph_traits::vertex_descriptor u, v; + typename graph_traits::edge_descriptor e; + typename graph_traits::degree_size_type n; + G g; + }; + + BOOST_concept(BidirectionalGraph,(G)) + : IncidenceGraph + { + typedef typename graph_traits::in_edge_iterator + in_edge_iterator; + typedef typename graph_traits::traversal_category + traversal_category; + + BOOST_CONCEPT_USAGE(BidirectionalGraph) { + BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); + BOOST_CONCEPT_ASSERT((Convertible)); + + p = in_edges(v, g); + n = in_degree(v, g); + e = *p.first; + const_constraints(g); + } + void const_constraints(const G& cg) { + p = in_edges(v, cg); + n = in_degree(v, cg); + e = *p.first; + } + std::pair p; + typename graph_traits::vertex_descriptor v; + typename graph_traits::edge_descriptor e; + typename graph_traits::degree_size_type n; + G g; + }; + + BOOST_concept(AdjacencyGraph,(G)) + : Graph + { + typedef typename graph_traits::adjacency_iterator + adjacency_iterator; + typedef typename graph_traits::traversal_category + traversal_category; + + BOOST_CONCEPT_USAGE(AdjacencyGraph) { + BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); + BOOST_CONCEPT_ASSERT((Convertible)); + + p = adjacent_vertices(v, g); + v = *p.first; + const_constraints(g); + } + void const_constraints(const G& cg) { + p = adjacent_vertices(v, cg); + } + std::pair p; + typename graph_traits::vertex_descriptor v; + G g; + }; + + BOOST_concept(VertexListGraph,(G)) + : Graph + { + typedef typename graph_traits::vertex_iterator vertex_iterator; + typedef typename graph_traits::vertices_size_type vertices_size_type; + typedef typename graph_traits::traversal_category + traversal_category; + + BOOST_CONCEPT_USAGE(VertexListGraph) { + BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); + BOOST_CONCEPT_ASSERT((Convertible)); + +#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK + // dwa 2003/7/11 -- This clearly shouldn't be necessary, but if + // you want to use vector_as_graph, it is! I'm sure the graph + // library leaves these out all over the place. Probably a + // redesign involving specializing a template with a static + // member function is in order :( + using boost::vertices; +#endif + p = vertices(g); + v = *p.first; + const_constraints(g); + } + void const_constraints(const G& cg) { +#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK + // dwa 2003/7/11 -- This clearly shouldn't be necessary, but if + // you want to use vector_as_graph, it is! I'm sure the graph + // library leaves these out all over the place. Probably a + // redesign involving specializing a template with a static + // member function is in order :( + using boost::vertices; +#endif + + p = vertices(cg); + v = *p.first; + V = num_vertices(cg); + } + std::pair p; + typename graph_traits::vertex_descriptor v; + G g; + vertices_size_type V; + }; + + BOOST_concept(EdgeListGraph,(G)) + : Graph + { + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename graph_traits::edge_iterator edge_iterator; + typedef typename graph_traits::edges_size_type edges_size_type; + typedef typename graph_traits::traversal_category + traversal_category; + + BOOST_CONCEPT_USAGE(EdgeListGraph) { + BOOST_CONCEPT_ASSERT((MultiPassInputIterator)); + BOOST_CONCEPT_ASSERT((DefaultConstructible)); + BOOST_CONCEPT_ASSERT((EqualityComparable)); + BOOST_CONCEPT_ASSERT((Assignable)); + BOOST_CONCEPT_ASSERT((Convertible)); + + p = edges(g); + e = *p.first; + u = source(e, g); + v = target(e, g); + const_constraints(g); + } + void const_constraints(const G& cg) { + p = edges(cg); + E = num_edges(cg); + e = *p.first; + u = source(e, cg); + v = target(e, cg); + } + std::pair p; + typename graph_traits::vertex_descriptor u, v; + typename graph_traits::edge_descriptor e; + edges_size_type E; + G g; + }; + + BOOST_concept(VertexAndEdgeListGraph,(G)) + : VertexListGraph + , EdgeListGraph + { + }; + + // Where to put the requirement for this constructor? + // G g(n_vertices); + // Not in mutable graph, then LEDA graph's can't be models of + // MutableGraph. + + BOOST_concept(EdgeMutableGraph,(G)) + { + typedef typename graph_traits::edge_descriptor edge_descriptor; + + BOOST_CONCEPT_USAGE(EdgeMutableGraph) { + p = add_edge(u, v, g); + remove_edge(u, v, g); + remove_edge(e, g); + clear_vertex(v, g); + } + G g; + edge_descriptor e; + std::pair p; + typename graph_traits::vertex_descriptor u, v; + }; + + BOOST_concept(VertexMutableGraph,(G)) + { + + BOOST_CONCEPT_USAGE(VertexMutableGraph) { + v = add_vertex(g); + remove_vertex(v, g); + } + G g; + typename graph_traits::vertex_descriptor u, v; + }; + + BOOST_concept(MutableGraph,(G)) + : EdgeMutableGraph + , VertexMutableGraph + { + }; + + template + struct dummy_edge_predicate { + bool operator()(const edge_descriptor&) const { + return false; + } + }; + + BOOST_concept(MutableIncidenceGraph,(G)) + : MutableGraph + { + BOOST_CONCEPT_USAGE(MutableIncidenceGraph) { + remove_edge(iter, g); + remove_out_edge_if(u, p, g); + } + G g; + typedef typename graph_traits::edge_descriptor edge_descriptor; + dummy_edge_predicate p; + typename boost::graph_traits::vertex_descriptor u; + typename boost::graph_traits::out_edge_iterator iter; + }; + + BOOST_concept(MutableBidirectionalGraph,(G)) + : MutableIncidenceGraph + { + BOOST_CONCEPT_USAGE(MutableBidirectionalGraph) + { + remove_in_edge_if(u, p, g); + } + G g; + typedef typename graph_traits::edge_descriptor edge_descriptor; + dummy_edge_predicate p; + typename boost::graph_traits::vertex_descriptor u; + }; + + BOOST_concept(MutableEdgeListGraph,(G)) + : EdgeMutableGraph + { + BOOST_CONCEPT_USAGE(MutableEdgeListGraph) { + remove_edge_if(p, g); + } + G g; + typedef typename graph_traits::edge_descriptor edge_descriptor; + dummy_edge_predicate p; + }; + + BOOST_concept(VertexMutablePropertyGraph,(G)) + : VertexMutableGraph + { + BOOST_CONCEPT_USAGE(VertexMutablePropertyGraph) { + v = add_vertex(vp, g); + } + G g; + typename graph_traits::vertex_descriptor v; + typename vertex_property::type vp; + }; + + BOOST_concept(EdgeMutablePropertyGraph,(G)) + : EdgeMutableGraph + { + typedef typename graph_traits::edge_descriptor edge_descriptor; + + BOOST_CONCEPT_USAGE(EdgeMutablePropertyGraph) { + p = add_edge(u, v, ep, g); + } + G g; + std::pair p; + typename graph_traits::vertex_descriptor u, v; + typename edge_property::type ep; + }; + + BOOST_concept(AdjacencyMatrix,(G)) + : Graph + { + typedef typename graph_traits::edge_descriptor edge_descriptor; + + BOOST_CONCEPT_USAGE(AdjacencyMatrix) { + p = edge(u, v, g); + const_constraints(g); + } + void const_constraints(const G& cg) { + p = edge(u, v, cg); + } + typename graph_traits::vertex_descriptor u, v; + std::pair p; + G g; + }; + + BOOST_concept(ReadablePropertyGraph,(G)(X)(Property)) + : Graph + { + typedef typename property_map::const_type const_Map; + + BOOST_CONCEPT_USAGE(ReadablePropertyGraph) + { + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept)); + + const_constraints(g); + } + void const_constraints(const G& cg) { + const_Map pmap = get(Property(), cg); + pval = get(Property(), cg, x); + ignore_unused_variable_warning(pmap); + } + G g; + X x; + typename property_traits::value_type pval; + }; + + BOOST_concept(PropertyGraph,(G)(X)(Property)) + : ReadablePropertyGraph + { + typedef typename property_map::type Map; + BOOST_CONCEPT_USAGE(PropertyGraph) { + BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept)); + + Map pmap = get(Property(), g); + pval = get(Property(), g, x); + put(Property(), g, x, pval); + ignore_unused_variable_warning(pmap); + } + G g; + X x; + typename property_traits::value_type pval; + }; + + BOOST_concept(LvaluePropertyGraph,(G)(X)(Property)) + : ReadablePropertyGraph + { + typedef typename property_map::type Map; + typedef typename property_map::const_type const_Map; + + BOOST_CONCEPT_USAGE(LvaluePropertyGraph) { + BOOST_CONCEPT_ASSERT((LvaluePropertyMapConcept)); + + pval = get(Property(), g, x); + put(Property(), g, x, pval); + } + G g; + X x; + typename property_traits::value_type pval; + }; + + // This needs to move out of the graph library + BOOST_concept(Buffer,(B)) + { + BOOST_CONCEPT_USAGE(Buffer) { + b.push(t); + b.pop(); + typename B::value_type& v = b.top(); + const_constraints(b); + ignore_unused_variable_warning(v); + } + void const_constraints(const B& cb) { + const typename B::value_type& v = cb.top(); + n = cb.size(); + bool e = cb.empty(); + ignore_unused_variable_warning(v); + ignore_unused_variable_warning(e); + } + typename B::size_type n; + typename B::value_type t; + B b; + }; + + BOOST_concept(ColorValue,(C)) + : EqualityComparable + , DefaultConstructible + { + BOOST_CONCEPT_USAGE(ColorValue) { + c = color_traits::white(); + c = color_traits::gray(); + c = color_traits::black(); + } + C c; + }; + + BOOST_concept(BasicMatrix,(M)(I)(V)) + { + BOOST_CONCEPT_USAGE(BasicMatrix) { + V& elt = A[i][j]; + const_constraints(A); + ignore_unused_variable_warning(elt); + } + void const_constraints(const M& cA) { + const V& elt = cA[i][j]; + ignore_unused_variable_warning(elt); + } + M A; + I i, j; + }; + + } // end namespace concepts + + using boost::concepts::MultiPassInputIteratorConcept; + using boost::concepts::GraphConcept; + using boost::concepts::IncidenceGraphConcept; + using boost::concepts::BidirectionalGraphConcept; + using boost::concepts::AdjacencyGraphConcept; + using boost::concepts::VertexListGraphConcept; + using boost::concepts::EdgeListGraphConcept; + using boost::concepts::VertexAndEdgeListGraphConcept; + using boost::concepts::EdgeMutableGraphConcept; + using boost::concepts::VertexMutableGraphConcept; + using boost::concepts::MutableGraphConcept; + using boost::concepts::MutableIncidenceGraphConcept; + using boost::concepts::MutableBidirectionalGraphConcept; + using boost::concepts::MutableEdgeListGraphConcept; + using boost::concepts::VertexMutablePropertyGraphConcept; + using boost::concepts::EdgeMutablePropertyGraphConcept; + using boost::concepts::AdjacencyMatrixConcept; + using boost::concepts::ReadablePropertyGraphConcept; + using boost::concepts::PropertyGraphConcept; + using boost::concepts::LvaluePropertyGraphConcept; + using boost::concepts::BufferConcept; + using boost::concepts::ColorValueConcept; + using boost::concepts::BasicMatrixConcept; +} // namespace boost + +#include + +#endif /* BOOST_GRAPH_CONCEPTS_H */ diff --git a/win32/include/boost/graph/graph_selectors.hpp b/win32/include/boost/graph/graph_selectors.hpp new file mode 100755 index 000000000..aeb7bf936 --- /dev/null +++ b/win32/include/boost/graph/graph_selectors.hpp @@ -0,0 +1,38 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_SELECTORS_HPP +#define BOOST_GRAPH_SELECTORS_HPP + +#include + +namespace boost { + + //=========================================================================== + // Selectors for the Directed template parameter of adjacency_list + // and adjacency_matrix. + + struct directedS { enum { is_directed = true, is_bidir = false }; + typedef mpl::true_ is_directed_t; + typedef mpl::false_ is_bidir_t; + }; + struct undirectedS { + enum { is_directed = false, is_bidir = false }; + typedef mpl::false_ is_directed_t; + typedef mpl::false_ is_bidir_t; + }; + struct bidirectionalS { + enum { is_directed = true, is_bidir = true }; + typedef mpl::true_ is_directed_t; + typedef mpl::true_ is_bidir_t; + }; + +} // namespace boost + +#endif // BOOST_GRAPH_SELECTORS_HPP diff --git a/win32/include/boost/graph/graph_test.hpp b/win32/include/boost/graph/graph_test.hpp new file mode 100755 index 000000000..3dc2a6485 --- /dev/null +++ b/win32/include/boost/graph/graph_test.hpp @@ -0,0 +1,382 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_TEST_HPP +#define BOOST_GRAPH_TEST_HPP + +#include +#include +#include +#include +#include +#include +#include // for connects + + +// UNDER CONSTRUCTION + +namespace boost { + + template + struct graph_test + { + + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::edge_descriptor edge_t; + typedef typename graph_traits::vertices_size_type v_size_t; + typedef typename graph_traits::degree_size_type deg_size_t; + typedef typename graph_traits::edges_size_type e_size_t; + typedef typename graph_traits::out_edge_iterator out_edge_iter; + typedef typename property_map::type index_map_t; + typedef iterator_property_map::iterator, + index_map_t,vertex_t,vertex_t&> IsoMap; + + struct ignore_vertex { + ignore_vertex() { } + ignore_vertex(vertex_t v) : v(v) { } + bool operator()(vertex_t x) const { return x != v; } + vertex_t v; + }; + struct ignore_edge { + ignore_edge() { } + ignore_edge(edge_t e) : e(e) { } + bool operator()(edge_t x) const { return x != e; } + edge_t e; + }; + struct ignore_edges { + ignore_edges(vertex_t s, vertex_t t, const Graph& g) + : s(s), t(t), g(g) { } + bool operator()(edge_t x) const { + return !(source(x, g) == s && target(x, g) == t); + } + vertex_t s; vertex_t t; const Graph& g; + }; + + //========================================================================= + // Traversal Operations + + void test_incidence_graph + (const std::vector& vertex_set, + const std::vector< std::pair >& edge_set, + const Graph& g) + { + typedef typename std::vector::const_iterator vertex_iter; + typedef typename std::vector< std::pair > + ::const_iterator edge_iter; + typedef typename graph_traits::out_edge_iterator out_edge_iter; + + for (vertex_iter ui = vertex_set.begin(); ui != vertex_set.end(); ++ui) { + vertex_t u = *ui; + std::vector adj; + for (edge_iter e = edge_set.begin(); e != edge_set.end(); ++e) + if (e->first == u) + adj.push_back(e->second); + + std::pair p = out_edges(u, g); + BOOST_CHECK(out_degree(u, g) == adj.size()); + BOOST_CHECK(deg_size_t(std::distance(p.first, p.second)) + == out_degree(u, g)); + for (; p.first != p.second; ++p.first) { + edge_t e = *p.first; + BOOST_CHECK(source(e, g) == u); + BOOST_CHECK(container_contains(adj, target(e, g)) == true); + } + } + } + + void test_bidirectional_graph + (const std::vector& vertex_set, + const std::vector< std::pair >& edge_set, + const Graph& g) + { + typedef typename std::vector::const_iterator vertex_iter; + typedef typename std::vector< std::pair > + ::const_iterator edge_iter; + typedef typename graph_traits::in_edge_iterator in_edge_iter; + + for (vertex_iter vi = vertex_set.begin(); vi != vertex_set.end(); ++vi) { + vertex_t v = *vi; + std::vector inv_adj; + for (edge_iter e = edge_set.begin(); e != edge_set.end(); ++e) + if (e->second == v) + inv_adj.push_back(e->first); + + std::pair p = in_edges(v, g); + BOOST_CHECK(in_degree(v, g) == inv_adj.size()); + BOOST_CHECK(deg_size_t(std::distance(p.first, p.second)) + == in_degree(v, g)); + for (; p.first != p.second; ++p.first) { + edge_t e = *p.first; + BOOST_CHECK(target(e, g) == v); + BOOST_CHECK(container_contains(inv_adj, source(e, g)) == true); + } + } + } + + void test_adjacency_graph + (const std::vector& vertex_set, + const std::vector< std::pair >& edge_set, + const Graph& g) + { + typedef typename std::vector::const_iterator vertex_iter; + typedef typename std::vector > + ::const_iterator edge_iter; + typedef typename graph_traits::adjacency_iterator adj_iter; + + for (vertex_iter ui = vertex_set.begin(); ui != vertex_set.end(); ++ui) { + vertex_t u = *ui; + std::vector adj; + for (edge_iter e = edge_set.begin(); e != edge_set.end(); ++e) + if (e->first == u) + adj.push_back(e->second); + + std::pair p = adjacent_vertices(u, g); + BOOST_CHECK(deg_size_t(std::distance(p.first, p.second)) == adj.size()); + for (; p.first != p.second; ++p.first) { + vertex_t v = *p.first; + BOOST_CHECK(container_contains(adj, v) == true); + } + } + } + + void test_vertex_list_graph + (const std::vector& vertex_set, const Graph& g) + { + typedef typename graph_traits::vertex_iterator v_iter; + std::pair p = vertices(g); + BOOST_CHECK(num_vertices(g) == vertex_set.size()); + v_size_t n = std::distance(p.first, p.second); + BOOST_CHECK(n == num_vertices(g)); + for (; p.first != p.second; ++p.first) { + vertex_t v = *p.first; + BOOST_CHECK(container_contains(vertex_set, v) == true); + } + } + + void test_edge_list_graph + (const std::vector& vertex_set, + const std::vector< std::pair >& edge_set, + const Graph& g) + { + typedef typename graph_traits::edge_iterator e_iter; + std::pair p = edges(g); + BOOST_CHECK(num_edges(g) == edge_set.size()); + e_size_t m = std::distance(p.first, p.second); + BOOST_CHECK(m == num_edges(g)); + for (; p.first != p.second; ++p.first) { + edge_t e = *p.first; + BOOST_CHECK(any_if(edge_set, connects(source(e, g), target(e, g), g))); + BOOST_CHECK(container_contains(vertex_set, source(e, g)) == true); + BOOST_CHECK(container_contains(vertex_set, target(e, g)) == true); + } + } + + void test_adjacency_matrix + (const std::vector& vertex_set, + const std::vector< std::pair >& edge_set, + const Graph& g) + { + std::pair p; + for (typename std::vector > + ::const_iterator i = edge_set.begin(); + i != edge_set.end(); ++i) { + p = edge(i->first, i->second, g); + BOOST_CHECK(p.second == true); + BOOST_CHECK(source(p.first, g) == i->first); + BOOST_CHECK(target(p.first, g) == i->second); + } + typename std::vector::const_iterator j, k; + for (j = vertex_set.begin(); j != vertex_set.end(); ++j) + for (k = vertex_set.begin(); k != vertex_set.end(); ++k) { + p = edge(*j, *k, g); + if (p.second == true) + BOOST_CHECK(any_if(edge_set, + connects(source(p.first, g), target(p.first, g), g)) == true); + } + } + + //========================================================================= + // Mutating Operations + + void test_add_vertex(Graph& g) + { + Graph cpy; + std::vector iso_vec(num_vertices(g)); + IsoMap iso_map(iso_vec.begin(), get(vertex_index, g)); + copy_graph(g, cpy, orig_to_copy(iso_map)); + + assert((verify_isomorphism(g, cpy, iso_map))); + + vertex_t v = add_vertex(g); + + BOOST_CHECK(num_vertices(g) == num_vertices(cpy) + 1); + + BOOST_CHECK(out_degree(v, g) == 0); + + // Make sure the rest of the graph stayed the same + BOOST_CHECK((verify_isomorphism + (make_filtered_graph(g, keep_all(), ignore_vertex(v)), cpy, + iso_map))); + } + + void test_add_edge(vertex_t u, vertex_t v, Graph& g) + { + Graph cpy; + std::vector iso_vec(num_vertices(g)); + IsoMap iso_map(iso_vec.begin(), get(vertex_index, g)); + copy_graph(g, cpy, orig_to_copy(iso_map)); + + bool parallel_edge_exists = container_contains(adjacent_vertices(u, g), v); + + std::pair p = add_edge(u, v, g); + edge_t e = p.first; + bool added = p.second; + + if (is_undirected(g) && u == v) // self edge + BOOST_CHECK(added == false); + else if (parallel_edge_exists) + BOOST_CHECK(allows_parallel_edges(g) && added == true + || !allows_parallel_edges(g) && added == false); + else + BOOST_CHECK(added == true); + + if (p.second == true) { // edge added + BOOST_CHECK(num_edges(g) == num_edges(cpy) + 1); + + BOOST_CHECK(container_contains(out_edges(u, g), e) == true); + + BOOST_CHECK((verify_isomorphism + (make_filtered_graph(g, ignore_edge(e)), cpy, iso_map))); + } + else { // edge not added + if (! (is_undirected(g) && u == v)) { + // e should be a parallel edge + BOOST_CHECK(source(e, g) == u); + BOOST_CHECK(target(e, g) == v); + } + // The graph should not be changed. + BOOST_CHECK((verify_isomorphism(g, cpy, iso_map))); + } + } // test_add_edge() + + + void test_remove_edge(vertex_t u, vertex_t v, Graph& g) + { + Graph cpy; + std::vector iso_vec(num_vertices(g)); + IsoMap iso_map(iso_vec.begin(), get(vertex_index, g)); + copy_graph(g, cpy, orig_to_copy(iso_map)); + + deg_size_t occurances = count(adjacent_vertices(u, g), v); + + remove_edge(u, v, g); + + BOOST_CHECK(num_edges(g) + occurances == num_edges(cpy)); + BOOST_CHECK((verify_isomorphism + (g, make_filtered_graph(cpy, ignore_edges(u,v,cpy)), + iso_map))); + } + + void test_remove_edge(edge_t e, Graph& g) + { + Graph cpy; + std::vector iso_vec(num_vertices(g)); + IsoMap iso_map(iso_vec.begin(), get(vertex_index, g)); + copy_graph(g, cpy, orig_to_copy(iso_map)); + + vertex_t u = source(e, g), v = target(e, g); + deg_size_t occurances = count(adjacent_vertices(u, g), v); + + remove_edge(e, g); + + BOOST_CHECK(num_edges(g) + 1 == num_edges(cpy)); + BOOST_CHECK(count(adjacent_vertices(u, g), v) + 1 == occurances); + BOOST_CHECK((verify_isomorphism + (g, make_filtered_graph(cpy, ignore_edge(e)), + iso_map))); + } + + void test_clear_vertex(vertex_t v, Graph& g) + { + Graph cpy; + std::vector iso_vec(num_vertices(g)); + IsoMap iso_map(iso_vec.begin(), get(vertex_index, g)); + copy_graph(g, cpy, orig_to_copy(iso_map)); + + clear_vertex(v, g); + + BOOST_CHECK(out_degree(v, g) == 0); + BOOST_CHECK(num_vertices(g) == num_vertices(cpy)); + BOOST_CHECK((verify_isomorphism + (g, make_filtered_graph(cpy, keep_all(), ignore_vertex(v)), + iso_map))); + } + + //========================================================================= + // Property Map + + template + void test_readable_vertex_property_graph + (const std::vector& vertex_prop, PropertyTag, const Graph& g) + { + typedef typename property_map::const_type const_Map; + const_Map pmap = get(PropertyTag(), g); + typename std::vector::const_iterator i = vertex_prop.begin(); + + for (typename boost::graph_traits::vertex_iterator + bgl_first_9 = vertices(g).first, bgl_last_9 = vertices(g).second; + bgl_first_9 != bgl_last_9; bgl_first_9 = bgl_last_9) + for (typename boost::graph_traits::vertex_descriptor v; + bgl_first_9 != bgl_last_9 ? (v = *bgl_first_9, true) : false; + ++bgl_first_9) { + //BGL_FORALL_VERTICES_T(v, g, Graph) { + typename property_traits::value_type + pval1 = get(pmap, v), pval2 = get(PropertyTag(), g, v); + BOOST_CHECK(pval1 == pval2); + BOOST_CHECK(pval1 == *i++); + } + } + + template + void test_vertex_property_graph + (const std::vector& vertex_prop, PropertyTag tag, Graph& g) + { + typedef typename property_map::type PMap; + PMap pmap = get(PropertyTag(), g); + typename std::vector::const_iterator i = vertex_prop.begin(); + for (typename boost::graph_traits::vertex_iterator + bgl_first_9 = vertices(g).first, bgl_last_9 = vertices(g).second; + bgl_first_9 != bgl_last_9; bgl_first_9 = bgl_last_9) + for (typename boost::graph_traits::vertex_descriptor v; + bgl_first_9 != bgl_last_9 ? (v = *bgl_first_9, true) : false; + ++bgl_first_9) + // BGL_FORALL_VERTICES_T(v, g, Graph) + put(pmap, v, *i++); + + test_readable_vertex_property_graph(vertex_prop, tag, g); + + BGL_FORALL_VERTICES_T(v, g, Graph) + put(pmap, v, vertex_prop[0]); + + typename std::vector::const_iterator j = vertex_prop.begin(); + BGL_FORALL_VERTICES_T(v, g, Graph) + put(PropertyTag(), g, v, *j++); + + test_readable_vertex_property_graph(vertex_prop, tag, g); + } + + + }; + + +} // namespace boost + +#include + +#endif // BOOST_GRAPH_TEST_HPP diff --git a/win32/include/boost/graph/graph_traits.hpp b/win32/include/boost/graph/graph_traits.hpp new file mode 100755 index 000000000..8854fc0c8 --- /dev/null +++ b/win32/include/boost/graph/graph_traits.hpp @@ -0,0 +1,168 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_TRAITS_HPP +#define BOOST_GRAPH_TRAITS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + template + struct graph_traits { + typedef typename G::vertex_descriptor vertex_descriptor; + typedef typename G::edge_descriptor edge_descriptor; + typedef typename G::adjacency_iterator adjacency_iterator; + typedef typename G::out_edge_iterator out_edge_iterator; + typedef typename G::in_edge_iterator in_edge_iterator; + typedef typename G::vertex_iterator vertex_iterator; + typedef typename G::edge_iterator edge_iterator; + + typedef typename G::directed_category directed_category; + typedef typename G::edge_parallel_category edge_parallel_category; + typedef typename G::traversal_category traversal_category; + + typedef typename G::vertices_size_type vertices_size_type; + typedef typename G::edges_size_type edges_size_type; + typedef typename G::degree_size_type degree_size_type; + + static inline vertex_descriptor null_vertex(); + }; + + template + inline typename graph_traits::vertex_descriptor + graph_traits::null_vertex() + { + return G::null_vertex(); + } + + // directed_category tags + struct directed_tag { }; + struct undirected_tag { }; + struct bidirectional_tag : public directed_tag { }; + + namespace detail { + inline bool is_directed(directed_tag) { return true; } + inline bool is_directed(undirected_tag) { return false; } + } + + template + bool is_directed(const Graph&) { + typedef typename graph_traits::directed_category Cat; + return detail::is_directed(Cat()); + } + template + bool is_undirected(const Graph& g) { + return ! is_directed(g); + } + + // edge_parallel_category tags + struct allow_parallel_edge_tag {}; + struct disallow_parallel_edge_tag {}; + + namespace detail { + inline bool allows_parallel(allow_parallel_edge_tag) { return true; } + inline bool allows_parallel(disallow_parallel_edge_tag) { return false; } + } + + template + bool allows_parallel_edges(const Graph&) { + typedef typename graph_traits::edge_parallel_category Cat; + return detail::allows_parallel(Cat()); + } + + // traversal_category tags + struct incidence_graph_tag { }; + struct adjacency_graph_tag { }; + struct bidirectional_graph_tag : + public virtual incidence_graph_tag { }; + struct vertex_list_graph_tag { }; + struct edge_list_graph_tag { }; + struct adjacency_matrix_tag { }; + + //?? not the right place ?? Lee + typedef boost::forward_traversal_tag multi_pass_input_iterator_tag; + + template + struct edge_property_type { + typedef typename G::edge_property_type type; + }; + template + struct vertex_property_type { + typedef typename G::vertex_property_type type; + }; + template + struct graph_property_type { + typedef typename G::graph_property_type type; + }; + + struct no_vertex_bundle {}; + struct no_edge_bundle {}; + + template + struct vertex_bundle_type + { + typedef typename G::vertex_bundled type; + }; + + template + struct edge_bundle_type + { + typedef typename G::edge_bundled type; + }; + + namespace graph { namespace detail { + template + class bundled_result + { + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename mpl::if_c<(is_same::value), + vertex_bundle_type, + edge_bundle_type >::type bundler; + + public: + typedef typename bundler::type type; + }; + } } // end namespace graph::detail +} // namespace boost + +// Since pair is in namespace std, Koenig lookup will find source and +// target if they are also defined in namespace std. This is illegal, +// but the alternative is to put source and target in the global +// namespace which causes name conflicts with other libraries (like +// SUIF). +namespace std { + + /* Some helper functions for dealing with pairs as edges */ + template + T source(pair p, const G&) { return p.first; } + + template + T target(pair p, const G&) { return p.second; } + +} + +#if defined(__GNUC__) && defined(__SGI_STL_PORT) +// For some reason g++ with STLport does not see the above definition +// of source() and target() unless we bring them into the boost +// namespace. +namespace boost { + using std::source; + using std::target; +} +#endif + +#endif // BOOST_GRAPH_TRAITS_HPP diff --git a/win32/include/boost/graph/graph_utility.hpp b/win32/include/boost/graph/graph_utility.hpp new file mode 100755 index 000000000..5095ba796 --- /dev/null +++ b/win32/include/boost/graph/graph_utility.hpp @@ -0,0 +1,425 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_UTILITY_HPP +#define BOOST_GRAPH_UTILITY_HPP + +#include +#include +#include +#include +#include +#include + +#if !defined BOOST_NO_SLIST +# ifdef BOOST_SLIST_HEADER +# include BOOST_SLIST_HEADER +# else +# include +# endif +#endif + +#include +#include +#include +#include +// iota moved to detail/algorithm.hpp +#include + +namespace boost { + + // Provide an undirected graph interface alternative to the + // the source() and target() edge functions. + template + inline + std::pair::vertex_descriptor, + typename graph_traits::vertex_descriptor> + incident(typename graph_traits::edge_descriptor e, + UndirectedGraph& g) + { + return std::make_pair(source(e,g), target(e,g)); + } + + // Provide an undirected graph interface alternative + // to the out_edges() function. + template + inline + std::pair::out_edge_iterator, + typename graph_traits::out_edge_iterator> + incident_edges(typename graph_traits::vertex_descriptor u, + Graph& g) + { + return out_edges(u, g); + } + + template + inline typename graph_traits::vertex_descriptor + opposite(typename graph_traits::edge_descriptor e, + typename graph_traits::vertex_descriptor v, + const Graph& g) + { + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + if (v == source(e, g)) + return target(e, g); + else if (v == target(e, g)) + return source(e, g); + else + return vertex_descriptor(); + } + + //=========================================================================== + // Some handy predicates + + template + struct incident_from_predicate { + incident_from_predicate(Vertex u, const Graph& g) + : m_u(u), m_g(g) { } + template + bool operator()(const Edge& e) const { + return source(e, m_g) == m_u; + } + Vertex m_u; + const Graph& m_g; + }; + template + inline incident_from_predicate + incident_from(Vertex u, const Graph& g) { + return incident_from_predicate(u, g); + } + + template + struct incident_to_predicate { + incident_to_predicate(Vertex u, const Graph& g) + : m_u(u), m_g(g) { } + template + bool operator()(const Edge& e) const { + return target(e, m_g) == m_u; + } + Vertex m_u; + const Graph& m_g; + }; + template + inline incident_to_predicate + incident_to(Vertex u, const Graph& g) { + return incident_to_predicate(u, g); + } + + template + struct incident_on_predicate { + incident_on_predicate(Vertex u, const Graph& g) + : m_u(u), m_g(g) { } + template + bool operator()(const Edge& e) const { + return source(e, m_g) == m_u || target(e, m_g) == m_u; + } + Vertex m_u; + const Graph& m_g; + }; + template + inline incident_on_predicate + incident_on(Vertex u, const Graph& g) { + return incident_on_predicate(u, g); + } + + template + struct connects_predicate { + connects_predicate(Vertex u, Vertex v, const Graph& g) + : m_u(u), m_v(v), m_g(g) { } + template + bool operator()(const Edge& e) const { + if (is_directed(m_g)) + return source(e, m_g) == m_u && target(e, m_g) == m_v; + else + return (source(e, m_g) == m_u && target(e, m_g) == m_v) + || (source(e, m_g) == m_v && target(e, m_g) == m_u); + } + Vertex m_u, m_v; + const Graph& m_g; + }; + template + inline connects_predicate + connects(Vertex u, Vertex v, const Graph& g) { + return connects_predicate(u, v, g); + } + + + // Need to convert all of these printing functions to take an ostream object + // -JGS + + template + void print_in_edges(const IncidenceGraph& G, Name name) + { + typename graph_traits::vertex_iterator ui,ui_end; + for (tie(ui,ui_end) = vertices(G); ui != ui_end; ++ui) { + std::cout << get(name,*ui) << " <-- "; + typename graph_traits + ::in_edge_iterator ei, ei_end; + for(tie(ei,ei_end) = in_edges(*ui,G); ei != ei_end; ++ei) + std::cout << get(name,source(*ei,G)) << " "; + std::cout << std::endl; + } + } + + template + void print_graph_dispatch(const IncidenceGraph& G, Name name, directed_tag) + { + typename graph_traits::vertex_iterator ui,ui_end; + for (tie(ui,ui_end) = vertices(G); ui != ui_end; ++ui) { + std::cout << get(name,*ui) << " --> "; + typename graph_traits + ::out_edge_iterator ei, ei_end; + for(tie(ei,ei_end) = out_edges(*ui,G); ei != ei_end; ++ei) + std::cout << get(name,target(*ei,G)) << " "; + std::cout << std::endl; + } + } + template + void print_graph_dispatch(const IncidenceGraph& G, Name name, undirected_tag) + { + typename graph_traits::vertex_iterator ui,ui_end; + for (tie(ui,ui_end) = vertices(G); ui != ui_end; ++ui) { + std::cout << get(name,*ui) << " <--> "; + typename graph_traits + ::out_edge_iterator ei, ei_end; + for(tie(ei,ei_end) = out_edges(*ui,G); ei != ei_end; ++ei) + std::cout << get(name,target(*ei,G)) << " "; + std::cout << std::endl; + } + } + template + void print_graph(const IncidenceGraph& G, Name name) + { + typedef typename graph_traits + ::directed_category Cat; + print_graph_dispatch(G, name, Cat()); + } + template + void print_graph(const IncidenceGraph& G) { + print_graph(G, get(vertex_index, G)); + } + + template + void print_edges(const EdgeListGraph& G, Name name) + { + typename graph_traits::edge_iterator ei, ei_end; + for (tie(ei, ei_end) = edges(G); ei != ei_end; ++ei) + std::cout << "(" << get(name, source(*ei, G)) + << "," << get(name, target(*ei, G)) << ") "; + std::cout << std::endl; + } + + template + void print_edges2(const EdgeListGraph& G, VertexName vname, EdgeName ename) + { + typename graph_traits::edge_iterator ei, ei_end; + for (tie(ei, ei_end) = edges(G); ei != ei_end; ++ei) + std::cout << get(ename, *ei) << "(" << get(vname, source(*ei, G)) + << "," << get(vname, target(*ei, G)) << ") "; + std::cout << std::endl; + } + + template + void print_vertices(const VertexListGraph& G, Name name) + { + typename graph_traits::vertex_iterator vi,vi_end; + for (tie(vi,vi_end) = vertices(G); vi != vi_end; ++vi) + std::cout << get(name,*vi) << " "; + std::cout << std::endl; + } + + template + bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, bidirectional_tag) + { + typedef typename graph_traits::edge_descriptor + edge_descriptor; + typename graph_traits::adjacency_iterator vi, viend, + adj_found; + tie(vi, viend) = adjacent_vertices(a, g); + adj_found = std::find(vi, viend, b); + if (adj_found == viend) + return false; + + typename graph_traits::out_edge_iterator oi, oiend, + out_found; + tie(oi, oiend) = out_edges(a, g); + out_found = std::find_if(oi, oiend, incident_to(b, g)); + if (out_found == oiend) + return false; + + typename graph_traits::in_edge_iterator ii, iiend, + in_found; + tie(ii, iiend) = in_edges(b, g); + in_found = std::find_if(ii, iiend, incident_from(a, g)); + if (in_found == iiend) + return false; + + return true; + } + template + bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, directed_tag) + { + typedef typename graph_traits::edge_descriptor + edge_descriptor; + typename graph_traits::adjacency_iterator vi, viend, found; + tie(vi, viend) = adjacent_vertices(a, g); +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && defined(__SGI_STL_PORT) + // Getting internal compiler error with std::find() + found = viend; + for (; vi != viend; ++vi) + if (*vi == b) { + found = vi; + break; + } +#else + found = std::find(vi, viend, b); +#endif + if ( found == viend ) + return false; + + typename graph_traits::out_edge_iterator oi, oiend, + out_found; + tie(oi, oiend) = out_edges(a, g); + +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && defined(__SGI_STL_PORT) + // Getting internal compiler error with std::find() + out_found = oiend; + for (; oi != oiend; ++oi) + if (target(*oi, g) == b) { + out_found = oi; + break; + } +#else + out_found = std::find_if(oi, oiend, incident_to(b, g)); +#endif + if (out_found == oiend) + return false; + return true; + } + template + bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, undirected_tag) + { + return is_adj_dispatch(g, a, b, directed_tag()); + } + + template + bool is_adjacent(Graph& g, Vertex a, Vertex b) { + typedef typename graph_traits::directed_category Cat; + return is_adj_dispatch(g, a, b, Cat()); + } + + template + bool in_edge_set(Graph& g, Edge e) + { + typename Graph::edge_iterator ei, ei_end, found; + tie(ei, ei_end) = edges(g); + found = std::find(ei, ei_end, e); + return found != ei_end; + } + + template + bool in_vertex_set(Graph& g, Vertex v) + { + typename Graph::vertex_iterator vi, vi_end, found; + tie(vi, vi_end) = vertices(g); + found = std::find(vi, vi_end, v); + return found != vi_end; + } + + template + bool in_edge_set(Graph& g, Vertex u, Vertex v) + { + typename Graph::edge_iterator ei, ei_end; + for (tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) + if (source(*ei,g) == u && target(*ei,g) == v) + return true; + return false; + } + + // is x a descendant of y? + template + inline bool is_descendant + (typename property_traits::value_type x, + typename property_traits::value_type y, + ParentMap parent) + { + if (get(parent, x) == x) // x is the root of the tree + return false; + else if (get(parent, x) == y) + return true; + else + return is_descendant(get(parent, x), y, parent); + } + + // is y reachable from x? + template + inline bool is_reachable + (typename graph_traits::vertex_descriptor x, + typename graph_traits::vertex_descriptor y, + const IncidenceGraph& g, + VertexColorMap color) // should start out white for every vertex + { + typedef typename property_traits::value_type ColorValue; + dfs_visitor<> vis; + depth_first_visit(g, x, vis, color); + return get(color, y) != color_traits::white(); + } + + // Is the undirected graph connected? + // Is the directed graph strongly connected? + template + inline bool is_connected(const VertexListGraph& g, VertexColorMap color) + { + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + typename graph_traits::vertex_iterator + ui, ui_end, vi, vi_end, ci, ci_end; + for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) + for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + if (*ui != *vi) { + for (tie(ci, ci_end) = vertices(g); ci != ci_end; ++ci) + put(color, *ci, Color::white()); + if (! is_reachable(*ui, *vi, g, color)) + return false; + } + return true; + } + + template + bool is_self_loop + (typename graph_traits::edge_descriptor e, + const Graph& g) + { + return source(e, g) == target(e, g); + } + + + template + std::pair + make_list(const T1& t1, const T2& t2) + { return std::make_pair(t1, t2); } + + template + std::pair > + make_list(const T1& t1, const T2& t2, const T3& t3) + { return std::make_pair(t1, std::make_pair(t2, t3)); } + + template + std::pair > > + make_list(const T1& t1, const T2& t2, const T3& t3, const T4& t4) + { return std::make_pair(t1, std::make_pair(t2, std::make_pair(t3, t4))); } + + template + std::pair > > > + make_list(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) + { return std::make_pair(t1, std::make_pair(t2, std::make_pair(t3, std::make_pair(t4, t5)))); } + +} /* namespace boost */ + +#endif /* BOOST_GRAPH_UTILITY_HPP*/ diff --git a/win32/include/boost/graph/graphml.hpp b/win32/include/boost/graph/graphml.hpp new file mode 100755 index 000000000..eac1c8c5b --- /dev/null +++ b/win32/include/boost/graph/graphml.hpp @@ -0,0 +1,332 @@ +// Copyright (C) 2006 Tiago de Paula Peixoto +// Copyright (C) 2004 The Trustees of Indiana University. +// +// Use, modification and distribution is subject to 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) +// +// Authors: Douglas Gregor +// Andrew Lumsdaine +// Tiago de Paula Peixoto + +#ifndef BOOST_GRAPH_GRAPHML_HPP +#define BOOST_GRAPH_GRAPHML_HPP + +#include +#include +#include +#include +#include // for exceptions +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + +///////////////////////////////////////////////////////////////////////////// +// Graph reader exceptions +///////////////////////////////////////////////////////////////////////////// +struct parse_error: public graph_exception +{ + parse_error(const std::string& error) {statement = "parse error: " + error;} + virtual ~parse_error() throw() {} + virtual const char* what() const throw() {return statement.c_str();} + std::string statement; +}; + + +class mutate_graph +{ +public: + virtual ~mutate_graph() {} + virtual bool is_directed() const = 0; + + virtual boost::any do_add_vertex() = 0; + virtual std::pair do_add_edge(boost::any source, boost::any target) = 0; + + virtual void + set_graph_property(const std::string& name, const std::string& value, const std::string& value_type) = 0; + + virtual void + set_vertex_property(const std::string& name, boost::any vertex, const std::string& value, const std::string& value_type) = 0; + + virtual void + set_edge_property(const std::string& name, boost::any edge, const std::string& value, const std::string& value_type) = 0; +}; + +template +class mutate_graph_impl : public mutate_graph +{ + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::edge_descriptor edge_descriptor; + + public: + mutate_graph_impl(MutableGraph& g, dynamic_properties& dp) + : m_g(g), m_dp(dp) { } + + bool is_directed() const + { + return is_convertible::directed_category, + directed_tag>::value; + } + + virtual any do_add_vertex() + { + return any(add_vertex(m_g)); + } + + virtual std::pair do_add_edge(any source, any target) + { + std::pair retval = add_edge(any_cast(source), + any_cast(target), m_g); + return std::make_pair(any(retval.first), retval.second); + } + + virtual void + set_graph_property(const std::string& name, const std::string& value, const std::string& value_type) + { + bool type_found = false; + try + { + mpl::for_each(put_property + (name, m_dp, m_g, value, value_type, m_type_names, type_found)); + } + catch (bad_lexical_cast) + { + throw parse_error("invalid value \"" + value + "\" for key " + + name + " of type " + value_type); + } + if (!type_found) + throw parse_error("unrecognized type \"" + value_type + + "\" for key " + name); + + } + + virtual void + set_vertex_property(const std::string& name, any vertex, const std::string& value, const std::string& value_type) + { + bool type_found = false; + try + { + mpl::for_each(put_property + (name, m_dp, any_cast(vertex), + value, value_type, m_type_names, type_found)); + } + catch (bad_lexical_cast) + { + throw parse_error("invalid value \"" + value + "\" for key " + + name + " of type " + value_type); + } + if (!type_found) + throw parse_error("unrecognized type \"" + value_type + + "\" for key " + name); + + } + + virtual void + set_edge_property(const std::string& name, any edge, const std::string& value, const std::string& value_type) + { + bool type_found = false; + try + { + mpl::for_each(put_property + (name, m_dp, any_cast(edge), + value, value_type, m_type_names, type_found)); + } + catch (bad_lexical_cast) + { + throw parse_error("invalid value \"" + value + "\" for key " + + name + " of type " + value_type); + } + if (!type_found) + throw parse_error("unrecognized type \"" + value_type + + "\" for key " + name); + } + + template + class put_property + { + public: + put_property(const std::string& name, dynamic_properties& dp, const Key& key, + const std::string& value, const std::string& value_type, + char** type_names, bool& type_found) + : m_name(name), m_dp(dp), m_key(key), m_value(value), + m_value_type(value_type), m_type_names(type_names), + m_type_found(type_found) {} + template + void operator()(Value) + { + if (m_value_type == m_type_names[mpl::find::type::pos::value]) + { + put(m_name, m_dp, m_key, lexical_cast(m_value)); + m_type_found = true; + } + } + private: + const std::string& m_name; + dynamic_properties& m_dp; + const Key& m_key; + const std::string& m_value; + const std::string& m_value_type; + char** m_type_names; + bool& m_type_found; + }; + +protected: + MutableGraph& m_g; + dynamic_properties& m_dp; + typedef mpl::vector value_types; + static char* m_type_names[]; +}; + +template +char* mutate_graph_impl::m_type_names[] = {"boolean", "int", "long", "float", "double", "string"}; + +void +read_graphml(std::istream& in, mutate_graph& g); + +template +void +read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp) +{ + mutate_graph_impl mg(g,dp); + read_graphml(in, mg); +} + +template +class get_type_name +{ +public: + get_type_name(const std::type_info& type, char** type_names, std::string& type_name) + : m_type(type), m_type_names(type_names), m_type_name(type_name) {} + template + void operator()(Type) + { + if (typeid(Type) == m_type) + m_type_name = m_type_names[mpl::find::type::pos::value]; + } +private: + const std::type_info &m_type; + char** m_type_names; + std::string &m_type_name; +}; + + +template +void +write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, + const dynamic_properties& dp, bool ordered_vertices=false) +{ + typedef typename graph_traits::directed_category directed_category; + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + + BOOST_STATIC_CONSTANT(bool, + graph_is_directed = + (is_convertible::value)); + + out << "\n" + << "\n"; + + typedef mpl::vector value_types; + char* type_names[] = {"boolean", "int", "int", "int", "int", "long", "long", "long", "long", "float", "double", "double", "string"}; + std::map graph_key_ids; + std::map vertex_key_ids; + std::map edge_key_ids; + int key_count = 0; + + // Output keys + for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i) + { + std::string key_id = "key" + lexical_cast(key_count++); + if (i->second->key() == typeid(Graph)) + vertex_key_ids[i->first] = key_id; + else if (i->second->key() == typeid(vertex_descriptor)) + vertex_key_ids[i->first] = key_id; + else if (i->second->key() == typeid(edge_descriptor)) + edge_key_ids[i->first] = key_id; + else + continue; + std::string type_name = "string"; + mpl::for_each(get_type_name(i->second->value(), type_names, type_name)); + out << " second->key() == typeid(Graph) ? "graph" : (i->second->key() == typeid(vertex_descriptor) ? "node" : "edge")) << "\"" + << " attr.name=\"" << i->first << "\"" + << " attr.type=\"" << type_name << "\"" + << " />\n"; + } + + out << " \n"; + + // Output graph data + for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i) + { + if (i->second->key() == typeid(Graph)) + { + out << " first] << "\">" + << i->second->get_string(g) << "\n"; + } + } + + typedef typename graph_traits::vertex_iterator vertex_iterator; + vertex_iterator v, v_end; + for (tie(v, v_end) = vertices(g); v != v_end; ++v) + { + out << " \n"; + // Output data + for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i) + { + if (i->second->key() == typeid(vertex_descriptor)) + { + out << " first] << "\">" + << i->second->get_string(*v) << "\n"; + } + } + out << " \n"; + } + + typedef typename graph_traits::edge_iterator edge_iterator; + edge_iterator e, e_end; + typename graph_traits::edges_size_type edge_count = 0; + for (tie(e, e_end) = edges(g); e != e_end; ++e) + { + out << " \n"; + + // Output data + for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i) + { + if (i->second->key() == typeid(edge_descriptor)) + { + out << " first] << "\">" + << i->second->get_string(*e) << "\n"; + } + } + out << " \n"; + } + + out << " \n" + << "\n"; +} + + +template +void +write_graphml(std::ostream& out, const Graph& g, const dynamic_properties& dp, + bool ordered_vertices=false) +{ + write_graphml(out, g, get(vertex_index, g), dp, ordered_vertices); +} + +} // boost namespace + +#endif // BOOST_GRAPH_GRAPHML_HPP diff --git a/win32/include/boost/graph/graphviz.hpp b/win32/include/boost/graph/graphviz.hpp new file mode 100755 index 000000000..5c260ef71 --- /dev/null +++ b/win32/include/boost/graph/graphviz.hpp @@ -0,0 +1,783 @@ +//======================================================================= +// Copyright 2001 University of Notre Dame. +// Copyright 2003 Jeremy Siek +// Authors: Lie-Quan Lee and Jeremy Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPHVIZ_HPP +#define BOOST_GRAPHVIZ_HPP + +#include +#include +#include +#include +#include +#include // for FILE +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_DECLSPEC +# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_GRAPH_DYN_LINK) +# ifdef BOOST_GRAPH_SOURCE +# define BOOST_GRAPH_DECL __declspec(dllexport) +# else +# define BOOST_GRAPH_DECL __declspec(dllimport) +# endif // BOOST_GRAPH_SOURCE +# endif // DYN_LINK +#endif // BOOST_HAS_DECLSPEC + +#ifndef BOOST_GRAPH_DECL +# define BOOST_GRAPH_DECL +#endif + +namespace boost { + + template + struct graphviz_io_traits { + static std::string name() { + return "digraph"; + } + static std::string delimiter() { + return "->"; + } }; + + template <> + struct graphviz_io_traits { + static std::string name() { + return "graph"; + } + static std::string delimiter() { + return "--"; + } + }; + + struct default_writer { + void operator()(std::ostream&) const { + } + template + void operator()(std::ostream&, const VorE&) const { + } + }; + + template + class label_writer { + public: + label_writer(Name _name) : name(_name) {} + template + void operator()(std::ostream& out, const VertexOrEdge& v) const { + out << "[label=\"" << get(name, v) << "\"]"; + } + private: + Name name; + }; + template + inline label_writer + make_label_writer(Name n) { + return label_writer(n); + } + + enum edge_attribute_t { edge_attribute = 1111 }; + enum vertex_attribute_t { vertex_attribute = 2222 }; + enum graph_graph_attribute_t { graph_graph_attribute = 3333 }; + enum graph_vertex_attribute_t { graph_vertex_attribute = 4444 }; + enum graph_edge_attribute_t { graph_edge_attribute = 5555 }; + + BOOST_INSTALL_PROPERTY(edge, attribute); + BOOST_INSTALL_PROPERTY(vertex, attribute); + BOOST_INSTALL_PROPERTY(graph, graph_attribute); + BOOST_INSTALL_PROPERTY(graph, vertex_attribute); + BOOST_INSTALL_PROPERTY(graph, edge_attribute); + + + template + inline void write_attributes(const Attribute& attr, std::ostream& out) { + typename Attribute::const_iterator i, iend; + i = attr.begin(); + iend = attr.end(); + + while ( i != iend ) { + out << i->first << "=\"" << i->second << "\""; + ++i; + if ( i != iend ) + out << ", "; + } + } + + template + inline void write_all_attributes(Attributes attributes, + const std::string& name, + std::ostream& out) + { + typename Attributes::const_iterator i = attributes.begin(), + end = attributes.end(); + if (i != end) { + out << name << " [\n"; + write_attributes(attributes, out); + out << "];\n"; + } + } + + inline void write_all_attributes(detail::error_property_not_found, + const std::string&, + std::ostream&) + { + // Do nothing - no attributes exist + } + + + + + template + struct graph_attributes_writer + { + graph_attributes_writer(GraphGraphAttributes gg, + GraphNodeAttributes gn, + GraphEdgeAttributes ge) + : g_attributes(gg), n_attributes(gn), e_attributes(ge) { } + + void operator()(std::ostream& out) const { + write_all_attributes(g_attributes, "graph", out); + write_all_attributes(n_attributes, "node", out); + write_all_attributes(e_attributes, "edge", out); + } + GraphGraphAttributes g_attributes; + GraphNodeAttributes n_attributes; + GraphEdgeAttributes e_attributes; + }; + + template + graph_attributes_writer + make_graph_attributes_writer(const GAttrMap& g_attr, const NAttrMap& n_attr, + const EAttrMap& e_attr) { + return graph_attributes_writer + (g_attr, n_attr, e_attr); + } + + + template + graph_attributes_writer + ::type, + typename graph_property::type, + typename graph_property::type> + make_graph_attributes_writer(const Graph& g) + { + typedef typename graph_property::type + GAttrMap; + typedef typename graph_property::type + NAttrMap; + typedef typename graph_property::type + EAttrMap; + GAttrMap gam = get_property(g, graph_graph_attribute); + NAttrMap nam = get_property(g, graph_vertex_attribute); + EAttrMap eam = get_property(g, graph_edge_attribute); + graph_attributes_writer writer(gam, nam, eam); + return writer; + } + + template + struct attributes_writer { + attributes_writer(AttributeMap attr) + : attributes(attr) { } + + template + void operator()(std::ostream& out, const VorE& e) const { + this->write_attribute(out, attributes[e]); + } + + private: + template + void write_attribute(std::ostream& out, + const AttributeSequence& seq) const + { + if (!seq.empty()) { + out << "["; + write_attributes(seq, out); + out << "]"; + } + } + + void write_attribute(std::ostream&, + detail::error_property_not_found) const + { + } + AttributeMap attributes; + }; + + template + attributes_writer + ::const_type> + make_edge_attributes_writer(const Graph& g) + { + typedef typename property_map::const_type + EdgeAttributeMap; + return attributes_writer(get(edge_attribute, g)); + } + + template + attributes_writer + ::const_type> + make_vertex_attributes_writer(const Graph& g) + { + typedef typename property_map::const_type + VertexAttributeMap; + return attributes_writer(get(vertex_attribute, g)); + } + + template + inline void write_graphviz(std::ostream& out, const Graph& g, + VertexPropertiesWriter vpw, + EdgePropertiesWriter epw, + GraphPropertiesWriter gpw, + VertexID vertex_id) + { + typedef typename graph_traits::directed_category cat_type; + typedef graphviz_io_traits Traits; + std::string name = "G"; + out << Traits::name() << " " << name << " {" << std::endl; + + gpw(out); //print graph properties + + typename graph_traits::vertex_iterator i, end; + + for(tie(i,end) = vertices(g); i != end; ++i) { + out << get(vertex_id, *i); + vpw(out, *i); //print vertex attributes + out << ";" << std::endl; + } + typename graph_traits::edge_iterator ei, edge_end; + for(tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) { + out << get(vertex_id, source(*ei, g)) << Traits::delimiter() << get(vertex_id, target(*ei, g)) << " "; + epw(out, *ei); //print edge attributes + out << ";" << std::endl; + } + out << "}" << std::endl; + } + + template + inline void write_graphviz(std::ostream& out, const Graph& g, + VertexPropertiesWriter vpw, + EdgePropertiesWriter epw, + GraphPropertiesWriter gpw) + { write_graphviz(out, g, vpw, epw, gpw, get(vertex_index, g)); } + +#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 + // ambiguous overload problem with VC++ + template + inline void + write_graphviz(std::ostream& out, const Graph& g) { + default_writer dw; + default_writer gw; + write_graphviz(out, g, dw, dw, gw); + } +#endif + + template + inline void + write_graphviz(std::ostream& out, const Graph& g, VertexWriter vw) { + default_writer dw; + default_writer gw; + write_graphviz(out, g, vw, dw, gw); + } + + template + inline void + write_graphviz(std::ostream& out, const Graph& g, + VertexWriter vw, EdgeWriter ew) { + default_writer gw; + write_graphviz(out, g, vw, ew, gw); + } + + namespace detail { + + template + void write_graphviz_subgraph (std::ostream& out, + const subgraph& g, + RandomAccessIterator vertex_marker, + RandomAccessIterator edge_marker, + VertexID vertex_id) + { + typedef subgraph Graph; + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::directed_category cat_type; + typedef graphviz_io_traits Traits; + + typedef typename graph_property::type NameType; + const NameType& g_name = get_property(g, graph_name); + + if ( g.is_root() ) + out << Traits::name() ; + else + out << "subgraph"; + + out << " " << g_name << " {" << std::endl; + + typename Graph::const_children_iterator i_child, j_child; + + //print graph/node/edge attributes +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 + typedef typename graph_property::type + GAttrMap; + typedef typename graph_property::type + NAttrMap; + typedef typename graph_property::type + EAttrMap; + GAttrMap gam = get_property(g, graph_graph_attribute); + NAttrMap nam = get_property(g, graph_vertex_attribute); + EAttrMap eam = get_property(g, graph_edge_attribute); + graph_attributes_writer writer(gam, nam, eam); + writer(out); +#else + make_graph_attributes_writer(g)(out); +#endif + + //print subgraph + for ( tie(i_child,j_child) = g.children(); + i_child != j_child; ++i_child ) + write_graphviz_subgraph(out, *i_child, vertex_marker, edge_marker, + vertex_id); + + // Print out vertices and edges not in the subgraphs. + + typename graph_traits::vertex_iterator i, end; + typename graph_traits::edge_iterator ei, edge_end; + + for(tie(i,end) = vertices(g); i != end; ++i) { + Vertex v = g.local_to_global(*i); + int pos = get(vertex_id, v); + if ( vertex_marker[pos] ) { + vertex_marker[pos] = false; + out << pos; +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 + typedef typename property_map::const_type + VertexAttributeMap; + attributes_writer vawriter(get(vertex_attribute, + g.root())); + vawriter(out, v); +#else + make_vertex_attributes_writer(g.root())(out, v); +#endif + out << ";" << std::endl; + } + } + + for (tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) { + Vertex u = g.local_to_global(source(*ei,g)), + v = g.local_to_global(target(*ei, g)); + int pos = get(get(edge_index, g.root()), g.local_to_global(*ei)); + if ( edge_marker[pos] ) { + edge_marker[pos] = false; + out << get(vertex_id, u) << " " << Traits::delimiter() + << " " << get(vertex_id, v); +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 + typedef typename property_map::const_type + EdgeAttributeMap; + attributes_writer eawriter(get(edge_attribute, g)); + eawriter(out, *ei); +#else + make_edge_attributes_writer(g)(out, *ei); //print edge properties +#endif + out << ";" << std::endl; + } + } + out << "}" << std::endl; + } + } // namespace detail + + // requires graph_name graph property + template + void write_graphviz(std::ostream& out, const subgraph& g) { + std::vector edge_marker(num_edges(g), true); + std::vector vertex_marker(num_vertices(g), true); + + detail::write_graphviz_subgraph(out, g, + vertex_marker.begin(), + edge_marker.begin(), + get(vertex_index, g)); + } + + template + void write_graphviz(const std::string& filename, const subgraph& g) { + std::ofstream out(filename.c_str()); + std::vector edge_marker(num_edges(g), true); + std::vector vertex_marker(num_vertices(g), true); + + detail::write_graphviz_subgraph(out, g, + vertex_marker.begin(), + edge_marker.begin(), + get(vertex_index, g)); + } + + template + void write_graphviz(std::ostream& out, const subgraph& g, + VertexID vertex_id) + { + std::vector edge_marker(num_edges(g), true); + std::vector vertex_marker(num_vertices(g), true); + + detail::write_graphviz_subgraph(out, g, + vertex_marker.begin(), + edge_marker.begin(), + vertex_id); + } + + template + void write_graphviz(const std::string& filename, const subgraph& g, + VertexID vertex_id) + { + std::ofstream out(filename.c_str()); + std::vector edge_marker(num_edges(g), true); + std::vector vertex_marker(num_vertices(g), true); + + detail::write_graphviz_subgraph(out, g, + vertex_marker.begin(), + edge_marker.begin(), + vertex_id); + } + + typedef std::map GraphvizAttrList; + + typedef property + GraphvizVertexProperty; + + typedef property > + GraphvizEdgeProperty; + + typedef property > > > + GraphvizGraphProperty; + + typedef subgraph > + GraphvizDigraph; + + typedef subgraph > + GraphvizGraph; + + + // These four require linking the BGL-Graphviz library: libbgl-viz.a + // from the /src directory. + extern void read_graphviz(const std::string& file, GraphvizDigraph& g); + extern void read_graphviz(FILE* file, GraphvizDigraph& g); + + extern void read_graphviz(const std::string& file, GraphvizGraph& g); + extern void read_graphviz(FILE* file, GraphvizGraph& g); + + class dynamic_properties_writer + { + public: + dynamic_properties_writer(const dynamic_properties& dp) : dp(&dp) { } + + template + void operator()(std::ostream& out, Descriptor key) const + { + bool first = true; + for (dynamic_properties::const_iterator i = dp->begin(); + i != dp->end(); ++i) { + if (typeid(key) == i->second->key()) { + if (first) out << " ["; + else out << ", "; + first = false; + + out << i->first << "=\"" << i->second->get_string(key) << "\""; + } + } + + if (!first) out << "]"; + } + + private: + const dynamic_properties* dp; + }; + + class dynamic_vertex_properties_writer + { + public: + dynamic_vertex_properties_writer(const dynamic_properties& dp, + const std::string& node_id) + : dp(&dp), node_id(&node_id) { } + + template + void operator()(std::ostream& out, Descriptor key) const + { + bool first = true; + for (dynamic_properties::const_iterator i = dp->begin(); + i != dp->end(); ++i) { + if (typeid(key) == i->second->key() + && i->first != *node_id) { + if (first) out << " ["; + else out << ", "; + first = false; + + out << i->first << "=\"" << i->second->get_string(key) << "\""; + } + } + + if (!first) out << "]"; + } + + private: + const dynamic_properties* dp; + const std::string* node_id; + }; + + namespace graph { namespace detail { + + template + struct node_id_property_map + { + typedef std::string value_type; + typedef value_type reference; + typedef Vertex key_type; + typedef readable_property_map_tag category; + + node_id_property_map() {} + + node_id_property_map(const dynamic_properties& dp, + const std::string& node_id) + : dp(&dp), node_id(&node_id) { } + + const dynamic_properties* dp; + const std::string* node_id; + }; + + template + inline std::string + get(node_id_property_map pm, + typename node_id_property_map::key_type v) + { return get(*pm.node_id, *pm.dp, v); } + + } } // end namespace graph::detail + + template + inline void + write_graphviz(std::ostream& out, const Graph& g, + const dynamic_properties& dp, + const std::string& node_id = "node_id") + { + typedef typename graph_traits::vertex_descriptor Vertex; + write_graphviz(out, g, dp, node_id, + graph::detail::node_id_property_map(dp, node_id)); + } + + template + void + write_graphviz(std::ostream& out, const Graph& g, + const dynamic_properties& dp, const std::string& node_id, + VertexID id) + { + write_graphviz + (out, g, + /*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id), + /*edge_writer=*/dynamic_properties_writer(dp), + /*graph_writer=*/default_writer(), + id); + } + +///////////////////////////////////////////////////////////////////////////// +// Graph reader exceptions +///////////////////////////////////////////////////////////////////////////// +struct graph_exception : public std::exception { + virtual ~graph_exception() throw() {} + virtual const char* what() const throw() = 0; +}; + +struct bad_parallel_edge : public graph_exception { + std::string from; + std::string to; + mutable std::string statement; + bad_parallel_edge(const std::string& i, const std::string& j) : + from(i), to(j) {} + + virtual ~bad_parallel_edge() throw() {} + const char* what() const throw() { + if(statement.empty()) + statement = + std::string("Failed to add parallel edge: (") + + from + "," + to + ")\n"; + + return statement.c_str(); + } +}; + +struct directed_graph_error : public graph_exception { + virtual ~directed_graph_error() throw() {} + virtual const char* what() const throw() { + return + "read_graphviz: " + "Tried to read a directed graph into an undirected graph."; + } +}; + +struct undirected_graph_error : public graph_exception { + virtual ~undirected_graph_error() throw() {} + virtual const char* what() const throw() { + return + "read_graphviz: " + "Tried to read an undirected graph into a directed graph."; + } +}; + +namespace detail { namespace graph { + +typedef std::string id_t; +typedef id_t node_t; + +// edges are not uniquely determined by adjacent nodes +class edge_t { + int idx_; + explicit edge_t(int i) : idx_(i) {} +public: + static edge_t new_edge() { + static int idx = 0; + return edge_t(idx++); + }; + + bool operator==(const edge_t& rhs) const { + return idx_ == rhs.idx_; + } + bool operator<(const edge_t& rhs) const { + return idx_ < rhs.idx_; + } +}; + +class mutate_graph +{ + public: + virtual ~mutate_graph() {} + virtual bool is_directed() const = 0; + virtual void do_add_vertex(const node_t& node) = 0; + + virtual void + do_add_edge(const edge_t& edge, const node_t& source, const node_t& target) + = 0; + + virtual void + set_node_property(const id_t& key, const node_t& node, const id_t& value) = 0; + + virtual void + set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) = 0; + + virtual void // RG: need new second parameter to support BGL subgraphs + set_graph_property(const id_t& key, const id_t& value) = 0; +}; + +template +class mutate_graph_impl : public mutate_graph +{ + typedef typename graph_traits::vertex_descriptor bgl_vertex_t; + typedef typename graph_traits::edge_descriptor bgl_edge_t; + + public: + mutate_graph_impl(MutableGraph& graph, dynamic_properties& dp, + std::string node_id_prop) + : graph_(graph), dp_(dp), node_id_prop_(node_id_prop) { } + + ~mutate_graph_impl() {} + + bool is_directed() const + { + return + boost::is_convertible< + typename boost::graph_traits::directed_category, + boost::directed_tag>::value; + } + + virtual void do_add_vertex(const node_t& node) + { + // Add the node to the graph. + bgl_vertex_t v = add_vertex(graph_); + + // Set up a mapping from name to BGL vertex. + bgl_nodes.insert(std::make_pair(node, v)); + + // node_id_prop_ allows the caller to see the real id names for nodes. + put(node_id_prop_, dp_, v, node); + } + + void + do_add_edge(const edge_t& edge, const node_t& source, const node_t& target) + { + std::pair result = + add_edge(bgl_nodes[source], bgl_nodes[target], graph_); + + if(!result.second) { + // In the case of no parallel edges allowed + throw bad_parallel_edge(source, target); + } else { + bgl_edges.insert(std::make_pair(edge, result.first)); + } + } + + void + set_node_property(const id_t& key, const node_t& node, const id_t& value) + { + put(key, dp_, bgl_nodes[node], value); + } + + void + set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) + { + put(key, dp_, bgl_edges[edge], value); + } + + void + set_graph_property(const id_t& key, const id_t& value) + { + /* RG: pointer to graph prevents copying */ + put(key, dp_, &graph_, value); + } + + + protected: + MutableGraph& graph_; + dynamic_properties& dp_; + std::string node_id_prop_; + std::map bgl_nodes; + std::map bgl_edges; +}; + +BOOST_GRAPH_DECL +bool read_graphviz(std::istream& in, mutate_graph& graph); + +} } // end namespace detail::graph + +// Parse the passed stream as a GraphViz dot file. +template +bool read_graphviz(std::istream& in, MutableGraph& graph, + dynamic_properties& dp, + std::string const& node_id = "node_id") +{ + detail::graph::mutate_graph_impl m_graph(graph, dp, node_id); + return detail::graph::read_graphviz(in, m_graph); +} + +} // namespace boost + +#ifdef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS +# include +#endif // BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS + +#endif // BOOST_GRAPHVIZ_HPP diff --git a/win32/include/boost/graph/gursoy_atun_layout.hpp b/win32/include/boost/graph/gursoy_atun_layout.hpp new file mode 100755 index 000000000..c9048cec8 --- /dev/null +++ b/win32/include/boost/graph/gursoy_atun_layout.hpp @@ -0,0 +1,631 @@ +// Copyright 2004 The Trustees of Indiana University. + +// 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) + +// Authors: Jeremiah Willcock +// Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP +#define BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP + +// Gursoy-Atun graph layout, based on: +// "Neighbourhood Preserving Load Balancing: A Self-Organizing Approach" +// in EuroPar 2000, p. 234 of LNCS 1900 +// http://springerlink.metapress.com/link.asp?id=pcu07ew5rhexp9yt + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + +namespace detail { + +struct over_distance_limit : public std::exception {}; + +template +struct update_position_visitor { + typedef typename Topology::point_type Point; + PositionMap position_map; + NodeDistanceMap node_distance; + const Topology& space; + Point input_vector; + double distance_limit; + double learning_constant; + double falloff_ratio; + + typedef boost::on_examine_vertex event_filter; + + typedef typename graph_traits::vertex_descriptor + vertex_descriptor; + + update_position_visitor(PositionMap position_map, + NodeDistanceMap node_distance, + const Topology& space, + const Point& input_vector, + double distance_limit, + double learning_constant, + double falloff_ratio): + position_map(position_map), node_distance(node_distance), + space(space), + input_vector(input_vector), distance_limit(distance_limit), + learning_constant(learning_constant), falloff_ratio(falloff_ratio) {} + + void operator()(vertex_descriptor v, const Graph&) const + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::pow; +#endif + + if (get(node_distance, v) > distance_limit) + throw over_distance_limit(); + Point old_position = get(position_map, v); + double distance = get(node_distance, v); + double fraction = + learning_constant * pow(falloff_ratio, distance * distance); + put(position_map, v, + space.move_position_toward(old_position, fraction, input_vector)); + } +}; + +template +struct gursoy_shortest +{ + template + static inline void + run(const Graph& g, typename graph_traits::vertex_descriptor s, + NodeDistanceMap node_distance, UpdatePosition& update_position, + EdgeWeightMap weight) + { + boost::dijkstra_shortest_paths(g, s, weight_map(weight). + visitor(boost::make_dijkstra_visitor(std::make_pair( + boost::record_distances(node_distance, boost::on_edge_relaxed()), + update_position)))); + } +}; + +template<> +struct gursoy_shortest +{ + template + static inline void + run(const Graph& g, typename graph_traits::vertex_descriptor s, + NodeDistanceMap node_distance, UpdatePosition& update_position, + dummy_property_map) + { + boost::breadth_first_search(g, s, + visitor(boost::make_bfs_visitor(std::make_pair( + boost::record_distances(node_distance, boost::on_tree_edge()), + update_position)))); + } +}; + +} // namespace detail + +template +void +gursoy_atun_step + (const VertexListAndIncidenceGraph& graph, + const Topology& space, + PositionMap position, + Diameter diameter, + double learning_constant, + VertexIndexMap vertex_index_map, + EdgeWeightMap weight) +{ +#ifndef BOOST_NO_STDC_NAMESPACE + using std::pow; + using std::exp; +#endif + + typedef typename graph_traits::vertex_iterator + vertex_iterator; + typedef typename graph_traits::vertex_descriptor + vertex_descriptor; + typedef typename Topology::point_type point_type; + vertex_iterator i, iend; + std::vector distance_from_input_vector(num_vertices(graph)); + typedef boost::iterator_property_map::iterator, + VertexIndexMap, + double, double&> + DistanceFromInputMap; + DistanceFromInputMap distance_from_input(distance_from_input_vector.begin(), + vertex_index_map); + std::vector node_distance_map_vector(num_vertices(graph)); + typedef boost::iterator_property_map::iterator, + VertexIndexMap, + double, double&> + NodeDistanceMap; + NodeDistanceMap node_distance(node_distance_map_vector.begin(), + vertex_index_map); + point_type input_vector = space.random_point(); + vertex_descriptor min_distance_loc + = graph_traits::null_vertex(); + double min_distance = 0.0; + bool min_distance_unset = true; + for (boost::tie(i, iend) = vertices(graph); i != iend; ++i) { + double this_distance = space.distance(get(position, *i), input_vector); + put(distance_from_input, *i, this_distance); + if (min_distance_unset || this_distance < min_distance) { + min_distance = this_distance; + min_distance_loc = *i; + } + min_distance_unset = false; + } + assert (!min_distance_unset); // Graph must have at least one vertex + boost::detail::update_position_visitor< + PositionMap, NodeDistanceMap, Topology, + VertexListAndIncidenceGraph> + update_position(position, node_distance, space, + input_vector, diameter, learning_constant, + exp(-1. / (2 * diameter * diameter))); + std::fill(node_distance_map_vector.begin(), node_distance_map_vector.end(), 0); + try { + typedef detail::gursoy_shortest shortest; + shortest::run(graph, min_distance_loc, node_distance, update_position, + weight); + } catch (detail::over_distance_limit) { + /* Thrown to break out of BFS or Dijkstra early */ + } +} + +template +void gursoy_atun_refine(const VertexListAndIncidenceGraph& graph, + const Topology& space, + PositionMap position, + int nsteps, + double diameter_initial, + double diameter_final, + double learning_constant_initial, + double learning_constant_final, + VertexIndexMap vertex_index_map, + EdgeWeightMap weight) +{ +#ifndef BOOST_NO_STDC_NAMESPACE + using std::pow; + using std::exp; +#endif + + typedef typename graph_traits::vertex_iterator + vertex_iterator; + typedef typename graph_traits::vertex_descriptor + vertex_descriptor; + typedef typename Topology::point_type point_type; + vertex_iterator i, iend; + double diameter_ratio = (double)diameter_final / diameter_initial; + double learning_constant_ratio = + learning_constant_final / learning_constant_initial; + std::vector distance_from_input_vector(num_vertices(graph)); + typedef boost::iterator_property_map::iterator, + VertexIndexMap, + double, double&> + DistanceFromInputMap; + DistanceFromInputMap distance_from_input(distance_from_input_vector.begin(), + vertex_index_map); + std::vector node_distance_map_vector(num_vertices(graph)); + typedef boost::iterator_property_map::iterator, + VertexIndexMap, double, double&> + NodeDistanceMap; + NodeDistanceMap node_distance(node_distance_map_vector.begin(), + vertex_index_map); + for (int round = 0; round < nsteps; ++round) { + double part_done = (double)round / (nsteps - 1); + int diameter = (int)(diameter_initial * pow(diameter_ratio, part_done)); + double learning_constant = + learning_constant_initial * pow(learning_constant_ratio, part_done); + gursoy_atun_step(graph, space, position, diameter, learning_constant, + vertex_index_map, weight); + } +} + +template +void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, + const Topology& space, + PositionMap position, + int nsteps, + double diameter_initial, + double diameter_final, + double learning_constant_initial, + double learning_constant_final, + VertexIndexMap vertex_index_map, + EdgeWeightMap weight) +{ + typedef typename graph_traits::vertex_iterator + vertex_iterator; + vertex_iterator i, iend; + for (boost::tie(i, iend) = vertices(graph); i != iend; ++i) { + put(position, *i, space.random_point()); + } + gursoy_atun_refine(graph, space, + position, nsteps, + diameter_initial, diameter_final, + learning_constant_initial, learning_constant_final, + vertex_index_map, weight); +} + +template +void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, + const Topology& space, + PositionMap position, + int nsteps, + double diameter_initial, + double diameter_final, + double learning_constant_initial, + double learning_constant_final, + VertexIndexMap vertex_index_map) +{ + gursoy_atun_layout(graph, space, position, nsteps, + diameter_initial, diameter_final, + learning_constant_initial, learning_constant_final, + vertex_index_map, dummy_property_map()); +} + +template +void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, + const Topology& space, + PositionMap position, + int nsteps, + double diameter_initial, + double diameter_final = 1.0, + double learning_constant_initial = 0.8, + double learning_constant_final = 0.2) +{ + gursoy_atun_layout(graph, space, position, nsteps, diameter_initial, + diameter_final, learning_constant_initial, + learning_constant_final, get(vertex_index, graph)); +} + +template +void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, + const Topology& space, + PositionMap position, + int nsteps) +{ +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif + + gursoy_atun_layout(graph, space, position, nsteps, + sqrt((double)num_vertices(graph))); +} + +template +void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, + const Topology& space, + PositionMap position) +{ + gursoy_atun_layout(graph, space, position, num_vertices(graph)); +} + +template +void +gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, + const Topology& space, + PositionMap position, + const bgl_named_params& params) +{ +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif + + std::pair diam(sqrt(double(num_vertices(graph))), 1.0); + std::pair learn(0.8, 0.2); + gursoy_atun_layout(graph, space, position, + choose_param(get_param(params, iterations_t()), + num_vertices(graph)), + choose_param(get_param(params, diameter_range_t()), + diam).first, + choose_param(get_param(params, diameter_range_t()), + diam).second, + choose_param(get_param(params, learning_constant_range_t()), + learn).first, + choose_param(get_param(params, learning_constant_range_t()), + learn).second, + choose_const_pmap(get_param(params, vertex_index), graph, + vertex_index), + choose_param(get_param(params, edge_weight), + dummy_property_map())); +} + +/*********************************************************** + * Topologies * + ***********************************************************/ +template +class convex_topology +{ + struct point + { + point() { } + double& operator[](std::size_t i) {return values[i];} + const double& operator[](std::size_t i) const {return values[i];} + + private: + double values[Dims]; + }; + + public: + typedef point point_type; + + double distance(point a, point b) const + { + double dist = 0; + for (std::size_t i = 0; i < Dims; ++i) { + double diff = b[i] - a[i]; + dist += diff * diff; + } + // Exact properties of the distance are not important, as long as + // < on what this returns matches real distances + return dist; + } + + point move_position_toward(point a, double fraction, point b) const + { + point result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] + (b[i] - a[i]) * fraction; + return result; + } +}; + +template +class hypercube_topology : public convex_topology +{ + typedef uniform_01 rand_t; + + public: + typedef typename convex_topology::point_type point_type; + + explicit hypercube_topology(double scaling = 1.0) + : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)), + scaling(scaling) + { } + + hypercube_topology(RandomNumberGenerator& gen, double scaling = 1.0) + : gen_ptr(), rand(new rand_t(gen)), scaling(scaling) { } + + point_type random_point() const + { + point_type p; + for (std::size_t i = 0; i < Dims; ++i) + p[i] = (*rand)() * scaling; + return p; + } + + private: + shared_ptr gen_ptr; + shared_ptr rand; + double scaling; +}; + +template +class square_topology : public hypercube_topology<2, RandomNumberGenerator> +{ + typedef hypercube_topology<2, RandomNumberGenerator> inherited; + + public: + explicit square_topology(double scaling = 1.0) : inherited(scaling) { } + + square_topology(RandomNumberGenerator& gen, double scaling = 1.0) + : inherited(gen, scaling) { } +}; + +template +class cube_topology : public hypercube_topology<3, RandomNumberGenerator> +{ + typedef hypercube_topology<3, RandomNumberGenerator> inherited; + + public: + explicit cube_topology(double scaling = 1.0) : inherited(scaling) { } + + cube_topology(RandomNumberGenerator& gen, double scaling = 1.0) + : inherited(gen, scaling) { } +}; + +template +class ball_topology : public convex_topology +{ + typedef uniform_01 rand_t; + + public: + typedef typename convex_topology::point_type point_type; + + explicit ball_topology(double radius = 1.0) + : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)), + radius(radius) + { } + + ball_topology(RandomNumberGenerator& gen, double radius = 1.0) + : gen_ptr(), rand(new rand_t(gen)), radius(radius) { } + + point_type random_point() const + { + point_type p; + double dist_sum; + do { + dist_sum = 0.0; + for (std::size_t i = 0; i < Dims; ++i) { + double x = (*rand)() * 2*radius - radius; + p[i] = x; + dist_sum += x * x; + } + } while (dist_sum > radius*radius); + return p; + } + + private: + shared_ptr gen_ptr; + shared_ptr rand; + double radius; +}; + +template +class circle_topology : public ball_topology<2, RandomNumberGenerator> +{ + typedef ball_topology<2, RandomNumberGenerator> inherited; + + public: + explicit circle_topology(double radius = 1.0) : inherited(radius) { } + + circle_topology(RandomNumberGenerator& gen, double radius = 1.0) + : inherited(gen, radius) { } +}; + +template +class sphere_topology : public ball_topology<3, RandomNumberGenerator> +{ + typedef ball_topology<3, RandomNumberGenerator> inherited; + + public: + explicit sphere_topology(double radius = 1.0) : inherited(radius) { } + + sphere_topology(RandomNumberGenerator& gen, double radius = 1.0) + : inherited(gen, radius) { } +}; + +template +class heart_topology +{ + // Heart is defined as the union of three shapes: + // Square w/ corners (+-1000, -1000), (0, 0), (0, -2000) + // Circle centered at (-500, -500) radius 500*sqrt(2) + // Circle centered at (500, -500) radius 500*sqrt(2) + // Bounding box (-1000, -2000) - (1000, 500*(sqrt(2) - 1)) + + struct point + { + point() { values[0] = 0.0; values[1] = 0.0; } + point(double x, double y) { values[0] = x; values[1] = y; } + + double& operator[](std::size_t i) { return values[i]; } + double operator[](std::size_t i) const { return values[i]; } + + private: + double values[2]; + }; + + bool in_heart(point p) const + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::abs; + using std::pow; +#endif + + if (p[1] < abs(p[0]) - 2000) return false; // Bottom + if (p[1] <= -1000) return true; // Diagonal of square + if (pow(p[0] - -500, 2) + pow(p[1] - -500, 2) <= 500000) + return true; // Left circle + if (pow(p[0] - 500, 2) + pow(p[1] - -500, 2) <= 500000) + return true; // Right circle + return false; + } + + bool segment_within_heart(point p1, point p2) const + { + // Assumes that p1 and p2 are within the heart + if ((p1[0] < 0) == (p2[0] < 0)) return true; // Same side of symmetry line + if (p1[0] == p2[0]) return true; // Vertical + double slope = (p2[1] - p1[1]) / (p2[0] - p1[0]); + double intercept = p1[1] - p1[0] * slope; + if (intercept > 0) return false; // Crosses between circles + return true; + } + + typedef uniform_01 rand_t; + + public: + typedef point point_type; + + heart_topology() + : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)) { } + + heart_topology(RandomNumberGenerator& gen) + : gen_ptr(), rand(new rand_t(gen)) { } + + point random_point() const + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif + + point result; + double sqrt2 = sqrt(2.); + do { + result[0] = (*rand)() * (1000 + 1000 * sqrt2) - (500 + 500 * sqrt2); + result[1] = (*rand)() * (2000 + 500 * (sqrt2 - 1)) - 2000; + } while (!in_heart(result)); + return result; + } + + double distance(point a, point b) const + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif + if (segment_within_heart(a, b)) { + // Straight line + return sqrt((b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1])); + } else { + // Straight line bending around (0, 0) + return sqrt(a[0] * a[0] + a[1] * a[1]) + sqrt(b[0] * b[0] + b[1] * b[1]); + } + } + + point move_position_toward(point a, double fraction, point b) const + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif + + if (segment_within_heart(a, b)) { + // Straight line + return point(a[0] + (b[0] - a[0]) * fraction, + a[1] + (b[1] - a[1]) * fraction); + } else { + double distance_to_point_a = sqrt(a[0] * a[0] + a[1] * a[1]); + double distance_to_point_b = sqrt(b[0] * b[0] + b[1] * b[1]); + double location_of_point = distance_to_point_a / + (distance_to_point_a + distance_to_point_b); + if (fraction < location_of_point) + return point(a[0] * (1 - fraction / location_of_point), + a[1] * (1 - fraction / location_of_point)); + else + return point( + b[0] * ((fraction - location_of_point) / (1 - location_of_point)), + b[1] * ((fraction - location_of_point) / (1 - location_of_point))); + } + } + + private: + shared_ptr gen_ptr; + shared_ptr rand; +}; + +} // namespace boost + +#endif // BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP diff --git a/win32/include/boost/graph/howard_cycle_ratio.hpp b/win32/include/boost/graph/howard_cycle_ratio.hpp new file mode 100755 index 000000000..dfef8d7fe --- /dev/null +++ b/win32/include/boost/graph/howard_cycle_ratio.hpp @@ -0,0 +1,611 @@ +/*! +* Copyright 2007 Technical University of Catalonia +* +* Use, modification and distribution is subject to 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) +* +* Authors: Dmitry Bufistov +* Andrey Parfenov +*/ + +#ifndef BOOST_GRAPH_HOWARD_CYCLE_RATIO_HOWARD_HPP +#define BOOST_GRAPH_HOWARD_CYCLE_RATIO_HOWARD_HPP + +/*! +* \file Maximum cycle ratio algorithm (Jean Cochet-Terrasson, Guy +* Cochen and others) +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + namespace detail { + /// To avoid round error. + static const double mcr_howard_ltolerance = 0.00001; + + /*! + * Calculate maximum cycle ratio of "good" directed multigraph + * g. Use Howard's iteration policy algorithm ("Numerical + * Computation of Spectral Elements in MAX-PLUS algebra" by Jean + * Cochet-Terrasson, Guy Cochen and others). + * + * \param g = (V, E) - a "good" directed multigraph (out_degree of + * each vertex is greater then 0). If graph is strongly connected + * then it is "good". + * + * \param vim - Vertex Index, read property Map: V -> [0, + * num_vertices(g)). + * + * \param ewm - edge weight read property map: E -> R + * + * \param ewm2 - edge weight2 read property map: E -> R+ + * + * \return maximum_{for all cycles C}CR(C), or + * -(std::numeric_limits)::max() if g is not "good". + */ + template + class Cmcr_Howard + { + public: + Cmcr_Howard(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm, + TWeight2EdgeMap ew2m) + : m_g(g), m_vim(vim), m_ew1m(ewm), m_ew2m(ew2m), + m_g2pi_g_vm(std::vector().end(), m_vim), /// Stupid dummy initialization + m_minus_infinity(-(std::numeric_limits::max)()) + { + typedef typename boost::graph_traits::directed_category DirCat; + BOOST_STATIC_ASSERT((boost::is_convertible::value == true)); + m_cr = m_minus_infinity; + } + + double operator()() + { + return maximum_cycle_ratio_Howard(); + } + + virtual ~Cmcr_Howard() { } + + protected: + typedef typename boost::graph_traits::vertex_descriptor + mcr_vertex_t; + typedef typename boost::graph_traits::edge_descriptor + mcr_edge_t; + + const TGraph& m_g; + typedef std::vector eigenmode_t; + eigenmode_t m_eigen_value; + eigenmode_t m_eigen_vector; + TVertexIndexMap m_vim; + TWeight1EdgeMap m_ew1m; + TWeight2EdgeMap m_ew2m; + + typedef typename boost::remove_const::value_type>::type mcr_edge_weight1_t; + typedef typename boost::remove_const::value_type>::type mcr_edge_weight2_t; + typedef typename boost::adjacency_list< + boost::listS, boost::vecS, boost::bidirectionalS, + boost::no_property, + boost::property > > + pi_graph_t; + typedef typename boost::property_map::type TPiGraphVertexIndexMap; + typedef typename boost::property_map::type TPiGraphEdgeWeight1Map; + typedef typename boost::property_map::type TPiGraphEdgeWeight2Map; + + typedef typename boost::property_traits::value_type pigraph_vertex_index_t; + + pi_graph_t m_pi_g; + typedef typename boost::graph_traits::vertex_descriptor pi_vertex_t; + typedef typename boost::graph_traits::edge_descriptor pi_edge_t; + typedef typename boost::iterator_property_map::iterator, TVertexIndexMap> g2pi_g_vm_t; + g2pi_g_vm_t m_g2pi_g_vm; ///Graph to Pi graph vertex map + std::vector m_g2pig; + int m_step_number; + const double m_minus_infinity; + typedef typename std::vector critical_cycle_t; + double m_cr; ///Cycle ratio that already has been found + + class bad_graph + { + public: + typedef typename boost::property_traits::value_type + v_index_t; + + bad_graph(v_index_t bvi) : bad_vertex_index(bvi) {} + v_index_t what() const throw() + { + return bad_vertex_index; + } + + private: + v_index_t bad_vertex_index; + }; + + double maximum_cycle_ratio_Howard() + { + try + { + construct_pi_graph(); + } + catch (const bad_graph& a) + { + return m_minus_infinity; + } + std::vector max_eigen_val(boost::num_vertices(m_g)); + m_eigen_value.resize(boost::num_vertices(m_g)); + m_eigen_vector.resize(boost::num_vertices(m_g)); + m_step_number = 0; + do + { + pi_eingen_value(get(vertex_index, m_pi_g), get(boost::edge_weight, m_pi_g), get(boost::edge_weight2, m_pi_g)); + ++m_step_number; + } + while (improve_policy_try1(max_eigen_val) || improve_policy_try2(max_eigen_val)); + return *(std::max_element(m_eigen_value.begin(), m_eigen_value.end())); + } + + /*! + * Construct an arbitrary policy m_pi_g. + */ + void construct_pi_graph() + { + m_g2pig.resize(boost::num_vertices(m_g)); + m_g2pi_g_vm = boost::make_iterator_property_map(m_g2pig.begin(), m_vim); + BGL_FORALL_VERTICES_T(vd, m_g, TGraph) + { + m_g2pi_g_vm[vd] = boost::add_vertex(m_pi_g); + store_pivertex(m_g2pi_g_vm[vd], vd); + } + BGL_FORALL_VERTICES_T(vd1, m_g, TGraph) + { + if (boost::out_edges(vd1, m_g).first == boost::out_edges(vd1, m_g).second) throw bad_graph(m_vim[vd1]); + mcr_edge_t ed = *boost::out_edges(vd1, m_g).first; + pi_edge_t pied = boost::add_edge(m_g2pi_g_vm[source(ed, m_g)], m_g2pi_g_vm[target(ed, m_g)], m_pi_g).first; + boost::put(boost::edge_weight, m_pi_g, pied, m_ew1m[ed]); + boost::put(boost::edge_weight2, m_pi_g, pied, m_ew2m[ed]); + } + } + + class bfs_eingmode_visitor : public boost::default_bfs_visitor + { + public: + bfs_eingmode_visitor(TPiGraphVertexIndexMap vi_m, TPiGraphEdgeWeight1Map w_m, TPiGraphEdgeWeight2Map& d_m, + eigenmode_t& e_val, eigenmode_t& e_vec, double ev) : m_index_map(vi_m), m_weight_map(w_m), m_delay_map(d_m), + m_eig_value(&e_val), m_eig_vec(&e_vec), m_eigen_value(ev) { } + + template < typename Edge, typename g_t> + void examine_edge(Edge e, const g_t & g) const + { + typedef typename boost::graph_traits::vertex_descriptor Vertex; + Vertex u = boost::target(e, g), v = boost::source(e, g); + pigraph_vertex_index_t ind = m_index_map[u]; + (*m_eig_value)[ind] = m_eigen_value; + (*m_eig_vec)[ind] = m_weight_map[e] - m_eigen_value * m_delay_map[e] + (*m_eig_vec)[m_index_map[v]]; + } + private: + TPiGraphVertexIndexMap m_index_map; + TPiGraphEdgeWeight1Map m_weight_map; + TPiGraphEdgeWeight2Map m_delay_map; + eigenmode_t* m_eig_value; + eigenmode_t* m_eig_vec; + double m_eigen_value; + }; + + /*! + * Find a vertex in the Pi Graph which belongs to cycle, just a DFV until back edge found + */ + pi_vertex_t find_good_source(const pi_vertex_t start_vertex) + { + pi_vertex_t good_vertex = start_vertex; + typename std::set s; + s.insert(start_vertex); + do + { + good_vertex = boost::target(*boost::out_edges(good_vertex, m_pi_g).first, m_pi_g); + } + while (s.insert(good_vertex).second); + return good_vertex; + } + virtual void store_pivertex(pi_vertex_t pivd, mcr_vertex_t vd) {} + virtual void store_critical_edge(pi_edge_t ed, critical_cycle_t& cc) {} + virtual void store_critical_cycle(critical_cycle_t& cc) {} + + /*! + * \param startV - vertex that belongs to a cycle in policy graph m_pi_g + */ + double calculate_eigen_value(pi_vertex_t startV) + { + std::pair accum_sums(0., 0.); + pi_vertex_t vd = startV; + critical_cycle_t cc; + do + { + pi_edge_t tmp_ed = *(boost::out_edges(vd, m_pi_g).first); + store_critical_edge(tmp_ed, cc); + accum_sums.first += boost::get(boost::edge_weight, m_pi_g, tmp_ed); + accum_sums.second += boost::get(boost::edge_weight2, m_pi_g, tmp_ed); + vd = boost::target(tmp_ed, m_pi_g); + } + while (vd != startV); + //assert((std::abs(accum_sums.first) <= 0.00000001) && "Division by zerro!"); + double cr = accum_sums.first / accum_sums.second; + if (cr > m_cr) + { + m_cr = cr; + store_critical_cycle(cc); + } + else + { + + } + return cr; + } + + /*! + * Value determination. Find a generalized eigenmode (n^{k+1}, x^{k+1}) of A^{Ï_{k+1}} of the pi graph (Algorithm IV.1). + */ + void pi_eingen_value( + TPiGraphVertexIndexMap index_map, + TPiGraphEdgeWeight1Map weight_map, + TPiGraphEdgeWeight2Map weigh2_map) + { + using namespace boost; + typedef std::vector color_map_t; + color_map_t vcm(num_vertices(m_pi_g), white_color);//Vertex color map + color_map_t::iterator uv_itr = vcm.begin(); //Undiscovered vertex + reverse_graph rev_g(m_pi_g); //For backward breadth visit + + while ((uv_itr = std::find_if(uv_itr, vcm.end(), + boost::bind(std::equal_to(), boost::white_color, _1))) != vcm.end()) + ///While there are undiscovered vertices + { + pi_vertex_t gv = find_good_source(pi_vertex_t(uv_itr - vcm.begin())); + pigraph_vertex_index_t gv_ind = index_map[gv]; + m_eigen_value[gv_ind] = calculate_eigen_value(gv) ; + bfs_eingmode_visitor bfs_vis(index_map, weight_map, weigh2_map, m_eigen_value, m_eigen_vector, m_eigen_value[gv_ind]); + typename boost::queue Q; + breadth_first_visit(rev_g, gv, Q, bfs_vis, make_iterator_property_map(vcm.begin(), index_map)); + } + } + + void improve_policy(mcr_vertex_t vd, mcr_edge_t new_edge) + { + remove_edge(*(out_edges(m_g2pi_g_vm[vd], m_pi_g).first), m_pi_g); + pi_edge_t ned = add_edge(m_g2pi_g_vm[vd], m_g2pi_g_vm[target(new_edge, m_g)], m_pi_g).first; + put(edge_weight, m_pi_g, ned, m_ew1m[new_edge]); + put(edge_weight2, m_pi_g, ned, m_ew2m[new_edge]); + } + /*! + * Policy Improvement. Improve the policy graph. The new policy graph has greater cycle ratio. + * \return false if nothing can be improved. + */ + bool improve_policy_try1(std::vector& max_eing_vals) + { + bool improved = false; + BGL_FORALL_VERTICES_T(vd, m_g, TGraph) + { + double max_ev = m_minus_infinity;/// Maximum eigen value for vertex + mcr_edge_t cr_ed;///Critical edge + + BGL_FORALL_OUTEDGES_T(vd, outed, m_g, TGraph) + { + if (m_eigen_value[m_vim[target(outed, m_g)]] > max_ev) + { + max_ev = m_eigen_value[m_vim[boost::target(outed, m_g)]]; + cr_ed = outed; + } + } + if (max_ev > m_eigen_value[get(m_vim,vd)]) + { + improve_policy(vd, cr_ed); + improved = true; + } + max_eing_vals[get(m_vim,vd)] = max_ev; + } + return improved; + } + + /*! + * \param max_eigen_values[u] = max_(for all adjacent vertices (u,v)) m_eigen_value[v] + */ + bool improve_policy_try2(const std::vector& max_eigen_values) + { + bool improved = false; + BGL_FORALL_VERTICES_T(vd, m_g, TGraph) + { + mcr_edge_t impr_edge; + double max_val = m_minus_infinity; + BGL_FORALL_OUTEDGES_T(vd, outed, m_g, TGraph) + { + ///If vertex vd is in the K(vd) set + if (max_eigen_values[get(m_vim, vd)] <= m_eigen_value[get(m_vim, target(outed, m_g))]) + { + double c_val = m_ew1m[outed] - m_ew2m[outed] * m_eigen_value[m_vim[boost::target(outed, m_g)]] + + m_eigen_vector[m_vim[boost::target(outed, m_g)]]; + if (c_val > max_val) + { + max_val = c_val; + impr_edge = outed; + } + } + } + if ((max_val - m_eigen_vector[get(m_vim, vd)]) > mcr_howard_ltolerance) + ///If m_eigen_vector[vd] == max_val + { + improve_policy(vd, impr_edge); + improved = true; + } + } + return improved; + } + };///Cmcr_Howard + + /*! + * \return maximum cycle ratio and one critical cycle. + */ + template + class Cmcr_Howard1 : public Cmcr_Howard + { + public: + typedef Cmcr_Howard inhr_t; + Cmcr_Howard1(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m) : inhr_t(g, vim, ewm, ew2m) + { + m_pi_g2g.resize(boost::num_vertices(g)); + m_pi_g2g_vm = boost::make_iterator_property_map(m_pi_g2g.begin(), boost::get(boost::vertex_index, this->m_pi_g)); + } + + void get_critical_cycle(typename inhr_t::critical_cycle_t& cc) { return cc.swap(m_critical_cycle); } + protected: + void store_pivertex(typename inhr_t::pi_vertex_t pivd, typename inhr_t::mcr_vertex_t vd) + { + m_pi_g2g_vm[pivd] = vd; + } + void store_critical_edge(typename inhr_t::pi_edge_t ed, typename inhr_t::critical_cycle_t& cc) + { + typename inhr_t::pi_vertex_t s = boost::source(ed, this->m_pi_g); + typename inhr_t::pi_vertex_t t = boost::target(ed, this->m_pi_g); + assert(boost::edge(m_pi_g2g_vm[s], m_pi_g2g_vm[t], this->m_g).second); + cc.push_back(boost::edge(m_pi_g2g_vm[s], m_pi_g2g_vm[t], this->m_g).first); ///Store corresponding edge of the m_g + } + void store_critical_cycle(typename inhr_t::critical_cycle_t& cc) + { + m_critical_cycle.swap(cc); + } + private: + typename inhr_t::critical_cycle_t m_critical_cycle; + typedef typename boost::iterator_property_map::iterator, typename inhr_t::TPiGraphVertexIndexMap> pi_g2g_vm_t; + pi_g2g_vm_t m_pi_g2g_vm; ///Maps policy graph vertices to input graph vertices + typename std::vector m_pi_g2g; + }; + + /*! + * Add sink vertex - this will make any graph good, the selfloop will have ratio equal to infinity + * Properties must be "self increasing" + */ + template + typename boost::graph_traits::vertex_descriptor + make_graph_good(TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m, + typename boost::property_traits::value_type infinity) + { + typedef typename boost::graph_traits::edge_descriptor Edge; + typename boost::graph_traits::vertex_descriptor sink = boost::add_vertex(g); + + BGL_FORALL_VERTICES_T(vd, g, TGraph) + { + Edge newed = boost::add_edge(vd, sink, g).first; + boost::put(ewm, newed, 0); + boost::put(ew2m, newed, 1); + } + Edge selfed = boost::edge(sink, sink, g).first; + boost::put(ewm, selfed, infinity); + return sink; + } + + /*! + * Construct from input graph g "safe" (suitable for maximum_cycle_ratio1() call) version - safeg + */ + template + void construct_safe_graph(const TG& g, TIndVertexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m, TSafeG& safeg, SafeG2GEdgeMap& sg2gm) + { + assert(num_vertices(g) == num_vertices(safeg)); + typedef typename graph_traits::edge_descriptor tmp_edge_t; + typedef typename graph_traits::edge_descriptor edge_t; + typename graph_traits::edge_iterator ei, ei_end; + + for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + tmp_edge_t tmped = add_edge(vim[source(*ei, g)], vim[target(*ei, g)], safeg).first; + sg2gm[tmped] = *ei; + put(edge_weight, safeg, tmped, get(ew1m, *ei)); + put(edge_weight2, safeg, tmped, get(ew2m, *ei)); + } + } + + template + double maximum_cycle_ratio_good_graph(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m, + typename std::vector::edge_descriptor>* pcc = 0) + { + if (pcc == 0) + { + return detail::Cmcr_Howard(g, vim, ewm, ew2m)(); + } + else + { + detail::Cmcr_Howard1 obj(g, vim, ewm, ew2m); + double maxcr = obj(); + obj.get_critical_cycle(*pcc); + return maxcr; + } + } + + template + double minimum_cycle_ratio_good_graph(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm, + TWeight2EdgeMap ew2m, TEdgeIndexMap eim, + typename std::vector::edge_descriptor>* pcc = 0) + { + typedef typename boost::remove_const::value_type>::type weight_value_t; + BOOST_STATIC_ASSERT(!is_integral::value || is_signed::value); + typename std::vector ne_w(boost::num_edges(g)); + BGL_FORALL_EDGES_T(ed, g, TGraph) ne_w[boost::get(eim, ed)] = -ewm[ed]; + return -maximum_cycle_ratio_good_graph(g, vim, boost::make_iterator_property_map(ne_w.begin(), eim), ew2m, pcc); + } + + /*! + * \param g directed multigraph. + * \param pcc - pointer to the critical edges list. + * \param minus_infinity must be small enough to garanty that g has at least one cycle with greater ratio. + * \return minus_infinity if there're no cycles in the graph + */ + template + double maximum_cycle_ratio1(const TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m, + typename std::vector::edge_descriptor>* pcc = 0, + typename boost::property_traits::value_type minus_infinity = -(std::numeric_limits::max)()) + { + typedef typename boost::graph_traits::vertex_descriptor Vertex; + typedef typename boost::graph_traits::edge_descriptor Edge; + boost::function_requires< boost::ReadWritePropertyMapConcept >(); + boost::function_requires< boost::ReadWritePropertyMapConcept >(); + + TGraph& ncg = const_cast(g); + Vertex sink = detail::make_graph_good(ncg, ewm, ew2m, minus_infinity ); + + double res = maximum_cycle_ratio_good_graph(ncg, boost::get(boost::vertex_index, g), ewm, ew2m, pcc); + boost::clear_vertex(sink, ncg); boost::remove_vertex(sink, ncg); + return res; + } + + /*! + * Edge index MUST be in diapazon [0,..., num_edges(g)-1] + * \return plus_infinity if g has no cycles. + */ + template + double minimum_cycle_ratio1(const TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m, TEdgeIndexMap eim, + typename std::vector::edge_descriptor>* pcc = 0, + typename boost::property_traits::value_type plus_infinity = (std::numeric_limits::max)() + ) + { + typedef typename boost::property_traits::value_type ei_t; + typedef typename boost::graph_traits::vertex_descriptor Vertex; + typedef typename boost::graph_traits::edge_descriptor Edge; + + boost::function_requires< boost::ReadWritePropertyMapConcept >(); + boost::function_requires< boost::ReadWritePropertyMapConcept >(); + boost::function_requires< boost::ReadWritePropertyMapConcept >(); + + TGraph& ncg = const_cast(g); + + ei_t nei = ei_t(boost::num_edges(g)); + Vertex sink = detail::make_graph_good(ncg, ewm, ew2m, plus_infinity ); + ///Maintain edge index invariant + BGL_FORALL_VERTICES_T(vd, ncg, TGraph) + { + typename boost::graph_traits::edge_descriptor ed = boost::edge(vd, sink, ncg).first; + boost::put(eim, ed, nei++); + } + double res = minimum_cycle_ratio_good_graph(ncg, boost::get(boost::vertex_index, ncg), ewm, ew2m, eim, pcc); + boost::clear_vertex(sink, ncg); boost::remove_vertex(sink, ncg); + return res; + } + struct edge_less_than + { + template bool operator()(const TEdgeDescriptor& x, const TEdgeDescriptor& y) const + { + return x.get_property() < y.get_property(); + } + }; + }///namespace detail + namespace + { + template struct safe_graph + { + typedef typename boost::adjacency_list > > type; + }; + } + + /*! + * Calculate the maximum cycle ratio (mcr) of the directed multigraph g. + * \param g directed multigraph + * \param pcc - If provided then a critical cycle will be written to corresponding vector. + * \param minus_infinity small enough value to garanty that g has at least one cycle with greater ratio. + * \return mcr or minus_infinity if g has no cycles. + */ + template + double maximum_cycle_ratio(const TGraph& g, TVertexIndexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m, + typename std::vector::edge_descriptor>* pcc = 0, + typename boost::property_traits::value_type minus_infinity = + -(std::numeric_limits::max)()) + { + typedef typename remove_const::value_type>::type w1_t; + typedef typename remove_const::value_type>::type w2_t; + typedef typename safe_graph::type safe_graph_t; + typedef typename graph_traits::edge_descriptor tmp_edge_t; + typedef typename graph_traits::edge_descriptor edge_t; + typename std::map tmpg2g; + std::vector cc; + safe_graph_t sg(num_vertices(g)); + detail::construct_safe_graph(g, vim, ew1m, ew2m, sg, tmpg2g); + double mcr = maximum_cycle_ratio1(sg, get(edge_weight, sg), get(edge_weight2, sg), pcc ? &cc : 0, minus_infinity); + if (pcc && (mcr > minus_infinity)) + { + pcc->clear(); + for (typename std::vector::iterator it = cc.begin(); it != cc.end(); ++it) pcc->push_back(tmpg2g[*it]); + } + return mcr; + } + + template + double minimum_cycle_ratio(const TGraph& g, TVertexIndexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m, TIndEdgeMap eim, + typename std::vector::edge_descriptor>* pcc = 0, + typename boost::property_traits::value_type plus_infinity = + (std::numeric_limits::max)()) + { + typedef typename boost::remove_const::value_type>::type weight_value_t; + BOOST_STATIC_ASSERT(!is_integral::value || is_signed::value); + typename std::vector ne_w(boost::num_edges(g)); + BGL_FORALL_EDGES_T(ed, g, TGraph) ne_w[boost::get(eim, ed)] = -ew1m[ed]; + return -maximum_cycle_ratio(g, vim, boost::make_iterator_property_map(ne_w.begin(), eim), ew2m, pcc, -plus_infinity); + } + /*! + * Calculate maximum mean cycle of directed weighted multigraph. + * \param g directed multigraph + * \return maximum mean cycle of g or minus_infinity if g has no cycles. + */ + template + double maximum_mean_cycle(const TGraph& g, TVertexIndexMap vim, TWeightEdgeMap ewm, TIndEdgeMap eim, + typename std::vector::edge_descriptor>* pcc = 0, + typename boost::property_traits::value_type minus_infinity = + -(std::numeric_limits::max)()) + { + typedef typename boost::remove_const::value_type>::type weight_value_t; + typedef typename boost::graph_traits::edge_descriptor Edge; + typename std::vector ed_w2(boost::num_edges(g), 1); + return maximum_cycle_ratio(g, vim, ewm, boost::make_iterator_property_map(ed_w2.begin(), eim), pcc, minus_infinity); + } + + template + double minimum_mean_cycle(const TGraph& g, TVertexIndexMap vim, TWeightEdgeMap ewm, TIndEdgeMap eim, + typename std::vector::edge_descriptor>* pcc = 0, + typename boost::property_traits::value_type plus_infinity = + (std::numeric_limits::max)()) + { + typedef typename boost::remove_const::value_type>::type weight_value_t; + typedef typename boost::graph_traits::edge_descriptor Edge; + typename std::vector ed_w2(boost::num_edges(g), 1); + return minimum_cycle_ratio(g, vim, ewm, boost::make_iterator_property_map(ed_w2.begin(), eim), eim, pcc, plus_infinity); + } +} //namespace boost +#endif diff --git a/win32/include/boost/graph/incremental_components.hpp b/win32/include/boost/graph/incremental_components.hpp new file mode 100755 index 000000000..25e3f5cf6 --- /dev/null +++ b/win32/include/boost/graph/incremental_components.hpp @@ -0,0 +1,170 @@ +// +//======================================================================= +// Copyright 1997-2001 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +#ifndef BOOST_INCREMENTAL_COMPONENTS_HPP +#define BOOST_INCREMENTAL_COMPONENTS_HPP + +#include +#include + +namespace boost { + + // A connected component algorithm for the case when dynamically + // adding (but not removing) edges is common. The + // incremental_components() function is a preparing operation. Call + // same_component to check whether two vertices are in the same + // component, or use disjoint_set::find_set to determine the + // representative for a vertex. + + // This version of connected components does not require a full + // Graph. Instead, it just needs an edge list, where the vertices of + // each edge need to be of integer type. The edges are assumed to + // be undirected. The other difference is that the result is stored in + // a container, instead of just a decorator. The container should be + // empty before the algorithm is called. It will grow during the + // course of the algorithm. The container must be a model of + // BackInsertionSequence and RandomAccessContainer + // (std::vector is a good choice). After running the algorithm the + // index container will map each vertex to the representative + // vertex of the component to which it belongs. + // + // Adapted from an implementation by Alex Stepanov. The disjoint + // sets data structure is from Tarjan's "Data Structures and Network + // Algorithms", and the application to connected components is + // similar to the algorithm described in Ch. 22 of "Intro to + // Algorithms" by Cormen, et. all. + // + // RankContainer is a random accessable container (operator[] is + // defined) with a value type that can represent an integer part of + // a binary log of the value type of the corresponding + // ParentContainer (char is always enough) its size_type is no less + // than the size_type of the corresponding ParentContainer + + // An implementation of disjoint sets can be found in + // boost/pending/disjoint_sets.hpp + + template + void incremental_components(EdgeListGraph& g, DisjointSets& ds) + { + typename graph_traits::edge_iterator e, end; + for (tie(e,end) = edges(g); e != end; ++e) + ds.union_set(source(*e,g),target(*e,g)); + } + + template + void compress_components(ParentIterator first, ParentIterator last) + { + for (ParentIterator current = first; current != last; ++current) + detail::find_representative_with_full_compression(first, current-first); + } + + template + typename boost::detail::iterator_traits::difference_type + component_count(ParentIterator first, ParentIterator last) + { + std::ptrdiff_t count = 0; + for (ParentIterator current = first; current != last; ++current) + if (*current == current - first) ++count; + return count; + } + + // This algorithm can be applied to the result container of the + // connected_components algorithm to normalize + // the components. + template + void normalize_components(ParentIterator first, ParentIterator last) + { + for (ParentIterator current = first; current != last; ++current) + detail::normalize_node(first, current - first); + } + + template + void initialize_incremental_components(VertexListGraph& G, DisjointSets& ds) + { + typename graph_traits + ::vertex_iterator v, vend; + for (tie(v, vend) = vertices(G); v != vend; ++v) + ds.make_set(*v); + } + + template + inline bool same_component(Vertex u, Vertex v, DisjointSet& ds) + { + return ds.find_set(u) == ds.find_set(v); + } + + // considering changing the so that it initializes with a pair of + // vertex iterators and a parent PA. + + template + class component_index + { + public://protected: (avoid friends for now) + typedef std::vector MyIndexContainer; + MyIndexContainer header; + MyIndexContainer index; + typedef typename MyIndexContainer::size_type SizeT; + typedef typename MyIndexContainer::const_iterator IndexIter; + public: + typedef detail::component_iterator + component_iterator; + class component { + friend class component_index; + protected: + IndexT number; + const component_index* comp_ind_ptr; + component(IndexT i, const component_index* p) + : number(i), comp_ind_ptr(p) {} + public: + typedef component_iterator iterator; + typedef component_iterator const_iterator; + typedef IndexT value_type; + iterator begin() const { + return iterator( comp_ind_ptr->index.begin(), + (comp_ind_ptr->header)[number] ); + } + iterator end() const { + return iterator( comp_ind_ptr->index.begin(), + comp_ind_ptr->index.size() ); + } + }; + typedef SizeT size_type; + typedef component value_type; + +#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS) + template + component_index(Iterator first, Iterator last) + : index(std::distance(first, last)) + { + std::copy(first, last, index.begin()); + detail::construct_component_index(index, header); + } +#else + template + component_index(Iterator first, Iterator last) + : index(first, last) + { + detail::construct_component_index(index, header); + } +#endif + + component operator[](IndexT i) const { + return component(i, this); + } + SizeT size() const { + return header.size(); + } + + }; + +} // namespace boost + +#endif // BOOST_INCREMENTAL_COMPONENTS_HPP diff --git a/win32/include/boost/graph/is_kuratowski_subgraph.hpp b/win32/include/boost/graph/is_kuratowski_subgraph.hpp new file mode 100755 index 000000000..5cdf68682 --- /dev/null +++ b/win32/include/boost/graph/is_kuratowski_subgraph.hpp @@ -0,0 +1,332 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __IS_KURATOWSKI_SUBGRAPH_HPP__ +#define __IS_KURATOWSKI_SUBGRAPH_HPP__ + +#include +#include //for next/prior +#include //for tie +#include +#include +#include +#include + +#include +#include +#include + + + +namespace boost +{ + + namespace detail + { + + template + Graph make_K_5() + { + typename graph_traits::vertex_iterator vi, vi_end, inner_vi; + Graph K_5(5); + for(tie(vi,vi_end) = vertices(K_5); vi != vi_end; ++vi) + for(inner_vi = next(vi); inner_vi != vi_end; ++inner_vi) + add_edge(*vi, *inner_vi, K_5); + return K_5; + } + + + template + Graph make_K_3_3() + { + typename graph_traits::vertex_iterator + vi, vi_end, bipartition_start, inner_vi; + Graph K_3_3(6); + bipartition_start = next(next(next(vertices(K_3_3).first))); + for(tie(vi, vi_end) = vertices(K_3_3); vi != bipartition_start; ++vi) + for(inner_vi= bipartition_start; inner_vi != vi_end; ++inner_vi) + add_edge(*vi, *inner_vi, K_3_3); + return K_3_3; + } + + + template + void contract_edge(AdjacencyList& neighbors, Vertex u, Vertex v) + { + // Remove u from v's neighbor list + neighbors[v].erase(std::remove(neighbors[v].begin(), + neighbors[v].end(), u + ), + neighbors[v].end() + ); + + // Replace any references to u with references to v + typedef typename AdjacencyList::value_type::iterator + adjacency_iterator_t; + + adjacency_iterator_t u_neighbor_end = neighbors[u].end(); + for(adjacency_iterator_t u_neighbor_itr = neighbors[u].begin(); + u_neighbor_itr != u_neighbor_end; ++u_neighbor_itr + ) + { + Vertex u_neighbor(*u_neighbor_itr); + std::replace(neighbors[u_neighbor].begin(), + neighbors[u_neighbor].end(), u, v + ); + } + + // Remove v from u's neighbor list + neighbors[u].erase(std::remove(neighbors[u].begin(), + neighbors[u].end(), v + ), + neighbors[u].end() + ); + + // Add everything in u's neighbor list to v's neighbor list + std::copy(neighbors[u].begin(), + neighbors[u].end(), + std::back_inserter(neighbors[v]) + ); + + // Clear u's neighbor list + neighbors[u].clear(); + + } + + } // namespace detail + + + + + template + bool is_kuratowski_subgraph(const Graph& g, + ForwardIterator begin, + ForwardIterator end, + VertexIndexMap vm + ) + { + + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::vertex_iterator vertex_iterator_t; + typedef typename graph_traits::edge_descriptor edge_t; + typedef typename graph_traits::edges_size_type e_size_t; + typedef typename graph_traits::vertices_size_type v_size_t; + typedef typename std::vector v_list_t; + typedef typename v_list_t::iterator v_list_iterator_t; + typedef iterator_property_map + ::iterator, VertexIndexMap> + vertex_to_v_list_map_t; + + typedef adjacency_list small_graph_t; + + enum target_graph_t { k_3_3, k_5}; + + target_graph_t target_graph = k_3_3; //unless we decide otherwise later + + static small_graph_t K_5(detail::make_K_5()); + + static small_graph_t K_3_3(detail::make_K_3_3()); + + v_size_t n_vertices(num_vertices(g)); + v_size_t max_num_edges(3*n_vertices - 5); + + std::vector neighbors_vector(n_vertices); + vertex_to_v_list_map_t neighbors(neighbors_vector.begin(), vm); + + e_size_t count = 0; + for(ForwardIterator itr = begin; itr != end; ++itr) + { + + if (count++ > max_num_edges) + return false; + + edge_t e(*itr); + vertex_t u(source(e,g)); + vertex_t v(target(e,g)); + + neighbors[u].push_back(v); + neighbors[v].push_back(u); + + } + + + for(v_size_t max_size = 2; max_size < 5; ++max_size) + { + + vertex_iterator_t vi, vi_end; + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_t v(*vi); + + //a hack to make sure we don't contract the middle edge of a path + //of four degree-3 vertices + if (max_size == 4 && neighbors[v].size() == 3) + { + if (neighbors[neighbors[v][0]].size() + + neighbors[neighbors[v][1]].size() + + neighbors[neighbors[v][2]].size() + < 11 // so, it has two degree-3 neighbors + ) + continue; + } + + while (neighbors[v].size() > 0 && neighbors[v].size() < max_size) + { + // Find one of v's neighbors u such that that v and u + // have no neighbors in common. We'll look for such a + // neighbor with a naive cubic-time algorithm since the + // max size of any of the neighbor sets we'll consider + // merging is 3 + + bool neighbor_sets_intersect = false; + + vertex_t min_u = graph_traits::null_vertex(); + vertex_t u; + v_list_iterator_t v_neighbor_end = neighbors[v].end(); + for(v_list_iterator_t v_neighbor_itr = neighbors[v].begin(); + v_neighbor_itr != v_neighbor_end; + ++v_neighbor_itr + ) + { + neighbor_sets_intersect = false; + u = *v_neighbor_itr; + v_list_iterator_t u_neighbor_end = neighbors[u].end(); + for(v_list_iterator_t u_neighbor_itr = + neighbors[u].begin(); + u_neighbor_itr != u_neighbor_end && + !neighbor_sets_intersect; + ++u_neighbor_itr + ) + { + for(v_list_iterator_t inner_v_neighbor_itr = + neighbors[v].begin(); + inner_v_neighbor_itr != v_neighbor_end; + ++inner_v_neighbor_itr + ) + { + if (*u_neighbor_itr == *inner_v_neighbor_itr) + { + neighbor_sets_intersect = true; + break; + } + } + + } + if (!neighbor_sets_intersect && + (min_u == graph_traits::null_vertex() || + neighbors[u].size() < neighbors[min_u].size()) + ) + { + min_u = u; + } + + } + + if (min_u == graph_traits::null_vertex()) + // Exited the loop without finding an appropriate neighbor of + // v, so v must be a lost cause. Move on to other vertices. + break; + else + u = min_u; + + detail::contract_edge(neighbors, u, v); + + }//end iteration over v's neighbors + + }//end iteration through vertices v + + if (max_size == 3) + { + // check to see whether we should go on to find a K_5 + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + if (neighbors[*vi].size() == 4) + { + target_graph = k_5; + break; + } + + if (target_graph == k_3_3) + break; + } + + }//end iteration through max degree 2,3, and 4 + + + //Now, there should only be 5 or 6 vertices with any neighbors. Find them. + + v_list_t main_vertices; + vertex_iterator_t vi, vi_end; + + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + { + if (!neighbors[*vi].empty()) + main_vertices.push_back(*vi); + } + + // create a graph isomorphic to the contracted graph to test + // against K_5 and K_3_3 + small_graph_t contracted_graph(main_vertices.size()); + std::map::vertex_descriptor> + contracted_vertex_map; + + typename v_list_t::iterator itr, itr_end; + itr_end = main_vertices.end(); + typename graph_traits::vertex_iterator + si = vertices(contracted_graph).first; + + for(itr = main_vertices.begin(); itr != itr_end; ++itr, ++si) + { + contracted_vertex_map[*itr] = *si; + } + + typename v_list_t::iterator jtr, jtr_end; + for(itr = main_vertices.begin(); itr != itr_end; ++itr) + { + jtr_end = neighbors[*itr].end(); + for(jtr = neighbors[*itr].begin(); jtr != jtr_end; ++jtr) + { + if (get(vm,*itr) < get(vm,*jtr)) + { + add_edge(contracted_vertex_map[*itr], + contracted_vertex_map[*jtr], + contracted_graph + ); + } + } + } + + if (target_graph == k_5) + { + return isomorphism(K_5,contracted_graph); + } + else //target_graph == k_3_3 + { + return isomorphism(K_3_3,contracted_graph); + } + + + } + + + + + + template + bool is_kuratowski_subgraph(const Graph& g, + ForwardIterator begin, + ForwardIterator end + ) + { + return is_kuratowski_subgraph(g, begin, end, get(vertex_index,g)); + } + + + + +} + +#endif //__IS_KURATOWSKI_SUBGRAPH_HPP__ diff --git a/win32/include/boost/graph/is_straight_line_drawing.hpp b/win32/include/boost/graph/is_straight_line_drawing.hpp new file mode 100755 index 000000000..e823477be --- /dev/null +++ b/win32/include/boost/graph/is_straight_line_drawing.hpp @@ -0,0 +1,232 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __IS_STRAIGHT_LINE_DRAWING_HPP__ +#define __IS_STRAIGHT_LINE_DRAWING_HPP__ + +#include +#include //for next and prior +#include +#include +#include +#include +#include + +#include +#include +#include + + + +namespace boost +{ + + // Return true exactly when the line segments s1 = ((x1,y1), (x2,y2)) and + // s2 = ((a1,b1), (a2,b2)) intersect in a point other than the endpoints of + // the line segments. The one exception to this rule is when s1 = s2, in + // which case false is returned - this is to accomodate multiple edges + // between the same pair of vertices, which shouldn't invalidate the straight + // line embedding. A tolerance variable epsilon can also be used, which + // defines how far away from the endpoints of s1 and s2 we want to consider + // an intersection. + + bool intersects(double x1, double y1, + double x2, double y2, + double a1, double b1, + double a2, double b2, + double epsilon = 0.000001 + ) + { + + if (x1 - x2 == 0) + { + std::swap(x1,a1); + std::swap(y1,b1); + std::swap(x2,a2); + std::swap(y2,b2); + } + + if (x1 - x2 == 0) + { + BOOST_USING_STD_MAX(); + BOOST_USING_STD_MIN(); + + //two vertical line segments + double min_y = min BOOST_PREVENT_MACRO_SUBSTITUTION(y1,y2); + double max_y = max BOOST_PREVENT_MACRO_SUBSTITUTION(y1,y2); + double min_b = min BOOST_PREVENT_MACRO_SUBSTITUTION(b1,b2); + double max_b = max BOOST_PREVENT_MACRO_SUBSTITUTION(b1,b2); + if ((max_y > max_b && max_b > min_y) || + (max_b > max_y && max_y > min_b) + ) + return true; + else + return false; + } + + double x_diff = x1 - x2; + double y_diff = y1 - y2; + double a_diff = a2 - a1; + double b_diff = b2 - b1; + + double beta_denominator = b_diff - (y_diff/((double)x_diff)) * a_diff; + + if (beta_denominator == 0) + { + //parallel lines + return false; + } + + double beta = (b2 - y2 - (y_diff/((double)x_diff)) * (a2 - x2)) / + beta_denominator; + double alpha = (a2 - x2 - beta*(a_diff))/x_diff; + + double upper_bound = 1 - epsilon; + double lower_bound = 0 + epsilon; + + return (beta < upper_bound && beta > lower_bound && + alpha < upper_bound && alpha > lower_bound); + + } + + + template + bool is_straight_line_drawing(const Graph& g, + GridPositionMap drawing, + VertexIndexMap vm + ) + { + + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::vertex_iterator vertex_iterator_t; + typedef typename graph_traits::edge_descriptor edge_t; + typedef typename graph_traits::edge_iterator edge_iterator_t; + typedef typename graph_traits::edges_size_type e_size_t; + typedef typename graph_traits::vertices_size_type v_size_t; + + typedef std::size_t x_coord_t; + typedef std::size_t y_coord_t; + typedef boost::tuple edge_event_t; + typedef typename std::vector< edge_event_t > edge_event_queue_t; + + typedef tuple active_map_key_t; + typedef edge_t active_map_value_t; + typedef std::map< active_map_key_t, active_map_value_t > active_map_t; + typedef typename active_map_t::iterator active_map_iterator_t; + + + edge_event_queue_t edge_event_queue; + active_map_t active_edges; + + edge_iterator_t ei, ei_end; + for(tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) + { + edge_t e(*ei); + vertex_t s(source(e,g)); + vertex_t t(target(e,g)); + edge_event_queue.push_back + (make_tuple(e, + static_cast(drawing[s].x), + static_cast(drawing[s].y) + ) + ); + edge_event_queue.push_back + (make_tuple(e, + static_cast(drawing[t].x), + static_cast(drawing[t].y) + ) + ); + } + + // Order by edge_event_queue by first, then second coordinate + // (bucket_sort is a stable sort.) + bucket_sort(edge_event_queue.begin(), edge_event_queue.end(), + property_map_tuple_adaptor() + ); + + bucket_sort(edge_event_queue.begin(), edge_event_queue.end(), + property_map_tuple_adaptor() + ); + + typedef typename edge_event_queue_t::iterator event_queue_iterator_t; + event_queue_iterator_t itr_end = edge_event_queue.end(); + for(event_queue_iterator_t itr = edge_event_queue.begin(); + itr != itr_end; ++itr + ) + { + edge_t e(get<0>(*itr)); + vertex_t source_v(source(e,g)); + vertex_t target_v(target(e,g)); + if (drawing[source_v].x > drawing[target_v].x) + std::swap(source_v, target_v); + + active_map_key_t key(get(drawing, source_v).y, + get(drawing, target_v).y, + get(drawing, source_v).x, + get(drawing, target_v).x + ); + + active_map_iterator_t a_itr = active_edges.find(key); + if (a_itr == active_edges.end()) + { + active_edges[key] = e; + } + else + { + active_map_iterator_t before, after; + if (a_itr == active_edges.begin()) + before = active_edges.end(); + else + before = prior(a_itr); + after = next(a_itr); + + if (after != active_edges.end() || before != active_edges.end()) + { + + edge_t f = after != active_edges.end() ? + after->second : before->second; + + vertex_t e_source(source(e,g)); + vertex_t e_target(target(e,g)); + vertex_t f_source(source(f,g)); + vertex_t f_target(target(f,g)); + + if (intersects(drawing[e_source].x, + drawing[e_source].y, + drawing[e_target].x, + drawing[e_target].y, + drawing[f_source].x, + drawing[f_source].y, + drawing[f_target].x, + drawing[f_target].y + ) + ) + return false; + } + + active_edges.erase(a_itr); + + } + } + + return true; + + } + + + template + bool is_straight_line_drawing(const Graph& g, GridPositionMap drawing) + { + return is_straight_line_drawing(g, drawing, get(vertex_index,g)); + } + +} + +#endif // __IS_STRAIGHT_LINE_DRAWING_HPP__ diff --git a/win32/include/boost/graph/isomorphism.hpp b/win32/include/boost/graph/isomorphism.hpp new file mode 100755 index 000000000..496a07658 --- /dev/null +++ b/win32/include/boost/graph/isomorphism.hpp @@ -0,0 +1,467 @@ +// Copyright (C) 2001 Jeremy Siek, Douglas Gregor, Brian Osman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_GRAPH_ISOMORPHISM_HPP +#define BOOST_GRAPH_ISOMORPHISM_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include // for make_indirect_pmap + +#ifndef BOOST_GRAPH_ITERATION_MACROS_HPP +#define BOOST_ISO_INCLUDED_ITER_MACROS // local macro, see bottom of file +#include +#endif + +namespace boost { + + namespace detail { + + template + class isomorphism_algo + { + typedef typename graph_traits::vertex_descriptor vertex1_t; + typedef typename graph_traits::vertex_descriptor vertex2_t; + typedef typename graph_traits::edge_descriptor edge1_t; + typedef typename graph_traits::vertices_size_type size_type; + typedef typename Invariant1::result_type invar1_value; + typedef typename Invariant2::result_type invar2_value; + + const Graph1& G1; + const Graph2& G2; + IsoMapping f; + Invariant1 invariant1; + Invariant2 invariant2; + std::size_t max_invariant; + IndexMap1 index_map1; + IndexMap2 index_map2; + + std::vector dfs_vertices; + typedef typename std::vector::iterator vertex_iter; + std::vector dfs_num_vec; + typedef safe_iterator_property_map::iterator, + IndexMap1 +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + , int, int& +#endif /* BOOST_NO_STD_ITERATOR_TRAITS */ + > DFSNumMap; + DFSNumMap dfs_num; + std::vector ordered_edges; + typedef typename std::vector::iterator edge_iter; + + std::vector in_S_vec; + typedef safe_iterator_property_map::iterator, + IndexMap2 +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + , char, char& +#endif /* BOOST_NO_STD_ITERATOR_TRAITS */ + > InSMap; + InSMap in_S; + + int num_edges_on_k; + + friend struct compare_multiplicity; + struct compare_multiplicity + { + compare_multiplicity(Invariant1 invariant1, size_type* multiplicity) + : invariant1(invariant1), multiplicity(multiplicity) { } + bool operator()(const vertex1_t& x, const vertex1_t& y) const { + return multiplicity[invariant1(x)] < multiplicity[invariant1(y)]; + } + Invariant1 invariant1; + size_type* multiplicity; + }; + + struct record_dfs_order : default_dfs_visitor + { + record_dfs_order(std::vector& v, std::vector& e) + : vertices(v), edges(e) { } + + void discover_vertex(vertex1_t v, const Graph1&) const { + vertices.push_back(v); + } + void examine_edge(edge1_t e, const Graph1& G1) const { + edges.push_back(e); + } + std::vector& vertices; + std::vector& edges; + }; + + struct edge_cmp { + edge_cmp(const Graph1& G1, DFSNumMap dfs_num) + : G1(G1), dfs_num(dfs_num) { } + bool operator()(const edge1_t& e1, const edge1_t& e2) const { + using namespace std; + int u1 = dfs_num[source(e1,G1)], v1 = dfs_num[target(e1,G1)]; + int u2 = dfs_num[source(e2,G1)], v2 = dfs_num[target(e2,G1)]; + int m1 = (max)(u1, v1); + int m2 = (max)(u2, v2); + // lexicographical comparison + return std::make_pair(m1, std::make_pair(u1, v1)) + < std::make_pair(m2, std::make_pair(u2, v2)); + } + const Graph1& G1; + DFSNumMap dfs_num; + }; + + public: + isomorphism_algo(const Graph1& G1, const Graph2& G2, IsoMapping f, + Invariant1 invariant1, Invariant2 invariant2, std::size_t max_invariant, + IndexMap1 index_map1, IndexMap2 index_map2) + : G1(G1), G2(G2), f(f), invariant1(invariant1), invariant2(invariant2), + max_invariant(max_invariant), + index_map1(index_map1), index_map2(index_map2) + { + in_S_vec.resize(num_vertices(G1)); + in_S = make_safe_iterator_property_map + (in_S_vec.begin(), in_S_vec.size(), index_map2 +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + , in_S_vec.front() +#endif /* BOOST_NO_STD_ITERATOR_TRAITS */ + ); + } + + bool test_isomorphism() + { + { + std::vector invar1_array; + BGL_FORALL_VERTICES_T(v, G1, Graph1) + invar1_array.push_back(invariant1(v)); + sort(invar1_array); + + std::vector invar2_array; + BGL_FORALL_VERTICES_T(v, G2, Graph2) + invar2_array.push_back(invariant2(v)); + sort(invar2_array); + if (! equal(invar1_array, invar2_array)) + return false; + } + + std::vector V_mult; + BGL_FORALL_VERTICES_T(v, G1, Graph1) + V_mult.push_back(v); + { + std::vector multiplicity(max_invariant, 0); + BGL_FORALL_VERTICES_T(v, G1, Graph1) + ++multiplicity[invariant1(v)]; + sort(V_mult, compare_multiplicity(invariant1, &multiplicity[0])); + } + + std::vector color_vec(num_vertices(G1)); + safe_iterator_property_map::iterator, + IndexMap1 +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + , default_color_type, default_color_type& +#endif /* BOOST_NO_STD_ITERATOR_TRAITS */ + > + color_map(color_vec.begin(), color_vec.size(), index_map1); + record_dfs_order dfs_visitor(dfs_vertices, ordered_edges); + typedef color_traits Color; + for (vertex_iter u = V_mult.begin(); u != V_mult.end(); ++u) { + if (color_map[*u] == Color::white()) { + dfs_visitor.start_vertex(*u, G1); + depth_first_visit(G1, *u, dfs_visitor, color_map); + } + } + // Create the dfs_num array and dfs_num_map + dfs_num_vec.resize(num_vertices(G1)); + dfs_num = make_safe_iterator_property_map(dfs_num_vec.begin(), + dfs_num_vec.size(), + index_map1 +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + , dfs_num_vec.front() +#endif /* BOOST_NO_STD_ITERATOR_TRAITS */ + ); + size_type n = 0; + for (vertex_iter v = dfs_vertices.begin(); v != dfs_vertices.end(); ++v) + dfs_num[*v] = n++; + + sort(ordered_edges, edge_cmp(G1, dfs_num)); + + + int dfs_num_k = -1; + return this->match(ordered_edges.begin(), dfs_num_k); + } + + private: + bool match(edge_iter iter, int dfs_num_k) + { + if (iter != ordered_edges.end()) { + vertex1_t i = source(*iter, G1), j = target(*iter, G2); + if (dfs_num[i] > dfs_num_k) { + vertex1_t kp1 = dfs_vertices[dfs_num_k + 1]; + BGL_FORALL_VERTICES_T(u, G2, Graph2) { + if (invariant1(kp1) == invariant2(u) && in_S[u] == false) { + f[kp1] = u; + in_S[u] = true; + num_edges_on_k = 0; + + if (match(iter, dfs_num_k + 1)) +#if 0 + // dwa 2003/7/11 -- this *HAS* to be a bug! + ; +#endif + return true; + + in_S[u] = false; + } + } + + } + else if (dfs_num[j] > dfs_num_k) { + vertex1_t k = dfs_vertices[dfs_num_k]; + num_edges_on_k -= + count_if(adjacent_vertices(f[k], G2), make_indirect_pmap(in_S)); + + for (int jj = 0; jj < dfs_num_k; ++jj) { + vertex1_t j = dfs_vertices[jj]; + num_edges_on_k -= count(adjacent_vertices(f[j], G2), f[k]); + } + + if (num_edges_on_k != 0) + return false; + BGL_FORALL_ADJ_T(f[i], v, G2, Graph2) + if (invariant2(v) == invariant1(j) && in_S[v] == false) { + f[j] = v; + in_S[v] = true; + num_edges_on_k = 1; + BOOST_USING_STD_MAX(); + int next_k = max BOOST_PREVENT_MACRO_SUBSTITUTION(dfs_num_k, max BOOST_PREVENT_MACRO_SUBSTITUTION(dfs_num[i], dfs_num[j])); + if (match(next(iter), next_k)) + return true; + in_S[v] = false; + } + + + } + else { + if (container_contains(adjacent_vertices(f[i], G2), f[j])) { + ++num_edges_on_k; + if (match(next(iter), dfs_num_k)) + return true; + } + + } + } else + return true; + return false; + } + + }; + + + template + void compute_in_degree(const Graph& g, InDegreeMap in_degree_map) + { + BGL_FORALL_VERTICES_T(v, g, Graph) + put(in_degree_map, v, 0); + + BGL_FORALL_VERTICES_T(u, g, Graph) + BGL_FORALL_ADJ_T(u, v, g, Graph) + put(in_degree_map, v, get(in_degree_map, v) + 1); + } + + } // namespace detail + + + template + class degree_vertex_invariant + { + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::degree_size_type size_type; + public: + typedef vertex_t argument_type; + typedef size_type result_type; + + degree_vertex_invariant(const InDegreeMap& in_degree_map, const Graph& g) + : m_in_degree_map(in_degree_map), m_g(g) { } + + size_type operator()(vertex_t v) const { + return (num_vertices(m_g) + 1) * out_degree(v, m_g) + + get(m_in_degree_map, v); + } + // The largest possible vertex invariant number + size_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { + return num_vertices(m_g) * num_vertices(m_g) + num_vertices(m_g); + } + private: + InDegreeMap m_in_degree_map; + const Graph& m_g; + }; + + + template + bool isomorphism(const Graph1& G1, const Graph2& G2, IsoMapping f, + Invariant1 invariant1, Invariant2 invariant2, + std::size_t max_invariant, + IndexMap1 index_map1, IndexMap2 index_map2) + + { + // Graph requirements + function_requires< VertexListGraphConcept >(); + function_requires< EdgeListGraphConcept >(); + function_requires< VertexListGraphConcept >(); + function_requires< BidirectionalGraphConcept >(); + + typedef typename graph_traits::vertex_descriptor vertex1_t; + typedef typename graph_traits::vertex_descriptor vertex2_t; + typedef typename graph_traits::vertices_size_type size_type; + + // Vertex invariant requirement + function_requires< AdaptableUnaryFunctionConcept >(); + function_requires< AdaptableUnaryFunctionConcept >(); + + // Property map requirements + function_requires< ReadWritePropertyMapConcept >(); + typedef typename property_traits::value_type IsoMappingValue; + BOOST_STATIC_ASSERT((is_same::value)); + + function_requires< ReadablePropertyMapConcept >(); + typedef typename property_traits::value_type IndexMap1Value; + BOOST_STATIC_ASSERT((is_convertible::value)); + + function_requires< ReadablePropertyMapConcept >(); + typedef typename property_traits::value_type IndexMap2Value; + BOOST_STATIC_ASSERT((is_convertible::value)); + + if (num_vertices(G1) != num_vertices(G2)) + return false; + if (num_vertices(G1) == 0 && num_vertices(G2) == 0) + return true; + + detail::isomorphism_algo + algo(G1, G2, f, invariant1, invariant2, max_invariant, + index_map1, index_map2); + return algo.test_isomorphism(); + } + + + namespace detail { + + template + bool isomorphism_impl(const Graph1& G1, const Graph2& G2, + IsoMapping f, IndexMap1 index_map1, IndexMap2 index_map2, + const bgl_named_params& params) + { + std::vector in_degree1_vec(num_vertices(G1)); + typedef safe_iterator_property_map::iterator, + IndexMap1 +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + , std::size_t, std::size_t& +#endif /* BOOST_NO_STD_ITERATOR_TRAITS */ + > InDeg1; + InDeg1 in_degree1(in_degree1_vec.begin(), in_degree1_vec.size(), index_map1); + compute_in_degree(G1, in_degree1); + + std::vector in_degree2_vec(num_vertices(G2)); + typedef safe_iterator_property_map::iterator, + IndexMap2 +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + , std::size_t, std::size_t& +#endif /* BOOST_NO_STD_ITERATOR_TRAITS */ + > InDeg2; + InDeg2 in_degree2(in_degree2_vec.begin(), in_degree2_vec.size(), index_map2); + compute_in_degree(G2, in_degree2); + + degree_vertex_invariant invariant1(in_degree1, G1); + degree_vertex_invariant invariant2(in_degree2, G2); + + return isomorphism(G1, G2, f, + choose_param(get_param(params, vertex_invariant1_t()), invariant1), + choose_param(get_param(params, vertex_invariant2_t()), invariant2), + choose_param(get_param(params, vertex_max_invariant_t()), (invariant2.max)()), + index_map1, index_map2 + ); + } + + } // namespace detail + + + // Named parameter interface + template + bool isomorphism(const Graph1& g1, + const Graph2& g2, + const bgl_named_params& params) + { + typedef typename graph_traits::vertex_descriptor vertex2_t; + typename std::vector::size_type n = num_vertices(g1); + std::vector f(n); + return detail::isomorphism_impl + (g1, g2, + choose_param(get_param(params, vertex_isomorphism_t()), + make_safe_iterator_property_map(f.begin(), f.size(), + choose_const_pmap(get_param(params, vertex_index1), + g1, vertex_index), vertex2_t())), + choose_const_pmap(get_param(params, vertex_index1), g1, vertex_index), + choose_const_pmap(get_param(params, vertex_index2), g2, vertex_index), + params + ); + } + + // All defaults interface + template + bool isomorphism(const Graph1& g1, const Graph2& g2) + { + return isomorphism(g1, g2, + bgl_named_params(0));// bogus named param + } + + + // Verify that the given mapping iso_map from the vertices of g1 to the + // vertices of g2 describes an isomorphism. + // Note: this could be made much faster by specializing based on the graph + // concepts modeled, but since we're verifying an O(n^(lg n)) algorithm, + // O(n^4) won't hurt us. + template + inline bool verify_isomorphism(const Graph1& g1, const Graph2& g2, IsoMap iso_map) + { +#if 0 + // problematic for filtered_graph! + if (num_vertices(g1) != num_vertices(g2) || num_edges(g1) != num_edges(g2)) + return false; +#endif + + for (typename graph_traits::edge_iterator e1 = edges(g1).first; + e1 != edges(g1).second; ++e1) { + bool found_edge = false; + for (typename graph_traits::edge_iterator e2 = edges(g2).first; + e2 != edges(g2).second && !found_edge; ++e2) { + if (source(*e2, g2) == get(iso_map, source(*e1, g1)) && + target(*e2, g2) == get(iso_map, target(*e1, g1))) { + found_edge = true; + } + } + + if (!found_edge) + return false; + } + + return true; + } + +} // namespace boost + +#ifdef BOOST_ISO_INCLUDED_ITER_MACROS +#undef BOOST_ISO_INCLUDED_ITER_MACROS +#include +#endif + +#endif // BOOST_GRAPH_ISOMORPHISM_HPP diff --git a/win32/include/boost/graph/iteration_macros.hpp b/win32/include/boost/graph/iteration_macros.hpp new file mode 100755 index 000000000..84aa2bad3 --- /dev/null +++ b/win32/include/boost/graph/iteration_macros.hpp @@ -0,0 +1,129 @@ +//======================================================================= +// Copyright 2001 Indiana University +// Author: Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_ITERATION_MACROS_HPP +#define BOOST_GRAPH_ITERATION_MACROS_HPP + +#define BGL_CAT(x,y) x ## y +#define BGL_FIRST(linenum) BGL_CAT(bgl_first_,linenum) +#define BGL_LAST(linenum) BGL_CAT(bgl_last_,linenum) + +/* + BGL_FORALL_VERTICES_T(v, g, graph_t) // This is on line 9 + expands to the following, but all on the same line + + for (typename boost::graph_traits::vertex_iterator + bgl_first_9 = vertices(g).first, bgl_last_9 = vertices(g).second; + bgl_first_9 != bgl_last_9; bgl_first_9 = bgl_last_9) + for (typename boost::graph_traits::vertex_descriptor v; + bgl_first_9 != bgl_last ? (v = *bgl_first_9, true) : false; + ++bgl_first_9) + + The purpose of having two for-loops is just to provide a place to + declare both the iterator and value variables. There is really only + one loop. The stopping condition gets executed two more times than it + usually would be, oh well. The reason for the bgl_first_9 = bgl_last_9 + in the outer for-loop is in case the user puts a break statement + in the inner for-loop. + + The other macros work in a similar fashion. + + Use the _T versions when the graph type is a template parameter or + dependent on a template parameter. Otherwise use the non _T versions. + + */ + + +#define BGL_FORALL_VERTICES_T(VNAME, GNAME, GraphType) \ +for (typename boost::graph_traits::vertex_iterator \ + BGL_FIRST(__LINE__) = vertices(GNAME).first, BGL_LAST(__LINE__) = vertices(GNAME).second; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \ + for (typename boost::graph_traits::vertex_descriptor VNAME; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (VNAME = *BGL_FIRST(__LINE__), true):false; \ + ++BGL_FIRST(__LINE__)) + +#define BGL_FORALL_VERTICES(VNAME, GNAME, GraphType) \ +for (boost::graph_traits::vertex_iterator \ + BGL_FIRST(__LINE__) = vertices(GNAME).first, BGL_LAST(__LINE__) = vertices(GNAME).second; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \ + for (boost::graph_traits::vertex_descriptor VNAME; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (VNAME = *BGL_FIRST(__LINE__), true):false; \ + ++BGL_FIRST(__LINE__)) + +#define BGL_FORALL_EDGES_T(ENAME, GNAME, GraphType) \ +for (typename boost::graph_traits::edge_iterator \ + BGL_FIRST(__LINE__) = edges(GNAME).first, BGL_LAST(__LINE__) = edges(GNAME).second; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \ + for (typename boost::graph_traits::edge_descriptor ENAME; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (ENAME = *BGL_FIRST(__LINE__), true):false; \ + ++BGL_FIRST(__LINE__)) + +#define BGL_FORALL_EDGES(ENAME, GNAME, GraphType) \ +for (boost::graph_traits::edge_iterator \ + BGL_FIRST(__LINE__) = edges(GNAME).first, BGL_LAST(__LINE__) = edges(GNAME).second; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \ + for (boost::graph_traits::edge_descriptor ENAME; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (ENAME = *BGL_FIRST(__LINE__), true):false; \ + ++BGL_FIRST(__LINE__)) + +#define BGL_FORALL_ADJ_T(UNAME, VNAME, GNAME, GraphType) \ +for (typename boost::graph_traits::adjacency_iterator \ + BGL_FIRST(__LINE__) = adjacent_vertices(UNAME, GNAME).first,\ + BGL_LAST(__LINE__) = adjacent_vertices(UNAME, GNAME).second; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \ +for (typename boost::graph_traits::vertex_descriptor VNAME; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (VNAME = *BGL_FIRST(__LINE__), true) : false; \ + ++BGL_FIRST(__LINE__)) + +#define BGL_FORALL_ADJ(UNAME, VNAME, GNAME, GraphType) \ +for (boost::graph_traits::adjacency_iterator \ + BGL_FIRST(__LINE__) = adjacent_vertices(UNAME, GNAME).first,\ + BGL_LAST(__LINE__) = adjacent_vertices(UNAME, GNAME).second; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \ +for (boost::graph_traits::vertex_descriptor VNAME; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (VNAME = *BGL_FIRST(__LINE__), true) : false; \ + ++BGL_FIRST(__LINE__)) + +#define BGL_FORALL_OUTEDGES_T(UNAME, ENAME, GNAME, GraphType) \ +for (typename boost::graph_traits::out_edge_iterator \ + BGL_FIRST(__LINE__) = out_edges(UNAME, GNAME).first,\ + BGL_LAST(__LINE__) = out_edges(UNAME, GNAME).second; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \ +for (typename boost::graph_traits::edge_descriptor ENAME; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (ENAME = *BGL_FIRST(__LINE__), true) : false; \ + ++BGL_FIRST(__LINE__)) + +#define BGL_FORALL_OUTEDGES(UNAME, ENAME, GNAME, GraphType) \ +for (boost::graph_traits::out_edge_iterator \ + BGL_FIRST(__LINE__) = out_edges(UNAME, GNAME).first,\ + BGL_LAST(__LINE__) = out_edges(UNAME, GNAME).second; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \ +for (boost::graph_traits::edge_descriptor ENAME; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (ENAME = *BGL_FIRST(__LINE__), true) : false; \ + ++BGL_FIRST(__LINE__)) + +#define BGL_FORALL_INEDGES_T(UNAME, ENAME, GNAME, GraphType) \ +for (typename boost::graph_traits::in_edge_iterator \ + BGL_FIRST(__LINE__) = in_edges(UNAME, GNAME).first,\ + BGL_LAST(__LINE__) = in_edges(UNAME, GNAME).second; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \ +for (typename boost::graph_traits::edge_descriptor ENAME; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (ENAME = *BGL_FIRST(__LINE__), true) : false; \ + ++BGL_FIRST(__LINE__)) + +#define BGL_FORALL_INEDGES(UNAME, ENAME, GNAME, GraphType) \ +for (boost::graph_traits::in_edge_iterator \ + BGL_FIRST(__LINE__) = in_edges(UNAME, GNAME).first,\ + BGL_LAST(__LINE__) = in_edges(UNAME, GNAME).second; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__); BGL_FIRST(__LINE__) = BGL_LAST(__LINE__)) \ +for (boost::graph_traits::edge_descriptor ENAME; \ + BGL_FIRST(__LINE__) != BGL_LAST(__LINE__) ? (ENAME = *BGL_FIRST(__LINE__), true) : false; \ + ++BGL_FIRST(__LINE__)) + +#endif // BOOST_GRAPH_ITERATION_MACROS_HPP diff --git a/win32/include/boost/graph/iteration_macros_undef.hpp b/win32/include/boost/graph/iteration_macros_undef.hpp new file mode 100755 index 000000000..94aa14552 --- /dev/null +++ b/win32/include/boost/graph/iteration_macros_undef.hpp @@ -0,0 +1,22 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// 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) +//======================================================================= + +#ifdef BOOST_GRAPH_ITERATION_MACROS_HPP + +#undef BOOST_GRAPH_ITERATION_MACROS_HPP +#undef BGL_CAT +#undef BGL_FIRST +#undef BGL_LAST +#undef BGL_FORALL_VERTICES +#undef BGL_FORALL_EDGES +#undef BGL_FORALL_ADJACENT +#undef BGL_FORALL_OUTEDGES +#undef BGL_FORALL_INEDGES + +#endif diff --git a/win32/include/boost/graph/johnson_all_pairs_shortest.hpp b/win32/include/boost/graph/johnson_all_pairs_shortest.hpp new file mode 100755 index 000000000..340b6d0e6 --- /dev/null +++ b/win32/include/boost/graph/johnson_all_pairs_shortest.hpp @@ -0,0 +1,205 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// 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) +//======================================================================= + +/* + This file implements the function + + template + bool + johnson_all_pairs_shortest_paths + (VertexAndEdgeListGraph& g, + DistanceMatrix& D, + const bgl_named_params& params) + */ + +#ifndef BOOST_GRAPH_JOHNSON_HPP +#define BOOST_GRAPH_JOHNSON_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { + + template + bool + johnson_all_pairs_shortest_paths(VertexAndEdgeListGraph& g1, + DistanceMatrix& D, + VertexID id1, Weight w1, const BinaryPredicate& compare, + const BinaryFunction& combine, const Infinity& inf, + DistanceZero zero) + { + typedef graph_traits Traits1; + typedef typename property_traits::value_type DT; + function_requires< BasicMatrixConcept >(); + + typedef typename Traits1::directed_category DirCat; + bool is_undirected = is_same::value; + + typedef adjacency_list, + property< edge_weight_t, DT, + property< edge_weight2_t, DT > > > Graph2; + typedef graph_traits Traits2; + + Graph2 g2(num_vertices(g1) + 1); + typename property_map::type + w = get(edge_weight, g2); + typename property_map::type + w_hat = get(edge_weight2, g2); + typename property_map::type + d = get(vertex_distance, g2); + typedef typename property_map::type VertexID2; + VertexID2 id2 = get(vertex_index, g2); + + // Construct g2 where V[g2] = V[g1] U {s} + // and E[g2] = E[g1] U {(s,v)| v in V[g1]} + std::vector + verts1(num_vertices(g1) + 1); + typename Traits2::vertex_descriptor s = *vertices(g2).first; + { + typename Traits1::vertex_iterator v, v_end; + int i = 1; + for (tie(v, v_end) = vertices(g1); v != v_end; ++v, ++i) { + typename Traits2::edge_descriptor e; bool z; + tie(e, z) = add_edge(s, get(id1, *v) + 1, g2); + put(w, e, zero); + verts1[i] = *v; + } + typename Traits1::edge_iterator e, e_end; + for (tie(e, e_end) = edges(g1); e != e_end; ++e) { + typename Traits2::edge_descriptor e2; bool z; + tie(e2, z) = add_edge(get(id1, source(*e, g1)) + 1, + get(id1, target(*e, g1)) + 1, g2); + put(w, e2, get(w1, *e)); + if (is_undirected) { + tie(e2, z) = add_edge(get(id1, target(*e, g1)) + 1, + get(id1, source(*e, g1)) + 1, g2); + put(w, e2, get(w1, *e)); + } + } + } + typename Traits2::vertex_iterator v, v_end, u, u_end; + typename Traits2::edge_iterator e, e_end; + std::vector

            h_vec(num_vertices(g2)); + typedef typename std::vector
            ::iterator iter_t; + iterator_property_map h(h_vec.begin(), id2); + + for (tie(v, v_end) = vertices(g2); v != v_end; ++v) + d[*v] = inf; + + put(d, s, zero); + // Using the non-named parameter versions of bellman_ford and + // dijkstra for portability reasons. + dummy_property_map pred; bellman_visitor<> bvis; + if (bellman_ford_shortest_paths + (g2, num_vertices(g2), w, pred, d, combine, compare, bvis)) { + for (tie(v, v_end) = vertices(g2); v != v_end; ++v) + put(h, *v, get(d, *v)); + // Reweight the edges to remove negatives + for (tie(e, e_end) = edges(g2); e != e_end; ++e) { + typename Traits2::vertex_descriptor a = source(*e, g2), + b = target(*e, g2); + put(w_hat, *e, get(w, *e) + get(h, a) - get(h, b)); + } + for (tie(u, u_end) = vertices(g2); u != u_end; ++u) { + dijkstra_visitor<> dvis; + dijkstra_shortest_paths + (g2, *u, pred, d, w_hat, id2, compare, combine, inf, zero,dvis); + for (tie(v, v_end) = vertices(g2); v != v_end; ++v) { + if (*u != s && *v != s) { + typename Traits1::vertex_descriptor u1, v1; + u1 = verts1[id2[*u]]; v1 = verts1[id2[*v]]; + D[id2[*u]-1][id2[*v]-1] = get(d, *v) + get(h, *v) - get(h, *u); + } + } + } + return true; + } else + return false; + } + + template + bool + johnson_all_pairs_shortest_paths(VertexAndEdgeListGraph& g1, + DistanceMatrix& D, + VertexID id1, Weight w1, DistanceZero zero) + { + typedef typename property_traits::value_type WT; + return johnson_all_pairs_shortest_paths(g1, D, id1, w1, + std::less(), + closed_plus(), + (std::numeric_limits::max)(), + zero); + } + + namespace detail { + + template + bool + johnson_dispatch(VertexAndEdgeListGraph& g, + DistanceMatrix& D, + const bgl_named_params& params, + Weight w, VertexID id) + { + typedef typename property_traits::value_type WT; + + return johnson_all_pairs_shortest_paths + (g, D, id, w, + choose_param(get_param(params, distance_compare_t()), + std::less()), + choose_param(get_param(params, distance_combine_t()), + closed_plus()), + choose_param(get_param(params, distance_inf_t()), + std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()), + choose_param(get_param(params, distance_zero_t()), WT()) ); + } + + } // namespace detail + + template + bool + johnson_all_pairs_shortest_paths + (VertexAndEdgeListGraph& g, + DistanceMatrix& D, + const bgl_named_params& params) + { + return detail::johnson_dispatch + (g, D, params, + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index) + ); + } + + template + bool + johnson_all_pairs_shortest_paths + (VertexAndEdgeListGraph& g, DistanceMatrix& D) + { + bgl_named_params params(1); + return detail::johnson_dispatch + (g, D, params, get(edge_weight, g), get(vertex_index, g)); + } + +} // namespace boost + +#endif // BOOST_GRAPH_JOHNSON_HPP + + diff --git a/win32/include/boost/graph/kamada_kawai_spring_layout.hpp b/win32/include/boost/graph/kamada_kawai_spring_layout.hpp new file mode 100755 index 000000000..3a12ccbdd --- /dev/null +++ b/win32/include/boost/graph/kamada_kawai_spring_layout.hpp @@ -0,0 +1,542 @@ +// Copyright 2004 The Trustees of Indiana University. + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_KAMADA_KAWAI_SPRING_LAYOUT_HPP +#define BOOST_GRAPH_KAMADA_KAWAI_SPRING_LAYOUT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + namespace detail { namespace graph { + /** + * Denotes an edge or display area side length used to scale a + * Kamada-Kawai drawing. + */ + template + struct edge_or_side + { + explicit edge_or_side(T value) : value(value) {} + + T value; + }; + + /** + * Compute the edge length from an edge length. This is trivial. + */ + template + T compute_edge_length(const Graph&, DistanceMap, IndexMap, + edge_or_side length) + { return length.value; } + + /** + * Compute the edge length based on the display area side + length. We do this by dividing the side length by the largest + shortest distance between any two vertices in the graph. + */ + template + T + compute_edge_length(const Graph& g, DistanceMap distance, IndexMap index, + edge_or_side length) + { + T result(0); + + typedef typename graph_traits::vertex_iterator vertex_iterator; + + for (vertex_iterator ui = vertices(g).first, end = vertices(g).second; + ui != end; ++ui) { + vertex_iterator vi = ui; + for (++vi; vi != end; ++vi) { + T dij = distance[get(index, *ui)][get(index, *vi)]; + if (dij > result) result = dij; + } + } + return length.value / result; + } + + /** + * Implementation of the Kamada-Kawai spring layout algorithm. + */ + template + struct kamada_kawai_spring_layout_impl + { + typedef typename property_traits::value_type weight_type; + typedef std::pair deriv_type; + typedef typename graph_traits::vertex_iterator vertex_iterator; + typedef typename graph_traits::vertex_descriptor + vertex_descriptor; + + kamada_kawai_spring_layout_impl( + const Graph& g, + PositionMap position, + WeightMap weight, + EdgeOrSideLength edge_or_side_length, + Done done, + weight_type spring_constant, + VertexIndexMap index, + DistanceMatrix distance, + SpringStrengthMatrix spring_strength, + PartialDerivativeMap partial_derivatives) + : g(g), position(position), weight(weight), + edge_or_side_length(edge_or_side_length), done(done), + spring_constant(spring_constant), index(index), distance(distance), + spring_strength(spring_strength), + partial_derivatives(partial_derivatives) {} + + // Compute contribution of vertex i to the first partial + // derivatives (dE/dx_m, dE/dy_m) (for vertex m) + deriv_type + compute_partial_derivative(vertex_descriptor m, vertex_descriptor i) + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif // BOOST_NO_STDC_NAMESPACE + + deriv_type result(0, 0); + if (i != m) { + weight_type x_diff = position[m].x - position[i].x; + weight_type y_diff = position[m].y - position[i].y; + weight_type dist = sqrt(x_diff * x_diff + y_diff * y_diff); + result.first = spring_strength[get(index, m)][get(index, i)] + * (x_diff - distance[get(index, m)][get(index, i)]*x_diff/dist); + result.second = spring_strength[get(index, m)][get(index, i)] + * (y_diff - distance[get(index, m)][get(index, i)]*y_diff/dist); + } + + return result; + } + + // Compute partial derivatives dE/dx_m and dE/dy_m + deriv_type + compute_partial_derivatives(vertex_descriptor m) + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif // BOOST_NO_STDC_NAMESPACE + + deriv_type result(0, 0); + + // TBD: looks like an accumulate to me + std::pair verts = vertices(g); + for (/* no init */; verts.first != verts.second; ++verts.first) { + vertex_descriptor i = *verts.first; + deriv_type deriv = compute_partial_derivative(m, i); + result.first += deriv.first; + result.second += deriv.second; + } + + return result; + } + + // The actual Kamada-Kawai spring layout algorithm implementation + bool run() + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif // BOOST_NO_STDC_NAMESPACE + + // Compute d_{ij} and place it in the distance matrix + if (!johnson_all_pairs_shortest_paths(g, distance, index, weight, + weight_type(0))) + return false; + + // Compute L based on side length (if needed), or retrieve L + weight_type edge_length = + detail::graph::compute_edge_length(g, distance, index, + edge_or_side_length); + + // Compute l_{ij} and k_{ij} + const weight_type K = spring_constant; + vertex_iterator ui, end = vertices(g).second; + for (ui = vertices(g).first; ui != end; ++ui) { + vertex_iterator vi = ui; + for (++vi; vi != end; ++vi) { + weight_type dij = distance[get(index, *ui)][get(index, *vi)]; + if (dij == (std::numeric_limits::max)()) + return false; + distance[get(index, *ui)][get(index, *vi)] = edge_length * dij; + distance[get(index, *vi)][get(index, *ui)] = edge_length * dij; + spring_strength[get(index, *ui)][get(index, *vi)] = K/(dij*dij); + spring_strength[get(index, *vi)][get(index, *ui)] = K/(dij*dij); + } + } + + // Compute Delta_i and find max + vertex_descriptor p = *vertices(g).first; + weight_type delta_p(0); + + for (ui = vertices(g).first; ui != end; ++ui) { + deriv_type deriv = compute_partial_derivatives(*ui); + put(partial_derivatives, *ui, deriv); + + weight_type delta = + sqrt(deriv.first*deriv.first + deriv.second*deriv.second); + + if (delta > delta_p) { + p = *ui; + delta_p = delta; + } + } + + while (!done(delta_p, p, g, true)) { + // The contribution p makes to the partial derivatives of + // each vertex. Computing this (at O(n) cost) allows us to + // update the delta_i values in O(n) time instead of O(n^2) + // time. + std::vector p_partials(num_vertices(g)); + for (ui = vertices(g).first; ui != end; ++ui) { + vertex_descriptor i = *ui; + p_partials[get(index, i)] = compute_partial_derivative(i, p); + } + + do { + // Compute the 4 elements of the Jacobian + weight_type dE_dx_dx = 0, dE_dx_dy = 0, dE_dy_dx = 0, dE_dy_dy = 0; + for (ui = vertices(g).first; ui != end; ++ui) { + vertex_descriptor i = *ui; + if (i != p) { + weight_type x_diff = position[p].x - position[i].x; + weight_type y_diff = position[p].y - position[i].y; + weight_type dist = sqrt(x_diff * x_diff + y_diff * y_diff); + weight_type dist_cubed = dist * dist * dist; + weight_type k_mi = spring_strength[get(index,p)][get(index,i)]; + weight_type l_mi = distance[get(index, p)][get(index, i)]; + dE_dx_dx += k_mi * (1 - (l_mi * y_diff * y_diff)/dist_cubed); + dE_dx_dy += k_mi * l_mi * x_diff * y_diff / dist_cubed; + dE_dy_dx += k_mi * l_mi * x_diff * y_diff / dist_cubed; + dE_dy_dy += k_mi * (1 - (l_mi * x_diff * x_diff)/dist_cubed); + } + } + + // Solve for delta_x and delta_y + weight_type dE_dx = get(partial_derivatives, p).first; + weight_type dE_dy = get(partial_derivatives, p).second; + + weight_type delta_x = + (dE_dx_dy * dE_dy - dE_dy_dy * dE_dx) + / (dE_dx_dx * dE_dy_dy - dE_dx_dy * dE_dy_dx); + + weight_type delta_y = + (dE_dx_dx * dE_dy - dE_dy_dx * dE_dx) + / (dE_dy_dx * dE_dx_dy - dE_dx_dx * dE_dy_dy); + + + // Move p by (delta_x, delta_y) + position[p].x += delta_x; + position[p].y += delta_y; + + // Recompute partial derivatives and delta_p + deriv_type deriv = compute_partial_derivatives(p); + put(partial_derivatives, p, deriv); + + delta_p = + sqrt(deriv.first*deriv.first + deriv.second*deriv.second); + } while (!done(delta_p, p, g, false)); + + // Select new p by updating each partial derivative and delta + vertex_descriptor old_p = p; + for (ui = vertices(g).first; ui != end; ++ui) { + deriv_type old_deriv_p = p_partials[get(index, *ui)]; + deriv_type old_p_partial = + compute_partial_derivative(*ui, old_p); + deriv_type deriv = get(partial_derivatives, *ui); + + deriv.first += old_p_partial.first - old_deriv_p.first; + deriv.second += old_p_partial.second - old_deriv_p.second; + + put(partial_derivatives, *ui, deriv); + weight_type delta = + sqrt(deriv.first*deriv.first + deriv.second*deriv.second); + + if (delta > delta_p) { + p = *ui; + delta_p = delta; + } + } + } + + return true; + } + + const Graph& g; + PositionMap position; + WeightMap weight; + EdgeOrSideLength edge_or_side_length; + Done done; + weight_type spring_constant; + VertexIndexMap index; + DistanceMatrix distance; + SpringStrengthMatrix spring_strength; + PartialDerivativeMap partial_derivatives; + }; + } } // end namespace detail::graph + + /// States that the given quantity is an edge length. + template + inline detail::graph::edge_or_side + edge_length(T x) + { return detail::graph::edge_or_side(x); } + + /// States that the given quantity is a display area side length. + template + inline detail::graph::edge_or_side + side_length(T x) + { return detail::graph::edge_or_side(x); } + + /** + * \brief Determines when to terminate layout of a particular graph based + * on a given relative tolerance. + */ + template + struct layout_tolerance + { + layout_tolerance(const T& tolerance = T(0.001)) + : tolerance(tolerance), last_energy((std::numeric_limits::max)()), + last_local_energy((std::numeric_limits::max)()) { } + + template + bool + operator()(T delta_p, + typename boost::graph_traits::vertex_descriptor p, + const Graph& g, + bool global) + { + if (global) { + if (last_energy == (std::numeric_limits::max)()) { + last_energy = delta_p; + return false; + } + + T diff = last_energy - delta_p; + if (diff < T(0)) diff = -diff; + bool done = (delta_p == T(0) || diff / last_energy < tolerance); + last_energy = delta_p; + return done; + } else { + if (last_local_energy == (std::numeric_limits::max)()) { + last_local_energy = delta_p; + return delta_p == T(0); + } + + T diff = last_local_energy - delta_p; + bool done = (delta_p == T(0) || (diff / last_local_energy) < tolerance); + last_local_energy = delta_p; + return done; + } + } + + private: + T tolerance; + T last_energy; + T last_local_energy; + }; + + /** \brief Kamada-Kawai spring layout for undirected graphs. + * + * This algorithm performs graph layout (in two dimensions) for + * connected, undirected graphs. It operates by relating the layout + * of graphs to a dynamic spring system and minimizing the energy + * within that system. The strength of a spring between two vertices + * is inversely proportional to the square of the shortest distance + * (in graph terms) between those two vertices. Essentially, + * vertices that are closer in the graph-theoretic sense (i.e., by + * following edges) will have stronger springs and will therefore be + * placed closer together. + * + * Prior to invoking this algorithm, it is recommended that the + * vertices be placed along the vertices of a regular n-sided + * polygon. + * + * \param g (IN) must be a model of Vertex List Graph, Edge List + * Graph, and Incidence Graph and must be undirected. + * + * \param position (OUT) must be a model of Lvalue Property Map, + * where the value type is a class containing fields @c x and @c y + * that will be set to the @c x and @c y coordinates of each vertex. + * + * \param weight (IN) must be a model of Readable Property Map, + * which provides the weight of each edge in the graph @p g. + * + * \param edge_or_side_length (IN) provides either the unit length + * @c e of an edge in the layout or the length of a side @c s of the + * display area, and must be either @c boost::edge_length(e) or @c + * boost::side_length(s), respectively. + * + * \param done (IN) is a 4-argument function object that is passed + * the current value of delta_p (i.e., the energy of vertex @p p), + * the vertex @p p, the graph @p g, and a boolean flag indicating + * whether @p delta_p is the maximum energy in the system (when @c + * true) or the energy of the vertex being moved. Defaults to @c + * layout_tolerance instantiated over the value type of the weight + * map. + * + * \param spring_constant (IN) is the constant multiplied by each + * spring's strength. Larger values create systems with more energy + * that can take longer to stabilize; smaller values create systems + * with less energy that stabilize quickly but do not necessarily + * result in pleasing layouts. The default value is 1. + * + * \param index (IN) is a mapping from vertices to index values + * between 0 and @c num_vertices(g). The default is @c + * get(vertex_index,g). + * + * \param distance (UTIL/OUT) will be used to store the distance + * from every vertex to every other vertex, which is computed in the + * first stages of the algorithm. This value's type must be a model + * of BasicMatrix with value type equal to the value type of the + * weight map. The default is a a vector of vectors. + * + * \param spring_strength (UTIL/OUT) will be used to store the + * strength of the spring between every pair of vertices. This + * value's type must be a model of BasicMatrix with value type equal + * to the value type of the weight map. The default is a a vector of + * vectors. + * + * \param partial_derivatives (UTIL) will be used to store the + * partial derivates of each vertex with respect to the @c x and @c + * y coordinates. This must be a Read/Write Property Map whose value + * type is a pair with both types equivalent to the value type of + * the weight map. The default is an iterator property map. + * + * \returns @c true if layout was successful or @c false if a + * negative weight cycle was detected. + */ + template + bool + kamada_kawai_spring_layout( + const Graph& g, + PositionMap position, + WeightMap weight, + detail::graph::edge_or_side edge_or_side_length, + Done done, + typename property_traits::value_type spring_constant, + VertexIndexMap index, + DistanceMatrix distance, + SpringStrengthMatrix spring_strength, + PartialDerivativeMap partial_derivatives) + { + BOOST_STATIC_ASSERT((is_convertible< + typename graph_traits::directed_category*, + undirected_tag* + >::value)); + + detail::graph::kamada_kawai_spring_layout_impl< + Graph, PositionMap, WeightMap, + detail::graph::edge_or_side, Done, VertexIndexMap, + DistanceMatrix, SpringStrengthMatrix, PartialDerivativeMap> + alg(g, position, weight, edge_or_side_length, done, spring_constant, + index, distance, spring_strength, partial_derivatives); + return alg.run(); + } + + /** + * \overload + */ + template + bool + kamada_kawai_spring_layout( + const Graph& g, + PositionMap position, + WeightMap weight, + detail::graph::edge_or_side edge_or_side_length, + Done done, + typename property_traits::value_type spring_constant, + VertexIndexMap index) + { + typedef typename property_traits::value_type weight_type; + + typename graph_traits::vertices_size_type n = num_vertices(g); + typedef std::vector weight_vec; + + std::vector distance(n, weight_vec(n)); + std::vector spring_strength(n, weight_vec(n)); + std::vector > partial_derivatives(n); + + return + kamada_kawai_spring_layout( + g, position, weight, edge_or_side_length, done, spring_constant, index, + distance.begin(), + spring_strength.begin(), + make_iterator_property_map(partial_derivatives.begin(), index, + std::pair())); + } + + /** + * \overload + */ + template + bool + kamada_kawai_spring_layout( + const Graph& g, + PositionMap position, + WeightMap weight, + detail::graph::edge_or_side edge_or_side_length, + Done done, + typename property_traits::value_type spring_constant) + { + return kamada_kawai_spring_layout(g, position, weight, edge_or_side_length, + done, spring_constant, + get(vertex_index, g)); + } + + /** + * \overload + */ + template + bool + kamada_kawai_spring_layout( + const Graph& g, + PositionMap position, + WeightMap weight, + detail::graph::edge_or_side edge_or_side_length, + Done done) + { + typedef typename property_traits::value_type weight_type; + return kamada_kawai_spring_layout(g, position, weight, edge_or_side_length, + done, weight_type(1)); + } + + /** + * \overload + */ + template + bool + kamada_kawai_spring_layout( + const Graph& g, + PositionMap position, + WeightMap weight, + detail::graph::edge_or_side edge_or_side_length) + { + typedef typename property_traits::value_type weight_type; + return kamada_kawai_spring_layout(g, position, weight, edge_or_side_length, + layout_tolerance(), + weight_type(1.0), + get(vertex_index, g)); + } +} // end namespace boost + +#endif // BOOST_GRAPH_KAMADA_KAWAI_SPRING_LAYOUT_HPP diff --git a/win32/include/boost/graph/king_ordering.hpp b/win32/include/boost/graph/king_ordering.hpp new file mode 100755 index 000000000..e4c1a2dc8 --- /dev/null +++ b/win32/include/boost/graph/king_ordering.hpp @@ -0,0 +1,320 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2004, 2005 Trustees of Indiana University +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, +// Doug Gregor, D. Kevin McGrath +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//=======================================================================// +#ifndef BOOST_GRAPH_KING_HPP +#define BOOST_GRAPH_KING_HPP + +#include +#include + +/* + King Algorithm for matrix reordering +*/ + +namespace boost { + namespace detail { + template + class bfs_king_visitor:public default_bfs_visitor + { + public: + bfs_king_visitor(OutputIterator *iter, Buffer *b, Compare compare, + PseudoDegreeMap deg, std::vector loc, VecMap color, + VertexIndexMap vertices): + permutation(iter), Qptr(b), degree(deg), comp(compare), + Qlocation(loc), colors(color), vertex_map(vertices) { } + + template + void finish_vertex(Vertex, Graph& g) { + typename graph_traits::out_edge_iterator ei, ei_end; + Vertex v, w; + + typedef typename std::deque::iterator iterator; + typedef typename std::deque::reverse_iterator reverse_iterator; + + reverse_iterator rend = Qptr->rend()-index_begin; + reverse_iterator rbegin = Qptr->rbegin(); + + + //heap the vertices already there + std::make_heap(rbegin, rend, boost::bind(comp, _2, _1)); + + unsigned i = 0; + + for(i = index_begin; i != Qptr->size(); ++i){ + colors[get(vertex_map, (*Qptr)[i])] = 1; + Qlocation[get(vertex_map, (*Qptr)[i])] = i; + } + + i = 0; + + for( ; rbegin != rend; rend--){ + percolate_down(i); + w = (*Qptr)[index_begin+i]; + for (tie(ei, ei_end) = out_edges(w, g); ei != ei_end; ++ei) { + v = target(*ei, g); + put(degree, v, get(degree, v) - 1); + + if (colors[get(vertex_map, v)] == 1) { + percolate_up(get(vertex_map, v), i); + } + } + + colors[get(vertex_map, w)] = 0; + i++; + } + } + + template + void examine_vertex(Vertex u, const Graph&) { + + *(*permutation)++ = u; + index_begin = Qptr->size(); + + } + protected: + + + //this function replaces pop_heap, and tracks state information + template + void percolate_down(int offset){ + typedef typename std::deque::reverse_iterator reverse_iterator; + + int heap_last = index_begin + offset; + int heap_first = Qptr->size() - 1; + + //pop_heap functionality: + //swap first, last + std::swap((*Qptr)[heap_last], (*Qptr)[heap_first]); + + //swap in the location queue + std::swap(Qlocation[heap_first], Qlocation[heap_last]); + + //set drifter, children + int drifter = heap_first; + int drifter_heap = Qptr->size() - drifter; + + int right_child_heap = drifter_heap * 2 + 1; + int right_child = Qptr->size() - right_child_heap; + + int left_child_heap = drifter_heap * 2; + int left_child = Qptr->size() - left_child_heap; + + //check that we are staying in the heap + bool valid = (right_child < heap_last) ? false : true; + + //pick smallest child of drifter, and keep in mind there might only be left child + int smallest_child = (valid && get(degree, (*Qptr)[left_child]) > get(degree,(*Qptr)[right_child])) ? + right_child : left_child; + + while(valid && smallest_child < heap_last && comp((*Qptr)[drifter], (*Qptr)[smallest_child])){ + + //if smallest child smaller than drifter, swap them + std::swap((*Qptr)[smallest_child], (*Qptr)[drifter]); + std::swap(Qlocation[drifter], Qlocation[smallest_child]); + + //update the values, run again, as necessary + drifter = smallest_child; + drifter_heap = Qptr->size() - drifter; + + right_child_heap = drifter_heap * 2 + 1; + right_child = Qptr->size() - right_child_heap; + + left_child_heap = drifter_heap * 2; + left_child = Qptr->size() - left_child_heap; + + valid = (right_child < heap_last) ? false : true; + + smallest_child = (valid && get(degree, (*Qptr)[left_child]) > get(degree,(*Qptr)[right_child])) ? + right_child : left_child; + } + + } + + + + // this is like percolate down, but we always compare against the + // parent, as there is only a single choice + template + void percolate_up(int vertex, int offset){ + + int child_location = Qlocation[vertex]; + int heap_child_location = Qptr->size() - child_location; + int heap_parent_location = (int)(heap_child_location/2); + unsigned parent_location = Qptr->size() - heap_parent_location; + + bool valid = (heap_parent_location != 0 && child_location > index_begin + offset && + parent_location < Qptr->size()); + + while(valid && comp((*Qptr)[child_location], (*Qptr)[parent_location])){ + + //swap in the heap + std::swap((*Qptr)[child_location], (*Qptr)[parent_location]); + + //swap in the location queue + std::swap(Qlocation[child_location], Qlocation[parent_location]); + + child_location = parent_location; + heap_child_location = heap_parent_location; + heap_parent_location = (int)(heap_child_location/2); + parent_location = Qptr->size() - heap_parent_location; + valid = (heap_parent_location != 0 && child_location > index_begin + offset); + } + } + + OutputIterator *permutation; + int index_begin; + Buffer *Qptr; + PseudoDegreeMap degree; + Compare comp; + std::vector Qlocation; + VecMap colors; + VertexIndexMap vertex_map; + }; + + + } // namespace detail + + + template + OutputIterator + king_ordering(const Graph& g, + std::deque< typename graph_traits::vertex_descriptor > + vertex_queue, + OutputIterator permutation, + ColorMap color, DegreeMap degree, + VertexIndexMap index_map) + { + typedef typename property_traits::value_type ds_type; + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + typedef typename graph_traits::vertex_descriptor Vertex; + typedef iterator_property_map::iterator, VertexIndexMap, ds_type, ds_type&> PseudoDegreeMap; + typedef indirect_cmp > Compare; + typedef typename boost::sparse::sparse_ordering_queue queue; + typedef typename detail::bfs_king_visitor, VertexIndexMap > Visitor; + typedef typename graph_traits::vertices_size_type + vertices_size_type; + std::vector pseudo_degree_vec(num_vertices(g)); + PseudoDegreeMap pseudo_degree(pseudo_degree_vec.begin(), index_map); + + typename graph_traits::vertex_iterator ui, ui_end; + queue Q; + // Copy degree to pseudo_degree + // initialize the color map + for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui){ + put(pseudo_degree, *ui, get(degree, *ui)); + put(color, *ui, Color::white()); + } + + Compare comp(pseudo_degree); + std::vector colors(num_vertices(g)); + + for(vertices_size_type i = 0; i < num_vertices(g); i++) + colors[i] = 0; + + std::vector loc(num_vertices(g)); + + //create the visitor + Visitor vis(&permutation, &Q, comp, pseudo_degree, loc, colors, index_map); + + while( !vertex_queue.empty() ) { + Vertex s = vertex_queue.front(); + vertex_queue.pop_front(); + + //call BFS with visitor + breadth_first_visit(g, s, Q, vis, color); + } + + return permutation; + } + + + // This is the case where only a single starting vertex is supplied. + template + OutputIterator + king_ordering(const Graph& g, + typename graph_traits::vertex_descriptor s, + OutputIterator permutation, + ColorMap color, DegreeMap degree, VertexIndexMap index_map) + { + + std::deque< typename graph_traits::vertex_descriptor > vertex_queue; + vertex_queue.push_front( s ); + return king_ordering(g, vertex_queue, permutation, color, degree, + index_map); + } + + + template < class Graph, class OutputIterator, + class ColorMap, class DegreeMap, class VertexIndexMap> + OutputIterator + king_ordering(const Graph& G, OutputIterator permutation, + ColorMap color, DegreeMap degree, VertexIndexMap index_map) + { + if (vertices(G).first == vertices(G).second) + return permutation; + + typedef typename boost::graph_traits::vertex_descriptor Vertex; + typedef typename boost::graph_traits::vertex_iterator VerIter; + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + + std::deque vertex_queue; + + // Mark everything white + BGL_FORALL_VERTICES_T(v, G, Graph) put(color, v, Color::white()); + + // Find one vertex from each connected component + BGL_FORALL_VERTICES_T(v, G, Graph) { + if (get(color, v) == Color::white()) { + depth_first_visit(G, v, dfs_visitor<>(), color); + vertex_queue.push_back(v); + } + } + + // Find starting nodes for all vertices + // TBD: How to do this with a directed graph? + for (typename std::deque::iterator i = vertex_queue.begin(); + i != vertex_queue.end(); ++i) + *i = find_starting_node(G, *i, color, degree); + + return king_ordering(G, vertex_queue, permutation, color, degree, + index_map); + } + + template + OutputIterator + king_ordering(const Graph& G, OutputIterator permutation, + VertexIndexMap index_map) + { + if (vertices(G).first == vertices(G).second) + return permutation; + + typedef out_degree_property_map DegreeMap; + std::vector colors(num_vertices(G)); + return king_ordering(G, permutation, + make_iterator_property_map(&colors[0], index_map, + colors[0]), + make_out_degree_map(G), index_map); + } + + template + inline OutputIterator + king_ordering(const Graph& G, OutputIterator permutation) + { return king_ordering(G, permutation, get(vertex_index, G)); } + +} // namespace boost + + +#endif // BOOST_GRAPH_KING_HPP diff --git a/win32/include/boost/graph/kolmogorov_max_flow.hpp b/win32/include/boost/graph/kolmogorov_max_flow.hpp new file mode 100755 index 000000000..a10f155f3 --- /dev/null +++ b/win32/include/boost/graph/kolmogorov_max_flow.hpp @@ -0,0 +1,807 @@ +// Copyright (c) 2006, Stephan Diederich +// +// This code may be used under either of the following two licences: +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. OF SUCH DAMAGE. +// +// Or: +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_KOLMOGOROV_MAX_FLOW_HPP +#define BOOST_KOLMOGOROV_MAX_FLOW_HPP + +#include +#include +#include +#include +#include +#include +#include // for std::min and std::max + +#include +#include +#include +#include +#include +#include + +namespace boost { + namespace detail { + + template + class kolmogorov{ + typedef typename property_traits::value_type tEdgeVal; + typedef graph_traits tGraphTraits; + typedef typename tGraphTraits::vertex_iterator vertex_iterator; + typedef typename tGraphTraits::vertex_descriptor vertex_descriptor; + typedef typename tGraphTraits::edge_descriptor edge_descriptor; + typedef typename tGraphTraits::edge_iterator edge_iterator; + typedef typename tGraphTraits::out_edge_iterator out_edge_iterator; + typedef boost::queue tQueue; //queue of vertices, used in adoption-stage + typedef typename property_traits::value_type tColorValue; + typedef color_traits tColorTraits; + typedef typename property_traits::value_type tDistanceVal; + + public: + kolmogorov(Graph& g, + EdgeCapacityMap cap, + ResidualCapacityEdgeMap res, + ReverseEdgeMap rev, + PredecessorMap pre, + ColorMap color, + DistanceMap dist, + IndexMap idx, + vertex_descriptor src, + vertex_descriptor sink): + m_g(g), + m_index_map(idx), + m_cap_map(cap), + m_res_cap_map(res), + m_rev_edge_map(rev), + m_pre_map(pre), + m_tree_map(color), + m_dist_map(dist), + m_source(src), + m_sink(sink), + m_active_nodes(), + m_in_active_list_vec(num_vertices(g), false), + m_in_active_list_map(make_iterator_property_map(m_in_active_list_vec.begin(), m_index_map)), + m_has_parent_vec(num_vertices(g), false), + m_has_parent_map(make_iterator_property_map(m_has_parent_vec.begin(), m_index_map)), + m_time_vec(num_vertices(g), 0), + m_time_map(make_iterator_property_map(m_time_vec.begin(), m_index_map)), + m_flow(0), + m_time(1), + m_last_grow_vertex(graph_traits::null_vertex()){ + // initialize the color-map with gray-values + vertex_iterator vi, v_end; + for(tie(vi, v_end) = vertices(m_g); vi != v_end; ++vi){ + set_tree(*vi, tColorTraits::gray()); + } + // Initialize flow to zero which means initializing + // the residual capacity equal to the capacity + edge_iterator ei, e_end; + for(tie(ei, e_end) = edges(m_g); ei != e_end; ++ei) { + m_res_cap_map[*ei] = m_cap_map[*ei]; + assert(m_rev_edge_map[m_rev_edge_map[*ei]] == *ei); //check if the reverse edge map is build up properly + } + //init the search trees with the two terminals + set_tree(m_source, tColorTraits::black()); + set_tree(m_sink, tColorTraits::white()); + m_time_map[m_source] = 1; + m_time_map[m_sink] = 1; + } + + ~kolmogorov(){} + + tEdgeVal max_flow(){ + //augment direct paths from SOURCE->SINK and SOURCE->VERTEX->SINK + augment_direct_paths(); + //start the main-loop + while(true){ + bool path_found; + edge_descriptor connecting_edge; + tie(connecting_edge, path_found) = grow(); //find a path from source to sink + if(!path_found){ + //we're finished, no more paths were found + break; + } + ++m_time; + augment(connecting_edge); //augment that path + adopt(); //rebuild search tree structure + } + return m_flow; + } + + //the complete class is protected, as we want access to members in derived test-class (see $(BOOST_ROOT)/libs/graph/test/kolmogorov_max_flow_test.cpp) + protected: + void augment_direct_paths(){ + //in a first step, we augment all direct paths from source->NODE->sink + //and additionally paths from source->sink + //this improves especially graphcuts for segmentation, as most of the nodes have source/sink connects + //but shouldn't have an impact on other maxflow problems (this is done in grow() anyway) + out_edge_iterator ei, e_end; + for(tie(ei, e_end) = out_edges(m_source, m_g); ei != e_end; ++ei){ + edge_descriptor from_source = *ei; + vertex_descriptor current_node = target(from_source, m_g); + if(current_node == m_sink){ + tEdgeVal cap = m_res_cap_map[from_source]; + m_res_cap_map[from_source] = 0; + m_flow += cap; + continue; + } + edge_descriptor to_sink; + bool is_there; + tie(to_sink, is_there) = edge(current_node, m_sink, m_g); + if(is_there){ + tEdgeVal cap_from_source = m_res_cap_map[from_source]; + tEdgeVal cap_to_sink = m_res_cap_map[to_sink]; + if(cap_from_source > cap_to_sink){ + set_tree(current_node, tColorTraits::black()); + add_active_node(current_node); + set_edge_to_parent(current_node, from_source); + m_dist_map[current_node] = 1; + m_time_map[current_node] = 1; + //add stuff to flow and update residuals + //we dont need to update reverse_edges, as incoming/outgoing edges to/from source/sink don't count for max-flow + m_res_cap_map[from_source] -= cap_to_sink; + m_res_cap_map[to_sink] = 0; + m_flow += cap_to_sink; + } else if(cap_to_sink > 0){ + set_tree(current_node, tColorTraits::white()); + add_active_node(current_node); + set_edge_to_parent(current_node, to_sink); + m_dist_map[current_node] = 1; + m_time_map[current_node] = 1; + //add stuff to flow and update residuals + //we dont need to update reverse_edges, as incoming/outgoing edges to/from source/sink don't count for max-flow + m_res_cap_map[to_sink] -= cap_from_source; + m_res_cap_map[from_source] = 0; + m_flow += cap_from_source; + } + } else if(m_res_cap_map[from_source]){ + //there is no sink connect, so we can't augment this path + //but to avoid adding m_source to the active nodes, we just activate this node and set the approciate things + set_tree(current_node, tColorTraits::black()); + set_edge_to_parent(current_node, from_source); + m_dist_map[current_node] = 1; + m_time_map[current_node] = 1; + add_active_node(current_node); + } + } + for(tie(ei, e_end) = out_edges(m_sink, m_g); ei != e_end; ++ei){ + edge_descriptor to_sink = m_rev_edge_map[*ei]; + vertex_descriptor current_node = source(to_sink, m_g); + if(m_res_cap_map[to_sink]){ + set_tree(current_node, tColorTraits::white()); + set_edge_to_parent(current_node, to_sink); + m_dist_map[current_node] = 1; + m_time_map[current_node] = 1; + add_active_node(current_node); + } + } + } + + /** + * returns a pair of an edge and a boolean. if the bool is true, the edge is a connection of a found path from s->t , read "the link" and + * source(returnVal, m_g) is the end of the path found in the source-tree + * target(returnVal, m_g) is the beginning of the path found in the sink-tree + */ + std::pair grow(){ + assert(m_orphans.empty()); + vertex_descriptor current_node; + while((current_node = get_next_active_node()) != graph_traits::null_vertex()){ //if there is one + assert(get_tree(current_node) != tColorTraits::gray() && (has_parent(current_node) || current_node==m_source || current_node==m_sink)); + if(get_tree(current_node) == tColorTraits::black()){ + //source tree growing + out_edge_iterator ei, e_end; + if(current_node != m_last_grow_vertex){ + m_last_grow_vertex = current_node; + tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g); + } + for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){ + edge_descriptor out_edge = *m_last_grow_edge_it; + if(m_res_cap_map[out_edge] > 0){ //check if we have capacity left on this edge + vertex_descriptor other_node = target(out_edge, m_g); + if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node + set_tree(other_node, tColorTraits::black()); //aquire other node to our search tree + set_edge_to_parent(other_node, out_edge); //set us as parent + m_dist_map[other_node] = m_dist_map[current_node] + 1; //and update the distance-heuristic + m_time_map[other_node] = m_time_map[current_node]; + add_active_node(other_node); + } else if(get_tree(other_node) == tColorTraits::black()){ + if(is_closer_to_terminal(current_node, other_node)){ //we do this to get shorter paths. check if we are nearer to the source as its parent is + set_edge_to_parent(other_node, out_edge); + m_dist_map[other_node] = m_dist_map[current_node] + 1; + m_time_map[other_node] = m_time_map[current_node]; + } + } else{ + assert(get_tree(other_node)==tColorTraits::white()); + //kewl, found a path from one to the other search tree, return the connecting edge in src->sink dir + return std::make_pair(out_edge, true); + } + } + } //for all out-edges + } //source-tree-growing + else{ + assert(get_tree(current_node) == tColorTraits::white()); + out_edge_iterator ei, e_end; + if(current_node != m_last_grow_vertex){ + m_last_grow_vertex = current_node; + tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g); + } + for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){ + edge_descriptor in_edge = m_rev_edge_map[*m_last_grow_edge_it]; + if(m_res_cap_map[in_edge] > 0){ //check if there is capacity left + vertex_descriptor other_node = source(in_edge, m_g); + if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node + set_tree(other_node, tColorTraits::white()); //aquire that node to our search tree + set_edge_to_parent(other_node, in_edge); //set us as parent + add_active_node(other_node); //activate that node + m_dist_map[other_node] = m_dist_map[current_node] + 1; //set its distance + m_time_map[other_node] = m_time_map[current_node]; //and time + } else if(get_tree(other_node) == tColorTraits::white()){ + if(is_closer_to_terminal(current_node, other_node)){ + //we are closer to the sink than its parent is, so we "adopt" him + set_edge_to_parent(other_node, in_edge); + m_dist_map[other_node] = m_dist_map[current_node] + 1; + m_time_map[other_node] = m_time_map[current_node]; + } + } else{ + assert(get_tree(other_node)==tColorTraits::black()); + //kewl, found a path from one to the other search tree, return the connecting edge in src->sink dir + return std::make_pair(in_edge, true); + } + } + } //for all out-edges + } //sink-tree growing + //all edges of that node are processed, and no more paths were found. so remove if from the front of the active queue + finish_node(current_node); + } //while active_nodes not empty + return std::make_pair(edge_descriptor(), false); //no active nodes anymore and no path found, we're done + } + + /** + * augments path from s->t and updates residual graph + * source(e, m_g) is the end of the path found in the source-tree + * target(e, m_g) is the beginning of the path found in the sink-tree + * this phase generates orphans on satured edges, if the attached verts are from different search-trees + * orphans are ordered in distance to sink/source. first the farest from the source are front_inserted into the orphans list, + * and after that the sink-tree-orphans are front_inserted. when going to adoption stage the orphans are popped_front, and so we process the nearest + * verts to the terminals first + */ + void augment(edge_descriptor e){ + assert(get_tree(target(e, m_g)) == tColorTraits::white()); + assert(get_tree(source(e, m_g)) == tColorTraits::black()); + assert(m_orphans.empty()); + + const tEdgeVal bottleneck = find_bottleneck(e); + //now we push the found flow through the path + //for each edge we saturate we have to look for the verts that belong to that edge, one of them becomes an orphans + //now process the connecting edge + m_res_cap_map[e] -= bottleneck; + assert(m_res_cap_map[e] >= 0); + m_res_cap_map[m_rev_edge_map[e]] += bottleneck; + + //now we follow the path back to the source + vertex_descriptor current_node = source(e, m_g); + while(current_node != m_source){ + edge_descriptor pred = get_edge_to_parent(current_node); + m_res_cap_map[pred] -= bottleneck; + assert(m_res_cap_map[pred] >= 0); + m_res_cap_map[m_rev_edge_map[pred]] += bottleneck; + if(m_res_cap_map[pred] == 0){ + set_no_parent(current_node); + m_orphans.push_front(current_node); + } + current_node = source(pred, m_g); + } + //then go forward in the sink-tree + current_node = target(e, m_g); + while(current_node != m_sink){ + edge_descriptor pred = get_edge_to_parent(current_node); + m_res_cap_map[pred] -= bottleneck; + assert(m_res_cap_map[pred] >= 0); + m_res_cap_map[m_rev_edge_map[pred]] += bottleneck; + if(m_res_cap_map[pred] == 0){ + set_no_parent(current_node); + m_orphans.push_front(current_node); + } + current_node = target(pred, m_g); + } + //and add it to the max-flow + m_flow += bottleneck; + } + + /** + * returns the bottleneck of a s->t path (end_of_path is last vertex in source-tree, begin_of_path is first vertex in sink-tree) + */ + inline tEdgeVal find_bottleneck(edge_descriptor e){ + BOOST_USING_STD_MIN(); + tEdgeVal minimum_cap = m_res_cap_map[e]; + vertex_descriptor current_node = source(e, m_g); + //first go back in the source tree + while(current_node != m_source){ + edge_descriptor pred = get_edge_to_parent(current_node); + minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]); + current_node = source(pred, m_g); + } + //then go forward in the sink-tree + current_node = target(e, m_g); + while(current_node != m_sink){ + edge_descriptor pred = get_edge_to_parent(current_node); + minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, m_res_cap_map[pred]); + current_node = target(pred, m_g); + } + return minimum_cap; + } + + /** + * rebuild search trees + * empty the queue of orphans, and find new parents for them or just drop them from the search trees + */ + void adopt(){ + while(!m_orphans.empty() || !m_child_orphans.empty()){ + vertex_descriptor current_node; + if(m_child_orphans.empty()){ + //get the next orphan from the main-queue and remove it + current_node = m_orphans.front(); + m_orphans.pop_front(); + } else{ + current_node = m_child_orphans.front(); + m_child_orphans.pop(); + } + if(get_tree(current_node) == tColorTraits::black()){ + //we're in the source-tree + tDistanceVal min_distance = (std::numeric_limits::max)(); + edge_descriptor new_parent_edge; + out_edge_iterator ei, e_end; + for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ + const edge_descriptor in_edge = m_rev_edge_map[*ei]; + assert(target(in_edge, m_g) == current_node); //we should be the target of this edge + if(m_res_cap_map[in_edge] > 0){ + vertex_descriptor other_node = source(in_edge, m_g); + if(get_tree(other_node) == tColorTraits::black() && has_source_connect(other_node)){ + if(m_dist_map[other_node] < min_distance){ + min_distance = m_dist_map[other_node]; + new_parent_edge = in_edge; + } + } + } + } + if(min_distance != (std::numeric_limits::max)()){ + set_edge_to_parent(current_node, new_parent_edge); + m_dist_map[current_node] = min_distance + 1; + m_time_map[current_node] = m_time; + } else{ + m_time_map[current_node] = 0; + for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ + edge_descriptor in_edge = m_rev_edge_map[*ei]; + vertex_descriptor other_node = source(in_edge, m_g); + if(get_tree(other_node) == tColorTraits::black() && has_parent(other_node)){ + if(m_res_cap_map[in_edge] > 0){ + add_active_node(other_node); + } + if(source(get_edge_to_parent(other_node), m_g) == current_node){ + //we are the parent of that node + //it has to find a new parent, too + set_no_parent(other_node); + m_child_orphans.push(other_node); + } + } + } + set_tree(current_node, tColorTraits::gray()); + } //no parent found + } //source-tree-adoption + else{ + //now we should be in the sink-tree, check that... + assert(get_tree(current_node) == tColorTraits::white()); + out_edge_iterator ei, e_end; + edge_descriptor new_parent_edge; + tDistanceVal min_distance = (std::numeric_limits::max)(); + for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ + const edge_descriptor out_edge = *ei; + if(m_res_cap_map[out_edge] > 0){ + const vertex_descriptor other_node = target(out_edge, m_g); + if(get_tree(other_node) == tColorTraits::white() && has_sink_connect(other_node)) + if(m_dist_map[other_node] < min_distance){ + min_distance = m_dist_map[other_node]; + new_parent_edge = out_edge; + } + } + } + if(min_distance != (std::numeric_limits::max)()){ + set_edge_to_parent(current_node, new_parent_edge); + m_dist_map[current_node] = min_distance + 1; + m_time_map[current_node] = m_time; + } else{ + m_time_map[current_node] = 0; + for(tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){ + const edge_descriptor out_edge = *ei; + const vertex_descriptor other_node = target(out_edge, m_g); + if(get_tree(other_node) == tColorTraits::white() && has_parent(other_node)){ + if(m_res_cap_map[out_edge] > 0){ + add_active_node(other_node); + } + if(target(get_edge_to_parent(other_node), m_g) == current_node){ + //we were it's parent, so it has to find a new one, too + set_no_parent(other_node); + m_child_orphans.push(other_node); + } + } + } + set_tree(current_node, tColorTraits::gray()); + } //no parent found + } //sink-tree adoption + } //while !orphans.empty() + } //adopt + + /** + * return next active vertex if there is one, otherwise a null_vertex + */ + inline vertex_descriptor get_next_active_node(){ + while(true){ + if(m_active_nodes.empty()) + return graph_traits::null_vertex(); + vertex_descriptor v = m_active_nodes.front(); + + if(!has_parent(v) && v != m_source && v != m_sink){ //if it has no parent, this node can't be active(if its not source or sink) + m_active_nodes.pop(); + m_in_active_list_map[v] = false; + } else{ + assert(get_tree(v) == tColorTraits::black() || get_tree(v) == tColorTraits::white()); + return v; + } + } + } + + /** + * adds v as an active vertex, but only if its not in the list already + */ + inline void add_active_node(vertex_descriptor v){ + assert(get_tree(v) != tColorTraits::gray()); + if(m_in_active_list_map[v]){ + return; + } else{ + m_in_active_list_map[v] = true; + m_active_nodes.push(v); + } + } + + /** + * finish_node removes a node from the front of the active queue (its called in grow phase, if no more paths can be found using this node) + */ + inline void finish_node(vertex_descriptor v){ + assert(m_active_nodes.front() == v); + m_active_nodes.pop(); + m_in_active_list_map[v] = false; + m_last_grow_vertex = graph_traits::null_vertex(); + } + + /** + * removes a vertex from the queue of active nodes (actually this does nothing, + * but checks if this node has no parent edge, as this is the criteria for beeing no more active) + */ + inline void remove_active_node(vertex_descriptor v){ + assert(!has_parent(v)); + } + + /** + * returns the search tree of v; tColorValue::black() for source tree, white() for sink tree, gray() for no tree + */ + inline tColorValue get_tree(vertex_descriptor v) const { + return m_tree_map[v]; + } + + /** + * sets search tree of v; tColorValue::black() for source tree, white() for sink tree, gray() for no tree + */ + inline void set_tree(vertex_descriptor v, tColorValue t){ + m_tree_map[v] = t; + } + + /** + * returns edge to parent vertex of v; + */ + inline edge_descriptor get_edge_to_parent(vertex_descriptor v) const{ + return m_pre_map[v]; + } + + /** + * returns true if the edge stored in m_pre_map[v] is a valid entry + */ + inline bool has_parent(vertex_descriptor v) const{ + return m_has_parent_map[v]; + } + + /** + * sets edge to parent vertex of v; + */ + inline void set_edge_to_parent(vertex_descriptor v, edge_descriptor f_edge_to_parent){ + assert(m_res_cap_map[f_edge_to_parent] > 0); + m_pre_map[v] = f_edge_to_parent; + m_has_parent_map[v] = true; + } + + /** + * removes the edge to parent of v (this is done by invalidating the entry an additional map) + */ + inline void set_no_parent(vertex_descriptor v){ + m_has_parent_map[v] = false; + } + + /** + * checks if vertex v has a connect to the sink-vertex (@var m_sink) + * @param v the vertex which is checked + * @return true if a path to the sink was found, false if not + */ + inline bool has_sink_connect(vertex_descriptor v){ + tDistanceVal current_distance = 0; + vertex_descriptor current_vertex = v; + while(true){ + if(m_time_map[current_vertex] == m_time){ + //we found a node which was already checked this round. use it for distance calculations + current_distance += m_dist_map[current_vertex]; + break; + } + if(current_vertex == m_sink){ + m_time_map[m_sink] = m_time; + break; + } + if(has_parent(current_vertex)){ + //it has a parent, so get it + current_vertex = target(get_edge_to_parent(current_vertex), m_g); + ++current_distance; + } else{ + //no path found + return false; + } + } + current_vertex=v; + while(m_time_map[current_vertex] != m_time){ + m_dist_map[current_vertex] = current_distance--; + m_time_map[current_vertex] = m_time; + current_vertex = target(get_edge_to_parent(current_vertex), m_g); + } + return true; + } + + /** + * checks if vertex v has a connect to the source-vertex (@var m_source) + * @param v the vertex which is checked + * @return true if a path to the source was found, false if not + */ + inline bool has_source_connect(vertex_descriptor v){ + tDistanceVal current_distance = 0; + vertex_descriptor current_vertex = v; + while(true){ + if(m_time_map[current_vertex] == m_time){ + //we found a node which was already checked this round. use it for distance calculations + current_distance += m_dist_map[current_vertex]; + break; + } + if(current_vertex == m_source){ + m_time_map[m_source] = m_time; + break; + } + if(has_parent(current_vertex)){ + //it has a parent, so get it + current_vertex = source(get_edge_to_parent(current_vertex), m_g); + ++current_distance; + } else{ + //no path found + return false; + } + } + current_vertex=v; + while(m_time_map[current_vertex] != m_time){ + m_dist_map[current_vertex] = current_distance-- ; + m_time_map[current_vertex] = m_time; + current_vertex = source(get_edge_to_parent(current_vertex), m_g); + } + return true; + } + + /** + * returns true, if p is closer to a terminal than q + */ + inline bool is_closer_to_terminal(vertex_descriptor p, vertex_descriptor q){ + //checks the timestamps first, to build no cycles, and after that the real distance + return (m_time_map[q] <= m_time_map[p] && m_dist_map[q] > m_dist_map[p]+1); + } + + //////// + // member vars + //////// + Graph& m_g; + IndexMap m_index_map; + EdgeCapacityMap m_cap_map; + ResidualCapacityEdgeMap m_res_cap_map; + ReverseEdgeMap m_rev_edge_map; + PredecessorMap m_pre_map; //stores paths found in the growth stage + ColorMap m_tree_map; //maps each vertex into one of the two search tree or none (gray()) + DistanceMap m_dist_map; //stores distance to source/sink nodes + vertex_descriptor m_source; + vertex_descriptor m_sink; + + tQueue m_active_nodes; + std::vector m_in_active_list_vec; + iterator_property_map::iterator, IndexMap> m_in_active_list_map; + + std::list m_orphans; + tQueue m_child_orphans; // we use a second queuqe for child orphans, as they are FIFO processed + + std::vector m_has_parent_vec; + iterator_property_map::iterator, IndexMap> m_has_parent_map; + + std::vector m_time_vec; //timestamp of each node, used for sink/source-path calculations + iterator_property_map::iterator, IndexMap> m_time_map; + tEdgeVal m_flow; + long m_time; + vertex_descriptor m_last_grow_vertex; + out_edge_iterator m_last_grow_edge_it; + out_edge_iterator m_last_grow_edge_end; + }; + } //namespace detail + + /** + * non-named-parameter version, given everything + * this is the catch all version + */ + template + typename property_traits::value_type + kolmogorov_max_flow + (Graph& g, + CapacityEdgeMap cap, + ResidualCapacityEdgeMap res_cap, + ReverseEdgeMap rev_map, + PredecessorMap pre_map, + ColorMap color, + DistanceMap dist, + IndexMap idx, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink + ) + { + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::edge_descriptor edge_descriptor; + //as this method is the last one before we instantiate the solver, we do the concept checks here + function_requires >(); //to have vertices(), num_vertices(), + function_requires >(); //to have edges() + function_requires >(); //to have source(), target() and out_edges() + function_requires >(); //read flow-values from edges + function_requires >(); //write flow-values to residuals + function_requires >(); //read out reverse edges + function_requires >(); //store predecessor there + function_requires >(); //write corresponding tree + function_requires >(); //write distance to source/sink + function_requires >(); //get index 0...|V|-1 + assert(num_vertices(g) >= 2 && src != sink); + detail::kolmogorov + algo(g, cap, res_cap, rev_map, pre_map, color, dist, idx, src, sink); + return algo.max_flow(); + } + + /** + * non-named-parameter version, given: capacity, residucal_capacity, reverse_edges, and an index map. + */ + template + typename property_traits::value_type + kolmogorov_max_flow + (Graph& g, + CapacityEdgeMap cap, + ResidualCapacityEdgeMap res_cap, + ReverseEdgeMap rev, + IndexMap idx, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink) + { + typename graph_traits::vertices_size_type n_verts = num_vertices(g); + std::vector::edge_descriptor> predecessor_vec(n_verts); + std::vector color_vec(n_verts); + std::vector::vertices_size_type> distance_vec(n_verts); + return kolmogorov_max_flow + (g, cap, res_cap, rev, + make_iterator_property_map(predecessor_vec.begin(), idx), + make_iterator_property_map(color_vec.begin(), idx), + make_iterator_property_map(distance_vec.begin(), idx), + idx, src, sink); + } + + /** + * non-named-parameter version, some given: capacity, residual_capacity, reverse_edges, color_map and an index map. + * Use this if you are interested in the minimum cut, as the color map provides that info + */ + template + typename property_traits::value_type + kolmogorov_max_flow + (Graph& g, + CapacityEdgeMap cap, + ResidualCapacityEdgeMap res_cap, + ReverseEdgeMap rev, + ColorMap color, + IndexMap idx, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink) + { + typename graph_traits::vertices_size_type n_verts = num_vertices(g); + std::vector::edge_descriptor> predecessor_vec(n_verts); + std::vector::vertices_size_type> distance_vec(n_verts); + + return kolmogorov_max_flow + (g, cap, res_cap, rev, + make_iterator_property_map(predecessor_vec.begin(), idx), + color, + make_iterator_property_map(distance_vec.begin(), idx), + idx, src, sink); + } + + /** + * named-parameter version, some given + */ + template + typename property_traits::const_type>::value_type + kolmogorov_max_flow + (Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink, + const bgl_named_params& params) + { + return kolmogorov_max_flow(g, + choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), + choose_pmap(get_param(params, edge_residual_capacity), g, edge_residual_capacity), + choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), + choose_pmap(get_param(params, vertex_predecessor), g, vertex_predecessor), + choose_pmap(get_param(params, vertex_color), g, vertex_color), + choose_pmap(get_param(params, vertex_distance), g, vertex_distance), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index), + src, sink); + } + + /** + * named-parameter version, none given + */ + template + typename property_traits::const_type>::value_type + kolmogorov_max_flow + (Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink) + { + bgl_named_params params(0); // bogus empty param + return kolmogorov_max_flow(g, src, sink, params); + } +} // namespace boost + +#endif // BOOST_KOLMOGOROV_MAX_FLOW_HPP + diff --git a/win32/include/boost/graph/kruskal_min_spanning_tree.hpp b/win32/include/boost/graph/kruskal_min_spanning_tree.hpp new file mode 100755 index 000000000..150aa9da6 --- /dev/null +++ b/win32/include/boost/graph/kruskal_min_spanning_tree.hpp @@ -0,0 +1,155 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_MST_KRUSKAL_HPP +#define BOOST_GRAPH_MST_KRUSKAL_HPP + +/* + *Minimum Spanning Tree + * Kruskal Algorithm + * + *Requirement: + * undirected graph + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + + +namespace boost { + + // Kruskal's algorithm for Minimum Spanning Tree + // + // This is a greedy algorithm to calculate the Minimum Spanning Tree + // for an undirected graph with weighted edges. The output will be a + // set of edges. + // + + namespace detail { + + template + void + kruskal_mst_impl(const Graph& G, + OutputIterator spanning_tree_edges, + Rank rank, Parent parent, Weight weight) + { + if (num_vertices(G) == 0) return; // Nothing to do in this case + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::edge_descriptor Edge; + function_requires >(); + function_requires >(); + function_requires >(); + function_requires >(); + function_requires >(); + function_requires >(); + typedef typename property_traits::value_type W_value; + typedef typename property_traits::value_type R_value; + typedef typename property_traits::value_type P_value; + function_requires >(); + function_requires >(); + function_requires >(); + + disjoint_sets dset(rank, parent); + + typename graph_traits::vertex_iterator ui, uiend; + for (boost::tie(ui, uiend) = vertices(G); ui != uiend; ++ui) + dset.make_set(*ui); + + typedef indirect_cmp > weight_greater; + weight_greater wl(weight); + std::priority_queue, weight_greater> Q(wl); + /*push all edge into Q*/ + typename graph_traits::edge_iterator ei, eiend; + for (boost::tie(ei, eiend) = edges(G); ei != eiend; ++ei) + Q.push(*ei); + + while (! Q.empty()) { + Edge e = Q.top(); + Q.pop(); + Vertex u = dset.find_set(source(e, G)); + Vertex v = dset.find_set(target(e, G)); + if ( u != v ) { + *spanning_tree_edges++ = e; + dset.link(u, v); + } + } + } + + } // namespace detail + + // Named Parameters Variants + + template + inline void + kruskal_minimum_spanning_tree(const Graph& g, + OutputIterator spanning_tree_edges) + { + typedef typename graph_traits::vertices_size_type size_type; + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename property_map::type index_map_t; + if (num_vertices(g) == 0) return; // Nothing to do in this case + typename graph_traits::vertices_size_type + n = num_vertices(g); + std::vector rank_map(n); + std::vector pred_map(n); + + detail::kruskal_mst_impl + (g, spanning_tree_edges, + make_iterator_property_map(rank_map.begin(), get(vertex_index, g), rank_map[0]), + make_iterator_property_map(pred_map.begin(), get(vertex_index, g), pred_map[0]), + get(edge_weight, g)); + } + + template + inline void + kruskal_minimum_spanning_tree(const Graph& g, + OutputIterator spanning_tree_edges, + const bgl_named_params& params) + { + typedef typename graph_traits::vertices_size_type size_type; + typedef typename graph_traits::vertex_descriptor vertex_t; + if (num_vertices(g) == 0) return; // Nothing to do in this case + typename graph_traits::vertices_size_type n; + n = is_default_param(get_param(params, vertex_rank)) + ? num_vertices(g) : 1; + std::vector rank_map(n); + n = is_default_param(get_param(params, vertex_predecessor)) + ? num_vertices(g) : 1; + std::vector pred_map(n); + + detail::kruskal_mst_impl + (g, spanning_tree_edges, + choose_param + (get_param(params, vertex_rank), + make_iterator_property_map + (rank_map.begin(), + choose_pmap(get_param(params, vertex_index), g, vertex_index), rank_map[0])), + choose_param + (get_param(params, vertex_predecessor), + make_iterator_property_map + (pred_map.begin(), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index), + pred_map[0])), + choose_const_pmap(get_param(params, edge_weight), g, edge_weight)); + } + +} // namespace boost + + +#endif // BOOST_GRAPH_MST_KRUSKAL_HPP + diff --git a/win32/include/boost/graph/leda_graph.hpp b/win32/include/boost/graph/leda_graph.hpp new file mode 100755 index 000000000..8df0bd5fe --- /dev/null +++ b/win32/include/boost/graph/leda_graph.hpp @@ -0,0 +1,952 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2004 The Trustees of Indiana University. +// Copyright 2007 University of Karlsruhe +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Douglas Gregor, +// Jens Mueller +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_LEDA_HPP +#define BOOST_GRAPH_LEDA_HPP + +#include +#include +#include +#include + +#include +#include +#include + +// The functions and classes in this file allows the user to +// treat a LEDA GRAPH object as a boost graph "as is". No +// wrapper is needed for the GRAPH object. + +// Warning: this implementation relies on partial specialization +// for the graph_traits class (so it won't compile with Visual C++) + +// Warning: this implementation is in alpha and has not been tested + +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost { + + struct leda_graph_traversal_category : + public virtual bidirectional_graph_tag, + public virtual adjacency_graph_tag, + public virtual vertex_list_graph_tag { }; + + template + struct graph_traits< leda::GRAPH > { + typedef leda::node vertex_descriptor; + typedef leda::edge edge_descriptor; + + class adjacency_iterator + : public iterator_facade + { + public: + adjacency_iterator(leda::node node = 0, + const leda::GRAPH* g = 0) + : base(node), g(g) {} + private: + leda::node dereference() const { return leda::target(base); } + + bool equal(const adjacency_iterator& other) const + { return base == other.base; } + + void increment() { base = g->adj_succ(base); } + void decrement() { base = g->adj_pred(base); } + + leda::edge base; + const leda::GRAPH* g; + + friend class iterator_core_access; + }; + + class out_edge_iterator + : public iterator_facade + { + public: + out_edge_iterator(leda::node node = 0, + const leda::GRAPH* g = 0) + : base(node), g(g) {} + + private: + const leda::edge& dereference() const { return base; } + + bool equal(const out_edge_iterator& other) const + { return base == other.base; } + + void increment() { base = g->adj_succ(base); } + void decrement() { base = g->adj_pred(base); } + + leda::edge base; + const leda::GRAPH* g; + + friend class iterator_core_access; + }; + + class in_edge_iterator + : public iterator_facade + { + public: + in_edge_iterator(leda::node node = 0, + const leda::GRAPH* g = 0) + : base(node), g(g) {} + + private: + const leda::edge& dereference() const { return base; } + + bool equal(const in_edge_iterator& other) const + { return base == other.base; } + + void increment() { base = g->in_succ(base); } + void decrement() { base = g->in_pred(base); } + + leda::edge base; + const leda::GRAPH* g; + + friend class iterator_core_access; + }; + + class vertex_iterator + : public iterator_facade + { + public: + vertex_iterator(leda::node node = 0, + const leda::GRAPH* g = 0) + : base(node), g(g) {} + + private: + const leda::node& dereference() const { return base; } + + bool equal(const vertex_iterator& other) const + { return base == other.base; } + + void increment() { base = g->succ_node(base); } + void decrement() { base = g->pred_node(base); } + + leda::node base; + const leda::GRAPH* g; + + friend class iterator_core_access; + }; + + class edge_iterator + : public iterator_facade + { + public: + edge_iterator(leda::edge edge = 0, + const leda::GRAPH* g = 0) + : base(edge), g(g) {} + + private: + const leda::edge& dereference() const { return base; } + + bool equal(const edge_iterator& other) const + { return base == other.base; } + + void increment() { base = g->succ_edge(base); } + void decrement() { base = g->pred_edge(base); } + + leda::node base; + const leda::GRAPH* g; + + friend class iterator_core_access; + }; + + typedef directed_tag directed_category; + typedef allow_parallel_edge_tag edge_parallel_category; // not sure here + typedef leda_graph_traversal_category traversal_category; + typedef int vertices_size_type; + typedef int edges_size_type; + typedef int degree_size_type; + }; + + + + template<> + struct graph_traits { + typedef leda::node vertex_descriptor; + typedef leda::edge edge_descriptor; + + class adjacency_iterator + : public iterator_facade + { + public: + adjacency_iterator(leda::edge edge = 0, + const leda::graph* g = 0) + : base(edge), g(g) {} + + private: + leda::node dereference() const { return leda::target(base); } + + bool equal(const adjacency_iterator& other) const + { return base == other.base; } + + void increment() { base = g->adj_succ(base); } + void decrement() { base = g->adj_pred(base); } + + leda::edge base; + const leda::graph* g; + + friend class iterator_core_access; + }; + + class out_edge_iterator + : public iterator_facade + { + public: + out_edge_iterator(leda::edge edge = 0, + const leda::graph* g = 0) + : base(edge), g(g) {} + + private: + const leda::edge& dereference() const { return base; } + + bool equal(const out_edge_iterator& other) const + { return base == other.base; } + + void increment() { base = g->adj_succ(base); } + void decrement() { base = g->adj_pred(base); } + + leda::edge base; + const leda::graph* g; + + friend class iterator_core_access; + }; + + class in_edge_iterator + : public iterator_facade + { + public: + in_edge_iterator(leda::edge edge = 0, + const leda::graph* g = 0) + : base(edge), g(g) {} + + private: + const leda::edge& dereference() const { return base; } + + bool equal(const in_edge_iterator& other) const + { return base == other.base; } + + void increment() { base = g->in_succ(base); } + void decrement() { base = g->in_pred(base); } + + leda::edge base; + const leda::graph* g; + + friend class iterator_core_access; + }; + + class vertex_iterator + : public iterator_facade + { + public: + vertex_iterator(leda::node node = 0, + const leda::graph* g = 0) + : base(node), g(g) {} + + private: + const leda::node& dereference() const { return base; } + + bool equal(const vertex_iterator& other) const + { return base == other.base; } + + void increment() { base = g->succ_node(base); } + void decrement() { base = g->pred_node(base); } + + leda::node base; + const leda::graph* g; + + friend class iterator_core_access; + }; + + class edge_iterator + : public iterator_facade + { + public: + edge_iterator(leda::edge edge = 0, + const leda::graph* g = 0) + : base(edge), g(g) {} + + private: + const leda::edge& dereference() const { return base; } + + bool equal(const edge_iterator& other) const + { return base == other.base; } + + void increment() { base = g->succ_edge(base); } + void decrement() { base = g->pred_edge(base); } + + leda::edge base; + const leda::graph* g; + + friend class iterator_core_access; + }; + + typedef directed_tag directed_category; + typedef allow_parallel_edge_tag edge_parallel_category; // not sure here + typedef leda_graph_traversal_category traversal_category; + typedef int vertices_size_type; + typedef int edges_size_type; + typedef int degree_size_type; + }; + +} // namespace boost +#endif + +namespace boost { + + //=========================================================================== + // functions for GRAPH + + template + typename graph_traits< leda::GRAPH >::vertex_descriptor + source(typename graph_traits< leda::GRAPH >::edge_descriptor e, + const leda::GRAPH& g) + { + return source(e); + } + + template + typename graph_traits< leda::GRAPH >::vertex_descriptor + target(typename graph_traits< leda::GRAPH >::edge_descriptor e, + const leda::GRAPH& g) + { + return target(e); + } + + template + inline std::pair< + typename graph_traits< leda::GRAPH >::vertex_iterator, + typename graph_traits< leda::GRAPH >::vertex_iterator > + vertices(const leda::GRAPH& g) + { + typedef typename graph_traits< leda::GRAPH >::vertex_iterator + Iter; + return std::make_pair( Iter(g.first_node(),&g), Iter(0,&g) ); + } + + template + inline std::pair< + typename graph_traits< leda::GRAPH >::edge_iterator, + typename graph_traits< leda::GRAPH >::edge_iterator > + edges(const leda::GRAPH& g) + { + typedef typename graph_traits< leda::GRAPH >::edge_iterator + Iter; + return std::make_pair( Iter(g.first_edge(),&g), Iter(0,&g) ); + } + + template + inline std::pair< + typename graph_traits< leda::GRAPH >::out_edge_iterator, + typename graph_traits< leda::GRAPH >::out_edge_iterator > + out_edges( + typename graph_traits< leda::GRAPH >::vertex_descriptor u, + const leda::GRAPH& g) + { + typedef typename graph_traits< leda::GRAPH > + ::out_edge_iterator Iter; + return std::make_pair( Iter(g.first_adj_edge(u,0),&g), Iter(0,&g) ); + } + + template + inline std::pair< + typename graph_traits< leda::GRAPH >::in_edge_iterator, + typename graph_traits< leda::GRAPH >::in_edge_iterator > + in_edges( + typename graph_traits< leda::GRAPH >::vertex_descriptor u, + const leda::GRAPH& g) + { + typedef typename graph_traits< leda::GRAPH > + ::in_edge_iterator Iter; + return std::make_pair( Iter(g.first_adj_edge(u,1),&g), Iter(0,&g) ); + } + + template + inline std::pair< + typename graph_traits< leda::GRAPH >::adjacency_iterator, + typename graph_traits< leda::GRAPH >::adjacency_iterator > + adjacent_vertices( + typename graph_traits< leda::GRAPH >::vertex_descriptor u, + const leda::GRAPH& g) + { + typedef typename graph_traits< leda::GRAPH > + ::adjacency_iterator Iter; + return std::make_pair( Iter(g.first_adj_edge(u,0),&g), Iter(0,&g) ); + } + + template + typename graph_traits< leda::GRAPH >::vertices_size_type + num_vertices(const leda::GRAPH& g) + { + return g.number_of_nodes(); + } + + template + typename graph_traits< leda::GRAPH >::edges_size_type + num_edges(const leda::GRAPH& g) + { + return g.number_of_edges(); + } + + template + typename graph_traits< leda::GRAPH >::degree_size_type + out_degree( + typename graph_traits< leda::GRAPH >::vertex_descriptor u, + const leda::GRAPH& g) + { + return g.outdeg(u); + } + + template + typename graph_traits< leda::GRAPH >::degree_size_type + in_degree( + typename graph_traits< leda::GRAPH >::vertex_descriptor u, + const leda::GRAPH& g) + { + return g.indeg(u); + } + + template + typename graph_traits< leda::GRAPH >::degree_size_type + degree( + typename graph_traits< leda::GRAPH >::vertex_descriptor u, + const leda::GRAPH& g) + { + return g.outdeg(u) + g.indeg(u); + } + + template + typename graph_traits< leda::GRAPH >::vertex_descriptor + add_vertex(leda::GRAPH& g) + { + return g.new_node(); + } + + template + typename graph_traits< leda::GRAPH >::vertex_descriptor + add_vertex(const vtype& vp, leda::GRAPH& g) + { + return g.new_node(vp); + } + + template + void clear_vertex( + typename graph_traits< leda::GRAPH >::vertex_descriptor u, + leda::GRAPH& g) + { + typename graph_traits< leda::GRAPH >::out_edge_iterator ei, ei_end; + for (tie(ei, ei_end)=out_edges(u,g); ei!=ei_end; ei++) + remove_edge(*ei); + + typename graph_traits< leda::GRAPH >::in_edge_iterator iei, iei_end; + for (tie(iei, iei_end)=in_edges(u,g); iei!=iei_end; iei++) + remove_edge(*iei); + } + + template + void remove_vertex( + typename graph_traits< leda::GRAPH >::vertex_descriptor u, + leda::GRAPH& g) + { + g.del_node(u); + } + + template + std::pair< + typename graph_traits< leda::GRAPH >::edge_descriptor, + bool> + add_edge( + typename graph_traits< leda::GRAPH >::vertex_descriptor u, + typename graph_traits< leda::GRAPH >::vertex_descriptor v, + leda::GRAPH& g) + { + return std::make_pair(g.new_edge(u, v), true); + } + + template + std::pair< + typename graph_traits< leda::GRAPH >::edge_descriptor, + bool> + add_edge( + typename graph_traits< leda::GRAPH >::vertex_descriptor u, + typename graph_traits< leda::GRAPH >::vertex_descriptor v, + const etype& et, + leda::GRAPH& g) + { + return std::make_pair(g.new_edge(u, v, et), true); + } + + template + void + remove_edge( + typename graph_traits< leda::GRAPH >::vertex_descriptor u, + typename graph_traits< leda::GRAPH >::vertex_descriptor v, + leda::GRAPH& g) + { + typename graph_traits< leda::GRAPH >::out_edge_iterator + i,iend; + for (boost::tie(i,iend) = out_edges(u,g); i != iend; ++i) + if (target(*i,g) == v) + g.del_edge(*i); + } + + template + void + remove_edge( + typename graph_traits< leda::GRAPH >::edge_descriptor e, + leda::GRAPH& g) + { + g.del_edge(e); + } + + //=========================================================================== + // functions for graph (non-templated version) + + graph_traits::vertex_descriptor + source(graph_traits::edge_descriptor e, + const leda::graph& g) + { + return source(e); + } + + graph_traits::vertex_descriptor + target(graph_traits::edge_descriptor e, + const leda::graph& g) + { + return target(e); + } + + inline std::pair< + graph_traits::vertex_iterator, + graph_traits::vertex_iterator > + vertices(const leda::graph& g) + { + typedef graph_traits::vertex_iterator + Iter; + return std::make_pair( Iter(g.first_node(),&g), Iter(0,&g) ); + } + + inline std::pair< + graph_traits::edge_iterator, + graph_traits::edge_iterator > + edges(const leda::graph& g) + { + typedef graph_traits::edge_iterator + Iter; + return std::make_pair( Iter(g.first_edge(),&g), Iter(0,&g) ); + } + + inline std::pair< + graph_traits::out_edge_iterator, + graph_traits::out_edge_iterator > + out_edges( + graph_traits::vertex_descriptor u, const leda::graph& g) + { + typedef graph_traits::out_edge_iterator Iter; + return std::make_pair( Iter(g.first_adj_edge(u),&g), Iter(0,&g) ); + } + + inline std::pair< + graph_traits::in_edge_iterator, + graph_traits::in_edge_iterator > + in_edges( + graph_traits::vertex_descriptor u, + const leda::graph& g) + { + typedef graph_traits + ::in_edge_iterator Iter; + return std::make_pair( Iter(g.first_in_edge(u),&g), Iter(0,&g) ); + } + + inline std::pair< + graph_traits::adjacency_iterator, + graph_traits::adjacency_iterator > + adjacent_vertices( + graph_traits::vertex_descriptor u, + const leda::graph& g) + { + typedef graph_traits + ::adjacency_iterator Iter; + return std::make_pair( Iter(g.first_adj_edge(u),&g), Iter(0,&g) ); + } + + graph_traits::vertices_size_type + num_vertices(const leda::graph& g) + { + return g.number_of_nodes(); + } + + graph_traits::edges_size_type + num_edges(const leda::graph& g) + { + return g.number_of_edges(); + } + + graph_traits::degree_size_type + out_degree( + graph_traits::vertex_descriptor u, + const leda::graph& g) + { + return g.outdeg(u); + } + + graph_traits::degree_size_type + in_degree( + graph_traits::vertex_descriptor u, + const leda::graph& g) + { + return g.indeg(u); + } + + graph_traits::degree_size_type + degree( + graph_traits::vertex_descriptor u, + const leda::graph& g) + { + return g.outdeg(u) + g.indeg(u); + } + + graph_traits::vertex_descriptor + add_vertex(leda::graph& g) + { + return g.new_node(); + } + + void + remove_edge( + graph_traits::vertex_descriptor u, + graph_traits::vertex_descriptor v, + leda::graph& g) + { + graph_traits::out_edge_iterator + i,iend; + for (boost::tie(i,iend) = out_edges(u,g); i != iend; ++i) + if (target(*i,g) == v) + g.del_edge(*i); + } + + void + remove_edge( + graph_traits::edge_descriptor e, + leda::graph& g) + { + g.del_edge(e); + } + + void clear_vertex( + graph_traits::vertex_descriptor u, + leda::graph& g) + { + graph_traits::out_edge_iterator ei, ei_end; + for (tie(ei, ei_end)=out_edges(u,g); ei!=ei_end; ei++) + remove_edge(*ei, g); + + graph_traits::in_edge_iterator iei, iei_end; + for (tie(iei, iei_end)=in_edges(u,g); iei!=iei_end; iei++) + remove_edge(*iei, g); + } + + void remove_vertex( + graph_traits::vertex_descriptor u, + leda::graph& g) + { + g.del_node(u); + } + + std::pair< + graph_traits::edge_descriptor, + bool> + add_edge( + graph_traits::vertex_descriptor u, + graph_traits::vertex_descriptor v, + leda::graph& g) + { + return std::make_pair(g.new_edge(u, v), true); + } + + + //=========================================================================== + // property maps for GRAPH + + class leda_graph_id_map + : public put_get_helper + { + public: + typedef readable_property_map_tag category; + typedef int value_type; + typedef int reference; + typedef leda::node key_type; + leda_graph_id_map() { } + template + long operator[](T x) const { return x->id(); } + }; + template + inline leda_graph_id_map + get(vertex_index_t, const leda::GRAPH& g) { + return leda_graph_id_map(); + } + template + inline leda_graph_id_map + get(edge_index_t, const leda::GRAPH& g) { + return leda_graph_id_map(); + } + + template + struct leda_property_map { }; + + template <> + struct leda_property_map { + template + struct bind_ { + typedef leda_graph_id_map type; + typedef leda_graph_id_map const_type; + }; + }; + template <> + struct leda_property_map { + template + struct bind_ { + typedef leda_graph_id_map type; + typedef leda_graph_id_map const_type; + }; + }; + + + template + class leda_graph_data_map + : public put_get_helper > + { + public: + typedef Data value_type; + typedef DataRef reference; + typedef void key_type; + typedef lvalue_property_map_tag category; + leda_graph_data_map(GraphPtr g) : m_g(g) { } + template + DataRef operator[](NodeOrEdge x) const { return (*m_g)[x]; } + protected: + GraphPtr m_g; + }; + + template <> + struct leda_property_map { + template + struct bind_ { + typedef leda_graph_data_map*> type; + typedef leda_graph_data_map*> const_type; + }; + }; + template + inline typename property_map< leda::GRAPH, vertex_all_t>::type + get(vertex_all_t, leda::GRAPH& g) { + typedef typename property_map< leda::GRAPH, vertex_all_t>::type + pmap_type; + return pmap_type(&g); + } + template + inline typename property_map< leda::GRAPH, vertex_all_t>::const_type + get(vertex_all_t, const leda::GRAPH& g) { + typedef typename property_map< leda::GRAPH, + vertex_all_t>::const_type pmap_type; + return pmap_type(&g); + } + + template <> + struct leda_property_map { + template + struct bind_ { + typedef leda_graph_data_map*> type; + typedef leda_graph_data_map*> const_type; + }; + }; + template + inline typename property_map< leda::GRAPH, edge_all_t>::type + get(edge_all_t, leda::GRAPH& g) { + typedef typename property_map< leda::GRAPH, edge_all_t>::type + pmap_type; + return pmap_type(&g); + } + template + inline typename property_map< leda::GRAPH, edge_all_t>::const_type + get(edge_all_t, const leda::GRAPH& g) { + typedef typename property_map< leda::GRAPH, + edge_all_t>::const_type pmap_type; + return pmap_type(&g); + } + + // property map interface to the LEDA node_array class + + template + class leda_node_property_map + : public put_get_helper > + { + public: + typedef E value_type; + typedef ERef reference; + typedef leda::node key_type; + typedef lvalue_property_map_tag category; + leda_node_property_map(NodeMapPtr a) : m_array(a) { } + ERef operator[](leda::node n) const { return (*m_array)[n]; } + protected: + NodeMapPtr m_array; + }; + template + leda_node_property_map*> + make_leda_node_property_map(const leda::node_array& a) + { + typedef leda_node_property_map*> + pmap_type; + return pmap_type(&a); + } + template + leda_node_property_map*> + make_leda_node_property_map(leda::node_array& a) + { + typedef leda_node_property_map*> pmap_type; + return pmap_type(&a); + } + + template + leda_node_property_map*> + make_leda_node_property_map(const leda::node_map& a) + { + typedef leda_node_property_map*> + pmap_type; + return pmap_type(&a); + } + template + leda_node_property_map*> + make_leda_node_property_map(leda::node_map& a) + { + typedef leda_node_property_map*> pmap_type; + return pmap_type(&a); + } + + // g++ 'enumeral_type' in template unification not implemented workaround + template + struct property_map, Tag> { + typedef typename + leda_property_map::template bind_ map_gen; + typedef typename map_gen::type type; + typedef typename map_gen::const_type const_type; + }; + + template + inline + typename boost::property_traits< + typename boost::property_map,PropertyTag>::const_type +::value_type + get(PropertyTag p, const leda::GRAPH& g, const Key& key) { + return get(get(p, g), key); + } + + template + inline void + put(PropertyTag p, leda::GRAPH& g, + const Key& key, const Value& value) + { + typedef typename property_map, PropertyTag>::type Map; + Map pmap = get(p, g); + put(pmap, key, value); + } + + // property map interface to the LEDA edge_array class + + template + class leda_edge_property_map + : public put_get_helper > + { + public: + typedef E value_type; + typedef ERef reference; + typedef leda::edge key_type; + typedef lvalue_property_map_tag category; + leda_edge_property_map(EdgeMapPtr a) : m_array(a) { } + ERef operator[](leda::edge n) const { return (*m_array)[n]; } + protected: + EdgeMapPtr m_array; + }; + template + leda_edge_property_map*> + make_leda_node_property_map(const leda::node_array& a) + { + typedef leda_edge_property_map*> + pmap_type; + return pmap_type(&a); + } + template + leda_edge_property_map*> + make_leda_edge_property_map(leda::edge_array& a) + { + typedef leda_edge_property_map*> pmap_type; + return pmap_type(&a); + } + + template + leda_edge_property_map*> + make_leda_edge_property_map(const leda::edge_map& a) + { + typedef leda_edge_property_map*> + pmap_type; + return pmap_type(&a); + } + template + leda_edge_property_map*> + make_leda_edge_property_map(leda::edge_map& a) + { + typedef leda_edge_property_map*> pmap_type; + return pmap_type(&a); + } + +} // namespace boost + +#endif // BOOST_GRAPH_LEDA_HPP diff --git a/win32/include/boost/graph/make_biconnected_planar.hpp b/win32/include/boost/graph/make_biconnected_planar.hpp new file mode 100755 index 000000000..09f9a6cbf --- /dev/null +++ b/win32/include/boost/graph/make_biconnected_planar.hpp @@ -0,0 +1,121 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __MAKE_BICONNECTED_PLANAR_HPP__ +#define __MAKE_BICONNECTED_PLANAR_HPP__ + +#include +#include //for tie +#include +#include +#include +#include +#include + +#include + + +namespace boost +{ + + + + template + void make_biconnected_planar(Graph& g, + PlanarEmbedding embedding, + EdgeIndexMap em, + AddEdgeVisitor& vis + ) + { + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::edge_descriptor edge_t; + typedef typename graph_traits::edges_size_type edge_size_t; + typedef typename + property_traits::value_type embedding_value_t; + typedef typename embedding_value_t::const_iterator embedding_iterator_t; + typedef iterator_property_map + ::iterator, EdgeIndexMap> component_map_t; + + edge_size_t n_edges(num_edges(g)); + std::vector articulation_points; + std::vector component_vector(n_edges); + component_map_t component_map(component_vector.begin(), em); + + biconnected_components(g, component_map, + std::back_inserter(articulation_points)); + + typename std::vector::iterator ap, ap_end; + ap_end = articulation_points.end(); + for(ap = articulation_points.begin(); ap != ap_end; ++ap) + { + vertex_t v(*ap); + embedding_iterator_t pi = embedding[v].begin(); + embedding_iterator_t pi_end = embedding[v].end(); + edge_size_t previous_component(n_edges + 1); + vertex_t previous_vertex = graph_traits::null_vertex(); + + for(; pi != pi_end; ++pi) + { + edge_t e(*pi); + vertex_t e_source(source(e,g)); + vertex_t e_target(target(e,g)); + + //Skip self-loops and parallel edges + if (e_source == e_target || previous_vertex == e_target) + continue; + + vertex_t current_vertex = e_source == v ? e_target : e_source; + edge_size_t current_component = component_map[e]; + if (previous_vertex != graph_traits::null_vertex() && + current_component != previous_component) + { + vis.visit_vertex_pair(current_vertex, previous_vertex, g); + } + previous_vertex = current_vertex; + previous_component = current_component; + } + } + + } + + + + + template + inline void make_biconnected_planar(Graph& g, + PlanarEmbedding embedding, + EdgeIndexMap em + ) + { + default_add_edge_visitor vis; + make_biconnected_planar(g, embedding, em, vis); + } + + + + + template + inline void make_biconnected_planar(Graph& g, PlanarEmbedding embedding) + { + make_biconnected_planar(g, embedding, get(edge_index,g)); + } + + +} // namespace boost + + + +#endif //__MAKE_BICONNECTED_PLANAR_HPP__ diff --git a/win32/include/boost/graph/make_connected.hpp b/win32/include/boost/graph/make_connected.hpp new file mode 100755 index 000000000..0e6536e63 --- /dev/null +++ b/win32/include/boost/graph/make_connected.hpp @@ -0,0 +1,99 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __MAKE_CONNECTED_HPP__ +#define __MAKE_CONNECTED_HPP__ + +#include +#include //for next +#include //for tie +#include +#include +#include + +#include +#include + + +namespace boost +{ + + + template + void make_connected(Graph& g, VertexIndexMap vm, AddEdgeVisitor& vis) + { + typedef typename graph_traits::vertex_iterator vertex_iterator_t; + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::vertices_size_type v_size_t; + typedef iterator_property_map< typename std::vector::iterator, + VertexIndexMap + > vertex_to_v_size_map_t; + + std::vector component_vector(num_vertices(g)); + vertex_to_v_size_map_t component(component_vector.begin(), vm); + std::vector vertices_by_component(num_vertices(g)); + + v_size_t num_components = connected_components(g, component); + + if (num_components < 2) + return; + + vertex_iterator_t vi, vi_end; + tie(vi,vi_end) = vertices(g); + std::copy(vi, vi_end, vertices_by_component.begin()); + + bucket_sort(vertices_by_component.begin(), + vertices_by_component.end(), + component, + num_components + ); + + typedef typename std::vector::iterator vec_of_vertices_itr_t; + + vec_of_vertices_itr_t ci_end = vertices_by_component.end(); + vec_of_vertices_itr_t ci_prev = vertices_by_component.begin(); + if (ci_prev == ci_end) + return; + + for(vec_of_vertices_itr_t ci = next(ci_prev); + ci != ci_end; ci_prev = ci, ++ci + ) + { + if (component[*ci_prev] != component[*ci]) + vis.visit_vertex_pair(*ci_prev, *ci, g); + } + + } + + + + + template + inline void make_connected(Graph& g, VertexIndexMap vm) + { + default_add_edge_visitor vis; + make_connected(g, vm, vis); + } + + + + + template + inline void make_connected(Graph& g) + { + make_connected(g, get(vertex_index,g)); + } + + + + +} // namespace boost + +#endif //__MAKE_CONNECTED_HPP__ diff --git a/win32/include/boost/graph/make_maximal_planar.hpp b/win32/include/boost/graph/make_maximal_planar.hpp new file mode 100755 index 000000000..687b70725 --- /dev/null +++ b/win32/include/boost/graph/make_maximal_planar.hpp @@ -0,0 +1,275 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __MAKE_MAXIMAL_PLANAR_HPP__ +#define __MAKE_MAXIMAL_PLANAR_HPP__ + +#include +#include //for tie +#include +#include +#include +#include +#include + +#include +#include + + +namespace boost +{ + + + template + struct triangulation_visitor : public planar_face_traversal_visitor + { + + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::edge_descriptor edge_t; + typedef typename graph_traits::vertices_size_type v_size_t; + typedef typename graph_traits::degree_size_type degree_size_t; + typedef typename graph_traits::edge_iterator edge_iterator_t; + typedef typename graph_traits::vertex_iterator vertex_iterator_t; + typedef typename graph_traits::adjacency_iterator + adjacency_iterator_t; + typedef typename std::vector vertex_vector_t; + typedef typename std::vector v_size_vector_t; + typedef typename std::vector degree_size_vector_t; + typedef iterator_property_map + < typename v_size_vector_t::iterator, VertexIndexMap > + vertex_to_v_size_map_t; + typedef iterator_property_map + < typename degree_size_vector_t::iterator, VertexIndexMap > + vertex_to_degree_size_map_t; + typedef typename vertex_vector_t::iterator face_iterator; + + + triangulation_visitor(Graph& arg_g, + VertexIndexMap arg_vm, + AddEdgeVisitor arg_add_edge_visitor + ) : + g(arg_g), + vm(arg_vm), + add_edge_visitor(arg_add_edge_visitor), + timestamp(0), + marked_vector(num_vertices(g), timestamp), + degree_vector(num_vertices(g), 0), + marked(marked_vector.begin(), vm), + degree(degree_vector.begin(), vm) + { + vertex_iterator_t vi, vi_end; + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + put(degree, *vi, out_degree(*vi, g)); + } + + template + void next_vertex(Vertex v) + { + // Self-loops will appear as consecutive vertices in the list of + // vertices on a face. We want to skip these. + if (!vertices_on_face.empty() && + (vertices_on_face.back() == v || vertices_on_face.front() == v) + ) + return; + + vertices_on_face.push_back(v); + } + + void end_face() + { + ++timestamp; + + if (vertices_on_face.size() <= 3) + { + // At most three vertices on this face - don't need to triangulate + vertices_on_face.clear(); + return; + } + + // Find vertex on face of minimum degree + degree_size_t min_degree = num_vertices(g); + typename vertex_vector_t::iterator min_degree_vertex_itr; + face_iterator fi_end = vertices_on_face.end(); + for(face_iterator fi = vertices_on_face.begin(); fi != fi_end; ++fi) + { + degree_size_t deg = get(degree,*fi); + if (deg < min_degree) + { + min_degree_vertex_itr = fi; + min_degree = deg; + } + } + + // To simplify some of the manipulations, we'll re-arrange + // vertices_on_face so that it still contains the same + // (counter-clockwise) order of the vertices on this face, but now the + // min_degree_vertex is the first element in vertices_on_face. + vertex_vector_t temp_vector; + std::copy(min_degree_vertex_itr, vertices_on_face.end(), + std::back_inserter(temp_vector)); + std::copy(vertices_on_face.begin(), min_degree_vertex_itr, + std::back_inserter(temp_vector)); + vertices_on_face.swap(temp_vector); + + // Mark all of the min degree vertex's neighbors + adjacency_iterator_t ai, ai_end; + for(tie(ai,ai_end) = adjacent_vertices(vertices_on_face.front(),g); + ai != ai_end; ++ai + ) + { + put(marked, *ai, timestamp); + } + + typename vertex_vector_t::iterator marked_neighbor + = vertices_on_face.end(); + + // The iterator manipulations on the next two lines are safe because + // vertices_on_face.size() > 3 (from the first test in this function) + fi_end = prior(vertices_on_face.end()); + for(face_iterator fi = next(next(vertices_on_face.begin())); + fi != fi_end; ++fi + ) + { + if (get(marked, *fi) == timestamp) + { + marked_neighbor = fi; + break; + } + } + + if (marked_neighbor == vertices_on_face.end()) + { + add_edge_range( + vertices_on_face[0], + next(next(vertices_on_face.begin())), + prior(vertices_on_face.end()) + ); + } + else + { + add_edge_range( + vertices_on_face[1], + next(marked_neighbor), + vertices_on_face.end() + ); + + add_edge_range( + *next(marked_neighbor), + next(next(vertices_on_face.begin())), + marked_neighbor + ); + } + + //reset for the next face + vertices_on_face.clear(); + + } + + private: + + + void add_edge_range(vertex_t anchor, + face_iterator fi, + face_iterator fi_end + ) + { + for (; fi != fi_end; ++fi) + { + vertex_t v(*fi); + add_edge_visitor.visit_vertex_pair(anchor, v, g); + put(degree, anchor, get(degree, anchor) + 1); + put(degree, v, get(degree, v) + 1); + } + } + + + Graph& g; + VertexIndexMap vm; + AddEdgeVisitor add_edge_visitor; + v_size_t timestamp; + vertex_vector_t vertices_on_face; + v_size_vector_t marked_vector; + degree_size_vector_t degree_vector; + vertex_to_v_size_map_t marked; + vertex_to_degree_size_map_t degree; + + }; + + + + + template + void make_maximal_planar(Graph& g, + PlanarEmbedding embedding, + VertexIndexMap vm, + EdgeIndexMap em, + AddEdgeVisitor& vis) + { + triangulation_visitor + visitor(g, vm, vis); + planar_face_traversal(g, embedding, visitor, em); + } + + + + + template + void make_maximal_planar(Graph& g, + PlanarEmbedding embedding, + VertexIndexMap vm, + EdgeIndexMap em + ) + { + default_add_edge_visitor vis; + make_maximal_planar(g, embedding, vm, em, vis); + } + + + + + template + void make_maximal_planar(Graph& g, + PlanarEmbedding embedding, + VertexIndexMap vm + ) + { + make_maximal_planar(g, embedding, vm, get(edge_index,g)); + } + + + + + template + void make_maximal_planar(Graph& g, + PlanarEmbedding embedding + ) + { + make_maximal_planar(g, embedding, get(vertex_index,g)); + } + + + + +} // namespace boost + + + +#endif //__MAKE_MAXIMAL_PLANAR_HPP__ diff --git a/win32/include/boost/graph/matrix_as_graph.hpp b/win32/include/boost/graph/matrix_as_graph.hpp new file mode 100755 index 000000000..064f36e80 --- /dev/null +++ b/win32/include/boost/graph/matrix_as_graph.hpp @@ -0,0 +1,127 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_MATRIX2GRAPH_HPP +#define BOOST_GRAPH_MATRIX2GRAPH_HPP + +#include +#include +#include +#include +#include + +namespace boost { + + template + class matrix_adj_iterator; + + template + class matrix_incidence_iterator; + +} + +#define BOOST_GRAPH_ADAPT_MATRIX_TO_GRAPH(Matrix) \ +namespace boost { \ + template <> \ + struct graph_traits< Matrix > { \ + typedef Matrix::OneD::const_iterator Iter; \ + typedef Matrix::size_type V; \ + typedef V vertex_descriptor; \ + typedef Iter E; \ + typedef E edge_descriptor; \ + typedef boost::matrix_incidence_iterator out_edge_iterator; \ + typedef boost::matrix_adj_iterator adjacency_iterator; \ + typedef Matrix::size_type size_type; \ + typedef boost::int_iterator vertex_iterator; \ + \ + friend std::pair \ + vertices(const Matrix& g) { \ + typedef vertex_iterator VIter; \ + return std::make_pair(VIter(0), VIter(g.nrows())); \ + } \ + \ + friend std::pair \ + out_edges(V v, const Matrix& g) { \ + typedef out_edge_iterator IncIter; \ + return std::make_pair(IncIter(g[v].begin()), \ + IncIter(g[v].end())); \ + } \ + friend std::pair \ + adjacent_vertices(V v, const Matrix& g) { \ + typedef adjacency_iterator AdjIter; \ + return std::make_pair(AdjIter(g[v].begin()), \ + AdjIter(g[v].end())); \ + } \ + friend vertex_descriptor \ + source(E e, const Matrix& g) { \ + return e.row(); \ + } \ + friend vertex_descriptor \ + target(E e, const Matrix& g) { \ + return e.column(); \ + } \ + friend size_type \ + num_vertices(const Matrix& g) { \ + return g.nrows(); \ + } \ + friend size_type \ + num_edges(const Matrix& g) { \ + return g.nnz(); \ + } \ + friend size_type \ + out_degree(V i, const Matrix& g) { \ + return g[i].nnz(); \ + } \ + }; \ +} + +namespace boost { + + template + class matrix_adj_iterator + : public std::iterator + { + typedef matrix_adj_iterator self; + public: + matrix_adj_iterator() { } + matrix_adj_iterator(Iter i) : _iter(i) { } + matrix_adj_iterator(const self& x) : _iter(x._iter) { } + self& operator=(const self& x) { _iter = x._iter; return *this; } + Vertex operator*() { return _iter.column(); } + self& operator++() { ++_iter; return *this; } + self operator++(int) { self t = *this; ++_iter; return t; } + bool operator==(const self& x) const { return _iter == x._iter; } + bool operator!=(const self& x) const { return _iter != x._iter; } + protected: + Iter _iter; + }; + + template + class matrix_incidence_iterator + : public std::iterator + { + typedef matrix_incidence_iterator self; + public: + matrix_incidence_iterator() { } + matrix_incidence_iterator(Iter i) : _iter(i) { } + matrix_incidence_iterator(const self& x) : _iter(x._iter) { } + self& operator=(const self& x) { _iter = x._iter; return *this; } + Iter operator*() { return _iter; } + self& operator++() { ++_iter; return *this; } + self operator++(int) { self t = *this; ++_iter; return t; } + bool operator==(const self& x) const { return _iter == x._iter; } + bool operator!=(const self& x) const { return _iter != x._iter; } + protected: + Iter _iter; + }; + +} /* namespace boost */ + +#endif /* BOOST_GRAPH_MATRIX2GRAPH_HPP*/ diff --git a/win32/include/boost/graph/max_cardinality_matching.hpp b/win32/include/boost/graph/max_cardinality_matching.hpp new file mode 100755 index 000000000..2405d5995 --- /dev/null +++ b/win32/include/boost/graph/max_cardinality_matching.hpp @@ -0,0 +1,883 @@ +//======================================================================= +// Copyright (c) 2005 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +//======================================================================= + +#ifndef BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP +#define BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP + +#include +#include +#include +#include // for std::sort and std::stable_sort +#include // for std::pair +#include +#include // for boost::tie +#include +#include +#include +#include +#include +#include + + +namespace boost +{ + namespace graph { namespace detail { + enum { V_EVEN, V_ODD, V_UNREACHED }; + } } // end namespace graph::detail + + template + typename graph_traits::vertices_size_type + matching_size(const Graph& g, MateMap mate, VertexIndexMap vm) + { + typedef typename graph_traits::vertex_iterator vertex_iterator_t; + typedef typename graph_traits::vertex_descriptor + vertex_descriptor_t; + typedef typename graph_traits::vertices_size_type v_size_t; + + v_size_t size_of_matching = 0; + vertex_iterator_t vi, vi_end; + + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_descriptor_t v = *vi; + if (get(mate,v) != graph_traits::null_vertex() + && get(vm,v) < get(vm,get(mate,v))) + ++size_of_matching; + } + return size_of_matching; + } + + + + + template + inline typename graph_traits::vertices_size_type + matching_size(const Graph& g, MateMap mate) + { + return matching_size(g, mate, get(vertex_index,g)); + } + + + + + template + bool is_a_matching(const Graph& g, MateMap mate, VertexIndexMap vm) + { + typedef typename graph_traits::vertex_descriptor + vertex_descriptor_t; + typedef typename graph_traits::vertex_iterator vertex_iterator_t; + + vertex_iterator_t vi, vi_end; + for( tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_descriptor_t v = *vi; + if (get(mate,v) != graph_traits::null_vertex() + && v != get(mate,get(mate,v))) + return false; + } + return true; + } + + + + + template + inline bool is_a_matching(const Graph& g, MateMap mate) + { + return is_a_matching(g, mate, get(vertex_index,g)); + } + + + + + //*************************************************************************** + //*************************************************************************** + // Maximum Cardinality Matching Functors + //*************************************************************************** + //*************************************************************************** + + template + struct no_augmenting_path_finder + { + no_augmenting_path_finder(const Graph& g, MateMap mate, VertexIndexMap vm) + { } + + inline bool augment_matching() { return false; } + + template + void get_current_matching(PropertyMap p) {} + }; + + + + + template + class edmonds_augmenting_path_finder + { + // This implementation of Edmonds' matching algorithm closely + // follows Tarjan's description of the algorithm in "Data + // Structures and Network Algorithms." + + public: + + //generates the type of an iterator property map from vertices to type X + template + struct map_vertex_to_ + { + typedef boost::iterator_property_map::iterator, + VertexIndexMap> type; + }; + + typedef typename graph_traits::vertex_descriptor + vertex_descriptor_t; + typedef typename std::pair< vertex_descriptor_t, vertex_descriptor_t > + vertex_pair_t; + typedef typename graph_traits::edge_descriptor edge_descriptor_t; + typedef typename graph_traits::vertices_size_type v_size_t; + typedef typename graph_traits::edges_size_type e_size_t; + typedef typename graph_traits::vertex_iterator vertex_iterator_t; + typedef typename graph_traits::out_edge_iterator + out_edge_iterator_t; + typedef typename std::deque vertex_list_t; + typedef typename std::vector edge_list_t; + typedef typename map_vertex_to_::type + vertex_to_vertex_map_t; + typedef typename map_vertex_to_::type vertex_to_int_map_t; + typedef typename map_vertex_to_::type + vertex_to_vertex_pair_map_t; + typedef typename map_vertex_to_::type vertex_to_vsize_map_t; + typedef typename map_vertex_to_::type vertex_to_esize_map_t; + + + + + edmonds_augmenting_path_finder(const Graph& arg_g, MateMap arg_mate, + VertexIndexMap arg_vm) : + g(arg_g), + vm(arg_vm), + n_vertices(num_vertices(arg_g)), + + mate_vector(n_vertices), + ancestor_of_v_vector(n_vertices), + ancestor_of_w_vector(n_vertices), + vertex_state_vector(n_vertices), + origin_vector(n_vertices), + pred_vector(n_vertices), + bridge_vector(n_vertices), + ds_parent_vector(n_vertices), + ds_rank_vector(n_vertices), + + mate(mate_vector.begin(), vm), + ancestor_of_v(ancestor_of_v_vector.begin(), vm), + ancestor_of_w(ancestor_of_w_vector.begin(), vm), + vertex_state(vertex_state_vector.begin(), vm), + origin(origin_vector.begin(), vm), + pred(pred_vector.begin(), vm), + bridge(bridge_vector.begin(), vm), + ds_parent_map(ds_parent_vector.begin(), vm), + ds_rank_map(ds_rank_vector.begin(), vm), + + ds(ds_rank_map, ds_parent_map) + { + vertex_iterator_t vi, vi_end; + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + mate[*vi] = get(arg_mate, *vi); + } + + + + + bool augment_matching() + { + //As an optimization, some of these values can be saved from one + //iteration to the next instead of being re-initialized each + //iteration, allowing for "lazy blossom expansion." This is not + //currently implemented. + + e_size_t timestamp = 0; + even_edges.clear(); + + vertex_iterator_t vi, vi_end; + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_descriptor_t u = *vi; + + origin[u] = u; + pred[u] = u; + ancestor_of_v[u] = 0; + ancestor_of_w[u] = 0; + ds.make_set(u); + + if (mate[u] == graph_traits::null_vertex()) + { + vertex_state[u] = graph::detail::V_EVEN; + out_edge_iterator_t ei, ei_end; + for(tie(ei,ei_end) = out_edges(u,g); ei != ei_end; ++ei) + even_edges.push_back( *ei ); + } + else + vertex_state[u] = graph::detail::V_UNREACHED; + } + + //end initializations + + vertex_descriptor_t v,w,w_free_ancestor,v_free_ancestor; + w_free_ancestor = graph_traits::null_vertex(); + v_free_ancestor = graph_traits::null_vertex(); + bool found_alternating_path = false; + + while(!even_edges.empty() && !found_alternating_path) + { + // since we push even edges onto the back of the list as + // they're discovered, taking them off the back will search + // for augmenting paths depth-first. + edge_descriptor_t current_edge = even_edges.back(); + even_edges.pop_back(); + + v = source(current_edge,g); + w = target(current_edge,g); + + vertex_descriptor_t v_prime = origin[ds.find_set(v)]; + vertex_descriptor_t w_prime = origin[ds.find_set(w)]; + + // because of the way we put all of the edges on the queue, + // v_prime should be labeled V_EVEN; the following is a + // little paranoid but it could happen... + if (vertex_state[v_prime] != graph::detail::V_EVEN) + { + std::swap(v_prime,w_prime); + std::swap(v,w); + } + + if (vertex_state[w_prime] == graph::detail::V_UNREACHED) + { + vertex_state[w_prime] = graph::detail::V_ODD; + vertex_state[mate[w_prime]] = graph::detail::V_EVEN; + out_edge_iterator_t ei, ei_end; + for( tie(ei,ei_end) = out_edges(mate[w_prime], g); ei != ei_end; ++ei) + even_edges.push_back(*ei); + pred[w_prime] = v; + } + + //w_prime == v_prime can happen below if we get an edge that has been + //shrunk into a blossom + else if (vertex_state[w_prime] == graph::detail::V_EVEN && w_prime != v_prime) + { + vertex_descriptor_t w_up = w_prime; + vertex_descriptor_t v_up = v_prime; + vertex_descriptor_t nearest_common_ancestor + = graph_traits::null_vertex(); + w_free_ancestor = graph_traits::null_vertex(); + v_free_ancestor = graph_traits::null_vertex(); + + // We now need to distinguish between the case that + // w_prime and v_prime share an ancestor under the + // "parent" relation, in which case we've found a + // blossom and should shrink it, or the case that + // w_prime and v_prime both have distinct ancestors that + // are free, in which case we've found an alternating + // path between those two ancestors. + + ++timestamp; + + while (nearest_common_ancestor == graph_traits::null_vertex() && + (v_free_ancestor == graph_traits::null_vertex() || + w_free_ancestor == graph_traits::null_vertex() + ) + ) + { + ancestor_of_w[w_up] = timestamp; + ancestor_of_v[v_up] = timestamp; + + if (w_free_ancestor == graph_traits::null_vertex()) + w_up = parent(w_up); + if (v_free_ancestor == graph_traits::null_vertex()) + v_up = parent(v_up); + + if (mate[v_up] == graph_traits::null_vertex()) + v_free_ancestor = v_up; + if (mate[w_up] == graph_traits::null_vertex()) + w_free_ancestor = w_up; + + if (ancestor_of_w[v_up] == timestamp) + nearest_common_ancestor = v_up; + else if (ancestor_of_v[w_up] == timestamp) + nearest_common_ancestor = w_up; + else if (v_free_ancestor == w_free_ancestor && + v_free_ancestor != graph_traits::null_vertex()) + nearest_common_ancestor = v_up; + } + + if (nearest_common_ancestor == graph_traits::null_vertex()) + found_alternating_path = true; //to break out of the loop + else + { + //shrink the blossom + link_and_set_bridges(w_prime, nearest_common_ancestor, std::make_pair(w,v)); + link_and_set_bridges(v_prime, nearest_common_ancestor, std::make_pair(v,w)); + } + } + } + + if (!found_alternating_path) + return false; + + // retrieve the augmenting path and put it in aug_path + reversed_retrieve_augmenting_path(v, v_free_ancestor); + retrieve_augmenting_path(w, w_free_ancestor); + + // augment the matching along aug_path + vertex_descriptor_t a,b; + while (!aug_path.empty()) + { + a = aug_path.front(); + aug_path.pop_front(); + b = aug_path.front(); + aug_path.pop_front(); + mate[a] = b; + mate[b] = a; + } + + return true; + + } + + + + + template + void get_current_matching(PropertyMap pm) + { + vertex_iterator_t vi,vi_end; + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + put(pm, *vi, mate[*vi]); + } + + + + + template + void get_vertex_state_map(PropertyMap pm) + { + vertex_iterator_t vi,vi_end; + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + put(pm, *vi, vertex_state[origin[ds.find_set(*vi)]]); + } + + + + + private: + + vertex_descriptor_t parent(vertex_descriptor_t x) + { + if (vertex_state[x] == graph::detail::V_EVEN + && mate[x] != graph_traits::null_vertex()) + return mate[x]; + else if (vertex_state[x] == graph::detail::V_ODD) + return origin[ds.find_set(pred[x])]; + else + return x; + } + + + + + void link_and_set_bridges(vertex_descriptor_t x, + vertex_descriptor_t stop_vertex, + vertex_pair_t the_bridge) + { + for(vertex_descriptor_t v = x; v != stop_vertex; v = parent(v)) + { + ds.union_set(v, stop_vertex); + origin[ds.find_set(stop_vertex)] = stop_vertex; + + if (vertex_state[v] == graph::detail::V_ODD) + { + bridge[v] = the_bridge; + out_edge_iterator_t oei, oei_end; + for(tie(oei, oei_end) = out_edges(v,g); oei != oei_end; ++oei) + even_edges.push_back(*oei); + } + } + } + + + // Since none of the STL containers support both constant-time + // concatenation and reversal, the process of expanding an + // augmenting path once we know one exists is a little more + // complicated than it has to be. If we know the path is from v to + // w, then the augmenting path is recursively defined as: + // + // path(v,w) = [v], if v = w + // = concat([v, mate[v]], path(pred[mate[v]], w), + // if v != w and vertex_state[v] == graph::detail::V_EVEN + // = concat([v], reverse(path(x,mate[v])), path(y,w)), + // if v != w, vertex_state[v] == graph::detail::V_ODD, and bridge[v] = (x,y) + // + // These next two mutually recursive functions implement this definition. + + void retrieve_augmenting_path(vertex_descriptor_t v, vertex_descriptor_t w) + { + if (v == w) + aug_path.push_back(v); + else if (vertex_state[v] == graph::detail::V_EVEN) + { + aug_path.push_back(v); + aug_path.push_back(mate[v]); + retrieve_augmenting_path(pred[mate[v]], w); + } + else //vertex_state[v] == graph::detail::V_ODD + { + aug_path.push_back(v); + reversed_retrieve_augmenting_path(bridge[v].first, mate[v]); + retrieve_augmenting_path(bridge[v].second, w); + } + } + + + void reversed_retrieve_augmenting_path(vertex_descriptor_t v, + vertex_descriptor_t w) + { + + if (v == w) + aug_path.push_back(v); + else if (vertex_state[v] == graph::detail::V_EVEN) + { + reversed_retrieve_augmenting_path(pred[mate[v]], w); + aug_path.push_back(mate[v]); + aug_path.push_back(v); + } + else //vertex_state[v] == graph::detail::V_ODD + { + reversed_retrieve_augmenting_path(bridge[v].second, w); + retrieve_augmenting_path(bridge[v].first, mate[v]); + aug_path.push_back(v); + } + } + + + + + //private data members + + const Graph& g; + VertexIndexMap vm; + v_size_t n_vertices; + + //storage for the property maps below + std::vector mate_vector; + std::vector ancestor_of_v_vector; + std::vector ancestor_of_w_vector; + std::vector vertex_state_vector; + std::vector origin_vector; + std::vector pred_vector; + std::vector bridge_vector; + std::vector ds_parent_vector; + std::vector ds_rank_vector; + + //iterator property maps + vertex_to_vertex_map_t mate; + vertex_to_esize_map_t ancestor_of_v; + vertex_to_esize_map_t ancestor_of_w; + vertex_to_int_map_t vertex_state; + vertex_to_vertex_map_t origin; + vertex_to_vertex_map_t pred; + vertex_to_vertex_pair_map_t bridge; + vertex_to_vertex_map_t ds_parent_map; + vertex_to_vsize_map_t ds_rank_map; + + vertex_list_t aug_path; + edge_list_t even_edges; + disjoint_sets< vertex_to_vsize_map_t, vertex_to_vertex_map_t > ds; + + }; + + + + + //*************************************************************************** + //*************************************************************************** + // Initial Matching Functors + //*************************************************************************** + //*************************************************************************** + + template + struct greedy_matching + { + typedef typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t; + typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t; + + static void find_matching(const Graph& g, MateMap mate) + { + vertex_iterator_t vi, vi_end; + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + put(mate, *vi, graph_traits::null_vertex()); + + edge_iterator_t ei, ei_end; + for( tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + edge_descriptor_t e = *ei; + vertex_descriptor_t u = source(e,g); + vertex_descriptor_t v = target(e,g); + + if (get(mate,u) == get(mate,v)) + //only way equality can hold is if + // mate[u] == mate[v] == null_vertex + { + put(mate,u,v); + put(mate,v,u); + } + } + } + }; + + + + + template + struct extra_greedy_matching + { + // The "extra greedy matching" is formed by repeating the + // following procedure as many times as possible: Choose the + // unmatched vertex v of minimum non-zero degree. Choose the + // neighbor w of v which is unmatched and has minimum degree over + // all of v's neighbors. Add (u,v) to the matching. Ties for + // either choice are broken arbitrarily. This procedure takes time + // O(m log n), where m is the number of edges in the graph and n + // is the number of vertices. + + typedef typename graph_traits< Graph >::vertex_descriptor + vertex_descriptor_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t; + typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t; + typedef std::pair vertex_pair_t; + + struct select_first + { + inline static vertex_descriptor_t select_vertex(const vertex_pair_t p) + {return p.first;} + }; + + struct select_second + { + inline static vertex_descriptor_t select_vertex(const vertex_pair_t p) + {return p.second;} + }; + + template + class less_than_by_degree + { + public: + less_than_by_degree(const Graph& g): m_g(g) {} + bool operator() (const vertex_pair_t x, const vertex_pair_t y) + { + return + out_degree(PairSelector::select_vertex(x), m_g) + < out_degree(PairSelector::select_vertex(y), m_g); + } + private: + const Graph& m_g; + }; + + + static void find_matching(const Graph& g, MateMap mate) + { + typedef std::vector > + directed_edges_vector_t; + + directed_edges_vector_t edge_list; + vertex_iterator_t vi, vi_end; + for(tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + put(mate, *vi, graph_traits::null_vertex()); + + edge_iterator_t ei, ei_end; + for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + edge_descriptor_t e = *ei; + vertex_descriptor_t u = source(e,g); + vertex_descriptor_t v = target(e,g); + edge_list.push_back(std::make_pair(u,v)); + edge_list.push_back(std::make_pair(v,u)); + } + + //sort the edges by the degree of the target, then (using a + //stable sort) by degree of the source + std::sort(edge_list.begin(), edge_list.end(), + less_than_by_degree(g)); + std::stable_sort(edge_list.begin(), edge_list.end(), + less_than_by_degree(g)); + + //construct the extra greedy matching + for(typename directed_edges_vector_t::const_iterator itr = edge_list.begin(); itr != edge_list.end(); ++itr) + { + if (get(mate,itr->first) == get(mate,itr->second)) + //only way equality can hold is if mate[itr->first] == mate[itr->second] == null_vertex + { + put(mate, itr->first, itr->second); + put(mate, itr->second, itr->first); + } + } + } + }; + + + + + template + struct empty_matching + { + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + + static void find_matching(const Graph& g, MateMap mate) + { + vertex_iterator_t vi, vi_end; + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + put(mate, *vi, graph_traits::null_vertex()); + } + }; + + + + + //*************************************************************************** + //*************************************************************************** + // Matching Verifiers + //*************************************************************************** + //*************************************************************************** + + namespace detail + { + + template + class odd_components_counter : public dfs_visitor<> + // This depth-first search visitor will count the number of connected + // components with an odd number of vertices. It's used by + // maximum_matching_verifier. + { + public: + odd_components_counter(SizeType& c_count): + m_count(c_count) + { + m_count = 0; + } + + template + void start_vertex(Vertex v, Graph&) + { + m_parity = false; + } + + template + void discover_vertex(Vertex u, Graph&) + { + m_parity = !m_parity; + m_parity ? ++m_count : --m_count; + } + + protected: + SizeType& m_count; + + private: + bool m_parity; + + }; + + }//namespace detail + + + + + template + struct no_matching_verifier + { + inline static bool + verify_matching(const Graph& g, MateMap mate, VertexIndexMap vm) + { return true;} + }; + + + + + template + struct maximum_cardinality_matching_verifier + { + + template + struct map_vertex_to_ + { + typedef boost::iterator_property_map::iterator, + VertexIndexMap> type; + }; + + typedef typename graph_traits::vertex_descriptor + vertex_descriptor_t; + typedef typename graph_traits::vertices_size_type v_size_t; + typedef typename graph_traits::vertex_iterator vertex_iterator_t; + typedef typename map_vertex_to_::type vertex_to_int_map_t; + typedef typename map_vertex_to_::type + vertex_to_vertex_map_t; + + + template + struct non_odd_vertex { + //this predicate is used to create a filtered graph that + //excludes vertices labeled "graph::detail::V_ODD" + non_odd_vertex() : vertex_state(0) { } + + non_odd_vertex(VertexStateMap* arg_vertex_state) + : vertex_state(arg_vertex_state) { } + + template + bool operator()(const Vertex& v) const + { + BOOST_ASSERT(vertex_state); + return get(*vertex_state, v) != graph::detail::V_ODD; + } + + VertexStateMap* vertex_state; + }; + + + static bool verify_matching(const Graph& g, MateMap mate, VertexIndexMap vm) + { + //For any graph G, let o(G) be the number of connected + //components in G of odd size. For a subset S of G's vertex set + //V(G), let (G - S) represent the subgraph of G induced by + //removing all vertices in S from G. Let M(G) be the size of the + //maximum cardinality matching in G. Then the Tutte-Berge + //formula guarantees that + // + // 2 * M(G) = min ( |V(G)| + |U| + o(G - U) ) + // + //where the minimum is taken over all subsets U of + //V(G). Edmonds' algorithm finds a set U that achieves the + //minimum in the above formula, namely the vertices labeled + //"ODD." This function runs one iteration of Edmonds' algorithm + //to find U, then verifies that the size of the matching given + //by mate satisfies the Tutte-Berge formula. + + //first, make sure it's a valid matching + if (!is_a_matching(g,mate,vm)) + return false; + + //We'll try to augment the matching once. This serves two + //purposes: first, if we find some augmenting path, the matching + //is obviously non-maximum. Second, running edmonds' algorithm + //on a graph with no augmenting path will create the + //Edmonds-Gallai decomposition that we need as a certificate of + //maximality - we can get it by looking at the vertex_state map + //that results. + edmonds_augmenting_path_finder + augmentor(g,mate,vm); + if (augmentor.augment_matching()) + return false; + + std::vector vertex_state_vector(num_vertices(g)); + vertex_to_int_map_t vertex_state(vertex_state_vector.begin(), vm); + augmentor.get_vertex_state_map(vertex_state); + + //count the number of graph::detail::V_ODD vertices + v_size_t num_odd_vertices = 0; + vertex_iterator_t vi, vi_end; + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + if (vertex_state[*vi] == graph::detail::V_ODD) + ++num_odd_vertices; + + //count the number of connected components with odd cardinality + //in the graph without graph::detail::V_ODD vertices + non_odd_vertex filter(&vertex_state); + filtered_graph > fg(g, keep_all(), filter); + + v_size_t num_odd_components; + detail::odd_components_counter occ(num_odd_components); + depth_first_search(fg, visitor(occ).vertex_index_map(vm)); + + if (2 * matching_size(g,mate,vm) == num_vertices(g) + num_odd_vertices - num_odd_components) + return true; + else + return false; + } + }; + + + + + template class AugmentingPathFinder, + template class InitialMatchingFinder, + template class MatchingVerifier> + bool matching(const Graph& g, MateMap mate, VertexIndexMap vm) + { + + InitialMatchingFinder::find_matching(g,mate); + + AugmentingPathFinder augmentor(g,mate,vm); + bool not_maximum_yet = true; + while(not_maximum_yet) + { + not_maximum_yet = augmentor.augment_matching(); + } + augmentor.get_current_matching(mate); + + return MatchingVerifier::verify_matching(g,mate,vm); + + } + + + + + template + inline bool checked_edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate, VertexIndexMap vm) + { + return matching + < Graph, MateMap, VertexIndexMap, + edmonds_augmenting_path_finder, extra_greedy_matching, maximum_cardinality_matching_verifier> + (g, mate, vm); + } + + + + + template + inline bool checked_edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate) + { + return checked_edmonds_maximum_cardinality_matching(g, mate, get(vertex_index,g)); + } + + + + + template + inline void edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate, VertexIndexMap vm) + { + matching < Graph, MateMap, VertexIndexMap, + edmonds_augmenting_path_finder, extra_greedy_matching, no_matching_verifier> + (g, mate, vm); + } + + + + + template + inline void edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate) + { + edmonds_maximum_cardinality_matching(g, mate, get(vertex_index,g)); + } + +}//namespace boost + +#endif //BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP diff --git a/win32/include/boost/graph/minimum_degree_ordering.hpp b/win32/include/boost/graph/minimum_degree_ordering.hpp new file mode 100755 index 000000000..b6d791a5b --- /dev/null +++ b/win32/include/boost/graph/minimum_degree_ordering.hpp @@ -0,0 +1,655 @@ +//-*-c++-*- +//======================================================================= +// Copyright 1997-2001 University of Notre Dame. +// Authors: Lie-Quan Lee, Jeremy Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef MINIMUM_DEGREE_ORDERING_HPP +#define MINIMUM_DEGREE_ORDERING_HPP + +#include +#include +#include +#include +#include // for integer_traits +#include +#include + +namespace boost { + + namespace detail { + + // + // Given a set of n integers (where the integer values range from + // zero to n-1), we want to keep track of a collection of stacks + // of integers. It so happens that an integer will appear in at + // most one stack at a time, so the stacks form disjoint sets. + // Because of these restrictions, we can use one big array to + // store all the stacks, intertwined with one another. + // No allocation/deallocation happens in the push()/pop() methods + // so this is faster than using std::stack's. + // + template + class Stacks { + typedef SignedInteger value_type; + typedef typename std::vector::size_type size_type; + public: + Stacks(size_type n) : data(n) {} + + //: stack + class stack { + typedef typename std::vector::iterator Iterator; + public: + stack(Iterator _data, const value_type& head) + : data(_data), current(head) {} + + // did not use default argument here to avoid internal compiler error + // in g++. + stack(Iterator _data) + : data(_data), current(-(std::numeric_limits::max)()) {} + + void pop() { + assert(! empty()); + current = data[current]; + } + void push(value_type v) { + data[v] = current; + current = v; + } + bool empty() { + return current == -(std::numeric_limits::max)(); + } + value_type& top() { return current; } + private: + Iterator data; + value_type current; + }; + + // To return a stack object + stack make_stack() + { return stack(data.begin()); } + protected: + std::vector data; + }; + + + // marker class, a generalization of coloring. + // + // This class is to provide a generalization of coloring which has + // complexity of amortized constant time to set all vertices' color + // back to be untagged. It implemented by increasing a tag. + // + // The colors are: + // not tagged + // tagged + // multiple_tagged + // done + // + template + class Marker { + typedef SignedInteger value_type; + typedef typename std::vector::size_type size_type; + + static value_type done() + { return (std::numeric_limits::max)()/2; } + public: + Marker(size_type _num, VertexIndexMap index_map) + : tag(1 - (std::numeric_limits::max)()), + data(_num, - (std::numeric_limits::max)()), + id(index_map) {} + + void mark_done(Vertex node) { data[get(id, node)] = done(); } + + bool is_done(Vertex node) { return data[get(id, node)] == done(); } + + void mark_tagged(Vertex node) { data[get(id, node)] = tag; } + + void mark_multiple_tagged(Vertex node) { data[get(id, node)] = multiple_tag; } + + bool is_tagged(Vertex node) const { return data[get(id, node)] >= tag; } + + bool is_not_tagged(Vertex node) const { return data[get(id, node)] < tag; } + + bool is_multiple_tagged(Vertex node) const + { return data[get(id, node)] >= multiple_tag; } + + void increment_tag() { + const size_type num = data.size(); + ++tag; + if ( tag >= done() ) { + tag = 1 - (std::numeric_limits::max)(); + for (size_type i = 0; i < num; ++i) + if ( data[i] < done() ) + data[i] = - (std::numeric_limits::max)(); + } + } + + void set_multiple_tag(value_type mdeg0) + { + const size_type num = data.size(); + multiple_tag = tag + mdeg0; + + if ( multiple_tag >= done() ) { + tag = 1-(std::numeric_limits::max)(); + + for (size_type i=0; i::max)(); + + multiple_tag = tag + mdeg0; + } + } + + void set_tag_as_multiple_tag() { tag = multiple_tag; } + + protected: + value_type tag; + value_type multiple_tag; + std::vector data; + VertexIndexMap id; + }; + + template< class Iterator, class SignedInteger, + class Vertex, class VertexIndexMap, int offset = 1 > + class Numbering { + typedef SignedInteger number_type; + number_type num; //start from 1 instead of zero + Iterator data; + number_type max_num; + VertexIndexMap id; + public: + Numbering(Iterator _data, number_type _max_num, VertexIndexMap id) + : num(1), data(_data), max_num(_max_num), id(id) {} + void operator()(Vertex node) { data[get(id, node)] = -num; } + bool all_done(number_type i = 0) const { return num + i > max_num; } + void increment(number_type i = 1) { num += i; } + bool is_numbered(Vertex node) const { + return data[get(id, node)] < 0; + } + void indistinguishable(Vertex i, Vertex j) { + data[get(id, i)] = - (get(id, j) + offset); + } + }; + + template + class degreelists_marker { + public: + typedef SignedInteger value_type; + typedef typename std::vector::size_type size_type; + degreelists_marker(size_type n, VertexIndexMap id) + : marks(n, 0), id(id) {} + void mark_need_update(Vertex i) { marks[get(id, i)] = 1; } + bool need_update(Vertex i) { return marks[get(id, i)] == 1; } + bool outmatched_or_done (Vertex i) { return marks[get(id, i)] == -1; } + void mark(Vertex i) { marks[get(id, i)] = -1; } + void unmark(Vertex i) { marks[get(id, i)] = 0; } + private: + std::vector marks; + VertexIndexMap id; + }; + + // Helper function object for edge removal + template + class predicateRemoveEdge1 { + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::edge_descriptor edge_t; + public: + predicateRemoveEdge1(Graph& _g, MarkerP& _marker, + NumberD _numbering, Stack& n_e, VertexIndexMap id) + : g(&_g), marker(&_marker), numbering(_numbering), + neighbor_elements(&n_e), id(id) {} + + bool operator()(edge_t e) { + vertex_t dist = target(e, *g); + if ( marker->is_tagged(dist) ) + return true; + marker->mark_tagged(dist); + if (numbering.is_numbered(dist)) { + neighbor_elements->push(get(id, dist)); + return true; + } + return false; + } + private: + Graph* g; + MarkerP* marker; + NumberD numbering; + Stack* neighbor_elements; + VertexIndexMap id; + }; + + // Helper function object for edge removal + template + class predicate_remove_tagged_edges + { + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::edge_descriptor edge_t; + public: + predicate_remove_tagged_edges(Graph& _g, MarkerP& _marker) + : g(&_g), marker(&_marker) {} + + bool operator()(edge_t e) { + vertex_t dist = target(e, *g); + if ( marker->is_tagged(dist) ) + return true; + return false; + } + private: + Graph* g; + MarkerP* marker; + }; + + template + class mmd_impl + { + // Typedefs + typedef graph_traits Traits; + typedef typename Traits::vertices_size_type size_type; + typedef typename detail::integer_traits::difference_type + diff_t; + typedef typename Traits::vertex_descriptor vertex_t; + typedef typename Traits::adjacency_iterator adj_iter; + typedef iterator_property_map IndexVertexMap; + typedef detail::Stacks Workspace; + typedef bucket_sorter + DegreeLists; + typedef Numbering + NumberingD; + typedef degreelists_marker + DegreeListsMarker; + typedef Marker MarkerP; + + // Data Members + + // input parameters + Graph& G; + int delta; + DegreeMap degree; + InversePermutationMap inverse_perm; + PermutationMap perm; + SuperNodeMap supernode_size; + VertexIndexMap vertex_index_map; + + // internal data-structures + std::vector index_vertex_vec; + size_type n; + IndexVertexMap index_vertex_map; + DegreeLists degreelists; + NumberingD numbering; + DegreeListsMarker degree_lists_marker; + MarkerP marker; + Workspace work_space; + public: + mmd_impl(Graph& g, size_type n_, int delta, DegreeMap degree, + InversePermutationMap inverse_perm, + PermutationMap perm, + SuperNodeMap supernode_size, + VertexIndexMap id) + : G(g), delta(delta), degree(degree), + inverse_perm(inverse_perm), + perm(perm), + supernode_size(supernode_size), + vertex_index_map(id), + index_vertex_vec(n_), + n(n_), + degreelists(n_ + 1, n_, degree, id), + numbering(inverse_perm, n_, vertex_index_map), + degree_lists_marker(n_, vertex_index_map), + marker(n_, vertex_index_map), + work_space(n_) + { + typename graph_traits::vertex_iterator v, vend; + size_type vid = 0; + for (tie(v, vend) = vertices(G); v != vend; ++v, ++vid) + index_vertex_vec[vid] = *v; + index_vertex_map = IndexVertexMap(&index_vertex_vec[0]); + + // Initialize degreelists. Degreelists organizes the nodes + // according to their degree. + for (tie(v, vend) = vertices(G); v != vend; ++v) { + put(degree, *v, out_degree(*v, G)); + degreelists.push(*v); + } + } + + void do_mmd() + { + // Eliminate the isolated nodes -- these are simply the nodes + // with no neighbors, which are accessible as a list (really, a + // stack) at location 0. Since these don't affect any other + // nodes, we can eliminate them without doing degree updates. + typename DegreeLists::stack list_isolated = degreelists[0]; + while (!list_isolated.empty()) { + vertex_t node = list_isolated.top(); + marker.mark_done(node); + numbering(node); + numbering.increment(); + list_isolated.pop(); + } + size_type min_degree = 1; + typename DegreeLists::stack list_min_degree = degreelists[min_degree]; + + while (list_min_degree.empty()) { + ++min_degree; + list_min_degree = degreelists[min_degree]; + } + + // check if the whole eliminating process is done + while (!numbering.all_done()) { + + size_type min_degree_limit = min_degree + delta; // WARNING + typename Workspace::stack llist = work_space.make_stack(); + + // multiple elimination + while (delta >= 0) { + + // Find the next non-empty degree + for (list_min_degree = degreelists[min_degree]; + list_min_degree.empty() && min_degree <= min_degree_limit; + ++min_degree, list_min_degree = degreelists[min_degree]) + ; + if (min_degree > min_degree_limit) + break; + + const vertex_t node = list_min_degree.top(); + const size_type node_id = get(vertex_index_map, node); + list_min_degree.pop(); + numbering(node); + + // check if node is the last one + if (numbering.all_done(supernode_size[node])) { + numbering.increment(supernode_size[node]); + break; + } + marker.increment_tag(); + marker.mark_tagged(node); + + this->eliminate(node); + + numbering.increment(supernode_size[node]); + llist.push(node_id); + } // multiple elimination + + if (numbering.all_done()) + break; + + this->update( llist, min_degree); + } + + } // do_mmd() + + void eliminate(vertex_t node) + { + typename Workspace::stack element_neighbor = work_space.make_stack(); + + // Create two function objects for edge removal + typedef typename Workspace::stack WorkStack; + predicateRemoveEdge1 + p(G, marker, numbering, element_neighbor, vertex_index_map); + + predicate_remove_tagged_edges p2(G, marker); + + // Reconstruct the adjacent node list, push element neighbor in a List. + remove_out_edge_if(node, p, G); + //during removal element neighbors are collected. + + while (!element_neighbor.empty()) { + // element absorb + size_type e_id = element_neighbor.top(); + vertex_t element = get(index_vertex_map, e_id); + adj_iter i, i_end; + for (tie(i, i_end) = adjacent_vertices(element, G); i != i_end; ++i){ + vertex_t i_node = *i; + if (!marker.is_tagged(i_node) && !numbering.is_numbered(i_node)) { + marker.mark_tagged(i_node); + add_edge(node, i_node, G); + } + } + element_neighbor.pop(); + } + adj_iter v, ve; + for (tie(v, ve) = adjacent_vertices(node, G); v != ve; ++v) { + vertex_t v_node = *v; + if (!degree_lists_marker.need_update(v_node) + && !degree_lists_marker.outmatched_or_done(v_node)) { + degreelists.remove(v_node); + } + //update out edges of v_node + remove_out_edge_if(v_node, p2, G); + + if ( out_degree(v_node, G) == 0 ) { // indistinguishable nodes + supernode_size[node] += supernode_size[v_node]; + supernode_size[v_node] = 0; + numbering.indistinguishable(v_node, node); + marker.mark_done(v_node); + degree_lists_marker.mark(v_node); + } else { // not indistinguishable nodes + add_edge(v_node, node, G); + degree_lists_marker.mark_need_update(v_node); + } + } + } // eliminate() + + + template + void update(Stack llist, size_type& min_degree) + { + size_type min_degree0 = min_degree + delta + 1; + + while (! llist.empty()) { + size_type deg, deg0 = 0; + + marker.set_multiple_tag(min_degree0); + typename Workspace::stack q2list = work_space.make_stack(); + typename Workspace::stack qxlist = work_space.make_stack(); + + vertex_t current = get(index_vertex_map, llist.top()); + adj_iter i, ie; + for (tie(i,ie) = adjacent_vertices(current, G); i != ie; ++i) { + vertex_t i_node = *i; + const size_type i_id = get(vertex_index_map, i_node); + if (supernode_size[i_node] != 0) { + deg0 += supernode_size[i_node]; + marker.mark_multiple_tagged(i_node); + if (degree_lists_marker.need_update(i_node)) { + if (out_degree(i_node, G) == 2) + q2list.push(i_id); + else + qxlist.push(i_id); + } + } + } + + while (!q2list.empty()) { + const size_type u_id = q2list.top(); + vertex_t u_node = get(index_vertex_map, u_id); + // if u_id is outmatched by others, no need to update degree + if (degree_lists_marker.outmatched_or_done(u_node)) { + q2list.pop(); + continue; + } + marker.increment_tag(); + deg = deg0; + + adj_iter nu = adjacent_vertices(u_node, G).first; + vertex_t neighbor = *nu; + if (neighbor == u_node) { + ++nu; + neighbor = *nu; + } + if (numbering.is_numbered(neighbor)) { + adj_iter i, ie; + for (tie(i,ie) = adjacent_vertices(neighbor, G); + i != ie; ++i) { + const vertex_t i_node = *i; + if (i_node == u_node || supernode_size[i_node] == 0) + continue; + if (marker.is_tagged(i_node)) { + if (degree_lists_marker.need_update(i_node)) { + if ( out_degree(i_node, G) == 2 ) { // is indistinguishable + supernode_size[u_node] += supernode_size[i_node]; + supernode_size[i_node] = 0; + numbering.indistinguishable(i_node, u_node); + marker.mark_done(i_node); + degree_lists_marker.mark(i_node); + } else // is outmatched + degree_lists_marker.mark(i_node); + } + } else { + marker.mark_tagged(i_node); + deg += supernode_size[i_node]; + } + } + } else + deg += supernode_size[neighbor]; + + deg -= supernode_size[u_node]; + degree[u_node] = deg; //update degree + degreelists[deg].push(u_node); + //u_id has been pushed back into degreelists + degree_lists_marker.unmark(u_node); + if (min_degree > deg) + min_degree = deg; + q2list.pop(); + } // while (!q2list.empty()) + + while (!qxlist.empty()) { + const size_type u_id = qxlist.top(); + const vertex_t u_node = get(index_vertex_map, u_id); + + // if u_id is outmatched by others, no need to update degree + if (degree_lists_marker.outmatched_or_done(u_node)) { + qxlist.pop(); + continue; + } + marker.increment_tag(); + deg = deg0; + adj_iter i, ie; + for (tie(i, ie) = adjacent_vertices(u_node, G); i != ie; ++i) { + vertex_t i_node = *i; + if (marker.is_tagged(i_node)) + continue; + marker.mark_tagged(i_node); + + if (numbering.is_numbered(i_node)) { + adj_iter j, je; + for (tie(j, je) = adjacent_vertices(i_node, G); j != je; ++j) { + const vertex_t j_node = *j; + if (marker.is_not_tagged(j_node)) { + marker.mark_tagged(j_node); + deg += supernode_size[j_node]; + } + } + } else + deg += supernode_size[i_node]; + } // for adjacent vertices of u_node + deg -= supernode_size[u_node]; + degree[u_node] = deg; + degreelists[deg].push(u_node); + // u_id has been pushed back into degreelists + degree_lists_marker.unmark(u_node); + if (min_degree > deg) + min_degree = deg; + qxlist.pop(); + } // while (!qxlist.empty()) { + + marker.set_tag_as_multiple_tag(); + llist.pop(); + } // while (! llist.empty()) + + } // update() + + + void build_permutation(InversePermutationMap next, + PermutationMap prev) + { + // collect the permutation info + size_type i; + for (i = 0; i < n; ++i) { + diff_t size = supernode_size[get(index_vertex_map, i)]; + if ( size <= 0 ) { + prev[i] = next[i]; + supernode_size[get(index_vertex_map, i)] + = next[i] + 1; // record the supernode info + } else + prev[i] = - next[i]; + } + for (i = 1; i < n + 1; ++i) { + if ( prev[i-1] > 0 ) + continue; + diff_t parent = i; + while ( prev[parent - 1] < 0 ) { + parent = - prev[parent - 1]; + } + + diff_t root = parent; + diff_t num = prev[root - 1] + 1; + next[i-1] = - num; + prev[root-1] = num; + + parent = i; + diff_t next_node = - prev[parent - 1]; + while (next_node > 0) { + prev[parent-1] = - root; + parent = next_node; + next_node = - prev[parent - 1]; + } + } + for (i = 0; i < n; i++) { + diff_t num = - next[i] - 1; + next[i] = num; + prev[num] = i; + } + } // build_permutation() + }; + + } //namespace detail + + + // MMD algorithm + // + //The implementation presently includes the enhancements for mass + //elimination, incomplete degree update, multiple elimination, and + //external degree. + // + //Important Note: This implementation requires the BGL graph to be + //directed. Therefore, nonzero entry (i, j) in a symmetrical matrix + //A coresponds to two directed edges (i->j and j->i). + // + //see Alan George and Joseph W. H. Liu, The Evolution of the Minimum + //Degree Ordering Algorithm, SIAM Review, 31, 1989, Page 1-19 + template + void minimum_degree_ordering + (Graph& G, + DegreeMap degree, + InversePermutationMap inverse_perm, + PermutationMap perm, + SuperNodeMap supernode_size, + int delta, + VertexIndexMap vertex_index_map) + { + detail::mmd_impl + impl(G, num_vertices(G), delta, degree, inverse_perm, + perm, supernode_size, vertex_index_map); + impl.do_mmd(); + impl.build_permutation(inverse_perm, perm); + } + +} // namespace boost + +#endif // MINIMUM_DEGREE_ORDERING_HPP diff --git a/win32/include/boost/graph/named_function_params.hpp b/win32/include/boost/graph/named_function_params.hpp new file mode 100755 index 000000000..6660b401c --- /dev/null +++ b/win32/include/boost/graph/named_function_params.hpp @@ -0,0 +1,795 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_NAMED_FUNCTION_PARAMS_HPP +#define BOOST_GRAPH_NAMED_FUNCTION_PARAMS_HPP + +#include + +namespace boost { + + struct distance_compare_t { }; + struct distance_combine_t { }; + struct distance_inf_t { }; + struct distance_zero_t { }; + struct buffer_param_t { }; + struct edge_copy_t { }; + struct vertex_copy_t { }; + struct vertex_isomorphism_t { }; + struct vertex_invariant_t { }; + struct vertex_invariant1_t { }; + struct vertex_invariant2_t { }; + struct edge_compare_t { }; + struct vertex_max_invariant_t { }; + struct orig_to_copy_t { }; + struct root_vertex_t { }; + struct attractive_force_t { }; + struct repulsive_force_t { }; + struct force_pairs_t { }; + struct cooling_t { }; + struct vertex_displacement_t { }; + struct iterations_t { }; + struct diameter_range_t { }; + struct learning_constant_range_t { }; + + namespace detail { + template + struct wrap_ref { + wrap_ref(T& r) : ref(r) {} + T& ref; + }; + } + + template + struct bgl_named_params : public Base + { + typedef bgl_named_params self; + typedef Base next_type; + typedef Tag tag_type; + typedef T value_type; + bgl_named_params(T v) : m_value(v) { } + bgl_named_params(T v, const Base& b) : Base(b), m_value(v) { } + T m_value; + + template + bgl_named_params + weight_map(const WeightMap& pmap) const { + typedef bgl_named_params Params; + return Params(pmap, *this); + } + + template + bgl_named_params + weight_map2(const WeightMap& pmap) const { + typedef bgl_named_params Params; + return Params(pmap, *this); + } + + template + bgl_named_params + distance_map(const DistanceMap& pmap) const { + typedef bgl_named_params Params; + return Params(pmap, *this); + } + + template + bgl_named_params + predecessor_map(const PredecessorMap& pmap) const { + typedef bgl_named_params + Params; + return Params(pmap, *this); + } + + template + bgl_named_params + rank_map(const RankMap& pmap) const { + typedef bgl_named_params + Params; + return Params(pmap, *this); + } + + template + bgl_named_params + root_map(const RootMap& pmap) const { + typedef bgl_named_params + Params; + return Params(pmap, *this); + } + + template + bgl_named_params + root_vertex(const Vertex& r) const { + typedef bgl_named_params Params; + return Params(r, *this); + } + + template + bgl_named_params + edge_centrality_map(const EdgeCentralityMap& r) const { + typedef bgl_named_params Params; + return Params(r, *this); + } + + template + bgl_named_params + centrality_map(const CentralityMap& r) const { + typedef bgl_named_params Params; + return Params(r, *this); + } + + template + bgl_named_params + color_map(const ColorMap& pmap) const { + typedef bgl_named_params Params; + return Params(pmap, *this); + } + + template + bgl_named_params + vertex_color_map(const ColorMap& pmap) const { + typedef bgl_named_params Params; + return Params(pmap, *this); + } + + template + bgl_named_params + edge_color_map(const ColorMap& pmap) const { + typedef bgl_named_params Params; + return Params(pmap, *this); + } + + template + bgl_named_params + capacity_map(CapacityMap pmap) { + typedef bgl_named_params Params; + return Params(pmap, *this); + } + + template + bgl_named_params + residual_capacity_map(Residual_CapacityMap pmap) { + typedef bgl_named_params + Params; + return Params(pmap, *this); + } + + template + bgl_named_params + reverse_edge_map(ReverseMap pmap) { + typedef bgl_named_params + Params; + return Params(pmap, *this); + } + + template + bgl_named_params + discover_time_map(const DiscoverTimeMap& pmap) const { + typedef bgl_named_params + Params; + return Params(pmap, *this); + } + + template + bgl_named_params + lowpoint_map(const LowPointMap& pmap) const { + typedef bgl_named_params + Params; + return Params(pmap, *this); + } + + template + bgl_named_params + vertex_index_map(const IndexMap& pmap) const { + typedef bgl_named_params Params; + return Params(pmap, *this); + } + + template + bgl_named_params + vertex_index1_map(const IndexMap& pmap) const { + typedef bgl_named_params Params; + return Params(pmap, *this); + } + + template + bgl_named_params + vertex_index2_map(const IndexMap& pmap) const { + typedef bgl_named_params Params; + return Params(pmap, *this); + } + + template + bgl_named_params + visitor(const Visitor& vis) const { + typedef bgl_named_params Params; + return Params(vis, *this); + } + + template + bgl_named_params + distance_compare(Compare cmp) const { + typedef bgl_named_params Params; + return Params(cmp, *this); + } + + template + bgl_named_params + distance_combine(Combine cmb) const { + typedef bgl_named_params Params; + return Params(cmb, *this); + } + + template + bgl_named_params + distance_inf(Init init) const { + typedef bgl_named_params Params; + return Params(init, *this); + } + + template + bgl_named_params + distance_zero(Init init) const { + typedef bgl_named_params Params; + return Params(init, *this); + } + + template + bgl_named_params, buffer_param_t, self> + buffer(Buffer& b) const { + typedef bgl_named_params, buffer_param_t, self> + Params; + return Params(detail::wrap_ref(b), *this); + } + + template + bgl_named_params + edge_copy(const Copier& c) const { + typedef bgl_named_params Params; + return Params(c, *this); + } + + template + bgl_named_params + vertex_copy(const Copier& c) const { + typedef bgl_named_params Params; + return Params(c, *this); + } + + template + bgl_named_params + orig_to_copy(const Orig2CopyMap& c) const { + typedef bgl_named_params Params; + return Params(c, *this); + } + + template + bgl_named_params + isomorphism_map(const IsoMap& c) const { + typedef bgl_named_params Params; + return Params(c, *this); + } + + template + bgl_named_params + vertex_invariant(const VertexInvar& c) const { + typedef bgl_named_params Params; + return Params(c, *this); + } + + template + bgl_named_params + vertex_invariant1(const VertexInvar& c) const { + typedef bgl_named_params Params; + return Params(c, *this); + } + + template + bgl_named_params + vertex_invariant2(const VertexInvar& c) const { + typedef bgl_named_params Params; + return Params(c, *this); + } + + template + bgl_named_params + vertex_max_invariant(const VertexMaxInvar& c) const { + typedef bgl_named_params Params; + return Params(c, *this); + } + + template + bgl_named_params + displacement_map(const VertexDisplacement& c) const { + typedef bgl_named_params Params; + return Params(c, *this); + } + + template + bgl_named_params + attractive_force(const AttractiveForce& c) { + typedef bgl_named_params Params; + return Params(c, *this); + } + + template + bgl_named_params + repulsive_force(const RepulsiveForce& c) { + typedef bgl_named_params Params; + return Params(c, *this); + } + + template + bgl_named_params + force_pairs(const ForcePairs& c) { + typedef bgl_named_params Params; + return Params(c, *this); + } + + template + bgl_named_params + cooling(const Cooling& c) { + typedef bgl_named_params Params; + return Params(c, *this); + } + + template + bgl_named_params + iterations(const TP& c) { + typedef bgl_named_params Params; + return Params(c, *this); + } + + template + bgl_named_params, diameter_range_t, self> + diameter_range(const std::pair& c) { + typedef bgl_named_params, diameter_range_t, self> Params; + return Params(c, *this); + } + + template + bgl_named_params, learning_constant_range_t, self> + learning_constant_range(const std::pair& c) { + typedef bgl_named_params, learning_constant_range_t, self> + Params; + return Params(c, *this); + } + }; + + template + bgl_named_params + weight_map(WeightMap pmap) { + typedef bgl_named_params Params; + return Params(pmap); + } + + template + bgl_named_params + weight_map2(WeightMap pmap) { + typedef bgl_named_params Params; + return Params(pmap); + } + + template + bgl_named_params + distance_map(DistanceMap pmap) { + typedef bgl_named_params Params; + return Params(pmap); + } + + template + bgl_named_params + predecessor_map(PredecessorMap pmap) { + typedef bgl_named_params Params; + return Params(pmap); + } + + template + bgl_named_params + rank_map(RankMap pmap) { + typedef bgl_named_params Params; + return Params(pmap); + } + + template + bgl_named_params + root_map(RootMap pmap) { + typedef bgl_named_params Params; + return Params(pmap); + } + + template + bgl_named_params + root_vertex(const Vertex& r) { + typedef bgl_named_params Params; + return Params(r); + } + + template + bgl_named_params + edge_centrality_map(const EdgeCentralityMap& r) { + typedef bgl_named_params Params; + return Params(r); + } + + template + bgl_named_params + centrality_map(const CentralityMap& r) { + typedef bgl_named_params Params; + return Params(r); + } + + template + bgl_named_params + color_map(ColorMap pmap) { + typedef bgl_named_params Params; + return Params(pmap); + } + + template + bgl_named_params + capacity_map(CapacityMap pmap) { + typedef bgl_named_params Params; + return Params(pmap); + } + + template + bgl_named_params + residual_capacity_map(Residual_CapacityMap pmap) { + typedef bgl_named_params + Params; + return Params(pmap); + } + + template + bgl_named_params + reverse_edge_map(ReverseMap pmap) { + typedef bgl_named_params + Params; + return Params(pmap); + } + + template + bgl_named_params + discover_time_map(DiscoverTimeMap pmap) { + typedef bgl_named_params Params; + return Params(pmap); + } + + template + bgl_named_params + lowpoint_map(LowPointMap pmap) { + typedef bgl_named_params Params; + return Params(pmap); + } + + template + bgl_named_params + vertex_index_map(IndexMap pmap) { + typedef bgl_named_params Params; + return Params(pmap); + } + + template + bgl_named_params + vertex_index1_map(const IndexMap& pmap) { + typedef bgl_named_params Params; + return Params(pmap); + } + + template + bgl_named_params + vertex_index2_map(const IndexMap& pmap) { + typedef bgl_named_params Params; + return Params(pmap); + } + + template + bgl_named_params + visitor(const Visitor& vis) { + typedef bgl_named_params Params; + return Params(vis); + } + + template + bgl_named_params + distance_compare(Compare cmp) { + typedef bgl_named_params Params; + return Params(cmp); + } + + template + bgl_named_params + distance_combine(Combine cmb) { + typedef bgl_named_params Params; + return Params(cmb); + } + + template + bgl_named_params + distance_inf(Init init) { + typedef bgl_named_params Params; + return Params(init); + } + + template + bgl_named_params + distance_zero(Init init) { + typedef bgl_named_params Params; + return Params(init); + } + + template + bgl_named_params, buffer_param_t> + buffer(Buffer& b) { + typedef bgl_named_params, buffer_param_t> Params; + return Params(detail::wrap_ref(b)); + } + + template + bgl_named_params + edge_copy(const Copier& c) { + typedef bgl_named_params Params; + return Params(c); + } + + template + bgl_named_params + vertex_copy(const Copier& c) { + typedef bgl_named_params Params; + return Params(c); + } + + template + bgl_named_params + orig_to_copy(const Orig2CopyMap& c) { + typedef bgl_named_params Params; + return Params(c); + } + + template + bgl_named_params + isomorphism_map(const IsoMap& c) { + typedef bgl_named_params Params; + return Params(c); + } + + template + bgl_named_params + vertex_invariant(const VertexInvar& c) { + typedef bgl_named_params Params; + return Params(c); + } + + template + bgl_named_params + vertex_invariant1(const VertexInvar& c) { + typedef bgl_named_params Params; + return Params(c); + } + + template + bgl_named_params + vertex_invariant2(const VertexInvar& c) { + typedef bgl_named_params Params; + return Params(c); + } + + template + bgl_named_params + vertex_max_invariant(const VertexMaxInvar& c) { + typedef bgl_named_params Params; + return Params(c); + } + + template + bgl_named_params + displacement_map(const VertexDisplacement& c) { + typedef bgl_named_params Params; + return Params(c); + } + + template + bgl_named_params + attractive_force(const AttractiveForce& c) { + typedef bgl_named_params Params; + return Params(c); + } + + template + bgl_named_params + repulsive_force(const RepulsiveForce& c) { + typedef bgl_named_params Params; + return Params(c); + } + + template + bgl_named_params + force_pairs(const ForcePairs& c) { + typedef bgl_named_params Params; + return Params(c); + } + + template + bgl_named_params + cooling(const Cooling& c) { + typedef bgl_named_params Params; + return Params(c); + } + + template + bgl_named_params + iterations(const T& c) { + typedef bgl_named_params Params; + return Params(c); + } + + template + bgl_named_params, diameter_range_t> + diameter_range(const std::pair& c) { + typedef bgl_named_params, diameter_range_t> Params; + return Params(c); + } + + template + bgl_named_params, learning_constant_range_t> + learning_constant_range(const std::pair& c) { + typedef bgl_named_params, learning_constant_range_t> + Params; + return Params(c); + } + + //=========================================================================== + // Functions for extracting parameters from bgl_named_params + + template + inline + typename property_value< bgl_named_params, Tag2>::type + get_param(const bgl_named_params& p, Tag2 tag2) + { + enum { match = detail::same_property::value }; + typedef typename + property_value< bgl_named_params, Tag2>::type T2; + T2* t2 = 0; + typedef detail::property_value_dispatch Dispatcher; + return Dispatcher::const_get_value(p, t2, tag2); + } + + + namespace detail { + // MSVC++ workaround + template + struct choose_param_helper { + template struct result { typedef Param type; }; + template + static const Param& apply(const Param& p, const Default&) { return p; } + }; + template <> + struct choose_param_helper { + template struct result { typedef Default type; }; + template + static const Default& apply(const error_property_not_found&, const Default& d) + { return d; } + }; + } // namespace detail + + template + const typename detail::choose_param_helper

            ::template result::type& + choose_param(const P& param, const Default& d) { + return detail::choose_param_helper

            ::apply(param, d); + } + + template + inline bool is_default_param(const T&) { return false; } + + inline bool is_default_param(const detail::error_property_not_found&) + { return true; } + + namespace detail { + + struct choose_parameter { + template + struct bind_ { + typedef const P& const_result_type; + typedef const P& result_type; + typedef P type; + }; + + template + static typename bind_::const_result_type + const_apply(const P& p, const Graph&, Tag&) + { return p; } + + template + static typename bind_::result_type + apply(const P& p, Graph&, Tag&) + { return p; } + }; + + struct choose_default_param { + template + struct bind_ { + typedef typename property_map::type + result_type; + typedef typename property_map::const_type + const_result_type; + typedef typename property_map::const_type + type; + }; + + template + static typename bind_::const_result_type + const_apply(const P&, const Graph& g, Tag tag) { + return get(tag, g); + } + template + static typename bind_::result_type + apply(const P&, Graph& g, Tag tag) { + return get(tag, g); + } + }; + + template + struct choose_property_map { + typedef choose_parameter type; + }; + template <> + struct choose_property_map { + typedef choose_default_param type; + }; + + template + struct choose_pmap_helper { + typedef typename choose_property_map::type Selector; + typedef typename Selector:: template bind_ Bind; + typedef Bind type; + typedef typename Bind::result_type result_type; + typedef typename Bind::const_result_type const_result_type; + typedef typename Bind::type result; + }; + + // used in the max-flow algorithms + template + struct edge_capacity_value + { + typedef bgl_named_params Params; + typedef typename property_value< Params, edge_capacity_t>::type Param; + typedef typename detail::choose_pmap_helper::result CapacityEdgeMap; + typedef typename property_traits::value_type type; + }; + + } // namespace detail + + + // Use this function instead of choose_param() when you want + // to avoid requiring get(tag, g) when it is not used. + template + typename + detail::choose_pmap_helper::const_result_type + choose_const_pmap(const Param& p, const Graph& g, PropertyTag tag) + { + typedef typename + detail::choose_pmap_helper::Selector Choice; + return Choice::const_apply(p, g, tag); + } + + template + typename detail::choose_pmap_helper::result_type + choose_pmap(const Param& p, Graph& g, PropertyTag tag) + { + typedef typename + detail::choose_pmap_helper::Selector Choice; + return Choice::apply(p, g, tag); + } + +} // namespace boost + +#endif // BOOST_GRAPH_NAMED_FUNCTION_PARAMS_HPP diff --git a/win32/include/boost/graph/neighbor_bfs.hpp b/win32/include/boost/graph/neighbor_bfs.hpp new file mode 100755 index 000000000..53ef7a18c --- /dev/null +++ b/win32/include/boost/graph/neighbor_bfs.hpp @@ -0,0 +1,323 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_NEIGHBOR_BREADTH_FIRST_SEARCH_HPP +#define BOOST_GRAPH_NEIGHBOR_BREADTH_FIRST_SEARCH_HPP + +/* + Neighbor Breadth First Search + Like BFS, but traverses in-edges as well as out-edges. + (for directed graphs only. use normal BFS for undirected graphs) +*/ +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + template + struct NeighborBFSVisitorConcept { + void constraints() { + function_requires< CopyConstructibleConcept >(); + vis.initialize_vertex(u, g); + vis.discover_vertex(u, g); + vis.examine_vertex(u, g); + vis.examine_out_edge(e, g); + vis.examine_in_edge(e, g); + vis.tree_out_edge(e, g); + vis.tree_in_edge(e, g); + vis.non_tree_out_edge(e, g); + vis.non_tree_in_edge(e, g); + vis.gray_target(e, g); + vis.black_target(e, g); + vis.gray_source(e, g); + vis.black_source(e, g); + vis.finish_vertex(u, g); + } + Visitor vis; + Graph g; + typename graph_traits::vertex_descriptor u; + typename graph_traits::edge_descriptor e; + }; + + template + class neighbor_bfs_visitor { + public: + neighbor_bfs_visitor(Visitors vis = Visitors()) : m_vis(vis) { } + + template + void initialize_vertex(Vertex u, Graph& g) { + invoke_visitors(m_vis, u, g, on_initialize_vertex()); + } + template + void discover_vertex(Vertex u, Graph& g) { + invoke_visitors(m_vis, u, g, on_discover_vertex()); + } + template + void examine_vertex(Vertex u, Graph& g) { + invoke_visitors(m_vis, u, g, on_examine_vertex()); + } + template + void examine_out_edge(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, on_examine_edge()); + } + template + void tree_out_edge(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, on_tree_edge()); + } + template + void non_tree_out_edge(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, on_non_tree_edge()); + } + template + void gray_target(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, on_gray_target()); + } + template + void black_target(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, on_black_target()); + } + template + void examine_in_edge(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, on_examine_edge()); + } + template + void tree_in_edge(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, on_tree_edge()); + } + template + void non_tree_in_edge(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, on_non_tree_edge()); + } + template + void gray_source(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, on_gray_target()); + } + template + void black_source(Edge e, Graph& g) { + invoke_visitors(m_vis, e, g, on_black_target()); + } + template + void finish_vertex(Vertex u, Graph& g) { + invoke_visitors(m_vis, u, g, on_finish_vertex()); + } + protected: + Visitors m_vis; + }; + + template + neighbor_bfs_visitor + make_neighbor_bfs_visitor(Visitors vis) { + return neighbor_bfs_visitor(vis); + } + + namespace detail { + + template + void neighbor_bfs_impl + (const BidirectionalGraph& g, + typename graph_traits::vertex_descriptor s, + Buffer& Q, BFSVisitor vis, ColorMap color) + + { + function_requires< BidirectionalGraphConcept >(); + typedef graph_traits GTraits; + typedef typename GTraits::vertex_descriptor Vertex; + typedef typename GTraits::edge_descriptor Edge; + function_requires< + NeighborBFSVisitorConcept >(); + function_requires< ReadWritePropertyMapConcept >(); + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + + put(color, s, Color::gray()); + vis.discover_vertex(s, g); + Q.push(s); + while (! Q.empty()) { + Vertex u = Q.top(); + Q.pop(); // pop before push to avoid problem if Q is priority_queue. + vis.examine_vertex(u, g); + + typename GTraits::out_edge_iterator ei, ei_end; + for (tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) { + Edge e = *ei; + vis.examine_out_edge(e, g); + Vertex v = target(e, g); + ColorValue v_color = get(color, v); + if (v_color == Color::white()) { + vis.tree_out_edge(e, g); + put(color, v, Color::gray()); + vis.discover_vertex(v, g); + Q.push(v); + } else { + vis.non_tree_out_edge(e, g); + if (v_color == Color::gray()) + vis.gray_target(e, g); + else + vis.black_target(e, g); + } + } // for out-edges + + typename GTraits::in_edge_iterator in_ei, in_ei_end; + for (tie(in_ei, in_ei_end) = in_edges(u, g); + in_ei != in_ei_end; ++in_ei) { + Edge e = *in_ei; + vis.examine_in_edge(e, g); + Vertex v = source(e, g); + ColorValue v_color = get(color, v); + if (v_color == Color::white()) { + vis.tree_in_edge(e, g); + put(color, v, Color::gray()); + vis.discover_vertex(v, g); + Q.push(v); + } else { + vis.non_tree_in_edge(e, g); + if (v_color == Color::gray()) + vis.gray_source(e, g); + else + vis.black_source(e, g); + } + } // for in-edges + + put(color, u, Color::black()); + vis.finish_vertex(u, g); + } // while + } + + + template + void neighbor_bfs_helper + (VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + ColorMap color, + BFSVisitor vis, + const bgl_named_params& params) + { + typedef graph_traits Traits; + // Buffer default + typedef typename Traits::vertex_descriptor Vertex; + typedef boost::queue queue_t; + queue_t Q; + detail::wrap_ref Qref(Q); + // Initialization + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + typename boost::graph_traits::vertex_iterator i, i_end; + for (tie(i, i_end) = vertices(g); i != i_end; ++i) { + put(color, *i, Color::white()); + vis.initialize_vertex(*i, g); + } + neighbor_bfs_impl + (g, s, + choose_param(get_param(params, buffer_param_t()), Qref).ref, + vis, color); + } + + //------------------------------------------------------------------------- + // Choose between default color and color parameters. Using + // function dispatching so that we don't require vertex index if + // the color default is not being used. + + template + struct neighbor_bfs_dispatch { + template + static void apply + (VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + const bgl_named_params& params, + ColorMap color) + { + neighbor_bfs_helper + (g, s, color, + choose_param(get_param(params, graph_visitor), + make_neighbor_bfs_visitor(null_visitor())), + params); + } + }; + + template <> + struct neighbor_bfs_dispatch { + template + static void apply + (VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + const bgl_named_params& params, + detail::error_property_not_found) + { + std::vector color_vec(num_vertices(g)); + null_visitor null_vis; + + neighbor_bfs_helper + (g, s, + make_iterator_property_map + (color_vec.begin(), + choose_const_pmap(get_param(params, vertex_index), + g, vertex_index), color_vec[0]), + choose_param(get_param(params, graph_visitor), + make_neighbor_bfs_visitor(null_vis)), + params); + } + }; + + } // namespace detail + + + // Named Parameter Variant + template + void neighbor_breadth_first_search + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + const bgl_named_params& params) + { + // The graph is passed by *const* reference so that graph adaptors + // (temporaries) can be passed into this function. However, the + // graph is not really const since we may write to property maps + // of the graph. + VertexListGraph& ng = const_cast(g); + typedef typename property_value< bgl_named_params, + vertex_color_t>::type C; + detail::neighbor_bfs_dispatch::apply(ng, s, params, + get_param(params, vertex_color)); + } + + + // This version does not initialize colors, user has to. + + template + void neighbor_breadth_first_visit + (IncidenceGraph& g, + typename graph_traits::vertex_descriptor s, + const bgl_named_params& params) + { + typedef graph_traits Traits; + // Buffer default + typedef boost::queue queue_t; + queue_t Q; + detail::wrap_ref Qref(Q); + + detail::neighbor_bfs_impl + (g, s, + choose_param(get_param(params, buffer_param_t()), Qref).ref, + choose_param(get_param(params, graph_visitor), + make_neighbor_bfs_visitor(null_visitor())), + choose_pmap(get_param(params, vertex_color), g, vertex_color) + ); + } + +} // namespace boost + +#endif // BOOST_GRAPH_NEIGHBOR_BREADTH_FIRST_SEARCH_HPP + diff --git a/win32/include/boost/graph/page_rank.hpp b/win32/include/boost/graph/page_rank.hpp new file mode 100755 index 000000000..f12644412 --- /dev/null +++ b/win32/include/boost/graph/page_rank.hpp @@ -0,0 +1,153 @@ +// Copyright 2004-5 The Trustees of Indiana University. +// Copyright 2002 Brad King and Douglas Gregor + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine + +#ifndef BOOST_GRAPH_PAGE_RANK_HPP +#define BOOST_GRAPH_PAGE_RANK_HPP + +#include +#include +#include +#include +#include + +namespace boost { namespace graph { + +struct n_iterations +{ + explicit n_iterations(std::size_t n) : n(n) { } + + template + bool + operator()(const RankMap&, const Graph&) + { + return n-- == 0; + } + + private: + std::size_t n; +}; + +namespace detail { + template + void page_rank_step(const Graph& g, RankMap from_rank, RankMap2 to_rank, + typename property_traits::value_type damping, + incidence_graph_tag) + { + typedef typename property_traits::value_type rank_type; + + // Set new rank maps + BGL_FORALL_VERTICES_T(v, g, Graph) put(to_rank, v, rank_type(1 - damping)); + + BGL_FORALL_VERTICES_T(u, g, Graph) { + rank_type u_rank_out = damping * get(from_rank, u) / out_degree(u, g); + BGL_FORALL_ADJ_T(u, v, g, Graph) + put(to_rank, v, get(to_rank, v) + u_rank_out); + } + } + + template + void page_rank_step(const Graph& g, RankMap from_rank, RankMap2 to_rank, + typename property_traits::value_type damping, + bidirectional_graph_tag) + { + typedef typename property_traits::value_type damping_type; + BGL_FORALL_VERTICES_T(v, g, Graph) { + typename property_traits::value_type rank(0); + BGL_FORALL_INEDGES_T(v, e, g, Graph) + rank += get(from_rank, source(e, g)) / out_degree(source(e, g), g); + put(to_rank, v, (damping_type(1) - damping) + damping * rank); + } + } +} // end namespace detail + +template +void +page_rank(const Graph& g, RankMap rank_map, Done done, + typename property_traits::value_type damping, + typename graph_traits::vertices_size_type n, + RankMap2 rank_map2) +{ + typedef typename property_traits::value_type rank_type; + + rank_type initial_rank = rank_type(rank_type(1) / n); + BGL_FORALL_VERTICES_T(v, g, Graph) put(rank_map, v, initial_rank); + + bool to_map_2 = true; + while ((to_map_2 && !done(rank_map, g)) || + (!to_map_2 && !done(rank_map2, g))) { + typedef typename graph_traits::traversal_category category; + + if (to_map_2) { + detail::page_rank_step(g, rank_map, rank_map2, damping, category()); + } else { + detail::page_rank_step(g, rank_map2, rank_map, damping, category()); + } + to_map_2 = !to_map_2; + } + + if (!to_map_2) { + BGL_FORALL_VERTICES_T(v, g, Graph) put(rank_map, v, get(rank_map2, v)); + } +} + +template +void +page_rank(const Graph& g, RankMap rank_map, Done done, + typename property_traits::value_type damping, + typename graph_traits::vertices_size_type n) +{ + typedef typename property_traits::value_type rank_type; + + std::vector ranks2(num_vertices(g)); + page_rank(g, rank_map, done, damping, n, + make_iterator_property_map(ranks2.begin(), get(vertex_index, g))); +} + +template +inline void +page_rank(const Graph& g, RankMap rank_map, Done done, + typename property_traits::value_type damping = 0.85) +{ + page_rank(g, rank_map, done, damping, num_vertices(g)); +} + +template +inline void +page_rank(const Graph& g, RankMap rank_map) +{ + page_rank(g, rank_map, n_iterations(20)); +} + +// TBD: this could be _much_ more efficient, using a queue to store +// the vertices that should be reprocessed and keeping track of which +// vertices are in the queue with a property map. Baah, this only +// applies when we have a bidirectional graph. +template +void +remove_dangling_links(MutableGraph& g) +{ + typename graph_traits::vertices_size_type old_n; + do { + old_n = num_vertices(g); + + typename graph_traits::vertex_iterator vi, vi_end; + for (tie(vi, vi_end) = vertices(g); vi != vi_end; /* in loop */) { + typename graph_traits::vertex_descriptor v = *vi++; + if (out_degree(v, g) == 0) { + clear_vertex(v, g); + remove_vertex(v, g); + } + } + } while (num_vertices(g) < old_n); +} + +} } // end namespace boost::graph + +#endif // BOOST_GRAPH_PAGE_RANK_HPP diff --git a/win32/include/boost/graph/planar_canonical_ordering.hpp b/win32/include/boost/graph/planar_canonical_ordering.hpp new file mode 100755 index 000000000..b10b95ac6 --- /dev/null +++ b/win32/include/boost/graph/planar_canonical_ordering.hpp @@ -0,0 +1,211 @@ +//======================================================================= +// Copyright (c) Aaron Windsor 2007 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef __PLANAR_CANONICAL_ORDERING_HPP__ +#define __PLANAR_CANONICAL_ORDERING_HPP__ + +#include +#include +#include +#include //for next and prior +#include +#include + + +namespace boost +{ + + + template + void planar_canonical_ordering(const Graph& g, + PlanarEmbedding embedding, + OutputIterator ordering, + VertexIndexMap vm) + { + + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::edge_descriptor edge_t; + typedef typename graph_traits::vertex_iterator vertex_iterator_t; + typedef typename graph_traits::adjacency_iterator + adjacency_iterator_t; + typedef typename std::pair vertex_pair_t; + typedef typename property_traits::value_type + embedding_value_t; + typedef typename embedding_value_t::const_iterator embedding_iterator_t; + typedef iterator_property_map + ::iterator, VertexIndexMap> + vertex_to_vertex_map_t; + typedef iterator_property_map + ::iterator, VertexIndexMap> + vertex_to_size_t_map_t; + + enum {PROCESSED, + UNPROCESSED, + ONE_NEIGHBOR_PROCESSED, + READY_TO_BE_PROCESSED}; + + std::vector processed_neighbor_vector(num_vertices(g)); + vertex_to_vertex_map_t processed_neighbor + (processed_neighbor_vector.begin(), vm); + + std::vector status_vector(num_vertices(g), UNPROCESSED); + vertex_to_size_t_map_t status(status_vector.begin(), vm); + + std::list ready_to_be_processed; + + vertex_t first_vertex = *vertices(g).first; + vertex_t second_vertex; + adjacency_iterator_t ai, ai_end; + for(tie(ai,ai_end) = adjacent_vertices(first_vertex,g); ai != ai_end; ++ai) + { + if (*ai == first_vertex) + continue; + second_vertex = *ai; + break; + } + + ready_to_be_processed.push_back(first_vertex); + status[first_vertex] = READY_TO_BE_PROCESSED; + ready_to_be_processed.push_back(second_vertex); + status[second_vertex] = READY_TO_BE_PROCESSED; + + while(!ready_to_be_processed.empty()) + { + vertex_t u = ready_to_be_processed.front(); + ready_to_be_processed.pop_front(); + + if (status[u] != READY_TO_BE_PROCESSED && u != second_vertex) + continue; + + embedding_iterator_t ei, ei_start, ei_end; + embedding_iterator_t next_edge_itr, prior_edge_itr; + + ei_start = embedding[u].begin(); + ei_end = embedding[u].end(); + prior_edge_itr = prior(ei_end); + while(source(*prior_edge_itr, g) == target(*prior_edge_itr,g)) + prior_edge_itr = prior(prior_edge_itr); + + for(ei = ei_start; ei != ei_end; ++ei) + { + + edge_t e(*ei); // e = (u,v) + next_edge_itr = next(ei) == ei_end ? ei_start : next(ei); + vertex_t v = source(e,g) == u ? target(e,g) : source(e,g); + + vertex_t prior_vertex = source(*prior_edge_itr, g) == u ? + target(*prior_edge_itr, g) : source(*prior_edge_itr, g); + vertex_t next_vertex = source(*next_edge_itr, g) == u ? + target(*next_edge_itr, g) : source(*next_edge_itr, g); + + // Need prior_vertex, u, v, and next_vertex to all be + // distinct. This is possible, since the input graph is + // triangulated. It'll be true all the time in a simple + // graph, but loops and parallel edges cause some complications. + if (prior_vertex == v || prior_vertex == u) + { + prior_edge_itr = ei; + continue; + } + + //Skip any self-loops + if (u == v) + continue; + + // Move next_edge_itr (and next_vertex) forwards + // past any loops or parallel edges + while (next_vertex == v || next_vertex == u) + { + next_edge_itr = next(next_edge_itr) == ei_end ? + ei_start : next(next_edge_itr); + next_vertex = source(*next_edge_itr, g) == u ? + target(*next_edge_itr, g) : source(*next_edge_itr, g); + } + + + if (status[v] == UNPROCESSED) + { + status[v] = ONE_NEIGHBOR_PROCESSED; + processed_neighbor[v] = u; + } + else if (status[v] == ONE_NEIGHBOR_PROCESSED) + { + vertex_t x = processed_neighbor[v]; + //are edges (v,u) and (v,x) adjacent in the planar + //embedding? if so, set status[v] = 1. otherwise, set + //status[v] = 2. + + if ((next_vertex == x && + !(first_vertex == u && second_vertex == x) + ) + || + (prior_vertex == x && + !(first_vertex == x && second_vertex == u) + ) + ) + { + status[v] = READY_TO_BE_PROCESSED; + } + else + { + status[v] = READY_TO_BE_PROCESSED + 1; + } + } + else if (status[v] > ONE_NEIGHBOR_PROCESSED) + { + //check the two edges before and after (v,u) in the planar + //embedding, and update status[v] accordingly + + bool processed_before = false; + if (status[prior_vertex] == PROCESSED) + processed_before = true; + + bool processed_after = false; + if (status[next_vertex] == PROCESSED) + processed_after = true; + + if (!processed_before && !processed_after) + ++status[v]; + + else if (processed_before && processed_after) + --status[v]; + + } + + if (status[v] == READY_TO_BE_PROCESSED) + ready_to_be_processed.push_back(v); + + prior_edge_itr = ei; + + } + + status[u] = PROCESSED; + *ordering = u; + ++ordering; + + } + + } + + + template + void planar_canonical_ordering(const Graph& g, + PlanarEmbedding embedding, + OutputIterator ordering + ) + { + planar_canonical_ordering(g, embedding, ordering, get(vertex_index,g)); + } + + +} //namespace boost + +#endif //__PLANAR_CANONICAL_ORDERING_HPP__ diff --git a/win32/include/boost/graph/planar_detail/add_edge_visitors.hpp b/win32/include/boost/graph/planar_detail/add_edge_visitors.hpp new file mode 100755 index 000000000..7b5bf6564 --- /dev/null +++ b/win32/include/boost/graph/planar_detail/add_edge_visitors.hpp @@ -0,0 +1,59 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __ADD_EDGE_VISITORS_HPP__ +#define __ADD_EDGE_VISITORS_HPP__ + +#include + +namespace boost +{ + + struct default_add_edge_visitor + { + + template + void visit_vertex_pair(Vertex u, Vertex v, Graph& g) + { + add_edge(u,v,g); + } + + }; + + template + struct edge_index_update_visitor + { + + typedef typename + property_traits::value_type edge_index_value_t; + + edge_index_update_visitor(EdgeIndexMap em, + edge_index_value_t next_index_available + ) : + m_em(em), + m_next_index(next_index_available) + {} + + template + void visit_vertex_pair(Vertex u, Vertex v, Graph& g) + { + typedef typename graph_traits::edge_descriptor edge_t; + std::pair return_value = add_edge(u,v,g); + if (return_value.second) + put( m_em, return_value.first, m_next_index++); + } + + private: + + EdgeIndexMap m_em; + edge_index_value_t m_next_index; + + }; + +} // namespace boost + +#endif //__ADD_EDGE_VISITORS_HPP__ diff --git a/win32/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp b/win32/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp new file mode 100755 index 000000000..44750fc60 --- /dev/null +++ b/win32/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp @@ -0,0 +1,2010 @@ +//======================================================================= +// Copyright (c) Aaron Windsor 2007 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __BOYER_MYRVOLD_IMPL_HPP__ +#define __BOYER_MYRVOLD_IMPL_HPP__ + +#include +#include +#include //for boost::next +#include //for std::min macros +#include +#include +#include +#include +#include +#include +#include +#include + + + +namespace boost +{ + + template + struct planar_dfs_visitor : public dfs_visitor<> + { + planar_dfs_visitor(LowPointMap lpm, DFSParentMap dfs_p, + DFSNumberMap dfs_n, LeastAncestorMap lam, + DFSParentEdgeMap dfs_edge) + : low(lpm), + parent(dfs_p), + df_number(dfs_n), + least_ancestor(lam), + df_edge(dfs_edge), + count(0) + {} + + + template + void start_vertex(const Vertex& u, Graph&) + { + put(parent, u, u); + put(least_ancestor, u, count); + } + + + template + void discover_vertex(const Vertex& u, Graph&) + { + put(low, u, count); + put(df_number, u, count); + ++count; + } + + template + void tree_edge(const Edge& e, Graph& g) + { + typedef typename graph_traits::vertex_descriptor vertex_t; + vertex_t s(source(e,g)); + vertex_t t(target(e,g)); + + put(parent, t, s); + put(df_edge, t, e); + put(least_ancestor, t, get(df_number, s)); + } + + template + void back_edge(const Edge& e, Graph& g) + { + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::vertices_size_type v_size_t; + + vertex_t s(source(e,g)); + vertex_t t(target(e,g)); + BOOST_USING_STD_MIN(); + + if ( t != get(parent, s) ) { + v_size_t s_low_df_number = get(low, s); + v_size_t t_df_number = get(df_number, t); + v_size_t s_least_ancestor_df_number = get(least_ancestor, s); + + put(low, s, + min BOOST_PREVENT_MACRO_SUBSTITUTION(s_low_df_number, + t_df_number) + ); + + put(least_ancestor, s, + min BOOST_PREVENT_MACRO_SUBSTITUTION(s_least_ancestor_df_number, + t_df_number + ) + ); + + } + } + + template + void finish_vertex(const Vertex& u, Graph& g) + { + typedef typename graph_traits::vertices_size_type v_size_t; + + Vertex u_parent = get(parent, u); + v_size_t u_parent_lowpoint = get(low, u_parent); + v_size_t u_lowpoint = get(low, u); + BOOST_USING_STD_MIN(); + + if (u_parent != u) + { + put(low, u_parent, + min BOOST_PREVENT_MACRO_SUBSTITUTION(u_lowpoint, + u_parent_lowpoint + ) + ); + } + } + + LowPointMap low; + DFSParentMap parent; + DFSNumberMap df_number; + LeastAncestorMap least_ancestor; + DFSParentEdgeMap df_edge; + SizeType count; + + }; + + + + + + + template + class boyer_myrvold_impl + { + + typedef typename graph_traits::vertices_size_type v_size_t; + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::edge_descriptor edge_t; + typedef typename graph_traits::vertex_iterator vertex_iterator_t; + typedef typename graph_traits::edge_iterator edge_iterator_t; + typedef typename graph_traits::out_edge_iterator + out_edge_iterator_t; + typedef graph::detail::face_handle + face_handle_t; + typedef std::vector vertex_vector_t; + typedef std::vector edge_vector_t; + typedef std::list vertex_list_t; + typedef std::list< face_handle_t > face_handle_list_t; + typedef boost::shared_ptr< face_handle_list_t > face_handle_list_ptr_t; + typedef boost::shared_ptr< vertex_list_t > vertex_list_ptr_t; + typedef boost::tuple merge_stack_frame_t; + typedef std::vector merge_stack_t; + + template + struct map_vertex_to_ + { + typedef iterator_property_map + ::iterator, VertexIndexMap> type; + }; + + typedef typename map_vertex_to_::type vertex_to_v_size_map_t; + typedef typename map_vertex_to_::type vertex_to_vertex_map_t; + typedef typename map_vertex_to_::type vertex_to_edge_map_t; + typedef typename map_vertex_to_::type + vertex_to_vertex_list_ptr_map_t; + typedef typename map_vertex_to_< edge_vector_t >::type + vertex_to_edge_vector_map_t; + typedef typename map_vertex_to_::type vertex_to_bool_map_t; + typedef typename map_vertex_to_::type + vertex_to_face_handle_map_t; + typedef typename map_vertex_to_::type + vertex_to_face_handle_list_ptr_map_t; + typedef typename map_vertex_to_::type + vertex_to_separated_node_map_t; + + template + struct face_vertex_iterator + { + typedef face_iterator + type; + }; + + template + struct face_edge_iterator + { + typedef face_iterator + type; + }; + + + + public: + + + + boyer_myrvold_impl(const Graph& arg_g, VertexIndexMap arg_vm): + g(arg_g), + vm(arg_vm), + + low_point_vector(num_vertices(g)), + dfs_parent_vector(num_vertices(g)), + dfs_number_vector(num_vertices(g)), + least_ancestor_vector(num_vertices(g)), + pertinent_roots_vector(num_vertices(g)), + backedge_flag_vector(num_vertices(g), num_vertices(g) + 1), + visited_vector(num_vertices(g), num_vertices(g) + 1), + face_handles_vector(num_vertices(g)), + dfs_child_handles_vector(num_vertices(g)), + separated_dfs_child_list_vector(num_vertices(g)), + separated_node_in_parent_list_vector(num_vertices(g)), + canonical_dfs_child_vector(num_vertices(g)), + flipped_vector(num_vertices(g), false), + backedges_vector(num_vertices(g)), + dfs_parent_edge_vector(num_vertices(g)), + + vertices_by_dfs_num(num_vertices(g)), + + low_point(low_point_vector.begin(), vm), + dfs_parent(dfs_parent_vector.begin(), vm), + dfs_number(dfs_number_vector.begin(), vm), + least_ancestor(least_ancestor_vector.begin(), vm), + pertinent_roots(pertinent_roots_vector.begin(), vm), + backedge_flag(backedge_flag_vector.begin(), vm), + visited(visited_vector.begin(), vm), + face_handles(face_handles_vector.begin(), vm), + dfs_child_handles(dfs_child_handles_vector.begin(), vm), + separated_dfs_child_list(separated_dfs_child_list_vector.begin(), vm), + separated_node_in_parent_list + (separated_node_in_parent_list_vector.begin(), vm), + canonical_dfs_child(canonical_dfs_child_vector.begin(), vm), + flipped(flipped_vector.begin(), vm), + backedges(backedges_vector.begin(), vm), + dfs_parent_edge(dfs_parent_edge_vector.begin(), vm) + + { + + planar_dfs_visitor + vis + (low_point, dfs_parent, dfs_number, least_ancestor, dfs_parent_edge); + + // Perform a depth-first search to find each vertex's low point, least + // ancestor, and dfs tree information + depth_first_search(g, visitor(vis).vertex_index_map(vm)); + + // Sort vertices by their lowpoint - need this later in the constructor + vertex_vector_t vertices_by_lowpoint(num_vertices(g)); + std::copy( vertices(g).first, vertices(g).second, + vertices_by_lowpoint.begin() + ); + bucket_sort(vertices_by_lowpoint.begin(), + vertices_by_lowpoint.end(), + low_point, + num_vertices(g) + ); + + // Sort vertices by their dfs number - need this to iterate by reverse + // DFS number in the main loop. + std::copy( vertices(g).first, vertices(g).second, + vertices_by_dfs_num.begin() + ); + bucket_sort(vertices_by_dfs_num.begin(), + vertices_by_dfs_num.end(), + dfs_number, + num_vertices(g) + ); + + // Initialize face handles. A face handle is an abstraction that serves + // two uses in our implementation - it allows us to efficiently move + // along the outer face of embedded bicomps in a partially embedded + // graph, and it provides storage for the planar embedding. Face + // handles are implemented by a sequence of edges and are associated + // with a particular vertex - the sequence of edges represents the + // current embedding of edges around that vertex, and the first and + // last edges in the sequence represent the pair of edges on the outer + // face that are adjacent to the associated vertex. This lets us embed + // edges in the graph by just pushing them on the front or back of the + // sequence of edges held by the face handles. + // + // Our algorithm starts with a DFS tree of edges (where every vertex is + // an articulation point and every edge is a singleton bicomp) and + // repeatedly merges bicomps by embedding additional edges. Note that + // any bicomp at any point in the algorithm can be associated with a + // unique edge connecting the vertex of that bicomp with the lowest DFS + // number (which we refer to as the "root" of the bicomp) with its DFS + // child in the bicomp: the existence of two such edges would contradict + // the properties of a DFS tree. We refer to the DFS child of the root + // of a bicomp as the "canonical DFS child" of the bicomp. Note that a + // vertex can be the root of more than one bicomp. + // + // We move around the external faces of a bicomp using a few property + // maps, which we'll initialize presently: + // + // - face_handles: maps a vertex to a face handle that can be used to + // move "up" a bicomp. For a vertex that isn't an articulation point, + // this holds the face handles that can be used to move around that + // vertex's unique bicomp. For a vertex that is an articulation point, + // this holds the face handles associated with the unique bicomp that + // the vertex is NOT the root of. These handles can therefore be used + // to move from any point on the outer face of the tree of bicomps + // around the current outer face towards the root of the DFS tree. + // + // - dfs_child_handles: these are used to hold face handles for + // vertices that are articulation points - dfs_child_handles[v] holds + // the face handles corresponding to vertex u in the bicomp with root + // u and canonical DFS child v. + // + // - canonical_dfs_child: this property map allows one to determine the + // canonical DFS child of a bicomp while traversing the outer face. + // This property map is only valid when applied to one of the two + // vertices adjacent to the root of the bicomp on the outer face. To + // be more precise, if v is the canonical DFS child of a bicomp, + // canonical_dfs_child[dfs_child_handles[v].first_vertex()] == v and + // canonical_dfs_child[dfs_child_handles[v].second_vertex()] == v. + // + // - pertinent_roots: given a vertex v, pertinent_roots[v] contains a + // list of face handles pointing to the top of bicomps that need to + // be visited by the current walkdown traversal (since they lead to + // backedges that need to be embedded). These lists are populated by + // the walkup and consumed by the walkdown. + + vertex_iterator_t vi, vi_end; + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_t v(*vi); + vertex_t parent = dfs_parent[v]; + + if (parent != v) + { + edge_t parent_edge = dfs_parent_edge[v]; + add_to_embedded_edges(parent_edge, StoreOldHandlesPolicy()); + face_handles[v] = face_handle_t(v, parent_edge, g); + dfs_child_handles[v] = face_handle_t(parent, parent_edge, g); + } + else + { + face_handles[v] = face_handle_t(v); + dfs_child_handles[v] = face_handle_t(parent); + } + + canonical_dfs_child[v] = v; + pertinent_roots[v] = face_handle_list_ptr_t(new face_handle_list_t); + separated_dfs_child_list[v] = vertex_list_ptr_t(new vertex_list_t); + + } + + // We need to create a list of not-yet-merged depth-first children for + // each vertex that will be updated as bicomps get merged. We sort each + // list by ascending lowpoint, which allows the externally_active + // function to run in constant time, and we keep a pointer to each + // vertex's representation in its parent's list, which allows merging + //in constant time. + + for(typename vertex_vector_t::iterator itr = + vertices_by_lowpoint.begin(); + itr != vertices_by_lowpoint.end(); ++itr) + { + vertex_t v(*itr); + vertex_t parent(dfs_parent[v]); + if (v != parent) + { + separated_node_in_parent_list[v] = + separated_dfs_child_list[parent]->insert + (separated_dfs_child_list[parent]->end(), v); + } + } + + // The merge stack holds path information during a walkdown iteration + merge_stack.reserve(num_vertices(g)); + + } + + + + + + + bool is_planar() + { + + // This is the main algorithm: starting with a DFS tree of embedded + // edges (which, since it's a tree, is planar), iterate through all + // vertices by reverse DFS number, attempting to embed all backedges + // connecting the current vertex to vertices with higher DFS numbers. + // + // The walkup is a procedure that examines all such backedges and sets + // up the required data structures so that they can be searched by the + // walkdown in linear time. The walkdown does the actual work of + // embedding edges and flipping bicomps, and can identify when it has + // come across a kuratowski subgraph. + // + // store_old_face_handles caches face handles from the previous + // iteration - this is used only for the kuratowski subgraph isolation, + // and is therefore dispatched based on the StoreOldHandlesPolicy. + // + // clean_up_embedding does some clean-up and fills in values that have + // to be computed lazily during the actual execution of the algorithm + // (for instance, whether or not a bicomp is flipped in the final + // embedding). It's dispatched on the the StoreEmbeddingPolicy, since + // it's not needed if an embedding isn't desired. + + typename vertex_vector_t::reverse_iterator vi, vi_end; + + vi_end = vertices_by_dfs_num.rend(); + for(vi = vertices_by_dfs_num.rbegin(); vi != vi_end; ++vi) + { + + store_old_face_handles(StoreOldHandlesPolicy()); + + vertex_t v(*vi); + + walkup(v); + + if (!walkdown(v)) + return false; + + } + + clean_up_embedding(StoreEmbeddingPolicy()); + + return true; + + } + + + + + + + private: + + + + + + void walkup(vertex_t v) + { + + // The point of the walkup is to follow all backedges from v to + // vertices with higher DFS numbers, and update pertinent_roots + // for the bicomp roots on the path from backedge endpoints up + // to v. This will set the stage for the walkdown to efficiently + // traverse the graph of bicomps down from v. + + typedef typename face_vertex_iterator::type walkup_iterator_t; + + out_edge_iterator_t oi, oi_end; + for(tie(oi,oi_end) = out_edges(v,g); oi != oi_end; ++oi) + { + edge_t e(*oi); + vertex_t e_source(source(e,g)); + vertex_t e_target(target(e,g)); + + if (e_source == e_target) + { + self_loops.push_back(e); + continue; + } + + vertex_t w(e_source == v ? e_target : e_source); + + //continue if not a back edge or already embedded + if (dfs_number[w] < dfs_number[v] || e == dfs_parent_edge[w]) + continue; + + backedges[w].push_back(e); + + v_size_t timestamp = dfs_number[v]; + backedge_flag[w] = timestamp; + + walkup_iterator_t walkup_itr(w, face_handles); + walkup_iterator_t walkup_end; + vertex_t lead_vertex = w; + + while (true) + { + + // Move to the root of the current bicomp or the first visited + // vertex on the bicomp by going up each side in parallel + + while(walkup_itr != walkup_end && + visited[*walkup_itr] != timestamp + ) + { + lead_vertex = *walkup_itr; + visited[lead_vertex] = timestamp; + ++walkup_itr; + } + + // If we've found the root of a bicomp through a path we haven't + // seen before, update pertinent_roots with a handle to the + // current bicomp. Otherwise, we've just seen a path we've been + // up before, so break out of the main while loop. + + if (walkup_itr == walkup_end) + { + vertex_t dfs_child = canonical_dfs_child[lead_vertex]; + vertex_t parent = dfs_parent[dfs_child]; + + visited[dfs_child_handles[dfs_child].first_vertex()] + = timestamp; + visited[dfs_child_handles[dfs_child].second_vertex()] + = timestamp; + + if (low_point[dfs_child] < dfs_number[v] || + least_ancestor[dfs_child] < dfs_number[v] + ) + { + pertinent_roots[parent]->push_back + (dfs_child_handles[dfs_child]); + } + else + { + pertinent_roots[parent]->push_front + (dfs_child_handles[dfs_child]); + } + + if (parent != v && visited[parent] != timestamp) + { + walkup_itr = walkup_iterator_t(parent, face_handles); + lead_vertex = parent; + } + else + break; + } + else + break; + } + + } + + } + + + + + + + + bool walkdown(vertex_t v) + { + // This procedure is where all of the action is - pertinent_roots + // has already been set up by the walkup, so we just need to move + // down bicomps from v until we find vertices that have been + // labeled as backedge endpoints. Once we find such a vertex, we + // embed the corresponding edge and glue together the bicomps on + // the path connecting the two vertices in the edge. This may + // involve flipping bicomps along the way. + + vertex_t w; //the other endpoint of the edge we're embedding + + while (!pertinent_roots[v]->empty()) + { + + face_handle_t root_face_handle = pertinent_roots[v]->front(); + face_handle_t curr_face_handle = root_face_handle; + pertinent_roots[v]->pop_front(); + + merge_stack.clear(); + + while(true) + { + + typename face_vertex_iterator<>::type + first_face_itr, second_face_itr, face_end; + vertex_t first_side_vertex + = graph_traits::null_vertex(); + vertex_t second_side_vertex; + vertex_t first_tail, second_tail; + + first_tail = second_tail = curr_face_handle.get_anchor(); + first_face_itr = typename face_vertex_iterator<>::type + (curr_face_handle, face_handles, first_side()); + second_face_itr = typename face_vertex_iterator<>::type + (curr_face_handle, face_handles, second_side()); + + for(; first_face_itr != face_end; ++first_face_itr) + { + vertex_t face_vertex(*first_face_itr); + if (pertinent(face_vertex, v) || + externally_active(face_vertex, v) + ) + { + first_side_vertex = face_vertex; + second_side_vertex = face_vertex; + break; + } + first_tail = face_vertex; + } + + if (first_side_vertex == graph_traits::null_vertex() || + first_side_vertex == curr_face_handle.get_anchor() + ) + break; + + for(;second_face_itr != face_end; ++second_face_itr) + { + vertex_t face_vertex(*second_face_itr); + if (pertinent(face_vertex, v) || + externally_active(face_vertex, v) + ) + { + second_side_vertex = face_vertex; + break; + } + second_tail = face_vertex; + } + + vertex_t chosen; + bool chose_first_upper_path; + if (internally_active(first_side_vertex, v)) + { + chosen = first_side_vertex; + chose_first_upper_path = true; + } + else if (internally_active(second_side_vertex, v)) + { + chosen = second_side_vertex; + chose_first_upper_path = false; + } + else if (pertinent(first_side_vertex, v)) + { + chosen = first_side_vertex; + chose_first_upper_path = true; + } + else if (pertinent(second_side_vertex, v)) + { + chosen = second_side_vertex; + chose_first_upper_path = false; + } + else + { + + // If there's a pertinent vertex on the lower face + // between the first_face_itr and the second_face_itr, + // this graph isn't planar. + for(; + *first_face_itr != second_side_vertex; + ++first_face_itr + ) + { + vertex_t p(*first_face_itr); + if (pertinent(p,v)) + { + //Found a Kuratowski subgraph + kuratowski_v = v; + kuratowski_x = first_side_vertex; + kuratowski_y = second_side_vertex; + return false; + } + } + + // Otherwise, the fact that we didn't find a pertinent + // vertex on this face is fine - we should set the + // short-circuit edges and break out of this loop to + // start looking at a different pertinent root. + + if (first_side_vertex == second_side_vertex) + { + if (first_tail != v) + { + vertex_t first + = face_handles[first_tail].first_vertex(); + vertex_t second + = face_handles[first_tail].second_vertex(); + tie(first_side_vertex, first_tail) + = make_tuple(first_tail, + first == first_side_vertex ? + second : first + ); + } + else if (second_tail != v) + { + vertex_t first + = face_handles[second_tail].first_vertex(); + vertex_t second + = face_handles[second_tail].second_vertex(); + tie(second_side_vertex, second_tail) + = make_tuple(second_tail, + first == second_side_vertex ? + second : first); + } + else + break; + } + + canonical_dfs_child[first_side_vertex] + = canonical_dfs_child[root_face_handle.first_vertex()]; + canonical_dfs_child[second_side_vertex] + = canonical_dfs_child[root_face_handle.second_vertex()]; + root_face_handle.set_first_vertex(first_side_vertex); + root_face_handle.set_second_vertex(second_side_vertex); + + if (face_handles[first_side_vertex].first_vertex() == + first_tail + ) + face_handles[first_side_vertex].set_first_vertex(v); + else + face_handles[first_side_vertex].set_second_vertex(v); + + if (face_handles[second_side_vertex].first_vertex() == + second_tail + ) + face_handles[second_side_vertex].set_first_vertex(v); + else + face_handles[second_side_vertex].set_second_vertex(v); + + break; + + } + + + // When we unwind the stack, we need to know which direction + // we came down from on the top face handle + + bool chose_first_lower_path = + (chose_first_upper_path && + face_handles[chosen].first_vertex() == first_tail) + || + (!chose_first_upper_path && + face_handles[chosen].first_vertex() == second_tail); + + //If there's a backedge at the chosen vertex, embed it now + if (backedge_flag[chosen] == dfs_number[v]) + { + w = chosen; + + backedge_flag[chosen] = num_vertices(g) + 1; + add_to_merge_points(chosen, StoreOldHandlesPolicy()); + + typename edge_vector_t::iterator ei, ei_end; + ei_end = backedges[chosen].end(); + for(ei = backedges[chosen].begin(); ei != ei_end; ++ei) + { + edge_t e(*ei); + add_to_embedded_edges(e, StoreOldHandlesPolicy()); + + if (chose_first_lower_path) + face_handles[chosen].push_first(e, g); + else + face_handles[chosen].push_second(e, g); + } + + } + else + { + merge_stack.push_back(make_tuple + (chosen, chose_first_upper_path, chose_first_lower_path) + ); + curr_face_handle = *pertinent_roots[chosen]->begin(); + continue; + } + + //Unwind the merge stack to the root, merging all bicomps + + bool bottom_path_follows_first; + bool top_path_follows_first; + bool next_bottom_follows_first = chose_first_upper_path; + face_handle_t top_handle, bottom_handle; + + vertex_t merge_point = chosen; + + while(!merge_stack.empty()) + { + + bottom_path_follows_first = next_bottom_follows_first; + tie(merge_point, + next_bottom_follows_first, + top_path_follows_first + ) = merge_stack.back(); + merge_stack.pop_back(); + + face_handle_t top_handle(face_handles[merge_point]); + face_handle_t bottom_handle + (*pertinent_roots[merge_point]->begin()); + + vertex_t bottom_dfs_child = canonical_dfs_child + [pertinent_roots[merge_point]->begin()->first_vertex()]; + + remove_vertex_from_separated_dfs_child_list( + canonical_dfs_child + [pertinent_roots[merge_point]->begin()->first_vertex()] + ); + + pertinent_roots[merge_point]->pop_front(); + + add_to_merge_points(top_handle.get_anchor(), + StoreOldHandlesPolicy() + ); + + if (top_path_follows_first && bottom_path_follows_first) + { + bottom_handle.flip(); + top_handle.glue_first_to_second(bottom_handle); + } + else if (!top_path_follows_first && + bottom_path_follows_first + ) + { + flipped[bottom_dfs_child] = true; + top_handle.glue_second_to_first(bottom_handle); + } + else if (top_path_follows_first && + !bottom_path_follows_first + ) + { + flipped[bottom_dfs_child] = true; + top_handle.glue_first_to_second(bottom_handle); + } + else //!top_path_follows_first && !bottom_path_follows_first + { + bottom_handle.flip(); + top_handle.glue_second_to_first(bottom_handle); + } + + } + + //Finally, embed all edges (v,w) at their upper end points + canonical_dfs_child[w] + = canonical_dfs_child[root_face_handle.first_vertex()]; + + add_to_merge_points(root_face_handle.get_anchor(), + StoreOldHandlesPolicy() + ); + + typename edge_vector_t::iterator ei, ei_end; + ei_end = backedges[chosen].end(); + for(ei = backedges[chosen].begin(); ei != ei_end; ++ei) + { + if (next_bottom_follows_first) + root_face_handle.push_first(*ei, g); + else + root_face_handle.push_second(*ei, g); + } + + backedges[chosen].clear(); + curr_face_handle = root_face_handle; + + }//while(true) + + }//while(!pertinent_roots[v]->empty()) + + return true; + + } + + + + + + + void store_old_face_handles(graph::detail::no_old_handles) {} + + void store_old_face_handles(graph::detail::store_old_handles) + { + for(typename std::vector::iterator mp_itr + = current_merge_points.begin(); + mp_itr != current_merge_points.end(); ++mp_itr) + { + face_handles[*mp_itr].store_old_face_handles(); + } + current_merge_points.clear(); + } + + + void add_to_merge_points(vertex_t v, graph::detail::no_old_handles) {} + + void add_to_merge_points(vertex_t v, graph::detail::store_old_handles) + { + current_merge_points.push_back(v); + } + + + void add_to_embedded_edges(edge_t e, graph::detail::no_old_handles) {} + + void add_to_embedded_edges(edge_t e, graph::detail::store_old_handles) + { + embedded_edges.push_back(e); + } + + + + + void clean_up_embedding(graph::detail::no_embedding) {} + + void clean_up_embedding(graph::detail::store_embedding) + { + + // If the graph isn't biconnected, we'll still have entries + // in the separated_dfs_child_list for some vertices. Since + // these represent articulation points, we can obtain a + // planar embedding no matter what order we embed them in. + + vertex_iterator_t xi, xi_end; + for(tie(xi,xi_end) = vertices(g); xi != xi_end; ++xi) + { + if (!separated_dfs_child_list[*xi]->empty()) + { + typename vertex_list_t::iterator yi, yi_end; + yi_end = separated_dfs_child_list[*xi]->end(); + for(yi = separated_dfs_child_list[*xi]->begin(); + yi != yi_end; ++yi + ) + { + dfs_child_handles[*yi].flip(); + face_handles[*xi].glue_first_to_second + (dfs_child_handles[*yi]); + } + } + } + + // Up until this point, we've flipped bicomps lazily by setting + // flipped[v] to true if the bicomp rooted at v was flipped (the + // lazy aspect of this flip is that all descendents of that vertex + // need to have their orientations reversed as well). Now, we + // traverse the DFS tree by DFS number and perform the actual + // flipping as needed + + typedef typename vertex_vector_t::iterator vertex_vector_itr_t; + vertex_vector_itr_t vi_end = vertices_by_dfs_num.end(); + for(vertex_vector_itr_t vi = vertices_by_dfs_num.begin(); + vi != vi_end; ++vi + ) + { + vertex_t v(*vi); + bool v_flipped = flipped[v]; + bool p_flipped = flipped[dfs_parent[v]]; + if (v_flipped && !p_flipped) + { + face_handles[v].flip(); + } + else if (p_flipped && !v_flipped) + { + face_handles[v].flip(); + flipped[v] = true; + } + else + { + flipped[v] = false; + } + } + + // If there are any self-loops in the graph, they were flagged + // during the walkup, and we should add them to the embedding now. + // Adding a self loop anywhere in the embedding could never + // invalidate the embedding, but they would complicate the traversal + // if they were added during the walkup/walkdown. + + typename edge_vector_t::iterator ei, ei_end; + ei_end = self_loops.end(); + for(ei = self_loops.begin(); ei != ei_end; ++ei) + { + edge_t e(*ei); + face_handles[source(e,g)].push_second(e,g); + } + + } + + + + + + bool pertinent(vertex_t w, vertex_t v) + { + // w is pertinent with respect to v if there is a backedge (v,w) or if + // w is the root of a bicomp that contains a pertinent vertex. + + return backedge_flag[w] == dfs_number[v] || !pertinent_roots[w]->empty(); + } + + + + bool externally_active(vertex_t w, vertex_t v) + { + // Let a be any proper depth-first search ancestor of v. w is externally + // active with respect to v if there exists a backedge (a,w) or a + // backedge (a,w_0) for some w_0 in a descendent bicomp of w. + + v_size_t dfs_number_of_v = dfs_number[v]; + return (least_ancestor[w] < dfs_number_of_v) || + (!separated_dfs_child_list[w]->empty() && + low_point[separated_dfs_child_list[w]->front()] < dfs_number_of_v); + } + + + + bool internally_active(vertex_t w, vertex_t v) + { + return pertinent(w,v) && !externally_active(w,v); + } + + + + + void remove_vertex_from_separated_dfs_child_list(vertex_t v) + { + typename vertex_list_t::iterator to_delete + = separated_node_in_parent_list[v]; + garbage.splice(garbage.end(), + *separated_dfs_child_list[dfs_parent[v]], + to_delete, + next(to_delete) + ); + } + + + + + + // End of the implementation of the basic Boyer-Myrvold Algorithm. The rest + // of the code below implements the isolation of a Kuratowski subgraph in + // the case that the input graph is not planar. This is by far the most + // complicated part of the implementation. + + + + + public: + + + + + template + vertex_t kuratowski_walkup(vertex_t v, + EdgeToBoolPropertyMap forbidden_edge, + EdgeToBoolPropertyMap goal_edge, + EdgeToBoolPropertyMap is_embedded, + EdgeContainer& path_edges + ) + { + vertex_t current_endpoint; + bool seen_goal_edge = false; + out_edge_iterator_t oi, oi_end; + + for(tie(oi,oi_end) = out_edges(v,g); oi != oi_end; ++oi) + forbidden_edge[*oi] = true; + + for(tie(oi,oi_end) = out_edges(v,g); oi != oi_end; ++oi) + { + path_edges.clear(); + + edge_t e(*oi); + current_endpoint = target(*oi,g) == v ? + source(*oi,g) : target(*oi,g); + + if (dfs_number[current_endpoint] < dfs_number[v] || + is_embedded[e] || + v == current_endpoint //self-loop + ) + { + //Not a backedge + continue; + } + + path_edges.push_back(e); + if (goal_edge[e]) + { + return current_endpoint; + } + + typedef typename face_edge_iterator<>::type walkup_itr_t; + + walkup_itr_t + walkup_itr(current_endpoint, face_handles, first_side()); + walkup_itr_t walkup_end; + + seen_goal_edge = false; + + while (true) + { + + if (walkup_itr != walkup_end && forbidden_edge[*walkup_itr]) + break; + + while(walkup_itr != walkup_end && + !goal_edge[*walkup_itr] && + !forbidden_edge[*walkup_itr] + ) + { + edge_t f(*walkup_itr); + forbidden_edge[f] = true; + path_edges.push_back(f); + current_endpoint = + source(f, g) == current_endpoint ? + target(f, g) : + source(f,g); + ++walkup_itr; + } + + if (walkup_itr != walkup_end && goal_edge[*walkup_itr]) + { + path_edges.push_back(*walkup_itr); + seen_goal_edge = true; + break; + } + + walkup_itr + = walkup_itr_t(current_endpoint, face_handles, first_side()); + + } + + if (seen_goal_edge) + break; + + } + + if (seen_goal_edge) + return current_endpoint; + else + return graph_traits::null_vertex(); + + } + + + + + + + + + template + void extract_kuratowski_subgraph(OutputIterator o_itr, EdgeIndexMap em) + { + + // If the main algorithm has failed to embed one of the back-edges from + // a vertex v, we can use the current state of the algorithm to isolate + // a Kuratowksi subgraph. The isolation process breaks down into five + // cases, A - E. The general configuration of all five cases is shown in + // figure 1. There is a vertex v from which the planar + // v embedding process could not proceed. This means that + // | there exists some bicomp containing three vertices + // ----- x,y, and z as shown such that x and y are externally + // | | active with respect to v (which means that there are + // x y two vertices x_0 and y_0 such that (1) both x_0 and + // | | y_0 are proper depth-first search ancestors of v and + // --z-- (2) there are two disjoint paths, one connecting x + // and x_0 and one connecting y and y_0, both consisting + // fig. 1 entirely of unembedded edges). Furthermore, there + // exists a vertex z_0 such that z is a depth-first + // search ancestor of z_0 and (v,z_0) is an unembedded back-edge from v. + // x,y and z all exist on the same bicomp, which consists entirely of + // embedded edges. The five subcases break down as follows, and are + // handled by the algorithm logically in the order A-E: First, if v is + // not on the same bicomp as x,y, and z, a K_3_3 can be isolated - this + // is case A. So, we'll assume that v is on the same bicomp as x,y, and + // z. If z_0 is on a different bicomp than x,y, and z, a K_3_3 can also + // be isolated - this is a case B - so we'll assume from now on that v + // is on the same bicomp as x, y, and z=z_0. In this case, one can use + // properties of the Boyer-Myrvold algorithm to show the existence of an + // "x-y path" connecting some vertex on the "left side" of the x,y,z + // bicomp with some vertex on the "right side" of the bicomp (where the + // left and right are split by a line drawn through v and z.If either of + // the endpoints of the x-y path is above x or y on the bicomp, a K_3_3 + // can be isolated - this is a case C. Otherwise, both endpoints are at + // or below x and y on the bicomp. If there is a vertex alpha on the x-y + // path such that alpha is not x or y and there's a path from alpha to v + // that's disjoint from any of the edges on the bicomp and the x-y path, + // a K_3_3 can be isolated - this is a case D. Otherwise, properties of + // the Boyer-Myrvold algorithm can be used to show that another vertex + // w exists on the lower half of the bicomp such that w is externally + // active with respect to v. w can then be used to isolate a K_5 - this + // is the configuration of case E. + + vertex_iterator_t vi, vi_end; + edge_iterator_t ei, ei_end; + out_edge_iterator_t oei, oei_end; + typename std::vector::iterator xi, xi_end; + + // Clear the short-circuit edges - these are needed for the planar + // testing/embedding algorithm to run in linear time, but they'll + // complicate the kuratowski subgraph isolation + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + { + face_handles[*vi].reset_vertex_cache(); + dfs_child_handles[*vi].reset_vertex_cache(); + } + + vertex_t v = kuratowski_v; + vertex_t x = kuratowski_x; + vertex_t y = kuratowski_y; + + typedef iterator_property_map + ::iterator, EdgeIndexMap> + edge_to_bool_map_t; + + std::vector is_in_subgraph_vector(num_edges(g), false); + edge_to_bool_map_t is_in_subgraph(is_in_subgraph_vector.begin(), em); + + std::vector is_embedded_vector(num_edges(g), false); + edge_to_bool_map_t is_embedded(is_embedded_vector.begin(), em); + + typename std::vector::iterator embedded_itr, embedded_end; + embedded_end = embedded_edges.end(); + for(embedded_itr = embedded_edges.begin(); + embedded_itr != embedded_end; ++embedded_itr + ) + is_embedded[*embedded_itr] = true; + + // upper_face_vertex is true for x,y, and all vertices above x and y in + // the bicomp + std::vector upper_face_vertex_vector(num_vertices(g), false); + vertex_to_bool_map_t upper_face_vertex + (upper_face_vertex_vector.begin(), vm); + + std::vector lower_face_vertex_vector(num_vertices(g), false); + vertex_to_bool_map_t lower_face_vertex + (lower_face_vertex_vector.begin(), vm); + + // These next few variable declarations are all things that we need + // to find. + vertex_t z; + vertex_t bicomp_root; + vertex_t w = graph_traits::null_vertex(); + face_handle_t w_handle; + face_handle_t v_dfchild_handle; + vertex_t first_x_y_path_endpoint = graph_traits::null_vertex(); + vertex_t second_x_y_path_endpoint = graph_traits::null_vertex(); + vertex_t w_ancestor = v; + + enum case_t{NO_CASE_CHOSEN, CASE_A, CASE_B, CASE_C, CASE_D, CASE_E}; + case_t chosen_case = NO_CASE_CHOSEN; + + std::vector x_external_path; + std::vector y_external_path; + std::vector case_d_edges; + + std::vector z_v_path; + std::vector w_path; + + //first, use a walkup to find a path from V that starts with a + //backedge from V, then goes up until it hits either X or Y + //(but doesn't find X or Y as the root of a bicomp) + + typename face_vertex_iterator<>::type + x_upper_itr(x, face_handles, first_side()); + typename face_vertex_iterator<>::type + x_lower_itr(x, face_handles, second_side()); + typename face_vertex_iterator<>::type face_itr, face_end; + + // Don't know which path from x is the upper or lower path - + // we'll find out here + for(face_itr = x_upper_itr; face_itr != face_end; ++face_itr) + { + if (*face_itr == y) + { + std::swap(x_upper_itr, x_lower_itr); + break; + } + } + + upper_face_vertex[x] = true; + + vertex_t current_vertex = x; + vertex_t previous_vertex; + for(face_itr = x_upper_itr; face_itr != face_end; ++face_itr) + { + previous_vertex = current_vertex; + current_vertex = *face_itr; + upper_face_vertex[current_vertex] = true; + } + + v_dfchild_handle + = dfs_child_handles[canonical_dfs_child[previous_vertex]]; + + for(face_itr = x_lower_itr; *face_itr != y; ++face_itr) + { + vertex_t current_vertex(*face_itr); + lower_face_vertex[current_vertex] = true; + + typename face_handle_list_t::iterator roots_itr, roots_end; + + if (w == graph_traits::null_vertex()) //haven't found a w yet + { + roots_end = pertinent_roots[current_vertex]->end(); + for(roots_itr = pertinent_roots[current_vertex]->begin(); + roots_itr != roots_end; ++roots_itr + ) + { + if (low_point[canonical_dfs_child[roots_itr->first_vertex()]] + < dfs_number[v] + ) + { + w = current_vertex; + w_handle = *roots_itr; + break; + } + } + } + + } + + for(; face_itr != face_end; ++face_itr) + { + vertex_t current_vertex(*face_itr); + upper_face_vertex[current_vertex] = true; + bicomp_root = current_vertex; + } + + typedef typename face_edge_iterator<>::type walkup_itr_t; + + std::vector outer_face_edge_vector(num_edges(g), false); + edge_to_bool_map_t outer_face_edge(outer_face_edge_vector.begin(), em); + + walkup_itr_t walkup_end; + for(walkup_itr_t walkup_itr(x, face_handles, first_side()); + walkup_itr != walkup_end; ++walkup_itr + ) + { + outer_face_edge[*walkup_itr] = true; + is_in_subgraph[*walkup_itr] = true; + } + + for(walkup_itr_t walkup_itr(x, face_handles, second_side()); + walkup_itr != walkup_end; ++walkup_itr + ) + { + outer_face_edge[*walkup_itr] = true; + is_in_subgraph[*walkup_itr] = true; + } + + std::vector forbidden_edge_vector(num_edges(g), false); + edge_to_bool_map_t forbidden_edge(forbidden_edge_vector.begin(), em); + + std::vector goal_edge_vector(num_edges(g), false); + edge_to_bool_map_t goal_edge(goal_edge_vector.begin(), em); + + + //Find external path to x and to y + + for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + edge_t e(*ei); + goal_edge[e] + = !outer_face_edge[e] && (source(e,g) == x || target(e,g) == x); + forbidden_edge[*ei] = outer_face_edge[*ei]; + } + + vertex_t x_ancestor = v; + vertex_t x_endpoint = graph_traits::null_vertex(); + + while(x_endpoint == graph_traits::null_vertex()) + { + x_ancestor = dfs_parent[x_ancestor]; + x_endpoint = kuratowski_walkup(x_ancestor, + forbidden_edge, + goal_edge, + is_embedded, + x_external_path + ); + + } + + + for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + edge_t e(*ei); + goal_edge[e] + = !outer_face_edge[e] && (source(e,g) == y || target(e,g) == y); + forbidden_edge[*ei] = outer_face_edge[*ei]; + } + + vertex_t y_ancestor = v; + vertex_t y_endpoint = graph_traits::null_vertex(); + + while(y_endpoint == graph_traits::null_vertex()) + { + y_ancestor = dfs_parent[y_ancestor]; + y_endpoint = kuratowski_walkup(y_ancestor, + forbidden_edge, + goal_edge, + is_embedded, + y_external_path + ); + + } + + + vertex_t parent, child; + + //If v isn't on the same bicomp as x and y, it's a case A + if (bicomp_root != v) + { + chosen_case = CASE_A; + + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + if (lower_face_vertex[*vi]) + for(tie(oei,oei_end) = out_edges(*vi,g); oei != oei_end; ++oei) + if(!outer_face_edge[*oei]) + goal_edge[*oei] = true; + + for(tie(ei,ei_end) = edges(g); ei != ei_end; ++ei) + forbidden_edge[*ei] = outer_face_edge[*ei]; + + z = kuratowski_walkup + (v, forbidden_edge, goal_edge, is_embedded, z_v_path); + + } + else if (w != graph_traits::null_vertex()) + { + chosen_case = CASE_B; + + for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + edge_t e(*ei); + goal_edge[e] = false; + forbidden_edge[e] = outer_face_edge[e]; + } + + goal_edge[w_handle.first_edge()] = true; + goal_edge[w_handle.second_edge()] = true; + + z = kuratowski_walkup(v, + forbidden_edge, + goal_edge, + is_embedded, + z_v_path + ); + + + for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + forbidden_edge[*ei] = outer_face_edge[*ei]; + } + + typename std::vector::iterator pi, pi_end; + pi_end = z_v_path.end(); + for(pi = z_v_path.begin(); pi != pi_end; ++pi) + { + goal_edge[*pi] = true; + } + + w_ancestor = v; + vertex_t w_endpoint = graph_traits::null_vertex(); + + while(w_endpoint == graph_traits::null_vertex()) + { + w_ancestor = dfs_parent[w_ancestor]; + w_endpoint = kuratowski_walkup(w_ancestor, + forbidden_edge, + goal_edge, + is_embedded, + w_path + ); + + } + + // We really want both the w walkup and the z walkup to finish on + // exactly the same edge, but for convenience (since we don't have + // control over which side of a bicomp a walkup moves up) we've + // defined the walkup to either end at w_handle.first_edge() or + // w_handle.second_edge(). If both walkups ended at different edges, + // we'll do a little surgery on the w walkup path to make it follow + // the other side of the final bicomp. + + if ((w_path.back() == w_handle.first_edge() && + z_v_path.back() == w_handle.second_edge()) + || + (w_path.back() == w_handle.second_edge() && + z_v_path.back() == w_handle.first_edge()) + ) + { + walkup_itr_t wi, wi_end; + edge_t final_edge = w_path.back(); + vertex_t anchor + = source(final_edge, g) == w_handle.get_anchor() ? + target(final_edge, g) : source(final_edge, g); + if (face_handles[anchor].first_edge() == final_edge) + wi = walkup_itr_t(anchor, face_handles, second_side()); + else + wi = walkup_itr_t(anchor, face_handles, first_side()); + + w_path.pop_back(); + + for(; wi != wi_end; ++wi) + { + edge_t e(*wi); + if (w_path.back() == e) + w_path.pop_back(); + else + w_path.push_back(e); + } + } + + + } + else + { + + //We need to find a valid z, since the x-y path re-defines the lower + //face, and the z we found earlier may now be on the upper face. + + chosen_case = CASE_E; + + + // The z we've used so far is just an externally active vertex on the + // lower face path, but may not be the z we need for a case C, D, or + // E subgraph. the z we need now is any externally active vertex on + // the lower face path with both old_face_handles edges on the outer + // face. Since we know an x-y path exists, such a z must also exist. + + //TODO: find this z in the first place. + + //find the new z + + for(face_itr = x_lower_itr; *face_itr != y; ++face_itr) + { + vertex_t possible_z(*face_itr); + if (pertinent(possible_z,v) && + outer_face_edge[face_handles[possible_z].old_first_edge()] && + outer_face_edge[face_handles[possible_z].old_second_edge()] + ) + { + z = possible_z; + break; + } + } + + //find x-y path, and a w if one exists. + + if (externally_active(z,v)) + w = z; + + + typedef typename face_edge_iterator + ::type old_face_iterator_t; + + old_face_iterator_t + first_old_face_itr(z, face_handles, first_side()); + old_face_iterator_t + second_old_face_itr(z, face_handles, second_side()); + old_face_iterator_t old_face_itr, old_face_end; + + std::vector old_face_iterators; + old_face_iterators.push_back(first_old_face_itr); + old_face_iterators.push_back(second_old_face_itr); + + std::vector x_y_path_vertex_vector(num_vertices(g), false); + vertex_to_bool_map_t x_y_path_vertex + (x_y_path_vertex_vector.begin(), vm); + + typename std::vector::iterator + of_itr, of_itr_end; + of_itr_end = old_face_iterators.end(); + for(of_itr = old_face_iterators.begin(); + of_itr != of_itr_end; ++of_itr + ) + { + + old_face_itr = *of_itr; + + vertex_t previous_vertex; + bool seen_x_or_y = false; + vertex_t current_vertex = z; + for(; old_face_itr != old_face_end; ++old_face_itr) + { + edge_t e(*old_face_itr); + previous_vertex = current_vertex; + current_vertex = source(e,g) == current_vertex ? + target(e,g) : source(e,g); + + if (current_vertex == x || current_vertex == y) + seen_x_or_y = true; + + if (w == graph_traits::null_vertex() && + externally_active(current_vertex,v) && + outer_face_edge[e] && + outer_face_edge[*next(old_face_itr)] && + !seen_x_or_y + ) + { + w = current_vertex; + } + + if (!outer_face_edge[e]) + { + if (!upper_face_vertex[current_vertex] && + !lower_face_vertex[current_vertex] + ) + { + x_y_path_vertex[current_vertex] = true; + } + + is_in_subgraph[e] = true; + if (upper_face_vertex[source(e,g)] || + lower_face_vertex[source(e,g)] + ) + { + if (first_x_y_path_endpoint == + graph_traits::null_vertex() + ) + first_x_y_path_endpoint = source(e,g); + else + second_x_y_path_endpoint = source(e,g); + } + if (upper_face_vertex[target(e,g)] || + lower_face_vertex[target(e,g)] + ) + { + if (first_x_y_path_endpoint == + graph_traits::null_vertex() + ) + first_x_y_path_endpoint = target(e,g); + else + second_x_y_path_endpoint = target(e,g); + } + + + } + else if (previous_vertex == x || previous_vertex == y) + { + chosen_case = CASE_C; + } + + } + + } + + // Look for a case D - one of v's embedded edges will connect to the + // x-y path along an inner face path. + + //First, get a list of all of v's embedded child edges + + out_edge_iterator_t v_edge_itr, v_edge_end; + for(tie(v_edge_itr,v_edge_end) = out_edges(v,g); + v_edge_itr != v_edge_end; ++v_edge_itr + ) + { + edge_t embedded_edge(*v_edge_itr); + + if (!is_embedded[embedded_edge] || + embedded_edge == dfs_parent_edge[v] + ) + continue; + + case_d_edges.push_back(embedded_edge); + + vertex_t current_vertex + = source(embedded_edge,g) == v ? + target(embedded_edge,g) : source(embedded_edge,g); + + typename face_edge_iterator<>::type + internal_face_itr, internal_face_end; + if (face_handles[current_vertex].first_vertex() == v) + { + internal_face_itr = typename face_edge_iterator<>::type + (current_vertex, face_handles, second_side()); + } + else + { + internal_face_itr = typename face_edge_iterator<>::type + (current_vertex, face_handles, first_side()); + } + + while(internal_face_itr != internal_face_end && + !outer_face_edge[*internal_face_itr] && + !x_y_path_vertex[current_vertex] + ) + { + edge_t e(*internal_face_itr); + case_d_edges.push_back(e); + current_vertex = + source(e,g) == current_vertex ? target(e,g) : source(e,g); + ++internal_face_itr; + } + + if (x_y_path_vertex[current_vertex]) + { + chosen_case = CASE_D; + break; + } + else + { + case_d_edges.clear(); + } + + } + + + } + + + + + if (chosen_case != CASE_B && chosen_case != CASE_A) + { + + //Finding z and w. + + for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + edge_t e(*ei); + goal_edge[e] = !outer_face_edge[e] && + (source(e,g) == z || target(e,g) == z); + forbidden_edge[e] = outer_face_edge[e]; + } + + kuratowski_walkup(v, + forbidden_edge, + goal_edge, + is_embedded, + z_v_path + ); + + if (chosen_case == CASE_E) + { + + for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + forbidden_edge[*ei] = outer_face_edge[*ei]; + goal_edge[*ei] = !outer_face_edge[*ei] && + (source(*ei,g) == w || target(*ei,g) == w); + } + + for(tie(oei, oei_end) = out_edges(w,g); oei != oei_end; ++oei) + { + if (!outer_face_edge[*oei]) + goal_edge[*oei] = true; + } + + typename std::vector::iterator pi, pi_end; + pi_end = z_v_path.end(); + for(pi = z_v_path.begin(); pi != pi_end; ++pi) + { + goal_edge[*pi] = true; + } + + w_ancestor = v; + vertex_t w_endpoint = graph_traits::null_vertex(); + + while(w_endpoint == graph_traits::null_vertex()) + { + w_ancestor = dfs_parent[w_ancestor]; + w_endpoint = kuratowski_walkup(w_ancestor, + forbidden_edge, + goal_edge, + is_embedded, + w_path + ); + + } + + } + + + } + + + //We're done isolating the Kuratowski subgraph at this point - + //but there's still some cleaning up to do. + + //Update is_in_subgraph with the paths we just found + + xi_end = x_external_path.end(); + for(xi = x_external_path.begin(); xi != xi_end; ++xi) + is_in_subgraph[*xi] = true; + + xi_end = y_external_path.end(); + for(xi = y_external_path.begin(); xi != xi_end; ++xi) + is_in_subgraph[*xi] = true; + + xi_end = z_v_path.end(); + for(xi = z_v_path.begin(); xi != xi_end; ++xi) + is_in_subgraph[*xi] = true; + + xi_end = case_d_edges.end(); + for(xi = case_d_edges.begin(); xi != xi_end; ++xi) + is_in_subgraph[*xi] = true; + + xi_end = w_path.end(); + for(xi = w_path.begin(); xi != xi_end; ++xi) + is_in_subgraph[*xi] = true; + + child = bicomp_root; + parent = dfs_parent[child]; + while(child != parent) + { + is_in_subgraph[dfs_parent_edge[child]] = true; + tie(parent, child) = std::make_pair( dfs_parent[parent], parent ); + } + + + + + // At this point, we've already isolated the Kuratowski subgraph and + // collected all of the edges that compose it in the is_in_subgraph + // property map. But we want the verification of such a subgraph to be + // a deterministic process, and we can simplify the function + // is_kuratowski_subgraph by cleaning up some edges here. + + if (chosen_case == CASE_B) + { + is_in_subgraph[dfs_parent_edge[v]] = false; + } + else if (chosen_case == CASE_C) + { + // In a case C subgraph, at least one of the x-y path endpoints + // (call it alpha) is above either x or y on the outer face. The + // other endpoint may be attached at x or y OR above OR below. In + // any of these three cases, we can form a K_3_3 by removing the + // edge attached to v on the outer face that is NOT on the path to + // alpha. + + typename face_vertex_iterator::type + face_itr, face_end; + if (face_handles[v_dfchild_handle.first_vertex()].first_edge() == + v_dfchild_handle.first_edge() + ) + { + face_itr = typename face_vertex_iterator + ::type + (v_dfchild_handle.first_vertex(), face_handles, second_side()); + } + else + { + face_itr = typename face_vertex_iterator + ::type + (v_dfchild_handle.first_vertex(), face_handles, first_side()); + } + + for(; true; ++face_itr) + { + vertex_t current_vertex(*face_itr); + if (current_vertex == x || current_vertex == y) + { + is_in_subgraph[v_dfchild_handle.first_edge()] = false; + break; + } + else if (current_vertex == first_x_y_path_endpoint || + current_vertex == second_x_y_path_endpoint) + { + is_in_subgraph[v_dfchild_handle.second_edge()] = false; + break; + } + } + + } + else if (chosen_case == CASE_D) + { + // Need to remove both of the edges adjacent to v on the outer face. + // remove the connecting edges from v to bicomp, then + // is_kuratowski_subgraph will shrink vertices of degree 1 + // automatically... + + is_in_subgraph[v_dfchild_handle.first_edge()] = false; + is_in_subgraph[v_dfchild_handle.second_edge()] = false; + + } + else if (chosen_case == CASE_E) + { + // Similarly to case C, if the endpoints of the x-y path are both + // below x and y, we should remove an edge to allow the subgraph to + // contract to a K_3_3. + + + if ((first_x_y_path_endpoint != x && first_x_y_path_endpoint != y) || + (second_x_y_path_endpoint != x && second_x_y_path_endpoint != y) + ) + { + is_in_subgraph[dfs_parent_edge[v]] = false; + + vertex_t deletion_endpoint, other_endpoint; + if (lower_face_vertex[first_x_y_path_endpoint]) + { + deletion_endpoint = second_x_y_path_endpoint; + other_endpoint = first_x_y_path_endpoint; + } + else + { + deletion_endpoint = first_x_y_path_endpoint; + other_endpoint = second_x_y_path_endpoint; + } + + typename face_edge_iterator<>::type face_itr, face_end; + + bool found_other_endpoint = false; + for(face_itr = typename face_edge_iterator<>::type + (deletion_endpoint, face_handles, first_side()); + face_itr != face_end; ++face_itr + ) + { + edge_t e(*face_itr); + if (source(e,g) == other_endpoint || + target(e,g) == other_endpoint + ) + { + found_other_endpoint = true; + break; + } + } + + if (found_other_endpoint) + { + is_in_subgraph[face_handles[deletion_endpoint].first_edge()] + = false; + } + else + { + is_in_subgraph[face_handles[deletion_endpoint].second_edge()] + = false; + } + } + + } + + + for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + if (is_in_subgraph[*ei]) + *o_itr = *ei; + + } + + + + template + void make_edge_permutation(EdgePermutation perm) + { + vertex_iterator_t vi, vi_end; + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_t v(*vi); + perm[v].clear(); + face_handles[v].get_list(std::back_inserter(perm[v])); + } + } + + + private: + + const Graph& g; + VertexIndexMap vm; + + vertex_t kuratowski_v; + vertex_t kuratowski_x; + vertex_t kuratowski_y; + + vertex_list_t garbage; // we delete items from linked lists by + // splicing them into garbage + + //only need these two for kuratowski subgraph isolation + std::vector current_merge_points; + std::vector embedded_edges; + + //property map storage + std::vector low_point_vector; + std::vector dfs_parent_vector; + std::vector dfs_number_vector; + std::vector least_ancestor_vector; + std::vector pertinent_roots_vector; + std::vector backedge_flag_vector; + std::vector visited_vector; + std::vector< face_handle_t > face_handles_vector; + std::vector< face_handle_t > dfs_child_handles_vector; + std::vector< vertex_list_ptr_t > separated_dfs_child_list_vector; + std::vector< typename vertex_list_t::iterator > + separated_node_in_parent_list_vector; + std::vector canonical_dfs_child_vector; + std::vector flipped_vector; + std::vector backedges_vector; + edge_vector_t self_loops; + std::vector dfs_parent_edge_vector; + vertex_vector_t vertices_by_dfs_num; + + //property maps + vertex_to_v_size_map_t low_point; + vertex_to_vertex_map_t dfs_parent; + vertex_to_v_size_map_t dfs_number; + vertex_to_v_size_map_t least_ancestor; + vertex_to_face_handle_list_ptr_map_t pertinent_roots; + vertex_to_v_size_map_t backedge_flag; + vertex_to_v_size_map_t visited; + vertex_to_face_handle_map_t face_handles; + vertex_to_face_handle_map_t dfs_child_handles; + vertex_to_vertex_list_ptr_map_t separated_dfs_child_list; + vertex_to_separated_node_map_t separated_node_in_parent_list; + vertex_to_vertex_map_t canonical_dfs_child; + vertex_to_bool_map_t flipped; + vertex_to_edge_vector_map_t backedges; + vertex_to_edge_map_t dfs_parent_edge; //only need for kuratowski + + merge_stack_t merge_stack; + + }; + + +} //namespace boost + +#endif //__BOYER_MYRVOLD_IMPL_HPP__ diff --git a/win32/include/boost/graph/planar_detail/bucket_sort.hpp b/win32/include/boost/graph/planar_detail/bucket_sort.hpp new file mode 100755 index 000000000..f656ccb1e --- /dev/null +++ b/win32/include/boost/graph/planar_detail/bucket_sort.hpp @@ -0,0 +1,144 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __BUCKET_SORT_HPP__ +#define __BUCKET_SORT_HPP__ + +#include +#include +#include + + + +namespace boost +{ + + + template + struct rank_comparison + { + rank_comparison(ItemToRankMap arg_itrm) : itrm(arg_itrm) {} + + template + bool operator() (Item x, Item y) const + { + return get(itrm, x) < get(itrm, y); + } + + private: + ItemToRankMap itrm; + + }; + + + template + struct property_map_tuple_adaptor : + public put_get_helper< typename PropertyMapWrapper::value_type, + property_map_tuple_adaptor + + > + { + typedef typename PropertyMapWrapper::reference reference; + typedef typename PropertyMapWrapper::value_type value_type; + typedef TupleType key_type; + typedef readable_property_map_tag category; + + property_map_tuple_adaptor() {} + + property_map_tuple_adaptor(PropertyMapWrapper wrapper_map) : + m_wrapper_map(wrapper_map) + {} + + inline value_type operator[](const key_type& x) const + { + return get(m_wrapper_map, get(x)); + } + + static const int n = N; + PropertyMapWrapper m_wrapper_map; + + }; + + + + + // This function sorts a sequence of n items by their ranks in linear time, + // given that all ranks are in the range [0, range). This sort is stable. + template + void bucket_sort(ForwardIterator begin, + ForwardIterator end, + ItemToRankMap rank, + SizeType range = 0) + { +#ifdef BOOST_GRAPH_PREFER_STD_LIB + std::stable_sort(begin, end, rank_comparison(rank)); +#else + typedef std::vector + < typename boost::property_traits::key_type > + vector_of_values_t; + typedef std::vector< vector_of_values_t > vector_of_vectors_t; + + if (!range) + { + rank_comparison cmp(rank); + ForwardIterator max_by_rank = std::max_element(begin, end, cmp); + if (max_by_rank == end) + return; + range = get(rank, *max_by_rank) + 1; + } + + vector_of_vectors_t temp_values(range); + + for(ForwardIterator itr = begin; itr != end; ++itr) + { + temp_values[get(rank, *itr)].push_back(*itr); + } + + ForwardIterator orig_seq_itr = begin; + typename vector_of_vectors_t::iterator itr_end = temp_values.end(); + for(typename vector_of_vectors_t::iterator itr = temp_values.begin(); + itr != itr_end; ++itr + ) + { + typename vector_of_values_t::iterator jtr_end = itr->end(); + for(typename vector_of_values_t::iterator jtr = itr->begin(); + jtr != jtr_end; ++jtr + ) + { + *orig_seq_itr = *jtr; + ++orig_seq_itr; + } + } +#endif + } + + + template + void bucket_sort(ForwardIterator begin, + ForwardIterator end, + ItemToRankMap rank) + { + bucket_sort(begin, end, rank, 0); + } + + template + void bucket_sort(ForwardIterator begin, + ForwardIterator end + ) + { + bucket_sort(begin, end, identity_property_map()); + } + + +} //namespace boost + + +#endif //__BUCKET_SORT_HPP__ diff --git a/win32/include/boost/graph/planar_detail/face_handles.hpp b/win32/include/boost/graph/planar_detail/face_handles.hpp new file mode 100755 index 000000000..81c8cce74 --- /dev/null +++ b/win32/include/boost/graph/planar_detail/face_handles.hpp @@ -0,0 +1,497 @@ +//======================================================================= +// Copyright (c) Aaron Windsor 2007 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef __FACE_HANDLES_HPP__ +#define __FACE_HANDLES_HPP__ + + +#include +#include +#include + + +// A "face handle" is an optimization meant to serve two purposes in +// the implementation of the Boyer-Myrvold planarity test: (1) it holds +// the partial planar embedding of a particular vertex as it's being +// constructed, and (2) it allows for efficient traversal around the +// outer face of the partial embedding at that particular vertex. A face +// handle is lightweight, just a shared pointer to the actual implementation, +// since it is passed around/copied liberally in the algorithm. It consists +// of an "anchor" (the actual vertex it's associated with) as well as a +// sequence of edges. The functions first_vertex/second_vertex and +// first_edge/second_edge allow fast access to the beginning and end of the +// stored sequence, which allows one to traverse the outer face of the partial +// planar embedding as it's being created. +// +// There are some policies below that define the contents of the face handles: +// in the case no embedding is needed (for example, if one just wants to use +// the Boyer-Myrvold algorithm as a true/false test for planarity, the +// no_embedding class can be passed as the StoreEmbedding policy. Otherwise, +// either std_list (which uses as std::list) or recursive_lazy_list can be +// passed as this policy. recursive_lazy_list has the best theoretical +// performance (O(n) for a sequence of interleaved concatenations and reversals +// of the underlying list), but I've noticed little difference between std_list +// and recursive_lazy_list in my tests, even though using std_list changes +// the worst-case complexity of the planarity test to O(n^2) +// +// Another policy is StoreOldHandlesPolicy, which specifies whether or not +// to keep a record of the previous first/second vertex/edge - this is needed +// if a Kuratowski subgraph needs to be isolated. + + +namespace boost { namespace graph { namespace detail { + + + //face handle policies + + //EmbeddingStorage policy + struct store_embedding {}; + struct recursive_lazy_list : public store_embedding {}; + struct std_list : public store_embedding {}; + struct no_embedding {}; + + //StoreOldHandlesPolicy + struct store_old_handles {}; + struct no_old_handles {}; + + + + + template + struct lazy_list_node + { + typedef shared_ptr< lazy_list_node > ptr_t; + + lazy_list_node(const DataType& data) : + m_reversed(false), + m_data(data), + m_has_data(true) + {} + + lazy_list_node(ptr_t left_child, ptr_t right_child) : + m_reversed(false), + m_has_data(false), + m_left_child(left_child), + m_right_child(right_child) + {} + + bool m_reversed; + DataType m_data; + bool m_has_data; + shared_ptr m_left_child; + shared_ptr m_right_child; + }; + + + + template + struct old_handles_storage; + + template + struct old_handles_storage + { + Vertex first_vertex; + Vertex second_vertex; + Edge first_edge; + Edge second_edge; + }; + + template + struct old_handles_storage + {}; + + + + + + + template + struct edge_list_storage; + + + + + + template + struct edge_list_storage + { + typedef void type; + + void push_back(Edge) {} + void push_front(Edge) {} + void reverse() {} + void concat_front(edge_list_storage) {} + void concat_back(edge_list_storage) {} + template + void get_list(OutputIterator) {} + }; + + + + + + template + struct edge_list_storage + { + typedef lazy_list_node node_type; + typedef shared_ptr< node_type > type; + type value; + + void push_back(Edge e) + { + type new_node(new node_type(e)); + value = type(new node_type(value, new_node)); + } + + void push_front(Edge e) + { + type new_node(new node_type(e)); + value = type(new node_type(new_node, value)); + } + + void reverse() + { + value->m_reversed = !value->m_reversed; + } + + void concat_front(edge_list_storage other) + { + value = type(new node_type(other.value, value)); + } + + void concat_back(edge_list_storage other) + { + value = type(new node_type(value, other.value)); + } + + template + void get_list(OutputIterator out) + { + get_list_helper(out, value); + } + + private: + + template + void get_list_helper(OutputIterator o_itr, + type root, + bool flipped = false + ) + { + if (!root) + return; + + if (root->m_has_data) + *o_itr = root->m_data; + + if ((flipped && !root->m_reversed) || + (!flipped && root->m_reversed) + ) + { + get_list_helper(o_itr, root->m_right_child, true); + get_list_helper(o_itr, root->m_left_child, true); + } + else + { + get_list_helper(o_itr, root->m_left_child, false); + get_list_helper(o_itr, root->m_right_child, false); + } + + } + + }; + + + + + + template + struct edge_list_storage + { + typedef std::list type; + type value; + + void push_back(Edge e) + { + value.push_back(e); + } + + void push_front(Edge e) + { + value.push_front(e); + } + + void reverse() + { + value.reverse(); + } + + void concat_front(edge_list_storage other) + { + value.splice(value.begin(), other.value); + } + + void concat_back(edge_list_storage other) + { + value.splice(value.end(), other.value); + } + + template + void get_list(OutputIterator out) + { + std::copy(value.begin(), value.end(), out); + } + + }; + + + + + + + + template + struct face_handle_impl + { + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::edge_descriptor edge_t; + typedef typename edge_list_storage::type + edge_list_storage_t; + + + face_handle_impl() : + cached_first_vertex(graph_traits::null_vertex()), + cached_second_vertex(graph_traits::null_vertex()), + true_first_vertex(graph_traits::null_vertex()), + true_second_vertex(graph_traits::null_vertex()), + anchor(graph_traits::null_vertex()) + { + initialize_old_vertices_dispatch(StoreOldHandlesPolicy()); + } + + void initialize_old_vertices_dispatch(store_old_handles) + { + old_handles.first_vertex = graph_traits::null_vertex(); + old_handles.second_vertex = graph_traits::null_vertex(); + } + + void initialize_old_vertices_dispatch(no_old_handles) {} + + vertex_t cached_first_vertex; + vertex_t cached_second_vertex; + vertex_t true_first_vertex; + vertex_t true_second_vertex; + vertex_t anchor; + edge_t cached_first_edge; + edge_t cached_second_edge; + + edge_list_storage edge_list; + old_handles_storage old_handles; + + }; + + + + + + + + + + + + template + class face_handle + { + public: + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::edge_descriptor edge_t; + typedef face_handle_impl + impl_t; + typedef face_handle + self_t; + + face_handle(vertex_t anchor = graph_traits::null_vertex()) : + pimpl(new impl_t()) + { + pimpl->anchor = anchor; + } + + face_handle(vertex_t anchor, edge_t initial_edge, const Graph& g) : + pimpl(new impl_t()) + { + vertex_t s(source(initial_edge,g)); + vertex_t t(target(initial_edge,g)); + vertex_t other_vertex = s == anchor ? t : s; + pimpl->anchor = anchor; + pimpl->cached_first_edge = initial_edge; + pimpl->cached_second_edge = initial_edge; + pimpl->cached_first_vertex = other_vertex; + pimpl->cached_second_vertex = other_vertex; + pimpl->true_first_vertex = other_vertex; + pimpl->true_second_vertex = other_vertex; + + pimpl->edge_list.push_back(initial_edge); + store_old_face_handles_dispatch(StoreOldHandlesPolicy()); + } + + //default copy construction, assignment okay. + + void push_first(edge_t e, const Graph& g) + { + pimpl->edge_list.push_front(e); + pimpl->cached_first_vertex = pimpl->true_first_vertex = + source(e, g) == pimpl->anchor ? target(e,g) : source(e,g); + pimpl->cached_first_edge = e; + } + + void push_second(edge_t e, const Graph& g) + { + pimpl->edge_list.push_back(e); + pimpl->cached_second_vertex = pimpl->true_second_vertex = + source(e, g) == pimpl->anchor ? target(e,g) : source(e,g); + pimpl->cached_second_edge = e; + } + + inline void store_old_face_handles() + { + store_old_face_handles_dispatch(StoreOldHandlesPolicy()); + } + + inline vertex_t first_vertex() const + { + return pimpl->cached_first_vertex; + } + + inline vertex_t second_vertex() const + { + return pimpl->cached_second_vertex; + } + + inline vertex_t true_first_vertex() const + { + return pimpl->true_first_vertex; + } + + inline vertex_t true_second_vertex() const + { + return pimpl->true_second_vertex; + } + + inline vertex_t old_first_vertex() const + { + return pimpl->old_handles.first_vertex; + } + + inline vertex_t old_second_vertex() const + { + return pimpl->old_handles.second_vertex; + } + + inline edge_t old_first_edge() const + { + return pimpl->old_handles.first_edge; + } + + inline edge_t old_second_edge() const + { + return pimpl->old_handles.second_edge; + } + + inline edge_t first_edge() const + { + return pimpl->cached_first_edge; + } + + inline edge_t second_edge() const + { + return pimpl->cached_second_edge; + } + + inline vertex_t get_anchor() const + { + return pimpl->anchor; + } + + void glue_first_to_second + (face_handle& bottom) + { + pimpl->edge_list.concat_front(bottom.pimpl->edge_list); + pimpl->true_first_vertex = bottom.pimpl->true_first_vertex; + pimpl->cached_first_vertex = bottom.pimpl->cached_first_vertex; + pimpl->cached_first_edge = bottom.pimpl->cached_first_edge; + } + + void glue_second_to_first + (face_handle& bottom) + { + pimpl->edge_list.concat_back(bottom.pimpl->edge_list); + pimpl->true_second_vertex = bottom.pimpl->true_second_vertex; + pimpl->cached_second_vertex = bottom.pimpl->cached_second_vertex; + pimpl->cached_second_edge = bottom.pimpl->cached_second_edge; + } + + void flip() + { + pimpl->edge_list.reverse(); + std::swap(pimpl->true_first_vertex, pimpl->true_second_vertex); + std::swap(pimpl->cached_first_vertex, pimpl->cached_second_vertex); + std::swap(pimpl->cached_first_edge, pimpl->cached_second_edge); + } + + template + void get_list(OutputIterator o_itr) + { + pimpl->edge_list.get_list(o_itr); + } + + void reset_vertex_cache() + { + pimpl->cached_first_vertex = pimpl->true_first_vertex; + pimpl->cached_second_vertex = pimpl->true_second_vertex; + } + + inline void set_first_vertex(vertex_t v) + { + pimpl->cached_first_vertex = v; + } + + inline void set_second_vertex(vertex_t v) + { + pimpl->cached_second_vertex = v; + } + + private: + + void store_old_face_handles_dispatch(store_old_handles) + { + pimpl->old_handles.first_vertex = pimpl->true_first_vertex; + pimpl->old_handles.second_vertex = pimpl->true_second_vertex; + pimpl->old_handles.first_edge = pimpl->cached_first_edge; + pimpl->old_handles.second_edge = pimpl->cached_second_edge; + } + + void store_old_face_handles_dispatch(no_old_handles) {} + + + + boost::shared_ptr pimpl; + + }; + + +} /* namespace detail */ } /* namespace graph */ } /* namespace boost */ + + +#endif //__FACE_HANDLES_HPP__ diff --git a/win32/include/boost/graph/planar_detail/face_iterators.hpp b/win32/include/boost/graph/planar_detail/face_iterators.hpp new file mode 100755 index 000000000..b4007d98f --- /dev/null +++ b/win32/include/boost/graph/planar_detail/face_iterators.hpp @@ -0,0 +1,375 @@ +//======================================================================= +// Copyright (c) Aaron Windsor 2007 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef __FACE_ITERATORS_HPP__ +#define __FACE_ITERATORS_HPP__ + +#include +#include +#include + +namespace boost +{ + + //tags for defining traversal properties + + //VisitorType + struct lead_visitor {}; + struct follow_visitor {}; + + //TraversalType + struct single_side {}; + struct both_sides {}; + + //TraversalSubType + struct first_side {}; //for single_side + struct second_side {}; //for single_side + struct alternating {}; //for both_sides + + //Time + struct current_iteration {}; + struct previous_iteration {}; + + // Why TraversalType AND TraversalSubType? TraversalSubType is a function + // template parameter passed in to the constructor of the face iterator, + // whereas TraversalType is a class template parameter. This lets us decide + // at runtime whether to move along the first or second side of a bicomp (by + // assigning a face_iterator that has been constructed with TraversalSubType + // = first_side or second_side to a face_iterator variable) without any of + // the virtual function overhead that comes with implementing this + // functionality as a more structured form of type erasure. It also allows + // a single face_iterator to be the end iterator of two iterators traversing + // both sides of a bicomp. + + //ValueType is either graph_traits::vertex_descriptor + //or graph_traits::edge_descriptor + + + //forward declaration (defining defaults) + template + class face_iterator; + + + + template + struct edge_storage + {}; + + template + struct edge_storage + { + typename graph_traits::edge_descriptor value; + }; + + + + + //specialization for TraversalType = traverse_vertices + template + + class face_iterator + : public boost::iterator_facade < face_iterator, + ValueType, + boost::forward_traversal_tag, + ValueType + > + { + public: + + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::edge_descriptor edge_t; + typedef face_iterator + self; + typedef typename FaceHandlesMap::value_type face_handle_t; + + face_iterator() : + m_lead(graph_traits::null_vertex()), + m_follow(graph_traits::null_vertex()) + {} + + template + face_iterator(face_handle_t anchor_handle, + FaceHandlesMap face_handles, + TraversalSubType traversal_type): + m_follow(anchor_handle.get_anchor()), + m_face_handles(face_handles) + { + set_lead_dispatch(anchor_handle, traversal_type); + } + + template + face_iterator(vertex_t anchor, + FaceHandlesMap face_handles, + TraversalSubType traversal_type): + m_follow(anchor), + m_face_handles(face_handles) + { + set_lead_dispatch(m_face_handles[anchor], traversal_type); + } + + private: + + friend class boost::iterator_core_access; + + + + + inline vertex_t get_first_vertex(face_handle_t anchor_handle, + current_iteration + ) + { + return anchor_handle.first_vertex(); + } + + inline vertex_t get_second_vertex(face_handle_t anchor_handle, + current_iteration + ) + { + return anchor_handle.second_vertex(); + } + + inline vertex_t get_first_vertex(face_handle_t anchor_handle, + previous_iteration + ) + { + return anchor_handle.old_first_vertex(); + } + + inline vertex_t get_second_vertex(face_handle_t anchor_handle, + previous_iteration + ) + { + return anchor_handle.old_second_vertex(); + } + + + + + + inline void set_lead_dispatch(face_handle_t anchor_handle, first_side) + { + m_lead = get_first_vertex(anchor_handle, Time()); + set_edge_to_first_dispatch(anchor_handle, ValueType(), Time()); + } + + inline void set_lead_dispatch(face_handle_t anchor_handle, second_side) + { + m_lead = get_second_vertex(anchor_handle, Time()); + set_edge_to_second_dispatch(anchor_handle, ValueType(), Time()); + } + + + + + + inline void set_edge_to_first_dispatch(face_handle_t anchor_handle, + edge_t, + current_iteration + ) + { + m_edge.value = anchor_handle.first_edge(); + } + + inline void set_edge_to_second_dispatch(face_handle_t anchor_handle, + edge_t, + current_iteration + ) + { + m_edge.value = anchor_handle.second_edge(); + } + + inline void set_edge_to_first_dispatch(face_handle_t anchor_handle, + edge_t, + previous_iteration + ) + { + m_edge.value = anchor_handle.old_first_edge(); + } + + inline void set_edge_to_second_dispatch(face_handle_t anchor_handle, + edge_t, + previous_iteration + ) + { + m_edge.value = anchor_handle.old_second_edge(); + } + + template + inline void set_edge_to_first_dispatch(face_handle_t, vertex_t, T) + {} + + template + inline void set_edge_to_second_dispatch(face_handle_t, vertex_t, T) + {} + + void increment() + { + face_handle_t curr_face_handle(m_face_handles[m_lead]); + vertex_t first = get_first_vertex(curr_face_handle, Time()); + vertex_t second = get_second_vertex(curr_face_handle, Time()); + if (first == m_follow) + { + m_follow = m_lead; + set_edge_to_second_dispatch(curr_face_handle, ValueType(), Time()); + m_lead = second; + } + else if (second == m_follow) + { + m_follow = m_lead; + set_edge_to_first_dispatch(curr_face_handle, ValueType(), Time()); + m_lead = first; + } + else + m_lead = m_follow = graph_traits::null_vertex(); + } + + bool equal(self const& other) const + { + return m_lead == other.m_lead && m_follow == other.m_follow; + } + + ValueType dereference() const + { + return dereference_dispatch(VisitorType(), ValueType()); + } + + inline ValueType dereference_dispatch(lead_visitor, vertex_t) const + { return m_lead; } + + inline ValueType dereference_dispatch(follow_visitor, vertex_t) const + { return m_follow; } + + inline ValueType dereference_dispatch(lead_visitor, edge_t) const + { return m_edge.value; } + + inline ValueType dereference_dispatch(follow_visitor, edge_t) const + { return m_edge.value; } + + vertex_t m_lead; + vertex_t m_follow; + edge_storage::value > m_edge; + FaceHandlesMap m_face_handles; + }; + + + + + + + + + + template + class face_iterator + + : public boost::iterator_facade< face_iterator, + ValueType, + boost::forward_traversal_tag, + ValueType > + { + public: + + typedef face_iterator + self; + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename FaceHandlesMap::value_type face_handle_t; + + face_iterator() {} + + face_iterator(face_handle_t anchor_handle, FaceHandlesMap face_handles): + first_itr(anchor_handle, face_handles, first_side()), + second_itr(anchor_handle, face_handles, second_side()), + first_is_active(true), + first_increment(true) + {} + + face_iterator(vertex_t anchor, FaceHandlesMap face_handles): + first_itr(face_handles[anchor], face_handles, first_side()), + second_itr(face_handles[anchor], face_handles, second_side()), + first_is_active(true), + first_increment(true) + {} + + private: + + friend class boost::iterator_core_access; + + typedef face_iterator + + inner_itr_t; + + void increment() + { + if (first_increment) + { + ++first_itr; + ++second_itr; + first_increment = false; + } + else if (first_is_active) + ++first_itr; + else + ++second_itr; + first_is_active = !first_is_active; + } + + bool equal(self const& other) const + { + //Want this iterator to be equal to the "end" iterator when at least + //one of the iterators has reached the root of the current bicomp. + //This isn't ideal, but it works. + + return (first_itr == other.first_itr || second_itr == other.second_itr); + } + + ValueType dereference() const + { + return first_is_active ? *first_itr : *second_itr; + } + + inner_itr_t first_itr; + inner_itr_t second_itr; + inner_itr_t face_end; + bool first_is_active; + bool first_increment; + + }; + + +} /* namespace boost */ + + +#endif //__FACE_ITERATORS_HPP__ diff --git a/win32/include/boost/graph/planar_face_traversal.hpp b/win32/include/boost/graph/planar_face_traversal.hpp new file mode 100755 index 000000000..eaa7c374e --- /dev/null +++ b/win32/include/boost/graph/planar_face_traversal.hpp @@ -0,0 +1,210 @@ +//======================================================================= +// Copyright (c) Aaron Windsor 2007 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef __PLANAR_FACE_TRAVERSAL_HPP__ +#define __PLANAR_FACE_TRAVERSAL_HPP__ + +#include +#include //for next and prior +#include + + +namespace boost +{ + + + + + struct planar_face_traversal_visitor + { + void begin_traversal() + {} + + void begin_face() + {} + + template + void next_edge(Edge e) + {} + + template + void next_vertex(Vertex v) + {} + + void end_face() + {} + + void end_traversal() + {} + + }; + + + + + + template + void planar_face_traversal(const Graph& g, + PlanarEmbedding embedding, + Visitor& visitor, EdgeIndexMap em + ) + { + typedef typename graph_traits::vertex_descriptor vertex_t; + typedef typename graph_traits::edge_descriptor edge_t; + typedef typename graph_traits::vertex_iterator vertex_iterator_t; + typedef typename graph_traits::edge_iterator edge_iterator_t; + typedef typename + property_traits::value_type embedding_value_t; + typedef typename embedding_value_t::const_iterator embedding_iterator_t; + + typedef typename + std::vector< std::set > distinguished_edge_storage_t; + typedef typename + std::vector< std::map > + distinguished_edge_to_edge_storage_t; + + typedef typename + boost::iterator_property_map + + distinguished_edge_map_t; + + typedef typename + boost::iterator_property_map + + distinguished_edge_to_edge_map_t; + + distinguished_edge_storage_t visited_vector(num_edges(g)); + distinguished_edge_to_edge_storage_t next_edge_vector(num_edges(g)); + + distinguished_edge_map_t visited(visited_vector.begin(), em); + distinguished_edge_to_edge_map_t next_edge(next_edge_vector.begin(), em); + + vertex_iterator_t vi, vi_end; + typename std::vector::iterator ei, ei_end; + edge_iterator_t fi, fi_end; + embedding_iterator_t pi, pi_begin, pi_end; + + visitor.begin_traversal(); + + // Initialize the next_edge property map. This map is initialized from the + // PlanarEmbedding so that get(next_edge, e)[v] is the edge that comes + // after e in the clockwise embedding around vertex v. + + for(tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_t v(*vi); + pi_begin = embedding[v].begin(); + pi_end = embedding[v].end(); + for(pi = pi_begin; pi != pi_end; ++pi) + { + edge_t e(*pi); + std::map m = get(next_edge, e); + m[v] = next(pi) == pi_end ? *pi_begin : *next(pi); + put(next_edge, e, m); + } + } + + // Take a copy of the edges in the graph here, since we want to accomodate + // face traversals that add edges to the graph (for triangulation, in + // particular) and don't want to use invalidated edge iterators. + // Also, while iterating over all edges in the graph, we single out + // any self-loops, which need some special treatment in the face traversal. + + std::vector self_loops; + std::vector edges_cache; + std::vector vertices_in_edge; + + for(tie(fi,fi_end) = edges(g); fi != fi_end; ++fi) + { + edge_t e(*fi); + edges_cache.push_back(e); + if (source(e,g) == target(e,g)) + self_loops.push_back(e); + } + + + // Iterate over all edges in the graph + ei_end = edges_cache.end(); + for(ei = edges_cache.begin(); ei != ei_end; ++ei) + { + + edge_t e(*ei); + vertices_in_edge.clear(); + vertices_in_edge.push_back(source(e,g)); + vertices_in_edge.push_back(target(e,g)); + + typename std::vector::iterator vi, vi_end; + vi_end = vertices_in_edge.end(); + + //Iterate over both vertices in the current edge + for(vi = vertices_in_edge.begin(); vi != vi_end; ++vi) + { + + vertex_t v(*vi); + std::set e_visited = get(visited, e); + typename std::set::iterator e_visited_found + = e_visited.find(v); + + if (e_visited_found == e_visited.end()) + visitor.begin_face(); + + while (e_visited.find(v) == e_visited.end()) + { + visitor.next_vertex(v); + visitor.next_edge(e); + e_visited.insert(v); + put(visited, e, e_visited); + v = source(e,g) == v ? target(e,g) : source(e,g); + e = get(next_edge, e)[v]; + e_visited = get(visited, e); + } + + if (e_visited_found == e_visited.end()) + visitor.end_face(); + + } + + } + + // Iterate over all self-loops, visiting them once separately + // (they've already been visited once, this visitation is for + // the "inside" of the self-loop) + + ei_end = self_loops.end(); + for(ei = self_loops.begin(); ei != ei_end; ++ei) + { + visitor.begin_face(); + visitor.next_edge(*ei); + visitor.next_vertex(source(*ei,g)); + visitor.end_face(); + } + + visitor.end_traversal(); + + } + + + + template + inline void planar_face_traversal(const Graph& g, + PlanarEmbedding embedding, + Visitor& visitor + ) + { + planar_face_traversal(g, embedding, visitor, get(edge_index, g)); + } + + + + +} //namespace boost + +#endif //__PLANAR_FACE_TRAVERSAL_HPP__ diff --git a/win32/include/boost/graph/plod_generator.hpp b/win32/include/boost/graph/plod_generator.hpp new file mode 100755 index 000000000..9277b3d79 --- /dev/null +++ b/win32/include/boost/graph/plod_generator.hpp @@ -0,0 +1,161 @@ +// Copyright 2004 The Trustees of Indiana University. + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_PLOD_GENERATOR_HPP +#define BOOST_GRAPH_PLOD_GENERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + template + class plod_iterator + { + typedef std::vector > out_degrees_t; + typedef typename graph_traits::directed_category directed_category; + + public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef void difference_type; + + plod_iterator() + : gen(0), out_degrees(), degrees_left(0), allow_self_loops(false) { } + + plod_iterator(RandomGenerator& gen, std::size_t n, + double alpha, double beta, bool allow_self_loops = false) + : gen(&gen), n(n), out_degrees(new out_degrees_t), + degrees_left(0), allow_self_loops(allow_self_loops) + { + using std::pow; + + uniform_int x(0, n-1); + for (std::size_t i = 0; i != n; ++i) { + std::size_t xv = x(gen); + std::size_t degree = (xv == 0? 0 : std::size_t(beta * pow(xv, -alpha))); + if (degree != 0) { + out_degrees->push_back(std::make_pair(i, degree)); + } + degrees_left += degree; + } + + next(directed_category()); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + plod_iterator& operator++() + { + next(directed_category()); + return *this; + } + + plod_iterator operator++(int) + { + plod_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const plod_iterator& other) const + { + return degrees_left == other.degrees_left; + } + + bool operator!=(const plod_iterator& other) const + { return !(*this == other); } + + private: + void next(directed_tag) + { + uniform_int x(0, out_degrees->size()-1); + std::size_t source; + do { + source = x(*gen); + } while ((*out_degrees)[source].second == 0); + current.first = (*out_degrees)[source].first; + do { + current.second = x(*gen); + } while (current.first == current.second && !allow_self_loops); + --degrees_left; + if (--(*out_degrees)[source].second == 0) { + (*out_degrees)[source] = out_degrees->back(); + out_degrees->pop_back(); + } + } + + void next(undirected_tag) + { + std::size_t source, target; + while (true) { + /* We may get to the point where we can't actually find any + new edges, so we just add some random edge and set the + degrees left = 0 to signal termination. */ + if (out_degrees->size() < 2) { + uniform_int x(0, n); + current.first = x(*gen); + do { + current.second = x(*gen); + } while (current.first == current.second && !allow_self_loops); + degrees_left = 0; + out_degrees->clear(); + return; + } + + uniform_int x(0, out_degrees->size()-1); + + // Select source vertex + source = x(*gen); + if ((*out_degrees)[source].second == 0) { + (*out_degrees)[source] = out_degrees->back(); + out_degrees->pop_back(); + continue; + } + + // Select target vertex + target = x(*gen); + if ((*out_degrees)[target].second == 0) { + (*out_degrees)[target] = out_degrees->back(); + out_degrees->pop_back(); + continue; + } else if (source != target + || (allow_self_loops && (*out_degrees)[source].second > 2)) { + break; + } + } + + // Update degree counts + --(*out_degrees)[source].second; + --degrees_left; + --(*out_degrees)[target].second; + --degrees_left; + current.first = (*out_degrees)[source].first; + current.second = (*out_degrees)[target].first; + } + + RandomGenerator* gen; + std::size_t n; + shared_ptr out_degrees; + std::size_t degrees_left; + bool allow_self_loops; + value_type current; + }; + +} // end namespace boost + +#endif // BOOST_GRAPH_PLOD_GENERATOR_HPP diff --git a/win32/include/boost/graph/prim_minimum_spanning_tree.hpp b/win32/include/boost/graph/prim_minimum_spanning_tree.hpp new file mode 100755 index 000000000..58e0b6ac7 --- /dev/null +++ b/win32/include/boost/graph/prim_minimum_spanning_tree.hpp @@ -0,0 +1,91 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_MST_PRIM_HPP +#define BOOST_GRAPH_MST_PRIM_HPP + +#include +#include +#include + +namespace boost { + + namespace detail { + // this should be somewhere else in boost... + template struct _project2nd { + V operator()(U, V v) const { return v; } + }; + } + + namespace detail { + + // This is Prim's algorithm to calculate the Minimum Spanning Tree + // for an undirected graph with weighted edges. + + template + inline void + prim_mst_impl(const Graph& G, + typename graph_traits::vertex_descriptor s, + const bgl_named_params& params, + Weight) + { + typedef typename property_traits::value_type W; + std::less compare; + detail::_project2nd combine; + dijkstra_shortest_paths(G, s, params.distance_compare(compare). + distance_combine(combine)); + } + } // namespace detail + + template + inline void + prim_minimum_spanning_tree + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + DijkstraVisitor vis) + { + typedef typename property_traits::value_type W; + std::less compare; + detail::_project2nd combine; + dijkstra_shortest_paths(g, s, predecessor, distance, weight, index_map, + compare, combine, (std::numeric_limits::max)(), 0, + vis); + } + + template + inline void prim_minimum_spanning_tree + (const VertexListGraph& g, + PredecessorMap p_map, + const bgl_named_params& params) + { + detail::prim_mst_impl + (g, + choose_param(get_param(params, root_vertex_t()), *vertices(g).first), + params.predecessor_map(p_map), + choose_const_pmap(get_param(params, edge_weight), g, edge_weight)); + } + + template + inline void prim_minimum_spanning_tree + (const VertexListGraph& g, PredecessorMap p_map) + { + detail::prim_mst_impl + (g, *vertices(g).first, predecessor_map(p_map). + weight_map(get(edge_weight, g)), + get(edge_weight, g)); + } + +} // namespace boost + +#endif // BOOST_GRAPH_MST_PRIM_HPP diff --git a/win32/include/boost/graph/profile.hpp b/win32/include/boost/graph/profile.hpp new file mode 100755 index 000000000..b9c21fa4d --- /dev/null +++ b/win32/include/boost/graph/profile.hpp @@ -0,0 +1,43 @@ +// +//======================================================================= +// Copyright 2002 Marc Wintermantel (wintermantel@even-ag.ch) +// ETH Zurich, Center of Structure Technologies (www.imes.ethz.ch/st) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_PROFILE_HPP +#define BOOST_GRAPH_PROFILE_HPP + +#include +#include +#include + +namespace boost { + + template + typename graph_traits::vertices_size_type + profile(const Graph& g, VertexIndexMap index) + { + typename graph_traits::vertices_size_type b = 0; + typename graph_traits::vertex_iterator i, end; + for (tie(i, end) = vertices(g); i != end; ++i){ + b += ith_bandwidth(*i, g, index) + 1; + } + + return b; + } + + template + typename graph_traits::vertices_size_type + profile(const Graph& g) + { + return profile(g, get(vertex_index, g)); + } + + +} // namespace boost + +#endif // BOOST_GRAPH_PROFILE_HPP diff --git a/win32/include/boost/graph/properties.hpp b/win32/include/boost/graph/properties.hpp new file mode 100755 index 000000000..98ca1ecf6 --- /dev/null +++ b/win32/include/boost/graph/properties.hpp @@ -0,0 +1,389 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_PROPERTIES_HPP +#define BOOST_GRAPH_PROPERTIES_HPP + +#include +#include +#include +#include +#include +#include + + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +// Stay out of the way of the concept checking class +# define Graph Graph_ +# define RandomAccessContainer RandomAccessContainer_ +#endif + +namespace boost { + + enum default_color_type { white_color, gray_color, green_color, red_color, black_color }; + + template + struct color_traits { + static default_color_type white() { return white_color; } + static default_color_type gray() { return gray_color; } + static default_color_type green() { return green_color; } + static default_color_type red() { return red_color; } + static default_color_type black() { return black_color; } + }; + + // These functions are now obsolete, replaced by color_traits. + inline default_color_type white(default_color_type) { return white_color; } + inline default_color_type gray(default_color_type) { return gray_color; } + inline default_color_type green(default_color_type) { return green_color; } + inline default_color_type red(default_color_type) { return red_color; } + inline default_color_type black(default_color_type) { return black_color; } + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template <> + struct property_traits { + typedef default_color_type value_type; + typedef std::ptrdiff_t key_type; + typedef default_color_type& reference; + typedef lvalue_property_map_tag category; + }; + // get/put already defined for T* +#endif + + struct graph_property_tag { }; + struct vertex_property_tag { }; + struct edge_property_tag { }; + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // See examples/edge_property.cpp for how to use this. +#define BOOST_INSTALL_PROPERTY(KIND, NAME) \ + template <> struct property_kind { \ + typedef KIND##_property_tag type; \ + } +#else +#define BOOST_INSTALL_PROPERTY(KIND, NAME) \ + template <> struct property_kind { \ + typedef KIND##_property_tag type; \ + } +#endif + +#define BOOST_DEF_PROPERTY(KIND, NAME) \ + enum KIND##_##NAME##_t { KIND##_##NAME }; \ + BOOST_INSTALL_PROPERTY(KIND, NAME) + + BOOST_DEF_PROPERTY(vertex, all); + BOOST_DEF_PROPERTY(edge, all); + BOOST_DEF_PROPERTY(graph, all); + BOOST_DEF_PROPERTY(vertex, index); + BOOST_DEF_PROPERTY(vertex, index1); + BOOST_DEF_PROPERTY(vertex, index2); + BOOST_DEF_PROPERTY(vertex, root); + BOOST_DEF_PROPERTY(edge, index); + BOOST_DEF_PROPERTY(edge, name); + BOOST_DEF_PROPERTY(edge, weight); + BOOST_DEF_PROPERTY(edge, weight2); + BOOST_DEF_PROPERTY(edge, color); + BOOST_DEF_PROPERTY(vertex, name); + BOOST_DEF_PROPERTY(graph, name); + BOOST_DEF_PROPERTY(vertex, distance); + BOOST_DEF_PROPERTY(vertex, color); + BOOST_DEF_PROPERTY(vertex, degree); + BOOST_DEF_PROPERTY(vertex, in_degree); + BOOST_DEF_PROPERTY(vertex, out_degree); + BOOST_DEF_PROPERTY(vertex, current_degree); + BOOST_DEF_PROPERTY(vertex, priority); + BOOST_DEF_PROPERTY(vertex, discover_time); + BOOST_DEF_PROPERTY(vertex, finish_time); + BOOST_DEF_PROPERTY(vertex, predecessor); + BOOST_DEF_PROPERTY(vertex, rank); + BOOST_DEF_PROPERTY(vertex, centrality); + BOOST_DEF_PROPERTY(vertex, lowpoint); + BOOST_DEF_PROPERTY(edge, reverse); + BOOST_DEF_PROPERTY(edge, capacity); + BOOST_DEF_PROPERTY(edge, residual_capacity); + BOOST_DEF_PROPERTY(edge, centrality); + BOOST_DEF_PROPERTY(graph, visitor); + + // These tags are used for property bundles + BOOST_DEF_PROPERTY(vertex, bundle); + BOOST_DEF_PROPERTY(edge, bundle); + +#undef BOOST_DEF_PROPERTY + + namespace detail { + + struct dummy_edge_property_selector { + template + struct bind_ { + typedef identity_property_map type; + typedef identity_property_map const_type; + }; + }; + struct dummy_vertex_property_selector { + template + struct bind_ { + typedef identity_property_map type; + typedef identity_property_map const_type; + }; + }; + + } // namespace detail + + // Graph classes can either partially specialize property_map + // or they can specialize these two selector classes. + template + struct edge_property_selector { + typedef detail::dummy_edge_property_selector type; + }; + + template + struct vertex_property_selector { + typedef detail::dummy_vertex_property_selector type; + }; + + namespace detail { + + template + struct edge_property_map { + typedef typename Graph::edge_property_type Property; + typedef typename Graph::graph_tag graph_tag; + typedef typename edge_property_selector::type Selector; + typedef typename Selector::template bind_ + Bind; + typedef typename Bind::type type; + typedef typename Bind::const_type const_type; + }; + template + class vertex_property_map { + typedef typename Graph::vertex_property_type Property; + typedef typename Graph::graph_tag graph_tag; + typedef typename vertex_property_selector::type Selector; + typedef typename Selector::template bind_ + Bind; + public: + typedef typename Bind::type type; + typedef typename Bind::const_type const_type; + }; + + // This selects the kind of property map, whether is maps from + // edges or from vertices. + // + // It is overly complicated because it's a workaround for + // partial specialization. + struct choose_vertex_property_map { + template + struct bind_ { + typedef vertex_property_map type; + }; + }; + struct choose_edge_property_map { + template + struct bind_ { + typedef edge_property_map type; + }; + }; + template + struct property_map_kind_selector { + // VC++ gets confused if this isn't defined, even though + // this never gets used. + typedef choose_vertex_property_map type; + }; + template <> struct property_map_kind_selector { + typedef choose_vertex_property_map type; + }; + template <> struct property_map_kind_selector { + typedef choose_edge_property_map type; + }; + } // namespace detail + + template + struct property_map { + private: + typedef typename property_kind::type Kind; + typedef typename detail::property_map_kind_selector::type Selector; + typedef typename Selector::template bind_ Bind; + typedef typename Bind::type Map; + public: + typedef typename Map::type type; + typedef typename Map::const_type const_type; + }; + + // shortcut for accessing the value type of the property map + template + class property_map_value { + typedef typename property_map::const_type PMap; + public: + typedef typename property_traits::value_type type; + }; + + template + class graph_property { + public: + typedef typename property_value::type type; + }; + + template + class vertex_property { + public: + typedef typename Graph::vertex_property_type type; + }; + template + class edge_property { + public: + typedef typename Graph::edge_property_type type; + }; + + template + class degree_property_map + : public put_get_helper::degree_size_type, + degree_property_map > + { + public: + typedef typename graph_traits::vertex_descriptor key_type; + typedef typename graph_traits::degree_size_type value_type; + typedef value_type reference; + typedef readable_property_map_tag category; + degree_property_map(const Graph& g) : m_g(g) { } + value_type operator[](const key_type& v) const { + return degree(v, m_g); + } + private: + const Graph& m_g; + }; + template + inline degree_property_map + make_degree_map(const Graph& g) { + return degree_property_map(g); + } + + //======================================================================== + // Iterator Property Map Generating Functions contributed by + // Kevin Vanhorn. (see also the property map generating functions + // in boost/property_map.hpp) + +#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) + // A helper function for creating a vertex property map out of a + // random access iterator and the internal vertex index map from a + // graph. + template + inline + iterator_property_map< + RandomAccessIterator, + typename property_map::type, + typename std::iterator_traits::value_type, + typename std::iterator_traits::reference + > + make_iterator_vertex_map(RandomAccessIterator iter, const PropertyGraph& g) + { + return make_iterator_property_map(iter, get(vertex_index, g)); + } + + // Use this next function when vertex_descriptor is known to be an + // integer type, with values ranging from 0 to num_vertices(g). + // + template + inline + iterator_property_map< + RandomAccessIterator, + identity_property_map, + typename std::iterator_traits::value_type, + typename std::iterator_traits::reference + > + make_iterator_vertex_map(RandomAccessIterator iter) + { + return make_iterator_property_map(iter, identity_property_map()); + } +#endif + + template + inline + iterator_property_map< + typename RandomAccessContainer::iterator, + typename property_map::type, + typename RandomAccessContainer::value_type, + typename RandomAccessContainer::reference + > + make_container_vertex_map(RandomAccessContainer& c, const PropertyGraph& g) + { + assert(c.size() >= num_vertices(g)); + return make_iterator_vertex_map(c.begin(), g); + } + + template inline + iterator_property_map< + typename RandomAccessContainer::iterator, + identity_property_map, + typename RandomAccessContainer::value_type, + typename RandomAccessContainer::reference + > + make_container_vertex_map(RandomAccessContainer& c) + { + return make_iterator_vertex_map(c.begin()); + } + +#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +# define BOOST_GRAPH_NO_BUNDLED_PROPERTIES +#endif + +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + template + struct bundle_property_map + : put_get_helper > + { + typedef Descriptor key_type; + typedef T value_type; + typedef T& reference; + typedef lvalue_property_map_tag category; + + bundle_property_map() { } + bundle_property_map(Graph* g_, T Bundle::* pm_) : g(g_), pm(pm_) {} + + reference operator[](key_type k) const { return (*g)[k].*pm; } + private: + Graph* g; + T Bundle::* pm; + }; + + namespace detail { + template + struct is_vertex_bundle : is_convertible {}; + } + + template + struct property_map + { + private: + typedef graph_traits traits; + typedef typename Graph::vertex_bundled vertex_bundled; + typedef typename Graph::edge_bundled edge_bundled; + typedef typename mpl::if_c<(detail::is_vertex_bundle::value), + typename traits::vertex_descriptor, + typename traits::edge_descriptor>::type + descriptor; + typedef typename mpl::if_c<(detail::is_vertex_bundle::value), + vertex_bundled, + edge_bundled>::type + actual_bundle; + + public: + typedef bundle_property_map type; + typedef bundle_property_map + const_type; + }; +#endif + +} // namespace boost + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +// Stay out of the way of the concept checking class +# undef Graph +# undef RandomAccessIterator +#endif + + +#endif /* BOOST_GRAPH_PROPERTIES_HPPA */ diff --git a/win32/include/boost/graph/property_iter_range.hpp b/win32/include/boost/graph/property_iter_range.hpp new file mode 100755 index 000000000..1c4570c0b --- /dev/null +++ b/win32/include/boost/graph/property_iter_range.hpp @@ -0,0 +1,118 @@ + +// (C) Copyright François Faure, iMAGIS-GRAVIR / UJF, 2001. +// +// 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) +// +// Revision History: +// 03 May 2001 Jeremy Siek +// Generalized the property map iterator and moved that +// part to boost/property_map.hpp. Also modified to +// differentiate between const/mutable graphs and +// added a workaround to avoid partial specialization. + +// 02 May 2001 François Faure +// Initial version. + +#ifndef BOOST_GRAPH_PROPERTY_ITER_RANGE_HPP +#define BOOST_GRAPH_PROPERTY_ITER_RANGE_HPP + +#include +#include +#include +#include + +namespace boost { + +//====================================================================== +// graph property iterator range + + template + class graph_property_iter_range { + typedef typename property_map::type map_type; + typedef typename property_map::const_type + const_map_type; + typedef typename property_kind::type Kind; + typedef typename mpl::if_c::value, + typename graph_traits::vertex_iterator, + typename graph_traits::edge_iterator>::type iter; + public: + typedef typename property_map_iterator_generator::type + iterator; + typedef typename property_map_iterator_generator + ::type const_iterator; + typedef std::pair type; + typedef std::pair const_type; + }; + + namespace detail { + + template + typename graph_property_iter_range::type + get_property_iter_range_kind(Graph& graph, const Tag& tag, + const vertex_property_tag& ) + { + typedef typename graph_property_iter_range::iterator iter; + return std::make_pair(iter(vertices(graph).first, get(tag, graph)), + iter(vertices(graph).second, get(tag, graph))); + } + + template + typename graph_property_iter_range::const_type + get_property_iter_range_kind(const Graph& graph, const Tag& tag, + const vertex_property_tag& ) + { + typedef typename graph_property_iter_range + ::const_iterator iter; + return std::make_pair(iter(vertices(graph).first, get(tag, graph)), + iter(vertices(graph).second, get(tag, graph))); + } + + + template + typename graph_property_iter_range::type + get_property_iter_range_kind(Graph& graph, const Tag& tag, + const edge_property_tag& ) + { + typedef typename graph_property_iter_range::iterator iter; + return std::make_pair(iter(edges(graph).first, get(tag, graph)), + iter(edges(graph).second, get(tag, graph))); + } + + template + typename graph_property_iter_range::const_type + get_property_iter_range_kind(const Graph& graph, const Tag& tag, + const edge_property_tag& ) + { + typedef typename graph_property_iter_range + ::const_iterator iter; + return std::make_pair(iter(edges(graph).first, get(tag, graph)), + iter(edges(graph).second, get(tag, graph))); + } + + } // namespace detail + + //====================================================================== + // get an iterator range of properties + + template + typename graph_property_iter_range::type + get_property_iter_range(Graph& graph, const Tag& tag) + { + typedef typename property_kind::type Kind; + return detail::get_property_iter_range_kind(graph, tag, Kind()); + } + + template + typename graph_property_iter_range::const_type + get_property_iter_range(const Graph& graph, const Tag& tag) + { + typedef typename property_kind::type Kind; + return detail::get_property_iter_range_kind(graph, tag, Kind()); + } + +} // namespace boost + + +#endif // BOOST_GRAPH_PROPERTY_ITER_RANGE_HPP diff --git a/win32/include/boost/graph/push_relabel_max_flow.hpp b/win32/include/boost/graph/push_relabel_max_flow.hpp new file mode 100755 index 000000000..64cbbd83f --- /dev/null +++ b/win32/include/boost/graph/push_relabel_max_flow.hpp @@ -0,0 +1,727 @@ +//======================================================================= +// Copyright 2000 University of Notre Dame. +// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_PUSH_RELABEL_MAX_FLOW_HPP +#define BOOST_PUSH_RELABEL_MAX_FLOW_HPP + +#include +#include +#include +#include +#include +#include // for std::min and std::max + +#include +#include +#include +#include + +namespace boost { + + namespace detail { + + // This implementation is based on Goldberg's + // "On Implementing Push-Relabel Method for the Maximum Flow Problem" + // by B.V. Cherkassky and A.V. Goldberg, IPCO '95, pp. 157--171 + // and on the h_prf.c and hi_pr.c code written by the above authors. + + // This implements the highest-label version of the push-relabel method + // with the global relabeling and gap relabeling heuristics. + + // The terms "rank", "distance", "height" are synonyms in + // Goldberg's implementation, paper and in the CLR. A "layer" is a + // group of vertices with the same distance. The vertices in each + // layer are categorized as active or inactive. An active vertex + // has positive excess flow and its distance is less than n (it is + // not blocked). + + template + struct preflow_layer { + std::list active_vertices; + std::list inactive_vertices; + }; + + template integer + class FlowValue> + class push_relabel + { + public: + typedef graph_traits Traits; + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::edge_descriptor edge_descriptor; + typedef typename Traits::vertex_iterator vertex_iterator; + typedef typename Traits::out_edge_iterator out_edge_iterator; + typedef typename Traits::vertices_size_type vertices_size_type; + typedef typename Traits::edges_size_type edges_size_type; + + typedef preflow_layer Layer; + typedef std::vector< Layer > LayerArray; + typedef typename LayerArray::iterator layer_iterator; + typedef typename LayerArray::size_type distance_size_type; + + typedef color_traits ColorTraits; + + //======================================================================= + // Some helper predicates + + inline bool is_admissible(vertex_descriptor u, vertex_descriptor v) { + return distance[u] == distance[v] + 1; + } + inline bool is_residual_edge(edge_descriptor a) { + return 0 < residual_capacity[a]; + } + inline bool is_saturated(edge_descriptor a) { + return residual_capacity[a] == 0; + } + + //======================================================================= + // Layer List Management Functions + + typedef typename std::list::iterator list_iterator; + + void add_to_active_list(vertex_descriptor u, Layer& layer) { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + layer.active_vertices.push_front(u); + max_active = max BOOST_PREVENT_MACRO_SUBSTITUTION(distance[u], max_active); + min_active = min BOOST_PREVENT_MACRO_SUBSTITUTION(distance[u], min_active); + layer_list_ptr[u] = layer.active_vertices.begin(); + } + void remove_from_active_list(vertex_descriptor u) { + layers[distance[u]].active_vertices.erase(layer_list_ptr[u]); + } + + void add_to_inactive_list(vertex_descriptor u, Layer& layer) { + layer.inactive_vertices.push_front(u); + layer_list_ptr[u] = layer.inactive_vertices.begin(); + } + void remove_from_inactive_list(vertex_descriptor u) { + layers[distance[u]].inactive_vertices.erase(layer_list_ptr[u]); + } + + //======================================================================= + // initialization + push_relabel(Graph& g_, + EdgeCapacityMap cap, + ResidualCapacityEdgeMap res, + ReverseEdgeMap rev, + vertex_descriptor src_, + vertex_descriptor sink_, + VertexIndexMap idx) + : g(g_), n(num_vertices(g_)), capacity(cap), src(src_), sink(sink_), + index(idx), + excess_flow(num_vertices(g_)), + current(num_vertices(g_), out_edges(*vertices(g_).first, g_).second), + distance(num_vertices(g_)), + color(num_vertices(g_)), + reverse_edge(rev), + residual_capacity(res), + layers(num_vertices(g_)), + layer_list_ptr(num_vertices(g_), + layers.front().inactive_vertices.end()), + push_count(0), update_count(0), relabel_count(0), + gap_count(0), gap_node_count(0), + work_since_last_update(0) + { + vertex_iterator u_iter, u_end; + // Don't count the reverse edges + edges_size_type m = num_edges(g) / 2; + nm = alpha() * n + m; + + // Initialize flow to zero which means initializing + // the residual capacity to equal the capacity. + out_edge_iterator ei, e_end; + for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) + for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei) { + residual_capacity[*ei] = capacity[*ei]; + } + + for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { + vertex_descriptor u = *u_iter; + excess_flow[u] = 0; + current[u] = out_edges(u, g).first; + } + + bool overflow_detected = false; + FlowValue test_excess = 0; + + out_edge_iterator a_iter, a_end; + for (tie(a_iter, a_end) = out_edges(src, g); a_iter != a_end; ++a_iter) + if (target(*a_iter, g) != src) + test_excess += residual_capacity[*a_iter]; + if (test_excess > (std::numeric_limits::max)()) + overflow_detected = true; + + if (overflow_detected) + excess_flow[src] = (std::numeric_limits::max)(); + else { + excess_flow[src] = 0; + for (tie(a_iter, a_end) = out_edges(src, g); + a_iter != a_end; ++a_iter) { + edge_descriptor a = *a_iter; + if (target(a, g) != src) { + ++push_count; + FlowValue delta = residual_capacity[a]; + residual_capacity[a] -= delta; + residual_capacity[reverse_edge[a]] += delta; + excess_flow[target(a, g)] += delta; + } + } + } + max_distance = num_vertices(g) - 1; + max_active = 0; + min_active = n; + + for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { + vertex_descriptor u = *u_iter; + if (u == sink) { + distance[u] = 0; + continue; + } else if (u == src && !overflow_detected) + distance[u] = n; + else + distance[u] = 1; + + if (excess_flow[u] > 0) + add_to_active_list(u, layers[1]); + else if (distance[u] < n) + add_to_inactive_list(u, layers[1]); + } + + } // push_relabel constructor + + //======================================================================= + // This is a breadth-first search over the residual graph + // (well, actually the reverse of the residual graph). + // Would be cool to have a graph view adaptor for hiding certain + // edges, like the saturated (non-residual) edges in this case. + // Goldberg's implementation abused "distance" for the coloring. + void global_distance_update() + { + BOOST_USING_STD_MAX(); + ++update_count; + vertex_iterator u_iter, u_end; + for (tie(u_iter,u_end) = vertices(g); u_iter != u_end; ++u_iter) { + color[*u_iter] = ColorTraits::white(); + distance[*u_iter] = n; + } + color[sink] = ColorTraits::gray(); + distance[sink] = 0; + + for (distance_size_type l = 0; l <= max_distance; ++l) { + layers[l].active_vertices.clear(); + layers[l].inactive_vertices.clear(); + } + + max_distance = max_active = 0; + min_active = n; + + Q.push(sink); + while (! Q.empty()) { + vertex_descriptor u = Q.top(); + Q.pop(); + distance_size_type d_v = distance[u] + 1; + + out_edge_iterator ai, a_end; + for (tie(ai, a_end) = out_edges(u, g); ai != a_end; ++ai) { + edge_descriptor a = *ai; + vertex_descriptor v = target(a, g); + if (color[v] == ColorTraits::white() + && is_residual_edge(reverse_edge[a])) { + distance[v] = d_v; + color[v] = ColorTraits::gray(); + current[v] = out_edges(v, g).first; + max_distance = max BOOST_PREVENT_MACRO_SUBSTITUTION(d_v, max_distance); + + if (excess_flow[v] > 0) + add_to_active_list(v, layers[d_v]); + else + add_to_inactive_list(v, layers[d_v]); + + Q.push(v); + } + } + } + } // global_distance_update() + + //======================================================================= + // This function is called "push" in Goldberg's h_prf implementation, + // but it is called "discharge" in the paper and in hi_pr.c. + void discharge(vertex_descriptor u) + { + assert(excess_flow[u] > 0); + while (1) { + out_edge_iterator ai, ai_end; + for (ai = current[u], ai_end = out_edges(u, g).second; + ai != ai_end; ++ai) { + edge_descriptor a = *ai; + if (is_residual_edge(a)) { + vertex_descriptor v = target(a, g); + if (is_admissible(u, v)) { + ++push_count; + if (v != sink && excess_flow[v] == 0) { + remove_from_inactive_list(v); + add_to_active_list(v, layers[distance[v]]); + } + push_flow(a); + if (excess_flow[u] == 0) + break; + } + } + } // for out_edges of i starting from current + + Layer& layer = layers[distance[u]]; + distance_size_type du = distance[u]; + + if (ai == ai_end) { // i must be relabeled + relabel_distance(u); + if (layer.active_vertices.empty() + && layer.inactive_vertices.empty()) + gap(du); + if (distance[u] == n) + break; + } else { // i is no longer active + current[u] = ai; + add_to_inactive_list(u, layer); + break; + } + } // while (1) + } // discharge() + + //======================================================================= + // This corresponds to the "push" update operation of the paper, + // not the "push" function in Goldberg's h_prf.c implementation. + // The idea is to push the excess flow from from vertex u to v. + void push_flow(edge_descriptor u_v) + { + vertex_descriptor + u = source(u_v, g), + v = target(u_v, g); + + BOOST_USING_STD_MIN(); + FlowValue flow_delta + = min BOOST_PREVENT_MACRO_SUBSTITUTION(excess_flow[u], residual_capacity[u_v]); + + residual_capacity[u_v] -= flow_delta; + residual_capacity[reverse_edge[u_v]] += flow_delta; + + excess_flow[u] -= flow_delta; + excess_flow[v] += flow_delta; + } // push_flow() + + //======================================================================= + // The main purpose of this routine is to set distance[v] + // to the smallest value allowed by the valid labeling constraints, + // which are: + // distance[t] = 0 + // distance[u] <= distance[v] + 1 for every residual edge (u,v) + // + distance_size_type relabel_distance(vertex_descriptor u) + { + BOOST_USING_STD_MAX(); + ++relabel_count; + work_since_last_update += beta(); + + distance_size_type min_distance = num_vertices(g); + distance[u] = min_distance; + + // Examine the residual out-edges of vertex i, choosing the + // edge whose target vertex has the minimal distance. + out_edge_iterator ai, a_end, min_edge_iter; + for (tie(ai, a_end) = out_edges(u, g); ai != a_end; ++ai) { + ++work_since_last_update; + edge_descriptor a = *ai; + vertex_descriptor v = target(a, g); + if (is_residual_edge(a) && distance[v] < min_distance) { + min_distance = distance[v]; + min_edge_iter = ai; + } + } + ++min_distance; + if (min_distance < n) { + distance[u] = min_distance; // this is the main action + current[u] = min_edge_iter; + max_distance = max BOOST_PREVENT_MACRO_SUBSTITUTION(min_distance, max_distance); + } + return min_distance; + } // relabel_distance() + + //======================================================================= + // cleanup beyond the gap + void gap(distance_size_type empty_distance) + { + ++gap_count; + + distance_size_type r; // distance of layer before the current layer + r = empty_distance - 1; + + // Set the distance for the vertices beyond the gap to "infinity". + for (layer_iterator l = layers.begin() + empty_distance + 1; + l < layers.begin() + max_distance; ++l) { + list_iterator i; + for (i = l->inactive_vertices.begin(); + i != l->inactive_vertices.end(); ++i) { + distance[*i] = n; + ++gap_node_count; + } + l->inactive_vertices.clear(); + } + max_distance = r; + max_active = r; + } + + //======================================================================= + // This is the core part of the algorithm, "phase one". + FlowValue maximum_preflow() + { + work_since_last_update = 0; + + while (max_active >= min_active) { // "main" loop + + Layer& layer = layers[max_active]; + list_iterator u_iter = layer.active_vertices.begin(); + + if (u_iter == layer.active_vertices.end()) + --max_active; + else { + vertex_descriptor u = *u_iter; + remove_from_active_list(u); + + discharge(u); + + if (work_since_last_update * global_update_frequency() > nm) { + global_distance_update(); + work_since_last_update = 0; + } + } + } // while (max_active >= min_active) + + return excess_flow[sink]; + } // maximum_preflow() + + //======================================================================= + // remove excess flow, the "second phase" + // This does a DFS on the reverse flow graph of nodes with excess flow. + // If a cycle is found, cancel it. + // Return the nodes with excess flow in topological order. + // + // Unlike the prefl_to_flow() implementation, we use + // "color" instead of "distance" for the DFS labels + // "parent" instead of nl_prev for the DFS tree + // "topo_next" instead of nl_next for the topological ordering + void convert_preflow_to_flow() + { + vertex_iterator u_iter, u_end; + out_edge_iterator ai, a_end; + + vertex_descriptor r, restart, u; + + std::vector parent(n); + std::vector topo_next(n); + + vertex_descriptor tos(parent[0]), + bos(parent[0]); // bogus initialization, just to avoid warning + bool bos_null = true; + + // handle self-loops + for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) + for (tie(ai, a_end) = out_edges(*u_iter, g); ai != a_end; ++ai) + if (target(*ai, g) == *u_iter) + residual_capacity[*ai] = capacity[*ai]; + + // initialize + for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { + u = *u_iter; + color[u] = ColorTraits::white(); + parent[u] = u; + current[u] = out_edges(u, g).first; + } + // eliminate flow cycles and topologically order the vertices + for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { + u = *u_iter; + if (color[u] == ColorTraits::white() + && excess_flow[u] > 0 + && u != src && u != sink ) { + r = u; + color[r] = ColorTraits::gray(); + while (1) { + for (; current[u] != out_edges(u, g).second; ++current[u]) { + edge_descriptor a = *current[u]; + if (capacity[a] == 0 && is_residual_edge(a)) { + vertex_descriptor v = target(a, g); + if (color[v] == ColorTraits::white()) { + color[v] = ColorTraits::gray(); + parent[v] = u; + u = v; + break; + } else if (color[v] == ColorTraits::gray()) { + // find minimum flow on the cycle + FlowValue delta = residual_capacity[a]; + while (1) { + BOOST_USING_STD_MIN(); + delta = min BOOST_PREVENT_MACRO_SUBSTITUTION(delta, residual_capacity[*current[v]]); + if (v == u) + break; + else + v = target(*current[v], g); + } + // remove delta flow units + v = u; + while (1) { + a = *current[v]; + residual_capacity[a] -= delta; + residual_capacity[reverse_edge[a]] += delta; + v = target(a, g); + if (v == u) + break; + } + + // back-out of DFS to the first saturated edge + restart = u; + for (v = target(*current[u], g); v != u; v = target(a, g)){ + a = *current[v]; + if (color[v] == ColorTraits::white() + || is_saturated(a)) { + color[target(*current[v], g)] = ColorTraits::white(); + if (color[v] != ColorTraits::white()) + restart = v; + } + } + if (restart != u) { + u = restart; + ++current[u]; + break; + } + } // else if (color[v] == ColorTraits::gray()) + } // if (capacity[a] == 0 ... + } // for out_edges(u, g) (though "u" changes during loop) + + if (current[u] == out_edges(u, g).second) { + // scan of i is complete + color[u] = ColorTraits::black(); + if (u != src) { + if (bos_null) { + bos = u; + bos_null = false; + tos = u; + } else { + topo_next[u] = tos; + tos = u; + } + } + if (u != r) { + u = parent[u]; + ++current[u]; + } else + break; + } + } // while (1) + } // if (color[u] == white && excess_flow[u] > 0 & ...) + } // for all vertices in g + + // return excess flows + // note that the sink is not on the stack + if (! bos_null) { + for (u = tos; u != bos; u = topo_next[u]) { + ai = out_edges(u, g).first; + while (excess_flow[u] > 0 && ai != out_edges(u, g).second) { + if (capacity[*ai] == 0 && is_residual_edge(*ai)) + push_flow(*ai); + ++ai; + } + } + // do the bottom + u = bos; + ai = out_edges(u, g).first; + while (excess_flow[u] > 0) { + if (capacity[*ai] == 0 && is_residual_edge(*ai)) + push_flow(*ai); + ++ai; + } + } + + } // convert_preflow_to_flow() + + //======================================================================= + inline bool is_flow() + { + vertex_iterator u_iter, u_end; + out_edge_iterator ai, a_end; + + // check edge flow values + for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { + for (tie(ai, a_end) = out_edges(*u_iter, g); ai != a_end; ++ai) { + edge_descriptor a = *ai; + if (capacity[a] > 0) + if ((residual_capacity[a] + residual_capacity[reverse_edge[a]] + != capacity[a] + capacity[reverse_edge[a]]) + || (residual_capacity[a] < 0) + || (residual_capacity[reverse_edge[a]] < 0)) + return false; + } + } + + // check conservation + FlowValue sum; + for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { + vertex_descriptor u = *u_iter; + if (u != src && u != sink) { + if (excess_flow[u] != 0) + return false; + sum = 0; + for (tie(ai, a_end) = out_edges(u, g); ai != a_end; ++ai) + if (capacity[*ai] > 0) + sum -= capacity[*ai] - residual_capacity[*ai]; + else + sum += residual_capacity[*ai]; + + if (excess_flow[u] != sum) + return false; + } + } + + return true; + } // is_flow() + + bool is_optimal() { + // check if mincut is saturated... + global_distance_update(); + return distance[src] >= n; + } + + void print_statistics(std::ostream& os) const { + os << "pushes: " << push_count << std::endl + << "relabels: " << relabel_count << std::endl + << "updates: " << update_count << std::endl + << "gaps: " << gap_count << std::endl + << "gap nodes: " << gap_node_count << std::endl + << std::endl; + } + + void print_flow_values(std::ostream& os) const { + os << "flow values" << std::endl; + vertex_iterator u_iter, u_end; + out_edge_iterator ei, e_end; + for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) + for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei) + if (capacity[*ei] > 0) + os << *u_iter << " " << target(*ei, g) << " " + << (capacity[*ei] - residual_capacity[*ei]) << std::endl; + os << std::endl; + } + + //======================================================================= + + Graph& g; + vertices_size_type n; + vertices_size_type nm; + EdgeCapacityMap capacity; + vertex_descriptor src; + vertex_descriptor sink; + VertexIndexMap index; + + // will need to use random_access_property_map with these + std::vector< FlowValue > excess_flow; + std::vector< out_edge_iterator > current; + std::vector< distance_size_type > distance; + std::vector< default_color_type > color; + + // Edge Property Maps that must be interior to the graph + ReverseEdgeMap reverse_edge; + ResidualCapacityEdgeMap residual_capacity; + + LayerArray layers; + std::vector< list_iterator > layer_list_ptr; + distance_size_type max_distance; // maximal distance + distance_size_type max_active; // maximal distance with active node + distance_size_type min_active; // minimal distance with active node + boost::queue Q; + + // Statistics counters + long push_count; + long update_count; + long relabel_count; + long gap_count; + long gap_node_count; + + inline double global_update_frequency() { return 0.5; } + inline vertices_size_type alpha() { return 6; } + inline long beta() { return 12; } + + long work_since_last_update; + }; + + } // namespace detail + + template + typename property_traits::value_type + push_relabel_max_flow + (Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink, + CapacityEdgeMap cap, ResidualCapacityEdgeMap res, + ReverseEdgeMap rev, VertexIndexMap index_map) + { + typedef typename property_traits::value_type FlowValue; + + detail::push_relabel + algo(g, cap, res, rev, src, sink, index_map); + + FlowValue flow = algo.maximum_preflow(); + + algo.convert_preflow_to_flow(); + + assert(algo.is_flow()); + assert(algo.is_optimal()); + + return flow; + } // push_relabel_max_flow() + + template + typename detail::edge_capacity_value::type + push_relabel_max_flow + (Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink, + const bgl_named_params& params) + { + return push_relabel_max_flow + (g, src, sink, + choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), + choose_pmap(get_param(params, edge_residual_capacity), + g, edge_residual_capacity), + choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index) + ); + } + + template + typename property_traits< + typename property_map::const_type + >::value_type + push_relabel_max_flow + (Graph& g, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink) + { + bgl_named_params params(0); // bogus empty param + return push_relabel_max_flow(g, src, sink, params); + } + +} // namespace boost + +#endif // BOOST_PUSH_RELABEL_MAX_FLOW_HPP + diff --git a/win32/include/boost/graph/random.hpp b/win32/include/boost/graph/random.hpp new file mode 100755 index 000000000..38c8ad783 --- /dev/null +++ b/win32/include/boost/graph/random.hpp @@ -0,0 +1,205 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright (C) Vladimir Prus 2003 +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_RANDOM_HPP +#define BOOST_GRAPH_RANDOM_HPP + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +namespace boost { + + // grab a random vertex from the graph's vertex set + template + typename graph_traits::vertex_descriptor + random_vertex(Graph& g, RandomNumGen& gen) + { + if (num_vertices(g) > 1) { + #if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581)) + std::size_t n = std::random( num_vertices(g) ); + #else + uniform_int<> distrib(0, num_vertices(g)-1); + variate_generator > rand_gen(gen, distrib); + std::size_t n = rand_gen(); + #endif + typename graph_traits::vertex_iterator + i = vertices(g).first; + while (n-- > 0) ++i; // std::advance not VC++ portable + return *i; + } else + return *vertices(g).first; + } + + template + typename graph_traits::edge_descriptor + random_edge(Graph& g, RandomNumGen& gen) { + if (num_edges(g) > 1) { + #if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581)) + typename graph_traits::edges_size_type + n = std::random( num_edges(g) ); + #else + uniform_int<> distrib(0, num_edges(g)-1); + variate_generator > rand_gen(gen, distrib); + typename graph_traits::edges_size_type + n = rand_gen(); + #endif + typename graph_traits::edge_iterator + i = edges(g).first; + while (n-- > 0) ++i; // std::advance not VC++ portable + return *i; + } else + return *edges(g).first; + } + + namespace detail { + class dummy_property_copier { + public: + template + void operator()(const V1&, const V2&) const {} + }; + } + + template + void generate_random_graph1 + (MutableGraph& g, + typename graph_traits::vertices_size_type V, + typename graph_traits::vertices_size_type E, + RandNumGen& gen, + bool allow_parallel = true, + bool self_edges = false) + { + typedef graph_traits Traits; + typedef typename Traits::vertices_size_type v_size_t; + typedef typename Traits::edges_size_type e_size_t; + typedef typename Traits::vertex_descriptor vertex_descriptor; + + // When parallel edges are not allowed, we create a new graph which + // does not allow parallel edges, construct it and copy back. + // This is not efficient if 'g' already disallow parallel edges, + // but that's task for later. + if (!allow_parallel) { + + typedef typename boost::graph_traits::directed_category dir; + typedef typename mpl::if_, + directedS, undirectedS>::type select; + adjacency_list g2; + generate_random_graph1(g2, V, E, gen, true, self_edges); + + copy_graph(g2, g, vertex_copy(detail::dummy_property_copier()). + edge_copy(detail::dummy_property_copier())); + + } else { + + for (v_size_t i = 0; i < V; ++i) + add_vertex(g); + + for (e_size_t j = 0; j < E; ++j) { + vertex_descriptor a = random_vertex(g, gen), b; + do { + b = random_vertex(g, gen); + } while (self_edges == false && a == b); + add_edge(a, b, g); + } + } + } + + template + void generate_random_graph + (MutableGraph& g, + typename graph_traits::vertices_size_type V, + typename graph_traits::vertices_size_type E, + RandNumGen& gen, + bool allow_parallel = true, + bool self_edges = false) + { + generate_random_graph1(g, V, E, gen, allow_parallel, self_edges); + } + + template + void generate_random_graph + (MutableGraph& g, + typename graph_traits::vertices_size_type V, + typename graph_traits::vertices_size_type E, + RandNumGen& gen, + VertexOutputIterator vertex_out, + EdgeOutputIterator edge_out, + bool self_edges = false) + { + typedef graph_traits Traits; + typedef typename Traits::vertices_size_type v_size_t; + typedef typename Traits::edges_size_type e_size_t; + typedef typename Traits::vertex_descriptor vertex_t; + typedef typename Traits::edge_descriptor edge_t; + + for (v_size_t i = 0; i < V; ++i) + *vertex_out++ = add_vertex(g); + + for (e_size_t j = 0; j < E; ++j) { + vertex_t a = random_vertex(g, gen), b; + do { + b = random_vertex(g, gen); + } while (self_edges == false && a == b); + edge_t e; bool inserted; + tie(e, inserted) = add_edge(a, b, g); + if (inserted) + *edge_out++ = std::make_pair(source(e, g), target(e, g)); + } + } + + namespace detail { + + template + void randomize_property(G& g, RandomGenerator& rg, + Property, vertex_property_tag) + { + typename property_map::type pm = get(Property(), g); + typename graph_traits::vertex_iterator vi, ve; + for (tie(vi, ve) = vertices(g); vi != ve; ++vi) { + pm[*vi] = rg(); + } + } + + template + void randomize_property(G& g, RandomGenerator& rg, + Property, edge_property_tag) + { + typename property_map::type pm = get(Property(), g); + typename graph_traits::edge_iterator ei, ee; + for (tie(ei, ee) = edges(g); ei != ee; ++ei) { + pm[*ei] = rg(); + } + } + } + + template + void randomize_property(G& g, RandomGenerator& rg) + { + detail::randomize_property + (g, rg, Property(), typename property_kind::type()); + } + + + + +} + + +#endif diff --git a/win32/include/boost/graph/random_layout.hpp b/win32/include/boost/graph/random_layout.hpp new file mode 100755 index 000000000..1bf75f267 --- /dev/null +++ b/win32/include/boost/graph/random_layout.hpp @@ -0,0 +1,49 @@ +// Copyright 2004 The Trustees of Indiana University. + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_RANDOM_LAYOUT_HPP +#define BOOST_GRAPH_RANDOM_LAYOUT_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { + +template +void +random_graph_layout(const Graph& g, PositionMap position_map, + Dimension minX, Dimension maxX, + Dimension minY, Dimension maxY, + RandomNumberGenerator& gen) +{ + typedef typename mpl::if_, + uniform_int, + uniform_real >::type distrib_t; + typedef typename mpl::if_, + RandomNumberGenerator&, + uniform_01 > + ::type gen_t; + + gen_t my_gen(gen); + distrib_t x(minX, maxX); + distrib_t y(minY, maxY); + typename graph_traits::vertex_iterator vi, vi_end; + for(tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) { + position_map[*vi].x = x(my_gen); + position_map[*vi].y = y(my_gen); + } +} + +} // end namespace boost + +#endif // BOOST_GRAPH_RANDOM_LAYOUT_HPP diff --git a/win32/include/boost/graph/read_dimacs.hpp b/win32/include/boost/graph/read_dimacs.hpp new file mode 100755 index 000000000..e4f1d2e8a --- /dev/null +++ b/win32/include/boost/graph/read_dimacs.hpp @@ -0,0 +1,277 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee +// +// 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) +//======================================================================= + +/* + Reads maximal flow problem in extended DIMACS format. + This works, but could use some polishing. +*/ + +/* ----------------------------------------------------------------- */ + +#include +#include +#include + +namespace boost { + +template +int read_dimacs_max_flow(Graph& g, + CapacityMap capacity, + ReverseEdgeMap reverse_edge, + typename graph_traits::vertex_descriptor& src, + typename graph_traits::vertex_descriptor& sink, + std::istream& in=std::cin) +{ + // const int MAXLINE = 100; /* max line length in the input file */ + const int ARC_FIELDS = 3; /* no of fields in arc line */ + const int NODE_FIELDS = 2; /* no of fields in node line */ + const int P_FIELDS = 3; /* no of fields in problem line */ + const char* PROBLEM_TYPE = "max"; /* name of problem type*/ + + typedef typename graph_traits::vertices_size_type vertices_size_type; + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::edge_descriptor edge_descriptor; + + std::vector verts; + + long m, n, /* number of edges and nodes */ + i, head, tail, cap; + + long no_lines=0, /* no of current input line */ + no_plines=0, /* no of problem-lines */ + no_nslines=0, /* no of node-source-lines */ + no_nklines=0, /* no of node-source-lines */ + no_alines=0; /* no of arc-lines */ + + std::string in_line; /* for reading input line */ + char pr_type[3]; /* for reading type of the problem */ + char nd; /* source (s) or sink (t) */ + + int k, /* temporary */ + err_no; /* no of detected error */ + + /* -------------- error numbers & error messages ---------------- */ + const int EN1 = 0; + const int EN2 = 1; + const int EN3 = 2; + const int EN4 = 3; + // const int EN6 = 4; + // const int EN10 = 5; + // const int EN7 = 6; + const int EN8 = 7; + const int EN9 = 8; + const int EN11 = 9; + const int EN12 = 10; + // const int EN13 = 11; + const int EN14 = 12; + const int EN16 = 13; + const int EN15 = 14; + const int EN17 = 15; + const int EN18 = 16; + const int EN21 = 17; + const int EN19 = 18; + const int EN20 = 19; + const int EN22 = 20; + + static char *err_message[] = + { + /* 0*/ "more than one problem line.", + /* 1*/ "wrong number of parameters in the problem line.", + /* 2*/ "it is not a Max Flow problem line.", + /* 3*/ "bad value of a parameter in the problem line.", + /* 4*/ "can't obtain enough memory to solve this problem.", + /* 5*/ "more than one line with the problem name.", + /* 6*/ "can't read problem name.", + /* 7*/ "problem description must be before node description.", + /* 8*/ "this parser doesn't support multiply sources and sinks.", + /* 9*/ "wrong number of parameters in the node line.", + /*10*/ "wrong value of parameters in the node line.", + /*11*/ " ", + /*12*/ "source and sink descriptions must be before arc descriptions.", + /*13*/ "too many arcs in the input.", + /*14*/ "wrong number of parameters in the arc line.", + /*15*/ "wrong value of parameters in the arc line.", + /*16*/ "unknown line type in the input.", + /*17*/ "reading error.", + /*18*/ "not enough arcs in the input.", + /*19*/ "source or sink doesn't have incident arcs.", + /*20*/ "can't read anything from the input file." + }; + /* --------------------------------------------------------------- */ + + /* The main loop: + - reads the line of the input, + - analyses its type, + - checks correctness of parameters, + - puts data to the arrays, + - does service functions + */ + + while (std::getline(in, in_line)) { + ++no_lines; + + switch (in_line[0]) { + case 'c': /* skip lines with comments */ + case '\n': /* skip empty lines */ + case '\0': /* skip empty lines at the end of file */ + break; + + case 'p': /* problem description */ + if ( no_plines > 0 ) + /* more than one problem line */ + { err_no = EN1 ; goto error; } + + no_plines = 1; + + if ( + /* reading problem line: type of problem, no of nodes, no of arcs */ + sscanf ( in_line.c_str(), "%*c %3s %ld %ld", pr_type, &n, &m ) + != P_FIELDS + ) + /*wrong number of parameters in the problem line*/ + { err_no = EN2; goto error; } + + if ( strcmp ( pr_type, PROBLEM_TYPE ) ) + /*wrong problem type*/ + { err_no = EN3; goto error; } + + if ( n <= 0 || m <= 0 ) + /*wrong value of no of arcs or nodes*/ + { err_no = EN4; goto error; } + + { + for (long vi = 0; vi < n; ++vi) + verts.push_back(add_vertex(g)); + } + break; + + case 'n': /* source(s) description */ + if ( no_plines == 0 ) + /* there was not problem line above */ + { err_no = EN8; goto error; } + + /* reading source or sink */ + k = sscanf ( in_line.c_str(),"%*c %ld %c", &i, &nd ); + --i; // index from 0 + if ( k < NODE_FIELDS ) + /* node line is incorrect */ + { err_no = EN11; goto error; } + + if ( i < 0 || i > n ) + /* wrong value of node */ + { err_no = EN12; goto error; } + + switch (nd) { + case 's': /* source line */ + + if ( no_nslines != 0) + /* more than one source line */ + { err_no = EN9; goto error; } + + no_nslines = 1; + src = verts[i]; + break; + + case 't': /* sink line */ + + if ( no_nklines != 0) + /* more than one sink line */ + { err_no = EN9; goto error; } + + no_nklines = 1; + sink = verts[i]; + break; + + default: + /* wrong type of node-line */ + err_no = EN12; goto error; + } + break; + + case 'a': /* arc description */ + if ( no_nslines == 0 || no_nklines == 0 ) + /* there was not source and sink description above */ + { err_no = EN14; goto error; } + + if ( no_alines >= m ) + /*too many arcs on input*/ + { err_no = EN16; goto error; } + + if ( + /* reading an arc description */ + sscanf ( in_line.c_str(),"%*c %ld %ld %ld", + &tail, &head, &cap ) + != ARC_FIELDS + ) + /* arc description is not correct */ + { err_no = EN15; goto error; } + + --tail; // index from 0, not 1 + --head; + if ( tail < 0 || tail > n || + head < 0 || head > n + ) + /* wrong value of nodes */ + { err_no = EN17; goto error; } + + { + edge_descriptor e1, e2; + bool in1, in2; + tie(e1, in1) = add_edge(verts[tail], verts[head], g); + tie(e2, in2) = add_edge(verts[head], verts[tail], g); + if (!in1 || !in2) { + std::cerr << "unable to add edge (" << head << "," << tail << ")" + << std::endl; + return -1; + } + capacity[e1] = cap; + capacity[e2] = 0; + reverse_edge[e1] = e2; + reverse_edge[e2] = e1; + } + ++no_alines; + break; + + default: + /* unknown type of line */ + err_no = EN18; goto error; + + } /* end of switch */ + } /* end of input loop */ + + /* ----- all is red or error while reading ----- */ + + if ( feof (stdin) == 0 ) /* reading error */ + { err_no=EN21; goto error; } + + if ( no_lines == 0 ) /* empty input */ + { err_no = EN22; goto error; } + + if ( no_alines < m ) /* not enough arcs */ + { err_no = EN19; goto error; } + + if ( out_degree(src, g) == 0 || out_degree(sink, g) == 0 ) + /* no arc goes out of the source */ + { err_no = EN20; goto error; } + + /* Thanks God! all is done */ + return (0); + + /* ---------------------------------- */ + error: /* error found reading input */ + + printf ( "\nline %ld of input - %s\n", + no_lines, err_message[err_no] ); + + exit (1); + return (0); /* to avoid warning */ +} +/* -------------------- end of parser -------------------*/ + +} // namespace boost diff --git a/win32/include/boost/graph/relax.hpp b/win32/include/boost/graph/relax.hpp new file mode 100755 index 000000000..65afefe84 --- /dev/null +++ b/win32/include/boost/graph/relax.hpp @@ -0,0 +1,77 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_RELAX_HPP +#define BOOST_GRAPH_RELAX_HPP + +#include +#include // for numeric limits +#include +#include + +namespace boost { + + // The following version of the plus functor prevents + // problems due to overflow at positive infinity. + + template + struct closed_plus + { + T operator()(const T& a, const T& b) const { + using namespace std; + T zero(0); + T result = a + b; + if (result < zero && a >= zero && b >= zero) + return (numeric_limits::max)(); + return result; + } + }; + + template + bool relax(typename graph_traits::edge_descriptor e, + const Graph& g, const WeightMap& w, + PredecessorMap& p, DistanceMap& d, + const BinaryFunction& combine, const BinaryPredicate& compare) + { + typedef typename graph_traits::directed_category DirCat; + bool is_undirected = is_same::value; + typedef typename graph_traits::vertex_descriptor Vertex; + Vertex u = source(e, g), v = target(e, g); + typedef typename property_traits::value_type D; + typedef typename property_traits::value_type W; + D d_u = get(d, u), d_v = get(d, v); + W w_e = get(w, e); + + if ( compare(combine(d_u, w_e), d_v) ) { + put(d, v, combine(d_u, w_e)); + put(p, v, u); + return true; + } else if (is_undirected && compare(combine(d_v, w_e), d_u)) { + put(d, u, combine(d_v, w_e)); + put(p, u, v); + return true; + } else + return false; + } + + template + bool relax(typename graph_traits::edge_descriptor e, + const Graph& g, WeightMap w, PredecessorMap p, DistanceMap d) + { + typedef typename property_traits::value_type D; + typedef closed_plus Combine; + typedef std::less Compare; + return relax(e, g, w, p, d, Combine(), Compare()); + } + +} // namespace boost + +#endif /* BOOST_GRAPH_RELAX_HPP */ diff --git a/win32/include/boost/graph/reverse_graph.hpp b/win32/include/boost/graph/reverse_graph.hpp new file mode 100755 index 000000000..fa3a5c632 --- /dev/null +++ b/win32/include/boost/graph/reverse_graph.hpp @@ -0,0 +1,324 @@ +// (C) Copyright David Abrahams 2000. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef REVERSE_GRAPH_DWA092300_H_ +# define REVERSE_GRAPH_DWA092300_H_ + +#include +#include +#include + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +// Stay out of the way of the concept checking class +# define BidirectionalGraph BidirectionalGraph_ +#endif + +namespace boost { + +struct reverse_graph_tag { }; + + namespace detail { + + template struct choose_rev_edge_iter { }; + template <> struct choose_rev_edge_iter { + template struct bind_ { + typedef typename graph_traits::edge_iterator type; + }; + }; + template <> struct choose_rev_edge_iter { + template struct bind_ { + typedef void type; + }; + }; + + } // namespace detail + +template +class reverse_graph { + typedef reverse_graph Self; + typedef graph_traits Traits; + public: + typedef BidirectionalGraph base_type; + + // Constructor + reverse_graph(GraphRef g) : m_g(g) {} + + // Graph requirements + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::edge_descriptor edge_descriptor; + typedef typename Traits::directed_category directed_category; + typedef typename Traits::edge_parallel_category edge_parallel_category; + typedef typename Traits::traversal_category traversal_category; + + // IncidenceGraph requirements + typedef typename Traits::in_edge_iterator out_edge_iterator; + typedef typename Traits::degree_size_type degree_size_type; + + // BidirectionalGraph requirements + typedef typename Traits::out_edge_iterator in_edge_iterator; + + // AdjacencyGraph requirements + typedef typename adjacency_iterator_generator::type adjacency_iterator; + + // VertexListGraph requirements + typedef typename Traits::vertex_iterator vertex_iterator; + + // EdgeListGraph requirements + enum { is_edge_list = is_convertible::value }; + typedef detail::choose_rev_edge_iter ChooseEdgeIter; + typedef typename ChooseEdgeIter:: + template bind_::type edge_iterator; + typedef typename Traits::vertices_size_type vertices_size_type; + typedef typename Traits::edges_size_type edges_size_type; + + // More typedefs used by detail::edge_property_map, vertex_property_map + typedef typename BidirectionalGraph::edge_property_type + edge_property_type; + typedef typename BidirectionalGraph::vertex_property_type + vertex_property_type; + typedef reverse_graph_tag graph_tag; + +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + // Bundled properties support + template + typename graph::detail::bundled_result::type& + operator[](Descriptor x) + { return m_g[x]; } + + template + typename graph::detail::bundled_result::type const& + operator[](Descriptor x) const + { return m_g[x]; } +#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES + + static vertex_descriptor null_vertex() + { return Traits::null_vertex(); } + + // would be private, but template friends aren't portable enough. + // private: + GraphRef m_g; +}; + +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + template + struct vertex_bundle_type > + : vertex_bundle_type { }; + + template + struct edge_bundle_type > + : edge_bundle_type { }; +#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES + +template +inline reverse_graph +make_reverse_graph(const BidirectionalGraph& g) +{ + return reverse_graph(g); +} + +template +inline reverse_graph +make_reverse_graph(BidirectionalGraph& g) +{ + return reverse_graph(g); +} + +template +std::pair::vertex_iterator, + typename reverse_graph::vertex_iterator> +vertices(const reverse_graph& g) +{ + return vertices(g.m_g); +} + +template +std::pair::edge_iterator, + typename reverse_graph::edge_iterator> +edges(const reverse_graph& g) +{ + return edges(g.m_g); +} + +template +inline std::pair +out_edges(const typename BidirectionalGraph::vertex_descriptor u, + const reverse_graph& g) +{ + return in_edges(u, g.m_g); +} + +template +inline typename BidirectionalGraph::vertices_size_type +num_vertices(const reverse_graph& g) +{ + return num_vertices(g.m_g); +} + +template +inline typename reverse_graph::edges_size_type +num_edges(const reverse_graph& g) +{ + return num_edges(g.m_g); +} + +template +inline typename BidirectionalGraph::degree_size_type +out_degree(const typename BidirectionalGraph::vertex_descriptor u, + const reverse_graph& g) +{ + return in_degree(u, g.m_g); +} + +template +inline std::pair +edge(const typename BidirectionalGraph::vertex_descriptor u, + const typename BidirectionalGraph::vertex_descriptor v, + const reverse_graph& g) +{ + return edge(v, u, g.m_g); +} + +template +inline std::pair +in_edges(const typename BidirectionalGraph::vertex_descriptor u, + const reverse_graph& g) +{ + return out_edges(u, g.m_g); +} + +template +inline std::pair::adjacency_iterator, + typename reverse_graph::adjacency_iterator> +adjacent_vertices(const typename BidirectionalGraph::vertex_descriptor u, + const reverse_graph& g) +{ + typedef reverse_graph Graph; + typename Graph::out_edge_iterator first, last; + tie(first, last) = out_edges(u, g); + typedef typename Graph::adjacency_iterator adjacency_iterator; + return std::make_pair(adjacency_iterator(first, const_cast(&g)), + adjacency_iterator(last, const_cast(&g))); +} + +template +inline typename BidirectionalGraph::degree_size_type +in_degree(const typename BidirectionalGraph::vertex_descriptor u, + const reverse_graph& g) +{ + return out_degree(u, g.m_g); +} + +template +inline typename graph_traits::vertex_descriptor +source(const Edge& e, const reverse_graph& g) +{ + return target(e, g.m_g); +} + +template +inline typename graph_traits::vertex_descriptor +target(const Edge& e, const reverse_graph& g) +{ + return source(e, g.m_g); +} + + +namespace detail { + + struct reverse_graph_vertex_property_selector { + template + struct bind_ { + typedef typename ReverseGraph::base_type Graph; + typedef property_map PMap; + typedef typename PMap::type type; + typedef typename PMap::const_type const_type; + }; + }; + + struct reverse_graph_edge_property_selector { + template + struct bind_ { + typedef typename ReverseGraph::base_type Graph; + typedef property_map PMap; + typedef typename PMap::type type; + typedef typename PMap::const_type const_type; + }; + }; + +} // namespace detail + +template <> +struct vertex_property_selector { + typedef detail::reverse_graph_vertex_property_selector type; +}; + +template <> +struct edge_property_selector { + typedef detail::reverse_graph_edge_property_selector type; +}; + +template +typename property_map::type +get(Property p, reverse_graph& g) +{ + return get(p, g.m_g); +} + +template +typename property_map::const_type +get(Property p, const reverse_graph& g) +{ + const BidirGraph& gref = g.m_g; // in case GRef is non-const + return get(p, gref); +} + +template +typename property_traits< + typename property_map::const_type +>::value_type +get(Property p, const reverse_graph& g, const Key& k) +{ + return get(p, g.m_g, k); +} + +template +void +put(Property p, const reverse_graph& g, const Key& k, + const Value& val) +{ + put(p, g.m_g, k, val); +} + +template +inline void +set_property(const reverse_graph& g, Tag tag, + const Value& value) +{ + set_property(g.m_g, tag, value); +} + +template +inline +typename graph_property::type +get_property(const reverse_graph& g, Tag tag) +{ + return get_property(g.m_g, tag); +} + +} // namespace boost + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +// Stay out of the way of the concept checking class +# undef BidirectionalGraph +#endif + +#endif diff --git a/win32/include/boost/graph/sequential_vertex_coloring.hpp b/win32/include/boost/graph/sequential_vertex_coloring.hpp new file mode 100755 index 000000000..a06712eac --- /dev/null +++ b/win32/include/boost/graph/sequential_vertex_coloring.hpp @@ -0,0 +1,124 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2004 The Trustees of Indiana University +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_SEQUENTIAL_VERTEX_COLORING_HPP +#define BOOST_GRAPH_SEQUENTIAL_VERTEX_COLORING_HPP + +#include +#include +#include +#include +#include + +#ifdef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +# include +#endif + +/* This algorithm is to find coloring of a graph + + Algorithm: + Let G = (V,E) be a graph with vertices (somehow) ordered v_1, v_2, ..., + v_n. For k = 1, 2, ..., n the sequential algorithm assigns v_k to the + smallest possible color. + + Reference: + + Thomas F. Coleman and Jorge J. More, Estimation of sparse Jacobian + matrices and graph coloring problems. J. Numer. Anal. V20, P187-209, 1983 + + v_k is stored as o[k] here. + + The color of the vertex v will be stored in color[v]. + i.e., vertex v belongs to coloring color[v] */ + +namespace boost { + template + typename property_traits::value_type + sequential_vertex_coloring(const VertexListGraph& G, OrderPA order, + ColorMap color) + { + typedef graph_traits GraphTraits; + typedef typename GraphTraits::vertex_descriptor Vertex; + typedef typename property_traits::value_type size_type; + + size_type max_color = 0; + const size_type V = num_vertices(G); + + // We need to keep track of which colors are used by + // adjacent vertices. We do this by marking the colors + // that are used. The mark array contains the mark + // for each color. The length of mark is the + // number of vertices since the maximum possible number of colors + // is the number of vertices. + std::vector mark(V, + std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()); + + //Initialize colors + typename GraphTraits::vertex_iterator v, vend; + for (tie(v, vend) = vertices(G); v != vend; ++v) + put(color, *v, V-1); + + //Determine the color for every vertex one by one + for ( size_type i = 0; i < V; i++) { + Vertex current = get(order,i); + typename GraphTraits::adjacency_iterator v, vend; + + //Mark the colors of vertices adjacent to current. + //i can be the value for marking since i increases successively + for (tie(v,vend) = adjacent_vertices(current, G); v != vend; ++v) + mark[get(color,*v)] = i; + + //Next step is to assign the smallest un-marked color + //to the current vertex. + size_type j = 0; + + //Scan through all useable colors, find the smallest possible + //color that is not used by neighbors. Note that if mark[j] + //is equal to i, color j is used by one of the current vertex's + //neighbors. + while ( j < max_color && mark[j] == i ) + ++j; + + if ( j == max_color ) //All colors are used up. Add one more color + ++max_color; + + //At this point, j is the smallest possible color + put(color, current, j); //Save the color of vertex current + } + + return max_color; + } + + template + typename property_traits::value_type + sequential_vertex_coloring(const VertexListGraph& G, ColorMap color) + { + typedef typename graph_traits::vertex_descriptor + vertex_descriptor; + typedef typename graph_traits::vertex_iterator + vertex_iterator; + + std::pair v = vertices(G); +#ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS + std::vector order(v.first, v.second); +#else + std::vector order; + order.reserve(std::distance(v.first, v.second)); + while (v.first != v.second) order.push_back(*v.first++); +#endif + return sequential_vertex_coloring + (G, + make_iterator_property_map + (order.begin(), identity_property_map(), + graph_traits::null_vertex()), + color); + } +} + +#endif diff --git a/win32/include/boost/graph/simple_point.hpp b/win32/include/boost/graph/simple_point.hpp new file mode 100755 index 000000000..63df03401 --- /dev/null +++ b/win32/include/boost/graph/simple_point.hpp @@ -0,0 +1,23 @@ +//======================================================================= +// Copyright 2005 Trustees of Indiana University +// Authors: Andrew Lumsdaine, Douglas Gregor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_SIMPLE_POINT_HPP +#define BOOST_GRAPH_SIMPLE_POINT_HPP + +namespace boost { + +template +struct simple_point +{ + T x; + T y; +}; + +} // end namespace boost + +#endif // BOOST_GRAPH_SIMPLE_POINT_HPP diff --git a/win32/include/boost/graph/sloan_ordering.hpp b/win32/include/boost/graph/sloan_ordering.hpp new file mode 100755 index 000000000..c24021528 --- /dev/null +++ b/win32/include/boost/graph/sloan_ordering.hpp @@ -0,0 +1,448 @@ +// +//======================================================================= +// Copyright 2002 Marc Wintermantel (wintermantel@even-ag.ch) +// ETH Zurich, Center of Structure Technologies (www.imes.ethz.ch/st) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +#ifndef BOOST_GRAPH_SLOAN_HPP +#define BOOST_GRAPH_SLOAN_HPP + +#define WEIGHT1 1 //default weight for the distance in the Sloan algorithm +#define WEIGHT2 2 //default weight for the degree in the Sloan algorithm +#define MAXINT 2147483647 //Maximum value for a 32bit integer + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +//////////////////////////////////////////////////////////// +// +//Sloan-Algorithm for graph reordering +//(optimzes profile and wavefront, not primiraly bandwidth +// +//////////////////////////////////////////////////////////// + +namespace boost { + + ///////////////////////////////////////////////////////////////////////// + // Function that returns the maximum depth of + // a rooted level strucutre (RLS) + // + ///////////////////////////////////////////////////////////////////////// + template + unsigned RLS_depth(Distance& d) + { + unsigned h_s = 0; + typename Distance::iterator iter; + + for (iter = d.begin(); iter != d.end(); ++iter) + { + if(*iter > h_s) + { + h_s = *iter; + } + } + + return h_s; + } + + + + ///////////////////////////////////////////////////////////////////////// + // Function that returns the width of the largest level of + // a rooted level strucutre (RLS) + // + ///////////////////////////////////////////////////////////////////////// + template + unsigned RLS_max_width(Distance& d, my_int depth) + { + + //Searching for the maximum width of a level + std::vector dummy_width(depth+1, 0); + std::vector::iterator my_it; + typename Distance::iterator iter; + unsigned w_max = 0; + + for (iter = d.begin(); iter != d.end(); ++iter) + { + dummy_width[*iter]++; + } + + for(my_it = dummy_width.begin(); my_it != dummy_width.end(); ++my_it) + { + if(*my_it > w_max) w_max = *my_it; + } + + return w_max; + + } + + + ///////////////////////////////////////////////////////////////////////// + // Function for finding a good starting node for Sloan algorithm + // + // This is to find a good starting node. "good" is in the sense + // of the ordering generated. + ///////////////////////////////////////////////////////////////////////// + template + typename graph_traits::vertex_descriptor + sloan_start_end_vertices(Graph& G, + typename graph_traits::vertex_descriptor &s, + ColorMap color, + DegreeMap degree) + { + typedef typename property_traits::value_type Degree; + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename std::vector< typename graph_traits::vertices_size_type>::iterator vec_iter; + typedef typename graph_traits::vertices_size_type size_type; + + typedef typename property_map::const_type VertexID; + + s = *(vertices(G).first); + Vertex e = s; + Vertex i; + unsigned my_degree = get(degree, s ); + unsigned dummy, h_i, h_s, w_i, w_e; + bool new_start = true; + unsigned maximum_degree = 0; + + //Creating a std-vector for storing the distance from the start vertex in dist + std::vector::vertices_size_type> dist(num_vertices(G), 0); + + //Wrap a property_map_iterator around the std::iterator + boost::iterator_property_map dist_pmap(dist.begin(), get(vertex_index, G)); + + //Creating a property_map for the indices of a vertex + typename property_map::type index_map = get(vertex_index, G); + + //Creating a priority queue + typedef indirect_cmp > Compare; + Compare comp(degree); + std::priority_queue, Compare> degree_queue(comp); + + //step 1 + //Scan for the vertex with the smallest degree and the maximum degree + typename graph_traits::vertex_iterator ui, ui_end; + for (tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) + { + dummy = get(degree, *ui); + + if(dummy < my_degree) + { + my_degree = dummy; + s = *ui; + } + + if(dummy > maximum_degree) + { + maximum_degree = dummy; + } + } + //end 1 + + do{ + new_start = false; //Setting the loop repetition status to false + + //step 2 + //initialize the the disance std-vector with 0 + for(typename std::vector::vertices_size_type>::iterator iter = dist.begin(); iter != dist.end(); ++iter) *iter = 0; + + //generating the RLS (rooted level structure) + breadth_first_search + (G, s, visitor + ( + make_bfs_visitor(record_distances(dist_pmap, on_tree_edge() ) ) + ) + ); + + //end 2 + + //step 3 + //calculating the depth of the RLS + h_s = RLS_depth(dist); + + //step 4 + //pushing one node of each degree in an ascending manner into degree_queue + std::vector shrink_trace(maximum_degree, false); + for (tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) + { + dummy = get(degree, *ui); + + if( (dist[index_map[*ui]] == h_s ) && ( !shrink_trace[ dummy ] ) ) + { + degree_queue.push(*ui); + shrink_trace[ dummy ] = true; + } + } + + //end 3 & 4 + + + //step 5 + //Initializing w + w_e = MAXINT; + //end 5 + + + //step 6 + //Testing for termination + while( !degree_queue.empty() ) + { + i = degree_queue.top(); //getting the node with the lowest degree from the degree queue + degree_queue.pop(); //ereasing the node with the lowest degree from the degree queue + + //generating a RLS + for(typename std::vector::vertices_size_type>::iterator iter = dist.begin(); iter != dist.end(); ++iter) *iter = 0; + + breadth_first_search + (G, i, boost::visitor + ( + make_bfs_visitor(record_distances(dist_pmap, on_tree_edge() ) ) + ) + ); + + //Calculating depth and width of the rooted level + h_i = RLS_depth(dist); + w_i = RLS_max_width(dist, h_i); + + //Testing for termination + if( (h_i > h_s) && (w_i < w_e) ) + { + h_s = h_i; + s = i; + while(!degree_queue.empty()) degree_queue.pop(); + new_start = true; + } + else if(w_i < w_e) + { + w_e = w_i; + e = i; + } + } + //end 6 + + }while(new_start); + + return e; + } + + ////////////////////////////////////////////////////////////////////////// + // Sloan algorithm with a given starting Vertex. + // + // This algorithm requires user to provide a starting vertex to + // compute Sloan ordering. + ////////////////////////////////////////////////////////////////////////// + template + OutputIterator + sloan_ordering(Graph& g, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor e, + OutputIterator permutation, + ColorMap color, + DegreeMap degree, + PriorityMap priority, + Weight W1, + Weight W2) + { + //typedef typename property_traits::value_type Degree; + typedef typename property_traits::value_type Degree; + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename std::vector::vertices_size_type>::iterator vec_iter; + typedef typename graph_traits::vertices_size_type size_type; + + typedef typename property_map::const_type VertexID; + + + //Creating a std-vector for storing the distance from the end vertex in it + typename std::vector::vertices_size_type> dist(num_vertices(g), 0); + + //Wrap a property_map_iterator around the std::iterator + boost::iterator_property_map dist_pmap(dist.begin(), get(vertex_index, g)); + + breadth_first_search + (g, e, visitor + ( + make_bfs_visitor(record_distances(dist_pmap, on_tree_edge() ) ) + ) + ); + + //Creating a property_map for the indices of a vertex + typename property_map::type index_map = get(vertex_index, g); + + //Sets the color and priority to their initial status + unsigned cdeg; + typename graph_traits::vertex_iterator ui, ui_end; + for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) + { + put(color, *ui, Color::white()); + cdeg=get(degree, *ui)+1; + put(priority, *ui, W1*dist[index_map[*ui]]-W2*cdeg ); + } + + //Priority list + typedef indirect_cmp > Compare; + Compare comp(priority); + std::list priority_list; + + //Some more declarations + typename graph_traits::out_edge_iterator ei, ei_end, ei2, ei2_end; + Vertex u, v, w; + + put(color, s, Color::green()); //Sets the color of the starting vertex to gray + priority_list.push_front(s); //Puts s into the priority_list + + while ( !priority_list.empty() ) + { + priority_list.sort(comp); //Orders the elements in the priority list in an ascending manner + + u = priority_list.front(); //Accesses the last element in the priority list + priority_list.pop_front(); //Removes the last element in the priority list + + if(get(color, u) == Color::green() ) + { + //for-loop over all out-edges of vertex u + for (tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) + { + v = target(*ei, g); + + put( priority, v, get(priority, v) + W2 ); //updates the priority + + if (get(color, v) == Color::white() ) //test if the vertex is inactive + { + put(color, v, Color::green() ); //giving the vertex a preactive status + priority_list.push_front(v); //writing the vertex in the priority_queue + } + } + } + + //Here starts step 8 + *permutation++ = u; //Puts u to the first position in the permutation-vector + put(color, u, Color::black() ); //Gives u an inactive status + + //for loop over all the adjacent vertices of u + for (tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) { + + v = target(*ei, g); + + if (get(color, v) == Color::green() ) { //tests if the vertex is inactive + + put(color, v, Color::red() ); //giving the vertex an active status + put(priority, v, get(priority, v)+W2); //updates the priority + + //for loop over alll adjacent vertices of v + for (tie(ei2, ei2_end) = out_edges(v, g); ei2 != ei2_end; ++ei2) { + w = target(*ei2, g); + + if(get(color, w) != Color::black() ) { //tests if vertex is postactive + + put(priority, w, get(priority, w)+W2); //updates the priority + + if(get(color, w) == Color::white() ){ + + put(color, w, Color::green() ); // gives the vertex a preactive status + priority_list.push_front(w); // puts the vertex into the priority queue + + } //end if + + } //end if + + } //end for + + } //end if + + } //end for + + } //end while + + + return permutation; + } + + ///////////////////////////////////////////////////////////////////////////////////////// + // Same algorithm as before, but without the weights given (taking default weights + template + OutputIterator + sloan_ordering(Graph& g, + typename graph_traits::vertex_descriptor s, + typename graph_traits::vertex_descriptor e, + OutputIterator permutation, + ColorMap color, + DegreeMap degree, + PriorityMap priority) + { + return sloan_ordering(g, s, e, permutation, color, degree, priority, WEIGHT1, WEIGHT2); + } + + + ////////////////////////////////////////////////////////////////////////// + // Sloan algorithm without a given starting Vertex. + // + // This algorithm finds a good starting vertex itself to + // compute Sloan-ordering. + ////////////////////////////////////////////////////////////////////////// + + + + template < class Graph, class OutputIterator, + class Color, class Degree, + class Priority, class Weight> + inline OutputIterator + sloan_ordering(Graph& G, + OutputIterator permutation, + Color color, + Degree degree, + Priority priority, + Weight W1, + Weight W2 ) + { + typedef typename boost::graph_traits::vertex_descriptor Vertex; + + Vertex s, e; + e = sloan_start_end_vertices(G, s, color, degree); + + return sloan_ordering(G, s, e, permutation, color, degree, priority, W1, W2); + } + + ///////////////////////////////////////////////////////////////////////////////////////// + // Same as before, but without given weights (default weights are taken instead) + template < class Graph, class OutputIterator, + class Color, class Degree, + class Priority > + inline OutputIterator + sloan_ordering(Graph& G, + OutputIterator permutation, + Color color, + Degree degree, + Priority priority) + { + return sloan_ordering(G, permutation, color, degree, priority, WEIGHT1, WEIGHT2); + } + + +} // namespace boost + + +#endif // BOOST_GRAPH_SLOAN_HPP diff --git a/win32/include/boost/graph/small_world_generator.hpp b/win32/include/boost/graph/small_world_generator.hpp new file mode 100755 index 000000000..8ae3e4df5 --- /dev/null +++ b/win32/include/boost/graph/small_world_generator.hpp @@ -0,0 +1,114 @@ +// Copyright 2004 The Trustees of Indiana University. + +// 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) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_SMALL_WORLD_GENERATOR_HPP +#define BOOST_GRAPH_SMALL_WORLD_GENERATOR_HPP + +#include +#include +#include +#include + +namespace boost { + + // Assumes undirected + template + class small_world_iterator + { + typedef typename graph_traits::vertices_size_type + vertices_size_type; + + public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef void difference_type; + + small_world_iterator() : gen(0) {} + small_world_iterator(RandomGenerator& gen, vertices_size_type n, + vertices_size_type k, double prob = 0.0, + bool allow_self_loops = false) + : gen(&gen), n(n), k(k), prob(prob), source(0), + target(allow_self_loops? 0 : 1), + allow_self_loops(allow_self_loops), + current(0, allow_self_loops? 0 : 1) + { } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + small_world_iterator& operator++() + { + target = (target + 1) % n; + if (target == (source + k/2 + 1) % n) { + ++source; + if (allow_self_loops) target = source; + else target = (source + 1) % n; + } + current.first = source; + + uniform_01 rand01(*gen); + uniform_int rand_vertex_gen(0, n-1); + double x = rand01(); + *gen = rand01.base(); // GRRRR + if (x < prob) { + vertices_size_type lower = (source + n - k/2) % n; + vertices_size_type upper = (source + k/2) % n; + do { + current.second = rand_vertex_gen(*gen); + } while (current.second >= lower && current.second <= upper + || (upper < lower + && (current.second >= lower || current.second <= upper))); + } else { + current.second = target; + } + return *this; + } + + small_world_iterator operator++(int) + { + small_world_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const small_world_iterator& other) const + { + if (!gen && other.gen) return other == *this; + else if (gen && !other.gen) return source == n; + else if (!gen && !other.gen) return true; + return source == other.source && target == other.target; + } + + bool operator!=(const small_world_iterator& other) const + { return !(*this == other); } + + private: + void next() + { + uniform_int rand_vertex(0, n-1); + current.first = rand_vertex(*gen); + do { + current.second = rand_vertex(*gen); + } while (current.first == current.second && !allow_self_loops); + } + + RandomGenerator* gen; + vertices_size_type n; + vertices_size_type k; + double prob; + vertices_size_type source; + vertices_size_type target; + bool allow_self_loops; + value_type current; + }; + +} // end namespace boost + +#endif // BOOST_GRAPH_SMALL_WORLD_GENERATOR_HPP diff --git a/win32/include/boost/graph/smallest_last_ordering.hpp b/win32/include/boost/graph/smallest_last_ordering.hpp new file mode 100755 index 000000000..2753fa158 --- /dev/null +++ b/win32/include/boost/graph/smallest_last_ordering.hpp @@ -0,0 +1,122 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// 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) +//======================================================================= + +// Revision History: +// 17 March 2006: Fixed a bug: when updating the degree a vertex +// could be moved to a wrong bucket. (Roman Dementiev) +// + + + +#ifndef BOOST_SMALLEST_LAST_VERTEX_ORDERING_HPP +#define BOOST_SMALLEST_LAST_VERTEX_ORDERING_HPP +/* + The smallest-last ordering is defined for the loopless graph G with + vertices a(j), j = 1,2,...,n where a(j) is the j-th column of A and + with edge (a(i),a(j)) if and only if columns i and j have a + non-zero in the same row position. The smallest-last ordering is + determined recursively by letting list(k), k = n,...,1 be a column + with least degree in the subgraph spanned by the un-ordered + columns. + */ +#include +#include +#include +#include +#include + +namespace boost { + + template + void + smallest_last_vertex_ordering(const VertexListGraph& G, Order order, + Degree degree, Marker marker) { + typedef typename boost::graph_traits GraphTraits; + typedef typename GraphTraits::vertex_descriptor Vertex; + //typedef typename GraphTraits::size_type size_type; + typedef std::size_t size_type; + + const size_type num = num_vertices(G); + + typedef typename boost::detail::vertex_property_map::type ID; + typedef bucket_sorter BucketSorter; + + BucketSorter degree_bucket_sorter(num, num, degree, + get(vertex_index,G)); + + smallest_last_vertex_ordering(G, order, degree, marker, degree_bucket_sorter); + } + + template + void + smallest_last_vertex_ordering(const VertexListGraph& G, Order order, + Degree degree, Marker marker, + BucketSorter& degree_buckets) { + typedef typename boost::graph_traits GraphTraits; + typedef typename GraphTraits::vertex_descriptor Vertex; + //typedef typename GraphTraits::size_type size_type; + typedef std::size_t size_type; + + const size_type num = num_vertices(G); + + typename GraphTraits::vertex_iterator v, vend; + for (boost::tie(v, vend) = vertices(G); v != vend; ++v) { + put(marker, *v, num); + put(degree, *v, out_degree(*v, G)); + degree_buckets.push(*v); + } + + size_type minimum_degree = 0; + size_type current_order = num - 1; + + while ( 1 ) { + typedef typename BucketSorter::stack MDStack; + MDStack minimum_degree_stack = degree_buckets[minimum_degree]; + while (minimum_degree_stack.empty()) + minimum_degree_stack = degree_buckets[++minimum_degree]; + + Vertex node = minimum_degree_stack.top(); + put(order, current_order, node); + + if ( current_order == 0 ) //find all vertices + break; + + minimum_degree_stack.pop(); + put(marker, node, 0); //node has been ordered. + + typename GraphTraits::adjacency_iterator v, vend; + for (boost::tie(v,vend) = adjacent_vertices(node, G); v != vend; ++v) + + if ( get(marker,*v) > current_order ) { //*v is unordered vertex + put(marker, *v, current_order); //mark the columns adjacent to node + + //delete *v from the bucket sorter + degree_buckets.remove(*v); + + //It is possible minimum degree goes down + //Here we keep tracking it. + put(degree, *v, get(degree, *v) - 1); + BOOST_USING_STD_MIN(); + minimum_degree = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_degree, get(degree, *v)); + + //reinsert *v in the bucket sorter with the new degree + degree_buckets.push(*v); + } + + current_order--; + } + + //at this point, order[i] = v_i; + } + +} + +#endif + diff --git a/win32/include/boost/graph/stanford_graph.hpp b/win32/include/boost/graph/stanford_graph.hpp new file mode 100755 index 000000000..e18384dd9 --- /dev/null +++ b/win32/include/boost/graph/stanford_graph.hpp @@ -0,0 +1,565 @@ +//======================================================================= +// Copyright 1997-2001 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_SGB_GRAPH_HPP +#define BOOST_GRAPH_SGB_GRAPH_HPP + +#include +#include +#include +#include +#include +#include + +// Thanks to Andreas Scherer for numerous suggestions and fixes! + +// This file adapts a Stanford GraphBase (SGB) Graph pointer into a +// VertexListGraph. Note that a graph adaptor class is not needed, +// SGB's Graph* is used as is. The VertexListGraph concept is fulfilled by +// defining the appropriate non-member functions for Graph*. +// +// The PROTOTYPES change file extensions to SGB must be applied so +// that the SGB functions have real prototypes which are necessary for +// the C++ compiler. To apply the PROTOTYPES extensions, before you do +// "make tests install" for SGB do "ln -s PROTOTYPES/* ." to the SGB +// root directory (or just copy all the files from the PROTOTYPES +// directory to the SGB root directory). +// +extern "C" { + // We include all global definitions for the general stuff + // of The Stanford GraphBase and its various graph generator + // functions by reading all SGB headerfiles as in section 2 of + // the "test_sample" program. +#include /* SGB data structures */ +#include /* SGB input/output routines */ +#include /* random number generator */ +#include /* routines for shortest paths */ +#include /* the basic graph operations */ +#undef empty /* avoid name clash with C++ standard library */ + inline Graph* empty( long n ) /* and provide workaround */ + { return board(n,0L,0L,0L,2L,0L,0L); } +#include /* graphs based on literature */ +#include /* graphs based on economic data */ +#include /* graphs based on football scores */ +#include /* graphs based on logic circuits */ +#undef val /* avoid name clash with g++ headerfile stl_tempbuf.h */ + // val ==> Vertex::x.I +#include /* graphs based on Mona Lisa */ +#include /* graphs based on mileage data */ +#include /* planar graphs */ +#include /* Ramanujan graphs */ +#include /* random graphs */ +#include /* graphs based on Roget's Thesaurus */ +#include /* we save results in ASCII format */ +#include /* five-letter-word graphs */ +#undef weight /* avoid name clash with BGL parameter */ + // weight ==> Vertex::u.I +} + +namespace boost { + class sgb_edge; +} + +class sgb_out_edge_iterator; +class sgb_adj_iterator; +class sgb_vertex_iterator; + +namespace boost { + typedef Graph* sgb_graph_ptr; + typedef const Graph* sgb_const_graph_ptr; + + struct sgb_traversal_tag : + public virtual vertex_list_graph_tag, + public virtual incidence_graph_tag, + public virtual adjacency_graph_tag { }; + + template <> struct graph_traits { + typedef Vertex* vertex_descriptor; + typedef boost::sgb_edge edge_descriptor; + typedef sgb_out_edge_iterator out_edge_iterator; + typedef void in_edge_iterator; + typedef sgb_adj_iterator adjacency_iterator; + typedef sgb_vertex_iterator vertex_iterator; + typedef void edge_iterator; + typedef long vertices_size_type; + typedef long edge_size_type; + typedef long degree_size_type; + typedef directed_tag directed_category; + typedef sgb_traversal_tag traversal_category; + typedef allow_parallel_edge_tag edge_parallel_category; + }; + template <> struct graph_traits { + typedef Vertex* vertex_descriptor; + typedef boost::sgb_edge edge_descriptor; + typedef sgb_out_edge_iterator out_edge_iterator; + typedef void in_edge_iterator; + typedef sgb_adj_iterator adjacency_iterator; + typedef sgb_vertex_iterator vertex_iterator; + typedef void edge_iterator; + typedef long vertices_size_type; + typedef long edge_size_type; + typedef long degree_size_type; + typedef directed_tag directed_category; + typedef sgb_traversal_tag traversal_category; + typedef allow_parallel_edge_tag edge_parallel_category; + }; +} + +namespace boost { + + struct edge_length_t { + typedef edge_property_tag kind; + }; + + // We could just use Arc* as the edge descriptor type, but + // we want to add the source(e,g) function which requires + // that we carry along a pointer to the source vertex. + class sgb_edge { + typedef sgb_edge self; + public: + sgb_edge() : _arc(0), _src(0) { } + sgb_edge(Arc* a, Vertex* s) : _arc(a), _src(s) { } + friend Vertex* source(self e, sgb_const_graph_ptr) { return e._src; } + friend Vertex* target(self e, sgb_const_graph_ptr) { return e._arc->tip; } + friend bool operator==(const self& a, const self& b) { + return a._arc == b._arc; } + friend bool operator!=(const self& a, const self& b) { + return a._arc != b._arc; } +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + template friend class sgb_edge_length_map; + template friend class sgb_edge_util_map; + friend long get(edge_length_t, const sgb_graph_ptr&, const sgb_edge& key); + friend long get(edge_length_t, const sgb_const_graph_ptr&, const sgb_edge& key); + friend void put(edge_length_t, sgb_graph_ptr&, const sgb_edge& key, long value); + protected: +#endif + Arc* _arc; + Vertex* _src; + }; +} // namespace boost + + class sgb_out_edge_iterator + : public boost::forward_iterator_helper< + sgb_out_edge_iterator, boost::sgb_edge, + std::ptrdiff_t, boost::sgb_edge*, boost::sgb_edge> + { + typedef sgb_out_edge_iterator self; + public: + sgb_out_edge_iterator() : _src(0), _arc(0) {} + sgb_out_edge_iterator(Vertex* s, Arc* d) : _src(s), _arc(d) {} + boost::sgb_edge operator*() { return boost::sgb_edge(_arc, _src); } + self& operator++() { _arc = _arc->next; return *this; } + friend bool operator==(const self& x, const self& y) { + return x._arc == y._arc; } + protected: + Vertex* _src; + Arc* _arc; + }; + + class sgb_adj_iterator + : public boost::forward_iterator_helper< + sgb_adj_iterator, Vertex*, std::ptrdiff_t, Vertex**,Vertex*> + { + typedef sgb_adj_iterator self; + public: + sgb_adj_iterator() : _arc(0) {} + sgb_adj_iterator(Arc* d) : _arc(d) {} + Vertex* operator*() { return _arc->tip; } + self& operator++() { _arc = _arc->next; return *this; } + friend bool operator==(const self& x, const self& y) { + return x._arc == y._arc; } + protected: + Arc* _arc; + }; + + // The reason we have this instead of just using Vertex* is that we + // want to use Vertex* as the vertex_descriptor instead of just + // Vertex, which avoids problems with boost passing vertex descriptors + // by value and how that interacts with the sgb_vertex_id_map. + class sgb_vertex_iterator + : public boost::forward_iterator_helper< + sgb_vertex_iterator, Vertex*, std::ptrdiff_t, Vertex**, Vertex*> + { + typedef sgb_vertex_iterator self; + public: + sgb_vertex_iterator() : _v(0) { } + sgb_vertex_iterator(Vertex* v) : _v(v) { } + Vertex* operator*() { return _v; } + self& operator++() { ++_v; return *this; } + friend bool operator==(const self& x, const self& y) { + return x._v == y._v; } + protected: + Vertex* _v; + }; + +namespace boost { + + inline std::pair + vertices(sgb_const_graph_ptr g) + { + return std::make_pair(sgb_vertex_iterator(g->vertices), + sgb_vertex_iterator(g->vertices + g->n)); + } + + inline std::pair + out_edges(Vertex* u, sgb_const_graph_ptr) + { + return std::make_pair( sgb_out_edge_iterator(u, u->arcs), + sgb_out_edge_iterator(u, 0) ); + } + + inline boost::graph_traits::degree_size_type + out_degree(Vertex* u, sgb_const_graph_ptr g) + { + boost::graph_traits::out_edge_iterator i, i_end; + boost::tie(i, i_end) = out_edges(u, g); + return std::distance(i, i_end); + } + + // in_edges? + + inline std::pair + adjacent_vertices(Vertex* u, sgb_const_graph_ptr) + { + return std::make_pair( sgb_adj_iterator(u->arcs), + sgb_adj_iterator(0) ); + } + + inline long num_vertices(sgb_const_graph_ptr g) { return g->n; } + inline long num_edges(sgb_const_graph_ptr g) { return g->m; } + + inline Vertex* vertex(long v, sgb_const_graph_ptr g) + { return g->vertices + v; } + + // Various Property Maps + + // Vertex ID + class sgb_vertex_id_map + : public boost::put_get_helper + { + public: + typedef boost::readable_property_map_tag category; + typedef long value_type; + typedef long reference; + typedef Vertex* key_type; + sgb_vertex_id_map() : _g(0) { } + sgb_vertex_id_map(sgb_graph_ptr g) : _g(g) { } + long operator[](Vertex* v) const { return v - _g->vertices; } + protected: + sgb_graph_ptr _g; + }; + inline sgb_vertex_id_map get(vertex_index_t, sgb_graph_ptr g) { + return sgb_vertex_id_map(g); + } + + // Vertex Name + class sgb_vertex_name_map + : public boost::put_get_helper + { + public: + typedef boost::readable_property_map_tag category; + typedef char* value_type; + typedef char* reference; + typedef Vertex* key_type; + char* operator[](Vertex* v) const { return v->name; } + }; + inline sgb_vertex_name_map get(vertex_name_t, sgb_graph_ptr) { + return sgb_vertex_name_map(); + } + + // Vertex Property Tags +#define SGB_PROPERTY_TAG(KIND,TAG) \ + template struct TAG##_property { \ + typedef KIND##_property_tag kind; \ + typedef T type; \ + }; + SGB_PROPERTY_TAG(vertex, u) + SGB_PROPERTY_TAG(vertex, v) + SGB_PROPERTY_TAG(vertex, w) + SGB_PROPERTY_TAG(vertex, x) + SGB_PROPERTY_TAG(vertex, y) + SGB_PROPERTY_TAG(vertex, z) + + // Edge Property Tags + SGB_PROPERTY_TAG(edge, a) + SGB_PROPERTY_TAG(edge, b) + + // Various Utility Maps + + // helpers + inline Vertex*& get_util(util& u, Vertex*) { return u.V; } + inline Arc*& get_util(util& u, Arc*) { return u.A; } + inline sgb_graph_ptr& get_util(util& u, sgb_graph_ptr) { return u.G; } + inline char*& get_util(util& u, char*) { return u.S; } + inline long& get_util(util& u, long) { return u.I; } + +#define SGB_GET_UTIL_FIELD(KIND,X) \ + template \ + inline T& get_util_field(KIND* k, X##_property) { \ + return get_util(k->X, T()); } + + SGB_GET_UTIL_FIELD(Vertex, u) + SGB_GET_UTIL_FIELD(Vertex, v) + SGB_GET_UTIL_FIELD(Vertex, w) + SGB_GET_UTIL_FIELD(Vertex, x) + SGB_GET_UTIL_FIELD(Vertex, y) + SGB_GET_UTIL_FIELD(Vertex, z) + + SGB_GET_UTIL_FIELD(Arc, a) + SGB_GET_UTIL_FIELD(Arc, b) + + // Vertex Utility Map + template + class sgb_vertex_util_map + : public boost::put_get_helper > + { + public: + typedef boost::lvalue_property_map_tag category; + typedef typename Tag::type value_type; + typedef Vertex* key_type; + typedef Ref reference; + reference operator[](Vertex* v) const { + return get_util_field(v, Tag()); + } + }; + + // Edge Utility Map + template + class sgb_edge_util_map + : public boost::put_get_helper > + { + public: + typedef boost::lvalue_property_map_tag category; + typedef typename Tag::type value_type; + typedef Vertex* key_type; + typedef Ref reference; + reference operator[](const sgb_edge& e) const { + return get_util_field(e._arc, Tag()); + } + }; + +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + template + inline sgb_vertex_util_map + get_property_map(Tag, const sgb_graph_ptr& g, vertex_property_tag) { + return sgb_vertex_util_map(); + } + template + inline sgb_vertex_util_map + get_property_map(Tag, sgb_graph_ptr& g, vertex_property_tag) { + return sgb_vertex_util_map(); + } + + template + inline sgb_edge_util_map + get_property_map(Tag, const sgb_graph_ptr& g, edge_property_tag) { + return sgb_edge_util_map(); + } + template + inline sgb_edge_util_map + get_property_map(Tag, sgb_graph_ptr& g, edge_property_tag) { + return sgb_edge_util_map(); + } + +#endif // ! BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // Edge Length Access + template + class sgb_edge_length_map + : public boost::put_get_helper > + { + public: + typedef boost::lvalue_property_map_tag category; + typedef long value_type; + typedef sgb_edge key_type; + typedef Ref reference; + reference operator[](const sgb_edge& e) const { + return e._arc->len; + } + }; + + inline sgb_edge_length_map + get(edge_length_t, const sgb_graph_ptr&) { + return sgb_edge_length_map(); + } + inline sgb_edge_length_map + get(edge_length_t, const sgb_const_graph_ptr&) { + return sgb_edge_length_map(); + } + inline sgb_edge_length_map + get(edge_length_t, sgb_graph_ptr&) { + return sgb_edge_length_map(); + } + inline long + get(edge_length_t, const sgb_graph_ptr&, const sgb_edge& key) { + return key._arc->len; + } + inline long + get(edge_length_t, const sgb_const_graph_ptr&, const sgb_edge& key) { + return key._arc->len; + } + inline void + put(edge_length_t, sgb_graph_ptr&, const sgb_edge& key, long value) + { + key._arc->len = value; + } + + // Property Map Traits Classes + template <> + struct property_map { + typedef sgb_edge_length_map type; + typedef sgb_edge_length_map const_type; + }; + template <> + struct property_map { + typedef sgb_vertex_id_map type; + typedef sgb_vertex_id_map const_type; + }; + template <> + struct property_map { + typedef sgb_vertex_name_map type; + typedef sgb_vertex_name_map const_type; + }; + + template <> + struct property_map { + typedef sgb_edge_length_map const_type; + }; + template <> + struct property_map { + typedef sgb_vertex_id_map const_type; + }; + template <> + struct property_map { + typedef sgb_vertex_name_map const_type; + }; + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + namespace detail { + template + struct sgb_choose_property_map { }; + template + struct sgb_choose_property_map { + typedef typename PropertyTag::type value_type; + typedef sgb_vertex_util_map type; + typedef sgb_vertex_util_map const_type; + }; + template + struct sgb_choose_property_map { + typedef typename PropertyTag::type value_type; + typedef sgb_edge_util_map type; + typedef sgb_edge_util_map const_type; + }; + } // namespace detail + template + struct property_map { + typedef typename property_kind::type Kind; + typedef detail::sgb_choose_property_map Choice; + typedef typename Choice::type type; + typedef typename Choice::const_type const_type; + }; + template + struct property_map { + typedef typename property_kind::type Kind; + typedef detail::sgb_choose_property_map Choice; + typedef typename Choice::const_type const_type; + }; + +#define SGB_UTIL_ACCESSOR(KIND,X) \ + template \ + inline sgb_##KIND##_util_map< X##_property, T&> \ + get(X##_property, sgb_graph_ptr&) { \ + return sgb_##KIND##_util_map< X##_property, T&>(); \ + } \ + template \ + inline sgb_##KIND##_util_map< X##_property, const T&> \ + get(X##_property, const sgb_graph_ptr&) { \ + return sgb_##KIND##_util_map< X##_property, const T&>(); \ + } \ + template \ + inline sgb_##KIND##_util_map< X##_property, const T&> \ + get(X##_property, const sgb_const_graph_ptr&) { \ + return sgb_##KIND##_util_map< X##_property, const T&>(); \ + } \ + template \ + inline typename \ + sgb_##KIND##_util_map< X##_property, const T&>::value_type \ + get(X##_property, const sgb_graph_ptr&, const Key& key) { \ + return sgb_##KIND##_util_map< X##_property, const T&>()[key]; \ + } \ + template \ + inline typename \ + sgb_##KIND##_util_map< X##_property, const T&>::value_type \ + get(X##_property, const sgb_const_graph_ptr&, const Key& key) { \ + return sgb_##KIND##_util_map< X##_property, const T&>()[key]; \ + } \ + template \ + inline void \ + put(X##_property, sgb_graph_ptr&, const Key& key, const Value& value) { \ + sgb_##KIND##_util_map< X##_property, T&>()[key] = value; \ + } + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#define SGB_UTIL_ACCESSOR_TYPE(KIND,TAG,TYPE) \ + inline sgb_##KIND##_util_map< TAG, TYPE& > \ + get(TAG, sgb_graph_ptr&) { \ + return sgb_##KIND##_util_map< TAG, TYPE& >(); \ + } \ + inline sgb_##KIND##_util_map< TAG, const TYPE& > \ + get(TAG, const sgb_graph_ptr&) { \ + return sgb_##KIND##_util_map< TAG, const TYPE& >(); \ + } \ + inline sgb_##KIND##_util_map< TAG, const TYPE& > \ + get(TAG, const sgb_const_graph_ptr&) { \ + return sgb_##KIND##_util_map< TAG, const TYPE& >(); \ + } \ + template \ + inline typename sgb_##KIND##_util_map< TAG, const TYPE& >::value_type \ + get(TAG, const sgb_graph_ptr&, const Key& key) { \ + return sgb_##KIND##_util_map< TAG, const TYPE& >()[key]; \ + } \ + template \ + inline typename sgb_##KIND##_util_map< TAG, const TYPE& >::value_type \ + get(TAG, const sgb_const_graph_ptr&, const Key& key) { \ + return sgb_##KIND##_util_map< TAG, const TYPE& >()[key]; \ + } \ + template \ + inline void \ + put(TAG, sgb_graph_ptr&, const Key& key, const Value& value) { \ + sgb_##KIND##_util_map< TAG, TYPE& >()[key] = value; \ + } \ + template <> struct property_map > { \ + typedef sgb_##KIND##_util_map< TAG, TYPE&> type; \ + typedef sgb_##KIND##_util_map< TAG, const TYPE&> const_type; \ + } + +#define SGB_UTIL_ACCESSOR(KIND,TAG) \ + SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, Vertex*); \ + SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, Arc*); \ + SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, sgb_graph_ptr); \ + SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, long); \ + SGB_UTIL_ACCESSOR_TYPE(KIND, TAG##_property, char*); + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + SGB_UTIL_ACCESSOR(vertex, u) + SGB_UTIL_ACCESSOR(vertex, v) + SGB_UTIL_ACCESSOR(vertex, w) + SGB_UTIL_ACCESSOR(vertex, x) + SGB_UTIL_ACCESSOR(vertex, y) + SGB_UTIL_ACCESSOR(vertex, z) + + SGB_UTIL_ACCESSOR(edge, a) + SGB_UTIL_ACCESSOR(edge, b) + +} // namespace boost + +#endif // BOOST_GRAPH_SGB_GRAPH_HPP diff --git a/win32/include/boost/graph/strong_components.hpp b/win32/include/boost/graph/strong_components.hpp new file mode 100755 index 000000000..7fdfcdb77 --- /dev/null +++ b/win32/include/boost/graph/strong_components.hpp @@ -0,0 +1,334 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +#ifndef BOOST_GRAPH_STRONG_COMPONENTS_HPP +#define BOOST_GRAPH_STRONG_COMPONENTS_HPP + +#include +#include +#include +#include +#include + +namespace boost { + + //========================================================================== + // This is Tarjan's algorithm for strongly connected components + // from his paper "Depth first search and linear graph algorithms". + // It calculates the components in a single application of DFS. + // We implement the algorithm as a dfs-visitor. + + namespace detail { + + template + class tarjan_scc_visitor : public dfs_visitor<> + { + typedef typename property_traits::value_type comp_type; + typedef typename property_traits::value_type time_type; + public: + tarjan_scc_visitor(ComponentMap comp_map, RootMap r, DiscoverTime d, + comp_type& c_, Stack& s_) + : c(c_), comp(comp_map), root(r), discover_time(d), + dfs_time(time_type()), s(s_) { } + + template + void discover_vertex(typename graph_traits::vertex_descriptor v, + const Graph&) { + put(root, v, v); + put(comp, v, (std::numeric_limits::max)()); + put(discover_time, v, dfs_time++); + s.push(v); + } + template + void finish_vertex(typename graph_traits::vertex_descriptor v, + const Graph& g) { + typename graph_traits::vertex_descriptor w; + typename graph_traits::out_edge_iterator ei, ei_end; + for (tie(ei, ei_end) = out_edges(v, g); ei != ei_end; ++ei) { + w = target(*ei, g); + if (get(comp, w) == (std::numeric_limits::max)()) + put(root, v, this->min_discover_time(get(root,v), get(root,w))); + } + if (get(root, v) == v) { + do { + w = s.top(); s.pop(); + put(comp, w, c); + } while (w != v); + ++c; + } + } + private: + template + Vertex min_discover_time(Vertex u, Vertex v) { + return get(discover_time, u) < get(discover_time,v) ? u : v; + } + + comp_type& c; + ComponentMap comp; + RootMap root; + DiscoverTime discover_time; + time_type dfs_time; + Stack& s; + }; + + template + typename property_traits::value_type + strong_components_impl + (const Graph& g, // Input + ComponentMap comp, // Output + // Internal record keeping + RootMap root, + DiscoverTime discover_time, + const bgl_named_params& params) + { + typedef typename graph_traits::vertex_descriptor Vertex; + function_requires< ReadWritePropertyMapConcept >(); + function_requires< ReadWritePropertyMapConcept >(); + typedef typename property_traits::value_type RootV; + function_requires< ConvertibleConcept >(); + function_requires< ReadWritePropertyMapConcept >(); + + typename property_traits::value_type total = 0; + + std::stack s; + detail::tarjan_scc_visitor > + vis(comp, root, discover_time, total, s); + depth_first_search(g, params.visitor(vis)); + return total; + } + + //------------------------------------------------------------------------- + // The dispatch functions handle the defaults for the rank and discover + // time property maps. + // dispatch with class specialization to avoid VC++ bug + + template + struct strong_comp_dispatch2 { + template + inline static typename property_traits::value_type + apply(const Graph& g, + ComponentMap comp, + RootMap r_map, + const bgl_named_params& params, + DiscoverTimeMap time_map) + { + return strong_components_impl(g, comp, r_map, time_map, params); + } + }; + + + template <> + struct strong_comp_dispatch2 { + template + inline static typename property_traits::value_type + apply(const Graph& g, + ComponentMap comp, + RootMap r_map, + const bgl_named_params& params, + detail::error_property_not_found) + { + typedef typename graph_traits::vertices_size_type size_type; + size_type n = num_vertices(g) > 0 ? num_vertices(g) : 1; + std::vector time_vec(n); + return strong_components_impl + (g, comp, r_map, + make_iterator_property_map(time_vec.begin(), choose_const_pmap + (get_param(params, vertex_index), + g, vertex_index), time_vec[0]), + params); + } + }; + + template + inline typename property_traits::value_type + scc_helper2(const Graph& g, + ComponentMap comp, + RootMap r_map, + const bgl_named_params& params, + DiscoverTimeMap time_map) + { + return strong_comp_dispatch2::apply(g, comp, r_map, params, time_map); + } + + template + struct strong_comp_dispatch1 { + + template + inline static typename property_traits::value_type + apply(const Graph& g, + ComponentMap comp, + const bgl_named_params& params, + RootMap r_map) + { + return scc_helper2(g, comp, r_map, params, get_param(params, vertex_discover_time)); + } + }; + template <> + struct strong_comp_dispatch1 { + + template + inline static typename property_traits::value_type + apply(const Graph& g, + ComponentMap comp, + const bgl_named_params& params, + detail::error_property_not_found) + { + typedef typename graph_traits::vertex_descriptor Vertex; + typename std::vector::size_type + n = num_vertices(g) > 0 ? num_vertices(g) : 1; + std::vector root_vec(n); + return scc_helper2 + (g, comp, + make_iterator_property_map(root_vec.begin(), choose_const_pmap + (get_param(params, vertex_index), + g, vertex_index), root_vec[0]), + params, + get_param(params, vertex_discover_time)); + } + }; + + template + inline typename property_traits::value_type + scc_helper1(const Graph& g, + ComponentMap comp, + const bgl_named_params& params, + RootMap r_map) + { + return detail::strong_comp_dispatch1::apply(g, comp, params, + r_map); + } + + } // namespace detail + + template + inline typename property_traits::value_type + strong_components(const Graph& g, ComponentMap comp, + const bgl_named_params& params) + { + typedef typename graph_traits::directed_category DirCat; + BOOST_STATIC_ASSERT((is_convertible::value == true)); + return detail::scc_helper1(g, comp, params, + get_param(params, vertex_root_t())); + } + + template + inline typename property_traits::value_type + strong_components(const Graph& g, ComponentMap comp) + { + typedef typename graph_traits::directed_category DirCat; + BOOST_STATIC_ASSERT((is_convertible::value == true)); + bgl_named_params params(0); + return strong_components(g, comp, params); + } + + template + void build_component_lists + (const Graph& g, + typename graph_traits::vertices_size_type num_scc, + ComponentMap component_number, + ComponentLists& components) + { + components.resize(num_scc); + typename graph_traits::vertex_iterator vi, vi_end; + for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + components[component_number[*vi]].push_back(*vi); + } + + +} // namespace boost + +#include +#include +#include +#include +#include // for components_recorder + +namespace boost { + + //========================================================================== + // This is the version of strongly connected components from + // "Intro. to Algorithms" by Cormen, Leiserson, Rivest, which was + // adapted from "Data Structure and Algorithms" by Aho, Hopcroft, + // and Ullman, who credit the algorithm to S.R. Kosaraju and M. Sharir. + // The algorithm is based on computing DFS forests the graph + // and its transpose. + + // This algorithm is slower than Tarjan's by a constant factor, uses + // more memory, and puts more requirements on the graph type. + + template + typename property_traits::value_type + kosaraju_strong_components(Graph& G, ComponentsMap c, + FinishTime finish_time, ColorMap color) + { + function_requires< MutableGraphConcept >(); + // ... + + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + typename property_traits::value_type time = 0; + depth_first_search + (G, make_dfs_visitor(stamp_times(finish_time, time, on_finish_vertex())), + color); + + Graph G_T(num_vertices(G)); + transpose_graph(G, G_T); + + typedef typename property_traits::value_type count_type; + + count_type c_count(0); + detail::components_recorder + vis(c, c_count); + + // initialize G_T + typename graph_traits::vertex_iterator ui, ui_end; + for (tie(ui, ui_end) = vertices(G_T); ui != ui_end; ++ui) + put(color, *ui, Color::white()); + + typedef typename property_traits::value_type D; + typedef indirect_cmp< FinishTime, std::less > Compare; + + Compare fl(finish_time); + std::priority_queue, Compare > Q(fl); + + typename graph_traits::vertex_iterator i, j, iend, jend; + tie(i, iend) = vertices(G_T); + tie(j, jend) = vertices(G); + for ( ; i != iend; ++i, ++j) { + put(finish_time, *i, get(finish_time, *j)); + Q.push(*i); + } + + while ( !Q.empty() ) { + Vertex u = Q.top(); + Q.pop(); + if (get(color, u) == Color::white()) { + depth_first_visit(G_T, u, vis, color); + ++c_count; + } + } + return c_count; + } + +} // namespace boost + +#endif // BOOST_GRAPH_STRONG_COMPONENTS_HPP diff --git a/win32/include/boost/graph/subgraph.hpp b/win32/include/boost/graph/subgraph.hpp new file mode 100755 index 000000000..e926f5122 --- /dev/null +++ b/win32/include/boost/graph/subgraph.hpp @@ -0,0 +1,872 @@ +//======================================================================= +// Copyright 2001 University of Notre Dame. +// Authors: Jeremy G. Siek and Lie-Quan Lee +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_SUBGRAPH_HPP +#define BOOST_SUBGRAPH_HPP + +// UNDER CONSTRUCTION + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { + + struct subgraph_tag { }; + + // Invariants of an induced subgraph: + // - If vertex u is in subgraph g, then u must be in g.parent(). + // - If edge e is in subgraph g, then e must be in g.parent(). + // - If edge e=(u,v) is in the root graph, then edge e + // is also in any subgraph that contains both vertex u and v. + + // The Graph template parameter must have a vertex_index + // and edge_index internal property. It is assumed that + // the vertex indices are assigned automatically by the + // graph during a call to add_vertex(). It is not + // assumed that the edge vertices are assigned automatically, + // they are explicitly assigned here. + + template + class subgraph { + typedef graph_traits Traits; + typedef std::list*> ChildrenList; + public: + // Graph requirements + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::edge_descriptor edge_descriptor; + typedef typename Traits::directed_category directed_category; + typedef typename Traits::edge_parallel_category edge_parallel_category; + typedef typename Traits::traversal_category traversal_category; + + static vertex_descriptor null_vertex() + { + return Traits::null_vertex(); + } + + + // IncidenceGraph requirements + typedef typename Traits::out_edge_iterator out_edge_iterator; + typedef typename Traits::degree_size_type degree_size_type; + + // AdjacencyGraph requirements + typedef typename Traits::adjacency_iterator adjacency_iterator; + + // VertexListGraph requirements + typedef typename Traits::vertex_iterator vertex_iterator; + typedef typename Traits::vertices_size_type vertices_size_type; + + // EdgeListGraph requirements + typedef typename Traits::edge_iterator edge_iterator; + typedef typename Traits::edges_size_type edges_size_type; + + typedef typename Traits::in_edge_iterator in_edge_iterator; + + typedef typename Graph::edge_property_type edge_property_type; + typedef typename Graph::vertex_property_type vertex_property_type; + typedef subgraph_tag graph_tag; + typedef Graph graph_type; + typedef typename Graph::graph_property_type graph_property_type; + + // Constructors + + // Create the main graph, the root of the subgraph tree + subgraph() + : m_parent(0), m_edge_counter(0) + { } + subgraph(const graph_property_type& p) + : m_graph(p), m_parent(0), m_edge_counter(0) + { } + subgraph(vertices_size_type n, + const graph_property_type& p = graph_property_type()) + : m_graph(n, p), m_parent(0), m_edge_counter(0), m_global_vertex(n) + { + typename Graph::vertex_iterator v, v_end; + vertices_size_type i = 0; + for (tie(v, v_end) = vertices(m_graph); v != v_end; ++v) + m_global_vertex[i++] = *v; + } + + // copy constructor + subgraph(const subgraph& x) + : m_graph(x.m_graph), m_parent(x.m_parent), + m_edge_counter(x.m_edge_counter), + m_global_vertex(x.m_global_vertex), + m_global_edge(x.m_global_edge) + { + // Do a deep copy + for (typename ChildrenList::const_iterator i = x.m_children.begin(); + i != x.m_children.end(); ++i) + m_children.push_back(new subgraph( **i )); + } + + + ~subgraph() { + for (typename ChildrenList::iterator i = m_children.begin(); + i != m_children.end(); ++i) + delete *i; + } + + + // Create a subgraph + subgraph& create_subgraph() { + m_children.push_back(new subgraph()); + m_children.back()->m_parent = this; + return *m_children.back(); + } + + // Create a subgraph with the specified vertex set. + template + subgraph& create_subgraph(VertexIterator first, + VertexIterator last) + { + m_children.push_back(new subgraph()); + m_children.back()->m_parent = this; + for (; first != last; ++first) + add_vertex(*first, *m_children.back()); + return *m_children.back(); + } + + // local <-> global descriptor conversion functions + vertex_descriptor local_to_global(vertex_descriptor u_local) const + { + return m_global_vertex[u_local]; + } + vertex_descriptor global_to_local(vertex_descriptor u_global) const + { + vertex_descriptor u_local; bool in_subgraph; + tie(u_local, in_subgraph) = this->find_vertex(u_global); + assert(in_subgraph == true); + return u_local; + } + edge_descriptor local_to_global(edge_descriptor e_local) const + { + return m_global_edge[get(get(edge_index, m_graph), e_local)]; + } + edge_descriptor global_to_local(edge_descriptor e_global) const + { + return + (*m_local_edge.find(get(get(edge_index, root().m_graph), e_global))).second; + } + + // Is vertex u (of the root graph) contained in this subgraph? + // If so, return the matching local vertex. + std::pair + find_vertex(vertex_descriptor u_global) const + { + typename std::map::const_iterator + i = m_local_vertex.find(u_global); + bool valid = i != m_local_vertex.end(); + return std::make_pair((valid ? (*i).second : null_vertex()), valid); + } + + // Return the parent graph. + subgraph& parent() { return *m_parent; } + const subgraph& parent() const { return *m_parent; } + + bool is_root() const { return m_parent == 0; } + + // Return the root graph of the subgraph tree. + subgraph& root() { + if (this->is_root()) + return *this; + else + return m_parent->root(); + } + const subgraph& root() const { + if (this->is_root()) + return *this; + else + return m_parent->root(); + } + + // Return the children subgraphs of this graph/subgraph. + // Use a list of pointers because the VC++ std::list doesn't like + // storing incomplete type. + typedef indirect_iterator< + typename ChildrenList::const_iterator + , subgraph + , std::bidirectional_iterator_tag + > + children_iterator; + + typedef indirect_iterator< + typename ChildrenList::const_iterator + , subgraph const + , std::bidirectional_iterator_tag + > + const_children_iterator; + + std::pair + children() const + { + return std::make_pair(const_children_iterator(m_children.begin()), + const_children_iterator(m_children.end())); + } + + std::pair + children() + { + return std::make_pair(children_iterator(m_children.begin()), + children_iterator(m_children.end())); + } + + std::size_t num_children() const { return m_children.size(); } + +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + // Bundled properties support + template + typename graph::detail::bundled_result::type& + operator[](Descriptor x) + { + if (m_parent == 0) return m_graph[x]; + else return root().m_graph[local_to_global(x)]; + } + + template + typename graph::detail::bundled_result::type const& + operator[](Descriptor x) const + { + if (m_parent == 0) return m_graph[x]; + else return root().m_graph[local_to_global(x)]; + } +#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES + + // private: + typedef typename property_map::type EdgeIndexMap; + typedef typename property_traits::value_type edge_index_type; + BOOST_STATIC_ASSERT((!is_same::value)); + + Graph m_graph; + subgraph* m_parent; + edge_index_type m_edge_counter; // for generating unique edge indices + ChildrenList m_children; + std::vector m_global_vertex; // local -> global + std::map m_local_vertex; // global -> local + std::vector m_global_edge; // local -> global + std::map m_local_edge; // global -> local + + edge_descriptor + local_add_edge(vertex_descriptor u_local, vertex_descriptor v_local, + edge_descriptor e_global) + { + edge_descriptor e_local; + bool inserted; + tie(e_local, inserted) = add_edge(u_local, v_local, m_graph); + put(edge_index, m_graph, e_local, m_edge_counter++); + m_global_edge.push_back(e_global); + m_local_edge[get(get(edge_index, this->root()), e_global)] = e_local; + return e_local; + } + + }; + +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + template + struct vertex_bundle_type > : vertex_bundle_type { }; + + template + struct edge_bundle_type > : edge_bundle_type { }; +#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES + + //=========================================================================== + // Functions special to the Subgraph Class + + template + typename subgraph::vertex_descriptor + add_vertex(typename subgraph::vertex_descriptor u_global, + subgraph& g) + { + assert(!g.is_root()); + typename subgraph::vertex_descriptor u_local, v_global, uu_global; + typename subgraph::edge_descriptor e_global; + + u_local = add_vertex(g.m_graph); + g.m_global_vertex.push_back(u_global); + g.m_local_vertex[u_global] = u_local; + + subgraph& r = g.root(); + + // remember edge global and local maps + { + typename subgraph::out_edge_iterator ei, ei_end; + for (tie(ei, ei_end) = out_edges(u_global, r); + ei != ei_end; ++ei) { + e_global = *ei; + v_global = target(e_global, r); + if (g.find_vertex(v_global).second == true) + g.local_add_edge(u_local, g.global_to_local(v_global), e_global); + } + } + if (is_directed(g)) { // not necessary for undirected graph + typename subgraph::vertex_iterator vi, vi_end; + typename subgraph::out_edge_iterator ei, ei_end; + for (tie(vi, vi_end) = vertices(r); vi != vi_end; ++vi) { + v_global = *vi; + if (g.find_vertex(v_global).second) + for (tie(ei, ei_end) = out_edges(*vi, r); ei != ei_end; ++ei) { + e_global = *ei; + uu_global = target(e_global, r); + if (uu_global == u_global && g.find_vertex(v_global).second) + g.local_add_edge(g.global_to_local(v_global), u_local, e_global); + } + } + } + + return u_local; + } + + //=========================================================================== + // Functions required by the IncidenceGraph concept + + template + std::pair::out_edge_iterator, + typename graph_traits::out_edge_iterator> + out_edges(typename graph_traits::vertex_descriptor u_local, + const subgraph& g) + { return out_edges(u_local, g.m_graph); } + + template + typename graph_traits::degree_size_type + out_degree(typename graph_traits::vertex_descriptor u_local, + const subgraph& g) + { return out_degree(u_local, g.m_graph); } + + template + typename graph_traits::vertex_descriptor + source(typename graph_traits::edge_descriptor e_local, + const subgraph& g) + { return source(e_local, g.m_graph); } + + template + typename graph_traits::vertex_descriptor + target(typename graph_traits::edge_descriptor e_local, + const subgraph& g) + { return target(e_local, g.m_graph); } + + //=========================================================================== + // Functions required by the BidirectionalGraph concept + + template + std::pair::in_edge_iterator, + typename graph_traits::in_edge_iterator> + in_edges(typename graph_traits::vertex_descriptor u_local, + const subgraph& g) + { return in_edges(u_local, g.m_graph); } + + template + typename graph_traits::degree_size_type + in_degree(typename graph_traits::vertex_descriptor u_local, + const subgraph& g) + { return in_degree(u_local, g.m_graph); } + + template + typename graph_traits::degree_size_type + degree(typename graph_traits::vertex_descriptor u_local, + const subgraph& g) + { return degree(u_local, g.m_graph); } + + //=========================================================================== + // Functions required by the AdjacencyGraph concept + + template + std::pair::adjacency_iterator, + typename subgraph::adjacency_iterator> + adjacent_vertices(typename subgraph::vertex_descriptor u_local, + const subgraph& g) + { return adjacent_vertices(u_local, g.m_graph); } + + //=========================================================================== + // Functions required by the VertexListGraph concept + + template + std::pair::vertex_iterator, + typename subgraph::vertex_iterator> + vertices(const subgraph& g) + { return vertices(g.m_graph); } + + template + typename subgraph::vertices_size_type + num_vertices(const subgraph& g) + { return num_vertices(g.m_graph); } + + //=========================================================================== + // Functions required by the EdgeListGraph concept + + template + std::pair::edge_iterator, + typename subgraph::edge_iterator> + edges(const subgraph& g) + { return edges(g.m_graph); } + + template + typename subgraph::edges_size_type + num_edges(const subgraph& g) + { return num_edges(g.m_graph); } + + //=========================================================================== + // Functions required by the AdjacencyMatrix concept + + template + std::pair::edge_descriptor, bool> + edge(typename subgraph::vertex_descriptor u_local, + typename subgraph::vertex_descriptor v_local, + const subgraph& g) + { + return edge(u_local, v_local, g.m_graph); + } + + //=========================================================================== + // Functions required by the MutableGraph concept + + namespace detail { + + template + void add_edge_recur_down + (Vertex u_global, Vertex v_global, Edge e_global, subgraph& g); + + template + void children_add_edge(Vertex u_global, Vertex v_global, Edge e_global, + Children& c, subgraph* orig) + { + for (typename Children::iterator i = c.begin(); i != c.end(); ++i) + if ((*i)->find_vertex(u_global).second + && (*i)->find_vertex(v_global).second) + add_edge_recur_down(u_global, v_global, e_global, **i, orig); + } + + template + void add_edge_recur_down + (Vertex u_global, Vertex v_global, Edge e_global, subgraph& g, + subgraph* orig) + { + if (&g != orig ) { + // add local edge only if u_global and v_global are in subgraph g + Vertex u_local, v_local; + bool u_in_subgraph, v_in_subgraph; + tie(u_local, u_in_subgraph) = g.find_vertex(u_global); + tie(v_local, v_in_subgraph) = g.find_vertex(v_global); + if (u_in_subgraph && v_in_subgraph) + g.local_add_edge(u_local, v_local, e_global); + } + children_add_edge(u_global, v_global, e_global, g.m_children, orig); + } + + template + std::pair::edge_descriptor, bool> + add_edge_recur_up(Vertex u_global, Vertex v_global, + const typename Graph::edge_property_type& ep, + subgraph& g, subgraph* orig) + { + if (g.is_root()) { + typename subgraph::edge_descriptor e_global; + bool inserted; + tie(e_global, inserted) = add_edge(u_global, v_global, ep, g.m_graph); + put(edge_index, g.m_graph, e_global, g.m_edge_counter++); + g.m_global_edge.push_back(e_global); + children_add_edge(u_global, v_global, e_global, g.m_children, orig); + return std::make_pair(e_global, inserted); + } else + return add_edge_recur_up(u_global, v_global, ep, *g.m_parent, orig); + } + + } // namespace detail + + // Add an edge to the subgraph g, specified by the local vertex + // descriptors u and v. In addition, the edge will be added to any + // other subgraphs which contain vertex descriptors u and v. + + template + std::pair::edge_descriptor, bool> + add_edge(typename subgraph::vertex_descriptor u_local, + typename subgraph::vertex_descriptor v_local, + const typename G::edge_property_type& ep, + subgraph& g) + { + if (g.is_root()) // u_local and v_local are really global + return detail::add_edge_recur_up(u_local, v_local, ep, g, &g); + else { + typename subgraph::edge_descriptor e_local, e_global; + bool inserted; + tie(e_global, inserted) = detail::add_edge_recur_up + (g.local_to_global(u_local), g.local_to_global(v_local), ep, g, &g); + e_local = g.local_add_edge(u_local, v_local, e_global); + return std::make_pair(e_local, inserted); + } + } + + template + std::pair::edge_descriptor, bool> + add_edge(typename subgraph::vertex_descriptor u, + typename subgraph::vertex_descriptor v, + subgraph& g) + { + typename G::edge_property_type ep; + return add_edge(u, v, ep, g); + } + + namespace detail { + + //------------------------------------------------------------------------- + // implementation of remove_edge(u,v,g) + + template + void remove_edge_recur_down(Vertex u_global, Vertex v_global, + subgraph& g); + + template + void children_remove_edge(Vertex u_global, Vertex v_global, + Children& c) + { + for (typename Children::iterator i = c.begin(); i != c.end(); ++i) + if ((*i)->find_vertex(u_global).second + && (*i)->find_vertex(v_global).second) + remove_edge_recur_down(u_global, v_global, **i); + } + + template + void remove_edge_recur_down(Vertex u_global, Vertex v_global, + subgraph& g) + { + Vertex u_local, v_local; + u_local = g.m_local_vertex[u_global]; + v_local = g.m_local_vertex[v_global]; + remove_edge(u_local, v_local, g.m_graph); + children_remove_edge(u_global, v_global, g.m_children); + } + + template + void remove_edge_recur_up(Vertex u_global, Vertex v_global, + subgraph& g) + { + if (g.is_root()) { + remove_edge(u_global, v_global, g.m_graph); + children_remove_edge(u_global, v_global, g.m_children); + } else + remove_edge_recur_up(u_global, v_global, *g.m_parent); + } + + //------------------------------------------------------------------------- + // implementation of remove_edge(e,g) + + template + void remove_edge_recur_down(Edge e_global, subgraph& g); + + template + void children_remove_edge(Edge e_global, Children& c) + { + for (typename Children::iterator i = c.begin(); i != c.end(); ++i) + if ((*i)->find_vertex(source(e_global, **i)).second + && (*i)->find_vertex(target(e_global, **i)).second) + remove_edge_recur_down(source(e_global, **i), + target(e_global, **i), **i); + } + + template + void remove_edge_recur_down(Edge e_global, subgraph& g) + { + remove_edge(g.global_to_local(e_global), g.m_graph); + children_remove_edge(e_global, g.m_children); + } + + template + void remove_edge_recur_up(Edge e_global, subgraph& g) + { + if (g.is_root()) { + remove_edge(e_global, g.m_graph); + children_remove_edge(e_global, g.m_children); + } else + remove_edge_recur_up(e_global, *g.m_parent); + } + + } // namespace detail + + template + void + remove_edge(typename subgraph::vertex_descriptor u_local, + typename subgraph::vertex_descriptor v_local, + subgraph& g) + { + if (g.is_root()) + detail::remove_edge_recur_up(u_local, v_local, g); + else + detail::remove_edge_recur_up(g.local_to_global(u_local), + g.local_to_global(v_local), g); + } + + template + void + remove_edge(typename subgraph::edge_descriptor e_local, + subgraph& g) + { + if (g.is_root()) + detail::remove_edge_recur_up(e_local, g); + else + detail::remove_edge_recur_up(g.local_to_global(e_local), g); + } + + template + void + remove_edge_if(Predicate p, subgraph& g) + { + // This is wrong... + remove_edge_if(p, g.m_graph); + } + + template + void + clear_vertex(typename subgraph::vertex_descriptor v_local, + subgraph& g) + { + // this is wrong... + clear_vertex(v_local, g.m_graph); + } + + namespace detail { + + template + typename subgraph::vertex_descriptor + add_vertex_recur_up(subgraph& g) + { + typename subgraph::vertex_descriptor u_local, u_global; + if (g.is_root()) { + u_global = add_vertex(g.m_graph); + g.m_global_vertex.push_back(u_global); + } else { + u_global = add_vertex_recur_up(*g.m_parent); + u_local = add_vertex(g.m_graph); + g.m_global_vertex.push_back(u_global); + g.m_local_vertex[u_global] = u_local; + } + return u_global; + } + + } // namespace detail + + template + typename subgraph::vertex_descriptor + add_vertex(subgraph& g) + { + typename subgraph::vertex_descriptor u_local, u_global; + if (g.is_root()) { + u_global = add_vertex(g.m_graph); + g.m_global_vertex.push_back(u_global); + u_local = u_global; + } else { + u_global = detail::add_vertex_recur_up(g.parent()); + u_local = add_vertex(g.m_graph); + g.m_global_vertex.push_back(u_global); + g.m_local_vertex[u_global] = u_local; + } + return u_local; + } + + template + void remove_vertex(typename subgraph::vertex_descriptor u, + subgraph& g) + { + // UNDER CONSTRUCTION + assert(false); + } + + + //=========================================================================== + // Functions required by the PropertyGraph concept + + template + class subgraph_global_property_map + : public put_get_helper< + typename property_traits::reference, + subgraph_global_property_map > + { + typedef property_traits Traits; + public: + typedef typename Traits::category category; + typedef typename Traits::value_type value_type; + typedef typename Traits::key_type key_type; + typedef typename Traits::reference reference; + + subgraph_global_property_map() { } + + subgraph_global_property_map(GraphPtr g) + : m_g(g) { } + + inline reference operator[](key_type e_local) const { + PropertyMap pmap = get(Tag(), m_g->root().m_graph); + if (m_g->m_parent == 0) + return pmap[e_local]; + else + return pmap[m_g->local_to_global(e_local)]; + } + GraphPtr m_g; + }; + + template + class subgraph_local_property_map + : public put_get_helper< + typename property_traits::reference, + subgraph_local_property_map > + { + typedef property_traits Traits; + public: + typedef typename Traits::category category; + typedef typename Traits::value_type value_type; + typedef typename Traits::key_type key_type; + typedef typename Traits::reference reference; + + subgraph_local_property_map() { } + + subgraph_local_property_map(GraphPtr g) + : m_g(g) { } + + inline reference operator[](key_type e_local) const { + PropertyMap pmap = get(Tag(), *m_g); + return pmap[e_local]; + } + GraphPtr m_g; + }; + + namespace detail { + + struct subgraph_any_pmap { + template + class bind_ { + typedef typename SubGraph::graph_type Graph; + typedef SubGraph* SubGraphPtr; + typedef const SubGraph* const_SubGraphPtr; + typedef typename property_map::type PMap; + typedef typename property_map::const_type const_PMap; + public: + typedef subgraph_global_property_map type; + typedef subgraph_global_property_map + const_type; + }; + }; + struct subgraph_id_pmap { + template + struct bind_ { + typedef typename SubGraph::graph_type Graph; + typedef SubGraph* SubGraphPtr; + typedef const SubGraph* const_SubGraphPtr; + typedef typename property_map::type PMap; + typedef typename property_map::const_type const_PMap; + public: + typedef subgraph_local_property_map type; + typedef subgraph_local_property_map + const_type; + }; + }; + template + struct subgraph_choose_pmap_helper { + typedef subgraph_any_pmap type; + }; + template <> + struct subgraph_choose_pmap_helper { + typedef subgraph_id_pmap type; + }; + template + struct subgraph_choose_pmap { + typedef typename subgraph_choose_pmap_helper::type Helper; + typedef typename Helper::template bind_ Bind; + typedef typename Bind::type type; + typedef typename Bind::const_type const_type; + }; + struct subgraph_property_generator { + template + struct bind_ { + typedef subgraph_choose_pmap Choice; + typedef typename Choice::type type; + typedef typename Choice::const_type const_type; + }; + }; + + } // namespace detail + + template <> + struct vertex_property_selector { + typedef detail::subgraph_property_generator type; + }; + + template <> + struct edge_property_selector { + typedef detail::subgraph_property_generator type; + }; + + template + typename property_map< subgraph, Property>::type + get(Property, subgraph& g) + { + typedef typename property_map< subgraph, Property>::type PMap; + return PMap(&g); + } + + template + typename property_map< subgraph, Property>::const_type + get(Property, const subgraph& g) + { + typedef typename property_map< subgraph, Property>::const_type PMap; + return PMap(&g); + } + + template + typename property_traits< + typename property_map< subgraph, Property>::const_type + >::value_type + get(Property, const subgraph& g, const Key& k) + { + typedef typename property_map< subgraph, Property>::const_type PMap; + PMap pmap(&g); + return pmap[k]; + } + + template + void + put(Property, subgraph& g, const Key& k, const Value& val) + { + typedef typename property_map< subgraph, Property>::type PMap; + PMap pmap(&g); + pmap[k] = val; + } + + template + inline + typename graph_property::type& + get_property(subgraph& g, Tag tag) { + return get_property(g.m_graph, tag); + } + + template + inline + const typename graph_property::type& + get_property(const subgraph& g, Tag tag) { + return get_property(g.m_graph, tag); + } + + //=========================================================================== + // Miscellaneous Functions + + template + typename subgraph::vertex_descriptor + vertex(typename subgraph::vertices_size_type n, const subgraph& g) + { + return vertex(n, g.m_graph); + } + +} // namespace boost + +#endif // BOOST_SUBGRAPH_HPP diff --git a/win32/include/boost/graph/topological_sort.hpp b/win32/include/boost/graph/topological_sort.hpp new file mode 100755 index 000000000..3faede2f6 --- /dev/null +++ b/win32/include/boost/graph/topological_sort.hpp @@ -0,0 +1,76 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_TOPOLOGICAL_SORT_HPP +#define BOOST_GRAPH_TOPOLOGICAL_SORT_HPP + +#include +#include +#include +#include +#include + +namespace boost { + + + // Topological sort visitor + // + // This visitor merely writes the linear ordering into an + // OutputIterator. The OutputIterator could be something like an + // ostream_iterator, or it could be a back/front_insert_iterator. + // Note that if it is a back_insert_iterator, the recorded order is + // the reverse topological order. On the other hand, if it is a + // front_insert_iterator, the recorded order is the topological + // order. + // + template + struct topo_sort_visitor : public dfs_visitor<> + { + topo_sort_visitor(OutputIterator _iter) + : m_iter(_iter) { } + + template + void back_edge(const Edge& u, Graph&) { throw not_a_dag(); } + + template + void finish_vertex(const Vertex& u, Graph&) { *m_iter++ = u; } + + OutputIterator m_iter; + }; + + + // Topological Sort + // + // The topological sort algorithm creates a linear ordering + // of the vertices such that if edge (u,v) appears in the graph, + // then u comes before v in the ordering. The graph must + // be a directed acyclic graph (DAG). The implementation + // consists mainly of a call to depth-first search. + // + + template + void topological_sort(VertexListGraph& g, OutputIterator result, + const bgl_named_params& params) + { + typedef topo_sort_visitor TopoVisitor; + depth_first_search(g, params.visitor(TopoVisitor(result))); + } + + template + void topological_sort(VertexListGraph& g, OutputIterator result) + { + topological_sort(g, result, + bgl_named_params(0)); // bogus + } + +} // namespace boost + +#endif /*BOOST_GRAPH_TOPOLOGICAL_SORT_H*/ diff --git a/win32/include/boost/graph/transitive_closure.hpp b/win32/include/boost/graph/transitive_closure.hpp new file mode 100755 index 000000000..f48cdae87 --- /dev/null +++ b/win32/include/boost/graph/transitive_closure.hpp @@ -0,0 +1,370 @@ +// Copyright (C) 2001 Vladimir Prus +// Copyright (C) 2001 Jeremy Siek +// 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) + +// NOTE: this final is generated by libs/graph/doc/transitive_closure.w + +#ifndef BOOST_GRAPH_TRANSITIVE_CLOSURE_HPP +#define BOOST_GRAPH_TRANSITIVE_CLOSURE_HPP + +#include +#include // for std::min and std::max +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + + namespace detail + { + inline void + union_successor_sets(const std::vector < std::size_t > &s1, + const std::vector < std::size_t > &s2, + std::vector < std::size_t > &s3) + { + BOOST_USING_STD_MIN(); + for (std::size_t k = 0; k < s1.size(); ++k) + s3[k] = min BOOST_PREVENT_MACRO_SUBSTITUTION(s1[k], s2[k]); + } + } // namespace detail + + namespace detail + { + template < typename Container, typename ST = std::size_t, + typename VT = typename Container::value_type > + struct subscript_t:public std::unary_function < ST, VT > + { + typedef VT& result_type; + + subscript_t(Container & c):container(&c) + { + } + VT & operator() (const ST & i) const + { + return (*container)[i]; + } + protected: + Container * container; + }; + template < typename Container > + subscript_t < Container > subscript(Container & c) { + return subscript_t < Container > (c); + } + } // namespace detail + + template < typename Graph, typename GraphTC, + typename G_to_TC_VertexMap, + typename VertexIndexMap > + void transitive_closure(const Graph & g, GraphTC & tc, + G_to_TC_VertexMap g_to_tc_map, + VertexIndexMap index_map) + { + if (num_vertices(g) == 0) + return; + typedef typename graph_traits < Graph >::vertex_descriptor vertex; + typedef typename graph_traits < Graph >::edge_descriptor edge; + typedef typename graph_traits < Graph >::vertex_iterator vertex_iterator; + typedef typename property_traits < VertexIndexMap >::value_type size_type; + typedef typename graph_traits < + Graph >::adjacency_iterator adjacency_iterator; + + function_requires < VertexListGraphConcept < Graph > >(); + function_requires < AdjacencyGraphConcept < Graph > >(); + function_requires < VertexMutableGraphConcept < GraphTC > >(); + function_requires < EdgeMutableGraphConcept < GraphTC > >(); + function_requires < ReadablePropertyMapConcept < VertexIndexMap, + vertex > >(); + + typedef size_type cg_vertex; + std::vector < cg_vertex > component_number_vec(num_vertices(g)); + iterator_property_map < cg_vertex *, VertexIndexMap, cg_vertex, cg_vertex& > + component_number(&component_number_vec[0], index_map); + + int num_scc = strong_components(g, component_number, + vertex_index_map(index_map)); + + std::vector < std::vector < vertex > >components; + build_component_lists(g, num_scc, component_number, components); + + typedef std::vector > CG_t; + CG_t CG(num_scc); + for (cg_vertex s = 0; s < components.size(); ++s) { + std::vector < cg_vertex > adj; + for (size_type i = 0; i < components[s].size(); ++i) { + vertex u = components[s][i]; + adjacency_iterator v, v_end; + for (tie(v, v_end) = adjacent_vertices(u, g); v != v_end; ++v) { + cg_vertex t = component_number[*v]; + if (s != t) // Avoid loops in the condensation graph + adj.push_back(t); + } + } + std::sort(adj.begin(), adj.end()); + typename std::vector::iterator di = + std::unique(adj.begin(), adj.end()); + if (di != adj.end()) + adj.erase(di, adj.end()); + CG[s] = adj; + } + + std::vector topo_order; + std::vector topo_number(num_vertices(CG)); + topological_sort(CG, std::back_inserter(topo_order), + vertex_index_map(identity_property_map())); + std::reverse(topo_order.begin(), topo_order.end()); + size_type n = 0; + for (typename std::vector::iterator iter = topo_order.begin(); + iter != topo_order.end(); ++iter) + topo_number[*iter] = n++; + + for (size_type i = 0; i < num_vertices(CG); ++i) + std::sort(CG[i].begin(), CG[i].end(), + boost::bind(std::less(), + boost::bind(detail::subscript(topo_number), _1), + boost::bind(detail::subscript(topo_number), _2))); + + std::vector > chains; + { + std::vector in_a_chain(num_vertices(CG)); + for (typename std::vector::iterator i = topo_order.begin(); + i != topo_order.end(); ++i) { + cg_vertex v = *i; + if (!in_a_chain[v]) { + chains.resize(chains.size() + 1); + std::vector& chain = chains.back(); + for (;;) { + chain.push_back(v); + in_a_chain[v] = true; + typename graph_traits::adjacency_iterator adj_first, adj_last; + tie(adj_first, adj_last) = adjacent_vertices(v, CG); + typename graph_traits::adjacency_iterator next + = std::find_if(adj_first, adj_last, + std::not1(detail::subscript(in_a_chain))); + if (next != adj_last) + v = *next; + else + break; // end of chain, dead-end + + } + } + } + } + std::vector chain_number(num_vertices(CG)); + std::vector pos_in_chain(num_vertices(CG)); + for (size_type i = 0; i < chains.size(); ++i) + for (size_type j = 0; j < chains[i].size(); ++j) { + cg_vertex v = chains[i][j]; + chain_number[v] = i; + pos_in_chain[v] = j; + } + + cg_vertex inf = (std::numeric_limits< cg_vertex >::max)(); + std::vector > successors(num_vertices(CG), + std::vector + (chains.size(), inf)); + for (typename std::vector::reverse_iterator + i = topo_order.rbegin(); i != topo_order.rend(); ++i) { + cg_vertex u = *i; + typename graph_traits::adjacency_iterator adj, adj_last; + for (tie(adj, adj_last) = adjacent_vertices(u, CG); + adj != adj_last; ++adj) { + cg_vertex v = *adj; + if (topo_number[v] < successors[u][chain_number[v]]) { + // Succ(u) = Succ(u) U Succ(v) + detail::union_successor_sets(successors[u], successors[v], + successors[u]); + // Succ(u) = Succ(u) U {v} + successors[u][chain_number[v]] = topo_number[v]; + } + } + } + + for (size_type i = 0; i < CG.size(); ++i) + CG[i].clear(); + for (size_type i = 0; i < CG.size(); ++i) + for (size_type j = 0; j < chains.size(); ++j) { + size_type topo_num = successors[i][j]; + if (topo_num < inf) { + cg_vertex v = topo_order[topo_num]; + for (size_type k = pos_in_chain[v]; k < chains[j].size(); ++k) + CG[i].push_back(chains[j][k]); + } + } + + + // Add vertices to the transitive closure graph + typedef typename graph_traits < GraphTC >::vertex_descriptor tc_vertex; + { + vertex_iterator i, i_end; + for (tie(i, i_end) = vertices(g); i != i_end; ++i) + g_to_tc_map[*i] = add_vertex(tc); + } + // Add edges between all the vertices in two adjacent SCCs + typename graph_traits::vertex_iterator si, si_end; + for (tie(si, si_end) = vertices(CG); si != si_end; ++si) { + cg_vertex s = *si; + typename graph_traits::adjacency_iterator i, i_end; + for (tie(i, i_end) = adjacent_vertices(s, CG); i != i_end; ++i) { + cg_vertex t = *i; + for (size_type k = 0; k < components[s].size(); ++k) + for (size_type l = 0; l < components[t].size(); ++l) + add_edge(g_to_tc_map[components[s][k]], + g_to_tc_map[components[t][l]], tc); + } + } + // Add edges connecting all vertices in a SCC + for (size_type i = 0; i < components.size(); ++i) + if (components[i].size() > 1) + for (size_type k = 0; k < components[i].size(); ++k) + for (size_type l = 0; l < components[i].size(); ++l) { + vertex u = components[i][k], v = components[i][l]; + add_edge(g_to_tc_map[u], g_to_tc_map[v], tc); + } + + // Find loopbacks in the original graph. + // Need to add it to transitive closure. + { + vertex_iterator i, i_end; + for (tie(i, i_end) = vertices(g); i != i_end; ++i) + { + adjacency_iterator ab, ae; + for (boost::tie(ab, ae) = adjacent_vertices(*i, g); ab != ae; ++ab) + { + if (*ab == *i) + if (components[component_number[*i]].size() == 1) + add_edge(g_to_tc_map[*i], g_to_tc_map[*i], tc); + } + } + } + } + + template + void transitive_closure(const Graph & g, GraphTC & tc) + { + if (num_vertices(g) == 0) + return; + typedef typename property_map::const_type + VertexIndexMap; + VertexIndexMap index_map = get(vertex_index, g); + + typedef typename graph_traits::vertex_descriptor tc_vertex; + std::vector to_tc_vec(num_vertices(g)); + iterator_property_map < tc_vertex *, VertexIndexMap, tc_vertex, tc_vertex&> + g_to_tc_map(&to_tc_vec[0], index_map); + + transitive_closure(g, tc, g_to_tc_map, index_map); + } + + namespace detail + { + template < typename Graph, typename GraphTC, typename G_to_TC_VertexMap, + typename VertexIndexMap> + void transitive_closure_dispatch + (const Graph & g, GraphTC & tc, + G_to_TC_VertexMap g_to_tc_map, VertexIndexMap index_map) + { + typedef typename graph_traits < GraphTC >::vertex_descriptor tc_vertex; + typename std::vector < tc_vertex >::size_type + n = is_default_param(g_to_tc_map) ? num_vertices(g) : 1; + std::vector < tc_vertex > to_tc_vec(n); + + transitive_closure + (g, tc, + choose_param(g_to_tc_map, make_iterator_property_map + (to_tc_vec.begin(), index_map, to_tc_vec[0])), + index_map); + } + } // namespace detail + + template < typename Graph, typename GraphTC, + typename P, typename T, typename R > + void transitive_closure(const Graph & g, GraphTC & tc, + const bgl_named_params < P, T, R > ¶ms) + { + if (num_vertices(g) == 0) + return; + detail::transitive_closure_dispatch + (g, tc, get_param(params, orig_to_copy_t()), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index) ); + } + + + template < typename G > void warshall_transitive_closure(G & g) + { + typedef typename graph_traits < G >::vertex_descriptor vertex; + typedef typename graph_traits < G >::vertex_iterator vertex_iterator; + + function_requires < AdjacencyMatrixConcept < G > >(); + function_requires < EdgeMutableGraphConcept < G > >(); + + // Matrix form: + // for k + // for i + // if A[i,k] + // for j + // A[i,j] = A[i,j] | A[k,j] + vertex_iterator ki, ke, ii, ie, ji, je; + for (tie(ki, ke) = vertices(g); ki != ke; ++ki) + for (tie(ii, ie) = vertices(g); ii != ie; ++ii) + if (edge(*ii, *ki, g).second) + for (tie(ji, je) = vertices(g); ji != je; ++ji) + if (!edge(*ii, *ji, g).second && edge(*ki, *ji, g).second) { + add_edge(*ii, *ji, g); + } + } + + + template < typename G > void warren_transitive_closure(G & g) + { + using namespace boost; + typedef typename graph_traits < G >::vertex_descriptor vertex; + typedef typename graph_traits < G >::vertex_iterator vertex_iterator; + + function_requires < AdjacencyMatrixConcept < G > >(); + function_requires < EdgeMutableGraphConcept < G > >(); + + // Make sure second loop will work + if (num_vertices(g) == 0) + return; + + // for i = 2 to n + // for k = 1 to i - 1 + // if A[i,k] + // for j = 1 to n + // A[i,j] = A[i,j] | A[k,j] + + vertex_iterator ic, ie, jc, je, kc, ke; + for (tie(ic, ie) = vertices(g), ++ic; ic != ie; ++ic) + for (tie(kc, ke) = vertices(g); *kc != *ic; ++kc) + if (edge(*ic, *kc, g).second) + for (tie(jc, je) = vertices(g); jc != je; ++jc) + if (!edge(*ic, *jc, g).second && edge(*kc, *jc, g).second) { + add_edge(*ic, *jc, g); + } + // for i = 1 to n - 1 + // for k = i + 1 to n + // if A[i,k] + // for j = 1 to n + // A[i,j] = A[i,j] | A[k,j] + + for (tie(ic, ie) = vertices(g), --ie; ic != ie; ++ic) + for (kc = ic, ke = ie, ++kc; kc != ke; ++kc) + if (edge(*ic, *kc, g).second) + for (tie(jc, je) = vertices(g); jc != je; ++jc) + if (!edge(*ic, *jc, g).second && edge(*kc, *jc, g).second) { + add_edge(*ic, *jc, g); + } + } + + +} // namespace boost + +#endif // BOOST_GRAPH_TRANSITIVE_CLOSURE_HPP diff --git a/win32/include/boost/graph/transpose_graph.hpp b/win32/include/boost/graph/transpose_graph.hpp new file mode 100755 index 000000000..5c0f352ed --- /dev/null +++ b/win32/include/boost/graph/transpose_graph.hpp @@ -0,0 +1,40 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_TRANSPOSE_HPP +#define BOOST_GRAPH_TRANSPOSE_HPP + +#include +#include +#include +#include + + +namespace boost { + + template + void transpose_graph(const VertexListGraph& G, MutableGraph& G_T) + { + reverse_graph R(G); + copy_graph(R, G_T); + } + + template + void transpose_graph(const VertexListGraph& G, MutableGraph& G_T, + const bgl_named_params& params) + { + reverse_graph Rev(G); + copy_graph(Rev, G_T, params); + } + +} // namespace boost + +#endif // BOOST_GRAPH_TRANSPOSE_HPP diff --git a/win32/include/boost/graph/tree_traits.hpp b/win32/include/boost/graph/tree_traits.hpp new file mode 100755 index 000000000..d7d840a10 --- /dev/null +++ b/win32/include/boost/graph/tree_traits.hpp @@ -0,0 +1,43 @@ +// (C) Copyright Jeremy Siek 1999. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_TREE_STRUCTURE_HPP +#define BOOST_TREE_STRUCTURE_HPP + +namespace boost { + + template + struct tree_traits { + typedef typename T::node_descriptor node_descriptor; + typedef typename T::children_iterator children_iterator; + }; + + + template + void traverse_tree(typename tree_traits::node_descriptor v, + Tree& t, TreeVisitor visitor) + { + visitor.preorder(v, t); + typename tree_traits::children_iterator i, end; + tie(i, end) = children(v, t); + if (i != end) { + traverse_tree(*i++, t, visitor); + visitor.inorder(v, t); + while (i != end) + traverse_tree(*i++, t, visitor); + } else + visitor.inorder(v, t); + visitor.postorder(v, t); + } + + struct null_tree_visitor { + template void preorder(Node, Tree&) { } + template void inorder(Node, Tree&) { } + template void postorder(Node, Tree&) { } + }; + +} /* namespace boost */ + +#endif /* BOOST_TREE_STRUCTURE_HPP */ diff --git a/win32/include/boost/graph/two_bit_color_map.hpp b/win32/include/boost/graph/two_bit_color_map.hpp new file mode 100755 index 000000000..9551bb887 --- /dev/null +++ b/win32/include/boost/graph/two_bit_color_map.hpp @@ -0,0 +1,90 @@ +// Copyright (C) 2005-2006 The Trustees of Indiana University. + +// 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) + +// Authors: Jeremiah Willcock +// Douglas Gregor +// Andrew Lumsdaine + +// Two bit per color property map + +#ifndef BOOST_TWO_BIT_COLOR_MAP_HPP +#define BOOST_TWO_BIT_COLOR_MAP_HPP + +#include +#include + +namespace boost { + +enum two_bit_color_type { + two_bit_white = 0, + two_bit_gray = 1, + two_bit_green = 2, + two_bit_black = 3 +}; + +template <> +struct color_traits +{ + static two_bit_color_type white() { return two_bit_white; } + static two_bit_color_type gray() { return two_bit_gray; } + static two_bit_color_type green() { return two_bit_green; } + static two_bit_color_type black() { return two_bit_black; } +}; + + +template +struct two_bit_color_map +{ + std::size_t n; + IndexMap index; + shared_array data; + + typedef typename property_traits::key_type key_type; + typedef two_bit_color_type value_type; + typedef void reference; + typedef read_write_property_map_tag category; + + explicit two_bit_color_map(std::size_t n, const IndexMap& index = IndexMap()) + : n(n), index(index), data(new unsigned char[(n + 3) / 4]) + { + } +}; + +template +inline two_bit_color_type +get(const two_bit_color_map& pm, + typename two_bit_color_map::key_type key) +{ + typename property_traits::value_type i = get(pm.index, key); + assert (i < pm.n); + return two_bit_color_type((pm.data.get()[i / 4] >> ((i % 4) * 2)) & 3); +} + +template +inline void +put(const two_bit_color_map& pm, + typename two_bit_color_map::key_type key, + two_bit_color_type value) +{ + typename property_traits::value_type i = get(pm.index, key); + assert (i < pm.n); + assert (value >= 0 && value < 4); + std::size_t byte_num = i / 4; + std::size_t bit_position = ((i % 4) * 2); + pm.data.get()[byte_num] = (pm.data.get()[byte_num] & ~(3 << bit_position)) + | (value << bit_position); +} + +template +inline two_bit_color_map +make_two_bit_color_map(std::size_t n, const IndexMap& index_map) +{ + return two_bit_color_map(n, index_map); +} + +} // end namespace boost + +#endif // BOOST_TWO_BIT_COLOR_MAP_HPP diff --git a/win32/include/boost/graph/undirected_dfs.hpp b/win32/include/boost/graph/undirected_dfs.hpp new file mode 100755 index 000000000..b372fbc2b --- /dev/null +++ b/win32/include/boost/graph/undirected_dfs.hpp @@ -0,0 +1,250 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_UNDIRECTED_DFS_HPP +#define BOOST_GRAPH_UNDIRECTED_DFS_HPP + +#include +#include + +namespace boost { + + namespace detail { + +// Define BOOST_RECURSIVE_DFS to use older, recursive version. +// It is retained for a while in order to perform performance +// comparison. +#ifndef BOOST_RECURSIVE_DFS + + template + void undir_dfv_impl + (const IncidenceGraph& g, + typename graph_traits::vertex_descriptor u, + DFSVisitor& vis, + VertexColorMap vertex_color, + EdgeColorMap edge_color) + { + function_requires >(); + function_requires >(); + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::edge_descriptor Edge; + function_requires >(); + function_requires >(); + typedef typename property_traits::value_type ColorValue; + typedef typename property_traits::value_type EColorValue; + function_requires< ColorValueConcept >(); + function_requires< ColorValueConcept >(); + typedef color_traits Color; + typedef color_traits EColor; + typedef typename graph_traits::out_edge_iterator Iter; + typedef std::pair > VertexInfo; + + std::vector stack; + + put(vertex_color, u, Color::gray()); + vis.discover_vertex(u, g); + stack.push_back(std::make_pair(u, out_edges(u, g))); + while (!stack.empty()) { + VertexInfo& back = stack.back(); + u = back.first; + Iter ei, ei_end; + tie(ei, ei_end) = back.second; + stack.pop_back(); + while (ei != ei_end) { + Vertex v = target(*ei, g); + vis.examine_edge(*ei, g); + ColorValue v_color = get(vertex_color, v); + EColorValue uv_color = get(edge_color, *ei); + put(edge_color, *ei, EColor::black()); + if (v_color == Color::white()) { + vis.tree_edge(*ei, g); + stack.push_back(std::make_pair(u, std::make_pair(++ei, ei_end))); + u = v; + put(vertex_color, u, Color::gray()); + vis.discover_vertex(u, g); + tie(ei, ei_end) = out_edges(u, g); + } else if (v_color == Color::gray()) { + if (uv_color == EColor::white()) vis.back_edge(*ei, g); + ++ei; + } else { // if (v_color == Color::black()) + ++ei; + } + } + put(vertex_color, u, Color::black()); + vis.finish_vertex(u, g); + } + } + +#else // BOOST_RECURSIVE_DFS + + template + void undir_dfv_impl + (const IncidenceGraph& g, + typename graph_traits::vertex_descriptor u, + DFSVisitor& vis, // pass-by-reference here, important! + VertexColorMap vertex_color, + EdgeColorMap edge_color) + { + function_requires >(); + function_requires >(); + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename graph_traits::edge_descriptor Edge; + function_requires >(); + function_requires >(); + typedef typename property_traits::value_type ColorValue; + typedef typename property_traits::value_type EColorValue; + function_requires< ColorValueConcept >(); + function_requires< ColorValueConcept >(); + typedef color_traits Color; + typedef color_traits EColor; + typename graph_traits::out_edge_iterator ei, ei_end; + + put(vertex_color, u, Color::gray()); vis.discover_vertex(u, g); + for (tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) { + Vertex v = target(*ei, g); vis.examine_edge(*ei, g); + ColorValue v_color = get(vertex_color, v); + EColorValue uv_color = get(edge_color, *ei); + put(edge_color, *ei, EColor::black()); + if (v_color == Color::white()) { vis.tree_edge(*ei, g); + undir_dfv_impl(g, v, vis, vertex_color, edge_color); + } else if (v_color == Color::gray() && uv_color == EColor::white()) + vis.back_edge(*ei, g); + } + put(vertex_color, u, Color::black()); vis.finish_vertex(u, g); + } + +#endif // ! BOOST_RECURSIVE_DFS + + } // namespace detail + + template + void + undirected_dfs(const Graph& g, DFSVisitor vis, + VertexColorMap vertex_color, EdgeColorMap edge_color, + Vertex start_vertex) + { + function_requires >(); + function_requires >(); + + typedef typename property_traits::value_type ColorValue; + typedef color_traits Color; + + typename graph_traits::vertex_iterator ui, ui_end; + for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) { + put(vertex_color, *ui, Color::white()); vis.initialize_vertex(*ui, g); + } + typename graph_traits::edge_iterator ei, ei_end; + for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + put(edge_color, *ei, Color::white()); + + if (start_vertex != *vertices(g).first){ vis.start_vertex(start_vertex, g); + detail::undir_dfv_impl(g, start_vertex, vis, vertex_color, edge_color); + } + + for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) { + ColorValue u_color = get(vertex_color, *ui); + if (u_color == Color::white()) { vis.start_vertex(*ui, g); + detail::undir_dfv_impl(g, *ui, vis, vertex_color, edge_color); + } + } + } + + template + void + undirected_dfs(const Graph& g, DFSVisitor vis, + VertexColorMap vertex_color, EdgeColorMap edge_color) + { + undirected_dfs(g, vis, vertex_color, edge_color, *vertices(g).first); + } + + namespace detail { + template + struct udfs_dispatch { + + template + static void + apply(const Graph& g, DFSVisitor vis, Vertex start_vertex, + const bgl_named_params&, + EdgeColorMap edge_color, + VertexColorMap vertex_color) + { + undirected_dfs(g, vis, vertex_color, edge_color, start_vertex); + } + }; + + template <> + struct udfs_dispatch { + template + static void + apply(const Graph& g, DFSVisitor vis, Vertex start_vertex, + const bgl_named_params& params, + EdgeColorMap edge_color, + detail::error_property_not_found) + { + std::vector color_vec(num_vertices(g)); + default_color_type c = white_color; // avoid warning about un-init + undirected_dfs + (g, vis, make_iterator_property_map + (color_vec.begin(), + choose_const_pmap(get_param(params, vertex_index), + g, vertex_index), c), + edge_color, + start_vertex); + } + }; + + } // namespace detail + + + // Named Parameter Variant + template + void + undirected_dfs(const Graph& g, + const bgl_named_params& params) + { + typedef typename property_value< bgl_named_params, + vertex_color_t>::type C; + detail::udfs_dispatch::apply + (g, + choose_param(get_param(params, graph_visitor), + make_dfs_visitor(null_visitor())), + choose_param(get_param(params, root_vertex_t()), + *vertices(g).first), + params, + get_param(params, edge_color), + get_param(params, vertex_color) + ); + } + + + template + void undirected_depth_first_visit + (const IncidenceGraph& g, + typename graph_traits::vertex_descriptor u, + DFSVisitor vis, VertexColorMap vertex_color, EdgeColorMap edge_color) + { + detail::undir_dfv_impl(g, u, vis, vertex_color, edge_color); + } + + +} // namespace boost + + +#endif diff --git a/win32/include/boost/graph/vector_as_graph.hpp b/win32/include/boost/graph/vector_as_graph.hpp new file mode 100755 index 000000000..ff03e9b3f --- /dev/null +++ b/win32/include/boost/graph/vector_as_graph.hpp @@ -0,0 +1,332 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2006 The Trustees of Indiana University. +// Copyright (C) 2001 Vladimir Prus +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Douglas Gregor +// +// 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) +//======================================================================= + +// The mutating functions (add_edge, etc.) were added by Vladimir Prus. + +#ifndef BOOST_VECTOR_AS_GRAPH_HPP +#define BOOST_VECTOR_AS_GRAPH_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + This module implements the VertexListGraph concept using a + std::vector as the "back-bone" of the graph (the vector *is* the + graph object). The edge-lists type of the graph is templated, so the + user can choose any STL container, so long as the value_type of the + container is convertible to the size_type of the vector. For now any + graph properties must be stored seperately. + + This module requires the C++ compiler to support partial + specialization for the graph_traits class, so this is not portable + to VC++. + +*/ + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +#error The vector-as-graph module requires a compiler that supports partial specialization +#endif + + +namespace boost { + namespace detail { + template struct val_out_edge_ret; + template struct val_out_edge_iter; + template struct val_edge; + } +} + +#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost { + + struct vector_as_graph_traversal_tag + : public vertex_list_graph_tag, + public adjacency_graph_tag, + public incidence_graph_tag { }; + + template + struct graph_traits< std::vector > + { + typedef typename EdgeList::value_type V; + typedef V vertex_descriptor; + typedef typename detail::val_edge::type edge_descriptor; + typedef typename EdgeList::const_iterator adjacency_iterator; + typedef typename detail::val_out_edge_iter::type + out_edge_iterator; + typedef void in_edge_iterator; + typedef void edge_iterator; + typedef typename integer_range::iterator vertex_iterator; + typedef directed_tag directed_category; + typedef allow_parallel_edge_tag edge_parallel_category; + typedef vector_as_graph_traversal_tag traversal_category; + typedef typename std::vector::size_type vertices_size_type; + typedef void edges_size_type; + typedef typename EdgeList::size_type degree_size_type; + }; + template + struct edge_property_type< std::vector > + { + typedef void type; + }; + template + struct vertex_property_type< std::vector > + { + typedef void type; + }; + template + struct graph_property_type< std::vector > + { + typedef void type; + }; +} +#endif + +namespace boost { + + namespace detail { + + // "val" is short for Vector Adjacency List + + template + struct val_edge + { + typedef typename EdgeList::value_type V; + typedef std::pair type; + }; + + // need rewrite this using boost::iterator_adaptor + template + class val_out_edge_iterator + : public boost::iterator, + std::ptrdiff_t, std::pair*, const std::pair > + { + typedef val_out_edge_iterator self; + typedef std::pair Edge; + public: + val_out_edge_iterator() { } + val_out_edge_iterator(V s, Iter i) : _source(s), _iter(i) { } + Edge operator*() const { return Edge(_source, *_iter); } + self& operator++() { ++_iter; return *this; } + self operator++(int) { self t = *this; ++_iter; return t; } + bool operator==(const self& x) const { return _iter == x._iter; } + bool operator!=(const self& x) const { return _iter != x._iter; } + protected: + V _source; + Iter _iter; + }; + + template + struct val_out_edge_iter + { + typedef typename EdgeList::value_type V; + typedef typename EdgeList::const_iterator Iter; + typedef val_out_edge_iterator type; + }; + + template + struct val_out_edge_ret + { + typedef typename val_out_edge_iter::type IncIter; + typedef std::pair type; + }; + + } // namesapce detail + + template + typename detail::val_out_edge_ret::type + out_edges(typename EdgeList::value_type v, + const std::vector& g) + { + typedef typename detail::val_out_edge_iter::type Iter; + typedef typename detail::val_out_edge_ret::type return_type; + return return_type(Iter(v, g[v].begin()), Iter(v, g[v].end())); + } + + template + typename EdgeList::size_type + out_degree(typename EdgeList::value_type v, + const std::vector& g) + { + return g[v].size(); + } + + template + std::pair + adjacent_vertices(typename EdgeList::value_type v, + const std::vector& g) + { + return std::make_pair(g[v].begin(), g[v].end()); + } + + // source() and target() already provided for pairs in graph_traits.hpp + + template + std::pair + ::iterator, + typename boost::integer_range + ::iterator > + vertices(const std::vector& v) + { + typedef typename boost::integer_range + ::iterator Iter; + return std::make_pair(Iter(0), Iter(v.size())); + } + + template + typename std::vector::size_type + num_vertices(const std::vector& v) + { + return v.size(); + } + + template + typename std::pair::type, bool> + add_edge(typename EdgeList::value_type u, typename EdgeList::value_type v, + std::vector& g) + { + typedef typename detail::val_edge::type edge_type; + g[u].insert(g[u].end(), v); + return std::make_pair(edge_type(u, v), true); + } + + template + typename std::pair::type, bool> + edge(typename EdgeList::value_type u, typename EdgeList::value_type v, + std::vector& g) + { + typedef typename detail::val_edge::type edge_type; + typename EdgeList::iterator i = g[u].begin(), end = g[u].end(); + for (; i != end; ++i) + if (*i == v) + return std::make_pair(edge_type(u, v), true); + return std::make_pair(edge_type(), false); + } + + template + void + remove_edge(typename EdgeList::value_type u, typename EdgeList::value_type v, + std::vector& g) + { + typename EdgeList::iterator i = std::remove(g[u].begin(), g[u].end(), v); + if (i != g[u].end()) + g[u].erase(i, g[u].end()); + } + + template + void + remove_edge(typename detail::val_edge::type e, + std::vector& g) + { + typename EdgeList::value_type u, v; + u = e.first; + v = e.second; + // FIXME: edge type does not fully specify the edge to be deleted + typename EdgeList::iterator i = std::remove(g[u].begin(), g[u].end(), v); + if (i != g[u].end()) + g[u].erase(i, g[u].end()); + } + + template + void + remove_edge_if(Predicate p, + std::vector& g) + { + for (std::size_t u = 0; u < g.size(); ++u) { + // Oops! gcc gets internal compiler error on compose_....... + + typedef typename EdgeList::iterator iterator; + iterator b = g[u].begin(), e = g[u].end(); + + if (!g[u].empty()) { + + for(; b != e;) { + if (p(std::make_pair(u, *b))) { + --e; + if (b == e) + break; + else + iter_swap(b, e); + } else { + ++b; + } + } + } + + if (e != g[u].end()) + g[u].erase(e, g[u].end()); + } + } + + template + typename EdgeList::value_type + add_vertex(std::vector& g) + { + g.resize(g.size()+1); + return g.size()-1; + } + + template + void + clear_vertex(typename EdgeList::value_type u, + std::vector& g) + { + g[u].clear(); + for (std::size_t i = 0; i < g.size(); ++i) + remove_edge(i, u, g); + } + + template + void + remove_vertex(typename EdgeList::value_type u, + std::vector& g) + { + typedef typename EdgeList::iterator iterator; + clear_vertex(u, g); + g.erase(g.begin() + u); + for (std::size_t i = 0; i < g.size(); ++i) + for ( iterator it = g[i].begin(); it != g[i].end(); ++it ) + // after clear_vertex *it is never equal to u + if ( *it > u ) + --*it; + } + + template + struct property_map, vertex_index_t> + { + typedef identity_property_map type; + typedef type const_type; + }; + + template + identity_property_map + get(vertex_index_t, const std::vector&) + { + return identity_property_map(); + } + + template + identity_property_map + get(vertex_index_t, std::vector&) + { + return identity_property_map(); + } +} // namespace boost + +#endif // BOOST_VECTOR_AS_GRAPH_HPP diff --git a/win32/include/boost/graph/visitors.hpp b/win32/include/boost/graph/visitors.hpp new file mode 100755 index 000000000..e0c44b27d --- /dev/null +++ b/win32/include/boost/graph/visitors.hpp @@ -0,0 +1,279 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// 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) +//======================================================================= +// +// Revision History: +// 01 April 2001: Modified to use new header. (JMaddock) +// +#ifndef BOOST_GRAPH_GRAPH_SEARCH_VISITORS_HPP +#define BOOST_GRAPH_GRAPH_SEARCH_VISITORS_HPP + +#include +#include +#include +#include +#include +#include + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +// Stay out of the way of the concept checking class +# define Graph Graph_ +#endif + +namespace boost { + + // This is a bit more convenient than std::numeric_limits because + // you don't have to explicitly provide type T. + template + inline T numeric_limits_max(T) { return (std::numeric_limits::max)(); } + + //======================================================================== + // Event Tags + + namespace detail { + // For partial specialization workaround + enum event_visitor_enum + { on_no_event_num, + on_initialize_vertex_num, on_start_vertex_num, + on_discover_vertex_num, on_finish_vertex_num, on_examine_vertex_num, + on_examine_edge_num, on_tree_edge_num, on_non_tree_edge_num, + on_gray_target_num, on_black_target_num, + on_forward_or_cross_edge_num, on_back_edge_num, + on_edge_relaxed_num, on_edge_not_relaxed_num, + on_edge_minimized_num, on_edge_not_minimized_num + }; + + template + struct functor_to_visitor : Visitor + { + typedef Event event_filter; + functor_to_visitor(const Visitor& visitor) : Visitor(visitor) {} + }; + + } // namespace detail + + struct on_no_event { enum { num = detail::on_no_event_num }; }; + + struct on_initialize_vertex { + enum { num = detail::on_initialize_vertex_num }; }; + struct on_start_vertex { enum { num = detail::on_start_vertex_num }; }; + struct on_discover_vertex { enum { num = detail::on_discover_vertex_num }; }; + struct on_examine_vertex { enum { num = detail::on_examine_vertex_num }; }; + struct on_finish_vertex { enum { num = detail::on_finish_vertex_num }; }; + + struct on_examine_edge { enum { num = detail::on_examine_edge_num }; }; + struct on_tree_edge { enum { num = detail::on_tree_edge_num }; }; + struct on_non_tree_edge { enum { num = detail::on_non_tree_edge_num }; }; + struct on_gray_target { enum { num = detail::on_gray_target_num }; }; + struct on_black_target { enum { num = detail::on_black_target_num }; }; + struct on_forward_or_cross_edge { + enum { num = detail::on_forward_or_cross_edge_num }; }; + struct on_back_edge { enum { num = detail::on_back_edge_num }; }; + + struct on_edge_relaxed { enum { num = detail::on_edge_relaxed_num }; }; + struct on_edge_not_relaxed { + enum { num = detail::on_edge_not_relaxed_num }; }; + struct on_edge_minimized { enum { num = detail::on_edge_minimized_num }; }; + struct on_edge_not_minimized { + enum { num = detail::on_edge_not_minimized_num }; }; + + struct true_tag { enum { num = true }; }; + struct false_tag { enum { num = false }; }; + + //======================================================================== + // base_visitor and null_visitor + + // needed for MSVC workaround + template + struct base_visitor { + typedef on_no_event event_filter; + template + void operator()(T, Graph&) { } + }; + + struct null_visitor : public base_visitor { + typedef on_no_event event_filter; + template + void operator()(T, Graph&) { } + }; + + //======================================================================== + // The invoke_visitors() function + + namespace detail { + template + inline void + invoke_dispatch(Visitor& v, T x, Graph& g, true_tag) { + v(x, g); + } + template + inline void + invoke_dispatch(Visitor&, T, Graph&, false_tag) { } + } // namespace detail + + template + inline void + invoke_visitors(std::pair& vlist, T x, Graph& g, Tag tag) { + typedef typename Visitor::event_filter Category; + typedef typename graph_detail::is_same::is_same_tag + IsSameTag; + detail::invoke_dispatch(vlist.first, x, g, IsSameTag()); + invoke_visitors(vlist.second, x, g, tag); + } +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 + template + inline void + invoke_visitors(base_visitor& vis, T x, Graph& g, Tag) { + typedef typename Visitor::event_filter Category; + typedef typename graph_detail::is_same::is_same_tag + IsSameTag; + Visitor& v = static_cast(vis); + detail::invoke_dispatch(v, x, g, IsSameTag()); + } +#else + template + inline void + invoke_visitors(Visitor& v, T x, Graph& g, Tag) { + typedef typename Visitor::event_filter Category; + typedef typename graph_detail::is_same::is_same_tag + IsSameTag; + detail::invoke_dispatch(v, x, g, IsSameTag()); + } +#endif + + //======================================================================== + // predecessor_recorder + + template + struct predecessor_recorder + : public base_visitor > + { + typedef Tag event_filter; + predecessor_recorder(PredecessorMap pa) : m_predecessor(pa) { } + template + void operator()(Edge e, const Graph& g) { + put(m_predecessor, target(e, g), source(e, g)); + } + PredecessorMap m_predecessor; + }; + template + predecessor_recorder + record_predecessors(PredecessorMap pa, Tag) { + return predecessor_recorder (pa); + } + + //======================================================================== + // edge_predecessor_recorder + + template + struct edge_predecessor_recorder + : public base_visitor > + { + typedef Tag event_filter; + edge_predecessor_recorder(PredEdgeMap pa) : m_predecessor(pa) { } + template + void operator()(Edge e, const Graph& g) { + put(m_predecessor, target(e, g), e); + } + PredEdgeMap m_predecessor; + }; + template + edge_predecessor_recorder + record_edge_predecessors(PredEdgeMap pa, Tag) { + return edge_predecessor_recorder (pa); + } + + //======================================================================== + // distance_recorder + + template + struct distance_recorder + : public base_visitor > + { + typedef Tag event_filter; + distance_recorder(DistanceMap pa) : m_distance(pa) { } + template + void operator()(Edge e, const Graph& g) { + typename graph_traits::vertex_descriptor + u = source(e, g), v = target(e, g); + put(m_distance, v, get(m_distance, u) + 1); + } + DistanceMap m_distance; + }; + template + distance_recorder + record_distances(DistanceMap pa, Tag) { + return distance_recorder (pa); + } + + //======================================================================== + // time_stamper + + + template + struct time_stamper + : public base_visitor > + { + typedef Tag event_filter; + time_stamper(TimeMap pa, TimeT& t) : m_time_pa(pa), m_time(t) { } + template + void operator()(Vertex u, const Graph&) { + put(m_time_pa, u, ++m_time); + } + TimeMap m_time_pa; + TimeT& m_time; + }; + template + time_stamper + stamp_times(TimeMap pa, TimeT& time_counter, Tag) { + return time_stamper(pa, time_counter); + } + + //======================================================================== + // property_writer + + template + struct property_writer + : public base_visitor > + { + typedef Tag event_filter; + + property_writer(PA pa, OutputIterator out) : m_pa(pa), m_out(out) { } + + template + void operator()(T x, Graph&) { *m_out++ = get(m_pa, x); } + PA m_pa; + OutputIterator m_out; + }; + template + property_writer + write_property(PA pa, OutputIterator out, Tag) { + return property_writer(pa, out); + } + +#define BOOST_GRAPH_EVENT_STUB(Event,Kind) \ + typedef ::boost::Event Event##_type; \ + template \ + Kind##_visitor, Visitors> > \ + do_##Event(Visitor visitor) \ + { \ + typedef std::pair, \ + Visitors> visitor_list; \ + typedef Kind##_visitor result_type; \ + return result_type(visitor_list(visitor, m_vis)); \ + } + +} /* namespace boost */ + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +// Stay out of the way of the concept checking class +# undef Graph +#endif + +#endif diff --git a/win32/include/boost/graph/wavefront.hpp b/win32/include/boost/graph/wavefront.hpp new file mode 100755 index 000000000..392396d63 --- /dev/null +++ b/win32/include/boost/graph/wavefront.hpp @@ -0,0 +1,135 @@ +// +//======================================================================= +// Copyright 2002 Marc Wintermantel (wintermantel@even-ag.ch) +// ETH Zurich, Center of Structure Technologies (www.imes.ethz.ch/st) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +#ifndef BOOST_GRAPH_WAVEFRONT_HPP +#define BOOST_GRAPH_WAVEFRONT_HPP + +#include +#include +#include +#include +#include +#include +#include // for std::min and std::max + +namespace boost { + + template + typename graph_traits::vertices_size_type + ith_wavefront(typename graph_traits::vertex_descriptor i, + const Graph& g, + VertexIndexMap index) + { + typename graph_traits::vertex_descriptor v, w; + typename graph_traits::vertices_size_type b = 1; + typename graph_traits::out_edge_iterator edge_it2, edge_it2_end; + typename graph_traits::vertices_size_type index_i = index[i]; + std::vector rows_active(num_vertices(g), false); + + rows_active[index_i] = true; + + typename graph_traits::vertex_iterator ui, ui_end; + for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) + { + v = *ui; + if(index[v] <= index_i) + { + for (tie(edge_it2, edge_it2_end) = out_edges(v, g); edge_it2 != edge_it2_end; ++edge_it2) + { + w = target(*edge_it2, g); + if( (index[w] >= index_i) && (!rows_active[index[w]]) ) + { + b++; + rows_active[index[w]] = true; + } + } + } + } + + return b; + } + + + template + typename graph_traits::vertices_size_type + ith_wavefront(typename graph_traits::vertex_descriptor i, + const Graph& g) + { + return ith_wavefront(i, g, get(vertex_index, g)); + } + + + template + typename graph_traits::vertices_size_type + max_wavefront(const Graph& g, VertexIndexMap index) + { + BOOST_USING_STD_MAX(); + typename graph_traits::vertices_size_type b = 0; + typename graph_traits::vertex_iterator i, end; + for (tie(i, end) = vertices(g); i != end; ++i) + b = max BOOST_PREVENT_MACRO_SUBSTITUTION(b, ith_wavefront(*i, g, index)); + return b; + } + + template + typename graph_traits::vertices_size_type + max_wavefront(const Graph& g) + { + return max_wavefront(g, get(vertex_index, g)); + } + + + template + double + aver_wavefront(const Graph& g, VertexIndexMap index) + { + double b = 0; + typename graph_traits::vertex_iterator i, end; + for (tie(i, end) = vertices(g); i != end; ++i) + b += ith_wavefront(*i, g, index); + + b /= num_vertices(g); + return b; + } + + template + double + aver_wavefront(const Graph& g) + { + return aver_wavefront(g, get(vertex_index, g)); + } + + + template + double + rms_wavefront(const Graph& g, VertexIndexMap index) + { + double b = 0; + typename graph_traits::vertex_iterator i, end; + for (tie(i, end) = vertices(g); i != end; ++i) + b += std::pow(double ( ith_wavefront(*i, g, index) ), 2.0); + + b /= num_vertices(g); + + return std::sqrt(b); + } + + template + double + rms_wavefront(const Graph& g) + { + return rms_wavefront(g, get(vertex_index, g)); + } + + +} // namespace boost + +#endif // BOOST_GRAPH_WAVEFRONT_HPP diff --git a/win32/include/boost/graph/write_dimacs.hpp b/win32/include/boost/graph/write_dimacs.hpp new file mode 100755 index 000000000..fb28259e6 --- /dev/null +++ b/win32/include/boost/graph/write_dimacs.hpp @@ -0,0 +1,72 @@ +// Copyright (c) 2006, Stephan Diederich +// +// This code may be used under either of the following two licences: +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. OF SUCH DAMAGE. +// +// Or: +// +// 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) + +/* + Writes maximal flow problem in extended DIMACS format to an OutputIterator + Vertex indices are read from an IndexMap and shiftet by 1. + so their new range is [1..num_vertices(g)] +*/ + +/* ----------------------------------------------------------------- */ + +#include +#include +#include + +namespace boost { + +template +void write_dimacs_max_flow(const Graph& g, + CapacityMap capacity, + IndexMap idx, + typename graph_traits::vertex_descriptor src, + typename graph_traits::vertex_descriptor sink, + std::ostream& out) +{ + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef typename graph_traits::vertices_size_type vertices_size_type; + typedef typename graph_traits::edge_descriptor edge_descriptor; + typedef typename graph_traits::edges_size_type edges_size_type; + typedef typename graph_traits::edge_iterator edge_iterator; + + out << "c DIMACS max-flow file generated from boost::write_dimacs_max_flow" << std::endl; + out << "p max " << num_vertices(g) << " " << num_edges(g) << std::endl; //print problem description "max" and number of verts and edges + out << "n " << get(idx, src) + 1 << " s" << std::endl;; //say which one is source + out << "n " << get(idx, sink) + 1 << " t" << std::endl; //say which one is sink + + //output the edges + edge_iterator ei, e_end; + for(tie(ei,e_end) = edges(g); ei!=e_end; ++ei){ + out << "a " << idx[ source(*ei, g) ] + 1 << " " << idx[ target(*ei, g) ] + 1 << " " << get(capacity,*ei) << std::endl; + } +} + +} // namespace boost diff --git a/win32/include/boost/implicit_cast.hpp b/win32/include/boost/implicit_cast.hpp new file mode 100755 index 000000000..b0ff30ae7 --- /dev/null +++ b/win32/include/boost/implicit_cast.hpp @@ -0,0 +1,29 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef IMPLICIT_CAST_DWA200356_HPP +# define IMPLICIT_CAST_DWA200356_HPP + +# include + +namespace boost { + +// implementation originally suggested by C. Green in +// http://lists.boost.org/MailArchives/boost/msg00886.php + +// The use of identity creates a non-deduced form, so that the +// explicit template argument must be supplied +template +inline T implicit_cast (typename mpl::identity::type x) { + return x; +} + +// incomplete return type now is here +//template +//void implicit_cast (...); + +} // namespace boost + + +#endif // IMPLICIT_CAST_DWA200356_HPP diff --git a/win32/include/boost/indirect_reference.hpp b/win32/include/boost/indirect_reference.hpp new file mode 100755 index 000000000..7675e78f1 --- /dev/null +++ b/win32/include/boost/indirect_reference.hpp @@ -0,0 +1,43 @@ +#ifndef INDIRECT_REFERENCE_DWA200415_HPP +# define INDIRECT_REFERENCE_DWA200415_HPP + +// +// Copyright David Abrahams 2004. Use, modification and distribution is +// subject to 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) +// +// typename indirect_reference

            ::type provides the type of *p. +// +// http://www.boost.org/libs/iterator/doc/pointee.html +// + +# include +# include +# include +# include +# include + +namespace boost { + +namespace detail +{ + template + struct smart_ptr_reference + { + typedef typename boost::pointee

            ::type& type; + }; +} + +template +struct indirect_reference + : mpl::eval_if< + detail::is_incrementable

            + , iterator_reference

            + , detail::smart_ptr_reference

            + > +{ +}; + +} // namespace boost + +#endif // INDIRECT_REFERENCE_DWA200415_HPP diff --git a/win32/include/boost/integer.hpp b/win32/include/boost/integer.hpp new file mode 100755 index 000000000..09d65127b --- /dev/null +++ b/win32/include/boost/integer.hpp @@ -0,0 +1,127 @@ +// boost integer.hpp header file -------------------------------------------// + +// Copyright Beman Dawes and Daryle Walker 1999. 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) + +// See http://www.boost.org/libs/integer for documentation. + +// Revision History +// 22 Sep 01 Added value-based integer templates. (Daryle Walker) +// 01 Apr 01 Modified to use new header. (John Maddock) +// 30 Jul 00 Add typename syntax fix (Jens Maurer) +// 28 Aug 99 Initial version + +#ifndef BOOST_INTEGER_HPP +#define BOOST_INTEGER_HPP + +#include // self include + +#include // for boost::integer_traits +#include // for std::numeric_limits + +namespace boost +{ + + // Helper templates ------------------------------------------------------// + + // fast integers from least integers + // int_fast_t<> works correctly for unsigned too, in spite of the name. + template< typename LeastInt > + struct int_fast_t { typedef LeastInt fast; }; // imps may specialize + + // convert category to type + template< int Category > struct int_least_helper {}; // default is empty + + // specializatons: 1=long, 2=int, 3=short, 4=signed char, + // 6=unsigned long, 7=unsigned int, 8=unsigned short, 9=unsigned char + // no specializations for 0 and 5: requests for a type > long are in error + template<> struct int_least_helper<1> { typedef long least; }; + template<> struct int_least_helper<2> { typedef int least; }; + template<> struct int_least_helper<3> { typedef short least; }; + template<> struct int_least_helper<4> { typedef signed char least; }; + template<> struct int_least_helper<6> { typedef unsigned long least; }; + template<> struct int_least_helper<7> { typedef unsigned int least; }; + template<> struct int_least_helper<8> { typedef unsigned short least; }; + template<> struct int_least_helper<9> { typedef unsigned char least; }; + + // integer templates specifying number of bits ---------------------------// + + // signed + template< int Bits > // bits (including sign) required + struct int_t + { + typedef typename int_least_helper + < + (Bits-1 <= std::numeric_limits::digits) + + (Bits-1 <= std::numeric_limits::digits) + + (Bits-1 <= std::numeric_limits::digits) + + (Bits-1 <= std::numeric_limits::digits) + >::least least; + typedef typename int_fast_t::fast fast; + }; + + // unsigned + template< int Bits > // bits required + struct uint_t + { + typedef typename int_least_helper + < + 5 + + (Bits <= std::numeric_limits::digits) + + (Bits <= std::numeric_limits::digits) + + (Bits <= std::numeric_limits::digits) + + (Bits <= std::numeric_limits::digits) + >::least least; + typedef typename int_fast_t::fast fast; + // int_fast_t<> works correctly for unsigned too, in spite of the name. + }; + + // integer templates specifying extreme value ----------------------------// + + // signed + template< long MaxValue > // maximum value to require support + struct int_max_value_t + { + typedef typename int_least_helper + < + (MaxValue <= integer_traits::const_max) + + (MaxValue <= integer_traits::const_max) + + (MaxValue <= integer_traits::const_max) + + (MaxValue <= integer_traits::const_max) + >::least least; + typedef typename int_fast_t::fast fast; + }; + + template< long MinValue > // minimum value to require support + struct int_min_value_t + { + typedef typename int_least_helper + < + (MinValue >= integer_traits::const_min) + + (MinValue >= integer_traits::const_min) + + (MinValue >= integer_traits::const_min) + + (MinValue >= integer_traits::const_min) + >::least least; + typedef typename int_fast_t::fast fast; + }; + + // unsigned + template< unsigned long Value > // maximum value to require support + struct uint_value_t + { + typedef typename int_least_helper + < + 5 + + (Value <= integer_traits::const_max) + + (Value <= integer_traits::const_max) + + (Value <= integer_traits::const_max) + + (Value <= integer_traits::const_max) + >::least least; + typedef typename int_fast_t::fast fast; + }; + + +} // namespace boost + +#endif // BOOST_INTEGER_HPP diff --git a/win32/include/boost/integer/integer_mask.hpp b/win32/include/boost/integer/integer_mask.hpp new file mode 100755 index 000000000..49060bcd7 --- /dev/null +++ b/win32/include/boost/integer/integer_mask.hpp @@ -0,0 +1,93 @@ +// Boost integer/integer_mask.hpp header file ------------------------------// + +// (C) Copyright Daryle Walker 2001. +// 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_INTEGER_INTEGER_MASK_HPP +#define BOOST_INTEGER_INTEGER_MASK_HPP + +#include // self include + +#include // for BOOST_STATIC_CONSTANT +#include // for boost::uint_t + +#include // for UCHAR_MAX, etc. +#include // for std::size_t + +#include // for std::numeric_limits + + +namespace boost +{ + + +// Specified single-bit mask class declaration -----------------------------// +// (Lowest bit starts counting at 0.) + +template < std::size_t Bit > +struct high_bit_mask_t +{ + typedef typename uint_t<(Bit + 1)>::least least; + typedef typename uint_t<(Bit + 1)>::fast fast; + + BOOST_STATIC_CONSTANT( least, high_bit = (least( 1u ) << Bit) ); + BOOST_STATIC_CONSTANT( fast, high_bit_fast = (fast( 1u ) << Bit) ); + + BOOST_STATIC_CONSTANT( std::size_t, bit_position = Bit ); + +}; // boost::high_bit_mask_t + + +// Specified bit-block mask class declaration ------------------------------// +// Makes masks for the lowest N bits +// (Specializations are needed when N fills up a type.) + +template < std::size_t Bits > +struct low_bits_mask_t +{ + typedef typename uint_t::least least; + typedef typename uint_t::fast fast; + + BOOST_STATIC_CONSTANT( least, sig_bits = (~( ~(least( 0u )) << Bits )) ); + BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); + + BOOST_STATIC_CONSTANT( std::size_t, bit_count = Bits ); + +}; // boost::low_bits_mask_t + + +#define BOOST_LOW_BITS_MASK_SPECIALIZE( Type ) \ + template < > struct low_bits_mask_t< std::numeric_limits::digits > { \ + typedef std::numeric_limits limits_type; \ + typedef uint_t::least least; \ + typedef uint_t::fast fast; \ + BOOST_STATIC_CONSTANT( least, sig_bits = (~( least(0u) )) ); \ + BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); \ + BOOST_STATIC_CONSTANT( std::size_t, bit_count = limits_type::digits ); \ + } + +BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned char ); + +#if USHRT_MAX > UCHAR_MAX +BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned short ); +#endif + +#if UINT_MAX > USHRT_MAX +BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned int ); +#endif + +#if ULONG_MAX > UINT_MAX +BOOST_LOW_BITS_MASK_SPECIALIZE( unsigned long ); +#endif + +#undef BOOST_LOW_BITS_MASK_SPECIALIZE + + +} // namespace boost + + +#endif // BOOST_INTEGER_INTEGER_MASK_HPP diff --git a/win32/include/boost/integer/static_log2.hpp b/win32/include/boost/integer/static_log2.hpp new file mode 100755 index 000000000..95ffcd40d --- /dev/null +++ b/win32/include/boost/integer/static_log2.hpp @@ -0,0 +1,132 @@ +// -------------- Boost static_log2.hpp header file ----------------------- // +// +// Copyright (C) 2001 Daryle Walker. +// Copyright (C) 2003 Vesa Karvonen. +// Copyright (C) 2003 Gennaro Prota. +// +// 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) +// +// --------------------------------------------------- +// See http://www.boost.org/libs/integer for documentation. +// ------------------------------------------------------------------------- // + + +#ifndef BOOST_INTEGER_STATIC_LOG2_HPP +#define BOOST_INTEGER_STATIC_LOG2_HPP + +#include "boost/config.hpp" // for BOOST_STATIC_CONSTANT + +namespace boost { + + namespace detail { + + namespace static_log2_impl { + + // choose_initial_n<> + // + // Recursively doubles its integer argument, until it + // becomes >= of the "width" (C99, 6.2.6.2p4) of + // static_log2_argument_type. + // + // Used to get the maximum power of two less then the width. + // + // Example: if on your platform argument_type has 48 value + // bits it yields n=32. + // + // It's easy to prove that, starting from such a value + // of n, the core algorithm works correctly for any width + // of static_log2_argument_type and that recursion always + // terminates with x = 1 and n = 0 (see the algorithm's + // invariant). + + typedef unsigned long argument_type; + typedef int result_type; + + + template + struct choose_initial_n { + + enum { c = (argument_type(1) << n << n) != 0 }; + BOOST_STATIC_CONSTANT( + result_type, + value = !c*n + choose_initial_n<2*c*n>::value + ); + + }; + + template <> + struct choose_initial_n<0> { + BOOST_STATIC_CONSTANT(result_type, value = 0); + }; + + + + // start computing from n_zero - must be a power of two + const result_type n_zero = 16; + const result_type initial_n = choose_initial_n::value; + + // static_log2_impl<> + // + // * Invariant: + // 2n + // 1 <= x && x < 2 at the start of each recursion + // (see also choose_initial_n<>) + // + // * Type requirements: + // + // argument_type maybe any unsigned type with at least n_zero + 1 + // value bits. (Note: If larger types will be standardized -e.g. + // unsigned long long- then the argument_type typedef can be + // changed without affecting the rest of the code.) + // + + template + struct static_log2_impl { + + enum { c = (x >> n) > 0 }; // x >= 2**n ? + BOOST_STATIC_CONSTANT( + result_type, + value = c*n + (static_log2_impl< (x>>c*n), n/2 >::value) + ); + + }; + + template <> + struct static_log2_impl<1, 0> { + BOOST_STATIC_CONSTANT(result_type, value = 0); + }; + + } + } // detail + + + + // -------------------------------------- + // static_log2 + // ---------------------------------------- + + typedef detail::static_log2_impl::argument_type static_log2_argument_type; + typedef detail::static_log2_impl::result_type static_log2_result_type; + + + template + struct static_log2 { + + BOOST_STATIC_CONSTANT( + static_log2_result_type, + value = detail::static_log2_impl::static_log2_impl::value + ); + + }; + + + template <> + struct static_log2<0> { }; + +} + + + +#endif // include guard diff --git a/win32/include/boost/integer/static_min_max.hpp b/win32/include/boost/integer/static_min_max.hpp new file mode 100755 index 000000000..e00a4af13 --- /dev/null +++ b/win32/include/boost/integer/static_min_max.hpp @@ -0,0 +1,55 @@ +// Boost integer/static_min_max.hpp header file ----------------------------// + +// (C) Copyright Daryle Walker 2001. +// 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_INTEGER_STATIC_MIN_MAX_HPP +#define BOOST_INTEGER_STATIC_MIN_MAX_HPP + +#include // self include + +#include // for BOOST_STATIC_CONSTANT + + +namespace boost +{ + + +// Compile-time extrema class declarations ---------------------------------// +// Get the minimum or maximum of two values, signed or unsigned. + +template < long Value1, long Value2 > +struct static_signed_min +{ + BOOST_STATIC_CONSTANT( long, value = (Value1 > Value2) ? Value2 : Value1 ); +}; + +template < long Value1, long Value2 > +struct static_signed_max +{ + BOOST_STATIC_CONSTANT( long, value = (Value1 < Value2) ? Value2 : Value1 ); +}; + +template < unsigned long Value1, unsigned long Value2 > +struct static_unsigned_min +{ + BOOST_STATIC_CONSTANT( unsigned long, value + = (Value1 > Value2) ? Value2 : Value1 ); +}; + +template < unsigned long Value1, unsigned long Value2 > +struct static_unsigned_max +{ + BOOST_STATIC_CONSTANT( unsigned long, value + = (Value1 < Value2) ? Value2 : Value1 ); +}; + + +} // namespace boost + + +#endif // BOOST_INTEGER_STATIC_MIN_MAX_HPP diff --git a/win32/include/boost/integer_fwd.hpp b/win32/include/boost/integer_fwd.hpp new file mode 100755 index 000000000..07d963d98 --- /dev/null +++ b/win32/include/boost/integer_fwd.hpp @@ -0,0 +1,152 @@ +// Boost integer_fwd.hpp header file ---------------------------------------// + +// (C) Copyright Dave Abrahams and Daryle Walker 2001. 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) + +// See http://www.boost.org/libs/integer for documentation. + +#ifndef BOOST_INTEGER_FWD_HPP +#define BOOST_INTEGER_FWD_HPP + +#include // for UCHAR_MAX, etc. +#include // for std::size_t + +#include // for BOOST_NO_INTRINSIC_WCHAR_T +#include // for std::numeric_limits + + +namespace boost +{ + + +// From ------------------------------------------------// + +// Only has typedefs or using statements, with #conditionals + + +// From -----------------------------------------// + +template < class T > + class integer_traits; + +template < > + class integer_traits< bool >; + +template < > + class integer_traits< char >; + +template < > + class integer_traits< signed char >; + +template < > + class integer_traits< unsigned char >; + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template < > + class integer_traits< wchar_t >; +#endif + +template < > + class integer_traits< short >; + +template < > + class integer_traits< unsigned short >; + +template < > + class integer_traits< int >; + +template < > + class integer_traits< unsigned int >; + +template < > + class integer_traits< long >; + +template < > + class integer_traits< unsigned long >; + +#ifdef ULLONG_MAX +template < > + class integer_traits< ::boost::long_long_type>; + +template < > + class integer_traits< ::boost::ulong_long_type >; +#endif + + +// From ------------------------------------------------// + +template < typename LeastInt > + struct int_fast_t; + +template< int Bits > + struct int_t; + +template< int Bits > + struct uint_t; + +template< long MaxValue > + struct int_max_value_t; + +template< long MinValue > + struct int_min_value_t; + +template< unsigned long Value > + struct uint_value_t; + + +// From -----------------------------------// + +template < std::size_t Bit > + struct high_bit_mask_t; + +template < std::size_t Bits > + struct low_bits_mask_t; + +template < > + struct low_bits_mask_t< ::std::numeric_limits::digits >; + +#if USHRT_MAX > UCHAR_MAX +template < > + struct low_bits_mask_t< ::std::numeric_limits::digits >; +#endif + +#if UINT_MAX > USHRT_MAX +template < > + struct low_bits_mask_t< ::std::numeric_limits::digits >; +#endif + +#if ULONG_MAX > UINT_MAX +template < > + struct low_bits_mask_t< ::std::numeric_limits::digits >; +#endif + + +// From ------------------------------------// + +template < unsigned long Value > + struct static_log2; + +template < > + struct static_log2< 0ul >; + + +// From ---------------------------------// + +template < long Value1, long Value2 > + struct static_signed_min; + +template < long Value1, long Value2 > + struct static_signed_max; + +template < unsigned long Value1, unsigned long Value2 > + struct static_unsigned_min; + +template < unsigned long Value1, unsigned long Value2 > + struct static_unsigned_max; + + +} // namespace boost + + +#endif // BOOST_INTEGER_FWD_HPP diff --git a/win32/include/boost/integer_traits.hpp b/win32/include/boost/integer_traits.hpp new file mode 100755 index 000000000..24b6774e9 --- /dev/null +++ b/win32/include/boost/integer_traits.hpp @@ -0,0 +1,236 @@ +/* boost integer_traits.hpp header file + * + * Copyright Jens Maurer 2000 + * 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) + * + * $Id: integer_traits.hpp 32576 2006-02-05 10:19:42Z johnmaddock $ + * + * Idea by Beman Dawes, Ed Brey, Steve Cleary, and Nathan Myers + */ + +// See http://www.boost.org/libs/integer for documentation. + + +#ifndef BOOST_INTEGER_TRAITS_HPP +#define BOOST_INTEGER_TRAITS_HPP + +#include +#include + +// These are an implementation detail and not part of the interface +#include +// we need wchar.h for WCHAR_MAX/MIN but not all platforms provide it, +// and some may have but not ... +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) && (!defined(BOOST_NO_CWCHAR) || defined(sun) || defined(__sun) || defined(__QNX__)) +#include +#endif + + +namespace boost { +template +class integer_traits : public std::numeric_limits +{ +public: + BOOST_STATIC_CONSTANT(bool, is_integral = false); +}; + +namespace detail { +template +class integer_traits_base +{ +public: + BOOST_STATIC_CONSTANT(bool, is_integral = true); + BOOST_STATIC_CONSTANT(T, const_min = min_val); + BOOST_STATIC_CONSTANT(T, const_max = max_val); +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool integer_traits_base::is_integral; + +template +const T integer_traits_base::const_min; + +template +const T integer_traits_base::const_max; +#endif + +} // namespace detail + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template<> +class integer_traits + : public std::numeric_limits, + // Don't trust WCHAR_MIN and WCHAR_MAX with Mac OS X's native + // library: they are wrong! +#if defined(WCHAR_MIN) && defined(WCHAR_MAX) && !defined(__APPLE__) + public detail::integer_traits_base +#elif defined(__BORLANDC__) || defined(__CYGWIN__) || defined(__MINGW32__) || (defined(__BEOS__) && defined(__GNUC__)) + // No WCHAR_MIN and WCHAR_MAX, whar_t is short and unsigned: + public detail::integer_traits_base +#elif (defined(__sgi) && (!defined(__SGI_STL_PORT) || __SGI_STL_PORT < 0x400))\ + || (defined __APPLE__)\ + || (defined(__OpenBSD__) && defined(__GNUC__))\ + || (defined(__NetBSD__) && defined(__GNUC__))\ + || (defined(__FreeBSD__) && defined(__GNUC__))\ + || (defined(__DragonFly__) && defined(__GNUC__))\ + || (defined(__hpux) && defined(__GNUC__) && (__GNUC__ == 3) && !defined(__SGI_STL_PORT)) + // No WCHAR_MIN and WCHAR_MAX, wchar_t has the same range as int. + // - SGI MIPSpro with native library + // - gcc 3.x on HP-UX + // - Mac OS X with native library + // - gcc on FreeBSD, OpenBSD and NetBSD + public detail::integer_traits_base +#elif defined(__hpux) && defined(__GNUC__) && (__GNUC__ == 2) && !defined(__SGI_STL_PORT) + // No WCHAR_MIN and WCHAR_MAX, wchar_t has the same range as unsigned int. + // - gcc 2.95.x on HP-UX + // (also, std::numeric_limits appears to return the wrong values). + public detail::integer_traits_base +#else +#error No WCHAR_MIN and WCHAR_MAX present, please adjust integer_traits<> for your compiler. +#endif +{ }; +#endif // BOOST_NO_INTRINSIC_WCHAR_T + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) +#if defined(ULLONG_MAX) && defined(BOOST_HAS_LONG_LONG) + +template<> +class integer_traits< ::boost::long_long_type> + : public std::numeric_limits< ::boost::long_long_type>, + public detail::integer_traits_base< ::boost::long_long_type, LLONG_MIN, LLONG_MAX> +{ }; + +template<> +class integer_traits< ::boost::ulong_long_type> + : public std::numeric_limits< ::boost::ulong_long_type>, + public detail::integer_traits_base< ::boost::ulong_long_type, 0, ULLONG_MAX> +{ }; + +#elif defined(ULONG_LONG_MAX) && defined(BOOST_HAS_LONG_LONG) + +template<> +class integer_traits< ::boost::long_long_type> : public std::numeric_limits< ::boost::long_long_type>, public detail::integer_traits_base< ::boost::long_long_type, LONG_LONG_MIN, LONG_LONG_MAX>{ }; +template<> +class integer_traits< ::boost::ulong_long_type> + : public std::numeric_limits< ::boost::ulong_long_type>, + public detail::integer_traits_base< ::boost::ulong_long_type, 0, ULONG_LONG_MAX> +{ }; + +#elif defined(ULONGLONG_MAX) && defined(BOOST_HAS_LONG_LONG) + +template<> +class integer_traits< ::boost::long_long_type> + : public std::numeric_limits< ::boost::long_long_type>, + public detail::integer_traits_base< ::boost::long_long_type, LONGLONG_MIN, LONGLONG_MAX> +{ }; + +template<> +class integer_traits< ::boost::ulong_long_type> + : public std::numeric_limits< ::boost::ulong_long_type>, + public detail::integer_traits_base< ::boost::ulong_long_type, 0, ULONGLONG_MAX> +{ }; + +#elif defined(_LLONG_MAX) && defined(_C2) && defined(BOOST_HAS_LONG_LONG) + +template<> +class integer_traits< ::boost::long_long_type> + : public std::numeric_limits< ::boost::long_long_type>, + public detail::integer_traits_base< ::boost::long_long_type, -_LLONG_MAX - _C2, _LLONG_MAX> +{ }; + +template<> +class integer_traits< ::boost::ulong_long_type> + : public std::numeric_limits< ::boost::ulong_long_type>, + public detail::integer_traits_base< ::boost::ulong_long_type, 0, _ULLONG_MAX> +{ }; + +#elif defined(BOOST_HAS_LONG_LONG) +// +// we have long long but no constants, this happens for example with gcc in -ansi mode, +// we'll just have to work out the values for ourselves (assumes 2's compliment representation): +// +template<> +class integer_traits< ::boost::long_long_type> + : public std::numeric_limits< ::boost::long_long_type>, + public detail::integer_traits_base< ::boost::long_long_type, (1LL << (sizeof(::boost::long_long_type) - 1)), ~(1LL << (sizeof(::boost::long_long_type) - 1))> +{ }; + +template<> +class integer_traits< ::boost::ulong_long_type> + : public std::numeric_limits< ::boost::ulong_long_type>, + public detail::integer_traits_base< ::boost::ulong_long_type, 0, ~0uLL> +{ }; + +#endif +#endif + +} // namespace boost + +#endif /* BOOST_INTEGER_TRAITS_HPP */ + + + diff --git a/win32/include/boost/interprocess/allocators/adaptive_pool.hpp b/win32/include/boost/interprocess/allocators/adaptive_pool.hpp new file mode 100755 index 000000000..e5fed628d --- /dev/null +++ b/win32/include/boost/interprocess/allocators/adaptive_pool.hpp @@ -0,0 +1,467 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP +#define BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes adaptive_pool pooled shared memory STL compatible allocator + +namespace boost { +namespace interprocess { + +/// @cond + +namespace detail{ + +template < unsigned int Version + , class T + , class SegmentManager + , std::size_t NodesPerBlock + , std::size_t MaxFreeBlocks + , unsigned char OverheadPercent + > +class adaptive_pool_base + : public node_pool_allocation_impl + < adaptive_pool_base + < Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> + , Version + , T + , SegmentManager + > +{ + public: + typedef typename SegmentManager::void_pointer void_pointer; + typedef SegmentManager segment_manager; + typedef adaptive_pool_base + self_t; + + /// @cond + + template + struct node_pool + { + typedef detail::shared_adaptive_node_pool + < SegmentManager, sizeof_value::value, NodesPerBlock, MaxFreeBlocks, OverheadPercent> type; + + static type *get(void *p) + { return static_cast(p); } + }; + /// @endcond + + BOOST_STATIC_ASSERT((Version <=2)); + + public: + //------- + typedef typename detail:: + pointer_to_other::type pointer; + typedef typename detail:: + pointer_to_other::type const_pointer; + typedef T value_type; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef detail::version_type version; + typedef transform_iterator + < typename SegmentManager:: + multiallocation_iterator + , detail::cast_functor > multiallocation_iterator; + typedef typename SegmentManager:: + multiallocation_chain multiallocation_chain; + + //!Obtains adaptive_pool_base from + //!adaptive_pool_base + template + struct rebind + { + typedef adaptive_pool_base other; + }; + + /// @cond + private: + //!Not assignable from related adaptive_pool_base + template + adaptive_pool_base& operator= + (const adaptive_pool_base&); + + /// @endcond + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + adaptive_pool_base(segment_manager *segment_mngr) + : mp_node_pool(detail::get_or_create_node_pool::type>(segment_mngr)) { } + + //!Copy constructor from other adaptive_pool_base. Increments the reference + //!count of the associated node pool. Never throws + adaptive_pool_base(const adaptive_pool_base &other) + : mp_node_pool(other.get_node_pool()) + { + node_pool<0>::get(detail::get_pointer(mp_node_pool))->inc_ref_count(); + } + + //!Assignment from other adaptive_pool_base + adaptive_pool_base& operator=(const adaptive_pool_base &other) + { + adaptive_pool_base c(other); + swap(*this, c); + return *this; + } + + //!Copy constructor from related adaptive_pool_base. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + adaptive_pool_base + (const adaptive_pool_base &other) + : mp_node_pool(detail::get_or_create_node_pool::type>(other.get_segment_manager())) { } + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~adaptive_pool_base() + { detail::destroy_node_pool_if_last_link(node_pool<0>::get(detail::get_pointer(mp_node_pool))); } + + //!Returns a pointer to the node pool. + //!Never throws + void* get_node_pool() const + { return detail::get_pointer(mp_node_pool); } + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const + { return node_pool<0>::get(detail::get_pointer(mp_node_pool))->get_segment_manager(); } + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2) + { detail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); } + + /// @cond + private: + void_pointer mp_node_pool; + /// @endcond +}; + +//!Equality test for same type +//!of adaptive_pool_base +template inline +bool operator==(const adaptive_pool_base &alloc1, + const adaptive_pool_base &alloc2) + { return alloc1.get_node_pool() == alloc2.get_node_pool(); } + +//!Inequality test for same type +//!of adaptive_pool_base +template inline +bool operator!=(const adaptive_pool_base &alloc1, + const adaptive_pool_base &alloc2) + { return alloc1.get_node_pool() != alloc2.get_node_pool(); } + +template < class T + , class SegmentManager + , std::size_t NodesPerBlock = 64 + , std::size_t MaxFreeBlocks = 2 + , unsigned char OverheadPercent = 5 + > +class adaptive_pool_v1 + : public adaptive_pool_base + < 1 + , T + , SegmentManager + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > +{ + public: + typedef detail::adaptive_pool_base + < 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t; + + template + struct rebind + { + typedef adaptive_pool_v1 other; + }; + + adaptive_pool_v1(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + adaptive_pool_v1 + (const adaptive_pool_v1 &other) + : base_t(other) + {} +}; + +} //namespace detail{ + +/// @endcond + +//!An STL node allocator that uses a segment manager as memory +//!source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the allocator in shared memory, memory mapped-files, etc... +//! +//!This node allocator shares a segregated storage between all instances +//!of adaptive_pool with equal sizeof(T) placed in the same segment +//!group. NodesPerBlock is the number of nodes allocated at once when the allocator +//!needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks +//!that the adaptive node pool will hold. The rest of the totally free blocks will be +//!deallocated with the segment manager. +//! +//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator: +//!(memory usable for nodes / total memory allocated from the segment manager) +template < class T + , class SegmentManager + , std::size_t NodesPerBlock + , std::size_t MaxFreeBlocks + , unsigned char OverheadPercent + > +class adaptive_pool + /// @cond + : public detail::adaptive_pool_base + < 2 + , T + , SegmentManager + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > + /// @endcond +{ + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + typedef detail::adaptive_pool_base + < 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t; + public: + typedef detail::version_type version; + + template + struct rebind + { + typedef adaptive_pool other; + }; + + adaptive_pool(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + adaptive_pool + (const adaptive_pool &other) + : base_t(other) + {} + + #else //BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + typedef implementation_defined::segment_manager segment_manager; + typedef segment_manager::void_pointer void_pointer; + typedef implementation_defined::pointer pointer; + typedef implementation_defined::const_pointer const_pointer; + typedef T value_type; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + //!Obtains adaptive_pool from + //!adaptive_pool + template + struct rebind + { + typedef adaptive_pool other; + }; + + private: + //!Not assignable from + //!related adaptive_pool + template + adaptive_pool& operator= + (const adaptive_pool&); + + //!Not assignable from + //!other adaptive_pool + //adaptive_pool& operator=(const adaptive_pool&); + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + adaptive_pool(segment_manager *segment_mngr); + + //!Copy constructor from other adaptive_pool. Increments the reference + //!count of the associated node pool. Never throws + adaptive_pool(const adaptive_pool &other); + + //!Copy constructor from related adaptive_pool. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + adaptive_pool + (const adaptive_pool &other); + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~adaptive_pool(); + + //!Returns a pointer to the node pool. + //!Never throws + void* get_node_pool() const; + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const; + + //!Returns the number of elements that could be allocated. + //!Never throws + size_type max_size() const; + + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0); + + //!Deallocate allocated memory. + //!Never throws + void deallocate(const pointer &ptr, size_type count); + + //!Deallocates all free blocks + //!of the pool + void deallocate_free_blocks(); + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2); + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const; + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const; + + //!Copy construct an object. + //!Throws if T's copy constructor throws + void construct(const pointer &ptr, const_reference v); + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr); + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const; + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, const pointer &reuse = 0); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements); + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_iterator it); + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one(); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + multiallocation_iterator allocate_individual(std::size_t num_elements); + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_iterator it); + #endif +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Equality test for same type +//!of adaptive_pool +template inline +bool operator==(const adaptive_pool &alloc1, + const adaptive_pool &alloc2); + +//!Inequality test for same type +//!of adaptive_pool +template inline +bool operator!=(const adaptive_pool &alloc1, + const adaptive_pool &alloc2); + +#endif + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP + diff --git a/win32/include/boost/interprocess/allocators/allocation_type.hpp b/win32/include/boost/interprocess/allocators/allocation_type.hpp new file mode 100755 index 000000000..ab2b2157e --- /dev/null +++ b/win32/include/boost/interprocess/allocators/allocation_type.hpp @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_TYPE_COMMAND_HPP +#define BOOST_INTERPROCESS_TYPE_COMMAND_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +namespace boost { +namespace interprocess { + +/// @cond +enum allocation_type_v +{ + // constants for allocation commands + allocate_new_v = 0x01, + expand_fwd_v = 0x02, + expand_bwd_v = 0x04, +// expand_both = expand_fwd | expand_bwd, +// expand_or_new = allocate_new | expand_both, + shrink_in_place_v = 0x08, + nothrow_allocation_v = 0x10, + zero_memory_v = 0x20, + try_shrink_in_place_v = 0x40 +}; + +typedef int allocation_type; +/// @endcond +static const allocation_type allocate_new = (allocation_type)allocate_new_v; +static const allocation_type expand_fwd = (allocation_type)expand_fwd_v; +static const allocation_type expand_bwd = (allocation_type)expand_bwd_v; +static const allocation_type shrink_in_place = (allocation_type)shrink_in_place_v; +static const allocation_type try_shrink_in_place= (allocation_type)try_shrink_in_place_v; +static const allocation_type nothrow_allocation = (allocation_type)nothrow_allocation_v; +static const allocation_type zero_memory = (allocation_type)zero_memory_v; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_TYPE_COMMAND_HPP + diff --git a/win32/include/boost/interprocess/allocators/allocator.hpp b/win32/include/boost/interprocess/allocators/allocator.hpp new file mode 100755 index 000000000..9c0303b76 --- /dev/null +++ b/win32/include/boost/interprocess/allocators/allocator.hpp @@ -0,0 +1,306 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_ALLOCATOR_HPP +#define BOOST_INTERPROCESS_ALLOCATOR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +//!\file +//!Describes an allocator that allocates portions of fixed size +//!memory buffer (shared memory, mapped file...) + +namespace boost { +namespace interprocess { + + +//!An STL compatible allocator that uses a segment manager as +//!memory source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the allocator in shared memory, memory mapped-files, etc... +template +class allocator +{ + public: + //Segment manager + typedef SegmentManager segment_manager; + typedef typename SegmentManager::void_pointer void_pointer; + + /// @cond + private: + + //Self type + typedef allocator self_t; + + //Pointer to void + typedef typename segment_manager::void_pointer aux_pointer_t; + + //Typedef to const void pointer + typedef typename + detail::pointer_to_other + ::type cvoid_ptr; + + //Pointer to the allocator + typedef typename detail::pointer_to_other + ::type alloc_ptr_t; + + //Not assignable from related allocator + template + allocator& operator=(const allocator&); + + //Not assignable from other allocator + allocator& operator=(const allocator&); + + //Pointer to the allocator + alloc_ptr_t mp_mngr; + /// @endcond + + public: + typedef T value_type; + typedef typename detail::pointer_to_other + ::type pointer; + typedef typename detail:: + pointer_to_other::type const_pointer; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef detail::version_type version; + + /// @cond + + //Experimental. Don't use. + typedef transform_iterator + < typename SegmentManager:: + multiallocation_iterator + , detail::cast_functor > multiallocation_iterator; + typedef detail::multiallocation_chain_adaptor + multiallocation_chain; + + /// @endcond + + //!Obtains an allocator that allocates + //!objects of type T2 + template + struct rebind + { + typedef allocator other; + }; + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const + { return detail::get_pointer(mp_mngr); } + + //!Constructor from the segment manager. + //!Never throws + allocator(segment_manager *segment_mngr) + : mp_mngr(segment_mngr) { } + + //!Constructor from other allocator. + //!Never throws + allocator(const allocator &other) + : mp_mngr(other.get_segment_manager()){ } + + //!Constructor from related allocator. + //!Never throws + template + allocator(const allocator &other) + : mp_mngr(other.get_segment_manager()){} + + //!Allocates memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_ptr hint = 0) + { + (void)hint; + if(count > this->max_size()) + throw bad_alloc(); + return pointer((value_type*)mp_mngr->allocate(count*sizeof(T))); + } + + //!Deallocates memory previously allocated. + //!Never throws + void deallocate(const pointer &ptr, size_type) + { mp_mngr->deallocate((void*)detail::get_pointer(ptr)); } + + //!Returns the number of elements that could be allocated. + //!Never throws + size_type max_size() const + { return mp_mngr->get_size()/sizeof(T); } + + //!Swap segment manager. Does not throw. If each allocator is placed in + //!different memory segments, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2) + { detail::do_swap(alloc1.mp_mngr, alloc2.mp_mngr); } + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const + { + return (size_type)mp_mngr->size(detail::get_pointer(p))/sizeof(T); + } + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, const pointer &reuse = 0) + { + return mp_mngr->allocation_command + (command, limit_size, preferred_size, received_size, detail::get_pointer(reuse)); + } + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements) + { + return multiallocation_iterator + (mp_mngr->allocate_many(sizeof(T)*elem_size, num_elements)); + } + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements) + { + return multiallocation_iterator + (mp_mngr->allocate_many(elem_sizes, n_elements, sizeof(T))); + } + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_iterator it) + { return mp_mngr->deallocate_many(it.base()); } + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one() + { return this->allocate(1); } + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + multiallocation_iterator allocate_individual(std::size_t num_elements) + { return this->allocate_many(1, num_elements); } + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p) + { return this->deallocate(p, 1); } + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_iterator it) + { return this->deallocate_many(it); } + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const + { return pointer(boost::addressof(value)); } + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const + { return const_pointer(boost::addressof(value)); } + + //!Copy construct an object + //!Throws if T's copy constructor throws + void construct(const pointer &ptr, const_reference v) + { new((void*)detail::get_pointer(ptr)) value_type(v); } + + //!Default construct an object. + //!Throws if T's default constructor throws + void construct(const pointer &ptr) + { new((void*)detail::get_pointer(ptr)) value_type; } + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr) + { BOOST_ASSERT(ptr != 0); (*ptr).~value_type(); } +}; + +//!Equality test for same type +//!of allocator +template inline +bool operator==(const allocator &alloc1, + const allocator &alloc2) + { return alloc1.get_segment_manager() == alloc2.get_segment_manager(); } + +//!Inequality test for same type +//!of allocator +template inline +bool operator!=(const allocator &alloc1, + const allocator &alloc2) + { return alloc1.get_segment_manager() != alloc2.get_segment_manager(); } + +} //namespace interprocess { + +/// @cond + +template +struct has_trivial_destructor; + +template +struct has_trivial_destructor + > +{ + enum { value = true }; +}; +/// @endcond + +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_ALLOCATOR_HPP + diff --git a/win32/include/boost/interprocess/allocators/cached_adaptive_pool.hpp b/win32/include/boost/interprocess/allocators/cached_adaptive_pool.hpp new file mode 100755 index 000000000..cdf5ac5a0 --- /dev/null +++ b/win32/include/boost/interprocess/allocators/cached_adaptive_pool.hpp @@ -0,0 +1,354 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP +#define BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes cached_adaptive_pool pooled shared memory STL compatible allocator + +namespace boost { +namespace interprocess { + +/// @cond + +namespace detail { + +template < class T + , class SegmentManager + , std::size_t NodesPerBlock = 64 + , std::size_t MaxFreeBlocks = 2 + , unsigned char OverheadPercent = 5 + > +class cached_adaptive_pool_v1 + : public detail::cached_allocator_impl + < T + , detail::shared_adaptive_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > + , 1> +{ + public: + typedef detail::cached_allocator_impl + < T + , detail::shared_adaptive_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > + , 1> base_t; + + template + struct rebind + { + typedef cached_adaptive_pool_v1 + other; + }; + + cached_adaptive_pool_v1(SegmentManager *segment_mngr, + std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) + : base_t(segment_mngr, max_cached_nodes) + {} + + template + cached_adaptive_pool_v1 + (const cached_adaptive_pool_v1 + &other) + : base_t(other) + {} +}; + +} //namespace detail{ + +/// @endcond + +//!An STL node allocator that uses a segment manager as memory +//!source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the allocator in shared memory, memory mapped-files, etc... +//! +//!This node allocator shares a segregated storage between all instances of +//!cached_adaptive_pool with equal sizeof(T) placed in the same +//!memory segment. But also caches some nodes privately to +//!avoid some synchronization overhead. +//! +//!NodesPerBlock is the minimum number of nodes of nodes allocated at once when +//!the allocator needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks +//!that the adaptive node pool will hold. The rest of the totally free blocks will be +//!deallocated with the segment manager. +//! +//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator: +//!(memory usable for nodes / total memory allocated from the segment manager) +template < class T + , class SegmentManager + , std::size_t NodesPerBlock + , std::size_t MaxFreeBlocks + , unsigned char OverheadPercent + > +class cached_adaptive_pool + /// @cond + : public detail::cached_allocator_impl + < T + , detail::shared_adaptive_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > + , 2> + /// @endcond +{ + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + typedef detail::cached_allocator_impl + < T + , detail::shared_adaptive_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > + , 2> base_t; + + public: + typedef detail::version_type version; + + template + struct rebind + { + typedef cached_adaptive_pool + other; + }; + + cached_adaptive_pool(SegmentManager *segment_mngr, + std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) + : base_t(segment_mngr, max_cached_nodes) + {} + + template + cached_adaptive_pool + (const cached_adaptive_pool &other) + : base_t(other) + {} + + #else + public: + typedef implementation_defined::segment_manager segment_manager; + typedef segment_manager::void_pointer void_pointer; + typedef implementation_defined::pointer pointer; + typedef implementation_defined::const_pointer const_pointer; + typedef T value_type; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + //!Obtains cached_adaptive_pool from + //!cached_adaptive_pool + template + struct rebind + { + typedef cached_adaptive_pool other; + }; + + private: + //!Not assignable from + //!related cached_adaptive_pool + template + cached_adaptive_pool& operator= + (const cached_adaptive_pool&); + + //!Not assignable from + //!other cached_adaptive_pool + cached_adaptive_pool& operator=(const cached_adaptive_pool&); + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + cached_adaptive_pool(segment_manager *segment_mngr); + + //!Copy constructor from other cached_adaptive_pool. Increments the reference + //!count of the associated node pool. Never throws + cached_adaptive_pool(const cached_adaptive_pool &other); + + //!Copy constructor from related cached_adaptive_pool. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + cached_adaptive_pool + (const cached_adaptive_pool &other); + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~cached_adaptive_pool(); + + //!Returns a pointer to the node pool. + //!Never throws + node_pool_t* get_node_pool() const; + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const; + + //!Returns the number of elements that could be allocated. + //!Never throws + size_type max_size() const; + + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0); + + //!Deallocate allocated memory. + //!Never throws + void deallocate(const pointer &ptr, size_type count); + + //!Deallocates all free blocks + //!of the pool + void deallocate_free_blocks(); + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2); + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const; + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const; + + //!Copy construct an object. + //!Throws if T's copy constructor throws + void construct(const pointer &ptr, const_reference v); + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr); + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const; + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, const pointer &reuse = 0); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements); + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_iterator it); + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one(); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + multiallocation_iterator allocate_individual(std::size_t num_elements); + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_iterator it); + //!Sets the new max cached nodes value. This can provoke deallocations + //!if "newmax" is less than current cached nodes. Never throws + void set_max_cached_nodes(std::size_t newmax); + + //!Returns the max cached nodes parameter. + //!Never throws + std::size_t get_max_cached_nodes() const; + #endif +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Equality test for same type +//!of cached_adaptive_pool +template inline +bool operator==(const cached_adaptive_pool &alloc1, + const cached_adaptive_pool &alloc2); + +//!Inequality test for same type +//!of cached_adaptive_pool +template inline +bool operator!=(const cached_adaptive_pool &alloc1, + const cached_adaptive_pool &alloc2); + +#endif + +} //namespace interprocess { +} //namespace boost { + + +#include + +#endif //#ifndef BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP + diff --git a/win32/include/boost/interprocess/allocators/cached_node_allocator.hpp b/win32/include/boost/interprocess/allocators/cached_node_allocator.hpp new file mode 100755 index 000000000..578a41073 --- /dev/null +++ b/win32/include/boost/interprocess/allocators/cached_node_allocator.hpp @@ -0,0 +1,324 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP +#define BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes cached_cached_node_allocator pooled shared memory STL compatible allocator + +namespace boost { +namespace interprocess { + + +/// @cond + +namespace detail { + +template < class T + , class SegmentManager + , std::size_t NodesPerBlock = 64 + > +class cached_node_allocator_v1 + : public detail::cached_allocator_impl + < T + , detail::shared_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + > + , 1> +{ + public: + typedef detail::cached_allocator_impl + < T + , detail::shared_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + > + , 1> base_t; + + template + struct rebind + { + typedef cached_node_allocator_v1 + other; + }; + + cached_node_allocator_v1(SegmentManager *segment_mngr, + std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) + : base_t(segment_mngr, max_cached_nodes) + {} + + template + cached_node_allocator_v1 + (const cached_node_allocator_v1 + &other) + : base_t(other) + {} +}; + +} //namespace detail{ + +/// @endcond + +template < class T + , class SegmentManager + , std::size_t NodesPerBlock + > +class cached_node_allocator + /// @cond + : public detail::cached_allocator_impl + < T + , detail::shared_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + > + , 2> + /// @endcond +{ + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + typedef detail::cached_allocator_impl + < T + , detail::shared_node_pool + < SegmentManager + , sizeof_value::value + , NodesPerBlock + > + , 2> base_t; + + public: + typedef detail::version_type version; + + template + struct rebind + { + typedef cached_node_allocator other; + }; + + cached_node_allocator(SegmentManager *segment_mngr, + std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) + : base_t(segment_mngr, max_cached_nodes) + {} + + template + cached_node_allocator + (const cached_node_allocator &other) + : base_t(other) + {} + + #else + public: + typedef implementation_defined::segment_manager segment_manager; + typedef segment_manager::void_pointer void_pointer; + typedef implementation_defined::pointer pointer; + typedef implementation_defined::const_pointer const_pointer; + typedef T value_type; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + //!Obtains cached_node_allocator from + //!cached_node_allocator + template + struct rebind + { + typedef cached_node_allocator other; + }; + + private: + //!Not assignable from + //!related cached_node_allocator + template + cached_node_allocator& operator= + (const cached_node_allocator&); + + //!Not assignable from + //!other cached_node_allocator + cached_node_allocator& operator=(const cached_node_allocator&); + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + cached_node_allocator(segment_manager *segment_mngr); + + //!Copy constructor from other cached_node_allocator. Increments the reference + //!count of the associated node pool. Never throws + cached_node_allocator(const cached_node_allocator &other); + + //!Copy constructor from related cached_node_allocator. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + cached_node_allocator + (const cached_node_allocator &other); + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~cached_node_allocator(); + + //!Returns a pointer to the node pool. + //!Never throws + node_pool_t* get_node_pool() const; + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const; + + //!Returns the number of elements that could be allocated. + //!Never throws + size_type max_size() const; + + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0); + + //!Deallocate allocated memory. + //!Never throws + void deallocate(const pointer &ptr, size_type count); + + //!Deallocates all free blocks + //!of the pool + void deallocate_free_blocks(); + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2); + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const; + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const; + + //!Default construct an object. + //!Throws if T's default constructor throws + void construct(const pointer &ptr, const_reference v); + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr); + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const; + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, const pointer &reuse = 0); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements); + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_iterator it); + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one(); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + multiallocation_iterator allocate_individual(std::size_t num_elements); + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_iterator it); + //!Sets the new max cached nodes value. This can provoke deallocations + //!if "newmax" is less than current cached nodes. Never throws + void set_max_cached_nodes(std::size_t newmax); + + //!Returns the max cached nodes parameter. + //!Never throws + std::size_t get_max_cached_nodes() const; + #endif +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Equality test for same type +//!of cached_node_allocator +template inline +bool operator==(const cached_node_allocator &alloc1, + const cached_node_allocator &alloc2); + +//!Inequality test for same type +//!of cached_node_allocator +template inline +bool operator!=(const cached_node_allocator &alloc1, + const cached_node_allocator &alloc2); + +#endif + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_CACHED_NODE_ALLOCATOR_HPP + diff --git a/win32/include/boost/interprocess/allocators/detail/adaptive_node_pool.hpp b/win32/include/boost/interprocess/allocators/detail/adaptive_node_pool.hpp new file mode 100755 index 000000000..3867ffaa5 --- /dev/null +++ b/win32/include/boost/interprocess/allocators/detail/adaptive_node_pool.hpp @@ -0,0 +1,653 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP +#define BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes the real adaptive pool shared by many Interprocess pool allocators + +namespace boost { +namespace interprocess { +namespace detail { + +template +class private_adaptive_node_pool_impl +{ + //Non-copyable + private_adaptive_node_pool_impl(); + private_adaptive_node_pool_impl(const private_adaptive_node_pool_impl &); + private_adaptive_node_pool_impl &operator=(const private_adaptive_node_pool_impl &); + + typedef typename SegmentManagerBase::void_pointer void_pointer; + static const std::size_t PayloadPerAllocation = SegmentManagerBase::PayloadPerAllocation; + public: + typedef typename node_slist::node_t node_t; + typedef typename node_slist::node_slist_t free_nodes_t; + typedef typename SegmentManagerBase::multiallocation_iterator multiallocation_iterator; + typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain; + + private: + typedef typename bi::make_set_base_hook + < bi::void_pointer + , bi::optimize_size + , bi::constant_time_size + , bi::link_mode >::type multiset_hook_t; + + struct hdr_offset_holder + { + hdr_offset_holder(std::size_t offset = 0) + : hdr_offset(offset) + {} + std::size_t hdr_offset; + }; + + struct block_info_t + : + public hdr_offset_holder, + public multiset_hook_t + { + //An intrusive list of free node from this block + free_nodes_t free_nodes; + friend bool operator <(const block_info_t &l, const block_info_t &r) + { +// { return l.free_nodes.size() < r.free_nodes.size(); } + //Let's order blocks first by free nodes and then by address + //so that highest address fully free blocks are deallocated. + //This improves returning memory to the OS (trimming). + const bool is_less = l.free_nodes.size() < r.free_nodes.size(); + const bool is_equal = l.free_nodes.size() == r.free_nodes.size(); + return is_less || (is_equal && (&l < &r)); + } + }; + typedef typename bi::make_multiset + >::type block_multiset_t; + typedef typename block_multiset_t::iterator block_iterator; + + static const std::size_t MaxAlign = alignment_of::value; + static const std::size_t HdrSize = ((sizeof(block_info_t)-1)/MaxAlign+1)*MaxAlign; + static const std::size_t HdrOffsetSize = ((sizeof(hdr_offset_holder)-1)/MaxAlign+1)*MaxAlign; + static std::size_t calculate_alignment + (std::size_t overhead_percent, std::size_t real_node_size) + { + //to-do: handle real_node_size != node_size + const std::size_t divisor = overhead_percent*real_node_size; + const std::size_t dividend = HdrOffsetSize*100; + std::size_t elements_per_subblock = (dividend - 1)/divisor + 1; + std::size_t candidate_power_of_2 = + upper_power_of_2(elements_per_subblock*real_node_size + HdrOffsetSize); + bool overhead_satisfied = false; + //Now calculate the wors-case overhead for a subblock + const std::size_t max_subblock_overhead = HdrSize + PayloadPerAllocation; + while(!overhead_satisfied){ + elements_per_subblock = (candidate_power_of_2 - max_subblock_overhead)/real_node_size; + const std::size_t overhead_size = candidate_power_of_2 - elements_per_subblock*real_node_size; + if(overhead_size*100/candidate_power_of_2 < overhead_percent){ + overhead_satisfied = true; + } + else{ + candidate_power_of_2 <<= 1; + } + } + return candidate_power_of_2; + } + + static void calculate_num_subblocks + (std::size_t alignment, std::size_t real_node_size, std::size_t elements_per_block + ,std::size_t &num_subblocks, std::size_t &real_num_node, std::size_t overhead_percent) + { + std::size_t elements_per_subblock = (alignment - HdrOffsetSize)/real_node_size; + std::size_t possible_num_subblock = (elements_per_block - 1)/elements_per_subblock + 1; + std::size_t hdr_subblock_elements = (alignment - HdrSize - PayloadPerAllocation)/real_node_size; + while(((possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements) < elements_per_block){ + ++possible_num_subblock; + } + elements_per_subblock = (alignment - HdrOffsetSize)/real_node_size; + bool overhead_satisfied = false; + while(!overhead_satisfied){ + const std::size_t total_data = (elements_per_subblock*(possible_num_subblock-1) + hdr_subblock_elements)*real_node_size; + const std::size_t total_size = alignment*possible_num_subblock; + if((total_size - total_data)*100/total_size < overhead_percent){ + overhead_satisfied = true; + } + else{ + ++possible_num_subblock; + } + } + num_subblocks = possible_num_subblock; + real_num_node = (possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements; + } + + public: + //!Segment manager typedef + typedef SegmentManagerBase segment_manager_base_type; + + //!Constructor from a segment manager. Never throws + private_adaptive_node_pool_impl + ( segment_manager_base_type *segment_mngr_base, std::size_t node_size + , std::size_t nodes_per_block, std::size_t max_free_blocks + , unsigned char overhead_percent + ) + : m_max_free_blocks(max_free_blocks) + , m_real_node_size(lcm(node_size, std::size_t(alignment_of::value))) + //Round the size to a power of two value. + //This is the total memory size (including payload) that we want to + //allocate from the general-purpose allocator + , m_real_block_alignment(calculate_alignment(overhead_percent, m_real_node_size)) + //This is the real number of nodes per block + , m_num_subblocks(0) + , m_real_num_node(0) + //General purpose allocator + , mp_segment_mngr_base(segment_mngr_base) + , m_block_multiset() + , m_totally_free_blocks(0) + { + calculate_num_subblocks(m_real_block_alignment, m_real_node_size, nodes_per_block, m_num_subblocks, m_real_num_node, overhead_percent); + } + + //!Destructor. Deallocates all allocated blocks. Never throws + ~private_adaptive_node_pool_impl() + { priv_clear(); } + + std::size_t get_real_num_node() const + { return m_real_num_node; } + + //!Returns the segment manager. Never throws + segment_manager_base_type* get_segment_manager_base()const + { return detail::get_pointer(mp_segment_mngr_base); } + + //!Allocates array of count elements. Can throw boost::interprocess::bad_alloc + void *allocate_node() + { + priv_invariants(); + //If there are no free nodes we allocate a new block + if (m_block_multiset.empty()){ + priv_alloc_block(1); + } + //We take the first free node the multiset can't be empty + return priv_take_first_node(); + } + + //!Deallocates an array pointed by ptr. Never throws + void deallocate_node(void *pElem) + { + this->priv_reinsert_nodes_in_block + (multiallocation_iterator::create_simple_range(pElem)); + //Update free block count + if(m_totally_free_blocks > m_max_free_blocks){ + this->priv_deallocate_free_blocks(m_max_free_blocks); + } + priv_invariants(); + } + + //!Allocates a singly linked list of n nodes ending in null pointer. + //!can throw boost::interprocess::bad_alloc + void allocate_nodes(multiallocation_chain &nodes, const std::size_t n) + { + try{ + priv_invariants(); + std::size_t i = 0; + while(i != n){ + //If there are no free nodes we allocate all needed blocks + if (m_block_multiset.empty()){ + priv_alloc_block(((n - i) - 1)/m_real_num_node + 1); + } + free_nodes_t &free_nodes = m_block_multiset.begin()->free_nodes; + const std::size_t free_nodes_count_before = free_nodes.size(); + if(free_nodes_count_before == m_real_num_node){ + --m_totally_free_blocks; + } + const std::size_t num_elems = ((n-i) < free_nodes_count_before) ? (n-i) : free_nodes_count_before; + for(std::size_t j = 0; j != num_elems; ++j){ + void *new_node = &free_nodes.front(); + free_nodes.pop_front(); + nodes.push_back(new_node); + } + + if(free_nodes.empty()){ + m_block_multiset.erase(m_block_multiset.begin()); + } + i += num_elems; + } + } + catch(...){ + this->deallocate_nodes(nodes, nodes.size()); + throw; + } + priv_invariants(); + } + + //!Allocates n nodes, pointed by the multiallocation_iterator. + //!Can throw boost::interprocess::bad_alloc + multiallocation_iterator allocate_nodes(const std::size_t n) + { + multiallocation_chain chain; + this->allocate_nodes(chain, n); + return chain.get_it(); + } + + //!Deallocates a linked list of nodes. Never throws + void deallocate_nodes(multiallocation_chain &nodes) + { + this->deallocate_nodes(nodes.get_it()); + nodes.reset(); + } + + //!Deallocates the first n nodes of a linked list of nodes. Never throws + void deallocate_nodes(multiallocation_chain &nodes, std::size_t n) + { + assert(nodes.size() >= n); + for(std::size_t i = 0; i < n; ++i){ + this->deallocate_node(nodes.pop_front()); + } + } + + //!Deallocates the nodes pointed by the multiallocation iterator. Never throws + void deallocate_nodes(multiallocation_iterator it) + { + this->priv_reinsert_nodes_in_block(it); + if(m_totally_free_blocks > m_max_free_blocks){ + this->priv_deallocate_free_blocks(m_max_free_blocks); + } + } + + void deallocate_free_blocks() + { this->priv_deallocate_free_blocks(0); } + + std::size_t num_free_nodes() + { + typedef typename block_multiset_t::const_iterator citerator; + std::size_t count = 0; + citerator it (m_block_multiset.begin()), itend(m_block_multiset.end()); + for(; it != itend; ++it){ + count += it->free_nodes.size(); + } + return count; + } + + void swap(private_adaptive_node_pool_impl &other) + { + assert(m_max_free_blocks == other.m_max_free_blocks); + assert(m_real_node_size == other.m_real_node_size); + assert(m_real_block_alignment == other.m_real_block_alignment); + assert(m_real_num_node == other.m_real_num_node); + std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base); + std::swap(m_totally_free_blocks, other.m_totally_free_blocks); + m_block_multiset.swap(other.m_block_multiset); + } + + //Deprecated, use deallocate_free_blocks + void deallocate_free_chunks() + { this->priv_deallocate_free_blocks(0); } + + private: + void priv_deallocate_free_blocks(std::size_t max_free_blocks) + { + priv_invariants(); + //Now check if we've reached the free nodes limit + //and check if we have free blocks. If so, deallocate as much + //as we can to stay below the limit + for( block_iterator itend = m_block_multiset.end() + ; m_totally_free_blocks > max_free_blocks + ; --m_totally_free_blocks + ){ + assert(!m_block_multiset.empty()); + block_iterator it = itend; + --it; + std::size_t num_nodes = it->free_nodes.size(); + assert(num_nodes == m_real_num_node); + (void)num_nodes; + m_block_multiset.erase_and_dispose + (it, block_destroyer(this)); + } + } + + void priv_reinsert_nodes_in_block(multiallocation_iterator it) + { + multiallocation_iterator itend; + block_iterator block_it(m_block_multiset.end()); + while(it != itend){ + void *pElem = &*it; + ++it; + priv_invariants(); + block_info_t *block_info = this->priv_block_from_node(pElem); + assert(block_info->free_nodes.size() < m_real_num_node); + //We put the node at the beginning of the free node list + node_t * to_deallocate = static_cast(pElem); + block_info->free_nodes.push_front(*to_deallocate); + + block_iterator this_block(block_multiset_t::s_iterator_to(*block_info)); + block_iterator next_block(this_block); + ++next_block; + + //Cache the free nodes from the block + std::size_t this_block_free_nodes = this_block->free_nodes.size(); + + if(this_block_free_nodes == 1){ + m_block_multiset.insert(m_block_multiset.begin(), *block_info); + } + else{ + block_iterator next_block(this_block); + ++next_block; + if(next_block != block_it){ + std::size_t next_free_nodes = next_block->free_nodes.size(); + if(this_block_free_nodes > next_free_nodes){ + //Now move the block to the new position + m_block_multiset.erase(this_block); + m_block_multiset.insert(*block_info); + } + } + } + //Update free block count + if(this_block_free_nodes == m_real_num_node){ + ++m_totally_free_blocks; + } + priv_invariants(); + } + } + + node_t *priv_take_first_node() + { + assert(m_block_multiset.begin() != m_block_multiset.end()); + //We take the first free node the multiset can't be empty + free_nodes_t &free_nodes = m_block_multiset.begin()->free_nodes; + node_t *first_node = &free_nodes.front(); + const std::size_t free_nodes_count = free_nodes.size(); + assert(0 != free_nodes_count); + free_nodes.pop_front(); + if(free_nodes_count == 1){ + m_block_multiset.erase(m_block_multiset.begin()); + } + else if(free_nodes_count == m_real_num_node){ + --m_totally_free_blocks; + } + priv_invariants(); + return first_node; + } + + class block_destroyer; + friend class block_destroyer; + + class block_destroyer + { + public: + block_destroyer(const private_adaptive_node_pool_impl *impl) + : mp_impl(impl) + {} + + void operator()(typename block_multiset_t::pointer to_deallocate) + { + std::size_t free_nodes = to_deallocate->free_nodes.size(); + (void)free_nodes; + assert(free_nodes == mp_impl->m_real_num_node); + assert(0 == to_deallocate->hdr_offset); + hdr_offset_holder *hdr_off_holder = mp_impl->priv_first_subblock_from_block((block_info_t*)detail::get_pointer(to_deallocate)); + mp_impl->mp_segment_mngr_base->deallocate(hdr_off_holder); + } + const private_adaptive_node_pool_impl *mp_impl; + }; + + //This macro will activate invariant checking. Slow, but helpful for debugging the code. + #define BOOST_INTERPROCESS_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS + void priv_invariants() + #ifdef BOOST_INTERPROCESS_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS + #undef BOOST_INTERPROCESS_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS + { + //We iterate through the block list to free the memory + block_iterator it(m_block_multiset.begin()), + itend(m_block_multiset.end()), to_deallocate; + if(it != itend){ + for(++it; it != itend; ++it){ + block_iterator prev(it); + --prev; + std::size_t sp = prev->free_nodes.size(), + si = it->free_nodes.size(); + assert(sp <= si); + (void)sp; (void)si; + } + } + + { + //Check that the total free nodes are correct + it = m_block_multiset.begin(); + itend = m_block_multiset.end(); + std::size_t total_free_nodes = 0; + for(; it != itend; ++it){ + total_free_nodes += it->free_nodes.size(); + } + assert(total_free_nodes >= m_totally_free_blocks*m_real_num_node); + } + + { + //Check that the total totally free blocks are correct + it = m_block_multiset.begin(); + itend = m_block_multiset.end(); + std::size_t total_free_blocks = 0; + for(; it != itend; ++it){ + total_free_blocks += (it->free_nodes.size() == m_real_num_node); + } + assert(total_free_blocks == m_totally_free_blocks); + } + { + //Check that header offsets are correct + it = m_block_multiset.begin(); + for(; it != itend; ++it){ + hdr_offset_holder *hdr_off_holder = priv_first_subblock_from_block(&*it); + for(std::size_t i = 0, max = m_num_subblocks; i < max; ++i){ + assert(hdr_off_holder->hdr_offset == std::size_t((char*)&*it- (char*)hdr_off_holder)); + assert(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1))); + assert(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1))); + hdr_off_holder = (hdr_offset_holder *)((char*)hdr_off_holder + m_real_block_alignment); + } + } + } + } + #else + {} //empty + #endif + + //!Deallocates all used memory. Never throws + void priv_clear() + { + #ifndef NDEBUG + block_iterator it = m_block_multiset.begin(); + block_iterator itend = m_block_multiset.end(); + std::size_t num_free_nodes = 0; + for(; it != itend; ++it){ + //Check for memory leak + assert(it->free_nodes.size() == m_real_num_node); + ++num_free_nodes; + } + assert(num_free_nodes == m_totally_free_blocks); + #endif + priv_invariants(); + m_block_multiset.clear_and_dispose + (block_destroyer(this)); + m_totally_free_blocks = 0; + } + + block_info_t *priv_block_from_node(void *node) const + { + hdr_offset_holder *hdr_off_holder = + (hdr_offset_holder*)((std::size_t)node & std::size_t(~(m_real_block_alignment - 1))); + assert(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1))); + assert(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1))); + block_info_t *block = (block_info_t *)(((char*)hdr_off_holder) + hdr_off_holder->hdr_offset); + assert(block->hdr_offset == 0); + return block; + } + + hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block) const + { + hdr_offset_holder *hdr_off_holder = (hdr_offset_holder*) + (((char*)block) - (m_num_subblocks-1)*m_real_block_alignment); + assert(hdr_off_holder->hdr_offset == std::size_t((char*)block - (char*)hdr_off_holder)); + assert(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1))); + assert(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1))); + return hdr_off_holder; + } + + //!Allocates a several blocks of nodes. Can throw boost::interprocess::bad_alloc + void priv_alloc_block(std::size_t n) + { + std::size_t real_block_size = m_real_block_alignment*m_num_subblocks - SegmentManagerBase::PayloadPerAllocation; + std::size_t elements_per_subblock = (m_real_block_alignment - HdrOffsetSize)/m_real_node_size; + std::size_t hdr_subblock_elements = (m_real_block_alignment - HdrSize - SegmentManagerBase::PayloadPerAllocation)/m_real_node_size; + + for(std::size_t i = 0; i != n; ++i){ + //We allocate a new NodeBlock and put it the last + //element of the tree + char *mem_address = detail::char_ptr_cast + (mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment)); + if(!mem_address) throw std::bad_alloc(); + ++m_totally_free_blocks; + + //First initialize header information on the last subblock + char *hdr_addr = mem_address + m_real_block_alignment*(m_num_subblocks-1); + block_info_t *c_info = new(hdr_addr)block_info_t; + //Some structural checks + assert(static_cast(&static_cast(c_info)->hdr_offset) == + static_cast(c_info)); + typename free_nodes_t::iterator prev_insert_pos = c_info->free_nodes.before_begin(); + for( std::size_t subblock = 0, maxsubblock = m_num_subblocks - 1 + ; subblock < maxsubblock + ; ++subblock, mem_address += m_real_block_alignment){ + //Initialize header offset mark + new(mem_address) hdr_offset_holder(std::size_t(hdr_addr - mem_address)); + char *pNode = mem_address + HdrOffsetSize; + for(std::size_t i = 0; i < elements_per_subblock; ++i){ + prev_insert_pos = c_info->free_nodes.insert_after(prev_insert_pos, *new (pNode) node_t); + pNode += m_real_node_size; + } + } + { + char *pNode = hdr_addr + HdrSize; + //We initialize all Nodes in Node Block to insert + //them in the free Node list + for(std::size_t i = 0; i < hdr_subblock_elements; ++i){ + prev_insert_pos = c_info->free_nodes.insert_after(prev_insert_pos, *new (pNode) node_t); + pNode += m_real_node_size; + } + } + //Insert the block after the free node list is full + m_block_multiset.insert(m_block_multiset.end(), *c_info); + } + } + + private: + typedef typename pointer_to_other + ::type segment_mngr_base_ptr_t; + + const std::size_t m_max_free_blocks; + const std::size_t m_real_node_size; + //Round the size to a power of two value. + //This is the total memory size (including payload) that we want to + //allocate from the general-purpose allocator + const std::size_t m_real_block_alignment; + std::size_t m_num_subblocks; + //This is the real number of nodes per block + //const + std::size_t m_real_num_node; + segment_mngr_base_ptr_t mp_segment_mngr_base;//Segment manager + block_multiset_t m_block_multiset; //Intrusive block list + std::size_t m_totally_free_blocks; //Free blocks +}; + +template< class SegmentManager + , std::size_t NodeSize + , std::size_t NodesPerBlock + , std::size_t MaxFreeBlocks + , unsigned char OverheadPercent + > +class private_adaptive_node_pool + : public private_adaptive_node_pool_impl + +{ + typedef private_adaptive_node_pool_impl + base_t; + //Non-copyable + private_adaptive_node_pool(); + private_adaptive_node_pool(const private_adaptive_node_pool &); + private_adaptive_node_pool &operator=(const private_adaptive_node_pool &); + + public: + typedef SegmentManager segment_manager; + + static const std::size_t nodes_per_block = NodesPerBlock; + + //Deprecated, use node_per_block + static const std::size_t nodes_per_chunk = NodesPerBlock; + + //!Constructor from a segment manager. Never throws + private_adaptive_node_pool(segment_manager *segment_mngr) + : base_t(segment_mngr, NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent) + {} + + //!Returns the segment manager. Never throws + segment_manager* get_segment_manager() const + { return static_cast(base_t::get_segment_manager_base()); } +}; + +//!Pooled shared memory allocator using adaptive pool. Includes +//!a reference count but the class does not delete itself, this is +//!responsibility of user classes. Node size (NodeSize) and the number of +//!nodes allocated per block (NodesPerBlock) are known at compile time +template< class SegmentManager + , std::size_t NodeSize + , std::size_t NodesPerBlock + , std::size_t MaxFreeBlocks + , unsigned char OverheadPercent + > +class shared_adaptive_node_pool + : public detail::shared_pool_impl + < private_adaptive_node_pool + + > +{ + typedef detail::shared_pool_impl + < private_adaptive_node_pool + + > base_t; + public: + shared_adaptive_node_pool(SegmentManager *segment_mgnr) + : base_t(segment_mgnr) + {} +}; + +} //namespace detail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ADAPTIVE_NODE_POOL_HPP + diff --git a/win32/include/boost/interprocess/allocators/detail/allocator_common.hpp b/win32/include/boost/interprocess/allocators/detail/allocator_common.hpp new file mode 100755 index 000000000..fdfc98fff --- /dev/null +++ b/win32/include/boost/interprocess/allocators/detail/allocator_common.hpp @@ -0,0 +1,817 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_NODE_ALLOCATOR_COMMON_HPP +#define BOOST_INTERPROCESS_DETAIL_NODE_ALLOCATOR_COMMON_HPP + +#include +#include +#include +#include +#include //pointer_to_other, get_pointer +#include //std::pair +#include //boost::addressof +#include //BOOST_ASSERT +#include //bad_alloc +#include //scoped_lock +#include //allocation_type +#include //std::swap + + +namespace boost { +namespace interprocess { +namespace detail { + +//!Object function that creates the node allocator if it is not created and +//!increments reference count if it is already created +template +struct get_or_create_node_pool_func +{ + + //!This connects or constructs the unique instance of node_pool_t + //!Can throw boost::interprocess::bad_alloc + void operator()() + { + //Find or create the node_pool_t + mp_node_pool = mp_segment_manager->template find_or_construct + (unique_instance)(mp_segment_manager); + //If valid, increment link count + if(mp_node_pool != 0) + mp_node_pool->inc_ref_count(); + } + + //!Constructor. Initializes function + //!object parameters + get_or_create_node_pool_func(typename NodePool::segment_manager *mngr) + : mp_segment_manager(mngr){} + + NodePool *mp_node_pool; + typename NodePool::segment_manager *mp_segment_manager; +}; + +template +inline NodePool *get_or_create_node_pool(typename NodePool::segment_manager *mgnr) +{ + detail::get_or_create_node_pool_func func(mgnr); + mgnr->atomic_func(func); + return func.mp_node_pool; +} + +//!Object function that decrements the reference count. If the count +//!reaches to zero destroys the node allocator from memory. +//!Never throws +template +struct destroy_if_last_link_func +{ + //!Decrements reference count and destroys the object if there is no + //!more attached allocators. Never throws + void operator()() + { + //If not the last link return + if(mp_node_pool->dec_ref_count() != 0) return; + + //Last link, let's destroy the segment_manager + mp_node_pool->get_segment_manager()->template destroy(unique_instance); + } + + //!Constructor. Initializes function + //!object parameters + destroy_if_last_link_func(NodePool *pool) + : mp_node_pool(pool) + {} + + NodePool *mp_node_pool; +}; + +//!Destruction function, initializes and executes destruction function +//!object. Never throws +template +inline void destroy_node_pool_if_last_link(NodePool *pool) +{ + //Get segment manager + typename NodePool::segment_manager *mngr = pool->get_segment_manager(); + //Execute destruction functor atomically + destroy_if_last_link_funcfunc(pool); + mngr->atomic_func(func); +} + +template +class cache_impl +{ + typedef typename NodePool::segment_manager:: + void_pointer void_pointer; + typedef typename pointer_to_other + ::type node_pool_ptr; + typedef typename NodePool::multiallocation_chain multiallocation_chain; + node_pool_ptr mp_node_pool; + multiallocation_chain m_cached_nodes; + std::size_t m_max_cached_nodes; + + public: + typedef typename NodePool::multiallocation_iterator multiallocation_iterator; + typedef typename NodePool::segment_manager segment_manager; + + cache_impl(segment_manager *segment_mngr, std::size_t max_cached_nodes) + : mp_node_pool(get_or_create_node_pool(segment_mngr)) + , m_max_cached_nodes(max_cached_nodes) + {} + + cache_impl(const cache_impl &other) + : mp_node_pool(other.get_node_pool()) + , m_max_cached_nodes(other.get_max_cached_nodes()) + { + mp_node_pool->inc_ref_count(); + } + + ~cache_impl() + { + this->deallocate_all_cached_nodes(); + detail::destroy_node_pool_if_last_link(detail::get_pointer(mp_node_pool)); + } + + NodePool *get_node_pool() const + { return detail::get_pointer(mp_node_pool); } + + segment_manager *get_segment_manager() const + { return mp_node_pool->get_segment_manager(); } + + std::size_t get_max_cached_nodes() const + { return m_max_cached_nodes; } + + void *cached_allocation() + { + //If don't have any cached node, we have to get a new list of free nodes from the pool + if(m_cached_nodes.empty()){ + mp_node_pool->allocate_nodes(m_cached_nodes, m_max_cached_nodes/2); + } + return m_cached_nodes.pop_front(); + } + + multiallocation_iterator cached_allocation(std::size_t n) + { + multiallocation_chain chain; + std::size_t count = n; + BOOST_TRY{ + //If don't have any cached node, we have to get a new list of free nodes from the pool + while(!m_cached_nodes.empty() && count--){ + void *ret = m_cached_nodes.pop_front(); + chain.push_back(ret); + } + + if(chain.size() != n){ + mp_node_pool->allocate_nodes(chain, n - chain.size()); + } + assert(chain.size() == n); + chain.splice_back(m_cached_nodes); + return multiallocation_iterator(chain.get_it()); + } + BOOST_CATCH(...){ + this->cached_deallocation(multiallocation_iterator(chain.get_it())); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + void cached_deallocation(void *ptr) + { + //Check if cache is full + if(m_cached_nodes.size() >= m_max_cached_nodes){ + //This only occurs if this allocator deallocate memory allocated + //with other equal allocator. Since the cache is full, and more + //deallocations are probably coming, we'll make some room in cache + //in a single, efficient multi node deallocation. + this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2); + } + m_cached_nodes.push_front(ptr); + } + + void cached_deallocation(multiallocation_iterator it) + { + multiallocation_iterator itend; + + while(it != itend){ + void *addr = &*it; + ++it; + m_cached_nodes.push_front(addr); + } + + //Check if cache is full + if(m_cached_nodes.size() >= m_max_cached_nodes){ + //This only occurs if this allocator deallocate memory allocated + //with other equal allocator. Since the cache is full, and more + //deallocations are probably coming, we'll make some room in cache + //in a single, efficient multi node deallocation. + this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2); + } + } + + //!Sets the new max cached nodes value. This can provoke deallocations + //!if "newmax" is less than current cached nodes. Never throws + void set_max_cached_nodes(std::size_t newmax) + { + m_max_cached_nodes = newmax; + this->priv_deallocate_remaining_nodes(); + } + + //!Frees all cached nodes. + //!Never throws + void deallocate_all_cached_nodes() + { + if(m_cached_nodes.empty()) return; + mp_node_pool->deallocate_nodes(m_cached_nodes); + } + + private: + //!Frees all cached nodes at once. + //!Never throws + void priv_deallocate_remaining_nodes() + { + if(m_cached_nodes.size() > m_max_cached_nodes){ + priv_deallocate_n_nodes(m_cached_nodes.size()-m_max_cached_nodes); + } + } + + //!Frees n cached nodes at once. Never throws + void priv_deallocate_n_nodes(std::size_t n) + { + //Deallocate all new linked list at once + mp_node_pool->deallocate_nodes(m_cached_nodes, n); + } +}; + +template +class array_allocation_impl +{ + const Derived *derived() const + { return static_cast(this); } + Derived *derived() + { return static_cast(this); } + + typedef typename SegmentManager::void_pointer void_pointer; + + public: + typedef typename detail:: + pointer_to_other::type pointer; + typedef typename detail:: + pointer_to_other::type const_pointer; + typedef T value_type; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef transform_iterator + < typename SegmentManager:: + multiallocation_iterator + , detail::cast_functor > multiallocation_iterator; + typedef typename SegmentManager:: + multiallocation_chain multiallocation_chain; + + public: + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const + { + return (size_type)this->derived()->get_segment_manager()->size(detail::get_pointer(p))/sizeof(T); + } + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, const pointer &reuse = 0) + { + return this->derived()->get_segment_manager()->allocation_command + (command, limit_size, preferred_size, received_size, detail::get_pointer(reuse)); + } + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements) + { + return multiallocation_iterator + (this->derived()->get_segment_manager()->allocate_many(sizeof(T)*elem_size, num_elements)); + } + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements) + { + return multiallocation_iterator + (this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T))); + } + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_iterator it) + { return this->derived()->get_segment_manager()->deallocate_many(it.base()); } + + //!Returns the number of elements that could be + //!allocated. Never throws + size_type max_size() const + { return this->derived()->get_segment_manager()->get_size()/sizeof(T); } + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const + { return pointer(boost::addressof(value)); } + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const + { return const_pointer(boost::addressof(value)); } + + //!Default construct an object. + //!Throws if T's default constructor throws + void construct(const pointer &ptr) + { new((void*)detail::get_pointer(ptr)) value_type; } + + //!Copy construct an object + //!Throws if T's copy constructor throws + void construct(const pointer &ptr, const_reference v) + { new((void*)detail::get_pointer(ptr)) value_type(v); } + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr) + { BOOST_ASSERT(ptr != 0); (*ptr).~value_type(); } +}; + + +template +class node_pool_allocation_impl + : public array_allocation_impl + < Derived + , T + , SegmentManager> +{ + const Derived *derived() const + { return static_cast(this); } + Derived *derived() + { return static_cast(this); } + + typedef typename SegmentManager::void_pointer void_pointer; + typedef typename detail:: + pointer_to_other::type cvoid_pointer; + + public: + typedef typename detail:: + pointer_to_other::type pointer; + typedef typename detail:: + pointer_to_other::type const_pointer; + typedef T value_type; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef transform_iterator + < typename SegmentManager:: + multiallocation_iterator + , detail::cast_functor > multiallocation_iterator; + typedef typename SegmentManager:: + multiallocation_chain multiallocation_chain; + + template + struct node_pool + { + typedef typename Derived::template node_pool<0>::type type; + static type *get(void *p) + { return static_cast(p); } + }; + + public: + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0) + { + (void)hint; + typedef typename node_pool<0>::type node_pool_t; + node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); + if(count > this->max_size()) + throw bad_alloc(); + else if(Version == 1 && count == 1) + return pointer(static_cast + (pool->allocate_node())); + else + return pointer(static_cast + (pool->get_segment_manager()->allocate(sizeof(T)*count))); + } + + //!Deallocate allocated memory. Never throws + void deallocate(const pointer &ptr, size_type count) + { + (void)count; + typedef typename node_pool<0>::type node_pool_t; + node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); + if(Version == 1 && count == 1) + pool->deallocate_node(detail::get_pointer(ptr)); + else + pool->get_segment_manager()->deallocate((void*)detail::get_pointer(ptr)); + } + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one() + { + typedef typename node_pool<0>::type node_pool_t; + node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); + return pointer(static_cast(pool->allocate_node())); + } + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + multiallocation_iterator allocate_individual(std::size_t num_elements) + { + typedef typename node_pool<0>::type node_pool_t; + node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); + return multiallocation_iterator(pool->allocate_nodes(num_elements)); + } + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p) + { + typedef typename node_pool<0>::type node_pool_t; + node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); + pool->deallocate_node(detail::get_pointer(p)); + } + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_iterator it) + { node_pool<0>::get(this->derived()->get_node_pool())->deallocate_nodes(it.base()); } + + //!Deallocates all free blocks of the pool + void deallocate_free_blocks() + { node_pool<0>::get(this->derived()->get_node_pool())->deallocate_free_blocks(); } + + //!Deprecated, use deallocate_free_blocks. + //!Deallocates all free chunks of the pool. + void deallocate_free_chunks() + { node_pool<0>::get(this->derived()->get_node_pool())->deallocate_free_blocks(); } +}; + +template +class cached_allocator_impl + : public array_allocation_impl + , T, typename NodePool::segment_manager> +{ + cached_allocator_impl & operator=(const cached_allocator_impl& other); + typedef array_allocation_impl + < cached_allocator_impl + + , T + , typename NodePool::segment_manager> base_t; + + public: + typedef NodePool node_pool_t; + typedef typename NodePool::segment_manager segment_manager; + typedef typename segment_manager::void_pointer void_pointer; + typedef typename detail:: + pointer_to_other::type cvoid_pointer; + typedef typename base_t::pointer pointer; + typedef typename base_t::size_type size_type; + typedef typename base_t::multiallocation_iterator multiallocation_iterator; + typedef typename base_t::multiallocation_chain multiallocation_chain; + typedef typename base_t::value_type value_type; + + public: + enum { DEFAULT_MAX_CACHED_NODES = 64 }; + + cached_allocator_impl(segment_manager *segment_mngr, std::size_t max_cached_nodes) + : m_cache(segment_mngr, max_cached_nodes) + {} + + cached_allocator_impl(const cached_allocator_impl &other) + : m_cache(other.m_cache) + {} + + //!Copy constructor from related cached_adaptive_pool_base. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + cached_allocator_impl + (const cached_allocator_impl + &other) + : m_cache(other.get_segment_manager(), other.get_max_cached_nodes()) + {} + + //!Returns a pointer to the node pool. + //!Never throws + node_pool_t* get_node_pool() const + { return m_cache.get_node_pool(); } + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const + { return m_cache.get_segment_manager(); } + + //!Sets the new max cached nodes value. This can provoke deallocations + //!if "newmax" is less than current cached nodes. Never throws + void set_max_cached_nodes(std::size_t newmax) + { m_cache.set_max_cached_nodes(newmax); } + + //!Returns the max cached nodes parameter. + //!Never throws + std::size_t get_max_cached_nodes() const + { return m_cache.get_max_cached_nodes(); } + + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0) + { + (void)hint; + void * ret; + if(count > this->max_size()) + throw bad_alloc(); + else if(Version == 1 && count == 1){ + ret = m_cache.cached_allocation(); + } + else{ + ret = this->get_segment_manager()->allocate(sizeof(T)*count); + } + return pointer(static_cast(ret)); + } + + //!Deallocate allocated memory. Never throws + void deallocate(const pointer &ptr, size_type count) + { + (void)count; + if(Version == 1 && count == 1){ + m_cache.cached_deallocation(detail::get_pointer(ptr)); + } + else{ + this->get_segment_manager()->deallocate((void*)detail::get_pointer(ptr)); + } + } + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one() + { return pointer(static_cast(this->m_cache.cached_allocation())); } + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + multiallocation_iterator allocate_individual(std::size_t num_elements) + { return multiallocation_iterator(this->m_cache.cached_allocation(num_elements)); } + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p) + { this->m_cache.cached_deallocation(detail::get_pointer(p)); } + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_iterator it) + { m_cache.cached_deallocation(it.base()); } + + //!Deallocates all free blocks of the pool + void deallocate_free_blocks() + { m_cache.get_node_pool()->deallocate_free_blocks(); } + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different shared memory segments, the result is undefined. + friend void swap(cached_allocator_impl &alloc1, cached_allocator_impl &alloc2) + { + detail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); + alloc1.m_cached_nodes.swap(alloc2.m_cached_nodes); + detail::do_swap(alloc1.m_max_cached_nodes, alloc2.m_max_cached_nodes); + } + + void deallocate_cache() + { m_cache.deallocate_all_cached_nodes(); } + + //!Deprecated use deallocate_free_blocks. + void deallocate_free_chunks() + { m_cache.get_node_pool()->deallocate_free_blocks(); } + + /// @cond + private: + cache_impl m_cache; +}; + +//!Equality test for same type of +//!cached_allocator_impl +template inline +bool operator==(const cached_allocator_impl &alloc1, + const cached_allocator_impl &alloc2) + { return alloc1.get_node_pool() == alloc2.get_node_pool(); } + +//!Inequality test for same type of +//!cached_allocator_impl +template inline +bool operator!=(const cached_allocator_impl &alloc1, + const cached_allocator_impl &alloc2) + { return alloc1.get_node_pool() != alloc2.get_node_pool(); } + + +//!Pooled shared memory allocator using adaptive pool. Includes +//!a reference count but the class does not delete itself, this is +//!responsibility of user classes. Node size (NodeSize) and the number of +//!nodes allocated per block (NodesPerBlock) are known at compile time +template +class shared_pool_impl + : public private_node_allocator_t +{ + public: + //!Segment manager typedef + typedef typename private_node_allocator_t::segment_manager segment_manager; + typedef typename private_node_allocator_t:: + multiallocation_iterator multiallocation_iterator; + typedef typename private_node_allocator_t:: + multiallocation_chain multiallocation_chain; + + private: + typedef typename segment_manager::mutex_family::mutex_type mutex_type; + + public: + //!Constructor from a segment manager. Never throws + shared_pool_impl(segment_manager *segment_mngr) + : private_node_allocator_t(segment_mngr) + {} + + //!Destructor. Deallocates all allocated blocks. Never throws + ~shared_pool_impl() + {} + + //!Allocates array of count elements. Can throw boost::interprocess::bad_alloc + void *allocate_node() + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return private_node_allocator_t::allocate_node(); + } + + //!Deallocates an array pointed by ptr. Never throws + void deallocate_node(void *ptr) + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::deallocate_node(ptr); + } + + //!Allocates a singly linked list of n nodes ending in null pointer. + //!can throw boost::interprocess::bad_alloc + void allocate_nodes(multiallocation_chain &nodes, std::size_t n) + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return private_node_allocator_t::allocate_nodes(nodes, n); + } + + //!Allocates n nodes, pointed by the multiallocation_iterator. + //!Can throw boost::interprocess::bad_alloc + multiallocation_iterator allocate_nodes(const std::size_t n) + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return private_node_allocator_t::allocate_nodes(n); + } + + //!Deallocates a linked list of nodes ending in null pointer. Never throws + void deallocate_nodes(multiallocation_chain &nodes, std::size_t num) + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::deallocate_nodes(nodes, num); + } + + //!Deallocates a linked list of nodes ending in null pointer. Never throws + void deallocate_nodes(multiallocation_chain &nodes) + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::deallocate_nodes(nodes); + } + + //!Deallocates the nodes pointed by the multiallocation iterator. Never throws + void deallocate_nodes(multiallocation_iterator it) + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::deallocate_nodes(it); + } + + //!Deallocates all the free blocks of memory. Never throws + void deallocate_free_blocks() + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::deallocate_free_blocks(); + } + + //!Deallocates all used memory from the common pool. + //!Precondition: all nodes allocated from this pool should + //!already be deallocated. Otherwise, undefined behavior. Never throws + void purge_blocks() + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::purge_blocks(); + } + + //!Increments internal reference count and returns new count. Never throws + std::size_t inc_ref_count() + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return ++m_header.m_usecount; + } + + //!Decrements internal reference count and returns new count. Never throws + std::size_t dec_ref_count() + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + assert(m_header.m_usecount > 0); + return --m_header.m_usecount; + } + + //!Deprecated, use deallocate_free_blocks. + void deallocate_free_chunks() + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::deallocate_free_blocks(); + } + + //!Deprecated, use purge_blocks. + void purge_chunks() + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + private_node_allocator_t::purge_blocks(); + } + + private: + //!This struct includes needed data and derives from + //!interprocess_mutex to allow EBO when using null_mutex + struct header_t : mutex_type + { + std::size_t m_usecount; //Number of attached allocators + + header_t() + : m_usecount(0) {} + } m_header; +}; + +} //namespace detail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_ALLOCATOR_COMMON_HPP diff --git a/win32/include/boost/interprocess/allocators/detail/node_pool.hpp b/win32/include/boost/interprocess/allocators/detail/node_pool.hpp new file mode 100755 index 000000000..5a64cd6fa --- /dev/null +++ b/win32/include/boost/interprocess/allocators/detail/node_pool.hpp @@ -0,0 +1,430 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP +#define BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes the real adaptive pool shared by many Interprocess adaptive pool allocators + +namespace boost { +namespace interprocess { +namespace detail { + +template +class private_node_pool_impl +{ + //Non-copyable + private_node_pool_impl(); + private_node_pool_impl(const private_node_pool_impl &); + private_node_pool_impl &operator=(const private_node_pool_impl &); + + //A node object will hold node_t when it's not allocated + public: + typedef typename SegmentManagerBase::void_pointer void_pointer; + typedef typename node_slist::slist_hook_t slist_hook_t; + typedef typename node_slist::node_t node_t; + typedef typename node_slist::node_slist_t free_nodes_t; + typedef typename SegmentManagerBase::multiallocation_iterator multiallocation_iterator; + typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain; + + private: + typedef typename bi::make_slist + < node_t, bi::base_hook + , bi::linear + , bi::constant_time_size >::type blockslist_t; + public: + + //!Segment manager typedef + typedef SegmentManagerBase segment_manager_base_type; + + //!Constructor from a segment manager. Never throws + private_node_pool_impl(segment_manager_base_type *segment_mngr_base, std::size_t node_size, std::size_t nodes_per_block) + : m_nodes_per_block(nodes_per_block) + , m_real_node_size(detail::lcm(node_size, std::size_t(alignment_of::value))) + //General purpose allocator + , mp_segment_mngr_base(segment_mngr_base) + , m_blocklist() + , m_freelist() + //Debug node count + , m_allocated(0) + {} + + //!Destructor. Deallocates all allocated blocks. Never throws + ~private_node_pool_impl() + { this->purge_blocks(); } + + std::size_t get_real_num_node() const + { return m_nodes_per_block; } + + //!Returns the segment manager. Never throws + segment_manager_base_type* get_segment_manager_base()const + { return detail::get_pointer(mp_segment_mngr_base); } + + //!Allocates array of count elements. Can throw boost::interprocess::bad_alloc + void *allocate_node() + { + //If there are no free nodes we allocate a new block + if (m_freelist.empty()) + priv_alloc_block(); + //We take the first free node + node_t *n = (node_t*)&m_freelist.front(); + m_freelist.pop_front(); + ++m_allocated; + return n; + } + + //!Deallocates an array pointed by ptr. Never throws + void deallocate_node(void *ptr) + { + //We put the node at the beginning of the free node list + node_t * to_deallocate = static_cast(ptr); + m_freelist.push_front(*to_deallocate); + assert(m_allocated>0); + --m_allocated; + } + + //!Allocates a singly linked list of n nodes ending in null pointer and pushes them in the chain. + //!can throw boost::interprocess::bad_alloc + void allocate_nodes(multiallocation_chain &nodes, const std::size_t n) + { + std::size_t i = 0; + try{ + for(; i < n; ++i){ + nodes.push_front(this->allocate_node()); + } + } + catch(...){ + this->deallocate_nodes(nodes, i); + throw; + } + } + + //!Allocates a singly linked list of n nodes ending in null pointer + //!can throw boost::interprocess::bad_alloc + multiallocation_iterator allocate_nodes(const std::size_t n) + { + multiallocation_chain nodes; + std::size_t i = 0; + try{ + for(; i < n; ++i){ + nodes.push_front(this->allocate_node()); + } + } + catch(...){ + this->deallocate_nodes(nodes, i); + throw; + } + return nodes.get_it(); + } + + //!Deallocates a linked list of nodes. Never throws + void deallocate_nodes(multiallocation_chain &nodes) + { + this->deallocate_nodes(nodes.get_it()); + nodes.reset(); + } + + //!Deallocates the first n nodes of a linked list of nodes. Never throws + void deallocate_nodes(multiallocation_chain &nodes, std::size_t num) + { + assert(nodes.size() >= num); + for(std::size_t i = 0; i < num; ++i){ + deallocate_node(nodes.pop_front()); + } + } + + //!Deallocates the nodes pointed by the multiallocation iterator. Never throws + void deallocate_nodes(multiallocation_iterator it) + { + multiallocation_iterator itend; + while(it != itend){ + void *addr = &*it; + ++it; + deallocate_node(addr); + } + } + + //!Deallocates all the free blocks of memory. Never throws + void deallocate_free_blocks() + { + typedef typename free_nodes_t::iterator nodelist_iterator; + typename blockslist_t::iterator bit(m_blocklist.before_begin()), + it(m_blocklist.begin()), + itend(m_blocklist.end()); + free_nodes_t backup_list; + nodelist_iterator backup_list_last = backup_list.before_begin(); + + //Execute the algorithm and get an iterator to the last value + std::size_t blocksize = detail::get_rounded_size + (m_real_node_size*m_nodes_per_block, alignment_of::value); + + while(it != itend){ + //Collect all the nodes from the block pointed by it + //and push them in the list + free_nodes_t free_nodes; + nodelist_iterator last_it = free_nodes.before_begin(); + const void *addr = get_block_from_hook(&*it, blocksize); + + m_freelist.remove_and_dispose_if + (is_between(addr, blocksize), push_in_list(free_nodes, last_it)); + + //If the number of nodes is equal to m_nodes_per_block + //this means that the block can be deallocated + if(free_nodes.size() == m_nodes_per_block){ + //Unlink the nodes + free_nodes.clear(); + it = m_blocklist.erase_after(bit); + mp_segment_mngr_base->deallocate((void*)addr); + } + //Otherwise, insert them in the backup list, since the + //next "remove_if" does not need to check them again. + else{ + //Assign the iterator to the last value if necessary + if(backup_list.empty() && !m_freelist.empty()){ + backup_list_last = last_it; + } + //Transfer nodes. This is constant time. + backup_list.splice_after + ( backup_list.before_begin() + , free_nodes + , free_nodes.before_begin() + , last_it + , free_nodes.size()); + bit = it; + ++it; + } + } + //We should have removed all the nodes from the free list + assert(m_freelist.empty()); + + //Now pass all the node to the free list again + m_freelist.splice_after + ( m_freelist.before_begin() + , backup_list + , backup_list.before_begin() + , backup_list_last + , backup_list.size()); + } + + std::size_t num_free_nodes() + { return m_freelist.size(); } + + //!Deallocates all used memory. Precondition: all nodes allocated from this pool should + //!already be deallocated. Otherwise, undefined behaviour. Never throws + void purge_blocks() + { + //check for memory leaks + assert(m_allocated==0); + std::size_t blocksize = detail::get_rounded_size + (m_real_node_size*m_nodes_per_block, alignment_of::value); + typename blockslist_t::iterator + it(m_blocklist.begin()), itend(m_blocklist.end()), aux; + + //We iterate though the NodeBlock list to free the memory + while(!m_blocklist.empty()){ + void *addr = get_block_from_hook(&m_blocklist.front(), blocksize); + m_blocklist.pop_front(); + mp_segment_mngr_base->deallocate((void*)addr); + } + //Just clear free node list + m_freelist.clear(); + } + + void swap(private_node_pool_impl &other) + { + std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base); + m_blocklist.swap(other.m_blocklist); + m_freelist.swap(other.m_freelist); + std::swap(m_allocated, other.m_allocated); + } + + private: + + struct push_in_list + { + push_in_list(free_nodes_t &l, typename free_nodes_t::iterator &it) + : slist_(l), last_it_(it) + {} + + void operator()(typename free_nodes_t::pointer p) const + { + slist_.push_front(*p); + if(slist_.size() == 1){ //Cache last element + ++last_it_ = slist_.begin(); + } + } + + private: + free_nodes_t &slist_; + typename free_nodes_t::iterator &last_it_; + }; + + struct is_between + : std::unary_function + { + is_between(const void *addr, std::size_t size) + : beg_((const char *)addr), end_(beg_+size) + {} + + bool operator()(typename free_nodes_t::const_reference v) const + { + return (beg_ <= (const char *)&v && + end_ > (const char *)&v); + } + private: + const char * beg_; + const char * end_; + }; + + //!Allocates a block of nodes. Can throw boost::interprocess::bad_alloc + void priv_alloc_block() + { + //We allocate a new NodeBlock and put it as first + //element in the free Node list + std::size_t blocksize = + detail::get_rounded_size(m_real_node_size*m_nodes_per_block, alignment_of::value); + char *pNode = detail::char_ptr_cast + (mp_segment_mngr_base->allocate(blocksize + sizeof(node_t))); + if(!pNode) throw bad_alloc(); + char *pBlock = pNode; + m_blocklist.push_front(get_block_hook(pBlock, blocksize)); + + //We initialize all Nodes in Node Block to insert + //them in the free Node list + for(std::size_t i = 0; i < m_nodes_per_block; ++i, pNode += m_real_node_size){ + m_freelist.push_front(*new (pNode) node_t); + } + } + + //!Deprecated, use deallocate_free_blocks + void deallocate_free_chunks() + { this->deallocate_free_blocks(); } + + //!Deprecated, use purge_blocks + void purge_chunks() + { this->purge_blocks(); } + + private: + //!Returns a reference to the block hook placed in the end of the block + static inline node_t & get_block_hook (void *block, std::size_t blocksize) + { + return *static_cast( + static_cast((detail::char_ptr_cast(block) + blocksize))); + } + + //!Returns the starting address of the block reference to the block hook placed in the end of the block + inline void *get_block_from_hook (node_t *hook, std::size_t blocksize) + { + return static_cast((detail::char_ptr_cast(hook) - blocksize)); + } + + private: + typedef typename pointer_to_other + ::type segment_mngr_base_ptr_t; + + const std::size_t m_nodes_per_block; + const std::size_t m_real_node_size; + segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager + blockslist_t m_blocklist; //Intrusive container of blocks + free_nodes_t m_freelist; //Intrusive container of free nods + std::size_t m_allocated; //Used nodes for debugging +}; + + +//!Pooled shared memory allocator using single segregated storage. Includes +//!a reference count but the class does not delete itself, this is +//!responsibility of user classes. Node size (NodeSize) and the number of +//!nodes allocated per block (NodesPerBlock) are known at compile time +template< class SegmentManager, std::size_t NodeSize, std::size_t NodesPerBlock > +class private_node_pool + //Inherit from the implementation to avoid template bloat + : public private_node_pool_impl +{ + typedef private_node_pool_impl base_t; + //Non-copyable + private_node_pool(); + private_node_pool(const private_node_pool &); + private_node_pool &operator=(const private_node_pool &); + + public: + typedef SegmentManager segment_manager; + + static const std::size_t nodes_per_block = NodesPerBlock; + //Deprecated, use nodes_per_block + static const std::size_t nodes_per_chunk = NodesPerBlock; + + //!Constructor from a segment manager. Never throws + private_node_pool(segment_manager *segment_mngr) + : base_t(segment_mngr, NodeSize, NodesPerBlock) + {} + + //!Returns the segment manager. Never throws + segment_manager* get_segment_manager() const + { return static_cast(base_t::get_segment_manager_base()); } +}; + + +//!Pooled shared memory allocator using single segregated storage. Includes +//!a reference count but the class does not delete itself, this is +//!responsibility of user classes. Node size (NodeSize) and the number of +//!nodes allocated per block (NodesPerBlock) are known at compile time +//!Pooled shared memory allocator using adaptive pool. Includes +//!a reference count but the class does not delete itself, this is +//!responsibility of user classes. Node size (NodeSize) and the number of +//!nodes allocated per block (NodesPerBlock) are known at compile time +template< class SegmentManager + , std::size_t NodeSize + , std::size_t NodesPerBlock + > +class shared_node_pool + : public detail::shared_pool_impl + < private_node_pool + + > +{ + typedef detail::shared_pool_impl + < private_node_pool + + > base_t; + public: + shared_node_pool(SegmentManager *segment_mgnr) + : base_t(segment_mgnr) + {} +}; + +} //namespace detail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_POOL_HPP diff --git a/win32/include/boost/interprocess/allocators/detail/node_tools.hpp b/win32/include/boost/interprocess/allocators/detail/node_tools.hpp new file mode 100755 index 000000000..e787aefa4 --- /dev/null +++ b/win32/include/boost/interprocess/allocators/detail/node_tools.hpp @@ -0,0 +1,50 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP +#define BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include + +namespace boost { +namespace interprocess { +namespace detail { + + +template +struct node_slist +{ + //This hook will be used to chain the individual nodes + typedef typename bi::make_slist_base_hook + , bi::link_mode >::type slist_hook_t; + + //A node object will hold node_t when it's not allocated + struct node_t + : public slist_hook_t + {}; + + typedef typename bi::make_slist + , bi::base_hook >::type node_slist_t; +}; + +} //namespace detail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_NODE_TOOLS_HPP diff --git a/win32/include/boost/interprocess/allocators/node_allocator.hpp b/win32/include/boost/interprocess/allocators/node_allocator.hpp new file mode 100755 index 000000000..dcf3293d6 --- /dev/null +++ b/win32/include/boost/interprocess/allocators/node_allocator.hpp @@ -0,0 +1,451 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP +#define BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes node_allocator pooled shared memory STL compatible allocator + +namespace boost { +namespace interprocess { + +/// @cond + +namespace detail{ + +template < unsigned int Version + , class T + , class SegmentManager + , std::size_t NodesPerBlock + > +class node_allocator_base + : public node_pool_allocation_impl + < node_allocator_base + < Version, T, SegmentManager, NodesPerBlock> + , Version + , T + , SegmentManager + > +{ + public: + typedef typename SegmentManager::void_pointer void_pointer; + typedef SegmentManager segment_manager; + typedef node_allocator_base + self_t; + + /// @cond + + template + struct node_pool + { + typedef detail::shared_node_pool + < SegmentManager, sizeof_value::value, NodesPerBlock> type; + + static type *get(void *p) + { return static_cast(p); } + }; + /// @endcond + + BOOST_STATIC_ASSERT((Version <=2)); + + public: + //------- + typedef typename detail:: + pointer_to_other::type pointer; + typedef typename detail:: + pointer_to_other::type const_pointer; + typedef T value_type; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef detail::version_type version; + typedef transform_iterator + < typename SegmentManager:: + multiallocation_iterator + , detail::cast_functor > multiallocation_iterator; + typedef typename SegmentManager:: + multiallocation_chain multiallocation_chain; + + //!Obtains node_allocator_base from + //!node_allocator_base + template + struct rebind + { + typedef node_allocator_base other; + }; + + /// @cond + private: + //!Not assignable from related node_allocator_base + template + node_allocator_base& operator= + (const node_allocator_base&); + + //!Not assignable from other node_allocator_base + //node_allocator_base& operator=(const node_allocator_base&); + /// @endcond + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + node_allocator_base(segment_manager *segment_mngr) + : mp_node_pool(detail::get_or_create_node_pool::type>(segment_mngr)) { } + + //!Copy constructor from other node_allocator_base. Increments the reference + //!count of the associated node pool. Never throws + node_allocator_base(const node_allocator_base &other) + : mp_node_pool(other.get_node_pool()) + { + node_pool<0>::get(detail::get_pointer(mp_node_pool))->inc_ref_count(); + } + + //!Copy constructor from related node_allocator_base. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + node_allocator_base + (const node_allocator_base &other) + : mp_node_pool(detail::get_or_create_node_pool::type>(other.get_segment_manager())) { } + + //!Assignment from other node_allocator_base + node_allocator_base& operator=(const node_allocator_base &other) + { + node_allocator_base c(other); + swap(*this, c); + return *this; + } + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~node_allocator_base() + { detail::destroy_node_pool_if_last_link(node_pool<0>::get(detail::get_pointer(mp_node_pool))); } + + //!Returns a pointer to the node pool. + //!Never throws + void* get_node_pool() const + { return detail::get_pointer(mp_node_pool); } + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const + { return node_pool<0>::get(detail::get_pointer(mp_node_pool))->get_segment_manager(); } + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2) + { detail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); } + + /// @cond + private: + void_pointer mp_node_pool; + /// @endcond +}; + +//!Equality test for same type +//!of node_allocator_base +template inline +bool operator==(const node_allocator_base &alloc1, + const node_allocator_base &alloc2) + { return alloc1.get_node_pool() == alloc2.get_node_pool(); } + +//!Inequality test for same type +//!of node_allocator_base +template inline +bool operator!=(const node_allocator_base &alloc1, + const node_allocator_base &alloc2) + { return alloc1.get_node_pool() != alloc2.get_node_pool(); } + +template < class T + , class SegmentManager + , std::size_t NodesPerBlock = 64 + > +class node_allocator_v1 + : public node_allocator_base + < 1 + , T + , SegmentManager + , NodesPerBlock + > +{ + public: + typedef detail::node_allocator_base + < 1, T, SegmentManager, NodesPerBlock> base_t; + + template + struct rebind + { + typedef node_allocator_v1 other; + }; + + node_allocator_v1(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + node_allocator_v1 + (const node_allocator_v1 &other) + : base_t(other) + {} +}; + +} //namespace detail{ + +/// @endcond + +//!An STL node allocator that uses a segment manager as memory +//!source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the allocator in shared memory, memory mapped-files, etc... +//!This node allocator shares a segregated storage between all instances +//!of node_allocator with equal sizeof(T) placed in the same segment +//!group. NodesPerBlock is the number of nodes allocated at once when the allocator +//!needs runs out of nodes +template < class T + , class SegmentManager + , std::size_t NodesPerBlock + > +class node_allocator + /// @cond + : public detail::node_allocator_base + < 2 + , T + , SegmentManager + , NodesPerBlock + > + /// @endcond +{ + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + typedef detail::node_allocator_base + < 2, T, SegmentManager, NodesPerBlock> base_t; + public: + typedef detail::version_type version; + + template + struct rebind + { + typedef node_allocator other; + }; + + node_allocator(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + node_allocator + (const node_allocator &other) + : base_t(other) + {} + + #else //BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: + typedef implementation_defined::segment_manager segment_manager; + typedef segment_manager::void_pointer void_pointer; + typedef implementation_defined::pointer pointer; + typedef implementation_defined::const_pointer const_pointer; + typedef T value_type; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + //!Obtains node_allocator from + //!node_allocator + template + struct rebind + { + typedef node_allocator other; + }; + + private: + //!Not assignable from + //!related node_allocator + template + node_allocator& operator= + (const node_allocator&); + + //!Not assignable from + //!other node_allocator + //node_allocator& operator=(const node_allocator&); + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + node_allocator(segment_manager *segment_mngr); + + //!Copy constructor from other node_allocator. Increments the reference + //!count of the associated node pool. Never throws + node_allocator(const node_allocator &other); + + //!Copy constructor from related node_allocator. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + node_allocator + (const node_allocator &other); + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~node_allocator(); + + //!Returns a pointer to the node pool. + //!Never throws + void* get_node_pool() const; + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const; + + //!Returns the number of elements that could be allocated. + //!Never throws + size_type max_size() const; + + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0); + + //!Deallocate allocated memory. + //!Never throws + void deallocate(const pointer &ptr, size_type count); + + //!Deallocates all free blocks + //!of the pool + void deallocate_free_blocks(); + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2); + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const; + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const; + + //!Copy construct an object. + //!Throws if T's copy constructor throws + void construct(const pointer &ptr, const_reference v); + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr); + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const; + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, const pointer &reuse = 0); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements); + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_iterator it); + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one(); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + multiallocation_iterator allocate_individual(std::size_t num_elements); + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_iterator it); + #endif +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Equality test for same type +//!of node_allocator +template inline +bool operator==(const node_allocator &alloc1, + const node_allocator &alloc2); + +//!Inequality test for same type +//!of node_allocator +template inline +bool operator!=(const node_allocator &alloc1, + const node_allocator &alloc2); + +#endif + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_NODE_ALLOCATOR_HPP diff --git a/win32/include/boost/interprocess/allocators/private_adaptive_pool.hpp b/win32/include/boost/interprocess/allocators/private_adaptive_pool.hpp new file mode 100755 index 000000000..25777b70c --- /dev/null +++ b/win32/include/boost/interprocess/allocators/private_adaptive_pool.hpp @@ -0,0 +1,467 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP +#define BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes private_adaptive_pool_base pooled shared memory STL compatible allocator + +namespace boost { +namespace interprocess { + +/// @cond + +namespace detail { + +template < unsigned int Version + , class T + , class SegmentManager + , std::size_t NodesPerBlock + , std::size_t MaxFreeBlocks + , unsigned char OverheadPercent + > +class private_adaptive_pool_base + : public node_pool_allocation_impl + < private_adaptive_pool_base < Version, T, SegmentManager, NodesPerBlock + , MaxFreeBlocks, OverheadPercent> + , Version + , T + , SegmentManager + > +{ + public: + //Segment manager + typedef SegmentManager segment_manager; + typedef typename SegmentManager::void_pointer void_pointer; + + /// @cond + private: + typedef private_adaptive_pool_base + < Version, T, SegmentManager, NodesPerBlock + , MaxFreeBlocks, OverheadPercent> self_t; + typedef detail::private_adaptive_node_pool + ::value + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > node_pool_t; + + BOOST_STATIC_ASSERT((Version <=2)); + + /// @endcond + + public: + typedef typename detail:: + pointer_to_other::type pointer; + typedef typename detail:: + pointer_to_other::type const_pointer; + typedef T value_type; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef detail::version_type + version; + typedef transform_iterator + < typename SegmentManager:: + multiallocation_iterator + , detail::cast_functor > multiallocation_iterator; + typedef typename SegmentManager:: + multiallocation_chain multiallocation_chain; + + //!Obtains node_allocator from other node_allocator + template + struct rebind + { + typedef private_adaptive_pool_base + other; + }; + + /// @cond + + template + struct node_pool + { + typedef detail::private_adaptive_node_pool + ::value + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > type; + + static type *get(void *p) + { return static_cast(p); } + }; + + private: + //!Not assignable from related private_adaptive_pool_base + template + private_adaptive_pool_base& operator= + (const private_adaptive_pool_base&); + + //!Not assignable from other private_adaptive_pool_base + private_adaptive_pool_base& operator=(const private_adaptive_pool_base&); + /// @endcond + + public: + //!Constructor from a segment manager + private_adaptive_pool_base(segment_manager *segment_mngr) + : m_node_pool(segment_mngr) + {} + + //!Copy constructor from other private_adaptive_pool_base. Never throws + private_adaptive_pool_base(const private_adaptive_pool_base &other) + : m_node_pool(other.get_segment_manager()) + {} + + //!Copy constructor from related private_adaptive_pool_base. Never throws. + template + private_adaptive_pool_base + (const private_adaptive_pool_base + &other) + : m_node_pool(other.get_segment_manager()) + {} + + //!Destructor, frees all used memory. Never throws + ~private_adaptive_pool_base() + {} + + //!Returns the segment manager. Never throws + segment_manager* get_segment_manager()const + { return m_node_pool.get_segment_manager(); } + + //!Returns the internal node pool. Never throws + node_pool_t* get_node_pool() const + { return const_cast(&m_node_pool); } + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different shared memory segments, the result is undefined. + friend void swap(self_t &alloc1,self_t &alloc2) + { alloc1.m_node_pool.swap(alloc2.m_node_pool); } + + /// @cond + private: + node_pool_t m_node_pool; + /// @endcond +}; + +//!Equality test for same type of private_adaptive_pool_base +template inline +bool operator==(const private_adaptive_pool_base &alloc1, + const private_adaptive_pool_base &alloc2) +{ return &alloc1 == &alloc2; } + +//!Inequality test for same type of private_adaptive_pool_base +template inline +bool operator!=(const private_adaptive_pool_base &alloc1, + const private_adaptive_pool_base &alloc2) +{ return &alloc1 != &alloc2; } + +template < class T + , class SegmentManager + , std::size_t NodesPerBlock = 64 + , std::size_t MaxFreeBlocks = 2 + , unsigned char OverheadPercent = 5 + > +class private_adaptive_pool_v1 + : public private_adaptive_pool_base + < 1 + , T + , SegmentManager + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > +{ + public: + typedef detail::private_adaptive_pool_base + < 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t; + + template + struct rebind + { + typedef private_adaptive_pool_v1 other; + }; + + private_adaptive_pool_v1(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + private_adaptive_pool_v1 + (const private_adaptive_pool_v1 &other) + : base_t(other) + {} +}; + +} //namespace detail { + +/// @endcond + +//!An STL node allocator that uses a segment manager as memory +//!source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the allocator in shared memory, memory mapped-files, etc... +//!This allocator has its own node pool. +//! +//!NodesPerBlock is the minimum number of nodes of nodes allocated at once when +//!the allocator needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks +//!that the adaptive node pool will hold. The rest of the totally free blocks will be +//!deallocated with the segment manager. +//! +//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator: +//!(memory usable for nodes / total memory allocated from the segment manager) +template < class T + , class SegmentManager + , std::size_t NodesPerBlock + , std::size_t MaxFreeBlocks + , unsigned char OverheadPercent + > +class private_adaptive_pool + /// @cond + : public detail::private_adaptive_pool_base + < 2 + , T + , SegmentManager + , NodesPerBlock + , MaxFreeBlocks + , OverheadPercent + > + /// @endcond +{ + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + typedef detail::private_adaptive_pool_base + < 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t; + public: + typedef detail::version_type version; + + template + struct rebind + { + typedef private_adaptive_pool + other; + }; + + private_adaptive_pool(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + private_adaptive_pool + (const private_adaptive_pool &other) + : base_t(other) + {} + + #else + public: + typedef implementation_defined::segment_manager segment_manager; + typedef segment_manager::void_pointer void_pointer; + typedef implementation_defined::pointer pointer; + typedef implementation_defined::const_pointer const_pointer; + typedef T value_type; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + //!Obtains private_adaptive_pool from + //!private_adaptive_pool + template + struct rebind + { + typedef private_adaptive_pool + other; + }; + + private: + //!Not assignable from + //!related private_adaptive_pool + template + private_adaptive_pool& operator= + (const private_adaptive_pool&); + + //!Not assignable from + //!other private_adaptive_pool + private_adaptive_pool& operator=(const private_adaptive_pool&); + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + private_adaptive_pool(segment_manager *segment_mngr); + + //!Copy constructor from other private_adaptive_pool. Increments the reference + //!count of the associated node pool. Never throws + private_adaptive_pool(const private_adaptive_pool &other); + + //!Copy constructor from related private_adaptive_pool. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + private_adaptive_pool + (const private_adaptive_pool &other); + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~private_adaptive_pool(); + + //!Returns a pointer to the node pool. + //!Never throws + node_pool_t* get_node_pool() const; + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const; + + //!Returns the number of elements that could be allocated. + //!Never throws + size_type max_size() const; + + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0); + + //!Deallocate allocated memory. + //!Never throws + void deallocate(const pointer &ptr, size_type count); + + //!Deallocates all free blocks + //!of the pool + void deallocate_free_blocks(); + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2); + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const; + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const; + + //!Copy construct an object. + //!Throws if T's copy constructor throws + void construct(const pointer &ptr, const_reference v); + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr); + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const; + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, const pointer &reuse = 0); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements); + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_iterator it); + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one(); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + multiallocation_iterator allocate_individual(std::size_t num_elements); + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_iterator it); + #endif +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Equality test for same type +//!of private_adaptive_pool +template inline +bool operator==(const private_adaptive_pool &alloc1, + const private_adaptive_pool &alloc2); + +//!Inequality test for same type +//!of private_adaptive_pool +template inline +bool operator!=(const private_adaptive_pool &alloc1, + const private_adaptive_pool &alloc2); + +#endif + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP + diff --git a/win32/include/boost/interprocess/allocators/private_node_allocator.hpp b/win32/include/boost/interprocess/allocators/private_node_allocator.hpp new file mode 100755 index 000000000..ff8446328 --- /dev/null +++ b/win32/include/boost/interprocess/allocators/private_node_allocator.hpp @@ -0,0 +1,443 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP +#define BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes private_node_allocator_base pooled shared memory STL compatible allocator + +namespace boost { +namespace interprocess { + +/// @cond + +namespace detail { + +template < unsigned int Version + , class T + , class SegmentManager + , std::size_t NodesPerBlock + > +class private_node_allocator_base + : public node_pool_allocation_impl + < private_node_allocator_base < Version, T, SegmentManager, NodesPerBlock> + , Version + , T + , SegmentManager + > +{ + public: + //Segment manager + typedef SegmentManager segment_manager; + typedef typename SegmentManager::void_pointer void_pointer; + + /// @cond + private: + typedef private_node_allocator_base + < Version, T, SegmentManager, NodesPerBlock> self_t; + typedef detail::private_node_pool + ::value + , NodesPerBlock + > node_pool_t; + + BOOST_STATIC_ASSERT((Version <=2)); + + /// @endcond + + public: + typedef typename detail:: + pointer_to_other::type pointer; + typedef typename detail:: + pointer_to_other::type const_pointer; + typedef T value_type; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef detail::version_type + version; + typedef transform_iterator + < typename SegmentManager:: + multiallocation_iterator + , detail::cast_functor > multiallocation_iterator; + typedef typename SegmentManager:: + multiallocation_chain multiallocation_chain; + + //!Obtains node_allocator from other node_allocator + template + struct rebind + { + typedef private_node_allocator_base + other; + }; + + /// @cond + template + struct node_pool + { + typedef detail::private_node_pool + ::value + , NodesPerBlock + > type; + + static type *get(void *p) + { return static_cast(p); } + }; + + private: + //!Not assignable from related private_node_allocator_base + template + private_node_allocator_base& operator= + (const private_node_allocator_base&); + + //!Not assignable from other private_node_allocator_base + private_node_allocator_base& operator=(const private_node_allocator_base&); + /// @endcond + + public: + //!Constructor from a segment manager + private_node_allocator_base(segment_manager *segment_mngr) + : m_node_pool(segment_mngr) + {} + + //!Copy constructor from other private_node_allocator_base. Never throws + private_node_allocator_base(const private_node_allocator_base &other) + : m_node_pool(other.get_segment_manager()) + {} + + //!Copy constructor from related private_node_allocator_base. Never throws. + template + private_node_allocator_base + (const private_node_allocator_base + &other) + : m_node_pool(other.get_segment_manager()) + {} + + //!Destructor, frees all used memory. Never throws + ~private_node_allocator_base() + {} + + //!Returns the segment manager. Never throws + segment_manager* get_segment_manager()const + { return m_node_pool.get_segment_manager(); } + + //!Returns the internal node pool. Never throws + node_pool_t* get_node_pool() const + { return const_cast(&m_node_pool); } + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different shared memory segments, the result is undefined. + friend void swap(self_t &alloc1,self_t &alloc2) + { alloc1.m_node_pool.swap(alloc2.m_node_pool); } + + /// @cond + private: + node_pool_t m_node_pool; + /// @endcond +}; + +//!Equality test for same type of private_node_allocator_base +template inline +bool operator==(const private_node_allocator_base &alloc1, + const private_node_allocator_base &alloc2) +{ return &alloc1 == &alloc2; } + +//!Inequality test for same type of private_node_allocator_base +template inline +bool operator!=(const private_node_allocator_base &alloc1, + const private_node_allocator_base &alloc2) +{ return &alloc1 != &alloc2; } + +template < class T + , class SegmentManager + , std::size_t NodesPerBlock = 64 + > +class private_node_allocator_v1 + : public private_node_allocator_base + < 1 + , T + , SegmentManager + , NodesPerBlock + > +{ + public: + typedef detail::private_node_allocator_base + < 1, T, SegmentManager, NodesPerBlock> base_t; + + template + struct rebind + { + typedef private_node_allocator_v1 other; + }; + + private_node_allocator_v1(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + private_node_allocator_v1 + (const private_node_allocator_v1 &other) + : base_t(other) + {} +}; + +} //namespace detail { + +/// @endcond + +//!An STL node allocator that uses a segment manager as memory +//!source. The internal pointer type will of the same type (raw, smart) as +//!"typename SegmentManager::void_pointer" type. This allows +//!placing the allocator in shared memory, memory mapped-files, etc... +//!This allocator has its own node pool. NodesPerBlock is the number of nodes allocated +//!at once when the allocator needs runs out of nodes +template < class T + , class SegmentManager + , std::size_t NodesPerBlock + > +class private_node_allocator + /// @cond + : public detail::private_node_allocator_base + < 2 + , T + , SegmentManager + , NodesPerBlock + > + /// @endcond +{ + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + typedef detail::private_node_allocator_base + < 2, T, SegmentManager, NodesPerBlock> base_t; + public: + typedef detail::version_type version; + + template + struct rebind + { + typedef private_node_allocator + other; + }; + + private_node_allocator(SegmentManager *segment_mngr) + : base_t(segment_mngr) + {} + + template + private_node_allocator + (const private_node_allocator &other) + : base_t(other) + {} + + #else + public: + typedef implementation_defined::segment_manager segment_manager; + typedef segment_manager::void_pointer void_pointer; + typedef implementation_defined::pointer pointer; + typedef implementation_defined::const_pointer const_pointer; + typedef T value_type; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + //!Obtains private_node_allocator from + //!private_node_allocator + template + struct rebind + { + typedef private_node_allocator + other; + }; + + private: + //!Not assignable from + //!related private_node_allocator + template + private_node_allocator& operator= + (const private_node_allocator&); + + //!Not assignable from + //!other private_node_allocator + private_node_allocator& operator=(const private_node_allocator&); + + public: + //!Constructor from a segment manager. If not present, constructs a node + //!pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + private_node_allocator(segment_manager *segment_mngr); + + //!Copy constructor from other private_node_allocator. Increments the reference + //!count of the associated node pool. Never throws + private_node_allocator(const private_node_allocator &other); + + //!Copy constructor from related private_node_allocator. If not present, constructs + //!a node pool. Increments the reference count of the associated node pool. + //!Can throw boost::interprocess::bad_alloc + template + private_node_allocator + (const private_node_allocator &other); + + //!Destructor, removes node_pool_t from memory + //!if its reference count reaches to zero. Never throws + ~private_node_allocator(); + + //!Returns a pointer to the node pool. + //!Never throws + node_pool_t* get_node_pool() const; + + //!Returns the segment manager. + //!Never throws + segment_manager* get_segment_manager()const; + + //!Returns the number of elements that could be allocated. + //!Never throws + size_type max_size() const; + + //!Allocate memory for an array of count elements. + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate(size_type count, cvoid_pointer hint = 0); + + //!Deallocate allocated memory. + //!Never throws + void deallocate(const pointer &ptr, size_type count); + + //!Deallocates all free blocks + //!of the pool + void deallocate_free_blocks(); + + //!Swaps allocators. Does not throw. If each allocator is placed in a + //!different memory segment, the result is undefined. + friend void swap(self_t &alloc1, self_t &alloc2); + + //!Returns address of mutable object. + //!Never throws + pointer address(reference value) const; + + //!Returns address of non mutable object. + //!Never throws + const_pointer address(const_reference value) const; + + //!Copy construct an object. + //!Throws if T's copy constructor throws + void construct(const pointer &ptr, const_reference v); + + //!Destroys object. Throws if object's + //!destructor throws + void destroy(const pointer &ptr); + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. This size only works for memory allocated with + //!allocate, allocation_command and allocate_many. + size_type size(const pointer &p) const; + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, const pointer &reuse = 0); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + multiallocation_iterator allocate_many(size_type elem_size, std::size_t num_elements); + + //!Allocates n_elements elements, each one of size elem_sizes[i]in a + //!contiguous block + //!of memory. The elements must be deallocated + multiallocation_iterator allocate_many(const size_type *elem_sizes, size_type n_elements); + + //!Allocates many elements of size elem_size in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. The elements must be deallocated + //!with deallocate(...) + void deallocate_many(multiallocation_iterator it); + + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws boost::interprocess::bad_alloc if there is no enough memory + pointer allocate_one(); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + multiallocation_iterator allocate_individual(std::size_t num_elements); + + //!Deallocates memory previously allocated with allocate_one(). + //!You should never use deallocate_one to deallocate memory allocated + //!with other functions different from allocate_one(). Never throws + void deallocate_one(const pointer &p); + + //!Allocates many elements of size == 1 in a contiguous block + //!of memory. The minimum number to be allocated is min_elements, + //!the preferred and maximum number is + //!preferred_elements. The number of actually allocated elements is + //!will be assigned to received_size. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + void deallocate_individual(multiallocation_iterator it); + #endif +}; + +#ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED + +//!Equality test for same type +//!of private_node_allocator +template inline +bool operator==(const private_node_allocator &alloc1, + const private_node_allocator &alloc2); + +//!Inequality test for same type +//!of private_node_allocator +template inline +bool operator!=(const private_node_allocator &alloc1, + const private_node_allocator &alloc2); + +#endif + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_PRIVATE_NODE_ALLOCATOR_HPP + diff --git a/win32/include/boost/interprocess/anonymous_shared_memory.hpp b/win32/include/boost/interprocess/anonymous_shared_memory.hpp new file mode 100755 index 000000000..1b3914e02 --- /dev/null +++ b/win32/include/boost/interprocess/anonymous_shared_memory.hpp @@ -0,0 +1,129 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP +#define BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP + +#include +#include +#include +#include +#include +#include +#include + +#if (!defined(BOOST_WINDOWS)) || defined(BOOST_DISABLE_WIN32) +# include //open, O_CREAT, O_*... +# include //mmap +# include //mode_t, S_IRWXG, S_IRWXO, S_IRWXU, +#else +#include +#endif + + +//!\file +//!Describes a function that creates anonymous shared memory that can be +//!shared between forked processes + +namespace boost { +namespace interprocess { + +/// @cond + +namespace detail{ + + class raw_mapped_region_creator + { + public: + static + #ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE + mapped_region + #else + move_return + #endif + create_posix_mapped_region(void *address, offset_t offset, std::size_t size) + { + mapped_region region; + region.m_base = address; + region.m_offset = offset; + region.m_extra_offset = 0; + region.m_size = size; + return region; + } + }; +} + +/// @endcond + +//!A function that creates an anonymous shared memory segment of size "size". +//!If "address" is passed the function will try to map the segment in that address. +//!Otherwise the operating system will choose the mapping address. +//!The function returns a mapped_region holding that segment or throws +//!interprocess_exception if the function fails. +static +#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE +mapped_region +#else +detail::move_return +#endif +anonymous_shared_memory(std::size_t size, void *address = 0) +#if (!defined(BOOST_WINDOWS)) || defined(BOOST_DISABLE_WIN32) +{ + int flags; + int fd = -1; + + #if defined(MAP_ANONYMOUS) //Use MAP_ANONYMOUS + flags = MAP_ANONYMOUS | MAP_SHARED; + #elif !defined(MAP_ANONYMOUS) && defined(MAP_ANON) //use MAP_ANON + flags = MAP_ANON | MAP_SHARED; + #else // Use "/dev/zero" + fd = open("/dev/zero", O_RDWR); + flags = MAP_SHARED; + if(fd == -1){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + #endif + + + address = mmap( (void*)address + , size + , PROT_READ|PROT_WRITE + , flags + , fd + , 0); + + if(address == MAP_FAILED){ + if(fd != -1) + close(fd); + error_info err = system_error_code(); + throw interprocess_exception(err); + } + + if(fd != -1) + close(fd); + + return detail::raw_mapped_region_creator::create_posix_mapped_region(address, 0, size); +} +#else +{ + windows_shared_memory anonymous_mapping(create_only, 0, read_write, size); + mapped_region region(anonymous_mapping, read_write, 0, size, address); + return region; +} + +#endif + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_ANONYMOUS_SHARED_MEMORY_HPP diff --git a/win32/include/boost/interprocess/containers/deque.hpp b/win32/include/boost/interprocess/containers/deque.hpp new file mode 100755 index 000000000..cc6f8ac04 --- /dev/null +++ b/win32/include/boost/interprocess/containers/deque.hpp @@ -0,0 +1,1561 @@ +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2006. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This file comes from SGI's stl_deque.h and stl_uninitialized.h files. +// Modified by Ion Gaztanaga 2005. +// Renaming, isolating and porting to generic algorithms. Pointer typedef +// set to allocator::pointer to allow placing it in shared memory. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DEQUE_HPP +#define BOOST_INTERPROCESS_DEQUE_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { + +/// @cond +template +class deque; + +// Note: this function is simply a kludge to work around several compilers' +// bugs in handling constant expressions. +inline std::size_t deque_buf_size(std::size_t size) + { return size < 512 ? std::size_t(512 / size) : std::size_t(1); } + +// Deque base class. It has two purposes. First, its constructor +// and destructor allocate (but don't initialize) storage. This makes +// exception safety easier. +template +class deque_base +{ + public: + typedef typename Alloc::value_type val_alloc_val; + typedef typename Alloc::pointer val_alloc_ptr; + typedef typename Alloc::const_pointer val_alloc_cptr; + typedef typename Alloc::reference val_alloc_ref; + typedef typename Alloc::const_reference val_alloc_cref; + typedef typename Alloc::value_type val_alloc_diff; + typedef typename Alloc::template rebind + ::other ptr_alloc_t; + typedef typename ptr_alloc_t::value_type ptr_alloc_val; + typedef typename ptr_alloc_t::pointer ptr_alloc_ptr; + typedef typename ptr_alloc_t::const_pointer ptr_alloc_cptr; + typedef typename ptr_alloc_t::reference ptr_alloc_ref; + typedef typename ptr_alloc_t::const_reference ptr_alloc_cref; + typedef typename Alloc::template + rebind::other allocator_type; + typedef allocator_type stored_allocator_type; + + protected: + enum { trivial_dctr_after_move = boost::has_trivial_destructor::value }; + + typedef typename Alloc::template + rebind::other map_allocator_type; + + val_alloc_ptr priv_allocate_node() + { return this->alloc().allocate(deque_buf_size(sizeof(T))); } + + void priv_deallocate_node(val_alloc_ptr p) + { this->alloc().deallocate(p, deque_buf_size(sizeof(T))); } + + ptr_alloc_ptr priv_allocate_map(std::size_t n) + { return this->ptr_alloc().allocate(n); } + + void priv_deallocate_map(ptr_alloc_ptr p, std::size_t n) + { this->ptr_alloc().deallocate(p, n); } + + public: + // Class invariants: + // For any nonsingular iterator i: + // i.node is the address of an element in the map array. The + // contents of i.node is a pointer to the beginning of a node. + // i.first == //(i.node) + // i.last == i.first + node_size + // i.cur is a pointer in the range [i.first, i.last). NOTE: + // the implication of this is that i.cur is always a dereferenceable + // pointer, even if i is a past-the-end iterator. + // Start and Finish are always nonsingular iterators. NOTE: this means + // that an empty deque must have one node, and that a deque + // with N elements, where N is the buffer size, must have two nodes. + // For every node other than start.node and finish.node, every element + // in the node is an initialized object. If start.node == finish.node, + // then [start.cur, finish.cur) are initialized objects, and + // the elements outside that range are uninitialized storage. Otherwise, + // [start.cur, start.last) and [finish.first, finish.cur) are initialized + // objects, and [start.first, start.cur) and [finish.cur, finish.last) + // are uninitialized storage. + // [map, map + map_size) is a valid, non-empty range. + // [start.node, finish.node] is a valid range contained within + // [map, map + map_size). + // A pointer in the range [map, map + map_size) points to an allocated node + // if and only if the pointer is in the range [start.node, finish.node]. + class const_iterator + : public std::iterator + { + public: + static std::size_t s_buffer_size() { return deque_buf_size(sizeof(T)); } + + typedef std::random_access_iterator_tag iterator_category; + typedef val_alloc_val value_type; + typedef val_alloc_cptr pointer; + typedef val_alloc_cref reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef ptr_alloc_ptr index_pointer; + typedef const_iterator self_t; + + friend class deque; + friend class deque_base; + + protected: + val_alloc_ptr m_cur; + val_alloc_ptr m_first; + val_alloc_ptr m_last; + index_pointer m_node; + + public: + const_iterator(val_alloc_ptr x, index_pointer y) + : m_cur(x), m_first(*y), + m_last(*y + s_buffer_size()), m_node(y) {} + + const_iterator() : m_cur(0), m_first(0), m_last(0), m_node(0) {} + + const_iterator(const const_iterator& x) + : m_cur(x.m_cur), m_first(x.m_first), + m_last(x.m_last), m_node(x.m_node) {} + + reference operator*() const + { return *this->m_cur; } + + pointer operator->() const + { return this->m_cur; } + + difference_type operator-(const self_t& x) const + { + return difference_type(this->s_buffer_size()) * (this->m_node - x.m_node - 1) + + (this->m_cur - this->m_first) + (x.m_last - x.m_cur); + } + + self_t& operator++() + { + ++this->m_cur; + if (this->m_cur == this->m_last) { + this->priv_set_node(this->m_node + 1); + this->m_cur = this->m_first; + } + return *this; + } + + self_t operator++(int) + { + self_t tmp = *this; + ++*this; + return tmp; + } + + self_t& operator--() + { + if (this->m_cur == this->m_first) { + this->priv_set_node(this->m_node - 1); + this->m_cur = this->m_last; + } + --this->m_cur; + return *this; + } + + self_t operator--(int) + { + self_t tmp = *this; + --*this; + return tmp; + } + + self_t& operator+=(difference_type n) + { + difference_type offset = n + (this->m_cur - this->m_first); + if (offset >= 0 && offset < difference_type(this->s_buffer_size())) + this->m_cur += n; + else { + difference_type node_offset = + offset > 0 ? offset / difference_type(this->s_buffer_size()) + : -difference_type((-offset - 1) / this->s_buffer_size()) - 1; + this->priv_set_node(this->m_node + node_offset); + this->m_cur = this->m_first + + (offset - node_offset * difference_type(this->s_buffer_size())); + } + return *this; + } + + self_t operator+(difference_type n) const + { self_t tmp = *this; return tmp += n; } + + self_t& operator-=(difference_type n) + { return *this += -n; } + + self_t operator-(difference_type n) const + { self_t tmp = *this; return tmp -= n; } + + reference operator[](difference_type n) const + { return *(*this + n); } + + bool operator==(const self_t& x) const + { return this->m_cur == x.m_cur; } + + bool operator!=(const self_t& x) const + { return !(*this == x); } + + bool operator<(const self_t& x) const + { + return (this->m_node == x.m_node) ? + (this->m_cur < x.m_cur) : (this->m_node < x.m_node); + } + + bool operator>(const self_t& x) const + { return x < *this; } + + bool operator<=(const self_t& x) const + { return !(x < *this); } + + bool operator>=(const self_t& x) const + { return !(*this < x); } + + void priv_set_node(index_pointer new_node) + { + this->m_node = new_node; + this->m_first = *new_node; + this->m_last = this->m_first + difference_type(this->s_buffer_size()); + } + + friend const_iterator operator+(std::ptrdiff_t n, const const_iterator& x) + { return x + n; } + }; + + //Deque iterator + class iterator : public const_iterator + { + public: + typedef std::random_access_iterator_tag iterator_category; + typedef val_alloc_val value_type; + typedef ptr_alloc_ptr pointer; + typedef val_alloc_ref reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef ptr_alloc_ptr index_pointer; + typedef const_iterator self_t; + + friend class deque; + friend class deque_base; + + private: + explicit iterator(const const_iterator& x) : const_iterator(x){} + + public: + //Constructors + iterator(val_alloc_ptr x, index_pointer y) : const_iterator(x, y){} + iterator() : const_iterator(){} + //iterator(const const_iterator &cit) : const_iterator(cit){} + iterator(const iterator& x) : const_iterator(x){} + + //Pointer like operators + reference operator*() const { return *this->m_cur; } + pointer operator->() const { return this->m_cur; } + + reference operator[](difference_type n) const { return *(*this + n); } + + //Increment / Decrement + iterator& operator++() + { this->const_iterator::operator++(); return *this; } + + iterator operator++(int) + { iterator tmp = *this; ++*this; return tmp; } + + iterator& operator--() + { this->const_iterator::operator--(); return *this; } + + iterator operator--(int) + { iterator tmp = *this; --*this; return tmp; } + + // Arithmetic + iterator& operator+=(difference_type off) + { this->const_iterator::operator+=(off); return *this; } + + iterator operator+(difference_type off) const + { return iterator(this->const_iterator::operator+(off)); } + + friend iterator operator+(difference_type off, const iterator& right) + { return iterator(off+static_cast(right)); } + + iterator& operator-=(difference_type off) + { this->const_iterator::operator-=(off); return *this; } + + iterator operator-(difference_type off) const + { return iterator(this->const_iterator::operator-(off)); } + + difference_type operator-(const const_iterator& right) const + { return static_cast(*this) - right; } + }; + + deque_base(const allocator_type& a, std::size_t num_elements) + : members_(a) + { this->priv_initialize_map(num_elements); } + + deque_base(const allocator_type& a) + : members_(a) + {} + + ~deque_base() + { + if (this->members_.m_map) { + this->priv_destroy_nodes(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1); + this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); + } + } + + protected: + void priv_initialize_map(std::size_t num_elements) + { + std::size_t num_nodes = num_elements / deque_buf_size(sizeof(T)) + 1; + + this->members_.m_map_size = max_value((std::size_t) InitialMapSize, num_nodes + 2); + this->members_.m_map = this->priv_allocate_map(this->members_.m_map_size); + + ptr_alloc_ptr nstart = this->members_.m_map + (this->members_.m_map_size - num_nodes) / 2; + ptr_alloc_ptr nfinish = nstart + num_nodes; + + BOOST_TRY { + this->priv_create_nodes(nstart, nfinish); + } + BOOST_CATCH(...){ + this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); + this->members_.m_map = 0; + this->members_.m_map_size = 0; + BOOST_RETHROW + } + BOOST_CATCH_END + + this->members_.m_start.priv_set_node(nstart); + this->members_.m_finish.priv_set_node(nfinish - 1); + this->members_.m_start.m_cur = this->members_.m_start.m_first; + this->members_.m_finish.m_cur = this->members_.m_finish.m_first + + num_elements % deque_buf_size(sizeof(T)); + } + + void priv_create_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) + { + ptr_alloc_ptr cur; + BOOST_TRY { + for (cur = nstart; cur < nfinish; ++cur) + *cur = this->priv_allocate_node(); + } + BOOST_CATCH(...){ + this->priv_destroy_nodes(nstart, cur); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + void priv_destroy_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) + { + for (ptr_alloc_ptr n = nstart; n < nfinish; ++n) + this->priv_deallocate_node(*n); + } + + enum { InitialMapSize = 8 }; + + protected: + struct members_holder + : public ptr_alloc_t + , public allocator_type + { + members_holder(const allocator_type &a) + : map_allocator_type(a), allocator_type(a) + , m_map(0), m_map_size(0) + , m_start(), m_finish() + {} + + ptr_alloc_ptr m_map; + std::size_t m_map_size; + iterator m_start; + iterator m_finish; + } members_; + + ptr_alloc_t &ptr_alloc() + { return members_; } + + const ptr_alloc_t &ptr_alloc() const + { return members_; } + + allocator_type &alloc() + { return members_; } + + const allocator_type &alloc() const + { return members_; } +}; +/// @endcond + +//! Deque class +//! +template +class deque : protected deque_base +{ + /// @cond + typedef deque_base Base; + + public: // Basic types + typedef typename Alloc::value_type val_alloc_val; + typedef typename Alloc::pointer val_alloc_ptr; + typedef typename Alloc::const_pointer val_alloc_cptr; + typedef typename Alloc::reference val_alloc_ref; + typedef typename Alloc::const_reference val_alloc_cref; + typedef typename Alloc::template + rebind::other ptr_alloc_t; + typedef typename ptr_alloc_t::value_type ptr_alloc_val; + typedef typename ptr_alloc_t::pointer ptr_alloc_ptr; + typedef typename ptr_alloc_t::const_pointer ptr_alloc_cptr; + typedef typename ptr_alloc_t::reference ptr_alloc_ref; + typedef typename ptr_alloc_t::const_reference ptr_alloc_cref; + /// @endcond + + typedef T value_type; + typedef val_alloc_ptr pointer; + typedef val_alloc_cptr const_pointer; + typedef val_alloc_ref reference; + typedef val_alloc_cref const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef typename Base::allocator_type allocator_type; + + public: // Iterators + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + /// @cond + protected: // Internal typedefs + typedef ptr_alloc_ptr index_pointer; + static std::size_t s_buffer_size() + { return deque_buf_size(sizeof(T)); } + /// @endcond + + allocator_type get_allocator() const { return Base::alloc(); } + + public: // Basic accessors + iterator begin() + { return this->members_.m_start; } + + iterator end() + { return this->members_.m_finish; } + + const_iterator begin() const + { return this->members_.m_start; } + + const_iterator end() const + { return this->members_.m_finish; } + + reverse_iterator rbegin() + { return reverse_iterator(this->members_.m_finish); } + + reverse_iterator rend() + { return reverse_iterator(this->members_.m_start); } + + const_reverse_iterator rbegin() const + { return const_reverse_iterator(this->members_.m_finish); } + + const_reverse_iterator rend() const + { return const_reverse_iterator(this->members_.m_start); } + + reference operator[](size_type n) + { return this->members_.m_start[difference_type(n)]; } + + const_reference operator[](size_type n) const + { return this->members_.m_start[difference_type(n)]; } + + void priv_range_check(size_type n) const + { if (n >= this->size()) BOOST_RETHROW std::out_of_range("deque"); } + + reference at(size_type n) + { this->priv_range_check(n); return (*this)[n]; } + + const_reference at(size_type n) const + { this->priv_range_check(n); return (*this)[n]; } + + reference front() { return *this->members_.m_start; } + + reference back() + { + iterator tmp = this->members_.m_finish; + --tmp; + return *tmp; + } + + const_reference front() const + { return *this->members_.m_start; } + + const_reference back() const + { const_iterator tmp = this->members_.m_finish; --tmp; return *tmp; } + + size_type size() const + { return this->members_.m_finish - this->members_.m_start; } + + size_type max_size() const + { return this->alloc().max_size(); } + + bool empty() const + { return this->members_.m_finish == this->members_.m_start; } + + explicit deque(const allocator_type& a = allocator_type()) + : Base(a, 0) {} + + deque(const deque& x) + : Base(x.alloc(), x.size()) + { std::uninitialized_copy(x.begin(), x.end(), this->members_.m_start); } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + deque(const detail::moved_object &mx) + : Base(mx.get()) + { this->swap(mx.get()); } + #else + deque(deque &&x) + : Base(detail::move_impl(x)) + { this->swap(x); } + #endif + + deque(size_type n, const value_type& value, + const allocator_type& a = allocator_type()) : Base(a, n) + { this->priv_fill_initialize(value); } + + explicit deque(size_type n) : Base(allocator_type(), n) + { this->resize(n); } + + // Check whether it's an integral type. If so, it's not an iterator. + template + deque(InpIt first, InpIt last, + const allocator_type& a = allocator_type()) : Base(a) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = detail::is_convertible::value; + typedef detail::bool_ Result; + this->priv_initialize_dispatch(first, last, Result()); + } + + ~deque() + { priv_destroy_range(this->members_.m_start, this->members_.m_finish); } + + deque& operator= (const deque& x) + { + const size_type len = size(); + if (&x != this) { + if (len >= x.size()) + this->erase(std::copy(x.begin(), x.end(), this->members_.m_start), this->members_.m_finish); + else { + const_iterator mid = x.begin() + difference_type(len); + std::copy(x.begin(), mid, this->members_.m_start); + this->insert(this->members_.m_finish, mid, x.end()); + } + } + return *this; + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + deque& operator= (const detail::moved_object &mx) + { this->clear(); this->swap(mx.get()); return *this; } + #else + deque& operator= (deque &&mx) + { this->clear(); this->swap(mx); return *this; } + #endif + + void swap(deque& x) + { + std::swap(this->members_.m_start, x.members_.m_start); + std::swap(this->members_.m_finish, x.members_.m_finish); + std::swap(this->members_.m_map, x.members_.m_map); + std::swap(this->members_.m_map_size, x.members_.m_map_size); + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(const detail::moved_object &mx) + { this->swap(mx.get()); } + #else + void swap(deque &&mx) + { this->swap(mx); } + #endif + + void assign(size_type n, const T& val) + { this->priv_fill_assign(n, val); } + + template + void assign(InpIt first, InpIt last) { + //Dispatch depending on integer/iterator + const bool aux_boolean = detail::is_convertible::value; + typedef detail::bool_ Result; + this->priv_assign_dispatch(first, last, Result()); + } + + void push_back(const value_type& t) + { + if (this->members_.m_finish.m_cur != this->members_.m_finish.m_last - 1) { + new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(t); + ++this->members_.m_finish.m_cur; + } + else + this->priv_push_back_aux(t); + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void push_back(const detail::moved_object &mt) + { + if (this->members_.m_finish.m_cur != this->members_.m_finish.m_last - 1) { + new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(mt); + ++this->members_.m_finish.m_cur; + } + else + this->priv_push_back_aux(mt); + } + #else + void push_back(value_type &&mt) + { + if (this->members_.m_finish.m_cur != this->members_.m_finish.m_last - 1) { + new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(detail::move_impl(mt)); + ++this->members_.m_finish.m_cur; + } + else + this->priv_push_back_aux(detail::move_impl(mt)); + } + #endif + + void push_front(const value_type& t) + { + if (this->members_.m_start.m_cur != this->members_.m_start.m_first) { + new((void*)(detail::get_pointer(this->members_.m_start.m_cur)- 1))value_type(t); + --this->members_.m_start.m_cur; + } + else + this->priv_push_front_aux(t); + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void push_front(const detail::moved_object &mt) + { + if (this->members_.m_start.m_cur != this->members_.m_start.m_first) { + new((void*)(detail::get_pointer(this->members_.m_start.m_cur)- 1))value_type(mt); + --this->members_.m_start.m_cur; + } + else + this->priv_push_front_aux(mt); + } + #else + void push_front(value_type &&mt) + { + if (this->members_.m_start.m_cur != this->members_.m_start.m_first) { + new((void*)(detail::get_pointer(this->members_.m_start.m_cur)- 1))value_type(detail::move_impl(mt)); + --this->members_.m_start.m_cur; + } + else + this->priv_push_front_aux(detail::move_impl(mt)); + } + #endif + + void pop_back() + { + if (this->members_.m_finish.m_cur != this->members_.m_finish.m_first) { + --this->members_.m_finish.m_cur; + detail::get_pointer(this->members_.m_finish.m_cur)->~value_type(); + } + else + this->priv_pop_back_aux(); + } + + void pop_front() + { + if (this->members_.m_start.m_cur != this->members_.m_start.m_last - 1) { + detail::get_pointer(this->members_.m_start.m_cur)->~value_type(); + ++this->members_.m_start.m_cur; + } + else + this->priv_pop_front_aux(); + } + + iterator insert(iterator position, const value_type& x) + { + if (position.m_cur == this->members_.m_start.m_cur) { + this->push_front(x); + return this->members_.m_start; + } + else if (position.m_cur == this->members_.m_finish.m_cur) { + this->push_back(x); + iterator tmp = this->members_.m_finish; + --tmp; + return tmp; + } + else { + return this->priv_insert_aux(position, x); + } + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(iterator position, const detail::moved_object &mx) + { + if (position.m_cur == this->members_.m_start.m_cur) { + this->push_front(mx); + return this->members_.m_start; + } + else if (position.m_cur == this->members_.m_finish.m_cur) { + this->push_back(mx); + iterator tmp = this->members_.m_finish; + --tmp; + return tmp; + } + else { + return this->priv_insert_aux(position, mx); + } + } + #else + iterator insert(iterator position, value_type &&mx) + { + if (position.m_cur == this->members_.m_start.m_cur) { + this->push_front(detail::move_impl(mx)); + return this->members_.m_start; + } + else if (position.m_cur == this->members_.m_finish.m_cur) { + this->push_back(detail::move_impl(mx)); + iterator tmp = this->members_.m_finish; + --tmp; + return tmp; + } + else { + return this->priv_insert_aux(position, detail::move_impl(mx)); + } + } + #endif + + void insert(iterator pos, size_type n, const value_type& x) + { this->priv_fill_insert(pos, n, x); } + + // Check whether it's an integral type. If so, it's not an iterator. + template + void insert(iterator pos, InpIt first, InpIt last) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = detail::is_convertible::value; + typedef detail::bool_ Result; + this->priv_insert_dispatch(pos, first, last, Result()); + } + + void resize(size_type new_size, const value_type& x) + { + const size_type len = size(); + if (new_size < len) + this->erase(this->members_.m_start + new_size, this->members_.m_finish); + else + this->insert(this->members_.m_finish, new_size - len, x); + } + + void resize(size_type new_size) + { + const size_type len = size(); + if (new_size < len) + this->erase(this->members_.m_start + new_size, this->members_.m_finish); + else{ + size_type n = new_size - this->size(); + this->priv_reserve_elements_at_back(new_size); + + while(n--){ + //T default_constructed = detail::move_impl(T()); + T default_constructed; +/* if(boost::is_scalar::value){ + //Value initialization + new(&default_constructed)T(); + }*/ + this->push_back(detail::move_impl(default_constructed)); + } + } + } + + iterator erase(iterator pos) + { + iterator next = pos; + ++next; + difference_type index = pos - this->members_.m_start; + if (size_type(index) < (this->size() >> 1)) { + std::copy_backward( detail::make_move_iterator(this->members_.m_start) + , detail::make_move_iterator(pos) + , next); + pop_front(); + } + else { + std::copy( detail::make_move_iterator(next) + , detail::make_move_iterator(this->members_.m_finish) + , pos); + pop_back(); + } + return this->members_.m_start + index; + } + + iterator erase(iterator first, iterator last) + { + if (first == this->members_.m_start && last == this->members_.m_finish) { + this->clear(); + return this->members_.m_finish; + } + else { + difference_type n = last - first; + difference_type elems_before = first - this->members_.m_start; + if (elems_before < static_cast(this->size() - n) - elems_before) { + std::copy_backward( detail::make_move_iterator(this->members_.m_start) + , detail::make_move_iterator(first) + , last); + iterator new_start = this->members_.m_start + n; + if(!Base::trivial_dctr_after_move) + this->priv_destroy_range(this->members_.m_start, new_start); + this->priv_destroy_nodes(new_start.m_node, this->members_.m_start.m_node); + this->members_.m_start = new_start; + } + else { + std::copy( detail::make_move_iterator(last) + , detail::make_move_iterator(this->members_.m_finish) + , first); + iterator new_finish = this->members_.m_finish - n; + if(!Base::trivial_dctr_after_move) + this->priv_destroy_range(new_finish, this->members_.m_finish); + this->priv_destroy_nodes(new_finish.m_node + 1, this->members_.m_finish.m_node + 1); + this->members_.m_finish = new_finish; + } + return this->members_.m_start + elems_before; + } + } + + void clear() + { + for (index_pointer node = this->members_.m_start.m_node + 1; + node < this->members_.m_finish.m_node; + ++node) { + this->priv_destroy_range(*node, *node + this->s_buffer_size()); + this->priv_deallocate_node(*node); + } + + if (this->members_.m_start.m_node != this->members_.m_finish.m_node) { + this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_start.m_last); + this->priv_destroy_range(this->members_.m_finish.m_first, this->members_.m_finish.m_cur); + this->priv_deallocate_node(this->members_.m_finish.m_first); + } + else + this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_finish.m_cur); + + this->members_.m_finish = this->members_.m_start; + } + + /// @cond + private: + + template + void insert(iterator pos, InpIt first, InpIt last, std::input_iterator_tag) + { std::copy(first, last, std::inserter(*this, pos)); } + + template + void insert(iterator pos, FwdIt first, FwdIt last, std::forward_iterator_tag) + { + + size_type n = 0; + n = std::distance(first, last); + + if (pos.m_cur == this->members_.m_start.m_cur) { + iterator new_start = this->priv_reserve_elements_at_front(n); + BOOST_TRY{ + std::uninitialized_copy(first, last, new_start); + this->members_.m_start = new_start; + } + BOOST_CATCH(...){ + this->priv_destroy_nodes(new_start.m_node, this->members_.m_start.m_node); + BOOST_RETHROW + } + BOOST_CATCH_END + } + else if (pos.m_cur == this->members_.m_finish.m_cur) { + iterator new_finish = this->priv_reserve_elements_at_back(n); + BOOST_TRY{ + std::uninitialized_copy(first, last, this->members_.m_finish); + this->members_.m_finish = new_finish; + } + BOOST_CATCH(...){ + this->priv_destroy_nodes(this->members_.m_finish.m_node + 1, new_finish.m_node + 1); + BOOST_RETHROW + } + BOOST_CATCH_END + } + else + this->priv_insert_aux(pos, first, last, n); + } + + // assign(), a generalized assignment member function. Two + // versions: one that takes a count, and one that takes a range. + // The range version is a member template, so we dispatch on whether + // or not the type is an integer. + void priv_fill_assign(size_type n, const T& val) { + if (n > size()) { + std::fill(begin(), end(), val); + this->insert(end(), n - size(), val); + } + else { + this->erase(begin() + n, end()); + std::fill(begin(), end(), val); + } + } + + template + void priv_initialize_dispatch(Integer n, Integer x, detail::true_) + { + this->priv_initialize_map(n); + this->priv_fill_initialize(x); + } + + template + void priv_initialize_dispatch(InpIt first, InpIt last, detail::false_) + { + typedef typename std::iterator_traits::iterator_category ItCat; + this->priv_range_initialize(first, last, ItCat()); + } + + void priv_destroy_range(iterator p, iterator p2) + { + for(;p != p2; ++p) + detail::get_pointer(&*p)->~value_type(); + } + + void priv_destroy_range(pointer p, pointer p2) + { + for(;p != p2; ++p) + detail::get_pointer(&*p)->~value_type(); + } + + template + void priv_assign_dispatch(Integer n, Integer val, detail::true_) + { this->priv_fill_assign((size_type) n, (T) val); } + + template + void priv_assign_dispatch(InpIt first, InpIt last, detail::false_) + { + typedef typename std::iterator_traits::iterator_category ItCat; + this->priv_assign_aux(first, last, ItCat()); + } + + template + void priv_assign_aux(InpIt first, InpIt last, std::input_iterator_tag) + { + iterator cur = begin(); + for ( ; first != last && cur != end(); ++cur, ++first) + *cur = *first; + if (first == last) + this->erase(cur, end()); + else + this->insert(end(), first, last); + } + + template + void priv_assign_aux(FwdIt first, FwdIt last, + std::forward_iterator_tag) { + size_type len = 0; + std::distance(first, last, len); + if (len > size()) { + FwdIt mid = first; + std::advance(mid, size()); + std::copy(first, mid, begin()); + this->insert(end(), mid, last); + } + else + this->erase(std::copy(first, last, begin()), end()); + } + + template + void priv_insert_dispatch(iterator pos, Integer n, Integer x, + detail::true_) + { + this->priv_fill_insert(pos, (size_type) n, (value_type) x); + } + + template + void priv_insert_dispatch(iterator pos, + InpIt first, InpIt last, + detail::false_) + { + typedef typename std::iterator_traits::iterator_category ItCat; + this->insert(pos, first, last, ItCat()); + } + + iterator priv_insert_aux(iterator pos, const value_type& x) + { + size_type n = pos - begin(); + this->priv_insert_aux(pos, size_type(1), x); + return iterator(this->begin() + n); + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator priv_insert_aux(iterator pos, const detail::moved_object &mx) + { + typedef repeat_iterator r_iterator; + typedef detail::move_iterator move_it; + //Just call more general insert(pos, size, value) and return iterator + size_type n = pos - begin(); + this->insert(pos + ,move_it(r_iterator(mx.get(), 1)) + ,move_it(r_iterator())); + return iterator(this->begin() + n); + } + #else + iterator priv_insert_aux(iterator pos, value_type &&mx) + { + typedef repeat_iterator r_iterator; + typedef detail::move_iterator move_it; + //Just call more general insert(pos, size, value) and return iterator + size_type n = pos - begin(); + this->insert(pos + ,move_it(r_iterator(mx, 1)) + ,move_it(r_iterator())); + return iterator(this->begin() + n); + } + #endif + + void priv_insert_aux(iterator pos, size_type n, const value_type& x) + { + typedef constant_iterator c_it; + this->insert(pos, c_it(x, n), c_it()); + } + + template + void priv_insert_aux(iterator pos, FwdIt first, FwdIt last, size_type n) + { + const difference_type elemsbefore = pos - this->members_.m_start; + size_type length = size(); + if (elemsbefore < static_cast(length / 2)) { + iterator new_start = this->priv_reserve_elements_at_front(n); + iterator old_start = this->members_.m_start; + pos = this->members_.m_start + elemsbefore; + BOOST_TRY { + if (elemsbefore >= difference_type(n)) { + iterator start_n = this->members_.m_start + difference_type(n); + std::uninitialized_copy(detail::make_move_iterator(this->members_.m_start), detail::make_move_iterator(start_n), new_start); + this->members_.m_start = new_start; + std::copy(detail::make_move_iterator(start_n), detail::make_move_iterator(pos), old_start); + std::copy(first, last, pos - difference_type(n)); + } + else { + FwdIt mid = first; + std::advance(mid, difference_type(n) - elemsbefore); + this->priv_uninitialized_copy_copy + (detail::make_move_iterator(this->members_.m_start), detail::make_move_iterator(pos), first, mid, new_start); + this->members_.m_start = new_start; + std::copy(mid, last, old_start); + } + } + BOOST_CATCH(...){ + this->priv_destroy_nodes(new_start.m_node, this->members_.m_start.m_node); + BOOST_RETHROW + } + BOOST_CATCH_END + } + else { + iterator new_finish = this->priv_reserve_elements_at_back(n); + iterator old_finish = this->members_.m_finish; + const difference_type elemsafter = + difference_type(length) - elemsbefore; + pos = this->members_.m_finish - elemsafter; + BOOST_TRY { + if (elemsafter > difference_type(n)) { + iterator finish_n = this->members_.m_finish - difference_type(n); + std::uninitialized_copy(detail::make_move_iterator(finish_n), detail::make_move_iterator(this->members_.m_finish), this->members_.m_finish); + this->members_.m_finish = new_finish; + std::copy_backward(detail::make_move_iterator(pos), detail::make_move_iterator(finish_n), old_finish); + std::copy(first, last, pos); + } + else { + FwdIt mid = first; + std::advance(mid, elemsafter); + this->priv_uninitialized_copy_copy(mid, last, detail::make_move_iterator(pos), detail::make_move_iterator(this->members_.m_finish), this->members_.m_finish); + this->members_.m_finish = new_finish; + std::copy(first, mid, pos); + } + } + BOOST_CATCH(...){ + this->priv_destroy_nodes(this->members_.m_finish.m_node + 1, new_finish.m_node + 1); + BOOST_RETHROW + } + BOOST_CATCH_END + } + } + + void priv_fill_insert(iterator pos, size_type n, const value_type& x) + { + typedef constant_iterator c_it; + this->insert(pos, c_it(x, n), c_it()); + } + + // Precondition: this->members_.m_start and this->members_.m_finish have already been initialized, + // but none of the deque's elements have yet been constructed. + void priv_fill_initialize(const value_type& value) + { + index_pointer cur; + BOOST_TRY { + for (cur = this->members_.m_start.m_node; cur < this->members_.m_finish.m_node; ++cur){ + std::uninitialized_fill(*cur, *cur + this->s_buffer_size(), value); + } + std::uninitialized_fill(this->members_.m_finish.m_first, this->members_.m_finish.m_cur, value); + } + BOOST_CATCH(...){ + this->priv_destroy_range(this->members_.m_start, iterator(*cur, cur)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + template + void priv_range_initialize(InpIt first, InpIt last, std::input_iterator_tag) + { + this->priv_initialize_map(0); + BOOST_TRY { + for ( ; first != last; ++first) + this->push_back(*first); + } + BOOST_CATCH(...){ + this->clear(); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + template + void priv_range_initialize(FwdIt first, FwdIt last, std::forward_iterator_tag) + { + size_type n = 0; + n = std::distance(first, last); + this->priv_initialize_map(n); + + index_pointer cur_node; + BOOST_TRY { + for (cur_node = this->members_.m_start.m_node; + cur_node < this->members_.m_finish.m_node; + ++cur_node) { + FwdIt mid = first; + std::advance(mid, this->s_buffer_size()); + std::uninitialized_copy(first, mid, *cur_node); + first = mid; + } + std::uninitialized_copy(first, last, this->members_.m_finish.m_first); + } + BOOST_CATCH(...){ + this->priv_destroy_range(this->members_.m_start, iterator(*cur_node, cur_node)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_last - 1. + void priv_push_back_aux(const value_type& t = value_type()) + { + this->priv_reserve_map_at_back(); + *(this->members_.m_finish.m_node + 1) = this->priv_allocate_node(); + BOOST_TRY { + new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(t); + this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node + 1); + this->members_.m_finish.m_cur = this->members_.m_finish.m_first; + } + BOOST_CATCH(...){ + this->priv_deallocate_node(*(this->members_.m_finish.m_node + 1)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_last - 1. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void priv_push_back_aux(const detail::moved_object &mt) + { + this->priv_reserve_map_at_back(); + *(this->members_.m_finish.m_node + 1) = this->priv_allocate_node(); + BOOST_TRY { + new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(mt); + this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node + 1); + this->members_.m_finish.m_cur = this->members_.m_finish.m_first; + } + BOOST_CATCH(...){ + this->priv_deallocate_node(*(this->members_.m_finish.m_node + 1)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + #else + void priv_push_back_aux(value_type &&mt) + { + this->priv_reserve_map_at_back(); + *(this->members_.m_finish.m_node + 1) = this->priv_allocate_node(); + BOOST_TRY { + new((void*)detail::get_pointer(this->members_.m_finish.m_cur))value_type(detail::move_impl(mt)); + this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node + 1); + this->members_.m_finish.m_cur = this->members_.m_finish.m_first; + } + BOOST_CATCH(...){ + this->priv_deallocate_node(*(this->members_.m_finish.m_node + 1)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + #endif + + // Called only if this->members_.m_start.m_cur == this->members_.m_start.m_first. + void priv_push_front_aux(const value_type& t) + { + this->priv_reserve_map_at_front(); + *(this->members_.m_start.m_node - 1) = this->priv_allocate_node(); + BOOST_TRY { + this->members_.m_start.priv_set_node(this->members_.m_start.m_node - 1); + this->members_.m_start.m_cur = this->members_.m_start.m_last - 1; + new((void*)detail::get_pointer(this->members_.m_start.m_cur))value_type(t); + } + BOOST_CATCH(...){ + ++this->members_.m_start; + this->priv_deallocate_node(*(this->members_.m_start.m_node - 1)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void priv_push_front_aux(const detail::moved_object &mt) + { + this->priv_reserve_map_at_front(); + *(this->members_.m_start.m_node - 1) = this->priv_allocate_node(); + BOOST_TRY { + this->members_.m_start.priv_set_node(this->members_.m_start.m_node - 1); + this->members_.m_start.m_cur = this->members_.m_start.m_last - 1; + new((void*)detail::get_pointer(this->members_.m_start.m_cur))value_type(mt); + } + BOOST_CATCH(...){ + ++this->members_.m_start; + this->priv_deallocate_node(*(this->members_.m_start.m_node - 1)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + #else + void priv_push_front_aux(value_type &&mt) + { + this->priv_reserve_map_at_front(); + *(this->members_.m_start.m_node - 1) = this->priv_allocate_node(); + BOOST_TRY { + this->members_.m_start.priv_set_node(this->members_.m_start.m_node - 1); + this->members_.m_start.m_cur = this->members_.m_start.m_last - 1; + new((void*)detail::get_pointer(this->members_.m_start.m_cur))value_type(detail::move_impl(mt)); + } + BOOST_CATCH(...){ + ++this->members_.m_start; + this->priv_deallocate_node(*(this->members_.m_start.m_node - 1)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + #endif + + // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_first. + void priv_pop_back_aux() + { + this->priv_deallocate_node(this->members_.m_finish.m_first); + this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1); + this->members_.m_finish.m_cur = this->members_.m_finish.m_last - 1; + detail::get_pointer(this->members_.m_finish.m_cur)->~value_type(); + } + + // Called only if this->members_.m_start.m_cur == this->members_.m_start.m_last - 1. Note that + // if the deque has at least one element (a precondition for this member + // function), and if this->members_.m_start.m_cur == this->members_.m_start.m_last, then the deque + // must have at least two nodes. + void priv_pop_front_aux() + { + detail::get_pointer(this->members_.m_start.m_cur)->~value_type(); + this->priv_deallocate_node(this->members_.m_start.m_first); + this->members_.m_start.priv_set_node(this->members_.m_start.m_node + 1); + this->members_.m_start.m_cur = this->members_.m_start.m_first; + } + + iterator priv_reserve_elements_at_front(size_type n) + { + size_type vacancies = this->members_.m_start.m_cur - this->members_.m_start.m_first; + if (n > vacancies) + this->priv_new_elements_at_front(n - vacancies); + return this->members_.m_start - difference_type(n); + } + + iterator priv_reserve_elements_at_back(size_type n) + { + size_type vacancies = (this->members_.m_finish.m_last - this->members_.m_finish.m_cur) - 1; + if (n > vacancies) + this->priv_new_elements_at_back(n - vacancies); + return this->members_.m_finish + difference_type(n); + } + + void priv_new_elements_at_front(size_type new_elems) + { + size_type new_nodes = (new_elems + this->s_buffer_size() - 1) / + this->s_buffer_size(); + this->priv_reserve_map_at_front(new_nodes); + size_type i = 1; + BOOST_TRY { + for (; i <= new_nodes; ++i) + *(this->members_.m_start.m_node - i) = this->priv_allocate_node(); + } + BOOST_CATCH(...) { + for (size_type j = 1; j < i; ++j) + this->priv_deallocate_node(*(this->members_.m_start.m_node - j)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + void priv_new_elements_at_back(size_type new_elems) + { + size_type new_nodes = (new_elems + this->s_buffer_size() - 1) + / this->s_buffer_size(); + this->priv_reserve_map_at_back(new_nodes); + size_type i; + BOOST_TRY { + for (i = 1; i <= new_nodes; ++i) + *(this->members_.m_finish.m_node + i) = this->priv_allocate_node(); + } + BOOST_CATCH(...) { + for (size_type j = 1; j < i; ++j) + this->priv_deallocate_node(*(this->members_.m_finish.m_node + j)); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + // Makes sure the this->members_.m_map has space for new nodes. Does not actually + // add the nodes. Can invalidate this->members_.m_map pointers. (And consequently, + // deque iterators.) + void priv_reserve_map_at_back (size_type nodes_to_add = 1) + { + if (nodes_to_add + 1 > this->members_.m_map_size - (this->members_.m_finish.m_node - this->members_.m_map)) + this->priv_reallocate_map(nodes_to_add, false); + } + + void priv_reserve_map_at_front (size_type nodes_to_add = 1) + { + if (nodes_to_add > size_type(this->members_.m_start.m_node - this->members_.m_map)) + this->priv_reallocate_map(nodes_to_add, true); + } + + void priv_reallocate_map(size_type nodes_to_add, bool add_at_front) + { + size_type old_num_nodes = this->members_.m_finish.m_node - this->members_.m_start.m_node + 1; + size_type new_num_nodes = old_num_nodes + nodes_to_add; + + index_pointer new_nstart; + if (this->members_.m_map_size > 2 * new_num_nodes) { + new_nstart = this->members_.m_map + (this->members_.m_map_size - new_num_nodes) / 2 + + (add_at_front ? nodes_to_add : 0); + if (new_nstart < this->members_.m_start.m_node) + std::copy(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart); + else + std::copy_backward(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, + new_nstart + old_num_nodes); + } + else { + size_type new_map_size = + this->members_.m_map_size + max_value(this->members_.m_map_size, nodes_to_add) + 2; + + index_pointer new_map = this->priv_allocate_map(new_map_size); + new_nstart = new_map + (new_map_size - new_num_nodes) / 2 + + (add_at_front ? nodes_to_add : 0); + std::copy(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart); + this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); + + this->members_.m_map = new_map; + this->members_.m_map_size = new_map_size; + } + + this->members_.m_start.priv_set_node(new_nstart); + this->members_.m_finish.priv_set_node(new_nstart + old_num_nodes - 1); + } + + // this->priv_uninitialized_copy_fill + // Copies [first1, last1) into [first2, first2 + (last1 - first1)), and + // fills [first2 + (last1 - first1), last2) with x. + void priv_uninitialized_copy_fill(iterator first1, iterator last1, + iterator first2, iterator last2, + const T& x) + { + iterator mid2 = std::uninitialized_copy(first1, last1, first2); + BOOST_TRY { + std::uninitialized_fill(mid2, last2, x); + } + BOOST_CATCH(...){ + for(;first2 != mid2; ++first2){ + detail::get_pointer(&*first2)->~value_type(); + } + BOOST_RETHROW + } + BOOST_CATCH_END + } + + // this->priv_uninitialized_fill_copy + // Fills [result, mid) with x, and copies [first, last) into + // [mid, mid + (last - first)). + iterator priv_uninitialized_fill_copy(iterator result, iterator mid, + const T& x, + iterator first, iterator last) + { + std::uninitialized_fill(result, mid, x); + BOOST_TRY { + return std::uninitialized_copy(first, last, mid); + } + BOOST_CATCH(...){ + for(;result != mid; ++result){ + detail::get_pointer(&*result)->~value_type(); + } + BOOST_RETHROW + } + BOOST_CATCH_END + } + + // this->priv_uninitialized_copy_copy + // Copies [first1, last1) into [result, result + (last1 - first1)), and + // copies [first2, last2) into + // [result, result + (last1 - first1) + (last2 - first2)). + template + FwdIt priv_uninitialized_copy_copy(InpIt1 first1, InpIt1 last1, + InpIt2 first2, InpIt2 last2, + FwdIt result) + { + FwdIt mid = std::uninitialized_copy(first1, last1, result); + BOOST_TRY { + return std::uninitialized_copy(first2, last2, mid); + } + BOOST_CATCH(...){ + for(;result != mid; ++result){ + detail::get_pointer(&*result)->~value_type(); + } + BOOST_RETHROW + } + BOOST_CATCH_END + } + /// @endcond +}; + +// Nonmember functions. +template +inline bool operator==(const deque& x, + const deque& y) +{ + return x.size() == y.size() && equal(x.begin(), x.end(), y.begin()); +} + +template +inline bool operator<(const deque& x, + const deque& y) +{ + return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); +} + +template +inline bool operator!=(const deque& x, + const deque& y) + { return !(x == y); } + +template +inline bool operator>(const deque& x, + const deque& y) + { return y < x; } + +template +inline bool operator<=(const deque& x, + const deque& y) + { return !(y < x); } + +template +inline bool operator>=(const deque& x, + const deque& y) + { return !(x < y); } + +template +inline void swap(deque& x, deque& y) + { x.swap(y); } + +/// @cond + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = has_trivial_destructor::value }; +}; +/// @endcond + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_DEQUE_HPP + diff --git a/win32/include/boost/interprocess/containers/detail/flat_tree.hpp b/win32/include/boost/interprocess/containers/detail/flat_tree.hpp new file mode 100755 index 000000000..eb5b6c094 --- /dev/null +++ b/win32/include/boost/interprocess/containers/detail/flat_tree.hpp @@ -0,0 +1,743 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +//////////////////////////////////////////////////////////////////////////////// +// The Loki Library +// Copyright (c) 2001 by Andrei Alexandrescu +// This code accompanies the book: +// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design +// Patterns Applied". Copyright (c) 2001. Addison-Wesley. +// Permission to use, copy, modify, distribute and sell this software for any +// purpose is hereby granted without fee, provided that the above copyright +// notice appear in all copies and that both that copyright notice and this +// permission notice appear in supporting documentation. +// The author or Addison-Welsey Longman make no representations about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. +/////////////////////////////////////////////////////////////////////////////// +// +// Parts of this file come from AssocVector.h file from Loki library +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_FLAT_TREE_HPP +#define BOOST_INTERPROCESS_FLAT_TREE_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + +namespace interprocess { + +namespace detail { + +template +class flat_tree +{ + typedef boost::interprocess::vector vector_t; + typedef Alloc allocator_t; + + public: + class value_compare + : private Compare + { + typedef Value first_argument_type; + typedef Value second_argument_type; + typedef bool return_type; + public: + value_compare(const Compare &pred) + : Compare(pred) + {} + + bool operator()(const Value& lhs, const Value& rhs) const + { + KeyOfValue key_extract; + return Compare::operator()(key_extract(lhs), key_extract(rhs)); + } + + const Compare &get_comp() const + { return *this; } + + Compare &get_comp() + { return *this; } + }; + + private: + struct Data + //Inherit from value_compare to do EBO + : public value_compare + { + public: + Data(const Compare &comp, + const vector_t &vect) + : value_compare(comp), m_vect(vect){} + + Data(const value_compare &comp, + const vector_t &vect) + : value_compare(comp), m_vect(vect){} + + Data(const Compare &comp, + const allocator_t &alloc) + : value_compare(comp), m_vect(alloc){} + public: + vector_t m_vect; + }; + + Data m_data; + + public: + + typedef typename vector_t::value_type value_type; + typedef typename vector_t::pointer pointer; + typedef typename vector_t::const_pointer const_pointer; + typedef typename vector_t::reference reference; + typedef typename vector_t::const_reference const_reference; + typedef Key key_type; + typedef Compare key_compare; + typedef typename vector_t::allocator_type allocator_type; + typedef allocator_type stored_allocator_type; + typedef typename allocator_type::size_type size_type; + typedef typename allocator_type::difference_type difference_type; + typedef typename vector_t::iterator iterator; + typedef typename vector_t::const_iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + + // allocation/deallocation + flat_tree(const Compare& comp = Compare(), + const allocator_type& a = allocator_type()) + : m_data(comp, a) + { } + + flat_tree(const flat_tree& x) + : m_data(x.m_data, x.m_data.m_vect) + { } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + flat_tree(const detail::moved_object &x) + : m_data(detail::move_impl(x.get().m_data)) + { } + #else + flat_tree(flat_tree &&x) + : m_data(detail::move_impl(x.m_data)) + { } + #endif + + ~flat_tree() + { } + + flat_tree& operator=(const flat_tree& x) + { m_data = x.m_data; return *this; } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + flat_tree& operator=(const detail::moved_object& mx) + { m_data = detail::move_impl(mx.get().m_data); return *this; } + #else + flat_tree& operator=(flat_tree &&mx) + { m_data = detail::move_impl(mx.m_data); return *this; } + #endif + + public: + // accessors: + Compare key_comp() const + { return this->m_data.get_comp(); } + + allocator_type get_allocator() const + { return this->m_data.m_vect.get_allocator(); } + + const stored_allocator_type &get_stored_allocator() const + { return this->m_data.m_vect.get_stored_allocator(); } + + stored_allocator_type &get_stored_allocator() + { return this->m_data.m_vect.get_stored_allocator(); } + + iterator begin() + { return this->m_data.m_vect.begin(); } + + const_iterator begin() const + { return this->m_data.m_vect.begin(); } + + iterator end() + { return this->m_data.m_vect.end(); } + + const_iterator end() const + { return this->m_data.m_vect.end(); } + + reverse_iterator rbegin() + { return reverse_iterator(this->end()); } + + const_reverse_iterator rbegin() const + { return const_reverse_iterator(this->end()); } + + reverse_iterator rend() + { return reverse_iterator(this->begin()); } + + const_reverse_iterator rend() const + { return const_reverse_iterator(this->begin()); } + + bool empty() const + { return this->m_data.m_vect.empty(); } + + size_type size() const + { return this->m_data.m_vect.size(); } + + size_type max_size() const + { return this->m_data.m_vect.max_size(); } + + void swap(flat_tree& other) + { + value_compare& mycomp = this->m_data; + value_compare& othercomp = other.m_data; + detail::do_swap(mycomp, othercomp); + vector_t & myvect = this->m_data.m_vect; + vector_t & othervect = other.m_data.m_vect; + myvect.swap(othervect); + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(const detail::moved_object& other) + { this->swap(other.get()); } + #else + void swap(flat_tree &&other) + { this->swap(other); } + #endif + + public: + // insert/erase + std::pair insert_unique(const value_type& val) + { + insert_commit_data data; + std::pair ret = priv_insert_unique_prepare(val, data); + if(ret.second){ + ret.first = priv_insert_commit(data, val); + } + return ret; + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + std::pair insert_unique(const detail::moved_object& mval) + { + insert_commit_data data; + std::pair ret = priv_insert_unique_prepare(mval.get(), data); + if(ret.second){ + ret.first = priv_insert_commit(data, mval); + } + return ret; + } + #else + std::pair insert_unique(value_type && mval) + { + insert_commit_data data; + std::pair ret = priv_insert_unique_prepare(mval, data); + if(ret.second){ + ret.first = priv_insert_commit(data, detail::move_impl(mval)); + } + return ret; + } + #endif + + + iterator insert_equal(const value_type& val) + { + iterator i = this->upper_bound(KeyOfValue()(val)); + i = this->m_data.m_vect.insert(i, val); + return i; + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert_equal(const detail::moved_object& mval) + { + iterator i = this->upper_bound(KeyOfValue()(mval.get())); + i = this->m_data.m_vect.insert(i, mval); + return i; + } + #else + iterator insert_equal(value_type && mval) + { + iterator i = this->upper_bound(KeyOfValue()(mval)); + i = this->m_data.m_vect.insert(i, detail::move_impl(mval)); + return i; + } + #endif + + iterator insert_unique(const_iterator pos, const value_type& val) + { + insert_commit_data data; + std::pair ret = priv_insert_unique_prepare(pos, val, data); + if(ret.second){ + ret.first = priv_insert_commit(data, val); + } + return ret.first; + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert_unique(const_iterator pos, const detail::moved_object& mval) + { + insert_commit_data data; + std::pair ret = priv_insert_unique_prepare(pos, mval.get(), data); + if(ret.second){ + ret.first = priv_insert_commit(data, mval); + } + return ret.first; + } + #else + iterator insert_unique(const_iterator pos, value_type&&mval) + { + insert_commit_data data; + std::pair ret = priv_insert_unique_prepare(pos, mval, data); + if(ret.second){ + ret.first = priv_insert_commit(data, detail::move_impl(mval)); + } + return ret.first; + } + #endif + + iterator insert_equal(const_iterator pos, const value_type& val) + { + insert_commit_data data; + priv_insert_equal_prepare(pos, val, data); + return priv_insert_commit(data, val); + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert_equal(const_iterator pos, const detail::moved_object& mval) + { + insert_commit_data data; + priv_insert_equal_prepare(pos, mval.get(), data); + return priv_insert_commit(data, mval); + } + #else + iterator insert_equal(const_iterator pos, value_type && mval) + { + insert_commit_data data; + priv_insert_equal_prepare(pos, mval, data); + return priv_insert_commit(data, detail::move_impl(mval)); + } + #endif + + template + void insert_unique(InIt first, InIt last) + { + for ( ; first != last; ++first) + this->insert_unique(*first); + } + + template + void insert_equal(InIt first, InIt last) + { + typedef typename + std::iterator_traits::iterator_category ItCat; + priv_insert_equal(first, last, ItCat()); + } + + iterator erase(const_iterator position) + { return this->m_data.m_vect.erase(position); } + + size_type erase(const key_type& k) + { + std::pair itp = this->equal_range(k); + size_type ret = static_cast(itp.second-itp.first); + if (ret){ + this->m_data.m_vect.erase(itp.first, itp.second); + } + return ret; + } + + iterator erase(const_iterator first, const_iterator last) + { return this->m_data.m_vect.erase(first, last); } + + void clear() + { this->m_data.m_vect.clear(); } + + //! Effects: Tries to deallocate the excess of memory created + // with previous allocations. The size of the vector is unchanged + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to size(). + void shrink_to_fit() + { this->m_data.m_vect.shrink_to_fit(); } + + // set operations: + iterator find(const key_type& k) + { + const Compare &key_comp = this->m_data.get_comp(); + iterator i = this->lower_bound(k); + + if (i != this->end() && key_comp(k, KeyOfValue()(*i))){ + i = this->end(); + } + return i; + } + + const_iterator find(const key_type& k) const + { + const Compare &key_comp = this->m_data.get_comp(); + const_iterator i = this->lower_bound(k); + + if (i != this->end() && key_comp(k, KeyOfValue()(*i))){ + i = this->end(); + } + return i; + } + + size_type count(const key_type& k) const + { + std::pair p = this->equal_range(k); + size_type n = p.second - p.first; + return n; + } + + iterator lower_bound(const key_type& k) + { return this->priv_lower_bound(this->begin(), this->end(), k); } + + const_iterator lower_bound(const key_type& k) const + { return this->priv_lower_bound(this->begin(), this->end(), k); } + + iterator upper_bound(const key_type& k) + { return this->priv_upper_bound(this->begin(), this->end(), k); } + + const_iterator upper_bound(const key_type& k) const + { return this->priv_upper_bound(this->begin(), this->end(), k); } + + std::pair equal_range(const key_type& k) + { return this->priv_equal_range(this->begin(), this->end(), k); } + + std::pair equal_range(const key_type& k) const + { return this->priv_equal_range(this->begin(), this->end(), k); } + + size_type capacity() const + { return this->m_data.m_vect.capacity(); } + + void reserve(size_type count) + { this->m_data.m_vect.reserve(count); } + + private: + struct insert_commit_data + { + iterator position; + }; + + // insert/erase + void priv_insert_equal_prepare + (const_iterator p, const value_type& val, insert_commit_data &data) + { + iterator &pos = (iterator &)(const_iterator &)p; + // N1780 + // To insert val at pos: + // if pos == end || val <= *pos + // if pos == begin || val >= *(pos-1) + // insert val before pos + // else + // insert val before upper_bound(val) + // else if pos+1 == end || val <= *(pos+1) + // insert val after pos + // else + // insert val before lower_bound(val) + const value_compare &value_comp = this->m_data; + + if(pos == this->end() || !value_comp(*pos, val)){ + if (pos == this->begin() || !value_comp(val, pos[-1])){ + data.position = pos; + } + else{ + data.position = + this->priv_upper_bound(this->begin(), pos, KeyOfValue()(val)); + } + } + //Works, but increases code complexity + //else if (++pos == this->end() || !value_comp(*pos, val)){ + // return this->m_data.m_vect.insert(pos, val); + //} + else{ + data.position = + this->priv_lower_bound(pos, this->end(), KeyOfValue()(val)); + } + } + + std::pair priv_insert_unique_prepare + (iterator beg, iterator end, const value_type& val, insert_commit_data &commit_data) + { + const value_compare &value_comp = this->m_data; + commit_data.position = this->priv_lower_bound(beg, end, KeyOfValue()(val)); + return std::pair + ( commit_data.position + , commit_data.position == end || value_comp(val, *commit_data.position)); + } + + std::pair priv_insert_unique_prepare + (const value_type& val, insert_commit_data &commit_data) + { return priv_insert_unique_prepare(this->begin(), this->end(), val, commit_data); } + + std::pair priv_insert_unique_prepare + (const_iterator p, const value_type& val, insert_commit_data &commit_data) + { + iterator &pos = (iterator &)(const_iterator &)p; + //N1780. Props to Howard Hinnant! + //To insert val at pos: + //if pos == end || val <= *pos + // if pos == begin || val >= *(pos-1) + // insert val before pos + // else + // insert val before upper_bound(val) + //else if pos+1 == end || val <= *(pos+1) + // insert val after pos + //else + // insert val before lower_bound(val) + const value_compare &value_comp = this->m_data; + + if(pos == this->end() || value_comp(val, *pos)){ + if(pos != this->begin() && !value_comp(val, pos[-1])){ + if(value_comp(pos[-1], val)){ + commit_data.position = iterator(pos); + return std::pair(pos, true); + } + else{ + return std::pair(pos, false); + } + } + return this->priv_insert_unique_prepare(this->begin(), pos, val, commit_data); + } + + // Works, but increases code complexity + //Next check + //else if (value_comp(*pos, val) && !value_comp(pos[1], val)){ + // if(value_comp(val, pos[1])){ + // commit_data.position = pos+1; + // return std::pair(pos+1, true); + // } + // else{ + // return std::pair(pos+1, false); + // } + //} + else{ + //[... pos ... val ... ] + //The hint is before the insertion position, so insert it + //in the remaining range + return this->priv_insert_unique_prepare(pos, this->end(), val, commit_data); + } + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + iterator priv_insert_commit + (insert_commit_data &commit_data, const Convertible &convertible) + { return this->m_data.m_vect.insert(commit_data.position, convertible); } + #else + template + iterator priv_insert_commit + (insert_commit_data &commit_data, Convertible &&convertible) + { return this->m_data.m_vect.insert(commit_data.position, detail::forward_impl(convertible)); } + #endif + + template + RanIt priv_lower_bound(RanIt first, RanIt last, + const key_type & key) const + { + const Compare &key_comp = this->m_data.get_comp(); + KeyOfValue key_extract; + difference_type len = last - first, half; + RanIt middle; + + while (len > 0) { + half = len >> 1; + middle = first; + middle += half; + + if (key_comp(key_extract(*middle), key)) { + ++middle; + first = middle; + len = len - half - 1; + } + else + len = half; + } + return first; + } + + template + RanIt priv_upper_bound(RanIt first, RanIt last, + const key_type & key) const + { + const Compare &key_comp = this->m_data.get_comp(); + KeyOfValue key_extract; + difference_type len = last - first, half; + RanIt middle; + + while (len > 0) { + half = len >> 1; + middle = first; + middle += half; + + if (key_comp(key, key_extract(*middle))) { + len = half; + } + else{ + first = ++middle; + len = len - half - 1; + } + } + return first; + } + + template + std::pair + priv_equal_range(RanIt first, RanIt last, const key_type& key) const + { + const Compare &key_comp = this->m_data.get_comp(); + KeyOfValue key_extract; + difference_type len = last - first, half; + RanIt middle, left, right; + + while (len > 0) { + half = len >> 1; + middle = first; + middle += half; + + if (key_comp(key_extract(*middle), key)){ + first = middle; + ++first; + len = len - half - 1; + } + else if (key_comp(key, key_extract(*middle))){ + len = half; + } + else { + left = this->priv_lower_bound(first, middle, key); + first += len; + right = this->priv_upper_bound(++middle, first, key); + return std::pair(left, right); + } + } + return std::pair(first, first); + } + + template + void priv_insert_equal(FwdIt first, FwdIt last, std::forward_iterator_tag) + { + size_type len = static_cast(std::distance(first, last)); + this->reserve(this->size()+len); + this->priv_insert_equal(first, last, std::input_iterator_tag()); + } + + template + void priv_insert_equal(InIt first, InIt last, std::input_iterator_tag) + { + for ( ; first != last; ++first) + this->insert_equal(*first); + } + +/* + template + void priv_insert_unique(FwdIt first, FwdIt last, std::forward_iterator_tag) + { + size_type len = static_cast(std::distance(first, last)); + this->reserve(this->size()+len); + priv_insert_unique(first, last, std::input_iterator_tag()); + } + + template + void priv_insert_unique(InIt first, InIt last, std::input_iterator_tag) + { + for ( ; first != last; ++first) + this->insert_unique(*first); + } +*/ +}; + +template +inline bool +operator==(const flat_tree& x, + const flat_tree& y) +{ + return x.size() == y.size() && + std::equal(x.begin(), x.end(), y.begin()); +} + +template +inline bool +operator<(const flat_tree& x, + const flat_tree& y) +{ + return std::lexicographical_compare(x.begin(), x.end(), + y.begin(), y.end()); +} + +template +inline bool +operator!=(const flat_tree& x, + const flat_tree& y) + { return !(x == y); } + +template +inline bool +operator>(const flat_tree& x, + const flat_tree& y) + { return y < x; } + +template +inline bool +operator<=(const flat_tree& x, + const flat_tree& y) + { return !(y < x); } + +template +inline bool +operator>=(const flat_tree& x, + const flat_tree& y) + { return !(x < y); } + + +template +inline void +swap(flat_tree& x, + flat_tree& y) + { x.swap(y); } + +} //namespace detail { + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = + has_trivial_destructor::value && + has_trivial_destructor::value }; +}; + +} //namespace interprocess { + +} //namespace boost { + +#include + +#endif // BOOST_INTERPROCESS_FLAT_TREE_HPP diff --git a/win32/include/boost/interprocess/containers/detail/node_alloc_holder.hpp b/win32/include/boost/interprocess/containers/detail/node_alloc_holder.hpp new file mode 100755 index 000000000..cb00fd5ea --- /dev/null +++ b/win32/include/boost/interprocess/containers/detail/node_alloc_holder.hpp @@ -0,0 +1,401 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_NODE_ALLOC_HPP_ +#define BOOST_INTERPROCESS_DETAIL_NODE_ALLOC_HPP_ + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +namespace boost { +namespace interprocess { +namespace detail { + +template +struct node_compare + : private ValueCompare +{ + typedef typename ValueCompare::key_type key_type; + typedef typename ValueCompare::value_type value_type; + typedef typename ValueCompare::key_of_value key_of_value; + + node_compare(const ValueCompare &pred) + : ValueCompare(pred) + {} + + ValueCompare &value_comp() + { return static_cast(*this); } + + ValueCompare &value_comp() const + { return static_cast(*this); } + + bool operator()(const Node &a, const Node &b) const + { return ValueCompare::operator()(a.m_data, b.m_data); } +}; + +template +struct node_alloc_holder +{ + typedef node_alloc_holder self_t; + typedef typename A::value_type value_type; + typedef typename ICont::value_type Node; + typedef typename A::template rebind::other NodeAlloc; + typedef A ValAlloc; + typedef typename NodeAlloc::pointer NodePtr; + typedef detail::scoped_deallocator Deallocator; + typedef typename NodeAlloc::size_type size_type; + typedef typename NodeAlloc::difference_type difference_type; + typedef detail::integral_constant allocator_v1; + typedef detail::integral_constant allocator_v2; + typedef detail::integral_constant::value> alloc_version; + typedef typename ICont::iterator icont_iterator; + typedef typename ICont::const_iterator icont_citerator; + typedef allocator_destroyer Destroyer; + + node_alloc_holder(const ValAlloc &a) + : members_(a) + {} + + node_alloc_holder(const node_alloc_holder &other) + : members_(other.node_alloc()) + {} + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + node_alloc_holder(const detail::moved_object &other) + : members_(detail::move_impl(other.get().node_alloc())) + { this->swap(other.get()); } + #else + node_alloc_holder(node_alloc_holder &&other) + : members_(detail::move_impl(other.node_alloc())) + { this->swap(other); } + #endif + + template + node_alloc_holder(const ValAlloc &a, const Pred &c) + : members_(a, typename ICont::value_compare(c)) + {} + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + node_alloc_holder(const detail::moved_object &a, const Pred &c) + : members_(a.get(), typename ICont::value_compare(c)) + {} + #else + template + node_alloc_holder(ValAlloc &&a, const Pred &c) + : members_(a, typename ICont::value_compare(c)) + {} + #endif + + template + node_alloc_holder(const node_alloc_holder &other, const Pred &c) + : members_(other.node_alloc(), typename ICont::value_compare(c)) + {} + + ~node_alloc_holder() + {} + + size_type max_size() const + { return this->node_alloc().max_size(); } + + NodePtr allocate_one() + { return this->allocate_one(alloc_version()); } + + NodePtr allocate_one(allocator_v1) + { return this->node_alloc().allocate(1); } + + NodePtr allocate_one(allocator_v2) + { return this->node_alloc().allocate_one(); } + + void deallocate_one(NodePtr p) + { return this->deallocate_one(p, alloc_version()); } + + void deallocate_one(NodePtr p, allocator_v1) + { this->node_alloc().deallocate(p, 1); } + + void deallocate_one(NodePtr p, allocator_v2) + { this->node_alloc().deallocate_one(p); } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + static void construct(const NodePtr &ptr, const Convertible &value) + { new((void*)detail::get_pointer(ptr)) Node(value); } + #else + template + static void construct(const NodePtr &ptr, Convertible &&value) + { new((void*)detail::get_pointer(ptr)) Node(detail::forward_impl(value)); } + #endif + + static void construct(const NodePtr &ptr) + { new((void*)detail::get_pointer(ptr)) Node(); } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + static void construct(const NodePtr &ptr, + const detail::moved_object > &value) + { + typedef typename Node::hook_type hook_type; + typedef typename Node::value_type::first_type first_type; + typedef typename Node::value_type::second_type second_type; + Node *nodeptr = detail::get_pointer(ptr); + + //Hook constructor does not throw + new(static_cast(nodeptr))hook_type(); + //Now construct pair members_holder + value_type *valueptr = &nodeptr->m_data; + new((void*)&valueptr->first) first_type(detail::move_impl(value.get().first)); + BOOST_TRY{ + new((void*)&valueptr->second) second_type(detail::move_impl(value.get().second)); + } + BOOST_CATCH(...){ + valueptr->first.~first_type(); + static_cast(nodeptr)->~hook_type(); + BOOST_RETHROW + } + BOOST_CATCH_END + } + #else + template + static void construct(const NodePtr &ptr, + std::pair &&value) + { + typedef typename Node::hook_type hook_type; + typedef typename Node::value_type::first_type first_type; + typedef typename Node::value_type::second_type second_type; + Node *nodeptr = detail::get_pointer(ptr); + + //Hook constructor does not throw + new(static_cast(nodeptr))hook_type(); + //Now construct pair members_holder + value_type *valueptr = &nodeptr->m_data; + new((void*)&valueptr->first) first_type(detail::move_impl(value.first)); + BOOST_TRY{ + new((void*)&valueptr->second) second_type(detail::move_impl(value.second)); + } + BOOST_CATCH(...){ + valueptr->first.~first_type(); + static_cast(nodeptr)->~hook_type(); + BOOST_RETHROW + } + BOOST_CATCH_END + } + #endif + + static void destroy(const NodePtr &ptr) + { detail::get_pointer(ptr)->~Node(); } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + NodePtr create_node(const Convertible& x) + { + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + self_t::construct(p, x); + node_deallocator.release(); + return (p); + } + #else + template + NodePtr create_node(Convertible &&x) + { + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + self_t::construct(p, detail::forward_impl(x)); + node_deallocator.release(); + return (p); + } + #endif + + template + NodePtr create_node_from_it(It it) + { + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + ::boost::interprocess::construct_in_place(detail::get_pointer(p), it); + node_deallocator.release(); + return (p); + } + + NodePtr create_node() + { + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + self_t::construct(p); + node_deallocator.release(); + return (p); + } + + void destroy_node(NodePtr node) + { + self_t::destroy(node); + this->deallocate_one(node); + } + + void swap(node_alloc_holder &x) + { + NodeAlloc& this_alloc = this->node_alloc(); + NodeAlloc& other_alloc = x.node_alloc(); + + if (this_alloc != other_alloc){ + detail::do_swap(this_alloc, other_alloc); + } + + this->icont().swap(x.icont()); + } + + template + FwdIterator allocate_many_and_construct + (FwdIterator beg, difference_type n, Inserter inserter) + { + typedef typename NodeAlloc::multiallocation_iterator multiallocation_iterator; + + //Try to allocate memory in a single block + multiallocation_iterator itbeg = + this->node_alloc().allocate_individual(n), itend, itold; + int constructed = 0; + Node *p = 0; + BOOST_TRY{ + for(difference_type i = 0; i < n; ++i, ++beg, --constructed){ + p = &*itbeg; + ++itbeg; + //This can throw + boost::interprocess::construct_in_place(p, beg); + ++constructed; + //This can throw in some containers (predicate might throw) + inserter(*p); + } + } + BOOST_CATCH(...){ + if(constructed){ + this->destroy(p); + } + this->node_alloc().deallocate_many(itbeg); + BOOST_RETHROW + } + BOOST_CATCH_END + return beg; + } + + void clear(allocator_v1) + { this->icont().clear_and_dispose(Destroyer(this->node_alloc())); } + + void clear(allocator_v2) + { + allocator_multialloc_chain_node_deallocator chain_holder(this->node_alloc()); + this->icont().clear_and_dispose(chain_holder.get_chain_builder()); + } + + icont_iterator erase_range(icont_iterator first, icont_iterator last, allocator_v1) + { return this->icont().erase_and_dispose(first, last, Destroyer(this->node_alloc())); } + + icont_iterator erase_range(icont_iterator first, icont_iterator last, allocator_v2) + { + allocator_multialloc_chain_node_deallocator chain_holder(this->node_alloc()); + return this->icont().erase_and_dispose(first, last, chain_holder.get_chain_builder()); + } + + template + size_type erase_key(const Key& k, const Comparator &comp, allocator_v1) + { return this->icont().erase_and_dispose(k, comp, Destroyer(this->node_alloc())); } + + template + size_type erase_key(const Key& k, const Comparator &comp, allocator_v2) + { + allocator_multialloc_chain_node_deallocator chain_holder(this->node_alloc()); + return this->icont().erase_and_dispose(k, comp, chain_holder.get_chain_builder()); + } + + protected: + struct cloner + { + cloner(node_alloc_holder &holder) + : m_holder(holder) + {} + + NodePtr operator()(const Node &other) const + { return m_holder.create_node(other.m_data); } + + node_alloc_holder &m_holder; + }; + + struct destroyer + { + destroyer(node_alloc_holder &holder) + : m_holder(holder) + {} + + void operator()(NodePtr n) const + { m_holder.destroy_node(n); } + + node_alloc_holder &m_holder; + }; + + struct members_holder + : public NodeAlloc + { + private: + members_holder(const members_holder&); + + public: + template + members_holder(const ConvertibleToAlloc &c2alloc) + : NodeAlloc(c2alloc) + {} + + template + members_holder(const ConvertibleToAlloc &c2alloc, const Pred &c) + : NodeAlloc(c2alloc), m_icont(c) + {} + //The intrusive container + ICont m_icont; + } members_; + + ICont &non_const_icont() const + { return const_cast(this->members_.m_icont); } + + ICont &icont() + { return this->members_.m_icont; } + + const ICont &icont() const + { return this->members_.m_icont; } + + NodeAlloc &node_alloc() + { return static_cast(this->members_); } + + const NodeAlloc &node_alloc() const + { return static_cast(this->members_); } +}; + +} //namespace detail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // BOOST_INTERPROCESS_DETAIL_NODE_ALLOC_HPP_ diff --git a/win32/include/boost/interprocess/containers/detail/tree.hpp b/win32/include/boost/interprocess/containers/detail/tree.hpp new file mode 100755 index 000000000..96e00f8e0 --- /dev/null +++ b/win32/include/boost/interprocess/containers/detail/tree.hpp @@ -0,0 +1,949 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This file comes from SGI's stl_tree file. Modified by Ion Gaztanaga 2005. +// Renaming, isolating and porting to generic algorithms. Pointer typedef +// set to allocator::pointer to allow placing it in shared memory. +// +/////////////////////////////////////////////////////////////////////////////// +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ +#ifndef BOOST_INTERPROCESS_TREE_HPP +#define BOOST_INTERPROCESS_TREE_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace interprocess { +namespace detail { + +template +struct value_compare_impl + : public KeyCompare +{ + typedef Value value_type; + typedef KeyCompare key_compare; + typedef KeyOfValue key_of_value; + typedef Key key_type; + + value_compare_impl(key_compare kcomp) + : key_compare(kcomp) + {} + + const key_compare &key_comp() const + { return static_cast(*this); } + + key_compare &key_comp() + { return static_cast(*this); } + + template + bool operator()(const A &a, const B &b) const + { return key_compare::operator()(KeyOfValue()(a), KeyOfValue()(b)); } +}; + +template +struct rbtree_node + : public bi::make_set_base_hook + < bi::void_pointer + , bi::link_mode + , bi::optimize_size + >::type +{ + typedef typename bi::make_set_base_hook + < bi::void_pointer + , bi::link_mode + , bi::optimize_size + >::type hook_type; + + typedef T value_type; + + typedef rbtree_node node_type; + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + rbtree_node(const Convertible &conv) + : m_data(conv){} + #else + template + rbtree_node(Convertible &&conv) + : m_data(detail::forward_impl(conv)){} + #endif + + rbtree_node &operator=(const rbtree_node &other) + { do_assign(other.m_data); return *this; } + + T m_data; + private: + + template + void do_assign(const std::pair &p) + { + const_cast(m_data.first) = p.first; + m_data.second = p.second; + } + + template + void do_assign(const V &v) + { m_data = v; } + + public: + #if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) + + template + static void construct(node_type *ptr, const Convertible &value) + { new(ptr) node_type(value); } + + template + static void construct(node_type *ptr, + const detail::moved_object > &value) + { + //std::pair is not movable so we define our own type and overwrite it + typedef detail::pair hack_pair_t; + + typedef rbtree_node hack_node_t; + + new((void*)ptr) hack_node_t(value); + } + + #elif !defined(BOOST_INTERPROCESS_RVALUE_PAIR) + + template + static void construct(node_type *ptr, Convertible &&value) + { new(ptr) node_type(detail::forward_impl(value)); } + + template + static void construct(node_type *ptr, + std::pair &&value) + { + //std::pair is not movable so we define our own type and overwrite it + typedef detail::pair hack_pair_t; + + typedef rbtree_node hack_node_t; + + new((void*)ptr) hack_node_t(value); + } + #endif +}; + +}//namespace detail { +#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) || !defined(BOOST_INTERPROCESS_RVALUE_PAIR) +template +struct has_own_construct_from_it + < boost::interprocess::detail::rbtree_node > +{ + static const bool value = true; +}; +#endif +namespace detail { + +template +struct intrusive_rbtree_type +{ + typedef typename A::value_type value_type; + typedef typename detail::pointer_to_other + ::type void_pointer; + typedef typename detail::rbtree_node + node_type; + typedef node_compare node_compare_type; + typedef typename bi::make_rbtree + + ,bi::base_hook + ,bi::constant_time_size + ,bi::size_type + >::type container_type; + typedef container_type type ; +}; + +} //namespace detail { + +namespace detail { + +template +class rbtree + : protected detail::node_alloc_holder + + >::type + > +{ + typedef typename detail::intrusive_rbtree_type + + >::type Icont; + typedef detail::node_alloc_holder AllocHolder; + typedef typename AllocHolder::NodePtr NodePtr; + typedef rbtree < Key, Value, KeyOfValue + , KeyCompare, A> ThisType; + typedef typename AllocHolder::NodeAlloc NodeAlloc; + typedef typename AllocHolder::ValAlloc ValAlloc; + typedef typename AllocHolder::Node Node; + typedef typename Icont::iterator iiterator; + typedef typename Icont::const_iterator iconst_iterator; + typedef detail::allocator_destroyer Destroyer; + typedef typename AllocHolder::allocator_v1 allocator_v1; + typedef typename AllocHolder::allocator_v2 allocator_v2; + typedef typename AllocHolder::alloc_version alloc_version; + + class RecyclingCloner; + friend class RecyclingCloner; + + class RecyclingCloner + { + public: + RecyclingCloner(AllocHolder &holder, Icont &irbtree) + : m_holder(holder), m_icont(irbtree) + {} + + NodePtr operator()(const Node &other) const + { +// if(!m_icont.empty()){ + if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){ + //First recycle a node (this can't throw) + //NodePtr p = m_icont.unlink_leftmost_without_rebalance(); + try{ + //This can throw + *p = other; + return p; + } + catch(...){ + //If there is an exception destroy the whole source + m_holder.destroy_node(p); + while((p = m_icont.unlink_leftmost_without_rebalance())){ + m_holder.destroy_node(p); + } + throw; + } + } + else{ + return m_holder.create_node(other); + } + } + + AllocHolder &m_holder; + Icont &m_icont; + }; + + public: + typedef Key key_type; + typedef Value value_type; + typedef A allocator_type; + typedef KeyCompare key_compare; + typedef value_compare_impl< Key, Value + , KeyCompare, KeyOfValue> value_compare; + typedef typename A::pointer pointer; + typedef typename A::const_pointer const_pointer; + typedef typename A::reference reference; + typedef typename A::const_reference const_reference; + typedef typename A::size_type size_type; + typedef typename A::difference_type difference_type; + typedef difference_type rbtree_difference_type; + typedef pointer rbtree_pointer; + typedef const_pointer rbtree_const_pointer; + typedef reference rbtree_reference; + typedef const_reference rbtree_const_reference; + typedef NodeAlloc stored_allocator_type; + + private: + + template + struct key_node_compare + : private KeyValueCompare + { + key_node_compare(KeyValueCompare comp) + : KeyValueCompare(comp) + {} + + template + bool operator()(const Node &n, const KeyType &k) const + { return KeyValueCompare::operator()(n.m_data, k); } + + template + bool operator()(const KeyType &k, const Node &n) const + { return KeyValueCompare::operator()(k, n.m_data); } + }; + + typedef key_node_compare KeyNodeCompare; + + public: + //rbtree const_iterator + class const_iterator + : public std::iterator + < std::bidirectional_iterator_tag + , value_type , rbtree_difference_type + , rbtree_const_pointer , rbtree_const_reference> + { + protected: + typedef typename Icont::iterator iiterator; + iiterator m_it; + explicit const_iterator(iiterator it) : m_it(it){} + void prot_incr() { ++m_it; } + void prot_decr() { --m_it; } + + private: + iiterator get() + { return this->m_it; } + + public: + friend class rbtree ; + typedef rbtree_difference_type difference_type; + + //Constructors + const_iterator() + : m_it() + {} + + //Pointer like operators + const_reference operator*() const + { return m_it->m_data; } + + const_pointer operator->() const + { return const_pointer(&m_it->m_data); } + + //Increment / Decrement + const_iterator& operator++() + { prot_incr(); return *this; } + + const_iterator operator++(int) + { iiterator tmp = m_it; ++*this; return const_iterator(tmp); } + + const_iterator& operator--() + { prot_decr(); return *this; } + + const_iterator operator--(int) + { iiterator tmp = m_it; --*this; return const_iterator(tmp); } + + //Comparison operators + bool operator== (const const_iterator& r) const + { return m_it == r.m_it; } + + bool operator!= (const const_iterator& r) const + { return m_it != r.m_it; } + }; + + //rbtree iterator + class iterator : public const_iterator + { + private: + explicit iterator(iiterator it) + : const_iterator(it) + {} + + iiterator get() + { return this->m_it; } + + public: + friend class rbtree ; + typedef rbtree_pointer pointer; + typedef rbtree_reference reference; + + //Constructors + iterator(){} + + //Pointer like operators + reference operator*() const { return this->m_it->m_data; } + pointer operator->() const { return pointer(&this->m_it->m_data); } + + //Increment / Decrement + iterator& operator++() + { this->prot_incr(); return *this; } + + iterator operator++(int) + { iiterator tmp = this->m_it; ++*this; return iterator(tmp); } + + iterator& operator--() + { this->prot_decr(); return *this; } + + iterator operator--(int) + { iterator tmp = *this; --*this; return tmp; } + }; + + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + rbtree(const key_compare& comp = key_compare(), + const allocator_type& a = allocator_type()) + : AllocHolder(a, comp) + {} + + template + rbtree(InputIterator first, InputIterator last, const key_compare& comp, + const allocator_type& a, bool unique_insertion) + : AllocHolder(a, comp) + { + typedef typename std::iterator_traits::iterator_category ItCat; + priv_create_and_insert_nodes(first, last, unique_insertion, alloc_version(), ItCat()); + } + + rbtree(const rbtree& x) + : AllocHolder(x, x.key_comp()) + { + this->icont().clone_from + (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + rbtree(const detail::moved_object& x) + : AllocHolder(x.get(), x.get().key_comp()) + { this->swap(x.get()); } + #else + rbtree(rbtree &&x) + : AllocHolder(x, x.key_comp()) + { this->swap(x); } + #endif + + ~rbtree() + { this->clear(); } + + rbtree& operator=(const rbtree& x) + { + if (this != &x) { + //Transfer all the nodes to a temporary tree + //If anything goes wrong, all the nodes will be destroyed + //automatically + Icont other_tree(this->icont().value_comp()); + other_tree.swap(this->icont()); + + //Now recreate the source tree reusing nodes stored by other_tree + this->icont().clone_from + (x.icont() + , RecyclingCloner(*this, other_tree) + //, AllocHolder::cloner(*this) + , Destroyer(this->node_alloc())); + + //If there are remaining nodes, destroy them + NodePtr p; + while((p = other_tree.unlink_leftmost_without_rebalance())){ + AllocHolder::destroy_node(p); + } + } + return *this; + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + rbtree& operator=(const detail::moved_object& mx) + { this->clear(); this->swap(mx.get()); return *this; } + #else + rbtree& operator=(rbtree &&mx) + { this->clear(); this->swap(mx); return *this; } + #endif + + public: + // accessors: + value_compare value_comp() const + { return this->icont().value_comp().value_comp(); } + + key_compare key_comp() const + { return this->icont().value_comp().value_comp().key_comp(); } + + allocator_type get_allocator() const + { return allocator_type(this->node_alloc()); } + + const stored_allocator_type &get_stored_allocator() const + { return this->node_alloc(); } + + stored_allocator_type &get_stored_allocator() + { return this->node_alloc(); } + + iterator begin() + { return iterator(this->icont().begin()); } + + const_iterator begin() const + { return const_iterator(this->non_const_icont().begin()); } + + iterator end() + { return iterator(this->icont().end()); } + + const_iterator end() const + { return const_iterator(this->non_const_icont().end()); } + + reverse_iterator rbegin() + { return reverse_iterator(end()); } + + const_reverse_iterator rbegin() const + { return const_reverse_iterator(end()); } + + reverse_iterator rend() + { return reverse_iterator(begin()); } + + const_reverse_iterator rend() const + { return const_reverse_iterator(begin()); } + + bool empty() const + { return !this->size(); } + + size_type size() const + { return this->icont().size(); } + + size_type max_size() const + { return AllocHolder::max_size(); } + + void swap(ThisType& x) + { AllocHolder::swap(x); } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(const detail::moved_object& mt) + { this->swap(mt.get()); } + #else + void swap(rbtree &&mt) + { this->swap(mt); } + #endif + + public: + + typedef typename Icont::insert_commit_data insert_commit_data; + + // insert/erase + std::pair insert_unique_check + (const key_type& key, insert_commit_data &data) + { + std::pair ret = + this->icont().insert_unique_check(key, KeyNodeCompare(value_comp()), data); + return std::pair(iterator(ret.first), ret.second); + } + + std::pair insert_unique_check + (const_iterator hint, const key_type& key, insert_commit_data &data) + { + std::pair ret = + this->icont().insert_unique_check(hint.get(), key, KeyNodeCompare(value_comp()), data); + return std::pair(iterator(ret.first), ret.second); + } + + iterator insert_unique_commit(const value_type& v, insert_commit_data &data) + { + NodePtr tmp = AllocHolder::create_node(v); + iiterator it(this->icont().insert_unique_commit(*tmp, data)); + return iterator(it); + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + iterator insert_unique_commit + (const detail::moved_object& mv, insert_commit_data &data) + { + NodePtr tmp = AllocHolder::create_node(mv); + iiterator it(this->icont().insert_unique_commit(*tmp, data)); + return iterator(it); + } + #else + template + iterator insert_unique_commit + (MovableConvertible && mv, insert_commit_data &data) + { + NodePtr tmp = AllocHolder::create_node(detail::forward_impl(mv)); + iiterator it(this->icont().insert_unique_commit(*tmp, data)); + return iterator(it); + } + #endif + + std::pair insert_unique(const value_type& v) + { + insert_commit_data data; + std::pair ret = + this->insert_unique_check(KeyOfValue()(v), data); + if(!ret.second) + return ret; + return std::pair + (this->insert_unique_commit(v, data), true); + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + std::pair insert_unique + (const detail::moved_object& mv) + { + insert_commit_data data; + std::pair ret = + this->insert_unique_check(KeyOfValue()(mv.get()), data); + if(!ret.second) + return ret; + return std::pair + (this->insert_unique_commit(mv, data), true); + } + #else + template + std::pair insert_unique(MovableConvertible &&mv) + { + insert_commit_data data; + std::pair ret = + this->insert_unique_check(KeyOfValue()(mv), data); + if(!ret.second) + return ret; + return std::pair + (this->insert_unique_commit(detail::forward_impl(mv), data), true); + } + #endif + + iterator insert_unique(const_iterator hint, const value_type& v) + { + insert_commit_data data; + std::pair ret = + this->insert_unique_check(hint, KeyOfValue()(v), data); + if(!ret.second) + return ret.first; + return this->insert_unique_commit(v, data); + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + iterator insert_unique + (const_iterator hint, const detail::moved_object &mv) + { + insert_commit_data data; + std::pair ret = + this->insert_unique_check(hint, KeyOfValue()(mv.get()), data); + if(!ret.second) + return ret.first; + return this->insert_unique_commit(mv, data); + } + #else + template + iterator insert_unique + (const_iterator hint, MovableConvertible &&mv) + { + insert_commit_data data; + std::pair ret = + this->insert_unique_check(hint, KeyOfValue()(mv), data); + if(!ret.second) + return ret.first; + return this->insert_unique_commit(detail::forward_impl(mv), data); + } + #endif + + template + void insert_unique(InputIterator first, InputIterator last) + { + if(this->empty()){ + //Insert with end hint, to achieve linear + //complexity if [first, last) is ordered + iterator end(this->end()); + for( ; first != last; ++first) + this->insert_unique(end, *first); + } + else{ + for( ; first != last; ++first) + this->insert_unique(*first); + } + } + + iterator insert_equal(const value_type& v) + { + NodePtr p(AllocHolder::create_node(v)); + return iterator(this->icont().insert_equal(this->icont().end(), *p)); + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + iterator insert_equal(const detail::moved_object &mv) + { + NodePtr p(AllocHolder::create_node(mv)); + return iterator(this->icont().insert_equal(this->icont().end(), *p)); + } + #else + template + iterator insert_equal(MovableConvertible &&mv) + { + NodePtr p(AllocHolder::create_node(detail::forward_impl(mv))); + return iterator(this->icont().insert_equal(this->icont().end(), *p)); + } + #endif + + iterator insert_equal(const_iterator hint, const value_type& v) + { + NodePtr p(AllocHolder::create_node(v)); + return iterator(this->icont().insert_equal(hint.get(), *p)); + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + iterator insert_equal(const_iterator hint, const detail::moved_object &mv) + { + NodePtr p(AllocHolder::create_node(mv)); + return iterator(this->icont().insert_equal(hint.get(), *p)); + } + #else + template + iterator insert_equal(const_iterator hint, MovableConvertible &&mv) + { + NodePtr p(AllocHolder::create_node(detail::move_impl(mv))); + return iterator(this->icont().insert_equal(hint.get(), *p)); + } + #endif + + template + void insert_equal(InputIterator first, InputIterator last) + { + //Insert with end hint, to achieve linear + //complexity if [first, last) is ordered + iterator end(this->end()); + for( ; first != last; ++first) + this->insert_equal(end, *first); + } + + iterator erase(const_iterator position) + { return iterator(this->icont().erase_and_dispose(position.get(), Destroyer(this->node_alloc()))); } + + size_type erase(const key_type& k) + { return AllocHolder::erase_key(k, KeyNodeCompare(value_comp()), alloc_version()); } + + iterator erase(const_iterator first, const_iterator last) + { return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); } + + void clear() + { AllocHolder::clear(alloc_version()); } + + // set operations: + iterator find(const key_type& k) + { return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); } + + const_iterator find(const key_type& k) const + { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(value_comp()))); } + + size_type count(const key_type& k) const + { return size_type(this->icont().count(k, KeyNodeCompare(value_comp()))); } + + iterator lower_bound(const key_type& k) + { return iterator(this->icont().lower_bound(k, KeyNodeCompare(value_comp()))); } + + const_iterator lower_bound(const key_type& k) const + { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(value_comp()))); } + + iterator upper_bound(const key_type& k) + { return iterator(this->icont().upper_bound(k, KeyNodeCompare(value_comp()))); } + + const_iterator upper_bound(const key_type& k) const + { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(value_comp()))); } + + std::pair equal_range(const key_type& k) + { + std::pair ret = + this->icont().equal_range(k, KeyNodeCompare(value_comp())); + return std::pair(iterator(ret.first), iterator(ret.second)); + } + + std::pair equal_range(const key_type& k) const + { + std::pair ret = + this->non_const_icont().equal_range(k, KeyNodeCompare(value_comp())); + return std::pair + (const_iterator(ret.first), const_iterator(ret.second)); + } + + private: + //Iterator range version + template + void priv_create_and_insert_nodes + (InpIterator beg, InpIterator end, bool unique) + { + typedef typename std::iterator_traits::iterator_category ItCat; + priv_create_and_insert_nodes(beg, end, unique, alloc_version(), ItCat()); + } + + template + void priv_create_and_insert_nodes + (InpIterator beg, InpIterator end, bool unique, allocator_v1, std::input_iterator_tag) + { + if(unique){ + for (; beg != end; ++beg){ + this->insert_unique(*beg); + } + } + else{ + for (; beg != end; ++beg){ + this->insert_equal(*beg); + } + } + } + + template + void priv_create_and_insert_nodes + (InpIterator beg, InpIterator end, bool unique, allocator_v2, std::input_iterator_tag) + { //Just forward to the default one + priv_create_and_insert_nodes(beg, end, unique, allocator_v1(), std::input_iterator_tag()); + } + + class insertion_functor; + friend class insertion_functor; + + class insertion_functor + { + Icont &icont_; + typename Icont::iterator pos_; + + public: + insertion_functor(Icont &icont) + : icont_(icont) + {} + + void operator()(Node &n) + { this->icont_.insert_equal(this->icont_.end(), n); } + }; + + + template + void priv_create_and_insert_nodes + (FwdIterator beg, FwdIterator end, bool unique, allocator_v2, std::forward_iterator_tag) + { + if(unique){ + priv_create_and_insert_nodes(beg, end, unique, allocator_v2(), std::input_iterator_tag()); + } + else{ + //Optimized allocation and construction + this->allocate_many_and_construct + (beg, std::distance(beg, end), insertion_functor(this->icont())); + } + } +}; + +template +inline bool +operator==(const rbtree& x, + const rbtree& y) +{ + return x.size() == y.size() && + std::equal(x.begin(), x.end(), y.begin()); +} + +template +inline bool +operator<(const rbtree& x, + const rbtree& y) +{ + return std::lexicographical_compare(x.begin(), x.end(), + y.begin(), y.end()); +} + +template +inline bool +operator!=(const rbtree& x, + const rbtree& y) { + return !(x == y); +} + +template +inline bool +operator>(const rbtree& x, + const rbtree& y) { + return y < x; +} + +template +inline bool +operator<=(const rbtree& x, + const rbtree& y) { + return !(y < x); +} + +template +inline bool +operator>=(const rbtree& x, + const rbtree& y) { + return !(x < y); +} + + +template +inline void +swap(rbtree& x, + rbtree& y) +{ + x.swap(y); +} + +} //namespace detail { + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +//!This class is movable +/* +template +struct is_movable > +{ + enum { value = true }; +}; +*/ + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = + has_trivial_destructor::value && + has_trivial_destructor::value }; +}; + + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_TREE_HPP diff --git a/win32/include/boost/interprocess/containers/flat_map.hpp b/win32/include/boost/interprocess/containers/flat_map.hpp new file mode 100755 index 000000000..a2d5dc77e --- /dev/null +++ b/win32/include/boost/interprocess/containers/flat_map.hpp @@ -0,0 +1,1284 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_FLAT_MAP_HPP +#define BOOST_INTERPROCESS_FLAT_MAP_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace interprocess { + +/// @cond +// Forward declarations of operators == and <, needed for friend declarations. +template +class flat_map; + +template +inline bool operator==(const flat_map& x, + const flat_map& y); + +template +inline bool operator<(const flat_map& x, + const flat_map& y); +/// @endcond + +//! A flat_map is a kind of associative container that supports unique keys (contains at +//! most one of each key value) and provides for fast retrieval of values of another +//! type T based on the keys. The flat_map class supports random-access iterators. +//! +//! A flat_map satisfies all of the requirements of a container and of a reversible +//! container and of an associative container. A flat_map also provides +//! most operations described for unique keys. For a +//! flat_map the key_type is Key and the value_type is std::pair +//! (unlike std::map which value_type is std::pair<const Key, T>). +//! +//! Pred is the ordering function for Keys (e.g. std::less). +//! +//! Alloc is the allocator to allocate the value_types +//! (e.g. boost::interprocess:allocator< std::pair). +//! +//! flat_map is similar to std::map but it's implemented like an ordered vector. +//! This means that inserting a new element into a flat_map invalidates +//! previous iterators and references +//! +//! Erasing an element of a flat_map invalidates iterators and references +//! pointing to elements that come after (their keys are bigger) the erased element. +template +class flat_map +{ + /// @cond + private: + //This is the tree that we should store if pair was movable + typedef detail::flat_tree, + detail::select1st< std::pair >, + Pred, + Alloc> tree_t; + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + //This is the real tree stored here. It's based on a movable pair + typedef detail::flat_tree, + detail::select1st< detail::pair >, + Pred, + typename Alloc::template + rebind >::other> impl_tree_t; + #else + typedef tree_t impl_tree_t; + #endif + + impl_tree_t m_flat_tree; // flat tree representing flat_map + + typedef typename impl_tree_t::value_type impl_value_type; + typedef typename impl_tree_t::pointer impl_pointer; + typedef typename impl_tree_t::const_pointer impl_const_pointer; + typedef typename impl_tree_t::reference impl_reference; + typedef typename impl_tree_t::const_reference impl_const_reference; + typedef typename impl_tree_t::value_compare impl_value_compare; + typedef typename impl_tree_t::iterator impl_iterator; + typedef typename impl_tree_t::const_iterator impl_const_iterator; + typedef typename impl_tree_t::reverse_iterator impl_reverse_iterator; + typedef typename impl_tree_t::const_reverse_iterator impl_const_reverse_iterator; + typedef typename impl_tree_t::allocator_type impl_allocator_type; + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + typedef detail::moved_object impl_moved_value_type; + #endif + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + static D &force(const S &s) + { return *((D*)(void*)(const void*)(&s)); } + #else + //For rvalue-aware compilers, just forward + template + static const Type &force(const Type &t) + { return t; } + + template + static Type &force(Type &t) + { return t; } + #endif + + /// @endcond + + public: + // typedefs: + typedef typename tree_t::key_type key_type; + typedef typename tree_t::value_type value_type; + typedef typename tree_t::pointer pointer; + typedef typename tree_t::const_pointer const_pointer; + typedef typename tree_t::reference reference; + typedef typename tree_t::const_reference const_reference; + typedef typename tree_t::value_compare value_compare; + typedef T mapped_type; + typedef typename tree_t::key_compare key_compare; + typedef typename tree_t::iterator iterator; + typedef typename tree_t::const_iterator const_iterator; + typedef typename tree_t::reverse_iterator reverse_iterator; + typedef typename tree_t::const_reverse_iterator const_reverse_iterator; + typedef typename tree_t::size_type size_type; + typedef typename tree_t::difference_type difference_type; + typedef typename tree_t::allocator_type allocator_type; + typedef typename tree_t::stored_allocator_type stored_allocator_type; + + //! Effects: Constructs an empty flat_map using the specified + //! comparison object and allocator. + //! + //! Complexity: Constant. + explicit flat_map(const Pred& comp = Pred(), const allocator_type& a = allocator_type()) + : m_flat_tree(comp, force(a)) {} + + //! Effects: Constructs an empty flat_map using the specified comparison object and + //! allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + flat_map(InputIterator first, InputIterator last, const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(comp, force(a)) + { m_flat_tree.insert_unique(first, last); } + + //! Effects: Copy constructs a flat_map. + //! + //! Complexity: Linear in x.size(). + flat_map(const flat_map& x) + : m_flat_tree(x.m_flat_tree) {} + + //! Effects: Move constructs a flat_map. + //! Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + flat_map(const detail::moved_object >& x) + : m_flat_tree(detail::move_impl(x.get().m_flat_tree)) {} + + #else + flat_map(flat_map && x) + : m_flat_tree(detail::move_impl(x.m_flat_tree)) {} + #endif + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + flat_map& operator=(const flat_map& x) + { m_flat_tree = x.m_flat_tree; return *this; } + + //! Effects: Move constructs a flat_map. + //! Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + flat_map& operator=(const detail::moved_object >& mx) + { m_flat_tree = detail::move_impl(mx.get().m_flat_tree); return *this; } + #else + flat_map& operator=(flat_map && mx) + { m_flat_tree = detail::move_impl(mx.m_flat_tree); return *this; } + #endif + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return force(m_flat_tree.key_comp()); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return value_compare(force(m_flat_tree.key_comp())); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return force(m_flat_tree.get_allocator()); } + + const stored_allocator_type &get_stored_allocator() const + { return force(m_flat_tree.get_stored_allocator()); } + + stored_allocator_type &get_stored_allocator() + { return force(m_flat_tree.get_stored_allocator()); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return force(m_flat_tree.begin()); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return force(m_flat_tree.begin()); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return force(m_flat_tree.end()); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return force(m_flat_tree.end()); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return force(m_flat_tree.rbegin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return force(m_flat_tree.rbegin()); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return force(m_flat_tree.rend()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return force(m_flat_tree.rend()); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_flat_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_flat_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_flat_tree.max_size(); } + + //! Effects: If there is no key equivalent to x in the flat_map, inserts + //! value_type(detail::move_impl(x), T()) into the flat_map (the key is move-constructed) + //! + //! Returns: A reference to the mapped_type corresponding to x in *this. + //! + //! Complexity: Logarithmic. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + //! Effects: If there is no key equivalent to x in the flat_map, inserts + //! value_type(x, T()) into the flat_map. + //! + //! Returns: A reference to the mapped_type corresponding to x in *this. + //! + //! Complexity: Logarithmic. + T &operator[](const key_type& k) + { + iterator i = lower_bound(k); + // i->first is greater than or equivalent to k. + if (i == end() || key_comp()(k, (*i).first)) + i = insert(i, value_type(k, T())); + return (*i).second; + } + + T &operator[](const detail::moved_object& mk) + { + key_type &k = mk.get(); + iterator i = lower_bound(k); + // i->first is greater than or equivalent to k. + if (i == end() || key_comp()(k, (*i).first)) + i = insert(i, value_type(k, detail::move_impl(T()))); + return (*i).second; + } + #else + //! Effects: If there is no key equivalent to x in the flat_map, inserts + //! value_type(x, T()) into the flat_map. + //! + //! Returns: A reference to the mapped_type corresponding to x in *this. + //! + //! Complexity: Logarithmic. + T &operator[](key_type &&mk) + { + key_type &k = mk; + iterator i = lower_bound(k); + // i->first is greater than or equivalent to k. + if (i == end() || key_comp()(k, (*i).first)) + i = insert(i, value_type(detail::forward_impl(k), detail::move_impl(T()))); + return (*i).second; + } + #endif + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(flat_map& x) + { m_flat_tree.swap(x.m_flat_tree); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(const detail::moved_object >& x) + { m_flat_tree.swap(x.get().m_flat_tree); } + #else + void swap(flat_map && x) + { m_flat_tree.swap(x.m_flat_tree); } + #endif + + //! Effects: Inserts x if and only if there is no element in the container + //! with key equivalent to the key of x. + //! + //! Returns: The bool component of the returned pair is true if and only + //! if the insertion takes place, and the iterator component of the pair + //! points to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + std::pair insert(const value_type& x) + { return force >( + m_flat_tree.insert_unique(force(x))); } + + //! Effects: Inserts a new value_type move constructed from the pair if and + //! only if there is no element in the container with key equivalent to the key of x. + //! + //! Returns: The bool component of the returned pair is true if and only + //! if the insertion takes place, and the iterator component of the pair + //! points to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + std::pair insert(const detail::moved_object& x) + { return force >( + m_flat_tree.insert_unique(force(x))); } + #else + std::pair insert(value_type &&x) + { return m_flat_tree.insert_unique(detail::move_impl(x)); } + #endif + + //! Effects: Inserts a copy of x in the container if and only if there is + //! no element in the container with key equivalent to the key of x. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(iterator position, const value_type& x) + { return force( + m_flat_tree.insert_unique(force(position), force(x))); } + + //! Effects: Inserts an element move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(iterator position, const detail::moved_object& x) + { return force( + m_flat_tree.insert_unique(force(position), force(x))); } + #else + iterator insert(iterator position, value_type &&x) + { return m_flat_tree.insert_unique(position, detail::move_impl(x)); } + #endif + + //! Requires: i, j are not iterators into *this. + //! + //! Effects: inserts each element from the range [i,j) if and only + //! if there is no element with key equivalent to the key of that element. + //! + //! Complexity: N log(size()+N) (N is the distance from i to j) + //! search time plus N*size() insertion time. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + void insert(InputIterator first, InputIterator last) + { m_flat_tree.insert_unique(first, last); } + + //! Effects: Erases the element pointed to by position. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Linear to the elements with keys bigger than position + //! + //! Note: Invalidates elements with keys + //! not less than the erased element. + iterator erase(const_iterator position) + { return force(m_flat_tree.erase(force(position))); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: Logarithmic search time plus erasure time + //! linear to the elements with bigger keys. + size_type erase(const key_type& x) + { return m_flat_tree.erase(x); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: size()*N where N is the distance from first to last. + //! + //! Complexity: Logarithmic search time plus erasure time + //! linear to the elements with bigger keys. + iterator erase(const_iterator first, const_iterator last) + { return force(m_flat_tree.erase(force(first), force(last))); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_flat_tree.clear(); } + + //! Effects: Tries to deallocate the excess of memory created + // with previous allocations. The size of the vector is unchanged + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to size(). + void shrink_to_fit() + { m_flat_tree.shrink_to_fit(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return force(m_flat_tree.find(x)); } + + //! Returns: A const_iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic.s + const_iterator find(const key_type& x) const + { return force(m_flat_tree.find(x)); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_flat_tree.find(x) == m_flat_tree.end() ? 0 : 1; } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + { return force(m_flat_tree.lower_bound(x)); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return force(m_flat_tree.lower_bound(x)); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + { return force(m_flat_tree.upper_bound(x)); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return force(m_flat_tree.upper_bound(x)); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair equal_range(const key_type& x) + { return force >(m_flat_tree.equal_range(x)); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair equal_range(const key_type& x) const + { return force >(m_flat_tree.equal_range(x)); } + + //! Effects: Number of elements for which memory has been allocated. + //! capacity() is always greater than or equal to size(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type capacity() const + { return m_flat_tree.capacity(); } + + //! Effects: If n is less than or equal to capacity(), this call has no + //! effect. Otherwise, it is a request for allocation of additional memory. + //! If the request is successful, then capacity() is greater than or equal to + //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged. + //! + //! Throws: If memory allocation allocation throws or T's copy constructor throws. + //! + //! Note: If capacity() is less than "count", iterators and references to + //! to values might be invalidated. + void reserve(size_type count) + { m_flat_tree.reserve(count); } + + /// @cond + template + friend bool operator== (const flat_map&, + const flat_map&); + template + friend bool operator< (const flat_map&, + const flat_map&); + /// @endcond +}; + +template +inline bool operator==(const flat_map& x, + const flat_map& y) + { return x.m_flat_tree == y.m_flat_tree; } + +template +inline bool operator<(const flat_map& x, + const flat_map& y) + { return x.m_flat_tree < y.m_flat_tree; } + +template +inline bool operator!=(const flat_map& x, + const flat_map& y) + { return !(x == y); } + +template +inline bool operator>(const flat_map& x, + const flat_map& y) + { return y < x; } + +template +inline bool operator<=(const flat_map& x, + const flat_map& y) + { return !(y < x); } + +template +inline bool operator>=(const flat_map& x, + const flat_map& y) + { return !(x < y); } + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline void swap(flat_map& x, + flat_map& y) + { x.swap(y); } + +template +inline void swap(const detail::moved_object >& x, + flat_map& y) + { x.get().swap(y); } + +template +inline void swap(flat_map& x, + const detail::moved_object >& y) + { x.swap(y.get()); } +#else +template +inline void swap(flat_map&&x, + flat_map&&y) + { x.swap(y); } +#endif + +/// @cond + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = + has_trivial_destructor::value && + has_trivial_destructor::value }; +}; + +// Forward declaration of operators < and ==, needed for friend declaration. +template +class flat_multimap; + +template +inline bool operator==(const flat_multimap& x, + const flat_multimap& y); + +template +inline bool operator<(const flat_multimap& x, + const flat_multimap& y); +/// @endcond + +//! A flat_multimap is a kind of associative container that supports equivalent keys +//! (possibly containing multiple copies of the same key value) and provides for +//! fast retrieval of values of another type T based on the keys. The flat_multimap +//! class supports random-access iterators. +//! +//! A flat_multimap satisfies all of the requirements of a container and of a reversible +//! container and of an associative container. For a +//! flat_multimap the key_type is Key and the value_type is std::pair +//! (unlike std::multimap which value_type is std::pair<const Key, T>). +//! +//! Pred is the ordering function for Keys (e.g. std::less). +//! +//! Alloc is the allocator to allocate the value_types +//! (e.g. boost::interprocess:allocator< std::pair). +template +class flat_multimap +{ + /// @cond + private: + typedef detail::flat_tree, + detail::select1st< std::pair >, + Pred, + Alloc> tree_t; + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + //This is the real tree stored here. It's based on a movable pair + typedef detail::flat_tree, + detail::select1st< detail::pair >, + Pred, + typename Alloc::template + rebind >::other> impl_tree_t; + #else + typedef tree_t impl_tree_t; + #endif + + impl_tree_t m_flat_tree; // flat tree representing flat_map + + typedef typename impl_tree_t::value_type impl_value_type; + typedef typename impl_tree_t::pointer impl_pointer; + typedef typename impl_tree_t::const_pointer impl_const_pointer; + typedef typename impl_tree_t::reference impl_reference; + typedef typename impl_tree_t::const_reference impl_const_reference; + typedef typename impl_tree_t::value_compare impl_value_compare; + typedef typename impl_tree_t::iterator impl_iterator; + typedef typename impl_tree_t::const_iterator impl_const_iterator; + typedef typename impl_tree_t::reverse_iterator impl_reverse_iterator; + typedef typename impl_tree_t::const_reverse_iterator impl_const_reverse_iterator; + typedef typename impl_tree_t::allocator_type impl_allocator_type; + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + typedef detail::moved_object impl_moved_value_type; + #endif + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + static D &force(const S &s) + { return *const_cast((reinterpret_cast(&s))); } + #else + //For rvalue-aware compilers, just forward + template + static const Type &force(const Type &t) + { return t; } + + template + static Type &force(Type &t) + { return t; } + #endif + /// @endcond + + public: + // typedefs: + typedef typename tree_t::key_type key_type; + typedef typename tree_t::value_type value_type; + typedef typename tree_t::pointer pointer; + typedef typename tree_t::const_pointer const_pointer; + typedef typename tree_t::reference reference; + typedef typename tree_t::const_reference const_reference; + typedef typename tree_t::value_compare value_compare; + typedef T mapped_type; + typedef typename tree_t::key_compare key_compare; + typedef typename tree_t::iterator iterator; + typedef typename tree_t::const_iterator const_iterator; + typedef typename tree_t::reverse_iterator reverse_iterator; + typedef typename tree_t::const_reverse_iterator const_reverse_iterator; + typedef typename tree_t::size_type size_type; + typedef typename tree_t::difference_type difference_type; + typedef typename tree_t::allocator_type allocator_type; + typedef typename tree_t::stored_allocator_type stored_allocator_type; + + //! Effects: Constructs an empty flat_multimap using the specified comparison + //! object and allocator. + //! + //! Complexity: Constant. + explicit flat_multimap(const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(comp, force(a)) { } + + //! Effects: Constructs an empty flat_multimap using the specified comparison object + //! and allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + flat_multimap(InputIterator first, InputIterator last, + const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(comp, force(a)) + { m_flat_tree.insert_equal(first, last); } + + //! Effects: Copy constructs a flat_multimap. + //! + //! Complexity: Linear in x.size(). + flat_multimap(const flat_multimap& x) + : m_flat_tree(x.m_flat_tree) { } + + //! Effects: Move constructs a flat_multimap. Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + flat_multimap(const detail::moved_object >& x) + : m_flat_tree(detail::move_impl(x.get().m_flat_tree)) { } + #else + flat_multimap(flat_multimap && x) + : m_flat_tree(detail::move_impl(x.m_flat_tree)) { } + #endif + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + flat_multimap& + operator=(const flat_multimap& x) + { m_flat_tree = x.m_flat_tree; return *this; } + + //! Effects: this->swap(x.get()). + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + flat_multimap& + operator=(const detail::moved_object >& mx) + { m_flat_tree = detail::move_impl(mx.get().m_flat_tree); return *this; } + #else + flat_multimap& + operator=(flat_multimap && mx) + { m_flat_tree = detail::move_impl(mx.m_flat_tree); return *this; } + #endif + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return force(m_flat_tree.key_comp()); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return value_compare(force(m_flat_tree.key_comp())); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return force(m_flat_tree.get_allocator()); } + + const stored_allocator_type &get_stored_allocator() const + { return force(m_flat_tree.get_stored_allocator()); } + + stored_allocator_type &get_stored_allocator() + { return force(m_flat_tree.get_stored_allocator()); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return force(m_flat_tree.begin()); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return force(m_flat_tree.begin()); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return force(m_flat_tree.end()); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return force(m_flat_tree.end()); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return force(m_flat_tree.rbegin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return force(m_flat_tree.rbegin()); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return force(m_flat_tree.rend()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return force(m_flat_tree.rend()); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_flat_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_flat_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_flat_tree.max_size(); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(flat_multimap& x) + { m_flat_tree.swap(x.m_flat_tree); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(const detail::moved_object >& x) + { m_flat_tree.swap(x.get().m_flat_tree); } + #else + void swap(flat_multimap && x) + { m_flat_tree.swap(x.m_flat_tree); } + #endif + + //! Effects: Inserts x and returns the iterator pointing to the + //! newly inserted element. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(const value_type& x) + { return force(m_flat_tree.insert_equal(force(x))); } + + //! Effects: Inserts a new value move-constructed from x and returns + //! the iterator pointing to the newly inserted element. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(const detail::moved_object& x) + { return force(m_flat_tree.insert_equal(force(x))); } + #else + iterator insert(value_type &&x) + { return m_flat_tree.insert_equal(detail::move_impl(x)); } + #endif + + //! Effects: Inserts a copy of x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic search time (constant time if the value + //! is to be inserted before p) plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(iterator position, const value_type& x) + { return force(m_flat_tree.insert_equal(force(position), force(x))); } + + //! Effects: Inserts a value move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic search time (constant time if the value + //! is to be inserted before p) plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(iterator position, const detail::moved_object& x) + { return force(m_flat_tree.insert_equal(force(position), force(x))); } + #else + iterator insert(iterator position, value_type &&x) + { return m_flat_tree.insert_equal(force(position), detail::move_impl(x)); } + #endif + + //! Requires: i, j are not iterators into *this. + //! + //! Effects: inserts each element from the range [i,j) . + //! + //! Complexity: N log(size()+N) (N is the distance from i to j) + //! search time plus N*size() insertion time. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + void insert(InputIterator first, InputIterator last) + { m_flat_tree.insert_equal(first, last); } + + //! Effects: Erases the element pointed to by position. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Linear to the elements with keys bigger than position + //! + //! Note: Invalidates elements with keys + //! not less than the erased element. + iterator erase(const_iterator position) + { return force(m_flat_tree.erase(force(position))); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: Logarithmic search time plus erasure time + //! linear to the elements with bigger keys. + size_type erase(const key_type& x) + { return m_flat_tree.erase(x); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: size()*N where N is the distance from first to last. + //! + //! Complexity: Logarithmic search time plus erasure time + //! linear to the elements with bigger keys. + iterator erase(const_iterator first, const_iterator last) + { return force(m_flat_tree.erase(force(first), force(last))); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_flat_tree.clear(); } + + //! Effects: Tries to deallocate the excess of memory created + // with previous allocations. The size of the vector is unchanged + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to size(). + void shrink_to_fit() + { m_flat_tree.shrink_to_fit(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return force(m_flat_tree.find(x)); } + + //! Returns: An const_iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + const_iterator find(const key_type& x) const + { return force(m_flat_tree.find(x)); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_flat_tree.count(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + {return force(m_flat_tree.lower_bound(x)); } + + //! Returns: A const iterator pointing to the first element with key + //! not less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return force(m_flat_tree.lower_bound(x)); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + {return force(m_flat_tree.upper_bound(x)); } + + //! Returns: A const iterator pointing to the first element with key + //! not less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return force(m_flat_tree.upper_bound(x)); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair equal_range(const key_type& x) + { return force >(m_flat_tree.equal_range(x)); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) const + { return force >(m_flat_tree.equal_range(x)); } + + //! Effects: Number of elements for which memory has been allocated. + //! capacity() is always greater than or equal to size(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type capacity() const + { return m_flat_tree.capacity(); } + + //! Effects: If n is less than or equal to capacity(), this call has no + //! effect. Otherwise, it is a request for allocation of additional memory. + //! If the request is successful, then capacity() is greater than or equal to + //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged. + //! + //! Throws: If memory allocation allocation throws or T's copy constructor throws. + //! + //! Note: If capacity() is less than "count", iterators and references to + //! to values might be invalidated. + void reserve(size_type count) + { m_flat_tree.reserve(count); } + + /// @cond + template + friend bool operator== (const flat_multimap& x, + const flat_multimap& y); + + template + friend bool operator< (const flat_multimap& x, + const flat_multimap& y); + /// @endcond +}; + +template +inline bool operator==(const flat_multimap& x, + const flat_multimap& y) + { return x.m_flat_tree == y.m_flat_tree; } + +template +inline bool operator<(const flat_multimap& x, + const flat_multimap& y) + { return x.m_flat_tree < y.m_flat_tree; } + +template +inline bool operator!=(const flat_multimap& x, + const flat_multimap& y) + { return !(x == y); } + +template +inline bool operator>(const flat_multimap& x, + const flat_multimap& y) + { return y < x; } + +template +inline bool operator<=(const flat_multimap& x, + const flat_multimap& y) + { return !(y < x); } + +template +inline bool operator>=(const flat_multimap& x, + const flat_multimap& y) + { return !(x < y); } + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline void swap(flat_multimap& x, + flat_multimap& y) + { x.swap(y); } + +template +inline void swap(const detail::moved_object >& x, + flat_multimap& y) + { x.get().swap(y); } + + +template +inline void swap(flat_multimap& x, + const detail::moved_object > & y) + { x.swap(y.get()); } +#else +template +inline void swap(flat_multimap&&x, + flat_multimap&&y) + { x.swap(y); } +#endif + +/// @cond + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = + has_trivial_destructor::value && + has_trivial_destructor::value }; +}; +/// @endcond + +}} //namespace boost { namespace interprocess { + +#include + +#endif /* BOOST_INTERPROCESS_FLAT_MAP_HPP */ diff --git a/win32/include/boost/interprocess/containers/flat_set.hpp b/win32/include/boost/interprocess/containers/flat_set.hpp new file mode 100755 index 000000000..dd6075793 --- /dev/null +++ b/win32/include/boost/interprocess/containers/flat_set.hpp @@ -0,0 +1,1093 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_FLAT_SET_HPP +#define BOOST_INTERPROCESS_FLAT_SET_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace interprocess { + +/// @cond +// Forward declarations of operators < and ==, needed for friend declaration. + +template +class flat_set; + +template +inline bool operator==(const flat_set& x, + const flat_set& y); + +template +inline bool operator<(const flat_set& x, + const flat_set& y); +/// @endcond + +//! flat_set is a Sorted Associative Container that stores objects of type Key. +//! flat_set is a Simple Associative Container, meaning that its value type, +//! as well as its key type, is Key. It is also a Unique Associative Container, +//! meaning that no two elements are the same. +//! +//! flat_set is similar to std::set but it's implemented like an ordered vector. +//! This means that inserting a new element into a flat_set invalidates +//! previous iterators and references +//! +//! Erasing an element of a flat_set invalidates iterators and references +//! pointing to elements that come after (their keys are bigger) the erased element. +template +class flat_set +{ + /// @cond + private: + typedef detail::flat_tree, Pred, Alloc> tree_t; + tree_t m_flat_tree; // flat tree representing flat_set + /// @endcond + + public: + // typedefs: + typedef typename tree_t::key_type key_type; + typedef typename tree_t::value_type value_type; + typedef typename tree_t::pointer pointer; + typedef typename tree_t::const_pointer const_pointer; + typedef typename tree_t::reference reference; + typedef typename tree_t::const_reference const_reference; + typedef typename tree_t::key_compare key_compare; + typedef typename tree_t::value_compare value_compare; + typedef typename tree_t::iterator iterator; + typedef typename tree_t::const_iterator const_iterator; + typedef typename tree_t::reverse_iterator reverse_iterator; + typedef typename tree_t::const_reverse_iterator const_reverse_iterator; + typedef typename tree_t::size_type size_type; + typedef typename tree_t::difference_type difference_type; + typedef typename tree_t::allocator_type allocator_type; + typedef typename tree_t::stored_allocator_type stored_allocator_type; + + //! Effects: Constructs an empty flat_map using the specified + //! comparison object and allocator. + //! + //! Complexity: Constant. + explicit flat_set(const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(comp, a) + {} + + //! Effects: Constructs an empty map using the specified comparison object and + //! allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + flat_set(InputIterator first, InputIterator last, + const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(comp, a) + { m_flat_tree.insert_unique(first, last); } + + //! Effects: Copy constructs a map. + //! + //! Complexity: Linear in x.size(). + flat_set(const flat_set& x) + : m_flat_tree(x.m_flat_tree) {} + + //! Effects: Move constructs a map. Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + flat_set(const detail::moved_object >& mx) + : m_flat_tree(detail::move_impl(mx.get().m_flat_tree)) {} + #else + flat_set(flat_set && mx) + : m_flat_tree(detail::move_impl(mx.m_flat_tree)) {} + #endif + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + flat_set& operator=(const flat_set& x) + { m_flat_tree = x.m_flat_tree; return *this; } + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + flat_set& operator=(const detail::moved_object > &mx) + { m_flat_tree = detail::move_impl(mx.get().m_flat_tree); return *this; } + + #else + flat_set& operator=(flat_set &&mx) + { m_flat_tree = detail::move_impl(mx.m_flat_tree); return *this; } + + #endif + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return m_flat_tree.key_comp(); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return m_flat_tree.key_comp(); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return m_flat_tree.get_allocator(); } + + const stored_allocator_type &get_stored_allocator() const + { return m_flat_tree.get_stored_allocator(); } + + stored_allocator_type &get_stored_allocator() + { return m_flat_tree.get_stored_allocator(); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return m_flat_tree.begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return m_flat_tree.begin(); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return m_flat_tree.end(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return m_flat_tree.end(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return m_flat_tree.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return m_flat_tree.rbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return m_flat_tree.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return m_flat_tree.rend(); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_flat_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_flat_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_flat_tree.max_size(); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(flat_set& x) + { m_flat_tree.swap(x.m_flat_tree); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(const detail::moved_object >& mx) + { this->swap(mx.get()); } + #else + void swap(flat_set && mx) + { this->swap(mx); } + #endif + + //! Effects: Inserts x if and only if there is no element in the container + //! with key equivalent to the key of x. + //! + //! Returns: The bool component of the returned pair is true if and only + //! if the insertion takes place, and the iterator component of the pair + //! points to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + std::pair insert(const value_type& x) + { return m_flat_tree.insert_unique(x); } + + //! Effects: Inserts a new value_type move constructed from the pair if and + //! only if there is no element in the container with key equivalent to the key of x. + //! + //! Returns: The bool component of the returned pair is true if and only + //! if the insertion takes place, and the iterator component of the pair + //! points to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + std::pair insert(const detail::moved_object& x) + { return m_flat_tree.insert_unique(x); } + #else + std::pair insert(value_type && x) + { return m_flat_tree.insert_unique(detail::move_impl(x)); } + #endif + + //! Effects: Inserts a copy of x in the container if and only if there is + //! no element in the container with key equivalent to the key of x. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(iterator position, const value_type& x) + { return m_flat_tree.insert_unique(position, x); } + + //! Effects: Inserts an element move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(iterator position, const detail::moved_object& x) + { return m_flat_tree.insert_unique(position, x); } + #else + iterator insert(iterator position, value_type && x) + { return m_flat_tree.insert_unique(position, detail::move_impl(x)); } + #endif + + //! Requires: i, j are not iterators into *this. + //! + //! Effects: inserts each element from the range [i,j) if and only + //! if there is no element with key equivalent to the key of that element. + //! + //! Complexity: N log(size()+N) (N is the distance from i to j) + //! search time plus N*size() insertion time. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + void insert(InputIterator first, InputIterator last) + { m_flat_tree.insert_unique(first, last); } + + //! Effects: Erases the element pointed to by position. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Linear to the elements with keys bigger than position + //! + //! Note: Invalidates elements with keys + //! not less than the erased element. + iterator erase(const_iterator position) + { return m_flat_tree.erase(position); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: Logarithmic search time plus erasure time + //! linear to the elements with bigger keys. + size_type erase(const key_type& x) + { return m_flat_tree.erase(x); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: size()*N where N is the distance from first to last. + //! + //! Complexity: Logarithmic search time plus erasure time + //! linear to the elements with bigger keys. + iterator erase(const_iterator first, const_iterator last) + { return m_flat_tree.erase(first, last); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_flat_tree.clear(); } + + //! Effects: Tries to deallocate the excess of memory created + // with previous allocations. The size of the vector is unchanged + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to size(). + void shrink_to_fit() + { m_flat_tree.shrink_to_fit(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return m_flat_tree.find(x); } + + //! Returns: A const_iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic.s + const_iterator find(const key_type& x) const + { return m_flat_tree.find(x); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_flat_tree.find(x) == m_flat_tree.end() ? 0 : 1; } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + { return m_flat_tree.lower_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return m_flat_tree.lower_bound(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + { return m_flat_tree.upper_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return m_flat_tree.upper_bound(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) const + { return m_flat_tree.equal_range(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) + { return m_flat_tree.equal_range(x); } + + //! Effects: Number of elements for which memory has been allocated. + //! capacity() is always greater than or equal to size(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type capacity() const + { return m_flat_tree.capacity(); } + + //! Effects: If n is less than or equal to capacity(), this call has no + //! effect. Otherwise, it is a request for allocation of additional memory. + //! If the request is successful, then capacity() is greater than or equal to + //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged. + //! + //! Throws: If memory allocation allocation throws or T's copy constructor throws. + //! + //! Note: If capacity() is less than "count", iterators and references to + //! to values might be invalidated. + void reserve(size_type count) + { m_flat_tree.reserve(count); } + + /// @cond + template + friend bool operator== (const flat_set&, const flat_set&); + + template + friend bool operator< (const flat_set&, const flat_set&); + /// @endcond +}; + +template +inline bool operator==(const flat_set& x, + const flat_set& y) + { return x.m_flat_tree == y.m_flat_tree; } + +template +inline bool operator<(const flat_set& x, + const flat_set& y) + { return x.m_flat_tree < y.m_flat_tree; } + +template +inline bool operator!=(const flat_set& x, + const flat_set& y) + { return !(x == y); } + +template +inline bool operator>(const flat_set& x, + const flat_set& y) + { return y < x; } + +template +inline bool operator<=(const flat_set& x, + const flat_set& y) + { return !(y < x); } + +template +inline bool operator>=(const flat_set& x, + const flat_set& y) + { return !(x < y); } + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline void swap(flat_set& x, + flat_set& y) + { x.swap(y); } + +template +inline void swap(const detail::moved_object >& x, + flat_set& y) + { x.get().swap(y); } + +template +inline void swap(flat_set& x, + const detail::moved_object >& y) + { x.swap(y.get()); } +#else +template +inline void swap(flat_set&&x, + flat_set&&y) + { x.swap(y); } +#endif + +/// @cond + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = + has_trivial_destructor::value && + has_trivial_destructor::value }; +}; + +// Forward declaration of operators < and ==, needed for friend declaration. + +template +class flat_multiset; + +template +inline bool operator==(const flat_multiset& x, + const flat_multiset& y); + +template +inline bool operator<(const flat_multiset& x, + const flat_multiset& y); +/// @endcond + +//! flat_multiset is a Sorted Associative Container that stores objects of type Key. +//! flat_multiset is a Simple Associative Container, meaning that its value type, +//! as well as its key type, is Key. +//! flat_Multiset can store multiple copies of the same key value. +//! +//! flat_multiset is similar to std::multiset but it's implemented like an ordered vector. +//! This means that inserting a new element into a flat_multiset invalidates +//! previous iterators and references +//! +//! Erasing an element of a flat_multiset invalidates iterators and references +//! pointing to elements that come after (their keys are equal or bigger) the erased element. +template +class flat_multiset +{ + /// @cond + private: + typedef detail::flat_tree, Pred, Alloc> tree_t; + tree_t m_flat_tree; // flat tree representing flat_multiset + /// @endcond + + public: + // typedefs: + typedef typename tree_t::key_type key_type; + typedef typename tree_t::value_type value_type; + typedef typename tree_t::pointer pointer; + typedef typename tree_t::const_pointer const_pointer; + typedef typename tree_t::reference reference; + typedef typename tree_t::const_reference const_reference; + typedef typename tree_t::key_compare key_compare; + typedef typename tree_t::value_compare value_compare; + typedef typename tree_t::iterator iterator; + typedef typename tree_t::const_iterator const_iterator; + typedef typename tree_t::reverse_iterator reverse_iterator; + typedef typename tree_t::const_reverse_iterator const_reverse_iterator; + typedef typename tree_t::size_type size_type; + typedef typename tree_t::difference_type difference_type; + typedef typename tree_t::allocator_type allocator_type; + typedef typename tree_t::stored_allocator_type stored_allocator_type; + + // allocation/deallocation + explicit flat_multiset(const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(comp, a) {} + + template + flat_multiset(InputIterator first, InputIterator last, + const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_flat_tree(comp, a) + { m_flat_tree.insert_equal(first, last); } + + flat_multiset(const flat_multiset& x) + : m_flat_tree(x.m_flat_tree) {} + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + flat_multiset(const detail::moved_object >& x) + : m_flat_tree(detail::move_impl(x.get().m_flat_tree)) {} + #else + flat_multiset(flat_multiset && x) + : m_flat_tree(detail::move_impl(x.m_flat_tree)) {} + #endif + + flat_multiset& operator=(const flat_multiset& x) + { m_flat_tree = x.m_flat_tree; return *this; } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + flat_multiset& operator=(const detail::moved_object >& mx) + { m_flat_tree = detail::move_impl(mx.get().m_flat_tree); return *this; } + #else + flat_multiset& operator=(flat_multiset && mx) + { m_flat_tree = detail::move_impl(mx.m_flat_tree); return *this; } + #endif + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return m_flat_tree.key_comp(); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return m_flat_tree.key_comp(); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return m_flat_tree.get_allocator(); } + + const stored_allocator_type &get_stored_allocator() const + { return m_flat_tree.get_stored_allocator(); } + + stored_allocator_type &get_stored_allocator() + { return m_flat_tree.get_stored_allocator(); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return m_flat_tree.begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return m_flat_tree.begin(); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return m_flat_tree.end(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return m_flat_tree.end(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return m_flat_tree.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return m_flat_tree.rbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return m_flat_tree.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return m_flat_tree.rend(); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_flat_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_flat_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_flat_tree.max_size(); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(flat_multiset& x) + { m_flat_tree.swap(x.m_flat_tree); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(const detail::moved_object >& mx) + { this->swap(mx.get()); } + #else + void swap(flat_multiset && mx) + { this->swap(mx); } + #endif + + //! Effects: Inserts x and returns the iterator pointing to the + //! newly inserted element. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(const value_type& x) + { return m_flat_tree.insert_equal(x); } + + //! Effects: Inserts a new value_type move constructed from x + //! and returns the iterator pointing to the newly inserted element. + //! + //! Complexity: Logarithmic search time plus linear insertion + //! to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(const detail::moved_object& x) + { return m_flat_tree.insert_equal(x); } + #else + iterator insert(value_type && x) + { return m_flat_tree.insert_equal(detail::move_impl(x)); } + #endif + + //! Effects: Inserts a copy of x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + iterator insert(iterator position, const value_type& x) + { return m_flat_tree.insert_equal(position, x); } + + //! Effects: Inserts a new value move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic search time (constant if x is inserted + //! right before p) plus insertion linear to the elements with bigger keys than x. + //! + //! Note: If an element it's inserted it might invalidate elements. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(iterator position, const detail::moved_object& x) + { return m_flat_tree.insert_equal(position, x); } + #else + iterator insert(iterator position, value_type && x) + { return m_flat_tree.insert_equal(position, detail::move_impl(x)); } + #endif + + //! Requires: i, j are not iterators into *this. + //! + //! Effects: inserts each element from the range [i,j) . + //! + //! Complexity: N log(size()+N) (N is the distance from i to j) + //! search time plus N*size() insertion time. + //! + //! Note: If an element it's inserted it might invalidate elements. + template + void insert(InputIterator first, InputIterator last) + { m_flat_tree.insert_equal(first, last); } + + //! Effects: Erases the element pointed to by position. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Linear to the elements with keys bigger than position + //! + //! Note: Invalidates elements with keys + //! not less than the erased element. + iterator erase(const_iterator position) + { return m_flat_tree.erase(position); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: Logarithmic search time plus erasure time + //! linear to the elements with bigger keys. + size_type erase(const key_type& x) + { return m_flat_tree.erase(x); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: size()*N where N is the distance from first to last. + //! + //! Complexity: Logarithmic search time plus erasure time + //! linear to the elements with bigger keys. + iterator erase(const_iterator first, const_iterator last) + { return m_flat_tree.erase(first, last); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_flat_tree.clear(); } + + //! Effects: Tries to deallocate the excess of memory created + // with previous allocations. The size of the vector is unchanged + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to size(). + void shrink_to_fit() + { m_flat_tree.shrink_to_fit(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return m_flat_tree.find(x); } + + //! Returns: A const_iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic.s + const_iterator find(const key_type& x) const + { return m_flat_tree.find(x); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_flat_tree.count(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + { return m_flat_tree.lower_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return m_flat_tree.lower_bound(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + { return m_flat_tree.upper_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return m_flat_tree.upper_bound(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) const + { return m_flat_tree.equal_range(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) + { return m_flat_tree.equal_range(x); } + + //! Effects: Number of elements for which memory has been allocated. + //! capacity() is always greater than or equal to size(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type capacity() const + { return m_flat_tree.capacity(); } + + //! Effects: If n is less than or equal to capacity(), this call has no + //! effect. Otherwise, it is a request for allocation of additional memory. + //! If the request is successful, then capacity() is greater than or equal to + //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged. + //! + //! Throws: If memory allocation allocation throws or T's copy constructor throws. + //! + //! Note: If capacity() is less than "count", iterators and references to + //! to values might be invalidated. + void reserve(size_type count) + { m_flat_tree.reserve(count); } + + /// @cond + template + friend bool operator== (const flat_multiset&, + const flat_multiset&); + template + friend bool operator< (const flat_multiset&, + const flat_multiset&); + /// @endcond +}; + +template +inline bool operator==(const flat_multiset& x, + const flat_multiset& y) + { return x.m_flat_tree == y.m_flat_tree; } + +template +inline bool operator<(const flat_multiset& x, + const flat_multiset& y) + { return x.m_flat_tree < y.m_flat_tree; } + +template +inline bool operator!=(const flat_multiset& x, + const flat_multiset& y) + { return !(x == y); } + +template +inline bool operator>(const flat_multiset& x, + const flat_multiset& y) + { return y < x; } + +template +inline bool operator<=(const flat_multiset& x, + const flat_multiset& y) + { return !(y < x); } + +template +inline bool operator>=(const flat_multiset& x, + const flat_multiset& y) +{ return !(x < y); } + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline void swap(flat_multiset& x, + flat_multiset& y) + { x.swap(y); } + +template +inline void swap(const detail::moved_object >& x, + flat_multiset& y) + { x.get().swap(y); } + +template +inline void swap(flat_multiset& x, + const detail::moved_object >& y) + { x.swap(y.get()); } +#else +template +inline void swap(flat_multiset&&x, + flat_multiset&&y) + { x.swap(y); } +#endif + +/// @cond + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = + has_trivial_destructor::value && + has_trivial_destructor::value }; +}; +/// @endcond + +}} //namespace boost { namespace interprocess { + +#include + +#endif /* BOOST_INTERPROCESS_FLAT_SET_HPP */ diff --git a/win32/include/boost/interprocess/containers/list.hpp b/win32/include/boost/interprocess/containers/list.hpp new file mode 100755 index 000000000..9c4c1f9e4 --- /dev/null +++ b/win32/include/boost/interprocess/containers/list.hpp @@ -0,0 +1,1339 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This file comes from SGI's stl_list.h file. Modified by Ion Gaztanaga 2004 +// Renaming, isolating and porting to generic algorithms. Pointer typedef +// set to allocator::pointer to allow placing it in shared memory. +// +/////////////////////////////////////////////////////////////////////////////// +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef BOOST_INTERPROCESS_LIST_HPP_ +#define BOOST_INTERPROCESS_LIST_HPP_ + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { + +/// @cond +namespace detail { + +template +struct list_node + : public bi::make_list_base_hook + , bi::link_mode >::type +{ + typedef typename bi::make_list_base_hook + , bi::link_mode >::type hook_type; + + list_node() + : m_data() + {} + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + list_node(const Convertible &conv) + : m_data(conv) + {} + #else + template + list_node(Convertible &&conv) + : m_data(detail::forward_impl(conv)) + {} + #endif + + T m_data; +}; + +template +struct intrusive_list_type +{ + typedef typename A::value_type value_type; + typedef typename detail::pointer_to_other + ::type void_pointer; + typedef typename detail::list_node + node_type; + typedef typename bi::make_list + < node_type + , bi::base_hook + , bi::constant_time_size + , bi::size_type + >::type container_type; + typedef container_type type ; +}; + +} //namespace detail { +/// @endcond + +//! A list is a doubly linked list. That is, it is a Sequence that supports both +//! forward and backward traversal, and (amortized) constant time insertion and +//! removal of elements at the beginning or the end, or in the middle. Lists have +//! the important property that insertion and splicing do not invalidate iterators +//! to list elements, and that even removal invalidates only the iterators that point +//! to the elements that are removed. The ordering of iterators may be changed +//! (that is, list::iterator might have a different predecessor or successor +//! after a list operation than it did before), but the iterators themselves will +//! not be invalidated or made to point to different elements unless that invalidation +//! or mutation is explicit. +template +class list + : protected detail::node_alloc_holder + ::type> +{ + /// @cond + typedef typename + detail::intrusive_list_type::type Icont; + typedef detail::node_alloc_holder AllocHolder; + typedef typename AllocHolder::NodePtr NodePtr; + typedef list ThisType; + typedef typename AllocHolder::NodeAlloc NodeAlloc; + typedef typename AllocHolder::ValAlloc ValAlloc; + typedef typename AllocHolder::Node Node; + typedef detail::allocator_destroyer Destroyer; + typedef typename AllocHolder::allocator_v1 allocator_v1; + typedef typename AllocHolder::allocator_v2 allocator_v2; + typedef typename AllocHolder::alloc_version alloc_version; + + class equal_to_value + { + typedef typename AllocHolder::value_type value_type; + const value_type &t_; + + public: + equal_to_value(const value_type &t) + : t_(t) + {} + + bool operator()(const value_type &t)const + { return t_ == t; } + }; + + template + struct ValueCompareToNodeCompare + : Pred + { + ValueCompareToNodeCompare(Pred pred) + : Pred(pred) + {} + + bool operator()(const Node &a, const Node &b) const + { return static_cast(*this)(a.m_data, b.m_data); } + + bool operator()(const Node &a) const + { return static_cast(*this)(a.m_data); } + }; + /// @endcond + + public: + //! The type of object, T, stored in the list + typedef T value_type; + //! Pointer to T + typedef typename A::pointer pointer; + //! Const pointer to T + typedef typename A::const_pointer const_pointer; + //! Reference to T + typedef typename A::reference reference; + //! Const reference to T + typedef typename A::const_reference const_reference; + //! An unsigned integral type + typedef typename A::size_type size_type; + //! A signed integral type + typedef typename A::difference_type difference_type; + //! The allocator type + typedef A allocator_type; + //! The stored allocator type + typedef NodeAlloc stored_allocator_type; + + /// @cond + private: + typedef difference_type list_difference_type; + typedef pointer list_pointer; + typedef const_pointer list_const_pointer; + typedef reference list_reference; + typedef const_reference list_const_reference; + /// @endcond + + public: + //! Const iterator used to iterate through a list. + class const_iterator + /// @cond + : public std::iterator + { + + protected: + typename Icont::iterator m_it; + explicit const_iterator(typename Icont::iterator it) : m_it(it){} + void prot_incr() { ++m_it; } + void prot_decr() { --m_it; } + + private: + typename Icont::iterator get() + { return this->m_it; } + + public: + friend class list; + typedef list_difference_type difference_type; + + //Constructors + const_iterator() + : m_it() + {} + + //Pointer like operators + const_reference operator*() const + { return m_it->m_data; } + + const_pointer operator->() const + { return const_pointer(&m_it->m_data); } + + //Increment / Decrement + const_iterator& operator++() + { prot_incr(); return *this; } + + const_iterator operator++(int) + { typename Icont::iterator tmp = m_it; ++*this; return const_iterator(tmp); } + + const_iterator& operator--() + { prot_decr(); return *this; } + + const_iterator operator--(int) + { typename Icont::iterator tmp = m_it; --*this; return const_iterator(tmp); } + + //Comparison operators + bool operator== (const const_iterator& r) const + { return m_it == r.m_it; } + + bool operator!= (const const_iterator& r) const + { return m_it != r.m_it; } + } + /// @endcond + ; + + //! Iterator used to iterate through a list + class iterator + /// @cond + : public const_iterator + { + + private: + explicit iterator(typename Icont::iterator it) + : const_iterator(it) + {} + + typename Icont::iterator get() + { return this->m_it; } + + public: + friend class list; + typedef list_pointer pointer; + typedef list_reference reference; + + //Constructors + iterator(){} + + //Pointer like operators + reference operator*() const { return this->m_it->m_data; } + pointer operator->() const { return pointer(&this->m_it->m_data); } + + //Increment / Decrement + iterator& operator++() + { this->prot_incr(); return *this; } + + iterator operator++(int) + { typename Icont::iterator tmp = this->m_it; ++*this; return iterator(tmp); } + + iterator& operator--() + { this->prot_decr(); return *this; } + + iterator operator--(int) + { iterator tmp = *this; --*this; return tmp; } + } + /// @endcond + ; + + //! Iterator used to iterate backwards through a list. + typedef std::reverse_iterator reverse_iterator; + //! Const iterator used to iterate backwards through a list. + typedef std::reverse_iterator const_reverse_iterator; + + //! Effects: Constructs a list taking the allocator as parameter. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + explicit list(const allocator_type &a = A()) + : AllocHolder(a) + {} + +// list(size_type n) +// : AllocHolder(detail::move_impl(allocator_type())) +// { this->resize(n); } + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + list(size_type n, const T& value = T(), const A& a = A()) + : AllocHolder(a) + { this->insert(begin(), n, value); } + + //! Effects: Copy constructs a list. + //! + //! Postcondition: x == *this. + //! + //! Throws: If allocator_type's default constructor or copy constructor throws. + //! + //! Complexity: Linear to the elements x contains. + list(const list& x) + : AllocHolder(x) + { this->insert(begin(), x.begin(), x.end()); } + + //! Effects: Move constructor. Moves mx's resources to *this. + //! + //! Throws: If allocator_type's default constructor throws. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + list(const detail::moved_object &x) + : AllocHolder(detail::move_impl((AllocHolder&)x.get())) + {} + #else + list(list &&x) + : AllocHolder(detail::move_impl((AllocHolder&)x)) + {} + #endif + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts a copy of the range [first, last) in the list. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's constructor taking an dereferenced InIt throws. + //! + //! Complexity: Linear to the range [first, last). + template + list(InpIt first, InpIt last, const A &a = A()) + : AllocHolder(a) + { insert(begin(), first, last); } + + //! Effects: Destroys the list. All stored values are destroyed + //! and used memory is deallocated. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements. + ~list() + { this->clear(); } + + //! Effects: Returns a copy of the internal allocator. + //! + //! Throws: If allocator's copy constructor throws. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return allocator_type(this->node_alloc()); } + + const stored_allocator_type &get_stored_allocator() const + { return this->node_alloc(); } + + stored_allocator_type &get_stored_allocator() + { return this->node_alloc(); } + + //! Effects: Erases all the elements of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements in the list. + void clear() + { AllocHolder::clear(alloc_version()); } + + //! Effects: Returns an iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return iterator(this->icont().begin()); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return const_iterator(this->non_const_icont().begin()); } + + //! Effects: Returns an iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return iterator(this->icont().end()); } + + //! Effects: Returns a const_iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return const_iterator(this->non_const_icont().end()); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return reverse_iterator(end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return const_reverse_iterator(end()); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return reverse_iterator(begin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return const_reverse_iterator(begin()); } + + //! Effects: Returns true if the list contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return !this->size(); } + + //! Effects: Returns the number of the elements contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return this->icont().size(); } + + //! Effects: Returns the largest possible size of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return AllocHolder::max_size(); } + + //! Effects: Inserts a copy of t in the beginning of the list. + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + void push_front(const T& x) + { this->insert(this->begin(), x); } + + //! Effects: Constructs a new element in the beginning of the list + //! and moves the resources of t to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void push_front(const detail::moved_object& x) + { this->insert(this->begin(), x); } + #else + void push_front(T &&x) + { this->insert(this->begin(), detail::move_impl(x)); } + #endif + + //! Effects: Removes the last element from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Amortized constant time. + void push_back (const T& x) + { this->insert(this->end(), x); } + + //! Effects: Removes the first element from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Amortized constant time. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void push_back (const detail::moved_object& x) + { this->insert(this->end(), x); } + #else + void push_back (T &&x) + { this->insert(this->end(), detail::move_impl(x)); } + #endif + + //! Effects: Removes the first element from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Amortized constant time. + void pop_front() + { this->erase(this->begin()); } + + //! Effects: Removes the last element from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Amortized constant time. + void pop_back() + { iterator tmp = this->end(); this->erase(--tmp); } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference front() + { return *this->begin(); } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference front() const + { return *this->begin(); } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference back() + { return *(--this->end()); } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference back() const + { return *(--this->end()); } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are copy constructed from x. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size, const T& x) + { + iterator iend = this->end(); + size_type len = this->size(); + + if(len > new_size){ + size_type to_erase = len - new_size; + while(to_erase--){ + --iend; + } + this->erase(iend, this->end()); + } + else{ + this->priv_create_and_insert_nodes(iend, new_size - len, x); + } + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are default constructed. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size) + { + iterator iend = this->end(); + size_type len = this->size(); + + if(len > new_size){ + size_type to_erase = len - new_size; + iterator ifirst; + if(to_erase < len/2u){ + ifirst = iend; + while(to_erase--){ + --ifirst; + } + } + else{ + ifirst = this->begin(); + size_type to_skip = len - to_erase; + while(to_skip--){ + ++ifirst; + } + } + this->erase(ifirst, iend); + } + else{ + this->priv_create_and_insert_nodes(this->end(), new_size - len); + } + } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() + //! allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(ThisType& x) + { AllocHolder::swap(x); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() + //! allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //void swap(const detail::moved_object& x) + //{ this->swap(x.get()); } + + //! Effects: Makes *this contain the same elements as x. + //! + //! Postcondition: this->size() == x.size(). *this contains a copy + //! of each of x's elements. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to the number of elements in x. + ThisType& operator=(const ThisType& x) + { + if (this != &x) { + this->assign(x.begin(), x.end()); + } + return *this; + } + + //! Effects: Move assignment. All mx's values are transferred to *this. + //! + //! Postcondition: x.empty(). *this contains a the elements x had + //! before the function. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + ThisType& operator=(const detail::moved_object& mx) + { + this->clear(); + this->swap(mx.get()); + return *this; + } + #else + ThisType& operator=(ThisType &&mx) + { + this->clear(); + this->swap(mx); + return *this; + } + #endif + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Inserts n copies of x before p. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void insert(iterator p, size_type n, const T& x) + { this->priv_create_and_insert_nodes(p, n, x); } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a copy of the [first, last) range before p. + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced InpIt throws. + //! + //! Complexity: Linear to std::distance [first, last). + template + void insert(iterator p, InpIt first, InpIt last) + { + const bool aux_boolean = detail::is_convertible::value; + typedef detail::bool_ Result; + this->priv_insert_dispatch(p, first, last, Result()); + } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a copy of x before p. + //! + //! Throws: If memory allocation throws or x's copy constructor throws. + //! + //! Complexity: Amortized constant time. + iterator insert(iterator p, const T& x) + { + NodePtr tmp = AllocHolder::create_node(x); + return iterator(this->icont().insert(p.get(), *tmp)); + } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a new element before p with mx's resources. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(iterator p, const detail::moved_object& x) + { + NodePtr tmp = AllocHolder::create_node(x); + return iterator(this->icont().insert(p.get(), *tmp)); + } + #else + iterator insert(iterator p, T &&x) + { + NodePtr tmp = AllocHolder::create_node(detail::move_impl(x)); + return iterator(this->icont().insert(p.get(), *tmp)); + } + #endif + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Erases the element at p p. + //! + //! Throws: Nothing. + //! + //! Complexity: Amortized constant time. + iterator erase(iterator p) + { return iterator(this->icont().erase_and_dispose(p.get(), Destroyer(this->node_alloc()))); } + + //! Requires: first and last must be valid iterator to elements in *this. + //! + //! Effects: Erases the elements pointed by [first, last). + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the distance between first and last. + iterator erase(iterator first, iterator last) + { return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); } + + //! Effects: Assigns the n copies of val to *this. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void assign(size_type n, const T& val) + { this->priv_fill_assign(n, val); } + + //! Effects: Assigns the the range [first, last) to *this. + //! + //! Throws: If memory allocation throws or + //! T's constructor from dereferencing InpIt throws. + //! + //! Complexity: Linear to n. + template + void assign(InpIt first, InpIt last) + { + const bool aux_boolean = detail::is_convertible::value; + typedef detail::bool_ Result; + this->priv_assign_dispatch(first, last, Result()); + } + + //! Requires: p must point to an element contained + //! by the list. x != *this + //! + //! Effects: Transfers all the elements of list x to this list, before the + //! the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of + //! this list. Iterators of this list and all the references are not invalidated. + void splice(iterator p, ThisType& x) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().splice(p.get(), x.icont()); + } + else{ + throw std::runtime_error("list::splice called with unequal allocators"); + } + } + +// void splice(iterator p, const detail::moved_object& x) +// { this->splice(p, x.get()); } + + //! Requires: p must point to an element contained + //! by this list. i must point to an element contained in list x. + //! + //! Effects: Transfers the value pointed by i, from list x to this list, + //! before the the element pointed by p. No destructors or copy constructors are called. + //! If p == i or p == ++i, this function is a null operation. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(iterator p, ThisType &x, iterator i) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().splice(p.get(), x.icont(), i.get()); + } + else{ + throw std::runtime_error("list::splice called with unequal allocators"); + } + } + +// void splice(iterator p, const detail::moved_object &x, iterator i) +// { this->splice(p, x.get(), i); } + + //! Requires: p must point to an element contained + //! by this list. first and last must point to elements contained in list x. + //! + //! Effects: Transfers the range pointed by first and last from list x to this list, + //! before the the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Linear to the number of elements transferred. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(iterator p, ThisType &x, iterator first, iterator last) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().splice(p.get(), x.icont(), first.get(), last.get()); + } + else{ + throw std::runtime_error("list::splice called with unequal allocators"); + } + } + +// void splice(iterator p, detail::moved_object &x, iterator first, iterator last) +// { return this->splice(p, x.get(), first, last); } + + //! Requires: p must point to an element contained + //! by this list. first and last must point to elements contained in list x. + //! n == std::distance(first, last) + //! + //! Effects: Transfers the range pointed by first and last from list x to this list, + //! before the the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(iterator p, ThisType &x, iterator first, iterator last, size_type n) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().splice(p.get(), x.icont(), first.get(), last.get(), n); + } + else{ + throw std::runtime_error("list::splice called with unequal allocators"); + } + } + +// void splice(iterator p, detail::moved_object &x, iterator first, iterator last, size_type n) +// { return this->splice(p, x.get(), first, last, n); } + + //! Effects: Reverses the order of elements in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time. + //! + //! Note: Iterators and references are not invalidated + void reverse() + { this->icont().reverse(); } + + //! Effects: Removes all the elements that compare equal to value. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear time. It performs exactly size() comparisons for equality. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + void remove(const T& value) + { remove_if(equal_to_value(value)); } + + //! Effects: Removes all the elements for which a specified + //! predicate is satisfied. + //! + //! Throws: If pred throws. + //! + //! Complexity: Linear time. It performs exactly size() calls to the predicate. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void remove_if(Pred pred) + { + typedef ValueCompareToNodeCompare Predicate; + this->icont().remove_and_dispose_if(Predicate(pred), Destroyer(this->node_alloc())); + } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that are equal from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear time (size()-1 comparisons calls to pred()). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + void unique() + { this->unique(value_equal()); } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that satisfy some binary predicate from the list. + //! + //! Throws: If pred throws. + //! + //! Complexity: Linear time (size()-1 comparisons equality comparisons). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void unique(BinaryPredicate binary_pred) + { + typedef ValueCompareToNodeCompare Predicate; + this->icont().unique_and_dispose(Predicate(binary_pred), Destroyer(this->node_alloc())); + } + + //! Requires: The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this according to std::less. The merge is stable; + //! that is, if an element from *this is equivalent to one from x, then the element + //! from *this will precede the one from x. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + void merge(list& x) + { this->merge(x, value_less()); } + + //! Effects: This function removes all of moved mx's elements and inserts them + //! in order into *this according to std::less. The merge is stable; + //! that is, if an element from *this is equivalent to one from x, then the element + //! from *this will precede the one from x. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references to *this are not invalidated. + //void merge(const detail::moved_object >& x) + //{ this->merge(x.get()); } + + //! Requires: p must be a comparison function that induces a strict weak + //! ordering and both *this and x must be sorted according to that ordering + //! The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this. The merge is stable; that is, if an element from *this is + //! equivalent to one from x, then the element from *this will precede the one from x. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references to *this are not invalidated. + template + void merge(list& x, StrictWeakOrdering comp) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().merge(x.icont(), + ValueCompareToNodeCompare(comp)); + } + else{ + throw std::runtime_error("list::merge called with unequal allocators"); + } + } + + //! Requires: p must be a comparison function that induces a strict weak + //! ordering and both *this and x must be sorted according to that ordering + //! The lists x and *this must be distinct. + //! + //! Effects: This function removes all of moved mx's elements and inserts them + //! in order into *this. The merge is stable; that is, if an element from *this is + //! equivalent to one from x, then the element from *this will precede the one from x. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references to *this are not invalidated. + //template + //void merge(const detail::moved_object >& x, StrictWeakOrdering comp) + //{ return this->merge(x.get(), comp); } + + //! Effects: This function sorts the list *this according to std::less. + //! The sort is stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: Nothing. + //! + //! Notes: Iterators and references are not invalidated. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + void sort() + { this->sort(value_less()); } + + //! Effects: This function sorts the list *this according to std::less. + //! The sort is stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: Nothing. + //! + //! Notes: Iterators and references are not invalidated. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + template + void sort(StrictWeakOrdering comp) + { + // nothing if the list has length 0 or 1. + if (this->size() < 2) + return; + this->icont().sort(ValueCompareToNodeCompare(comp)); + } + + /// @cond + private: + + //Iterator range version + template + void priv_create_and_insert_nodes + (const_iterator pos, InpIterator beg, InpIterator end) + { + typedef typename std::iterator_traits::iterator_category ItCat; + priv_create_and_insert_nodes(pos, beg, end, alloc_version(), ItCat()); + } + + template + void priv_create_and_insert_nodes + (const_iterator pos, InpIterator beg, InpIterator end, allocator_v1, std::input_iterator_tag) + { + for (; beg != end; ++beg){ + this->icont().insert(pos.get(), *this->create_node_from_it(beg)); + } + } + + template + void priv_create_and_insert_nodes + (const_iterator pos, InpIterator beg, InpIterator end, allocator_v2, std::input_iterator_tag) + { //Just forward to the default one + priv_create_and_insert_nodes(pos, beg, end, allocator_v1(), std::input_iterator_tag()); + } + + class insertion_functor; + friend class insertion_functor; + + class insertion_functor + { + Icont &icont_; + typename Icont::iterator pos_; + + public: + insertion_functor(Icont &icont, typename Icont::iterator pos) + : icont_(icont), pos_(pos) + {} + + void operator()(Node &n) + { this->icont_.insert(pos_, n); } + }; + + + template + void priv_create_and_insert_nodes + (const_iterator pos, FwdIterator beg, FwdIterator end, allocator_v2, std::forward_iterator_tag) + { + //Optimized allocation and construction + this->allocate_many_and_construct + (beg, std::distance(beg, end), insertion_functor(this->icont(), pos.get())); + } + + //Default constructed version + void priv_create_and_insert_nodes(const_iterator pos, size_type n) + { + typedef default_construct_iterator default_iterator; + this->priv_create_and_insert_nodes(pos, default_iterator(n), default_iterator()); + } + + //Copy constructed version + void priv_create_and_insert_nodes(const_iterator pos, size_type n, const T& x) + { + typedef constant_iterator cvalue_iterator; + this->priv_create_and_insert_nodes(pos, cvalue_iterator(x, n), cvalue_iterator()); + } + + //Dispatch to detect iterator range or integer overloads + template + void priv_insert_dispatch(iterator p, + InputIter first, InputIter last, + detail::false_) + { this->priv_create_and_insert_nodes(p, first, last); } + + template + void priv_insert_dispatch(iterator p, Integer n, Integer x, detail::true_) + { this->insert(p, (size_type)n, x); } + + void priv_fill_assign(size_type n, const T& val) + { + iterator i = this->begin(), iend = this->end(); + + for ( ; i != iend && n > 0; ++i, --n) + *i = val; + if (n > 0){ + this->priv_create_and_insert_nodes(this->end(), n, val); + } + else{ + this->erase(i, end()); + } + } + + template + void priv_assign_dispatch(Integer n, Integer val, detail::true_) + { this->priv_fill_assign((size_type) n, (T) val); } + + template + void priv_assign_dispatch(InputIter first2, InputIter last2, + detail::false_) + { + iterator first1 = this->begin(); + iterator last1 = this->end(); + for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) + *first1 = *first2; + if (first2 == last2) + this->erase(first1, last1); + else{ + this->priv_create_and_insert_nodes(last1, first2, last2); + } + } + + //Functors for member algorithm defaults + struct value_less + { + bool operator()(const value_type &a, const value_type &b) const + { return a < b; } + }; + + struct value_equal + { + bool operator()(const value_type &a, const value_type &b) const + { return a == b; } + }; + /// @endcond + +}; + +template +inline bool operator==(const list& x, const list& y) +{ + if(x.size() != y.size()){ + return false; + } + typedef typename list::const_iterator const_iterator; + const_iterator end1 = x.end(); + + const_iterator i1 = x.begin(); + const_iterator i2 = y.begin(); + while (i1 != end1 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1; +} + +template +inline bool operator<(const list& x, + const list& y) +{ + return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); +} + +template +inline bool operator!=(const list& x, const list& y) +{ + return !(x == y); +} + +template +inline bool operator>(const list& x, const list& y) +{ + return y < x; +} + +template +inline bool operator<=(const list& x, const list& y) +{ + return !(y < x); +} + +template +inline bool operator>=(const list& x, const list& y) +{ + return !(x < y); +} + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline void swap(list& x, list& y) +{ + x.swap(y); +} + +template +inline void swap(const detail::moved_object >& x, list& y) +{ + x.get().swap(y); +} + +template +inline void swap(list& x, const detail::moved_object >& y) +{ + x.swap(y.get()); +} +#else +template +inline void swap(list &&x, list &&y) +{ + x.swap(y); +} + +#endif + +/// @cond + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; +/* +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; +*/ +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = has_trivial_destructor::value }; +}; +/// @endcond + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // BOOST_INTERPROCESS_LIST_HPP_ diff --git a/win32/include/boost/interprocess/containers/map.hpp b/win32/include/boost/interprocess/containers/map.hpp new file mode 100755 index 000000000..da44b3ce5 --- /dev/null +++ b/win32/include/boost/interprocess/containers/map.hpp @@ -0,0 +1,1241 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This file comes from SGI's stl_map/stl_multimap files. Modified by Ion Gaztanaga. +// Renaming, isolating and porting to generic algorithms. Pointer typedef +// set to allocator::pointer to allow placing it in shared memory. +// +/////////////////////////////////////////////////////////////////////////////// +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef BOOST_INTERPROCESS_MAP_HPP +#define BOOST_INTERPROCESS_MAP_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace interprocess { + +/// @cond +// Forward declarations of operators == and <, needed for friend declarations. +template +inline bool operator==(const map& x, + const map& y); + +template +inline bool operator<(const map& x, + const map& y); +/// @endcond + +//! A map is a kind of associative container that supports unique keys (contains at +//! most one of each key value) and provides for fast retrieval of values of another +//! type T based on the keys. The map class supports bidirectional iterators. +//! +//! A map satisfies all of the requirements of a container and of a reversible +//! container and of an associative container. For a +//! map the key_type is Key and the value_type is std::pair. +//! +//! Pred is the ordering function for Keys (e.g. std::less). +//! +//! Alloc is the allocator to allocate the value_types +//! (e.g. boost::interprocess:allocator< std::pair). +template +class map +{ + /// @cond + private: + typedef detail::rbtree, + detail::select1st< std::pair >, + Pred, + Alloc> tree_t; + tree_t m_tree; // red-black tree representing map + /// @endcond + + public: + // typedefs: + typedef typename tree_t::key_type key_type; + typedef typename tree_t::value_type value_type; + typedef typename tree_t::pointer pointer; + typedef typename tree_t::const_pointer const_pointer; + typedef typename tree_t::reference reference; + typedef typename tree_t::const_reference const_reference; + typedef T mapped_type; + typedef Pred key_compare; + typedef typename tree_t::iterator iterator; + typedef typename tree_t::const_iterator const_iterator; + typedef typename tree_t::reverse_iterator reverse_iterator; + typedef typename tree_t::const_reverse_iterator const_reverse_iterator; + typedef typename tree_t::size_type size_type; + typedef typename tree_t::difference_type difference_type; + typedef typename tree_t::allocator_type allocator_type; + typedef typename tree_t::stored_allocator_type stored_allocator_type; + + /// @cond + class value_compare_impl + : public Pred, + public std::binary_function + { + friend class map; + protected : + value_compare_impl(const Pred &c) : Pred(c) {} + public: + bool operator()(const value_type& x, const value_type& y) const { + return Pred::operator()(x.first, y.first); + } + }; + /// @endcond + typedef value_compare_impl value_compare; + + //! Effects: Constructs an empty map using the specified comparison object + //! and allocator. + //! + //! Complexity: Constant. + explicit map(const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(comp, a) + {} + + //! Effects: Constructs an empty map using the specified comparison object and + //! allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + map(InputIterator first, InputIterator last, const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(first, last, comp, a, true) + {} + + //! Effects: Copy constructs a map. + //! + //! Complexity: Linear in x.size(). + map(const map& x) + : m_tree(x.m_tree) + {} + + //! Effects: Move constructs a map. Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + map(const detail::moved_object >& x) + : m_tree(detail::move_impl(x.get().m_tree)) + {} + #else + map(map &&x) + : m_tree(detail::move_impl(x.m_tree)) + {} + #endif + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + map& operator=(const map& x) + { m_tree = x.m_tree; return *this; } + + //! Effects: this->swap(x.get()). + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + map& operator=(const detail::moved_object >& x) + { m_tree = detail::move_impl(x.get().m_tree); return *this; } + #else + map& operator=(map &&x) + { m_tree = detail::move_impl(x.m_tree); return *this; } + #endif + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return m_tree.key_comp(); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return value_compare(m_tree.key_comp()); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return m_tree.get_allocator(); } + + const stored_allocator_type &get_stored_allocator() const + { return m_tree.get_stored_allocator(); } + + stored_allocator_type &get_stored_allocator() + { return m_tree.get_stored_allocator(); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return m_tree.begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return m_tree.begin(); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return m_tree.end(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return m_tree.end(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return m_tree.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return m_tree.rbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return m_tree.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return m_tree.rend(); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_tree.max_size(); } + + //! Effects: If there is no key equivalent to x in the map, inserts + //! value_type(x, T()) into the map. + //! + //! Returns: A reference to the mapped_type corresponding to x in *this. + //! + //! Complexity: Logarithmic. + T& operator[](const key_type& k) + { + //we can optimize this + iterator i = lower_bound(k); + // i->first is greater than or equivalent to k. + if (i == end() || key_comp()(k, (*i).first)){ + value_type val(k, detail::move_impl(T())); + i = insert(i, detail::move_impl(val)); + } + return (*i).second; + } + + //! Effects: If there is no key equivalent to x in the map, inserts + //! value_type(detail::move_impl(x), T()) into the map (the key is move-constructed) + //! + //! Returns: A reference to the mapped_type corresponding to x in *this. + //! + //! Complexity: Logarithmic. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + T& operator[](const detail::moved_object& mk) + { + key_type &k = mk.get(); + //we can optimize this + iterator i = lower_bound(k); + // i->first is greater than or equivalent to k. + if (i == end() || key_comp()(k, (*i).first)){ + value_type val(k, detail::move_impl(T())); + i = insert(i, detail::move_impl(val)); + } + return (*i).second; + } + #else + T& operator[](key_type &&mk) + { + key_type &k = mk; + //we can optimize this + iterator i = lower_bound(k); + // i->first is greater than or equivalent to k. + if (i == end() || key_comp()(k, (*i).first)){ + value_type val(detail::move_impl(k), detail::move_impl(T())); + i = insert(i, detail::move_impl(val)); + } + return (*i).second; + } + #endif + +/* + //! Effects: If there is no key equivalent to x in the map, inserts + //! value_type(detail::move_impl(x), T()) into the map (the key is move-constructed) + //! + //! Returns: A reference to the mapped_type corresponding to x in *this. + //! + //! Complexity: Logarithmic. + T& at(const key_type& x) + { + if(this->find(x) == this->end()){ + + } + key_type &k = mk.get(); + //we can optimize this + iterator i = lower_bound(k); + // i->first is greater than or equivalent to k. + if (i == end() || key_comp()(k, (*i).first)){ + value_type val(k, detail::move_impl(T())); + i = insert(i, detail::move_impl(val)); + } + return (*i).second; + } + +//; +//const T& at(const key_type& x) const; +//4 Returns: A reference to the element whose key is equivalent to x. +//5 Throws: An exception object of type out_of_range if no such element is present. +*/ + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(map& x) + { m_tree.swap(x.m_tree); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(const detail::moved_object >& x) + { m_tree.swap(x.get().m_tree); } + #else + void swap(map &&x) + { m_tree.swap(x.m_tree); } + #endif + + //! Effects: Inserts x if and only if there is no element in the container + //! with key equivalent to the key of x. + //! + //! Returns: The bool component of the returned pair is true if and only + //! if the insertion takes place, and the iterator component of the pair + //! points to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic. + std::pair insert(const value_type& x) + { return m_tree.insert_unique(x); } + + //! Effects: Inserts a new value_type created from the pair if and only if + //! there is no element in the container with key equivalent to the key of x. + //! + //! Returns: The bool component of the returned pair is true if and only + //! if the insertion takes place, and the iterator component of the pair + //! points to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic. + std::pair insert(const std::pair& x) + { return m_tree.insert_unique(x); } + + //! Effects: Inserts a new value_type move constructed from the pair if and + //! only if there is no element in the container with key equivalent to the key of x. + //! + //! Returns: The bool component of the returned pair is true if and only + //! if the insertion takes place, and the iterator component of the pair + //! points to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + std::pair insert(const detail::moved_object > &x) + { return m_tree.insert_unique(x); } + #else + std::pair insert(std::pair &&x) + { return m_tree.insert_unique(detail::move_impl(x)); } + #endif + + //! Effects: Move constructs a new value from x if and only if there is + //! no element in the container with key equivalent to the key of x. + //! + //! Returns: The bool component of the returned pair is true if and only + //! if the insertion takes place, and the iterator component of the pair + //! points to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + std::pair insert(const detail::moved_object& x) + { return m_tree.insert_unique(x); } + #else + std::pair insert(value_type &&x) + { return m_tree.insert_unique(detail::move_impl(x)); } + #endif + + //! Effects: Inserts a copy of x in the container if and only if there is + //! no element in the container with key equivalent to the key of x. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + iterator insert(iterator position, const value_type& x) + { return m_tree.insert_unique(position, x); } + + //! Effects: Move constructs a new value from x if and only if there is + //! no element in the container with key equivalent to the key of x. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(iterator position, const detail::moved_object > &x) + { return m_tree.insert_unique(position, x); } + #else + iterator insert(iterator position, std::pair &&x) + { return m_tree.insert_unique(position, detail::move_impl(x)); } + #endif + + //! Effects: Inserts a copy of x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic. + iterator insert(iterator position, const std::pair& x) + { return m_tree.insert_unique(position, x); } + + //! Effects: Inserts an element move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(iterator position, const detail::moved_object& x) + { return m_tree.insert_unique(position, x); } + #else + iterator insert(iterator position, value_type &&x) + { return m_tree.insert_unique(position, detail::move_impl(x)); } + #endif + + //! Requires: i, j are not iterators into *this. + //! + //! Effects: inserts each element from the range [i,j) if and only + //! if there is no element with key equivalent to the key of that element. + //! + //! Complexity: N log(size()+N) (N is the distance from i to j) + template + void insert(InputIterator first, InputIterator last) + { m_tree.insert_unique(first, last); } + + //! Effects: Erases the element pointed to by position. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Amortized constant time + iterator erase(const_iterator position) + { return m_tree.erase(position); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: log(size()) + count(k) + size_type erase(const key_type& x) + { return m_tree.erase(x); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: log(size())+N where N is the distance from first to last. + iterator erase(const_iterator first, const_iterator last) + { return m_tree.erase(first, last); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_tree.clear(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return m_tree.find(x); } + + //! Returns: A const_iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + const_iterator find(const key_type& x) const + { return m_tree.find(x); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_tree.find(x) == m_tree.end() ? 0 : 1; } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + { return m_tree.lower_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return m_tree.lower_bound(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + { return m_tree.upper_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return m_tree.upper_bound(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair equal_range(const key_type& x) + { return m_tree.equal_range(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair equal_range(const key_type& x) const + { return m_tree.equal_range(x); } + + /// @cond + template + friend bool operator== (const map&, + const map&); + template + friend bool operator< (const map&, + const map&); + /// @endcond +}; + +template +inline bool operator==(const map& x, + const map& y) + { return x.m_tree == y.m_tree; } + +template +inline bool operator<(const map& x, + const map& y) + { return x.m_tree < y.m_tree; } + +template +inline bool operator!=(const map& x, + const map& y) + { return !(x == y); } + +template +inline bool operator>(const map& x, + const map& y) + { return y < x; } + +template +inline bool operator<=(const map& x, + const map& y) + { return !(y < x); } + +template +inline bool operator>=(const map& x, + const map& y) + { return !(x < y); } + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline void swap(map& x, + map& y) + { x.swap(y); } + +template +inline void swap(const detail::moved_object >& x, + map& y) + { x.get().swap(y); } + +template +inline void swap(map& x, + const detail::moved_object >& y) + { x.swap(y.get()); } +#else +template +inline void swap(map&&x, + map&&y) + { x.swap(y); } +#endif + + +/// @cond + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +// Forward declaration of operators < and ==, needed for friend declaration. + +template +inline bool operator==(const multimap& x, + const multimap& y); + +template +inline bool operator<(const multimap& x, + const multimap& y); + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = + has_trivial_destructor::value && + has_trivial_destructor::value }; +}; +/// @endcond + +//! A multimap is a kind of associative container that supports equivalent keys +//! (possibly containing multiple copies of the same key value) and provides for +//! fast retrieval of values of another type T based on the keys. The multimap class +//! supports bidirectional iterators. +//! +//! A multimap satisfies all of the requirements of a container and of a reversible +//! container and of an associative container. For a +//! map the key_type is Key and the value_type is std::pair. +//! +//! Pred is the ordering function for Keys (e.g. std::less). +//! +//! Alloc is the allocator to allocate the value_types +//!(e.g. boost::interprocess:allocator< std::pair<const Key, T>). +template +class multimap +{ + /// @cond + private: + typedef detail::rbtree, + detail::select1st< std::pair >, + Pred, + Alloc> tree_t; + tree_t m_tree; // red-black tree representing map + /// @endcond + + public: + // typedefs: + typedef typename tree_t::key_type key_type; + typedef typename tree_t::value_type value_type; + typedef typename tree_t::pointer pointer; + typedef typename tree_t::const_pointer const_pointer; + typedef typename tree_t::reference reference; + typedef typename tree_t::const_reference const_reference; + typedef T mapped_type; + typedef Pred key_compare; + typedef typename tree_t::iterator iterator; + typedef typename tree_t::const_iterator const_iterator; + typedef typename tree_t::reverse_iterator reverse_iterator; + typedef typename tree_t::const_reverse_iterator const_reverse_iterator; + typedef typename tree_t::size_type size_type; + typedef typename tree_t::difference_type difference_type; + typedef typename tree_t::allocator_type allocator_type; + typedef typename tree_t::stored_allocator_type stored_allocator_type; + + /// @cond + class value_compare_impl + : public Pred, + public std::binary_function + { + friend class multimap; + protected : + value_compare_impl(const Pred &c) : Pred(c) {} + public: + bool operator()(const value_type& x, const value_type& y) const { + return Pred::operator()(x.first, y.first); + } + }; + /// @endcond + typedef value_compare_impl value_compare; + + //! Effects: Constructs an empty multimap using the specified comparison + //! object and allocator. + //! + //! Complexity: Constant. + explicit multimap(const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(comp, a) + {} + + //! Effects: Constructs an empty multimap using the specified comparison object + //! and allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + multimap(InputIterator first, InputIterator last, + const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(first, last, comp, a, false) + {} + + //! Effects: Copy constructs a multimap. + //! + //! Complexity: Linear in x.size(). + multimap(const multimap& x) + : m_tree(x.m_tree) + {} + + //! Effects: Move constructs a multimap. Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + multimap(const detail::moved_object >& x) + : m_tree(detail::move_impl(x.get().m_tree)) + {} + #else + multimap(multimap && x) + : m_tree(detail::move_impl(x.m_tree)) + {} + #endif + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + multimap& + operator=(const multimap& x) + { m_tree = x.m_tree; return *this; } + + //! Effects: this->swap(x.get()). + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + multimap& + operator=(const detail::moved_object >& x) + { m_tree = detail::move_impl(x.get().m_tree); return *this; } + #else + multimap& + operator=(multimap && x) + { m_tree = detail::move_impl(x.m_tree); return *this; } + #endif + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return m_tree.key_comp(); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return value_compare(m_tree.key_comp()); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return m_tree.get_allocator(); } + + const stored_allocator_type &get_stored_allocator() const + { return m_tree.get_stored_allocator(); } + + stored_allocator_type &get_stored_allocator() + { return m_tree.get_stored_allocator(); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return m_tree.begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return m_tree.begin(); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return m_tree.end(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return m_tree.end(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return m_tree.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return m_tree.rbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return m_tree.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return m_tree.rend(); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_tree.max_size(); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(multimap& x) + { m_tree.swap(x.m_tree); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(const detail::moved_object >& x) + { m_tree.swap(x.get().m_tree); } + #else + void swap(multimap && x) + { m_tree.swap(x.m_tree); } + #endif + + //! Effects: Inserts x and returns the iterator pointing to the + //! newly inserted element. + //! + //! Complexity: Logarithmic. + iterator insert(const value_type& x) + { return m_tree.insert_equal(x); } + + //! Effects: Inserts a new value constructed from x and returns + //! the iterator pointing to the newly inserted element. + //! + //! Complexity: Logarithmic. + iterator insert(const std::pair& x) + { return m_tree.insert_equal(x); } + + //! Effects: Inserts a new value move-constructed from x and returns + //! the iterator pointing to the newly inserted element. + //! + //! Complexity: Logarithmic. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(const detail::moved_object >& x) + { return m_tree.insert_equal(x); } + #else + iterator insert(std::pair && x) + { return m_tree.insert_equal(detail::move_impl(x)); } + #endif + + //! Effects: Inserts a copy of x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + iterator insert(iterator position, const value_type& x) + { return m_tree.insert_equal(position, x); } + + //! Effects: Inserts a new value constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + iterator insert(iterator position, const std::pair& x) + { return m_tree.insert_equal(position, x); } + + //! Effects: Inserts a new value move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(iterator position, const detail::moved_object >& x) + { return m_tree.insert_equal(position, x); } + #else + iterator insert(iterator position, std::pair && x) + { return m_tree.insert_equal(position, detail::move_impl(x)); } + #endif + + //! Requires: i, j are not iterators into *this. + //! + //! Effects: inserts each element from the range [i,j) . + //! + //! Complexity: N log(size()+N) (N is the distance from i to j) + template + void insert(InputIterator first, InputIterator last) + { m_tree.insert_equal(first, last); } + + //! Effects: Erases the element pointed to by position. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Amortized constant time + iterator erase(const_iterator position) + { return m_tree.erase(position); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: log(size()) + count(k) + size_type erase(const key_type& x) + { return m_tree.erase(x); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: log(size())+N where N is the distance from first to last. + iterator erase(const_iterator first, const_iterator last) + { return m_tree.erase(first, last); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_tree.clear(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return m_tree.find(x); } + + //! Returns: A const iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + const_iterator find(const key_type& x) const + { return m_tree.find(x); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_tree.count(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + {return m_tree.lower_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return m_tree.lower_bound(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + { return m_tree.upper_bound(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair equal_range(const key_type& x) + { return m_tree.equal_range(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return m_tree.upper_bound(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) const + { return m_tree.equal_range(x); } + + /// @cond + template + friend bool operator== (const multimap& x, + const multimap& y); + + template + friend bool operator< (const multimap& x, + const multimap& y); + /// @endcond +}; + +template +inline bool operator==(const multimap& x, + const multimap& y) +{ return x.m_tree == y.m_tree; } + +template +inline bool operator<(const multimap& x, + const multimap& y) +{ return x.m_tree < y.m_tree; } + +template +inline bool operator!=(const multimap& x, + const multimap& y) +{ return !(x == y); } + +template +inline bool operator>(const multimap& x, + const multimap& y) +{ return y < x; } + +template +inline bool operator<=(const multimap& x, + const multimap& y) +{ return !(y < x); } + +template +inline bool operator>=(const multimap& x, + const multimap& y) +{ return !(x < y); } + + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline void swap(multimap& x, + multimap& y) +{ x.swap(y); } + +template +inline void swap(const detail::moved_object >& x, + multimap& y) +{ x.get().swap(y); } + +template +inline void swap(multimap& x, + const detail::moved_object >& y) +{ x.swap(y.get()); } +#else +template +inline void swap(multimap&&x, + multimap&&y) +{ x.swap(y); } +#endif + +/// @cond +template +struct is_movable > +{ + enum { value = true }; +}; + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = + has_trivial_destructor::value && + has_trivial_destructor::value }; +}; +/// @endcond + +}} //namespace boost { namespace interprocess { + +#include + +#endif /* BOOST_INTERPROCESS_MAP_HPP */ + diff --git a/win32/include/boost/interprocess/containers/set.hpp b/win32/include/boost/interprocess/containers/set.hpp new file mode 100755 index 000000000..11f213ad7 --- /dev/null +++ b/win32/include/boost/interprocess/containers/set.hpp @@ -0,0 +1,1043 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This file comes from SGI's stl_set/stl_multiset files. Modified by Ion Gaztanaga 2004. +// Renaming, isolating and porting to generic algorithms. Pointer typedef +// set to allocator::pointer to allow placing it in shared memory. +// +/////////////////////////////////////////////////////////////////////////////// +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef BOOST_INTERPROCESS_SET_HPP +#define BOOST_INTERPROCESS_SET_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost { namespace interprocess { + +/// @cond +// Forward declarations of operators < and ==, needed for friend declaration. +template +inline bool operator==(const set& x, + const set& y); + +template +inline bool operator<(const set& x, + const set& y); +/// @endcond + +//! A set is a kind of associative container that supports unique keys (contains at +//! most one of each key value) and provides for fast retrieval of the keys themselves. +//! Class set supports bidirectional iterators. +//! +//! A set satisfies all of the requirements of a container and of a reversible container +//! , and of an associative container. A set also provides most operations described in +//! for unique keys. +template +class set +{ + /// @cond + private: + typedef detail::rbtree, Pred, Alloc> tree_t; + tree_t m_tree; // red-black tree representing set + /// @endcond + + public: + // typedefs: + typedef typename tree_t::key_type key_type; + typedef typename tree_t::value_type value_type; + typedef typename tree_t::pointer pointer; + typedef typename tree_t::const_pointer const_pointer; + typedef typename tree_t::reference reference; + typedef typename tree_t::const_reference const_reference; + typedef Pred key_compare; + typedef Pred value_compare; + typedef typename tree_t::iterator iterator; + typedef typename tree_t::const_iterator const_iterator; + typedef typename tree_t::reverse_iterator reverse_iterator; + typedef typename tree_t::const_reverse_iterator const_reverse_iterator; + typedef typename tree_t::size_type size_type; + typedef typename tree_t::difference_type difference_type; + typedef typename tree_t::allocator_type allocator_type; + typedef typename tree_t::stored_allocator_type stored_allocator_type; + + //! Effects: Constructs an empty set using the specified comparison object + //! and allocator. + //! + //! Complexity: Constant. + explicit set(const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(comp, a) + {} + + //! Effects: Constructs an empty set using the specified comparison object and + //! allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + set(InputIterator first, InputIterator last, const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(first, last, comp, a, true) + {} + + //! Effects: Copy constructs a set. + //! + //! Complexity: Linear in x.size(). + set(const set& x) + : m_tree(x.m_tree) + {} + + //! Effects: Move constructs a set. Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + set(const detail::moved_object >& x) + : m_tree(detail::move_impl(x.get().m_tree)) + {} + #else + set(set &&x) + : m_tree(detail::move_impl(x.m_tree)) + {} + #endif + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + set& operator=(const set& x) + { m_tree = x.m_tree; return *this; } + + //! Effects: this->swap(x.get()). + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + set& operator=(const detail::moved_object >& x) + { m_tree = detail::move_impl(x.get().m_tree); return *this; } + #else + set& operator=(set &&x) + { m_tree = detail::move_impl(x.m_tree); return *this; } + #endif + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return m_tree.key_comp(); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return m_tree.key_comp(); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return m_tree.get_allocator(); } + + const stored_allocator_type &get_stored_allocator() const + { return m_tree.get_stored_allocator(); } + + stored_allocator_type &get_stored_allocator() + { return m_tree.get_stored_allocator(); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant + iterator begin() + { return m_tree.begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return m_tree.begin(); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return m_tree.end(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return m_tree.end(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return m_tree.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return m_tree.rbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return m_tree.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return m_tree.rend(); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_tree.max_size(); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(set& x) + { m_tree.swap(x.m_tree); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(const detail::moved_object >& x) + { m_tree.swap(x.get().m_tree); } + #else + void swap(set &&x) + { m_tree.swap(x.m_tree); } + #endif + + //! Effects: Inserts x if and only if there is no element in the container + //! with key equivalent to the key of x. + //! + //! Returns: The bool component of the returned pair is true if and only + //! if the insertion takes place, and the iterator component of the pair + //! points to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic. + std::pair insert(const value_type& x) + { return m_tree.insert_unique(x); } + + //! Effects: Move constructs a new value from x if and only if there is + //! no element in the container with key equivalent to the key of x. + //! + //! Returns: The bool component of the returned pair is true if and only + //! if the insertion takes place, and the iterator component of the pair + //! points to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + std::pair insert(const detail::moved_object& x) + { return m_tree.insert_unique(x); } + #else + std::pair insert(value_type &&x) + { return m_tree.insert_unique(detail::move_impl(x)); } + #endif + + //! Effects: Inserts a copy of x in the container if and only if there is + //! no element in the container with key equivalent to the key of x. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + iterator insert(const_iterator p, const value_type& x) + { return m_tree.insert_unique(p, x); } + + //! Effects: Inserts an element move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent to the key of x. + //! + //! Complexity: Logarithmic. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(const_iterator p, const detail::moved_object& x) + { return m_tree.insert_unique(p, x); } + #else + iterator insert(const_iterator p, value_type &&x) + { return m_tree.insert_unique(p, detail::move_impl(x)); } + #endif + + //! Requires: i, j are not iterators into *this. + //! + //! Effects: inserts each element from the range [i,j) if and only + //! if there is no element with key equivalent to the key of that element. + //! + //! Complexity: N log(size()+N) (N is the distance from i to j) + template + void insert(InputIterator first, InputIterator last) + { m_tree.insert_unique(first, last); } + + //! Effects: Erases the element pointed to by p. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Amortized constant time + iterator erase(const_iterator p) + { return m_tree.erase(p); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: log(size()) + count(k) + size_type erase(const key_type& x) + { return m_tree.erase(x); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: log(size())+N where N is the distance from first to last. + iterator erase(const_iterator first, const_iterator last) + { return m_tree.erase(first, last); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_tree.clear(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return m_tree.find(x); } + + //! Returns: A const_iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + const_iterator find(const key_type& x) const + { return m_tree.find(x); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_tree.find(x) == m_tree.end() ? 0 : 1; } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + { return m_tree.lower_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return m_tree.lower_bound(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + { return m_tree.upper_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return m_tree.upper_bound(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) + { return m_tree.equal_range(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) const + { return m_tree.equal_range(x); } + + /// @cond + template + friend bool operator== (const set&, const set&); + + template + friend bool operator< (const set&, const set&); + /// @endcond +}; + +template +inline bool operator==(const set& x, + const set& y) +{ return x.m_tree == y.m_tree; } + +template +inline bool operator<(const set& x, + const set& y) +{ return x.m_tree < y.m_tree; } + +template +inline bool operator!=(const set& x, + const set& y) +{ return !(x == y); } + +template +inline bool operator>(const set& x, + const set& y) +{ return y < x; } + +template +inline bool operator<=(const set& x, + const set& y) +{ return !(y < x); } + +template +inline bool operator>=(const set& x, + const set& y) +{ return !(x < y); } + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline void swap(set& x, + set& y) +{ x.swap(y); } + +template +inline void swap(set& x, + detail::moved_object >& y) +{ x.swap(y.get()); } + +template +inline void swap(detail::moved_object >& y, + set& x) +{ y.swap(x.get()); } + +#else +template +inline void swap(set&&x, + set&&y) +{ x.swap(y); } +#endif + +/// @cond + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = + has_trivial_destructor::value && + has_trivial_destructor::value }; +}; + +// Forward declaration of operators < and ==, needed for friend declaration. + +template +inline bool operator==(const multiset& x, + const multiset& y); + +template +inline bool operator<(const multiset& x, + const multiset& y); +/// @endcond + +//! A multiset is a kind of associative container that supports equivalent keys +//! (possibly contains multiple copies of the same key value) and provides for +//! fast retrieval of the keys themselves. Class multiset supports bidirectional iterators. +//! +//! A multiset satisfies all of the requirements of a container and of a reversible +//! container, and of an associative container). multiset also provides most operations +//! described for duplicate keys. +template +class multiset +{ + /// @cond + private: + typedef detail::rbtree, Pred, Alloc> tree_t; + tree_t m_tree; // red-black tree representing multiset + /// @endcond + + public: + // typedefs: + typedef typename tree_t::key_type key_type; + typedef typename tree_t::value_type value_type; + typedef typename tree_t::pointer pointer; + typedef typename tree_t::const_pointer const_pointer; + typedef typename tree_t::reference reference; + typedef typename tree_t::const_reference const_reference; + typedef Pred key_compare; + typedef Pred value_compare; + typedef typename tree_t::iterator iterator; + typedef typename tree_t::const_iterator const_iterator; + typedef typename tree_t::reverse_iterator reverse_iterator; + typedef typename tree_t::const_reverse_iterator const_reverse_iterator; + typedef typename tree_t::size_type size_type; + typedef typename tree_t::difference_type difference_type; + typedef typename tree_t::allocator_type allocator_type; + typedef typename tree_t::stored_allocator_type stored_allocator_type; + + //! Effects: Constructs an empty multiset using the specified comparison + //! object and allocator. + //! + //! Complexity: Constant. + explicit multiset(const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(comp, a) + {} + + //! Effects: Constructs an empty multiset using the specified comparison object + //! and allocator, and inserts elements from the range [first ,last ). + //! + //! Complexity: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template + multiset(InputIterator first, InputIterator last, + const Pred& comp = Pred(), + const allocator_type& a = allocator_type()) + : m_tree(first, last, comp, a, false) + {} + + //! Effects: Copy constructs a multiset. + //! + //! Complexity: Linear in x.size(). + multiset(const multiset& x) + : m_tree(x.m_tree) + {} + + //! Effects: Move constructs a multiset. Constructs *this using x's resources. + //! + //! Complexity: Construct. + //! + //! Postcondition: x is emptied. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + multiset(const detail::moved_object >& x) + : m_tree(detail::move_impl(x.get().m_tree)) + {} + #else + multiset(multiset &&x) + : m_tree(detail::move_impl(x.m_tree)) + {} + #endif + + //! Effects: Makes *this a copy of x. + //! + //! Complexity: Linear in x.size(). + multiset& operator=(const multiset& x) + { m_tree = x.m_tree; return *this; } + + //! Effects: this->swap(x.get()). + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + multiset& operator=(const detail::moved_object >& x) + { m_tree = detail::move_impl(x.get().m_tree); return *this; } + #else + multiset& operator=(multiset &&x) + { m_tree = detail::move_impl(x.m_tree); return *this; } + #endif + + //! Effects: Returns the comparison object out + //! of which a was constructed. + //! + //! Complexity: Constant. + key_compare key_comp() const + { return m_tree.key_comp(); } + + //! Effects: Returns an object of value_compare constructed out + //! of the comparison object. + //! + //! Complexity: Constant. + value_compare value_comp() const + { return m_tree.key_comp(); } + + //! Effects: Returns a copy of the Allocator that + //! was passed to the object's constructor. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return m_tree.get_allocator(); } + + const stored_allocator_type &get_stored_allocator() const + { return m_tree.get_stored_allocator(); } + + stored_allocator_type &get_stored_allocator() + { return m_tree.get_stored_allocator(); } + + //! Effects: Returns an iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return m_tree.begin(); } + + //! Effects: Returns a const_iterator to the first element contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return m_tree.begin(); } + + //! Effects: Returns an iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return m_tree.end(); } + + //! Effects: Returns a const_iterator to the end of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return m_tree.end(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return m_tree.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return m_tree.rbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return m_tree.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return m_tree.rend(); } + + //! Effects: Returns true if the container contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return m_tree.empty(); } + + //! Effects: Returns the number of the elements contained in the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return m_tree.size(); } + + //! Effects: Returns the largest possible size of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return m_tree.max_size(); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(multiset& x) + { m_tree.swap(x.m_tree); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(const detail::moved_object >& x) + { m_tree.swap(x.get().m_tree); } + #else + void swap(multiset && x) + { m_tree.swap(x.m_tree); } + #endif + + //! Effects: Inserts x and returns the iterator pointing to the + //! newly inserted element. + //! + //! Complexity: Logarithmic. + iterator insert(const value_type& x) + { return m_tree.insert_equal(x); } + + //! Effects: Inserts a copy of x in the container. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(const detail::moved_object& x) + { return m_tree.insert_equal(x); } + #else + iterator insert(value_type && x) + { return m_tree.insert_equal(detail::move_impl(x)); } + #endif + + //! Effects: Inserts a copy of x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + iterator insert(const_iterator p, const value_type& x) + { return m_tree.insert_equal(p, x); } + + //! Effects: Inserts a value move constructed from x in the container. + //! p is a hint pointing to where the insert should start to search. + //! + //! Returns: An iterator pointing to the element with key equivalent + //! to the key of x. + //! + //! Complexity: Logarithmic in general, but amortized constant if t + //! is inserted right before p. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(const_iterator p, const detail::moved_object& x) + { return m_tree.insert_equal(p, x); } + #else + iterator insert(const_iterator p, value_type && x) + { return m_tree.insert_equal(p, detail::move_impl(x)); } + #endif + + //! Requires: i, j are not iterators into *this. + //! + //! Effects: inserts each element from the range [i,j) . + //! + //! Complexity: N log(size()+N) (N is the distance from i to j) + template + void insert(InputIterator first, InputIterator last) + { m_tree.insert_equal(first, last); } + + //! Effects: Erases the element pointed to by p. + //! + //! Returns: Returns an iterator pointing to the element immediately + //! following q prior to the element being erased. If no such element exists, + //! returns end(). + //! + //! Complexity: Amortized constant time + iterator erase(const_iterator p) + { return m_tree.erase(p); } + + //! Effects: Erases all elements in the container with key equivalent to x. + //! + //! Returns: Returns the number of erased elements. + //! + //! Complexity: log(size()) + count(k) + size_type erase(const key_type& x) + { return m_tree.erase(x); } + + //! Effects: Erases all the elements in the range [first, last). + //! + //! Returns: Returns last. + //! + //! Complexity: log(size())+N where N is the distance from first to last. + iterator erase(const_iterator first, const_iterator last) + { return m_tree.erase(first, last); } + + //! Effects: erase(a.begin(),a.end()). + //! + //! Postcondition: size() == 0. + //! + //! Complexity: linear in size(). + void clear() + { m_tree.clear(); } + + //! Returns: An iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + iterator find(const key_type& x) + { return m_tree.find(x); } + + //! Returns: A const iterator pointing to an element with the key + //! equivalent to x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic. + const_iterator find(const key_type& x) const + { return m_tree.find(x); } + + //! Returns: The number of elements with key equivalent to x. + //! + //! Complexity: log(size())+count(k) + size_type count(const key_type& x) const + { return m_tree.count(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator lower_bound(const key_type& x) + { return m_tree.lower_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than k, or a.end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator lower_bound(const key_type& x) const + { return m_tree.lower_bound(x); } + + //! Returns: An iterator pointing to the first element with key not less + //! than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + iterator upper_bound(const key_type& x) + { return m_tree.upper_bound(x); } + + //! Returns: A const iterator pointing to the first element with key not + //! less than x, or end() if such an element is not found. + //! + //! Complexity: Logarithmic + const_iterator upper_bound(const key_type& x) const + { return m_tree.upper_bound(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) + { return m_tree.equal_range(x); } + + //! Effects: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). + //! + //! Complexity: Logarithmic + std::pair + equal_range(const key_type& x) const + { return m_tree.equal_range(x); } + + /// @cond + template + friend bool operator== (const multiset&, + const multiset&); + template + friend bool operator< (const multiset&, + const multiset&); + /// @endcond +}; + +template +inline bool operator==(const multiset& x, + const multiset& y) +{ return x.m_tree == y.m_tree; } + +template +inline bool operator<(const multiset& x, + const multiset& y) +{ return x.m_tree < y.m_tree; } + +template +inline bool operator!=(const multiset& x, + const multiset& y) +{ return !(x == y); } + +template +inline bool operator>(const multiset& x, + const multiset& y) +{ return y < x; } + +template +inline bool operator<=(const multiset& x, + const multiset& y) +{ return !(y < x); } + +template +inline bool operator>=(const multiset& x, + const multiset& y) +{ return !(x < y); } + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline void swap(multiset& x, + multiset& y) +{ x.swap(y); } + +template +inline void swap(multiset& x, + detail::moved_object >& y) +{ x.swap(y.get()); } + +template +inline void swap(detail::moved_object >& y, + multiset& x) +{ y.swap(x.get()); } +#else +template +inline void swap(multiset&&x, + multiset&&y) +{ x.swap(y); } +#endif + +/// @cond + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = + has_trivial_destructor::value && + has_trivial_destructor::value }; +}; +/// @endcond + +}} //namespace boost { namespace interprocess { + +#include + +#endif /* BOOST_INTERPROCESS_SET_HPP */ + diff --git a/win32/include/boost/interprocess/containers/slist.hpp b/win32/include/boost/interprocess/containers/slist.hpp new file mode 100755 index 000000000..3c0af7bc3 --- /dev/null +++ b/win32/include/boost/interprocess/containers/slist.hpp @@ -0,0 +1,1472 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This file comes from SGI's stl_slist.h file. Modified by Ion Gaztanaga 2004-2008 +// Renaming, isolating and porting to generic algorithms. Pointer typedef +// set to allocator::pointer to allow placing it in shared memory. +// +/////////////////////////////////////////////////////////////////////////////// +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef BOOST_INTERPROCESS_SLIST_HPP +#define BOOST_INTERPROCESS_SLIST_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace boost{ namespace interprocess{ + +namespace detail { +/// @cond +template +struct slist_node + : public bi::make_slist_base_hook + , bi::link_mode >::type +{ + typedef typename bi::make_slist_base_hook + , bi::link_mode >::type hook_type; + + slist_node() + : m_data() + {} + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + slist_node(const Convertible &value) + : m_data(value){} + #else + template + slist_node(Convertible &&value) + : m_data(detail::forward_impl(value)){} + #endif + + T m_data; +}; + +template +struct intrusive_slist_type +{ + typedef typename A::value_type value_type; + typedef typename detail::pointer_to_other + ::type void_pointer; + typedef typename detail::slist_node + node_type; + + typedef typename bi::make_slist + + ,bi::constant_time_size + ,bi::size_type + >::type container_type; + typedef container_type type ; +}; + +/// @endcond +} //namespace detail { + +//! An slist is a singly linked list: a list where each element is linked to the next +//! element, but not to the previous element. That is, it is a Sequence that +//! supports forward but not backward traversal, and (amortized) constant time +//! insertion and removal of elements. Slists, like lists, have the important +//! property that insertion and splicing do not invalidate iterators to list elements, +//! and that even removal invalidates only the iterators that point to the elements +//! that are removed. The ordering of iterators may be changed (that is, +//! slist::iterator might have a different predecessor or successor after a list +//! operation than it did before), but the iterators themselves will not be invalidated +//! or made to point to different elements unless that invalidation or mutation is explicit. +//! +//! The main difference between slist and list is that list's iterators are bidirectional +//! iterators, while slist's iterators are forward iterators. This means that slist is +//! less versatile than list; frequently, however, bidirectional iterators are +//! unnecessary. You should usually use slist unless you actually need the extra +//! functionality of list, because singly linked lists are smaller and faster than double +//! linked lists. +//! +//! Important performance note: like every other Sequence, slist defines the member +//! functions insert and erase. Using these member functions carelessly, however, can +//! result in disastrously slow programs. The problem is that insert's first argument is +//! an iterator p, and that it inserts the new element(s) before p. This means that +//! insert must find the iterator just before p; this is a constant-time operation +//! for list, since list has bidirectional iterators, but for slist it must find that +//! iterator by traversing the list from the beginning up to p. In other words: +//! insert and erase are slow operations anywhere but near the beginning of the slist. +//! +//! Slist provides the member functions insert_after and erase_after, which are constant +//! time operations: you should always use insert_after and erase_after whenever +//! possible. If you find that insert_after and erase_after aren't adequate for your +//! needs, and that you often need to use insert and erase in the middle of the list, +//! then you should probably use list instead of slist. +template +class slist + : protected detail::node_alloc_holder + ::type> +{ + /// @cond + typedef typename + detail::intrusive_slist_type::type Icont; + typedef detail::node_alloc_holder AllocHolder; + typedef typename AllocHolder::NodePtr NodePtr; + typedef list ThisType; + typedef typename AllocHolder::NodeAlloc NodeAlloc; + typedef typename AllocHolder::ValAlloc ValAlloc; + typedef typename AllocHolder::Node Node; + typedef detail::allocator_destroyer Destroyer; + typedef typename AllocHolder::allocator_v1 allocator_v1; + typedef typename AllocHolder::allocator_v2 allocator_v2; + typedef typename AllocHolder::alloc_version alloc_version; + + class equal_to_value + { + typedef typename AllocHolder::value_type value_type; + const value_type &t_; + + public: + equal_to_value(const value_type &t) + : t_(t) + {} + + bool operator()(const value_type &t)const + { return t_ == t; } + }; + + template + struct ValueCompareToNodeCompare + : Pred + { + ValueCompareToNodeCompare(Pred pred) + : Pred(pred) + {} + + bool operator()(const Node &a, const Node &b) const + { return static_cast(*this)(a.m_data, b.m_data); } + + bool operator()(const Node &a) const + { return static_cast(*this)(a.m_data); } + }; + /// @endcond + public: + //! The type of object, T, stored in the list + typedef T value_type; + //! Pointer to T + typedef typename A::pointer pointer; + //! Const pointer to T + typedef typename A::const_pointer const_pointer; + //! Reference to T + typedef typename A::reference reference; + //! Const reference to T + typedef typename A::const_reference const_reference; + //! An unsigned integral type + typedef typename A::size_type size_type; + //! A signed integral type + typedef typename A::difference_type difference_type; + //! The allocator type + typedef A allocator_type; + //! The stored allocator type + typedef NodeAlloc stored_allocator_type; + + /// @cond + private: + typedef difference_type list_difference_type; + typedef pointer list_pointer; + typedef const_pointer list_const_pointer; + typedef reference list_reference; + typedef const_reference list_const_reference; + /// @endcond + + public: + //! Const iterator used to iterate through a list. + class const_iterator + /// @cond + : public std::iterator + { + + protected: + typename Icont::iterator m_it; + explicit const_iterator(typename Icont::iterator it) : m_it(it){} + void prot_incr(){ ++m_it; } + + private: + typename Icont::iterator get() + { return this->m_it; } + + public: + friend class slist; + typedef list_difference_type difference_type; + + //Constructors + const_iterator() + : m_it() + {} + + //Pointer like operators + const_reference operator*() const + { return m_it->m_data; } + + const_pointer operator->() const + { return const_pointer(&m_it->m_data); } + + //Increment / Decrement + const_iterator& operator++() + { prot_incr(); return *this; } + + const_iterator operator++(int) + { typename Icont::iterator tmp = m_it; ++*this; return const_iterator(tmp); } + + //Comparison operators + bool operator== (const const_iterator& r) const + { return m_it == r.m_it; } + + bool operator!= (const const_iterator& r) const + { return m_it != r.m_it; } + } + /// @endcond + ; + + //! Iterator used to iterate through a list + class iterator + /// @cond + : public const_iterator + { + + private: + explicit iterator(typename Icont::iterator it) + : const_iterator(it) + {} + + typename Icont::iterator get() + { return this->m_it; } + + public: + friend class slist; + typedef list_pointer pointer; + typedef list_reference reference; + + //Constructors + iterator(){} + + //Pointer like operators + reference operator*() const { return this->m_it->m_data; } + pointer operator->() const { return pointer(&this->m_it->m_data); } + + //Increment / Decrement + iterator& operator++() + { this->prot_incr(); return *this; } + + iterator operator++(int) + { typename Icont::iterator tmp = this->m_it; ++*this; return iterator(tmp); } + } + /// @endcond + ; + + public: + //! Effects: Constructs a list taking the allocator as parameter. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + explicit slist(const allocator_type& a = allocator_type()) + : AllocHolder(a) + {} + +// explicit slist(size_type n) +// : AllocHolder(detail::move_impl(allocator_type())) +// { this->resize(n); } + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + explicit slist(size_type n, const value_type& x = value_type(), + const allocator_type& a = allocator_type()) + : AllocHolder(a) + { this->priv_create_and_insert_nodes(this->before_begin(), n, x); } + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts a copy of the range [first, last) in the list. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's constructor taking an dereferenced InIt throws. + //! + //! Complexity: Linear to the range [first, last). + template + slist(InpIt first, InpIt last, + const allocator_type& a = allocator_type()) + : AllocHolder(a) + { this->insert_after(this->before_begin(), first, last); } + + //! Effects: Copy constructs a list. + //! + //! Postcondition: x == *this. + //! + //! Throws: If allocator_type's default constructor or copy constructor throws. + //! + //! Complexity: Linear to the elements x contains. + slist(const slist& x) + : AllocHolder(x) + { this->insert_after(this->before_begin(), x.begin(), x.end()); } + + //! Effects: Move constructor. Moves mx's resources to *this. + //! + //! Throws: If allocator_type's default constructor throws. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + slist(const detail::moved_object &x) + : AllocHolder(detail::move_impl((AllocHolder&)x.get())) + {} + #else + slist(slist &&x) + : AllocHolder(detail::move_impl((AllocHolder&)x)) + {} + #endif + + //! Effects: Makes *this contain the same elements as x. + //! + //! Postcondition: this->size() == x.size(). *this contains a copy + //! of each of x's elements. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to the number of elements in x. + slist& operator= (const slist& x) + { + if (&x != this){ + this->assign(x.begin(), x.end()); + } + return *this; + } + + //! Effects: Makes *this contain the same elements as x. + //! + //! Postcondition: this->size() == x.size(). *this contains a copy + //! of each of x's elements. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to the number of elements in x. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + slist& operator= (const detail::moved_object& mx) + { + if (&mx.get() != this){ + this->clear(); + this->swap(mx.get()); + } + return *this; + } + #else + slist& operator= (slist && mx) + { + if (&mx != this){ + this->clear(); + this->swap(mx); + } + return *this; + } + #endif + + //! Effects: Destroys the list. All stored values are destroyed + //! and used memory is deallocated. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements. + ~slist() + { this->clear(); } + + //! Effects: Returns a copy of the internal allocator. + //! + //! Throws: If allocator's copy constructor throws. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return allocator_type(this->node_alloc()); } + + const stored_allocator_type &get_stored_allocator() const + { return this->node_alloc(); } + + stored_allocator_type &get_stored_allocator() + { return this->node_alloc(); } + + public: + + //! Effects: Assigns the n copies of val to *this. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void assign(size_type n, const T& val) + { this->priv_fill_assign(n, val); } + + //! Effects: Assigns the range [first, last) to *this. + //! + //! Throws: If memory allocation throws or + //! T's constructor from dereferencing InpIt throws. + //! + //! Complexity: Linear to n. + template + void assign(InpIt first, InpIt last) + { + const bool aux_boolean = detail::is_convertible::value; + typedef detail::bool_ Result; + this->priv_assign_dispatch(first, last, Result()); + } + + //! Effects: Returns an iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return iterator(this->icont().begin()); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return const_iterator(this->non_const_icont().begin()); } + + //! Effects: Returns an iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return iterator(this->icont().end()); } + + //! Effects: Returns a const_iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return const_iterator(this->non_const_icont().end()); } + + //! Effects: Returns a non-dereferenceable iterator that, + //! when incremented, yields begin(). This iterator may be used + //! as the argument toinsert_after, erase_after, etc. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator before_begin() + { return iterator(end()); } + + //! Effects: Returns a non-dereferenceable const_iterator + //! that, when incremented, yields begin(). This iterator may be used + //! as the argument toinsert_after, erase_after, etc. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator before_begin() const + { return const_iterator(end()); } + + //! Effects: Returns the number of the elements contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return this->icont().size(); } + + //! Effects: Returns the largest possible size of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return AllocHolder::max_size(); } + + //! Effects: Returns true if the list contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return !this->size(); } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() + //! allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements on *this and x. + void swap(slist& x) + { AllocHolder::swap(x); } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference front() + { return *this->begin(); } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference front() const + { return *this->begin(); } + + //! Effects: Inserts a copy of t in the beginning of the list. + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + void push_front(const value_type& x) + { this->icont().push_front(*this->create_node(x)); } + + //! Effects: Constructs a new element in the beginning of the list + //! and moves the resources of t to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void push_front(const detail::moved_object& x) + { this->icont().push_front(*this->create_node(x)); } + #else + void push_front(T && x) + { this->icont().push_front(*this->create_node(detail::move_impl(x))); } + #endif + + //! Effects: Removes the first element from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Amortized constant time. + void pop_front() + { this->icont().pop_front_and_dispose(Destroyer(this->node_alloc())); } + + //! Returns: The iterator to the element before i in the sequence. + //! Returns the end-iterator, if either i is the begin-iterator or the + //! sequence is empty. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before i. + iterator previous(iterator p) + { return iterator(this->icont().previous(p.get())); } + + //! Returns: The const_iterator to the element before i in the sequence. + //! Returns the end-const_iterator, if either i is the begin-const_iterator or + //! the sequence is empty. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before i. + const_iterator previous(const_iterator p) + { return const_iterator(this->icont().previous(p.get())); } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Inserts a copy of the value after the p pointed + //! by prev_p. + //! + //! Returns: An iterator to the inserted element. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + //! + //! Note: Does not affect the validity of iterators and references of + //! previous values. + iterator insert_after(iterator prev_pos, const value_type& x) + { return iterator(this->icont().insert_after(prev_pos.get(), *this->create_node(x))); } + + //! Requires: prev_pos must be a valid iterator of *this. + //! + //! Effects: Inserts a move constructed copy object from the value after the + //! p pointed by prev_pos. + //! + //! Returns: An iterator to the inserted element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + //! + //! Note: Does not affect the validity of iterators and references of + //! previous values. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert_after(iterator prev_pos, const detail::moved_object& x) + { return iterator(this->icont().insert_after(prev_pos.get(), *this->create_node(x))); } + #else + iterator insert_after(iterator prev_pos, value_type && x) + { return iterator(this->icont().insert_after(prev_pos.get(), *this->create_node(detail::move_impl(x)))); } + #endif + + //! Requires: prev_pos must be a valid iterator of *this. + //! + //! Effects: Inserts n copies of x after prev_pos. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + //! + //! Note: Does not affect the validity of iterators and references of + //! previous values. + void insert_after(iterator prev_pos, size_type n, const value_type& x) + { this->priv_create_and_insert_nodes(prev_pos, n, x); } + + //! Requires: prev_pos must be a valid iterator of *this. + //! + //! Effects: Inserts the range pointed by [first, last) + //! after the p prev_pos. + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced InpIt throws. + //! + //! Complexity: Linear to the number of elements inserted. + //! + //! Note: Does not affect the validity of iterators and references of + //! previous values. + template + void insert_after(iterator prev_pos, InIter first, InIter last) + { + const bool aux_boolean = detail::is_convertible::value; + typedef detail::bool_ Result; + this->priv_insert_after_range_dispatch(prev_pos, first, last, Result()); + } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a copy of x before p. + //! + //! Throws: If memory allocation throws or x's copy constructor throws. + //! + //! Complexity: Linear to the elements before p. + iterator insert(iterator p, const value_type& x) + { return this->insert_after(previous(p), x); } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a new element before p with mx's resources. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Linear to the elements before p. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(iterator p, const detail::moved_object& x) + { return this->insert_after(previous(p), x); } + #else + iterator insert(iterator p, value_type && x) + { return this->insert_after(previous(p), detail::move_impl(x)); } + #endif + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Inserts n copies of x before p. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n plus linear to the elements before p. + void insert(iterator p, size_type n, const value_type& x) + { return this->insert_after(previous(p), n, x); } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a copy of the [first, last) range before p. + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced InpIt throws. + //! + //! Complexity: Linear to std::distance [first, last) plus + //! linear to the elements before p. + template + void insert(iterator p, InIter first, InIter last) + { return this->insert_after(previous(p), first, last); } + + //! Effects: Erases the element after the element pointed by prev_pos + //! of the list. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Does not invalidate iterators or references to non erased elements. + iterator erase_after(iterator prev_pos) + { + return iterator(this->icont().erase_after_and_dispose(prev_pos.get(), Destroyer(this->node_alloc()))); + } + + //! Effects: Erases the range (before_first, last) from + //! the list. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of erased elements. + //! + //! Note: Does not invalidate iterators or references to non erased elements. + iterator erase_after(iterator before_first, iterator last) + { + return iterator(this->icont().erase_after_and_dispose(before_first.get(), last.get(), Destroyer(this->node_alloc()))); + } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Erases the element at p p. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before p. + iterator erase(iterator p) + { return iterator(this->erase_after(previous(p))); } + + //! Requires: first and last must be valid iterator to elements in *this. + //! + //! Effects: Erases the elements pointed by [first, last). + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the distance between first and last plus + //! linear to the elements before first. + iterator erase(iterator first, iterator last) + { return iterator(this->erase_after(previous(first), last)); } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are copy constructed from x. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size, const T& x) + { + typename Icont::iterator end_n(this->icont().end()), cur(this->icont().before_begin()), cur_next; + while (++(cur_next = cur) != end_n && new_size > 0){ + --new_size; + cur = cur_next; + } + if (cur_next != end_n) + this->erase_after(iterator(cur), iterator(end_n)); + else + this->insert_after(iterator(cur), new_size, x); + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are default constructed. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size) + { + typename Icont::iterator end_n(this->icont().end()), cur(this->icont().before_begin()), cur_next; + size_type len = this->size(); + size_type left = new_size; + + while (++(cur_next = cur) != end_n && left > 0){ + --left; + cur = cur_next; + } + if (cur_next != end_n){ + this->erase_after(iterator(cur), iterator(end_n)); + } + else{ + this->priv_create_and_insert_nodes(iterator(cur), new_size - len); + } + } + + //! Effects: Erases all the elements of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements in the list. + void clear() + { this->icont().clear_and_dispose(Destroyer(this->node_alloc())); } + + //! Requires: p must point to an element contained + //! by the list. x != *this + //! + //! Effects: Transfers all the elements of list x to this list, after the + //! the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Linear to the elements in x. + //! + //! Note: Iterators of values obtained from list x now point to elements of + //! this list. Iterators of this list and all the references are not invalidated. + void splice_after(iterator prev_pos, slist& x) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().splice_after(prev_pos.get(), x.icont()); + } + else{ + throw std::runtime_error("slist::splice called with unequal allocators"); + } + } + + //void splice_after(iterator prev_pos, const detail::moved_object& x) + //{ this->splice_after(prev_pos, x.get()); } + + // Moves the element that follows prev to *this, inserting it immediately + // after p. This is constant time. + + //! Requires: prev_pos must be a valid iterator of this. + //! i must point to an element contained in list x. + //! + //! Effects: Transfers the value pointed by i, from list x to this list, + //! after the element pointed by prev_pos. + //! If prev_pos == prev or prev_pos == ++prev, this function is a null operation. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice_after(iterator prev_pos, slist& x, iterator prev) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().splice_after(prev_pos.get(), x.icont(), prev.get()); + } + else{ + throw std::runtime_error("slist::splice called with unequal allocators"); + } + } + + //void splice_after(iterator prev_pos, const detail::moved_object& x, iterator prev) + //{ return splice_after(prev_pos, x.get(), prev); } + + // Moves the range [before_first + 1, before_last + 1) to *this, + // inserting it immediately after p. This is constant time. + + + //! Requires: prev_pos must be a valid iterator of this. + //! before_first and before_last must be valid iterators of x. + //! prev_pos must not be contained in [before_first, before_last) range. + //! + //! Effects: Transfers the range [before_first + 1, before_last + 1) + //! from list x to this list, after the element pointed by prev_pos. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Linear to the number of transferred elements. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice_after(iterator prev_pos, slist& x, + iterator before_first, iterator before_last) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().splice_after + (prev_pos.get(), x.icont(), before_first.get(), before_last.get()); + } + else{ + throw std::runtime_error("slist::splice called with unequal allocators"); + } + } + + //void splice_after(iterator prev_pos, const detail::moved_object& x, + // iterator before_first, iterator before_last) + //{ this->splice_after(prev_pos, x.get(), before_first, before_last); } + + //! Requires: prev_pos must be a valid iterator of this. + //! before_first and before_last must be valid iterators of x. + //! prev_pos must not be contained in [before_first, before_last) range. + //! n == std::distance(before_first, before_last) + //! + //! Effects: Transfers the range [before_first + 1, before_last + 1) + //! from list x to this list, after the element pointed by prev_pos. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice_after(iterator prev_pos, slist& x, + iterator before_first, iterator before_last, + size_type n) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().splice_after + (prev_pos.get(), x.icont(), before_first.get(), before_last.get(), n); + } + else{ + throw std::runtime_error("slist::splice called with unequal allocators"); + } + } + + //void splice_after(iterator prev_pos, const detail::moved_object& x, + // iterator before_first, iterator before_last, size_type n) + //{ this->splice_after(prev_pos, x.get(), before_first, before_last, n); } + + //! Requires: p must point to an element contained + //! by the list. x != *this + //! + //! Effects: Transfers all the elements of list x to this list, before the + //! the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Linear in distance(begin(), p), and linear in x.size(). + //! + //! Note: Iterators of values obtained from list x now point to elements of + //! this list. Iterators of this list and all the references are not invalidated. + void splice(iterator p, slist& x) + { this->splice_after(this->previous(p), x); } + + //void splice(iterator p, const detail::moved_object& x) + //{ return this->splice(p, x.get()); } + + //! Requires: p must point to an element contained + //! by this list. i must point to an element contained in list x. + //! + //! Effects: Transfers the value pointed by i, from list x to this list, + //! before the the element pointed by p. No destructors or copy constructors are called. + //! If p == i or p == ++i, this function is a null operation. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Linear in distance(begin(), p), and in distance(x.begin(), i). + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(iterator p, slist& x, iterator i) + { this->splice_after(previous(p), x, i); } + + //void splice(iterator p, const detail::moved_object& x, iterator i) + //{ this->splice(p, x.get(), i); } + + //! Requires: p must point to an element contained + //! by this list. first and last must point to elements contained in list x. + //! + //! Effects: Transfers the range pointed by first and last from list x to this list, + //! before the the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: std::runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Linear in distance(begin(), p), in distance(x.begin(), first), + //! and in distance(first, last). + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(iterator p, slist& x, iterator first, iterator last) + { this->splice_after(previous(p), x, previous(first), previous(last)); } + + //void splice(iterator p, const detail::moved_object& x, iterator first, iterator last) + //{ this->splice(p, x.get(), first, last); } + + //! Effects: Reverses the order of elements in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time. + //! + //! Note: Iterators and references are not invalidated + void reverse() + { this->icont().reverse(); } + + //! Effects: Removes all the elements that compare equal to value. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear time. It performs exactly size() comparisons for equality. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + void remove(const T& value) + { remove_if(equal_to_value(value)); } + + //! Effects: Removes all the elements for which a specified + //! predicate is satisfied. + //! + //! Throws: If pred throws. + //! + //! Complexity: Linear time. It performs exactly size() calls to the predicate. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void remove_if(Pred pred) + { + typedef ValueCompareToNodeCompare Predicate; + this->icont().remove_and_dispose_if(Predicate(pred), Destroyer(this->node_alloc())); + } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that are equal from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear time (size()-1 comparisons calls to pred()). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + void unique() + { this->unique(value_equal()); } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that satisfy some binary predicate from the list. + //! + //! Throws: If pred throws. + //! + //! Complexity: Linear time (size()-1 comparisons equality comparisons). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void unique(Pred pred) + { + typedef ValueCompareToNodeCompare Predicate; + this->icont().unique_and_dispose(Predicate(pred), Destroyer(this->node_alloc())); + } + + //! Requires: The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this according to std::less. The merge is stable; + //! that is, if an element from *this is equivalent to one from x, then the element + //! from *this will precede the one from x. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + void merge(slist& x) + { this->merge(x, value_less()); } + + //void merge(const detail::moved_object& x) + //{ this->merge(x.get(), value_less()); } + + //! Requires: p must be a comparison function that induces a strict weak + //! ordering and both *this and x must be sorted according to that ordering + //! The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this. The merge is stable; that is, if an element from *this is + //! equivalent to one from x, then the element from *this will precede the one from x. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references to *this are not invalidated. + template + void merge(slist& x, StrictWeakOrdering comp) + { + if((NodeAlloc&)*this == (NodeAlloc&)x){ + this->icont().merge(x.icont(), + ValueCompareToNodeCompare(comp)); + } + else{ + throw std::runtime_error("list::merge called with unequal allocators"); + } + } + + //template + //void merge(const detail::moved_object& x, StrictWeakOrdering comp) + //{ this->merge(x.get(), comp); } + + //! Effects: This function sorts the list *this according to std::less. + //! The sort is stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: Nothing. + //! + //! Notes: Iterators and references are not invalidated. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + void sort() + { this->sort(value_less()); } + + //! Effects: This function sorts the list *this according to std::less. + //! The sort is stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: Nothing. + //! + //! Notes: Iterators and references are not invalidated. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + template + void sort(StrictWeakOrdering comp) + { + // nothing if the slist has length 0 or 1. + if (this->size() < 2) + return; + this->icont().sort(ValueCompareToNodeCompare(comp)); + } + + /// @cond + private: + + //Iterator range version + template + void priv_create_and_insert_nodes + (const_iterator prev, InpIterator beg, InpIterator end) + { + typedef typename std::iterator_traits::iterator_category ItCat; + priv_create_and_insert_nodes(prev, beg, end, alloc_version(), ItCat()); + } + + template + void priv_create_and_insert_nodes + (const_iterator prev, InpIterator beg, InpIterator end, allocator_v1, std::input_iterator_tag) + { + for (; beg != end; ++beg){ + this->icont().insert_after(prev.get(), *this->create_node_from_it(beg)); + ++prev; + } + } + + template + void priv_create_and_insert_nodes + (const_iterator prev, InpIterator beg, InpIterator end, allocator_v2, std::input_iterator_tag) + { //Just forward to the default one + priv_create_and_insert_nodes(prev, beg, end, allocator_v1(), std::input_iterator_tag()); + } + + class insertion_functor; + friend class insertion_functor; + + class insertion_functor + { + Icont &icont_; + typename Icont::iterator prev_; + + public: + insertion_functor(Icont &icont, typename Icont::iterator prev) + : icont_(icont), prev_(prev) + {} + + void operator()(Node &n) + { prev_ = this->icont_.insert_after(prev_, n); } + }; + + template + void priv_create_and_insert_nodes + (const_iterator prev, FwdIterator beg, FwdIterator end, allocator_v2, std::forward_iterator_tag) + { + //Optimized allocation and construction + this->allocate_many_and_construct + (beg, std::distance(beg, end), insertion_functor(this->icont(), prev.get())); + } + + //Default constructed version + void priv_create_and_insert_nodes(const_iterator prev, size_type n) + { + typedef default_construct_iterator default_iterator; + this->priv_create_and_insert_nodes(prev, default_iterator(n), default_iterator()); + } + + //Copy constructed version + void priv_create_and_insert_nodes(const_iterator prev, size_type n, const T& x) + { + typedef constant_iterator cvalue_iterator; + this->priv_create_and_insert_nodes(prev, cvalue_iterator(x, n), cvalue_iterator()); + } + + //Dispatch to detect iterator range or integer overloads + template + void priv_insert_dispatch(iterator prev, + InputIter first, InputIter last, + detail::false_) + { this->priv_create_and_insert_nodes(prev, first, last); } + + template + void priv_insert_dispatch(iterator prev, Integer n, Integer x, detail::true_) + { this->priv_create_and_insert_nodes(prev, n, x); } + + void priv_fill_assign(size_type n, const T& val) + { + iterator end_n(this->end()); + iterator prev(this->before_begin()); + iterator node(this->begin()); + for ( ; node != end_n && n > 0 ; --n){ + *node = val; + prev = node; + ++node; + } + if (n > 0) + this->priv_create_and_insert_nodes(prev, n, val); + else + this->erase_after(prev, end_n); + } + + template + void priv_assign_dispatch(Int n, Int val, detail::true_) + { this->priv_fill_assign((size_type) n, (T)val); } + + template + void priv_assign_dispatch(InpIt first, InpIt last, + detail::false_) + { + iterator end_n(this->end()); + iterator prev(this->before_begin()); + iterator node(this->begin()); + while (node != end_n && first != last){ + *node = *first; + prev = node; + ++node; + ++first; + } + if (first != last) + this->priv_create_and_insert_nodes(prev, first, last); + else + this->erase_after(prev, end_n); + } + + template + void priv_insert_after_range_dispatch(iterator prev_pos, Int n, Int x, detail::true_) + { this->priv_create_and_insert_nodes(prev_pos, n, x); } + + template + void priv_insert_after_range_dispatch(iterator prev_pos, InIter first, InIter last, detail::false_) + { this->priv_create_and_insert_nodes(prev_pos, first, last); } + + //Functors for member algorithm defaults + struct value_less + { + bool operator()(const value_type &a, const value_type &b) const + { return a < b; } + }; + + struct value_equal + { + bool operator()(const value_type &a, const value_type &b) const + { return a == b; } + }; + + struct value_equal_to_this + { + explicit value_equal_to_this(const value_type &ref) + : m_ref(ref){} + + bool operator()(const value_type &val) const + { return m_ref == val; } + + const value_type &m_ref; + }; + /// @endcond +}; + +template +inline bool +operator==(const slist& x, const slist& y) +{ + if(x.size() != y.size()){ + return false; + } + typedef typename slist::const_iterator const_iterator; + const_iterator end1 = x.end(); + + const_iterator i1 = x.begin(); + const_iterator i2 = y.begin(); + while (i1 != end1 && *i1 == *i2){ + ++i1; + ++i2; + } + return i1 == end1; +} + +template +inline bool +operator<(const slist& sL1, const slist& sL2) +{ + return std::lexicographical_compare + (sL1.begin(), sL1.end(), sL2.begin(), sL2.end()); +} + +template +inline bool +operator!=(const slist& sL1, const slist& sL2) + { return !(sL1 == sL2); } + +template +inline bool +operator>(const slist& sL1, const slist& sL2) + { return sL2 < sL1; } + +template +inline bool +operator<=(const slist& sL1, const slist& sL2) + { return !(sL2 < sL1); } + +template +inline bool +operator>=(const slist& sL1, const slist& sL2) + { return !(sL1 < sL2); } + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline void swap(slist& x, slist& y) + { x.swap(y); } + +template +inline void swap(const detail::moved_object >& x, slist& y) + { x.get().swap(y); } + +template +inline void swap(slist& x, const detail::moved_object >& y) + { x.swap(y.get()); } +#else +template +inline void swap(slist&&x, slist&&y) + { x.swap(y); } +#endif + +/// @cond + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +//!This class is movable +/* +template +struct is_movable > +{ + enum { value = true }; +}; +*/ +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = has_trivial_destructor::value }; +}; +/// @endcond + +}} //namespace boost{ namespace interprocess{ + +// Specialization of insert_iterator so that insertions will be constant +// time rather than linear time. + +///@cond + +//Ummm, I don't like to define things in namespace std, but +//there is no other way +namespace std { + +template +class insert_iterator > +{ + protected: + typedef boost::interprocess::slist Container; + Container* container; + typename Container::iterator iter; + public: + typedef Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(Container& x, + typename Container::iterator i, + bool is_previous = false) + : container(&x), iter(is_previous ? i : x.previous(i)){ } + + insert_iterator& + operator=(const typename Container::value_type& value) + { + iter = container->insert_after(iter, value); + return *this; + } + insert_iterator& operator*(){ return *this; } + insert_iterator& operator++(){ return *this; } + insert_iterator& operator++(int){ return *this; } +}; + +} //namespace std; + +///@endcond + +#include + +#endif /* BOOST_INTERPROCESS_SLIST_HPP */ diff --git a/win32/include/boost/interprocess/containers/string.hpp b/win32/include/boost/interprocess/containers/string.hpp new file mode 100755 index 000000000..8666dff40 --- /dev/null +++ b/win32/include/boost/interprocess/containers/string.hpp @@ -0,0 +1,2490 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This file comes from SGI's string file. Modified by Ion Gaztanaga 2004-2008 +// Renaming, isolating and porting to generic algorithms. Pointer typedef +// set to allocator::pointer to allow placing it in shared memory. +// +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 1994 +// Hewlett-Packard Company +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. Hewlett-Packard Company makes no +// representations about the suitability of this software for any +// purpose. It is provided "as is" without express or implied warranty. + +#ifndef BOOST_INTERPROCESS_STRING_HPP +#define BOOST_INTERPROCESS_STRING_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace detail { + +/// @cond +// ------------------------------------------------------------ +// Class basic_string_base. + +// basic_string_base is a helper class that makes it it easier to write +// an exception-safe version of basic_string. The constructor allocates, +// but does not initialize, a block of memory. The destructor +// deallocates, but does not destroy elements within, a block of +// memory. The destructor assumes that the memory either is the internal buffer, +// or else points to a block of memory that was allocated using _String_base's +// allocator and whose size is this->m_storage. +template +class basic_string_base +{ + basic_string_base(); + public: + typedef A allocator_type; + //! The stored allocator type + typedef allocator_type stored_allocator_type; + typedef typename A::pointer pointer; + typedef typename A::value_type value_type; + typedef typename A::size_type size_type; + + basic_string_base(const allocator_type& a) + : members_(a) + { init(); } + + basic_string_base(const allocator_type& a, std::size_t n) + : members_(a) + { + this->init(); + this->allocate_initial_block(n); + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_string_base(const detail::moved_object >& b) + : members_(b.get().members_) + { + init(); + this->swap(b.get()); + } + #else + basic_string_base(basic_string_base && b) + : members_(b.members_) + { + init(); + this->swap(b); + } + #endif + + ~basic_string_base() + { + this->deallocate_block(); + if(!this->is_short()){ + static_cast(static_cast(&this->members_.m_repr.r))->~long_t(); + } + } + + private: + + //This is the structure controlling a long string + struct long_t + { + size_type is_short : 1; + size_type length : (sizeof(size_type)*CHAR_BIT - 1); + size_type storage; + pointer start; + + long_t() + {} + + long_t(const long_t &other) + { + this->is_short = other.is_short; + length = other.length; + storage = other.storage; + start = other.start; + } + + long_t &operator =(const long_t &other) + { + this->is_short = other.is_short; + length = other.length; + storage = other.storage; + start = other.start; + return *this; + } + }; + + //This basic type should have the same alignment as long_t +//iG typedef typename type_with_alignment::value>::type +// long_alignment_type; + typedef void *long_alignment_type; + BOOST_STATIC_ASSERT((detail::alignment_of::value % + detail::alignment_of::value) == 0); + + + //This type is the first part of the structure controlling a short string + //The "data" member stores + struct short_header + { + unsigned char is_short : 1; + unsigned char length : (CHAR_BIT - 1); + }; + + //This type has the same alignment and size as long_t but it's POD + //so, unlike long_t, it can be placed in a union + struct long_raw_t + { + long_alignment_type a; + unsigned char b[sizeof(long_t) - sizeof(long_alignment_type)]; + }; + + protected: + static const size_type MinInternalBufferChars = 8; + static const size_type AlignmentOfValueType = + alignment_of::value; + static const size_type ShortDataOffset = + detail::ct_rounded_size::value; + static const size_type ZeroCostInternalBufferChars = + (sizeof(long_t) - ShortDataOffset)/sizeof(value_type); + static const size_type UnalignedFinalInternalBufferChars = + (ZeroCostInternalBufferChars > MinInternalBufferChars) ? + ZeroCostInternalBufferChars : MinInternalBufferChars; + + struct short_t + { + short_header h; + value_type data[UnalignedFinalInternalBufferChars]; + }; + + union repr_t + { + long_raw_t r; + short_t s; + + short_t &short_repr() const + { return *const_cast(&s); } + + long_t &long_repr() const + { return *static_cast(const_cast(static_cast(&r))); } + }; + + struct members_holder + : public A + { + members_holder(const A &a) + : A(a) + {} + + repr_t m_repr; + } members_; + + const A &alloc() const + { return members_; } + + A &alloc() + { return members_; } + + static const size_type InternalBufferChars = (sizeof(repr_t) - ShortDataOffset)/sizeof(value_type); + + private: + + static const size_type MinAllocation = InternalBufferChars*2; + + protected: + bool is_short() const + { return static_cast(this->members_.m_repr.s.h.is_short != 0); } + + void is_short(bool yes) + { + if(yes && !this->is_short()){ + static_cast(static_cast(&this->members_.m_repr.r))->~long_t(); + } + else{ + new(static_cast(&this->members_.m_repr.r))long_t(); + } + this->members_.m_repr.s.h.is_short = yes; + } + + private: + void init() + { + this->members_.m_repr.s.h.is_short = 1; + this->members_.m_repr.s.h.length = 0; + } + + protected: + + typedef detail::integral_constant allocator_v1; + typedef detail::integral_constant allocator_v2; + typedef detail::integral_constant::value> alloc_version; + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, pointer reuse = 0) + { + if(this->is_short() && (command & (expand_fwd | expand_bwd)) ){ + reuse = pointer(0); + command &= ~(expand_fwd | expand_bwd); + } + return this->allocation_command + (command, limit_size, preferred_size, received_size, reuse, alloc_version()); + } + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, + const pointer &reuse, + allocator_v1) + { + (void)limit_size; + (void)reuse; + if(!(command & allocate_new)) + return std::pair(pointer(0), 0); + received_size = preferred_size; + return std::make_pair(this->alloc().allocate(received_size), false); + } + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, + pointer reuse, + allocator_v2) + { + return this->alloc().allocation_command(command, limit_size, preferred_size, + received_size, reuse); + } + + size_type next_capacity(size_type additional_objects) const + { return get_next_capacity(this->alloc().max_size(), this->priv_storage(), additional_objects); } + + void deallocate(pointer p, std::size_t n) + { + if (p && (n > InternalBufferChars)) + this->alloc().deallocate(p, n); + } + + void construct(pointer p, const value_type &value = value_type()) + { new((void*)detail::get_pointer(p)) value_type(value); } + + void destroy(pointer p, size_type n) + { + for(; n--; ++p) + detail::get_pointer(p)->~value_type(); + } + + void destroy(pointer p) + { detail::get_pointer(p)->~value_type(); } + + void allocate_initial_block(std::size_t n) + { + if (n <= this->max_size()) { + if(n > InternalBufferChars){ + size_type new_cap = this->next_capacity(n); + pointer p = this->allocation_command(allocate_new, n, new_cap, new_cap).first; + this->is_short(false); + this->priv_addr(p); + this->priv_size(0); + this->priv_storage(new_cap); + } + } + else + throw_length_error(); + } + + void deallocate_block() + { this->deallocate(this->priv_addr(), this->priv_storage()); } + + std::size_t max_size() const + { return this->alloc().max_size() - 1; } + + // Helper functions for exception handling. + void throw_length_error() const + { throw(std::length_error("basic_string")); } + + void throw_out_of_range() const + { throw(std::out_of_range("basic_string")); } + + protected: + size_type priv_capacity() const + { return this->priv_storage() - 1; } + + pointer priv_addr() const + { return this->is_short() ? pointer(&this->members_.m_repr.short_repr().data[0]) : this->members_.m_repr.long_repr().start; } + + void priv_addr(pointer addr) + { this->members_.m_repr.long_repr().start = addr; } + + size_type priv_storage() const + { return this->is_short() ? InternalBufferChars : this->members_.m_repr.long_repr().storage; } + + void priv_storage(size_type storage) + { + if(!this->is_short()) + this->members_.m_repr.long_repr().storage = storage; + } + + size_type priv_size() const + { return this->is_short() ? this->members_.m_repr.short_repr().h.length : this->members_.m_repr.long_repr().length; } + + void priv_size(size_type sz) + { + if(this->is_short()) + this->members_.m_repr.s.h.length = (unsigned char)sz; + else + this->members_.m_repr.long_repr().length = static_cast(sz); + } + + void swap(basic_string_base& other) + { + if(this->is_short()){ + if(other.is_short()){ + std::swap(this->members_.m_repr, other.members_.m_repr); + } + else{ + repr_t copied(this->members_.m_repr); + this->members_.m_repr.long_repr() = other.members_.m_repr.long_repr(); + other.members_.m_repr = copied; + } + } + else{ + if(other.is_short()){ + repr_t copied(other.members_.m_repr); + other.members_.m_repr.long_repr() = this->members_.m_repr.long_repr(); + this->members_.m_repr = copied; + } + else{ + std::swap(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr()); + } + } + + allocator_type & this_al = this->alloc(), &other_al = other.alloc(); + if(this_al != other_al){ + detail::do_swap(this_al, other_al); + } + } +}; +/// @endcond + +} //namespace detail { + + +//! The basic_string class represents a Sequence of characters. It contains all the +//! usual operations of a Sequence, and, additionally, it contains standard string +//! operations such as search and concatenation. +//! +//! The basic_string class is parameterized by character type, and by that type's +//! Character Traits. +//! +//! This class has performance characteristics very much like vector<>, meaning, +//! for example, that it does not perform reference-count or copy-on-write, and that +//! concatenation of two strings is an O(N) operation. +//! +//! Some of basic_string's member functions use an unusual method of specifying positions +//! and ranges. In addition to the conventional method using iterators, many of +//! basic_string's member functions use a single value pos of type size_type to represent a +//! position (in which case the position is begin() + pos, and many of basic_string's +//! member functions use two values, pos and n, to represent a range. In that case pos is +//! the beginning of the range and n is its size. That is, the range is +//! [begin() + pos, begin() + pos + n). +//! +//! Note that the C++ standard does not specify the complexity of basic_string operations. +//! In this implementation, basic_string has performance characteristics very similar to +//! those of vector: access to a single character is O(1), while copy and concatenation +//! are O(N). +//! +//! In this implementation, begin(), +//! end(), rbegin(), rend(), operator[], c_str(), and data() do not invalidate iterators. +//! In this implementation, iterators are only invalidated by member functions that +//! explicitly change the string's contents. +template +class basic_string + : private detail::basic_string_base +{ + /// @cond + private: + typedef detail::basic_string_base base_t; + static const typename base_t::size_type InternalBufferChars = base_t::InternalBufferChars; + + protected: + // A helper class to use a char_traits as a function object. + + template + struct Eq_traits + : public std::binary_function + { + bool operator()(const typename Tr::char_type& x, + const typename Tr::char_type& y) const + { return Tr::eq(x, y); } + }; + + template + struct Not_within_traits + : public std::unary_function + { + typedef const typename Tr::char_type* Pointer; + const Pointer m_first; + const Pointer m_last; + + Not_within_traits(Pointer f, Pointer l) + : m_first(f), m_last(l) {} + + bool operator()(const typename Tr::char_type& x) const + { + return std::find_if(m_first, m_last, + std::bind1st(Eq_traits(), x)) == m_last; + } + }; + /// @endcond + + public: + //! The allocator type + typedef A allocator_type; + //! The stored allocator type + typedef allocator_type stored_allocator_type; + //! The type of object, CharT, stored in the string + typedef CharT value_type; + //! The second template parameter Traits + typedef Traits traits_type; + //! Pointer to CharT + typedef typename A::pointer pointer; + //! Const pointer to CharT + typedef typename A::const_pointer const_pointer; + //! Reference to CharT + typedef typename A::reference reference; + //! Const reference to CharT + typedef typename A::const_reference const_reference; + //! An unsigned integral type + typedef typename A::size_type size_type; + //! A signed integral type + typedef typename A::difference_type difference_type; + //! Iterator used to iterate through a string. It's a Random Access Iterator + typedef pointer iterator; + //! Const iterator used to iterate through a string. It's a Random Access Iterator + typedef const_pointer const_iterator; + //! Iterator used to iterate backwards through a string + typedef std::reverse_iterator reverse_iterator; + //! Const iterator used to iterate backwards through a string + typedef std::reverse_iterator const_reverse_iterator; + //! The largest possible value of type size_type. That is, size_type(-1). + static const size_type npos; + + /// @cond + private: + typedef constant_iterator cvalue_iterator; + /// @endcond + + public: // Constructor, destructor, assignment. + /// @cond + struct reserve_t {}; + /// @endcond + + basic_string(reserve_t, std::size_t n, + const allocator_type& a = allocator_type()) + : base_t(a, n + 1) + { this->priv_terminate_string(); } + + //! Effects: Constructs a basic_string taking the allocator as parameter. + //! + //! Throws: If allocator_type's copy constructor throws. + explicit basic_string(const allocator_type& a = allocator_type()) + : base_t(a, InternalBufferChars) + { this->priv_terminate_string(); } + + //! Effects: Copy constructs a basic_string. + //! + //! Postcondition: x == *this. + //! + //! Throws: If allocator_type's default constructor or copy constructor throws. + basic_string(const basic_string& s) + : base_t(s.alloc()) + { this->priv_range_initialize(s.begin(), s.end()); } + + //! Effects: Move constructor. Moves mx's resources to *this. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_string(const detail::moved_object& s) + : base_t(detail::move_impl((base_t&)s.get())) + {} + #else + basic_string(basic_string && s) + : base_t(detail::move_impl((base_t&)s)) + {} + #endif + + //! Effects: Constructs a basic_string taking the allocator as parameter, + //! and is initialized by a specific number of characters of the s string. + basic_string(const basic_string& s, size_type pos, size_type n = npos, + const allocator_type& a = allocator_type()) + : base_t(a) + { + if (pos > s.size()) + this->throw_out_of_range(); + else + this->priv_range_initialize + (s.begin() + pos, s.begin() + pos + min_value(n, s.size() - pos)); + } + + //! Effects: Constructs a basic_string taking the allocator as parameter, + //! and is initialized by a specific number of characters of the s c-string. + basic_string(const CharT* s, size_type n, + const allocator_type& a = allocator_type()) + : base_t(a) + { this->priv_range_initialize(s, s + n); } + + //! Effects: Constructs a basic_string taking the allocator as parameter, + //! and is initialized by the null-terminated s c-string. + basic_string(const CharT* s, + const allocator_type& a = allocator_type()) + : base_t(a) + { this->priv_range_initialize(s, s + Traits::length(s)); } + + //! Effects: Constructs a basic_string taking the allocator as parameter, + //! and is initialized by n copies of c. + basic_string(size_type n, CharT c, + const allocator_type& a = allocator_type()) + : base_t(a) + { + this->priv_range_initialize(cvalue_iterator(c, n), + cvalue_iterator()); + } + + //! Effects: Constructs a basic_string taking the allocator as parameter, + //! and a range of iterators. + template + basic_string(InputIterator f, InputIterator l, + const allocator_type& a = allocator_type()) + : base_t(a) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = detail::is_convertible::value; + typedef detail::bool_ Result; + this->priv_initialize_dispatch(f, l, Result()); + } + + //! Effects: Destroys the basic_string. All used memory is deallocated. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + ~basic_string() + {} + + //! Effects: Copy constructs a string. + //! + //! Postcondition: x == *this. + //! + //! Complexity: Linear to the elements x contains. + basic_string& operator=(const basic_string& s) + { + if (&s != this) + this->assign(s.begin(), s.end()); + return *this; + } + + //! Effects: Move constructor. Moves mx's resources to *this. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_string& operator=(const detail::moved_object& ms) + { + basic_string &s = ms.get(); + if (&s != this){ + this->swap(s); + } + return *this; + } + #else + basic_string& operator=(basic_string && ms) + { + basic_string &s = ms; + if (&s != this){ + this->swap(s); + } + return *this; + } + #endif + + //! Effects: Assignment from a null-terminated c-string. + basic_string& operator=(const CharT* s) + { return this->assign(s, s + Traits::length(s)); } + + //! Effects: Assignment from character. + basic_string& operator=(CharT c) + { return this->assign(static_cast(1), c); } + + //! Effects: Returns an iterator to the first element contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return this->priv_addr(); } + + //! Effects: Returns a const_iterator to the first element contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return this->priv_addr(); } + + //! Effects: Returns an iterator to the end of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return this->priv_addr() + this->priv_size(); } + + //! Effects: Returns a const_iterator to the end of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return this->priv_addr() + this->priv_size(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return reverse_iterator(this->priv_addr() + this->priv_size()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return const_reverse_iterator(this->priv_addr() + this->priv_size()); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return reverse_iterator(this->priv_addr()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return const_reverse_iterator(this->priv_addr()); } + + //! Effects: Returns a copy of the internal allocator. + //! + //! Throws: If allocator's copy constructor throws. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return this->alloc(); } + + //! Effects: Returns the number of the elements contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return this->priv_size(); } + + //! Effects: Returns the number of the elements contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type length() const + { return this->size(); } + + //! Effects: Returns the largest possible size of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return base_t::max_size(); } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are copy constructed from x. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type n, CharT c) + { + if (n <= size()) + this->erase(this->begin() + n, this->end()); + else + this->append(n - this->size(), c); + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are default constructed. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type n) + { resize(n, this->priv_null()); } + + //! Effects: If n is less than or equal to capacity(), this call has no + //! effect. Otherwise, it is a request for allocation of additional memory. + //! If the request is successful, then capacity() is greater than or equal to + //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged. + //! + //! Throws: If memory allocation allocation throws or T's copy constructor throws. + void reserve(size_type res_arg) + { + if (res_arg > this->max_size()) + this->throw_length_error(); + + if (this->capacity() < res_arg){ + size_type n = max_value(res_arg, this->size()) + 1; + size_type new_cap = this->next_capacity(n); + pointer new_start = this->allocation_command + (allocate_new, n, new_cap, new_cap).first; + size_type new_length = 0; + + new_length += priv_uninitialized_copy + (this->priv_addr(), this->priv_addr() + this->priv_size(), new_start); + this->priv_construct_null(new_start + new_length); + this->deallocate_block(); + this->is_short(false); + this->priv_addr(new_start); + this->priv_size(new_length); + this->priv_storage(new_cap); + } + } + + //! Effects: Number of elements for which memory has been allocated. + //! capacity() is always greater than or equal to size(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type capacity() const + { return this->priv_capacity(); } + + //! Effects: Erases all the elements of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements in the vector. + void clear() + { + if (!empty()) { + Traits::assign(*this->priv_addr(), this->priv_null()); + this->priv_size(0); + } + } + + //! Effects: Returns true if the vector contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return !this->priv_size(); } + + //! Requires: size() < n. + //! + //! Effects: Returns a reference to the nth element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference operator[](size_type n) + { return *(this->priv_addr() + n); } + + //! Requires: size() < n. + //! + //! Effects: Returns a const reference to the nth element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference operator[](size_type n) const + { return *(this->priv_addr() + n); } + + //! Requires: size() < n. + //! + //! Effects: Returns a reference to the nth element + //! from the beginning of the container. + //! + //! Throws: std::range_error if n >= size() + //! + //! Complexity: Constant. + reference at(size_type n) { + if (n >= size()) + this->throw_out_of_range(); + return *(this->priv_addr() + n); + } + + //! Requires: size() < n. + //! + //! Effects: Returns a const reference to the nth element + //! from the beginning of the container. + //! + //! Throws: std::range_error if n >= size() + //! + //! Complexity: Constant. + const_reference at(size_type n) const { + if (n >= size()) + this->throw_out_of_range(); + return *(this->priv_addr() + n); + } + + //! Effects: Appends string s to *this. + basic_string& operator+=(const basic_string& s) + { return this->append(s); } + + //! Effects: Appends c-string s to *this. + basic_string& operator+=(const CharT* s) + { return this->append(s); } + + //! Effects: Appends character c to *this. + basic_string& operator+=(CharT c) + { this->push_back(c); return *this; } + + //! Effects: Appends string s to *this. + basic_string& append(const basic_string& s) + { return this->append(s.begin(), s.end()); } + + //! Effects: Appends the range [pos, pos + n) from string s to *this. + basic_string& append(const basic_string& s, size_type pos, size_type n) + { + if (pos > s.size()) + this->throw_out_of_range(); + return this->append(s.begin() + pos, + s.begin() + pos + min_value(n, s.size() - pos)); + } + + //! Effects: Appends the range [s, s + n) from c-string s to *this. + basic_string& append(const CharT* s, size_type n) + { return this->append(s, s + n); } + + //! Effects: Appends the c-string s to *this. + basic_string& append(const CharT* s) + { return this->append(s, s + Traits::length(s)); } + + //! Effects: Appends the n times the character c to *this. + basic_string& append(size_type n, CharT c) + { return this->append(cvalue_iterator(c, n), cvalue_iterator()); } + + //! Effects: Appends the range [first, last) *this. + template + basic_string& append(InputIter first, InputIter last) + { this->insert(this->end(), first, last); return *this; } + + //! Effects: Inserts a copy of c at the end of the vector. + void push_back(CharT c) + { + if (this->priv_size() < this->capacity()){ + this->priv_construct_null(this->priv_addr() + (this->priv_size() + 1)); + Traits::assign(this->priv_addr()[this->priv_size()], c); + this->priv_size(this->priv_size()+1); + } + else{ + //No enough memory, insert a new object at the end + this->append((size_type)1, c); + } + } + + //! Effects: Removes the last element from the vector. + void pop_back() + { + Traits::assign(this->priv_addr()[this->priv_size()-1], this->priv_null()); + this->priv_size(this->priv_size()-1);; + } + + //! Effects: Assigns the value s to *this. + basic_string& assign(const basic_string& s) + { return this->operator=(s); } + + //! Effects: Moves the resources from ms *this. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_string& assign(const detail::moved_object& ms) + { return this->operator=(ms);} + #else + basic_string& assign(basic_string && ms) + { return this->operator=(ms);} + #endif + + //! Effects: Assigns the range [pos, pos + n) from s to *this. + basic_string& assign(const basic_string& s, + size_type pos, size_type n) { + if (pos > s.size()) + this->throw_out_of_range(); + return this->assign(s.begin() + pos, + s.begin() + pos + min_value(n, s.size() - pos)); + } + + //! Effects: Assigns the range [s, s + n) from s to *this. + basic_string& assign(const CharT* s, size_type n) + { return this->assign(s, s + n); } + + //! Effects: Assigns the c-string s to *this. + basic_string& assign(const CharT* s) + { return this->assign(s, s + Traits::length(s)); } + + //! Effects: Assigns the character c n-times to *this. + basic_string& assign(size_type n, CharT c) + { return this->assign(cvalue_iterator(c, n), cvalue_iterator()); } + + //! Effects: Assigns the range [first, last) to *this. + template + basic_string& assign(InputIter first, InputIter last) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = detail::is_convertible::value; + typedef detail::bool_ Result; + return this->priv_assign_dispatch(first, last, Result()); + } + + //! Effects: Assigns the range [f, l) to *this. + basic_string& assign(const CharT* f, const CharT* l) + { + const std::ptrdiff_t n = l - f; + if (static_cast(n) <= size()) { + Traits::copy(detail::get_pointer(this->priv_addr()), f, n); + this->erase(this->priv_addr() + n, this->priv_addr() + this->priv_size()); + } + else { + Traits::copy(detail::get_pointer(this->priv_addr()), f, this->priv_size()); + this->append(f + this->priv_size(), l); + } + return *this; + } + + //! Effects: Inserts the string s before pos. + basic_string& insert(size_type pos, const basic_string& s) + { + if (pos > size()) + this->throw_out_of_range(); + if (this->size() > this->max_size() - s.size()) + this->throw_length_error(); + this->insert(this->priv_addr() + pos, s.begin(), s.end()); + return *this; + } + + //! Effects: Inserts the range [pos, pos + n) from string s before pos. + basic_string& insert(size_type pos, const basic_string& s, + size_type beg, size_type n) + { + if (pos > this->size() || beg > s.size()) + this->throw_out_of_range(); + size_type len = min_value(n, s.size() - beg); + if (this->size() > this->max_size() - len) + this->throw_length_error(); + const CharT *beg_ptr = detail::get_pointer(s.begin()) + beg; + const CharT *end_ptr = beg_ptr + len; + this->insert(this->priv_addr() + pos, beg_ptr, end_ptr); + return *this; + } + + //! Effects: Inserts the range [s, s + n) before pos. + basic_string& insert(size_type pos, const CharT* s, size_type n) + { + if (pos > this->size()) + this->throw_out_of_range(); + if (this->size() > this->max_size() - n) + this->throw_length_error(); + this->insert(this->priv_addr() + pos, s, s + n); + return *this; + } + + //! Effects: Inserts the c-string s before pos. + basic_string& insert(size_type pos, const CharT* s) + { + if (pos > size()) + this->throw_out_of_range(); + size_type len = Traits::length(s); + if (this->size() > this->max_size() - len) + this->throw_length_error(); + this->insert(this->priv_addr() + pos, s, s + len); + return *this; + } + + //! Effects: Inserts the character c n-times before pos. + basic_string& insert(size_type pos, size_type n, CharT c) + { + if (pos > this->size()) + this->throw_out_of_range(); + if (this->size() > this->max_size() - n) + this->throw_length_error(); + this->insert(this->priv_addr() + pos, n, c); + return *this; + } + + //! Effects: Inserts the character c before position. + iterator insert(iterator position, CharT c) + { + size_type new_offset = position - this->priv_addr() + 1; + this->insert(position, cvalue_iterator(c, 1), + cvalue_iterator()); + return this->priv_addr() + new_offset; + } + + //! Effects: Inserts the character c n-times before position. + void insert(iterator position, std::size_t n, CharT c) + { + this->insert(position, cvalue_iterator(c, n), + cvalue_iterator()); + } + + //! Effects: Inserts the range [first, last) before position. + template + void insert(iterator p, InputIter first, InputIter last) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = detail::is_convertible::value; + typedef detail::bool_ Result; + this->priv_insert_dispatch(p, first, last, Result()); + } + + //! Effects: Inserts the range [pos, pos + n). + basic_string& erase(size_type pos = 0, size_type n = npos) + { + if (pos > size()) + this->throw_out_of_range(); + erase(this->priv_addr() + pos, this->priv_addr() + pos + min_value(n, size() - pos)); + return *this; + } + + //! Effects: Erases the character pointed by position. + iterator erase(iterator position) + { + // The move includes the terminating null. + Traits::move(detail::get_pointer(position), + detail::get_pointer(position + 1), + this->priv_size() - (position - this->priv_addr())); + this->priv_size(this->priv_size()-1); + return position; + } + + //! Effects: Erases the range [first, last). + iterator erase(iterator first, iterator last) + { + if (first != last) { // The move includes the terminating null. + size_type num_erased = last - first; + Traits::move(detail::get_pointer(first), + detail::get_pointer(last), + (this->priv_size() + 1)-(last - this->priv_addr())); + size_type new_length = this->priv_size() - num_erased; + this->priv_size(new_length); + } + return first; + } + + //! Effects: Replaces a substring of *this with the string s. + basic_string& replace(size_type pos, size_type n, + const basic_string& s) + { + if (pos > size()) + this->throw_out_of_range(); + const size_type len = min_value(n, size() - pos); + if (this->size() - len >= this->max_size() - s.size()) + this->throw_length_error(); + return this->replace(this->priv_addr() + pos, this->priv_addr() + pos + len, + s.begin(), s.end()); + } + + //! Effects: Replaces a substring of *this with a substring of s. + basic_string& replace(size_type pos1, size_type n1, + const basic_string& s, + size_type pos2, size_type n2) + { + if (pos1 > size() || pos2 > s.size()) + this->throw_out_of_range(); + const size_type len1 = min_value(n1, size() - pos1); + const size_type len2 = min_value(n2, s.size() - pos2); + if (this->size() - len1 >= this->max_size() - len2) + this->throw_length_error(); + return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len1, + s.priv_addr() + pos2, s.priv_addr() + pos2 + len2); + } + + //! Effects: Replaces a substring of *this with the first n1 characters of s. + basic_string& replace(size_type pos, size_type n1, + const CharT* s, size_type n2) + { + if (pos > size()) + this->throw_out_of_range(); + const size_type len = min_value(n1, size() - pos); + if (n2 > this->max_size() || size() - len >= this->max_size() - n2) + this->throw_length_error(); + return this->replace(this->priv_addr() + pos, this->priv_addr() + pos + len, + s, s + n2); + } + + //! Effects: Replaces a substring of *this with a null-terminated character array. + basic_string& replace(size_type pos, size_type n1, + const CharT* s) + { + if (pos > size()) + this->throw_out_of_range(); + const size_type len = min_value(n1, size() - pos); + const size_type n2 = Traits::length(s); + if (n2 > this->max_size() || size() - len >= this->max_size() - n2) + this->throw_length_error(); + return this->replace(this->priv_addr() + pos, this->priv_addr() + pos + len, + s, s + Traits::length(s)); + } + + //! Effects: Replaces a substring of *this with n1 copies of c. + basic_string& replace(size_type pos, size_type n1, + size_type n2, CharT c) + { + if (pos > size()) + this->throw_out_of_range(); + const size_type len = min_value(n1, size() - pos); + if (n2 > this->max_size() || size() - len >= this->max_size() - n2) + this->throw_length_error(); + return this->replace(this->priv_addr() + pos, this->priv_addr() + pos + len, n2, c); + } + + //! Effects: Replaces a substring of *this with the string s. + basic_string& replace(iterator first, iterator last, + const basic_string& s) + { return this->replace(first, last, s.begin(), s.end()); } + + //! Effects: Replaces a substring of *this with the first n characters of s. + basic_string& replace(iterator first, iterator last, + const CharT* s, size_type n) + { return this->replace(first, last, s, s + n); } + + //! Effects: Replaces a substring of *this with a null-terminated character array. + basic_string& replace(iterator first, iterator last, + const CharT* s) + { return this->replace(first, last, s, s + Traits::length(s)); } + + //! Effects: Replaces a substring of *this with n copies of c. + basic_string& replace(iterator first, iterator last, + size_type n, CharT c) + { + const size_type len = static_cast(last - first); + if (len >= n) { + Traits::assign(detail::get_pointer(first), n, c); + erase(first + n, last); + } + else { + Traits::assign(detail::get_pointer(first), len, c); + insert(last, n - len, c); + } + return *this; + } + + //! Effects: Replaces a substring of *this with the range [f, l) + template + basic_string& replace(iterator first, iterator last, + InputIter f, InputIter l) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = detail::is_convertible::value; + typedef detail::bool_ Result; + return this->priv_replace_dispatch(first, last, f, l, Result()); + } + + //! Effects: Copies a substring of *this to a buffer. + size_type copy(CharT* s, size_type n, size_type pos = 0) const + { + if (pos > size()) + this->throw_out_of_range(); + const size_type len = min_value(n, size() - pos); + Traits::copy(s, detail::get_pointer(this->priv_addr() + pos), len); + return len; + } + + //! Effects: Swaps the contents of two strings. + void swap(basic_string& s) + { base_t::swap(s); } + + //! Effects: Swaps the contents of two strings. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(const detail::moved_object& ms) + { this->swap(ms.get()); } + #else + void swap(basic_string && ms) + { this->swap(ms); } + #endif + + //! Returns: Returns a pointer to a null-terminated array of characters + //! representing the string's contents. For any string s it is guaranteed + //! that the first s.size() characters in the array pointed to by s.c_str() + //! are equal to the character in s, and that s.c_str()[s.size()] is a null + //! character. Note, however, that it not necessarily the first null character. + //! Characters within a string are permitted to be null. + const CharT* c_str() const + { return detail::get_pointer(this->priv_addr()); } + + //! Returns: Returns a pointer to an array of characters, not necessarily + //! null-terminated, representing the string's contents. data() is permitted, + //! but not required, to be identical to c_str(). The first size() characters + //! of that array are guaranteed to be identical to the characters in *this. + //! The return value of data() is never a null pointer, even if size() is zero. + const CharT* data() const + { return detail::get_pointer(this->priv_addr()); } + + //! Effects: Searches for s as a substring of *this, beginning at + //! character pos of *this. + size_type find(const basic_string& s, size_type pos = 0) const + { return find(s.c_str(), pos, s.size()); } + + //! Effects: Searches for a null-terminated character array as a + //! substring of *this, beginning at character pos of *this. + size_type find(const CharT* s, size_type pos = 0) const + { return find(s, pos, Traits::length(s)); } + + //! Effects: Searches for the first n characters of s as a substring + //! of *this, beginning at character pos of *this. + size_type find(const CharT* s, size_type pos, size_type n) const + { + if (pos + n > size()) + return npos; + else { + pointer finish = this->priv_addr() + this->priv_size(); + const const_iterator result = + std::search(detail::get_pointer(this->priv_addr() + pos), + detail::get_pointer(finish), + s, s + n, Eq_traits()); + return result != finish ? result - begin() : npos; + } + } + + //! Effects: Searches for the character c, beginning at character + //! position pos. + size_type find(CharT c, size_type pos = 0) const + { + if (pos >= size()) + return npos; + else { + pointer finish = this->priv_addr() + this->priv_size(); + const const_iterator result = + std::find_if(this->priv_addr() + pos, finish, + std::bind2nd(Eq_traits(), c)); + return result != finish ? result - begin() : npos; + } + } + + //! Effects: Searches backward for s as a substring of *this, + //! beginning at character position min(pos, size()) + size_type rfind(const basic_string& s, size_type pos = npos) const + { return rfind(s.c_str(), pos, s.size()); } + + //! Effects: Searches backward for a null-terminated character array + //! as a substring of *this, beginning at character min(pos, size()) + size_type rfind(const CharT* s, size_type pos = npos) const + { return rfind(s, pos, Traits::length(s)); } + + //! Effects: Searches backward for the first n characters of s as a + //! substring of *this, beginning at character position min(pos, size()). + size_type rfind(const CharT* s, size_type pos, size_type n) const + { + const std::size_t len = size(); + + if (n > len) + return npos; + else if (n == 0) + return min_value(len, pos); + else { + const const_iterator last = begin() + min_value(len - n, pos) + n; + const const_iterator result = find_end(begin(), last, + s, s + n, + Eq_traits()); + return result != last ? result - begin() : npos; + } + } + + //! Effects: Searches backward for a null-terminated character array + //! as a substring of *this, beginning at character min(pos, size()). + size_type rfind(CharT c, size_type pos = npos) const + { + const size_type len = size(); + + if (len < 1) + return npos; + else { + const const_iterator last = begin() + min_value(len - 1, pos) + 1; + const_reverse_iterator rresult = + std::find_if(const_reverse_iterator(last), rend(), + std::bind2nd(Eq_traits(), c)); + return rresult != rend() ? (rresult.base() - 1) - begin() : npos; + } + } + + //! Effects: Searches within *this, beginning at pos, for the first + //! character that is equal to any character within s. + size_type find_first_of(const basic_string& s, size_type pos = 0) const + { return find_first_of(s.c_str(), pos, s.size()); } + + //! Effects: Searches within *this, beginning at pos, for the first + //! character that is equal to any character within s. + size_type find_first_of(const CharT* s, size_type pos = 0) const + { return find_first_of(s, pos, Traits::length(s)); } + + //! Effects: Searches within *this, beginning at pos, for the first + //! character that is equal to any character within the first n characters of s. + size_type find_first_of(const CharT* s, size_type pos, + size_type n) const + { + if (pos >= size()) + return npos; + else { + pointer finish = this->priv_addr() + this->priv_size(); + const_iterator result = std::find_first_of(this->priv_addr() + pos, finish, + s, s + n, + Eq_traits()); + return result != finish ? result - begin() : npos; + } + } + + //! Effects: Searches within *this, beginning at pos, for the first + //! character that is equal to c. + size_type find_first_of(CharT c, size_type pos = 0) const + { return find(c, pos); } + + //! Effects: Searches backward within *this, beginning at min(pos, size()), + //! for the first character that is equal to any character within s. + size_type find_last_of(const basic_string& s, + size_type pos = npos) const + { return find_last_of(s.c_str(), pos, s.size()); } + + //! Effects: Searches backward *this, beginning at min(pos, size()), for + //! the first character that is equal to any character within s. + size_type find_last_of(const CharT* s, size_type pos = npos) const + { return find_last_of(s, pos, Traits::length(s)); } + + //! Effects: Searches backward within *this, beginning at min(pos, size()), + //! for the first character that is equal to any character within the first n + //! characters of s. + size_type find_last_of(const CharT* s, size_type pos, size_type n) const + { + const size_type len = size(); + + if (len < 1) + return npos; + else { + const const_iterator last = this->priv_addr() + min_value(len - 1, pos) + 1; + const const_reverse_iterator rresult = + std::find_first_of(const_reverse_iterator(last), rend(), + s, s + n, + Eq_traits()); + return rresult != rend() ? (rresult.base() - 1) - this->priv_addr() : npos; + } + } + + //! Effects: Searches backward *this, beginning at min(pos, size()), for + //! the first character that is equal to c. + size_type find_last_of(CharT c, size_type pos = npos) const + { return rfind(c, pos); } + + //! Effects: Searches within *this, beginning at pos, for the first + //! character that is not equal to any character within s. + size_type find_first_not_of(const basic_string& s, + size_type pos = 0) const + { return find_first_not_of(s.c_str(), pos, s.size()); } + + //! Effects: Searches within *this, beginning at pos, for the first + //! character that is not equal to any character within s. + size_type find_first_not_of(const CharT* s, size_type pos = 0) const + { return find_first_not_of(s, pos, Traits::length(s)); } + + //! Effects: Searches within *this, beginning at pos, for the first + //! character that is not equal to any character within the first n + //! characters of s. + size_type find_first_not_of(const CharT* s, size_type pos, + size_type n) const + { + if (pos > size()) + return npos; + else { + pointer finish = this->priv_addr() + this->priv_size(); + const_iterator result = std::find_if(this->priv_addr() + pos, finish, + Not_within_traits(s, s + n)); + return result != finish ? result - this->priv_addr() : npos; + } + } + + //! Effects: Searches within *this, beginning at pos, for the first + //! character that is not equal to c. + size_type find_first_not_of(CharT c, size_type pos = 0) const + { + if (pos > size()) + return npos; + else { + pointer finish = this->priv_addr() + this->priv_size(); + const_iterator result + = std::find_if(this->priv_addr() + pos, finish, + std::not1(std::bind2nd(Eq_traits(), c))); + return result != finish ? result - begin() : npos; + } + } + + //! Effects: Searches backward within *this, beginning at min(pos, size()), + //! for the first character that is not equal to any character within s. + size_type find_last_not_of(const basic_string& s, + size_type pos = npos) const + { return find_last_not_of(s.c_str(), pos, s.size()); } + + //! Effects: Searches backward *this, beginning at min(pos, size()), + //! for the first character that is not equal to any character within s. + size_type find_last_not_of(const CharT* s, size_type pos = npos) const + { return find_last_not_of(s, pos, Traits::length(s)); } + + //! Effects: Searches backward within *this, beginning at min(pos, size()), + //! for the first character that is not equal to any character within the first + //! n characters of s. + size_type find_last_not_of(const CharT* s, size_type pos, size_type n) const + { + const size_type len = size(); + + if (len < 1) + return npos; + else { + const const_iterator last = begin() + min_value(len - 1, pos) + 1; + const const_reverse_iterator rresult = + std::find_if(const_reverse_iterator(last), rend(), + Not_within_traits(s, s + n)); + return rresult != rend() ? (rresult.base() - 1) - begin() : npos; + } + } + + //! Effects: Searches backward *this, beginning at min(pos, size()), + //! for the first character that is not equal to c. + size_type find_last_not_of(CharT c, size_type pos = npos) const + { + const size_type len = size(); + + if (len < 1) + return npos; + else { + const const_iterator last = begin() + min_value(len - 1, pos) + 1; + const_reverse_iterator rresult = + std::find_if(const_reverse_iterator(last), rend(), + std::not1(std::bind2nd(Eq_traits(), c))); + return rresult != rend() ? (rresult.base() - 1) - begin() : npos; + } + } + + //! Effects: Returns a substring of *this. + basic_string substr(size_type pos = 0, size_type n = npos) const + { + if (pos > size()) + this->throw_out_of_range(); + return basic_string(this->priv_addr() + pos, + this->priv_addr() + pos + min_value(n, size() - pos), this->alloc()); + } + + //! Effects: Three-way lexicographical comparison of s and *this. + int compare(const basic_string& s) const + { return s_compare(this->priv_addr(), this->priv_addr() + this->priv_size(), s.priv_addr(), s.priv_addr() + s.priv_size()); } + + //! Effects: Three-way lexicographical comparison of s and a substring + //! of *this. + int compare(size_type pos1, size_type n1, const basic_string& s) const + { + if (pos1 > size()) + this->throw_out_of_range(); + return s_compare(this->priv_addr() + pos1, + this->priv_addr() + pos1 + min_value(n1, size() - pos1), + s.priv_addr(), s.priv_addr() + s.priv_size()); + } + + //! Effects: Three-way lexicographical comparison of a substring of s + //! and a substring of *this. + int compare(size_type pos1, size_type n1, + const basic_string& s, + size_type pos2, size_type n2) const { + if (pos1 > size() || pos2 > s.size()) + this->throw_out_of_range(); + return s_compare(this->priv_addr() + pos1, + this->priv_addr() + pos1 + min_value(n1, size() - pos1), + s.priv_addr() + pos2, + s.priv_addr() + pos2 + min_value(n2, size() - pos2)); + } + + //! Effects: Three-way lexicographical comparison of s and *this. + int compare(const CharT* s) const + { return s_compare(this->priv_addr(), this->priv_addr() + this->priv_size(), s, s + Traits::length(s)); } + + + //! Effects: Three-way lexicographical comparison of the first + //! min(len, traits::length(s) characters of s and a substring of *this. + int compare(size_type pos1, size_type n1, const CharT* s, + size_type n2 = npos) const + { + if (pos1 > size()) + this->throw_out_of_range(); + return s_compare(this->priv_addr() + pos1, + this->priv_addr() + pos1 + min_value(n1, size() - pos1), + s, s + n2); + } + + /// @cond + private: + static int s_compare(const_pointer f1, const_pointer l1, + const_pointer f2, const_pointer l2) + { + const std::ptrdiff_t n1 = l1 - f1; + const std::ptrdiff_t n2 = l2 - f2; + const int cmp = Traits::compare(detail::get_pointer(f1), + detail::get_pointer(f2), + min_value(n1, n2)); + return cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0)); + } + + void priv_construct_null(pointer p) + { this->construct(p, 0); } + + static CharT priv_null() + { return (CharT) 0; } + + // Helper functions used by constructors. It is a severe error for + // any of them to be called anywhere except from within constructors. + void priv_terminate_string() + { this->priv_construct_null(this->priv_addr() + this->priv_size()); } + + template + void priv_range_initialize(InputIter f, InputIter l, + std::input_iterator_tag) + { + this->allocate_initial_block(InternalBufferChars); + this->priv_construct_null(this->priv_addr() + this->priv_size()); + this->append(f, l); + } + + template + void priv_range_initialize(ForwardIter f, ForwardIter l, + std::forward_iterator_tag) + { + difference_type n = std::distance(f, l); + this->allocate_initial_block(max_value(n+1, InternalBufferChars)); + priv_uninitialized_copy(f, l, this->priv_addr()); + this->priv_size(n); + this->priv_terminate_string(); + } + + template + void priv_range_initialize(InputIter f, InputIter l) + { + typedef typename std::iterator_traits::iterator_category Category; + this->priv_range_initialize(f, l, Category()); + } + + template + void priv_initialize_dispatch(Integer n, Integer x, detail::true_) + { + this->allocate_initial_block(max_value(n+1, InternalBufferChars)); + priv_uninitialized_fill_n(this->priv_addr(), n, x); + this->priv_size(n); + this->priv_terminate_string(); + } + + template + void priv_initialize_dispatch(InputIter f, InputIter l, detail::false_) + { this->priv_range_initialize(f, l); } + + template inline + void priv_uninitialized_fill_n(FwdIt first, Count count, const CharT val) + { + //Save initial position + FwdIt init = first; + + BOOST_TRY{ + //Construct objects + for (; count--; ++first){ + this->construct(first, val); + } + } + BOOST_CATCH(...){ + //Call destructors + for (; init != first; ++init){ + this->destroy(init); + } + BOOST_RETHROW + } + BOOST_CATCH_END + } + + template inline + size_type priv_uninitialized_copy(InpIt first, InpIt last, FwdIt dest) + { + //Save initial destination position + FwdIt dest_init = dest; + size_type constructed = 0; + + BOOST_TRY{ + //Try to build objects + for (; first != last; ++dest, ++first, ++constructed){ + this->construct(dest, *first); + } + } + BOOST_CATCH(...){ + //Call destructors + for (; constructed--; ++dest_init){ + this->destroy(dest_init); + } + BOOST_RETHROW + } + BOOST_CATCH_END + return (constructed); + } + + template + basic_string& priv_assign_dispatch(Integer n, Integer x, detail::true_) + { return this->assign((size_type) n, (CharT) x); } + + template + basic_string& priv_assign_dispatch(InputIter f, InputIter l, + detail::false_) + { + size_type cur = 0; + CharT *ptr = detail::get_pointer(this->priv_addr()); + while (f != l && cur != this->priv_size()) { + Traits::assign(*ptr, *f); + ++f; + ++cur; + ++ptr; + } + if (f == l) + this->erase(this->priv_addr() + cur, this->priv_addr() + this->priv_size()); + else + this->append(f, l); + return *this; + } + + template + void priv_insert(iterator p, InputIter first, InputIter last, std::input_iterator_tag) + { + for ( ; first != last; ++first, ++p) { + p = this->insert(p, *first); + } + } + + template + void priv_insert(iterator position, ForwardIter first, + ForwardIter last, std::forward_iterator_tag) + { + if (first != last) { + size_type n = std::distance(first, last); + size_type remaining = this->capacity() - this->priv_size(); + const size_type old_size = this->size(); + pointer old_start = this->priv_addr(); + bool enough_capacity = false; + std::pair allocation_ret; + size_type new_cap = 0; + + //Check if we have enough capacity + if (remaining >= n){ + enough_capacity = true; + } + else { + //Otherwise expand current buffer or allocate new storage + new_cap = this->next_capacity(n); + allocation_ret = this->allocation_command + (allocate_new | expand_fwd | expand_bwd, old_size + n + 1, + new_cap, new_cap, old_start); + + //Check forward expansion + if(old_start == allocation_ret.first){ + enough_capacity = true; + this->priv_storage(new_cap); + } + } + + //Reuse same buffer + if(enough_capacity){ + const size_type elems_after = + this->priv_size() - (position - this->priv_addr()); + size_type old_length = this->priv_size(); + if (elems_after >= n) { + pointer pointer_past_last = this->priv_addr() + this->priv_size() + 1; + priv_uninitialized_copy(this->priv_addr() + (this->priv_size() - n + 1), + pointer_past_last, pointer_past_last); + + this->priv_size(this->priv_size()+n); + Traits::move(detail::get_pointer(position + n), + detail::get_pointer(position), + (elems_after - n) + 1); + this->priv_copy(first, last, position); + } + else { + ForwardIter mid = first; + std::advance(mid, elems_after + 1); + + priv_uninitialized_copy(mid, last, this->priv_addr() + this->priv_size() + 1); + this->priv_size(this->priv_size() + (n - elems_after)); + priv_uninitialized_copy + (position, this->priv_addr() + old_length + 1, + this->priv_addr() + this->priv_size()); + this->priv_size(this->priv_size() + elems_after); + this->priv_copy(first, mid, position); + } + } + else{ + pointer new_start = allocation_ret.first; + if(!allocation_ret.second){ + //Copy data to new buffer + size_type new_length = 0; + //This can't throw, since characters are POD + new_length += priv_uninitialized_copy + (this->priv_addr(), position, new_start); + new_length += priv_uninitialized_copy + (first, last, new_start + new_length); + new_length += priv_uninitialized_copy + (position, this->priv_addr() + this->priv_size(), + new_start + new_length); + this->priv_construct_null(new_start + new_length); + + this->deallocate_block(); + this->is_short(false); + this->priv_addr(new_start); + this->priv_size(new_length); + this->priv_storage(new_cap); + } + else{ + //value_type is POD, so backwards expansion is much easier + //than with vector + value_type *oldbuf = detail::get_pointer(old_start); + value_type *newbuf = detail::get_pointer(new_start); + value_type *pos = detail::get_pointer(position); + size_type before = pos - oldbuf; + + //First move old data + Traits::move(newbuf, oldbuf, before); + Traits::move(newbuf + before + n, pos, old_size - before); + //Now initialize the new data + priv_uninitialized_copy(first, last, new_start + before); + this->priv_construct_null(new_start + (old_size + n)); + this->is_short(false); + this->priv_addr(new_start); + this->priv_size(old_size + n); + this->priv_storage(new_cap); + } + } + } + } + + template + void priv_insert_dispatch(iterator p, Integer n, Integer x, + detail::true_) + { insert(p, (size_type) n, (CharT) x); } + + template + void priv_insert_dispatch(iterator p, InputIter first, InputIter last, + detail::false_) + { + typedef typename std::iterator_traits::iterator_category Category; + priv_insert(p, first, last, Category()); + } + + template + void priv_copy(InputIterator first, InputIterator last, iterator result) + { + for ( ; first != last; ++first, ++result) + Traits::assign(*result, *first); + } + + void priv_copy(const CharT* first, const CharT* last, CharT* result) + { Traits::copy(result, first, last - first); } + + template + basic_string& priv_replace_dispatch(iterator first, iterator last, + Integer n, Integer x, + detail::true_) + { return this->replace(first, last, (size_type) n, (CharT) x); } + + template + basic_string& priv_replace_dispatch(iterator first, iterator last, + InputIter f, InputIter l, + detail::false_) + { + typedef typename std::iterator_traits::iterator_category Category; + return this->priv_replace(first, last, f, l, Category()); + } + + + template + basic_string& priv_replace(iterator first, iterator last, + InputIter f, InputIter l, std::input_iterator_tag) + { + for ( ; first != last && f != l; ++first, ++f) + Traits::assign(*first, *f); + + if (f == l) + this->erase(first, last); + else + this->insert(last, f, l); + return *this; + } + + template + basic_string& priv_replace(iterator first, iterator last, + ForwardIter f, ForwardIter l, + std::forward_iterator_tag) + { + difference_type n = std::distance(f, l); + const difference_type len = last - first; + if (len >= n) { + this->priv_copy(f, l, first); + this->erase(first + n, last); + } + else { + ForwardIter m = f; + std::advance(m, len); + this->priv_copy(f, m, first); + this->insert(last, m, l); + } + return *this; + } + /// @endcond +}; + +template +const typename basic_string::size_type +basic_string::npos + = (typename basic_string::size_type) -1; + +// ------------------------------------------------------------ +// Non-member functions. + +// Operator+ + +template +inline basic_string +operator+(const basic_string& x, + const basic_string& y) +{ + typedef basic_string str_t; + typedef typename str_t::reserve_t reserve_t; + reserve_t reserve; + str_t result(reserve, x.size() + y.size(), x.alloc()); + result.append(x); + result.append(y); + return result; +} + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline detail::moved_object > +operator+(const detail::moved_object >& mx, + const basic_string& y) +{ + mx.get() += y; + return mx; +} +#else +template +basic_string && +operator+(basic_string && mx, + const basic_string& y) +{ + mx += y; + return detail::move_impl(mx); +} +#endif + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline detail::moved_object > +operator+(const basic_string& x, + const detail::moved_object >& my) +{ + typedef typename basic_string::size_type size_type; + return my.get().replace(size_type(0), size_type(0), x); +} +#else +template +inline basic_string && +operator+(const basic_string& x, + basic_string && my) +{ + typedef typename basic_string::size_type size_type; + return my.replace(size_type(0), size_type(0), x); +} +#endif + +template +inline basic_string +operator+(const CharT* s, const basic_string& y) +{ + typedef basic_string str_t; + typedef typename str_t::reserve_t reserve_t; + reserve_t reserve; + const std::size_t n = Traits::length(s); + str_t result(reserve, n + y.size()); + result.append(s, s + n); + result.append(y); + return result; +} + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline detail::moved_object > +operator+(const CharT* s, + const detail::moved_object >& my) +{ + typedef typename basic_string::size_type size_type; + return my.get().replace(size_type(0), size_type(0), s); +} +#else +template +inline basic_string && +operator+(const CharT* s, + basic_string && my) +{ + typedef typename basic_string::size_type size_type; + return detail::move_impl(my.get().replace(size_type(0), size_type(0), s)); +} +#endif + +template +inline basic_string +operator+(CharT c, const basic_string& y) +{ + typedef basic_string str_t; + typedef typename str_t::reserve_t reserve_t; + reserve_t reserve; + str_t result(reserve, 1 + y.size()); + result.push_back(c); + result.append(y); + return result; +} + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline detail::moved_object > +operator+(CharT c, + const detail::moved_object >& my) +{ + typedef typename basic_string::size_type size_type; + return my.get().replace(size_type(0), size_type(0), &c, &c + 1); +} +#else +template +inline basic_string && +operator+(CharT c, + basic_string && my) +{ + typedef typename basic_string::size_type size_type; + return my.replace(size_type(0), size_type(0), &c, &c + 1); +} +#endif + +template +inline basic_string +operator+(const basic_string& x, const CharT* s) +{ + typedef basic_string str_t; + typedef typename str_t::reserve_t reserve_t; + reserve_t reserve; + const std::size_t n = Traits::length(s); + str_t result(reserve, x.size() + n, x.alloc()); + result.append(x); + result.append(s, s + n); + return result; +} + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline detail::moved_object > +operator+(const detail::moved_object >& mx, + const CharT* s) +{ + mx.get() += s; + return mx; +} +#else +template +basic_string && +operator+(basic_string && mx, + const CharT* s) +{ + mx += s; + return detail::move_impl(mx); +} +#endif + +template +inline basic_string +operator+(const basic_string& x, const CharT c) +{ + typedef basic_string str_t; + typedef typename str_t::reserve_t reserve_t; + reserve_t reserve; + str_t result(reserve, x.size() + 1, x.alloc()); + result.append(x); + result.push_back(c); + return result; +} + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline detail::moved_object > +operator+(const detail::moved_object >& mx, + const CharT c) +{ + mx.get() += c; + return mx; +} +#else +template +basic_string && +operator+(basic_string && mx, const CharT c) +{ + mx += c; + return detail::move_impl(mx); +} +#endif + +// Operator== and operator!= + +template +inline bool +operator==(const basic_string& x, + const basic_string& y) +{ + return x.size() == y.size() && + Traits::compare(x.data(), y.data(), x.size()) == 0; +} + +template +inline bool +operator==(const CharT* s, const basic_string& y) +{ + std::size_t n = Traits::length(s); + return n == y.size() && Traits::compare(s, y.data(), n) == 0; +} + +template +inline bool +operator==(const basic_string& x, const CharT* s) +{ + std::size_t n = Traits::length(s); + return x.size() == n && Traits::compare(x.data(), s, n) == 0; +} + +template +inline bool +operator!=(const basic_string& x, + const basic_string& y) + { return !(x == y); } + +template +inline bool +operator!=(const CharT* s, const basic_string& y) + { return !(s == y); } + +template +inline bool +operator!=(const basic_string& x, const CharT* s) + { return !(x == s); } + + +// Operator< (and also >, <=, and >=). + +template +inline bool +operator<(const basic_string& x, + const basic_string& y) +{ + return x.compare(y) < 0; +// return basic_string +// ::s_compare(x.begin(), x.end(), y.begin(), y.end()) < 0; +} + +template +inline bool +operator<(const CharT* s, const basic_string& y) +{ + return y.compare(s) > 0; +// std::size_t n = Traits::length(s); +// return basic_string +// ::s_compare(s, s + n, y.begin(), y.end()) < 0; +} + +template +inline bool +operator<(const basic_string& x, + const CharT* s) +{ + return x.compare(s) < 0; +// std::size_t n = Traits::length(s); +// return basic_string +// ::s_compare(x.begin(), x.end(), s, s + n) < 0; +} + +template +inline bool +operator>(const basic_string& x, + const basic_string& y) { + return y < x; +} + +template +inline bool +operator>(const CharT* s, const basic_string& y) { + return y < s; +} + +template +inline bool +operator>(const basic_string& x, const CharT* s) +{ + return s < x; +} + +template +inline bool +operator<=(const basic_string& x, + const basic_string& y) +{ + return !(y < x); +} + +template +inline bool +operator<=(const CharT* s, const basic_string& y) + { return !(y < s); } + +template +inline bool +operator<=(const basic_string& x, const CharT* s) + { return !(s < x); } + +template +inline bool +operator>=(const basic_string& x, + const basic_string& y) + { return !(x < y); } + +template +inline bool +operator>=(const CharT* s, const basic_string& y) + { return !(s < y); } + +template +inline bool +operator>=(const basic_string& x, const CharT* s) + { return !(x < s); } + +// Swap. +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline void swap(basic_string& x, + basic_string& y) +{ x.swap(y); } + +template +inline void swap(const detail::moved_object >& mx, + basic_string& y) +{ mx.get().swap(y); } + +template +inline void swap(basic_string& x, + const detail::moved_object >& my) +{ x.swap(my.get()); } +#else +template +inline void swap(basic_string && x, + basic_string &&y) +{ x.swap(y); } +#endif + +/// @cond +// I/O. +namespace detail { + +template +inline bool +interprocess_string_fill(std::basic_ostream& os, + std::basic_streambuf* buf, + std::size_t n) +{ + CharT f = os.fill(); + std::size_t i; + bool ok = true; + + for (i = 0; i < n; i++) + ok = ok && !Traits::eq_int_type(buf->sputc(f), Traits::eof()); + return ok; +} + +} //namespace detail { +/// @endcond + +template +std::basic_ostream& +operator<<(std::basic_ostream& os, + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + const basic_string& s) + #else + const basic_string&&s) + #endif +{ + typename std::basic_ostream::sentry sentry(os); + bool ok = false; + + if (sentry) { + ok = true; + std::size_t n = s.size(); + std::size_t pad_len = 0; + const bool left = (os.flags() & std::ios::left) != 0; + const std::size_t w = os.width(0); + std::basic_streambuf* buf = os.rdbuf(); + + if (w != 0 && n < w) + pad_len = w - n; + + if (!left) + ok = detail::interprocess_string_fill(os, buf, pad_len); + + ok = ok && + buf->sputn(s.data(), std::streamsize(n)) == std::streamsize(n); + + if (left) + ok = ok && detail::interprocess_string_fill(os, buf, pad_len); + } + + if (!ok) + os.setstate(std::ios_base::failbit); + + return os; +} + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +std::basic_ostream& +operator<<(std::basic_ostream& os, + const detail::moved_object >& ms) +{ return os << ms.get(); } +#endif + + +template +std::basic_istream& +operator>>(std::basic_istream& is, + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_string& s) + #else + basic_string&&s) + #endif +{ + typename std::basic_istream::sentry sentry(is); + + if (sentry) { + std::basic_streambuf* buf = is.rdbuf(); + const std::ctype& ctype = std::use_facet >(is.getloc()); + + s.clear(); + std::size_t n = is.width(0); + if (n == 0) + n = static_cast(-1); + else + s.reserve(n); + + while (n-- > 0) { + typename Traits::int_type c1 = buf->sbumpc(); + + if (Traits::eq_int_type(c1, Traits::eof())) { + is.setstate(std::ios_base::eofbit); + break; + } + else { + CharT c = Traits::to_char_type(c1); + + if (ctype.is(std::ctype::space, c)) { + if (Traits::eq_int_type(buf->sputbackc(c), Traits::eof())) + is.setstate(std::ios_base::failbit); + break; + } + else + s.push_back(c); + } + } + + // If we have read no characters, then set failbit. + if (s.size() == 0) + is.setstate(std::ios_base::failbit); + } + else + is.setstate(std::ios_base::failbit); + + return is; +} + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +std::basic_istream& +operator>>(std::basic_istream& is, + const detail::moved_object >& ms) +{ return is >> ms.get(); } +#endif + +template +std::basic_istream& +getline(std::istream& is, + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_string& s, + #else + basic_string&&s, + #endif + CharT delim) +{ + std::size_t nread = 0; + typename std::basic_istream::sentry sentry(is, true); + if (sentry) { + std::basic_streambuf* buf = is.rdbuf(); + s.clear(); + + int c1; + while (nread < s.max_size()) { + int c1 = buf->sbumpc(); + if (Traits::eq_int_type(c1, Traits::eof())) { + is.setstate(std::ios_base::eofbit); + break; + } + else { + ++nread; + CharT c = Traits::to_char_type(c1); + if (!Traits::eq(c, delim)) + s.push_back(c); + else + break; // Character is extracted but not appended. + } + } + } + if (nread == 0 || nread >= s.max_size()) + is.setstate(std::ios_base::failbit); + + return is; +} + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +std::basic_istream& +getline(std::istream& is, + const detail::moved_object >& ms, + CharT delim) +{ return getline(is, ms.get(), delim); } +#endif + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline std::basic_istream& +getline(std::basic_istream& is, + basic_string& s) +{ + return getline(is, s, '\n'); +} + +template +std::basic_istream& +getline(std::istream& is, + const detail::moved_object >& ms) +{ return getline(is, ms.get()); } +#else +template +std::basic_istream& +getline(std::istream& is, + basic_string && ms) +{ return getline(is, ms); } +#endif + +template +inline std::size_t hash_value(basic_string, A> const& v) +{ + return hash_range(v.begin(), v.end()); +} + +/// @cond + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = has_trivial_destructor::value }; +}; +/// @endcond + +}} //namespace boost { namespace interprocess + +#include + +#endif // BOOST_INTERPROCESS_STRING_HPP diff --git a/win32/include/boost/interprocess/containers/vector.hpp b/win32/include/boost/interprocess/containers/vector.hpp new file mode 100755 index 000000000..a5377c021 --- /dev/null +++ b/win32/include/boost/interprocess/containers/vector.hpp @@ -0,0 +1,1880 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This file comes from SGI's stl_vector.h file. Modified by Ion Gaztanaga. +// Renaming, isolating and porting to generic algorithms. Pointer typedef +// set to allocator::pointer to allow placing it in shared memory. +// +/////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 1994 +// Hewlett-Packard Company +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. Hewlett-Packard Company makes no +// representations about the suitability of this software for any +// purpose. It is provided "as is" without express or implied warranty. +// +// +// Copyright (c) 1996 +// Silicon Graphics Computer Systems, Inc. +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. Silicon Graphics makes no +// representations about the suitability of this software for any +// purpose. It is provided "as is" without express or implied warranty. + +#ifndef BOOST_INTERPROCESS_VECTOR_HPP +#define BOOST_INTERPROCESS_VECTOR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { + +/// @cond + +namespace detail { + +//! Const vector_iterator used to iterate through a vector. +template +class vector_const_iterator + : public std::iterator::value_type + ,typename std::iterator_traits::difference_type + ,typename pointer_to_other + ::value_type + >::type + ,const typename std::iterator_traits::value_type &> +{ + public: + typedef const typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename pointer_to_other::type pointer; + typedef value_type& reference; + + /// @cond + protected: + Pointer m_ptr; + + public: + Pointer get_ptr() const { return m_ptr; } + explicit vector_const_iterator(Pointer ptr) : m_ptr(ptr){} + /// @endcond + + public: + + //Constructors + vector_const_iterator() : m_ptr(0){} + + //Pointer like operators + reference operator*() const + { return *m_ptr; } + + const value_type * operator->() const + { return detail::get_pointer(m_ptr); } + + reference operator[](difference_type off) const + { return m_ptr[off]; } + + //Increment / Decrement + vector_const_iterator& operator++() + { ++m_ptr; return *this; } + + vector_const_iterator operator++(int) + { Pointer tmp = m_ptr; ++*this; return vector_const_iterator(tmp); } + + vector_const_iterator& operator--() + { --m_ptr; return *this; } + + vector_const_iterator operator--(int) + { Pointer tmp = m_ptr; --*this; return vector_const_iterator(tmp); } + + //Arithmetic + vector_const_iterator& operator+=(difference_type off) + { m_ptr += off; return *this; } + + vector_const_iterator operator+(difference_type off) const + { return vector_const_iterator(m_ptr+off); } + + friend vector_const_iterator operator+(difference_type off, const vector_const_iterator& right) + { return vector_const_iterator(off + right.m_ptr); } + + vector_const_iterator& operator-=(difference_type off) + { m_ptr -= off; return *this; } + + vector_const_iterator operator-(difference_type off) const + { return vector_const_iterator(m_ptr-off); } + + difference_type operator-(const vector_const_iterator& right) const + { return m_ptr - right.m_ptr; } + + //Comparison operators + bool operator== (const vector_const_iterator& r) const + { return m_ptr == r.m_ptr; } + + bool operator!= (const vector_const_iterator& r) const + { return m_ptr != r.m_ptr; } + + bool operator< (const vector_const_iterator& r) const + { return m_ptr < r.m_ptr; } + + bool operator<= (const vector_const_iterator& r) const + { return m_ptr <= r.m_ptr; } + + bool operator> (const vector_const_iterator& r) const + { return m_ptr > r.m_ptr; } + + bool operator>= (const vector_const_iterator& r) const + { return m_ptr >= r.m_ptr; } +}; + +//! Iterator used to iterate through a vector +template +class vector_iterator + : public vector_const_iterator +{ + public: + explicit vector_iterator(Pointer ptr) + : vector_const_iterator(ptr) + {} + + public: + typedef typename std::iterator_traits::value_type value_type; + typedef typename vector_const_iterator::difference_type difference_type; + typedef Pointer pointer; + typedef value_type& reference; + + //Constructors + vector_iterator() + {} + + //Pointer like operators + reference operator*() const + { return *this->m_ptr; } + + value_type* operator->() const + { return detail::get_pointer(this->m_ptr); } + + reference operator[](difference_type off) const + { return this->m_ptr[off]; } + + //Increment / Decrement + vector_iterator& operator++() + { ++this->m_ptr; return *this; } + + vector_iterator operator++(int) + { pointer tmp = this->m_ptr; ++*this; return vector_iterator(tmp); } + + vector_iterator& operator--() + { --this->m_ptr; return *this; } + + vector_iterator operator--(int) + { vector_iterator tmp = *this; --*this; return vector_iterator(tmp); } + + // Arithmetic + vector_iterator& operator+=(difference_type off) + { this->m_ptr += off; return *this; } + + vector_iterator operator+(difference_type off) const + { return vector_iterator(this->m_ptr+off); } + + friend vector_iterator operator+(difference_type off, const vector_iterator& right) + { return vector_iterator(off + right.m_ptr); } + + vector_iterator& operator-=(difference_type off) + { this->m_ptr -= off; return *this; } + + vector_iterator operator-(difference_type off) const + { return vector_iterator(this->m_ptr-off); } + + difference_type operator-(const vector_const_iterator& right) const + { return static_cast&>(*this) - right; } +}; + +//!This struct deallocates and allocated memory +template +struct vector_alloc_holder +{ + typedef typename A::pointer pointer; + typedef typename A::size_type size_type; + typedef typename A::value_type value_type; + + static const bool trivial_dctr = boost::has_trivial_destructor::value; + static const bool trivial_dctr_after_move = + has_trivial_destructor_after_move::value || trivial_dctr; + static const bool trivial_copy = has_trivial_copy::value; + static const bool nothrow_copy = has_nothrow_copy::value; + static const bool trivial_assign = has_trivial_assign::value; + static const bool nothrow_assign = has_nothrow_assign::value; + + //Constructor, does not throw + vector_alloc_holder(const A &a) + : members_(a) + {} + + //Constructor, does not throw + vector_alloc_holder(const vector_alloc_holder &h) + : members_(h.alloc()) + {} + + //Destructor + ~vector_alloc_holder() + { this->prot_deallocate(); } + + typedef detail::integral_constant allocator_v1; + typedef detail::integral_constant allocator_v2; + typedef detail::integral_constant::value> alloc_version; + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, const pointer &reuse = 0) + { + return allocation_command(command, limit_size, preferred_size, + received_size, reuse, alloc_version()); + } + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, + const pointer &reuse, + allocator_v1) + { + (void)limit_size; + (void)reuse; + if(!(command & allocate_new)) + return std::pair(pointer(0), 0); + received_size = preferred_size; + return std::make_pair(this->alloc().allocate(received_size), false); + } + + std::pair + allocation_command(allocation_type command, + size_type limit_size, + size_type preferred_size, + size_type &received_size, + const pointer &reuse, + allocator_v2) + { + return this->alloc().allocation_command + (command, limit_size, preferred_size, received_size, reuse); + } + + size_type next_capacity(size_type additional_objects) const + { return get_next_capacity(this->alloc().max_size(), this->members_.m_capacity, additional_objects); } + + struct members_holder + : public A + { + private: + members_holder(const members_holder&); + + public: + members_holder(const A &alloc) + : A(alloc), m_start(0), m_size(0), m_capacity(0) + {} + + pointer m_start; + size_type m_size; + size_type m_capacity; + } members_; + + protected: + void prot_deallocate() + { + if(!this->members_.m_capacity) return; + this->alloc().deallocate(this->members_.m_start, this->members_.m_capacity); + this->members_.m_start = 0; + this->members_.m_size = 0; + this->members_.m_capacity = 0; + } + + void destroy(value_type* p) + { + if(!trivial_dctr) + detail::get_pointer(p)->~value_type(); + } + + void destroy_n(value_type* p, size_type n) + { + if(!trivial_dctr) + for(; n--; ++p) p->~value_type(); + } + + A &alloc() + { return members_; } + + const A &alloc() const + { return members_; } +}; + +} //namespace detail { +/// @endcond + +//! A vector is a sequence that supports random access to elements, constant +//! time insertion and removal of elements at the end, and linear time insertion +//! and removal of elements at the beginning or in the middle. The number of +//! elements in a vector may vary dynamically; memory management is automatic. +//! boost::interprocess::vector is similar to std::vector but it's compatible +//! with shared memory and memory mapped files. +template +class vector : private detail::vector_alloc_holder +{ + /// @cond + typedef vector self_t; + typedef detail::vector_alloc_holder base_t; + /// @endcond + public: + //! The type of object, T, stored in the vector + typedef T value_type; + //! Pointer to T + typedef typename A::pointer pointer; + //! Const pointer to T + typedef typename A::const_pointer const_pointer; + //! Reference to T + typedef typename A::reference reference; + //! Const reference to T + typedef typename A::const_reference const_reference; + //! An unsigned integral type + typedef typename A::size_type size_type; + //! A signed integral type + typedef typename A::difference_type difference_type; + //! The allocator type + typedef A allocator_type; + //! The random access iterator + typedef detail::vector_iterator iterator; + //! The random access const_iterator + typedef detail::vector_const_iterator const_iterator; + + //! Iterator used to iterate backwards through a vector. + typedef std::reverse_iterator + reverse_iterator; + //! Const iterator used to iterate backwards through a vector. + typedef std::reverse_iterator + const_reverse_iterator; + //! The stored allocator type + typedef allocator_type stored_allocator_type; + + /// @cond + private: + + typedef typename base_t::allocator_v1 allocator_v1; + typedef typename base_t::allocator_v2 allocator_v2; + typedef typename base_t::alloc_version alloc_version; + + typedef constant_iterator cvalue_iterator; + typedef repeat_iterator repeat_it; + typedef detail::move_iterator repeat_move_it; + //This is the anti-exception array destructor + //to deallocate values already constructed + typedef typename detail::if_c + + ,detail::scoped_destructor_n + >::type OldArrayDestructor; + //This is the anti-exception array destructor + //to destroy objects created with copy construction + typedef typename detail::if_c + + ,detail::scoped_destructor_n + >::type UCopiedArrayDestructor; + //This is the anti-exception array deallocator + typedef typename detail::if_c + + ,detail::scoped_array_deallocator + >::type UCopiedArrayDeallocator; + + //This is the optimized move iterator for copy constructors + //so that std::copy and similar can use memcpy + typedef typename detail::if_c + ::value + #endif + ,T* + ,detail::move_iterator + >::type copy_move_it; + + //This is the optimized move iterator for assignments + //so that std::uninitialized_copy and similar can use memcpy + typedef typename detail::if_c + ::value + #endif + ,T* + ,detail::move_iterator + >::type assign_move_it; + /// @endcond + + public: + + //! Effects: Constructs a vector taking the allocator as parameter. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + explicit vector(const A& a = A()) + : base_t(a) + {} + + //! Effects: Constructs a vector that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + vector(size_type n, const T& value = T(), + const allocator_type& a = allocator_type()) + : base_t(a) + { this->insert(this->end(), n, value); } + + //! Effects: Copy constructs a vector. + //! + //! Postcondition: x == *this. + //! + //! Complexity: Linear to the elements x contains. + vector(const vector& x) + : base_t((base_t&)x) + { *this = x; } + + //! Effects: Move constructor. Moves mx's resources to *this. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + vector(const detail::moved_object >& mx) + : base_t(mx.get()) + { this->swap(mx.get()); } + #else + vector(vector && mx) + : base_t(detail::move_impl(mx)) + { this->swap(mx); } + #endif + + //! Effects: Constructs a vector that will use a copy of allocator a + //! and inserts a copy of the range [first, last) in the vector. + //! + //! Throws: If allocator_type's default constructor or copy constructor + //! throws or T's constructor taking an dereferenced InIt throws. + //! + //! Complexity: Linear to the range [first, last). + template + vector(InIt first, InIt last, const allocator_type& a = allocator_type()) + : base_t(a) + { this->assign(first, last); } + + //! Effects: Destroys the vector. All stored values are destroyed + //! and used memory is deallocated. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements. + ~vector() + { this->priv_destroy_all(); } + + //! Effects: Returns an iterator to the first element contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return iterator(this->members_.m_start); } + + //! Effects: Returns a const_iterator to the first element contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return const_iterator(this->members_.m_start); } + + //! Effects: Returns an iterator to the end of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return iterator(this->members_.m_start + this->members_.m_size); } + + //! Effects: Returns a const_iterator to the end of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return const_iterator(this->members_.m_start + this->members_.m_size); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return reverse_iterator(this->end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin()const + { return const_reverse_iterator(this->end());} + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return reverse_iterator(this->begin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return const_reverse_iterator(this->begin()); } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference front() + { return *this->members_.m_start; } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference front() const + { return *this->members_.m_start; } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference back() + { return this->members_.m_start[this->members_.m_size - 1]; } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference back() const + { return this->members_.m_start[this->members_.m_size - 1]; } + + //! Effects: Returns the number of the elements contained in the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type size() const + { return this->members_.m_size; } + + //! Effects: Returns the largest possible size of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type max_size() const + { return this->alloc().max_size(); } + + //! Effects: Number of elements for which memory has been allocated. + //! capacity() is always greater than or equal to size(). + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + size_type capacity() const + { return this->members_.m_capacity; } + + //! Effects: Returns true if the vector contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + bool empty() const + { return !this->members_.m_size; } + + //! Requires: size() < n. + //! + //! Effects: Returns a reference to the nth element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference operator[](size_type n) + { return this->members_.m_start[n]; } + + //! Requires: size() < n. + //! + //! Effects: Returns a const reference to the nth element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference operator[](size_type n) const + { return this->members_.m_start[n]; } + + //! Requires: size() < n. + //! + //! Effects: Returns a reference to the nth element + //! from the beginning of the container. + //! + //! Throws: std::range_error if n >= size() + //! + //! Complexity: Constant. + reference at(size_type n) + { this->priv_check_range(n); return this->members_.m_start[n]; } + + //! Requires: size() < n. + //! + //! Effects: Returns a const reference to the nth element + //! from the beginning of the container. + //! + //! Throws: std::range_error if n >= size() + //! + //! Complexity: Constant. + const_reference at(size_type n) const + { this->priv_check_range(n); return this->members_.m_start[n]; } + + //! Effects: Returns a copy of the internal allocator. + //! + //! Throws: If allocator's copy constructor throws. + //! + //! Complexity: Constant. + allocator_type get_allocator() const + { return this->alloc(); } + + const stored_allocator_type &get_stored_allocator() const + { return this->alloc(); } + + stored_allocator_type &get_stored_allocator() + { return this->alloc(); } + + //! Effects: If n is less than or equal to capacity(), this call has no + //! effect. Otherwise, it is a request for allocation of additional memory. + //! If the request is successful, then capacity() is greater than or equal to + //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged. + //! + //! Throws: If memory allocation allocation throws or T's copy constructor throws. + void reserve(size_type new_cap) + { + if (this->capacity() < new_cap){ + //There is not enough memory, allocate a new + //buffer or expand the old one. + bool same_buffer_start; + size_type real_cap = 0; + std::pair ret = + this->allocation_command + (allocate_new | expand_fwd | expand_bwd, + new_cap, new_cap, real_cap, this->members_.m_start); + + //Check for forward expansion + same_buffer_start = ret.second && this->members_.m_start == ret.first; + if(same_buffer_start){ + #ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS + ++this->num_expand_fwd; + #endif + this->members_.m_capacity = real_cap; + } + //If there is no forward expansion, move objects + else{ + //We will reuse insert code, so create a dummy input iterator + copy_move_it dummy_it(detail::get_pointer(this->members_.m_start)); + //Backwards (and possibly forward) expansion + if(ret.second){ + #ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS + ++this->num_expand_bwd; + #endif + this->priv_range_insert_expand_backwards + ( detail::get_pointer(ret.first) + , real_cap + , detail::get_pointer(this->members_.m_start) + , dummy_it + , dummy_it + , 0); + } + //New buffer + else{ + #ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS + ++this->num_alloc; + #endif + this->priv_range_insert_new_allocation + ( detail::get_pointer(ret.first) + , real_cap + , detail::get_pointer(this->members_.m_start) + , dummy_it + , dummy_it); + } + } + } + } + + //! Effects: Makes *this contain the same elements as x. + //! + //! Postcondition: this->size() == x.size(). *this contains a copy + //! of each of x's elements. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to the number of elements in x. + vector& operator=(const vector& x) + { + if (&x != this){ + this->assign(x.members_.m_start, x.members_.m_start + x.members_.m_size); + } + return *this; + } + + //! Effects: Move assignment. All mx's values are transferred to *this. + //! + //! Postcondition: x.empty(). *this contains a the elements x had + //! before the function. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + vector& operator=(const detail::moved_object >& mx) + { + vector &x = mx.get(); + + if (&x != this){ + this->swap(x); + x.clear(); + } + return *this; + } + #else + vector& operator=(vector && mx) + { + vector &x = mx; + + if (&x != this){ + this->swap(x); + x.clear(); + } + return *this; + } + #endif + + //! Effects: Assigns the n copies of val to *this. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void assign(size_type n, const value_type& val) + { this->assign(cvalue_iterator(val, n), cvalue_iterator()); } + + //! Effects: Assigns the the range [first, last) to *this. + //! + //! Throws: If memory allocation throws or + //! T's constructor from dereferencing InpIt throws. + //! + //! Complexity: Linear to n. + template + void assign(InIt first, InIt last) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = detail::is_convertible::value; + typedef detail::bool_ Result; + this->priv_assign_dispatch(first, last, Result()); + } + + //! Effects: Inserts a copy of x at the end of the vector. + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + void push_back(const T& x) + { + if (this->members_.m_size < this->members_.m_capacity){ + //There is more memory, just construct a new object at the end + new((void*)(detail::get_pointer(this->members_.m_start) + this->members_.m_size))value_type(x); + ++this->members_.m_size; + } + else{ + this->insert(this->end(), x); + } + } + + //! Effects: Constructs a new element in the end of the vector + //! and moves the resources of mx to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void push_back(const detail::moved_object & mx) + { + if (this->members_.m_size < this->members_.m_capacity){ + //There is more memory, just construct a new object at the end + new((void*)detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(mx); + ++this->members_.m_size; + } + else{ + this->insert(this->end(), mx); + } + } + #else + void push_back(T && mx) + { + if (this->members_.m_size < this->members_.m_capacity){ + //There is more memory, just construct a new object at the end + new((void*)detail::get_pointer(this->members_.m_start + this->members_.m_size))value_type(detail::move_impl(mx)); + ++this->members_.m_size; + } + else{ + this->insert(this->end(), detail::move_impl(mx)); + } + } + #endif + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() + //! allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(vector& x) + { + allocator_type &this_al = this->alloc(), &other_al = x.alloc(); + //Just swap internals + detail::do_swap(this->members_.m_start, x.members_.m_start); + detail::do_swap(this->members_.m_size, x.members_.m_size); + detail::do_swap(this->members_.m_capacity, x.members_.m_capacity); + + if (this_al != other_al){ + detail::do_swap(this_al, other_al); + } + } + + //! Effects: Swaps the contents of *this and x. + //! If this->allocator_type() != x.allocator_type() + //! allocators are also swapped. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(const detail::moved_object >& mx) + { + vector &x = mx.get(); + this->swap(x); + } + #else + void swap(vector && mx) + { + vector &x = mx; + this->swap(x); + } + #endif + + //! Requires: position must be a valid iterator of *this. + //! + //! Effects: Insert a copy of x before position. + //! + //! Throws: If memory allocation throws or x's copy constructor throws. + //! + //! Complexity: If position is begin() or end(), amortized constant time + //! Linear time otherwise. + iterator insert(iterator position, const T& x) + { + //Just call more general insert(pos, size, value) and return iterator + size_type n = position - begin(); + this->insert(position, (size_type)1, x); + return iterator(this->members_.m_start + n); + } + + //! Requires: position must be a valid iterator of *this. + //! + //! Effects: Insert a new element before position with mx's resources. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: If position is begin() or end(), amortized constant time + //! Linear time otherwise. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + iterator insert(iterator position, const detail::moved_object &mx) + { + //Just call more general insert(pos, size, value) and return iterator + size_type n = position - begin(); + this->insert(position + ,repeat_move_it(repeat_it(mx.get(), 1)) + ,repeat_move_it(repeat_it())); + return iterator(this->members_.m_start + n); + } + #else + iterator insert(iterator position, T &&mx) + { + //Just call more general insert(pos, size, value) and return iterator + size_type n = position - begin(); + this->insert(position + ,repeat_move_it(repeat_it(mx, 1)) + ,repeat_move_it(repeat_it())); + return iterator(this->members_.m_start + n); + } + #endif + + //! Requires: pos must be a valid iterator of *this. + //! + //! Effects: Insert a copy of the [first, last) range before pos. + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced InpIt throws or T's copy constructor throws. + //! + //! Complexity: Linear to std::distance [first, last). + template + void insert(iterator pos, InIt first, InIt last) + { + //Dispatch depending on integer/iterator + const bool aux_boolean = detail::is_convertible::value; + typedef detail::bool_ Result; + this->priv_insert_dispatch(pos, first, last, Result()); + } + + //! Requires: pos must be a valid iterator of *this. + //! + //! Effects: Insert n copies of x before pos. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void insert (iterator p, size_type n, const T& x) + { this->insert(p, cvalue_iterator(x, n), cvalue_iterator()); } + + //! Effects: Removes the last element from the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + void pop_back() + { + //Destroy last element + --this->members_.m_size; + this->destroy(detail::get_pointer(this->members_.m_start) + this->members_.m_size); + } + + //! Effects: Erases the element at position pos. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements between pos and the + //! last element. Constant if pos is the first or the last element. + iterator erase(const_iterator position) + { + T *pos = detail::get_pointer(position.get_ptr()); + T *beg = detail::get_pointer(this->members_.m_start); + + std::copy(assign_move_it(pos + 1), assign_move_it(beg + this->members_.m_size), pos); + --this->members_.m_size; + //Destroy last element + base_t::destroy(detail::get_pointer(this->members_.m_start) + this->members_.m_size); + return iterator(position.get_ptr()); + } + + //! Effects: Erases the elements pointed by [first, last). + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the distance between first and last. + iterator erase(const_iterator first, const_iterator last) + { + if (first != last){ // worth doing, copy down over hole + T* end_pos = detail::get_pointer(this->members_.m_start) + this->members_.m_size; + T* ptr = detail::get_pointer(std::copy + (assign_move_it(detail::get_pointer(last.get_ptr())) + ,assign_move_it(end_pos) + ,detail::get_pointer(first.get_ptr()) + )); + size_type destroyed = (end_pos - ptr); + this->destroy_n(ptr, destroyed); + this->members_.m_size -= destroyed; + } + return iterator(first.get_ptr()); + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are copy constructed from x. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size, const T& x) + { + pointer finish = this->members_.m_start + this->members_.m_size; + if (new_size < size()){ + //Destroy last elements + this->erase(iterator(this->members_.m_start + new_size), this->end()); + } + else{ + //Insert new elements at the end + this->insert(iterator(finish), new_size - this->size(), x); + } + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are default constructed. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size) + { + if (new_size < this->size()){ + //Destroy last elements + this->erase(iterator(this->members_.m_start + new_size), this->end()); + } + else{ + size_type n = new_size - this->size(); + this->reserve(new_size); + T *ptr = detail::get_pointer(this->members_.m_start + this->members_.m_size); + while(n--){ + //Default construct + new((void*)ptr++)T(); + ++this->members_.m_size; + } + } + } + + //! Effects: Erases all the elements of the vector. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements in the vector. + void clear() + { this->priv_destroy_all(); } + + /// @cond + + //! Effects: Tries to deallocate the excess of memory created + //! with previous allocations. The size of the vector is unchanged + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to size(). + void shrink_to_fit() + { priv_shrink_to_fit(alloc_version()); } + + private: + void priv_shrink_to_fit(allocator_v1) + { + if(this->members_.m_capacity){ + if(!size()){ + this->prot_deallocate(); + } + else{ + //This would not work with stateful allocators + vector(*this).swap(*this); + } + } + } + + void priv_shrink_to_fit(allocator_v2) + { + if(this->members_.m_capacity){ + if(!size()){ + this->prot_deallocate(); + } + else{ + size_type received_size; + if(this->alloc().allocation_command + ( shrink_in_place | nothrow_allocation + , this->capacity(), this->size() + , received_size, this->members_.m_start).first){ + this->members_.m_capacity = received_size; + #ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS + ++this->num_shrink; + #endif + } + } + } + } + + void priv_destroy_all() + { + this->destroy_n(detail::get_pointer(this->members_.m_start), this->members_.m_size); + this->members_.m_size = 0; + } + + template + void priv_range_insert(pointer pos, FwdIt first, + FwdIt last, std::forward_iterator_tag) + { + if (first != last){ + size_type n = std::distance(first, last); + //Check if we have enough memory or try to expand current memory + size_type remaining = this->members_.m_capacity - this->members_.m_size; + bool same_buffer_start; + std::pair ret; + size_type real_cap = this->members_.m_capacity; + + //Check if we already have room + if (n <= remaining){ + same_buffer_start = true; + } + else{ + //There is not enough memory, allocate a new + //buffer or expand the old one. + size_type new_cap = this->next_capacity(n); + ret = this->allocation_command + (allocate_new | expand_fwd | expand_bwd, + this->members_.m_size + n, new_cap, real_cap, this->members_.m_start); + + //Check for forward expansion + same_buffer_start = ret.second && this->members_.m_start == ret.first; + if(same_buffer_start){ + this->members_.m_capacity = real_cap; + } + } + + //If we had room or we have expanded forward + if (same_buffer_start){ + #ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS + ++this->num_expand_fwd; + #endif + this->priv_range_insert_expand_forward + (detail::get_pointer(pos), first, last, n); + } + //Backwards (and possibly forward) expansion + else if(ret.second){ + #ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS + ++this->num_expand_bwd; + #endif + this->priv_range_insert_expand_backwards + ( detail::get_pointer(ret.first) + , real_cap + , detail::get_pointer(pos) + , first + , last + , n); + } + //New buffer + else{ + #ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS + ++this->num_alloc; + #endif + this->priv_range_insert_new_allocation + ( detail::get_pointer(ret.first) + , real_cap + , detail::get_pointer(pos) + , first + , last); + } + } + } + + template + void priv_range_insert_expand_forward + (T* pos, FwdIt first, FwdIt last, size_type n) + { + //There is enough memory + T* old_finish = detail::get_pointer(this->members_.m_start) + this->members_.m_size; + const size_type elems_after = old_finish - pos; + + if (elems_after > n){ + //New elements can be just copied. + //Move to uninitialized memory last objects + std::uninitialized_copy(copy_move_it(old_finish - n), copy_move_it(old_finish), old_finish); + this->members_.m_size += n; + //Copy previous to last objects to the initialized end + std::copy_backward(assign_move_it(pos), assign_move_it(old_finish - n), old_finish); + //Insert new objects in the pos + std::copy(first, last, pos); + } + else { + //The new elements don't fit in the [pos, end()) range. Copy + //to the beginning of the unallocated zone the last new elements. + FwdIt mid = first; + std::advance(mid, elems_after); + std::uninitialized_copy(mid, last, old_finish); + this->members_.m_size += n - elems_after; + //Copy old [pos, end()) elements to the uninitialized memory + std::uninitialized_copy + ( copy_move_it(pos) + , copy_move_it(old_finish) + , detail::get_pointer(this->members_.m_start) + this->members_.m_size); + this->members_.m_size += elems_after; + //Copy first new elements in pos + std::copy(first, mid, pos); + } + } + + template + void priv_range_insert_new_allocation + (T* new_start, size_type new_cap, T* pos, FwdIt first, FwdIt last) + { + T* new_finish = new_start; + T *old_finish; + //Anti-exception rollbacks + UCopiedArrayDeallocator scoped_alloc(new_start, this->alloc(), new_cap); + UCopiedArrayDestructor construted_values_destroyer(new_start, 0u); + + //Initialize with [begin(), pos) old buffer + //the start of the new buffer + new_finish = std::uninitialized_copy + ( copy_move_it(detail::get_pointer(this->members_.m_start)) + , copy_move_it(pos) + , old_finish = new_finish); + construted_values_destroyer.increment_size(new_finish - old_finish); + //Initialize new objects, starting from previous point + new_finish = std::uninitialized_copy + (first, last, old_finish = new_finish); + construted_values_destroyer.increment_size(new_finish - old_finish); + //Initialize from the rest of the old buffer, + //starting from previous point + new_finish = std::uninitialized_copy + ( copy_move_it(pos) + , copy_move_it(detail::get_pointer(this->members_.m_start) + this->members_.m_size) + , new_finish); + + //All construction successful, disable rollbacks + construted_values_destroyer.release(); + scoped_alloc.release(); + //Destroy and deallocate old elements + //If there is allocated memory, destroy and deallocate + if(this->members_.m_start != 0){ + if(!base_t::trivial_dctr_after_move) + this->destroy_n(detail::get_pointer(this->members_.m_start), this->members_.m_size); + this->alloc().deallocate(this->members_.m_start, this->members_.m_capacity); + } + this->members_.m_start = new_start; + this->members_.m_size = new_finish - new_start; + this->members_.m_capacity = new_cap; + } + + template + void priv_range_insert_expand_backwards + (T* new_start, size_type new_capacity, + T* pos, FwdIt first, FwdIt last, size_type n) + { + //Backup old data + T* old_start = detail::get_pointer(this->members_.m_start); + T* old_finish = old_start + this->members_.m_size; + size_type old_size = this->members_.m_size; + + //We can have 8 possibilities: + const size_type elemsbefore = (size_type)(pos - old_start); + const size_type s_before = (size_type)(old_start - new_start); + + //Update the vector buffer information to a safe state + this->members_.m_start = new_start; + this->members_.m_capacity = new_capacity; + this->members_.m_size = 0; + + //If anything goes wrong, this object will destroy + //all the old objects to fulfill previous vector state + OldArrayDestructor old_values_destroyer(old_start, old_size); + + //Check if s_before is so big that even copying the old data + new data + //there is a gap between the new data and the old data + if(s_before >= (old_size + n)){ + //Old situation: + // _________________________________________________________ + //| raw_mem | old_begin | old_end | + //| __________________________________|___________|_________| + // + //New situation: + // _________________________________________________________ + //| old_begin | new | old_end | raw_mem | + //|___________|__________|_________|________________________| + // + //Copy first old values before pos, after that the + //new objects + boost::interprocess::uninitialized_copy_copy + (copy_move_it(old_start), copy_move_it(pos), first, last, new_start); + UCopiedArrayDestructor new_values_destroyer(new_start, elemsbefore); + //Now initialize the rest of memory with the last old values + std::uninitialized_copy + (copy_move_it(pos), copy_move_it(old_finish), new_start + elemsbefore + n); + //All new elements correctly constructed, avoid new element destruction + new_values_destroyer.release(); + this->members_.m_size = old_size + n; + //Old values destroyed automatically with "old_values_destroyer" + //when "old_values_destroyer" goes out of scope unless the have trivial + //destructor after move. + if(base_t::trivial_dctr_after_move) + old_values_destroyer.release(); + } + //Check if s_before is so big that divides old_end + else if(difference_type(s_before) >= difference_type(elemsbefore + n)){ + //Old situation: + // __________________________________________________ + //| raw_mem | old_begin | old_end | + //| ___________________________|___________|_________| + // + //New situation: + // __________________________________________________ + //| old_begin | new | old_end | raw_mem | + //|___________|__________|_________|_________________| + // + //Copy first old values before pos, after that the + //new objects + boost::interprocess::uninitialized_copy_copy + (copy_move_it(old_start), copy_move_it(pos), first, last, new_start); + UCopiedArrayDestructor new_values_destroyer(new_start, elemsbefore); + size_type raw_gap = s_before - (elemsbefore + n); + //Now initialize the rest of s_before memory with the + //first of elements after new values + std::uninitialized_copy + (copy_move_it(pos), copy_move_it(pos + raw_gap), new_start + elemsbefore + n); + //All new elements correctly constructed, avoid new element destruction + new_values_destroyer.release(); + //All new elements correctly constructed, avoid old element destruction + old_values_destroyer.release(); + //Update size since we have a contiguous buffer + this->members_.m_size = old_size + s_before; + //Now copy remaining last objects in the old buffer begin + T *to_destroy = std::copy(assign_move_it(pos + raw_gap), assign_move_it(old_finish), old_start); + //Now destroy redundant elements except if they were moved and + //they have trivial destructor after move + size_type n_destroy = old_finish - to_destroy; + if(!base_t::trivial_dctr_after_move) + this->destroy_n(to_destroy, n_destroy); + this->members_.m_size -= n_destroy; + } + else{ + //Check if we have to do the insertion in two phases + //since maybe s_before is not big enough and + //the buffer was expanded both sides + // + //Old situation: + // _________________________________________________ + //| raw_mem | old_begin + old_end | raw_mem | + //|_________|_____________________|_________________| + // + //New situation with do_after: + // _________________________________________________ + //| old_begin + new + old_end | raw_mem | + //|___________________________________|_____________| + // + //New without do_after: + // _________________________________________________ + //| old_begin + new + old_end | raw_mem | + //|____________________________|____________________| + // + bool do_after = n > s_before; + FwdIt before_end = first; + //If we have to expand both sides, + //we will play if the first new values so + //calculate the upper bound of new values + if(do_after){ + std::advance(before_end, s_before); + } + + //Now we can have two situations: the raw_mem of the + //beginning divides the old_begin, or the new elements: + if (s_before <= elemsbefore) { + //The raw memory divides the old_begin group: + // + //If we need two phase construction (do_after) + //new group is divided in new = new_beg + new_end groups + //In this phase only new_beg will be inserted + // + //Old situation: + // _________________________________________________ + //| raw_mem | old_begin | old_end | raw_mem | + //|_________|___________|_________|_________________| + // + //New situation with do_after(1): + //This is not definitive situation, the second phase + //will include + // _________________________________________________ + //| old_begin | new_beg | old_end | raw_mem | + //|___________|_________|_________|_________________| + // + //New situation without do_after: + // _________________________________________________ + //| old_begin | new | old_end | raw_mem | + //|___________|_____|_________|_____________________| + // + //Copy the first part of old_begin to raw_mem + T *start_n = old_start + difference_type(s_before); + std::uninitialized_copy + (copy_move_it(old_start), copy_move_it(start_n), new_start); + //The buffer is all constructed until old_end, + //release destroyer and update size + old_values_destroyer.release(); + this->members_.m_size = old_size + s_before; + //Now copy the second part of old_begin overwriting himself + T* next = std::copy(assign_move_it(start_n), assign_move_it(pos), old_start); + if(do_after){ + //Now copy the new_beg elements + std::copy(first, before_end, next); + } + else{ + //Now copy the all the new elements + T* move_start = std::copy(first, last, next); + //Now displace old_end elements + T* move_end = std::copy(assign_move_it(pos), assign_move_it(old_finish), move_start); + //Destroy remaining moved elements from old_end except if + //they have trivial destructor after being moved + difference_type n_destroy = s_before - n; + if(!base_t::trivial_dctr_after_move) + this->destroy_n(move_end, n_destroy); + this->members_.m_size -= n_destroy; + } + } + else { + //The raw memory divides the new elements + // + //If we need two phase construction (do_after) + //new group is divided in new = new_beg + new_end groups + //In this phase only new_beg will be inserted + // + //Old situation: + // _______________________________________________________ + //| raw_mem | old_begin | old_end | raw_mem | + //|_______________|___________|_________|_________________| + // + //New situation with do_after(): + // ____________________________________________________ + //| old_begin | new_beg | old_end | raw_mem | + //|___________|_______________|_________|______________| + // + //New situation without do_after: + // ______________________________________________________ + //| old_begin | new | old_end | raw_mem | + //|___________|_____|_________|__________________________| + // + //First copy whole old_begin and part of new to raw_mem + FwdIt mid = first; + size_type n_new_init = difference_type(s_before) - elemsbefore; + std::advance(mid, n_new_init); + boost::interprocess::uninitialized_copy_copy + (copy_move_it(old_start), copy_move_it(pos), first, mid, new_start); + //The buffer is all constructed until old_end, + //release destroyer and update size + old_values_destroyer.release(); + this->members_.m_size = old_size + s_before; + + if(do_after){ + //Copy new_beg part + std::copy(mid, before_end, old_start); + } + else{ + //Copy all new elements + T* move_start = std::copy(mid, last, old_start); + //Displace old_end + T* move_end = std::copy(copy_move_it(pos), copy_move_it(old_finish), move_start); + //Destroy remaining moved elements from old_end except if they + //have trivial destructor after being moved + difference_type n_destroy = s_before - n; + if(!base_t::trivial_dctr_after_move) + this->destroy_n(move_end, n_destroy); + this->members_.m_size -= n_destroy; + } + } + + //This is only executed if two phase construction is needed + //This can be executed without exception handling since we + //have to just copy and append in raw memory and + //old_values_destroyer has been released in phase 1. + if(do_after){ + //The raw memory divides the new elements + // + //Old situation: + // ______________________________________________________ + //| raw_mem | old_begin | old_end | raw_mem | + //|______________|___________|____________|______________| + // + //New situation with do_after(1): + // _______________________________________________________ + //| old_begin + new_beg | new_end |old_end | raw_mem | + //|__________________________|_________|________|_________| + // + //New situation with do_after(2): + // ______________________________________________________ + //| old_begin + new | old_end |raw | + //|_______________________________________|_________|____| + // + const size_type n_after = n - s_before; + const difference_type elemsafter = old_size - elemsbefore; + + //The new_end part is [first + (n - n_after), last) + std::advance(first, n - n_after); + + //We can have two situations: + if (elemsafter > difference_type(n_after)){ + //The raw_mem from end will divide displaced old_end + // + //Old situation: + // ______________________________________________________ + //| raw_mem | old_begin | old_end | raw_mem | + //|______________|___________|____________|______________| + // + //New situation with do_after(1): + // _______________________________________________________ + //| old_begin + new_beg | new_end |old_end | raw_mem | + //|__________________________|_________|________|_________| + // + //First copy the part of old_end raw_mem + T* finish_n = old_finish - difference_type(n_after); + std::uninitialized_copy + (copy_move_it(finish_n), copy_move_it(old_finish), old_finish); + this->members_.m_size += n_after; + //Displace the rest of old_end to the new position + std::copy_backward(assign_move_it(pos), assign_move_it(finish_n), old_finish); + //Now overwrite with new_end + std::copy(first, last, pos); + } + else { + //The raw_mem from end will divide new_end part + // + //Old situation: + // _____________________________________________________________ + //| raw_mem | old_begin | old_end | raw_mem | + //|______________|___________|____________|_____________________| + // + //New situation with do_after(2): + // _____________________________________________________________ + //| old_begin + new_beg | new_end |old_end | raw_mem | + //|__________________________|_______________|________|_________| + // + FwdIt mid = first; + std::advance(mid, elemsafter); + //First initialize data in raw memory + boost::interprocess::uninitialized_copy_copy + ( mid, last, copy_move_it(pos), copy_move_it(old_finish), old_finish); + this->members_.m_size += n_after; + //Now copy the part of new_end over constructed elements + std::copy(first, mid, pos); + } + } + } + } + + template + void priv_range_insert(iterator pos, + InIt first, InIt last, + std::input_iterator_tag) + { + //Insert range before the pos position + std::copy(std::inserter(*this, pos), first, last); + } + + template + void priv_assign_aux(InIt first, InIt last, + std::input_iterator_tag) + { + //Overwrite all elements we can from [first, last) + iterator cur = begin(); + for ( ; first != last && cur != end(); ++cur, ++first){ + *cur = *first; + } + + if (first == last){ + //There are no more elements in the sequence, erase remaining + this->erase(cur, end()); + } + else{ + //There are more elements in the range, insert the remaining ones + this->insert(this->end(), first, last); + } + } + + template + void priv_assign_aux(FwdIt first, FwdIt last, + std::forward_iterator_tag) + { + size_type n = std::distance(first, last); + //Check if we have enough memory or try to expand current memory + size_type remaining = this->members_.m_capacity - this->members_.m_size; + bool same_buffer_start; + std::pair ret; + size_type real_cap = this->members_.m_capacity; + + if (n <= remaining){ + same_buffer_start = true; + } + else{ + //There is not enough memory, allocate a new buffer + size_type new_cap = this->next_capacity(n); + ret = this->allocation_command + (allocate_new | expand_fwd | expand_bwd, + this->size() + n, new_cap, real_cap, this->members_.m_start); + same_buffer_start = ret.second && this->members_.m_start == ret.first; + if(same_buffer_start){ + this->members_.m_capacity = real_cap; + } + } + + if(same_buffer_start){ + T *start = detail::get_pointer(this->members_.m_start); + if (this->size() >= n){ + //There is memory, but there are more old elements than new ones + //Overwrite old elements with new ones + std::copy(first, last, start); + //Destroy remaining old elements + this->destroy_n(start + n, this->members_.m_size - n); + this->members_.m_size = n; + } + else{ + //There is memory, but there are less old elements than new ones + //First overwrite some old elements with new ones + FwdIt mid = first; + std::advance(mid, this->size()); + T *end = std::copy(first, mid, start); + //Initialize the remaining new elements in the uninitialized memory + std::uninitialized_copy(mid, last, end); + this->members_.m_size = n; + } + } + else if(!ret.second){ + UCopiedArrayDeallocator scoped_alloc(ret.first, this->alloc(), real_cap); + std::uninitialized_copy(first, last, detail::get_pointer(ret.first)); + scoped_alloc.release(); + //Destroy and deallocate old buffer + if(this->members_.m_start != 0){ + this->destroy_n(detail::get_pointer(this->members_.m_start), this->members_.m_size); + this->alloc().deallocate(this->members_.m_start, this->members_.m_capacity); + } + this->members_.m_start = ret.first; + this->members_.m_size = n; + this->members_.m_capacity = real_cap; + } + else{ + //Backwards expansion + //If anything goes wrong, this object will destroy + //all old objects + T *old_start = detail::get_pointer(this->members_.m_start); + size_type old_size = this->members_.m_size; + OldArrayDestructor old_values_destroyer(old_start, old_size); + //If something goes wrong size will be 0 + //but holding the whole buffer + this->members_.m_size = 0; + this->members_.m_start = ret.first; + this->members_.m_capacity = real_cap; + + //Backup old buffer data + size_type old_offset = old_start - detail::get_pointer(ret.first); + size_type first_count = min_value(n, old_offset); + boost::interprocess::uninitialized_copy_n + (first, first_count, detail::get_pointer(ret.first)); + FwdIt mid = first + first_count; + + if(old_offset > n){ + //All old elements will be destroyed by "old_values_destroyer" + this->members_.m_size = n; + } + else{ + //We have constructed objects from the new begin until + //the old end so release the rollback destruction + old_values_destroyer.release(); + this->members_.m_start = ret.first; + this->members_.m_size = first_count + old_size; + //Now overwrite the old values + size_type second_count = min_value(old_size, n - first_count); + copy_n(mid, second_count, old_start); + mid += second_count; + + //Check if we still have to append elements in the + //uninitialized end + if(second_count == old_size){ + boost::interprocess::uninitialized_copy_n + ( mid + , n - first_count - second_count + , old_start + old_size); + } + else{ + //We have to destroy some old values + this->destroy_n + (old_start + second_count, old_size - second_count); + this->members_.m_size = n; + } + this->members_.m_size = n; + } + } + } + + template + void priv_assign_dispatch(Integer n, Integer val, detail::true_) + { this->assign((size_type) n, (T) val); } + + template + void priv_assign_dispatch(InIt first, InIt last, detail::false_) + { + //Dispatch depending on integer/iterator + typedef typename + std::iterator_traits::iterator_category ItCat; + this->priv_assign_aux(first, last, ItCat()); + } + + template + void priv_insert_dispatch( iterator pos, Integer n, Integer val, detail::true_) + { this->insert(pos, (size_type)n, (T)val); } + + template + void priv_insert_dispatch(iterator pos, InIt first, + InIt last, detail::false_) + { + //Dispatch depending on integer/iterator + typedef typename + std::iterator_traits::iterator_category ItCat; + this->priv_range_insert(pos.get_ptr(), first, last, ItCat()); + } + + void priv_check_range(size_type n) const + { + //If n is out of range, throw an out_of_range exception + if (n >= size()) + throw std::out_of_range("vector::at"); + } + + #ifdef BOOST_INTERPROCESS_VECTOR_ALLOC_STATS + public: + unsigned int num_expand_fwd; + unsigned int num_expand_bwd; + unsigned int num_shrink; + unsigned int num_alloc; + void reset_alloc_stats() + { num_expand_fwd = num_expand_bwd = num_alloc = 0, num_shrink = 0; } + #endif + /// @endcond +}; + +template +inline bool +operator==(const vector& x, const vector& y) +{ + //Check first size and each element if needed + return x.size() == y.size() && + std::equal(x.begin(), x.end(), y.begin()); +} + +template +inline bool +operator!=(const vector& x, const vector& y) +{ + //Check first size and each element if needed + return x.size() != y.size() || + !std::equal(x.begin(), x.end(), y.begin()); +} + +template +inline bool +operator<(const vector& x, const vector& y) +{ + return std::lexicographical_compare(x.begin(), x.end(), + y.begin(), y.end()); +} + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline void swap(vector& x, vector& y) +{ x.swap(y); } + +template +inline void swap(const detail::moved_object >& x, vector& y) +{ x.get().swap(y); } + +template +inline void swap(vector &x, const detail::moved_object >& y) +{ x.swap(y.get()); } +#else +template +inline void swap(vector&&x, vector&&y) +{ x.swap(y); } +#endif + +/// @cond + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + enum { value = has_trivial_destructor::value }; +}; +/// @endcond + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif // #ifndef BOOST_INTERPROCESS_VECTOR_HPP + diff --git a/win32/include/boost/interprocess/creation_tags.hpp b/win32/include/boost/interprocess/creation_tags.hpp new file mode 100755 index 000000000..b127acf90 --- /dev/null +++ b/win32/include/boost/interprocess/creation_tags.hpp @@ -0,0 +1,73 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_CREATION_TAGS_HPP +#define BOOST_INTERPROCESS_CREATION_TAGS_HPP + +#include +#include + +namespace boost { +namespace interprocess { + +//!Tag to indicate that the resource must +//!be only created +struct create_only_t {}; + +//!Tag to indicate that the resource must +//!be only opened +struct open_only_t {}; + +//!Tag to indicate that the resource must +//!be only opened for reading +struct open_read_only_t {}; + +//!Tag to indicate that the resource must +//!be only opened for reading +struct open_copy_on_write_t {}; + +//!Tag to indicate that the resource must +//!be created. If already created, it must be opened. +struct open_or_create_t {}; + +//!Value to indicate that the resource must +//!be only created +static const create_only_t create_only = create_only_t(); + +//!Value to indicate that the resource must +//!be only opened +static const open_only_t open_only = open_only_t(); + +//!Value to indicate that the resource must +//!be only opened for reading +static const open_read_only_t open_read_only = open_read_only_t(); + +//!Value to indicate that the resource must +//!be created. If already created, it must be opened. +static const open_or_create_t open_or_create = open_or_create_t(); + +//!Value to indicate that the resource must +//!be only opened for reading +static const open_copy_on_write_t open_copy_on_write = open_copy_on_write_t(); + +namespace detail { + +enum create_enum_t +{ DoCreate, DoOpen, DoOpenOrCreate }; + +} //namespace detail { + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_CREATION_TAGS_HPP + diff --git a/win32/include/boost/interprocess/detail/algorithms.hpp b/win32/include/boost/interprocess/detail/algorithms.hpp new file mode 100755 index 000000000..eb533b6a4 --- /dev/null +++ b/win32/include/boost/interprocess/detail/algorithms.hpp @@ -0,0 +1,210 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. +// +// 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_ALGORITHMS_HPP +#define BOOST_INTERPROCESS_DETAIL_ALGORITHMS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { + +#if !defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) || !defined(BOOST_INTERPROCESS_RVALUE_PAIR) + +template +struct has_own_construct_from_it +{ + static const bool value = false; +}; + +namespace detail { + +template +inline void construct_in_place_impl(T* dest, const InpIt &source, detail::true_) +{ + T::construct(dest, *source); +} + +template +inline void construct_in_place_impl(T* dest, const InpIt &source, detail::false_) +{ + new((void*)dest)T(*source); +} + +} //namespace detail { + +template +inline void construct_in_place(T* dest, InpIt source) +{ + typedef detail::bool_::value> boolean_t; + detail::construct_in_place_impl(dest, source, boolean_t()); +} + +#else +template +inline void construct_in_place(T* dest, InpIt source) +{ new((void*)dest)T(*source); } +#endif + +template +inline void construct_in_place(T *dest, default_construct_iterator) +{ + new((void*)dest)T(); +} + + +template +struct optimize_assign +{ + static const bool value = false; +}; + +template +struct optimize_assign +{ + static const bool value = boost::has_trivial_assign::value; +}; + +template +struct optimize_assign + : public optimize_assign +{}; + +template +struct optimize_copy +{ + static const bool value = false; +}; + +template +struct optimize_copy +{ + static const bool value = boost::has_trivial_copy::value; +}; + +template +struct optimize_copy + : public optimize_copy +{}; + + +template inline +OutIt copy_n_dispatch(InIt first, typename std::iterator_traits::difference_type length, OutIt dest, detail::bool_) +{ + for (; length--; ++dest, ++first) + *dest = *first; + return dest; +} + +template inline +T *copy_n_dispatch(const T *first, typename std::iterator_traits::difference_type length, T *dest, detail::bool_) +{ + std::size_t size = length*sizeof(T); + return ((T*)std::memmove(dest, first, size)) + size; +} + +template inline +OutIt copy_n(InIt first, typename std::iterator_traits::difference_type length, OutIt dest) +{ + const bool do_optimized_assign = optimize_assign::value; + return copy_n_dispatch(first, length, dest, detail::bool_()); +} + +template inline +FwdIt uninitialized_copy_n_dispatch + (InIt first, + typename std::iterator_traits::difference_type count, + FwdIt dest, detail::bool_) +{ + typedef typename std::iterator_traits::value_type value_type; + //Save initial destination position + FwdIt dest_init = dest; + typename std::iterator_traits::difference_type new_count = count+1; + + BOOST_TRY{ + //Try to build objects + for (; --new_count; ++dest, ++first){ + construct_in_place(detail::get_pointer(&*dest), first); + } + } + BOOST_CATCH(...){ + //Call destructors + new_count = count - new_count; + for (; new_count--; ++dest_init){ + detail::get_pointer(&*dest_init)->~value_type(); + } + BOOST_RETHROW + } + BOOST_CATCH_END + return dest; +} + + +template inline +T *uninitialized_copy_n_dispatch(const T *first, typename std::iterator_traits::difference_type length, T *dest, detail::bool_) +{ + std::size_t size = length*sizeof(T); + return ((T*)std::memmove(dest, first, size)) + size; +} + +template inline +FwdIt uninitialized_copy_n + (InIt first, + typename std::iterator_traits::difference_type count, + FwdIt dest) +{ + const bool do_optimized_copy = optimize_copy::value; + return uninitialized_copy_n_dispatch(first, count, dest, detail::bool_()); +} + + +// uninitialized_copy_copy +// Copies [first1, last1) into [result, result + (last1 - first1)), and +// copies [first2, last2) into +// [result + (last1 - first1), result + (last1 - first1) + (last2 - first2)). +template +FwdIt uninitialized_copy_copy + (InpIt1 first1, InpIt1 last1, InpIt2 first2, InpIt2 last2, FwdIt result) +{ + typedef typename std::iterator_traits::value_type value_type; + FwdIt mid = std::uninitialized_copy(first1, last1, result); + BOOST_TRY { + return std::uninitialized_copy(first2, last2, mid); + } + BOOST_CATCH(...){ + for(;result != mid; ++result){ + result->~value_type(); + } + BOOST_RETHROW + } + BOOST_CATCH_END +} + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ALGORITHMS_HPP + diff --git a/win32/include/boost/interprocess/detail/atomic.hpp b/win32/include/boost/interprocess/detail/atomic.hpp new file mode 100755 index 000000000..a9ca7d369 --- /dev/null +++ b/win32/include/boost/interprocess/detail/atomic.hpp @@ -0,0 +1,472 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2008 +// (C) Copyright Markus Schoepflin 2007 +// +// 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP +#define BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP + +#include +#include +#include + +namespace boost{ +namespace interprocess{ +namespace detail{ + +//! Atomically increment an apr_uint32_t by 1 +//! "mem": pointer to the object +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem); + +//! Atomically read an boost::uint32_t from memory +inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem); + +//! Atomically set an boost::uint32_t in memory +//! "mem": pointer to the object +//! "param": val value that the object will assume +inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val); + +//! Compare an boost::uint32_t's value with "cmp". +//! If they are the same swap the value with "with" +//! "mem": pointer to the value +//! "with": what to swap it with +//! "cmp": the value to compare it to +//! Returns the old value of *mem +inline boost::uint32_t atomic_cas32 + (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp); + +} //namespace detail{ +} //namespace interprocess{ +} //namespace boost{ + +#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +#include + +namespace boost{ +namespace interprocess{ +namespace detail{ + +//! Atomically decrement an boost::uint32_t by 1 +//! "mem": pointer to the atomic value +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) +{ return winapi::interlocked_decrement((volatile long*)mem) + 1; } + +//! Atomically increment an apr_uint32_t by 1 +//! "mem": pointer to the object +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) +{ return winapi::interlocked_increment((volatile long*)mem)-1; } + +//! Atomically read an boost::uint32_t from memory +inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) +{ return *mem; } + +//! Atomically set an boost::uint32_t in memory +//! "mem": pointer to the object +//! "param": val value that the object will assume +inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) +{ winapi::interlocked_exchange((volatile long*)mem, val); } + +//! Compare an boost::uint32_t's value with "cmp". +//! If they are the same swap the value with "with" +//! "mem": pointer to the value +//! "with": what to swap it with +//! "cmp": the value to compare it to +//! Returns the old value of *mem +inline boost::uint32_t atomic_cas32 + (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) +{ return winapi::interlocked_compare_exchange((volatile long*)mem, with, cmp); } + +} //namespace detail{ +} //namespace interprocess{ +} //namespace boost{ + +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + +namespace boost { +namespace interprocess { +namespace detail{ + +//! Compare an boost::uint32_t's value with "cmp". +//! If they are the same swap the value with "with" +//! "mem": pointer to the value +//! "with" what to swap it with +//! "cmp": the value to compare it to +//! Returns the old value of *mem +inline boost::uint32_t atomic_cas32 + (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) +{ + boost::uint32_t prev = cmp; + asm volatile( "lock\n\t" + "cmpxchg %3,%1" + : "=a" (prev), "=m" (*(mem)) + : "0" (prev), "r" (with) + : "memory", "cc"); + return prev; +/* + boost::uint32_t prev; + + asm volatile ("lock; cmpxchgl %1, %2" + : "=a" (prev) + : "r" (with), "m" (*(mem)), "0"(cmp)); + asm volatile("" : : : "memory"); + + return prev; +*/ +} + +//! Atomically add 'val' to an boost::uint32_t +//! "mem": pointer to the object +//! "val": amount to add +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_add32 + (volatile boost::uint32_t *mem, boost::uint32_t val) +{ + // int r = *pw; + // *mem += val; + // return r; + int r; + + asm volatile + ( + "lock\n\t" + "xadd %1, %0": + "+m"( *mem ), "=r"( r ): // outputs (%0, %1) + "1"( val ): // inputs (%2 == %1) + "memory", "cc" // clobbers + ); + + return r; +/* + asm volatile( "lock\n\t; xaddl %0,%1" + : "=r"(val), "=m"(*mem) + : "0"(val), "m"(*mem)); + asm volatile("" : : : "memory"); + + return val; +*/ +} + +//! Atomically increment an apr_uint32_t by 1 +//! "mem": pointer to the object +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, 1); } + +//! Atomically decrement an boost::uint32_t by 1 +//! "mem": pointer to the atomic value +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, (boost::uint32_t)-1); } + +//! Atomically read an boost::uint32_t from memory +inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) +{ return *mem; } + +//! Atomically set an boost::uint32_t in memory +//! "mem": pointer to the object +//! "param": val value that the object will assume +inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) +{ *mem = val; } + +} //namespace detail{ +} //namespace interprocess{ +} //namespace boost{ + +#elif defined(__GNUC__) && (defined(__PPC__) || defined(__ppc__)) + +namespace boost { +namespace interprocess { +namespace detail{ + +//! Atomically add 'val' to an boost::uint32_t +//! "mem": pointer to the object +//! "val": amount to add +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32_t val) +{ + boost::uint32_t prev, temp; + + asm volatile ("0:\n\t" // retry local label + "lwarx %0,0,%2\n\t" // load prev and reserve + "add %1,%0,%3\n\t" // temp = prev + val + "stwcx. %1,0,%2\n\t" // conditionally store + "bne- 0b" // start over if we lost + // the reservation + //XXX find a cleaner way to define the temp + //it's not an output + : "=&r" (prev), "=&r" (temp) // output, temp + : "b" (mem), "r" (val) // inputs + : "memory", "cc"); // clobbered + return prev; +} + +//! Compare an boost::uint32_t's value with "cmp". +//! If they are the same swap the value with "with" +//! "mem": pointer to the value +//! "with" what to swap it with +//! "cmp": the value to compare it to +//! Returns the old value of *mem +inline boost::uint32_t atomic_cas32 + (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) +{ + boost::uint32_t prev; + + asm volatile ("0:\n\t" // retry local label + "lwarx %0,0,%1\n\t" // load prev and reserve + "cmpw %0,%3\n\t" // does it match cmp? + "bne- 1f\n\t" // ...no, bail out + "stwcx. %2,0,%1\n\t" // ...yes, conditionally + // store with + "bne- 0b\n\t" // start over if we lost + // the reservation + "1:" // exit local label + + : "=&r"(prev) // output + : "b" (mem), "r" (with), "r"(cmp) // inputs + : "memory", "cc"); // clobbered + return prev; +} + +//! Atomically increment an apr_uint32_t by 1 +//! "mem": pointer to the object +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, 1); } + +//! Atomically decrement an boost::uint32_t by 1 +//! "mem": pointer to the atomic value +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, boost::uint32_t(-1u)); } + +//! Atomically read an boost::uint32_t from memory +inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) +{ return *mem; } + +//! Atomically set an boost::uint32_t in memory +//! "mem": pointer to the object +//! "param": val value that the object will assume +inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) +{ *mem = val; } + +} //namespace detail{ +} //namespace interprocess{ +} //namespace boost{ + +#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) + +namespace boost { +namespace interprocess { +namespace detail{ + +//! Atomically add 'val' to an boost::uint32_t +//! "mem": pointer to the object +//! "val": amount to add +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_add32 + (volatile boost::uint32_t *mem, boost::uint32_t val) +{ return __sync_fetch_and_add(const_cast(mem), val); } + +//! Atomically increment an apr_uint32_t by 1 +//! "mem": pointer to the object +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, 1); } + +//! Atomically decrement an boost::uint32_t by 1 +//! "mem": pointer to the atomic value +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, (boost::uint32_t)-1); } + +//! Atomically read an boost::uint32_t from memory +inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) +{ return *mem; } + +//! Compare an boost::uint32_t's value with "cmp". +//! If they are the same swap the value with "with" +//! "mem": pointer to the value +//! "with" what to swap it with +//! "cmp": the value to compare it to +//! Returns the old value of *mem +inline boost::uint32_t atomic_cas32 + (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) +{ return __sync_val_compare_and_swap(const_cast(mem), with, cmp); } + +//! Atomically set an boost::uint32_t in memory +//! "mem": pointer to the object +//! "param": val value that the object will assume +inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) +{ *mem = val; } + +} //namespace detail{ +} //namespace interprocess{ +} //namespace boost{ + +#elif (defined(sun) || defined(__sun)) + +#include + +namespace boost{ +namespace interprocess{ +namespace detail{ + +//! Atomically add 'val' to an boost::uint32_t +//! "mem": pointer to the object +//! "val": amount to add +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32_t val) +{ return atomic_add_32_nv(reinterpret_cast(mem), (int32_t)val) - val; } + +//! Compare an boost::uint32_t's value with "cmp". +//! If they are the same swap the value with "with" +//! "mem": pointer to the value +//! "with" what to swap it with +//! "cmp": the value to compare it to +//! Returns the old value of *mem +inline boost::uint32_t atomic_cas32 + (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) +{ return atomic_cas_32(reinterpret_cast(mem), cmp, with); } + +//! Atomically increment an apr_uint32_t by 1 +//! "mem": pointer to the object +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) +{ return atomic_add_32_nv(reinterpret_cast(mem), 1) - 1; } + +//! Atomically decrement an boost::uint32_t by 1 +//! "mem": pointer to the atomic value +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) +{ return atomic_add_32_nv(reinterpret_cast(mem), (boost::uint32_t)-1) + 1; } + +//! Atomically read an boost::uint32_t from memory +inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) +{ return *mem; } + +//! Atomically set an boost::uint32_t in memory +//! "mem": pointer to the object +//! "param": val value that the object will assume +inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) +{ *mem = val; } + +} //namespace detail{ +} //namespace interprocess{ +} //namespace boost{ + +#elif defined(__osf__) && defined(__DECCXX) + +#include +#include + +namespace boost{ +namespace interprocess{ +namespace detail{ + +//! Atomically decrement a uint32_t by 1 +//! "mem": pointer to the atomic value +//! Returns the old value pointed to by mem +//! Acquire, memory barrier after decrement. +inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) +{ boost::uint32_t old_val = __ATOMIC_DECREMENT_LONG(mem); __MB(); return old_val; } + +//! Atomically increment a uint32_t by 1 +//! "mem": pointer to the object +//! Returns the old value pointed to by mem +//! Release, memory barrier before increment. +inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) +{ __MB(); return __ATOMIC_INCREMENT_LONG(mem); } + +// Rational for the implementation of the atomic read and write functions. +// +// 1. The Alpha Architecture Handbook requires that access to a byte, +// an aligned word, an aligned longword, or an aligned quadword is +// atomic. (See 'Alpha Architecture Handbook', version 4, chapter 5.2.2.) +// +// 2. The CXX User's Guide states that volatile quantities are accessed +// with single assembler instructions, and that a compilation error +// occurs when declaring a quantity as volatile which is not properly +// aligned. + +//! Atomically read an boost::uint32_t from memory +//! Acquire, memory barrier after load. +inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) +{ boost::uint32_t old_val = *mem; __MB(); return old_val; } + +//! Atomically set an boost::uint32_t in memory +//! "mem": pointer to the object +//! "param": val value that the object will assume +//! Release, memory barrier before store. +inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) +{ __MB(); *mem = val; } + +//! Compare an boost::uint32_t's value with "cmp". +//! If they are the same swap the value with "with" +//! "mem": pointer to the value +//! "with" what to swap it with +//! "cmp": the value to compare it to +//! Returns the old value of *mem +//! Memory barrier between load and store. +inline boost::uint32_t atomic_cas32( + volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) +{ + // Note: + // + // Branch prediction prefers backward branches, and the Alpha Architecture + // Handbook explicitely states that the loop should not be implemented like + // it is below. (See chapter 4.2.5.) Therefore the code should probably look + // like this: + // + // return asm( + // "10: ldl_l %v0,(%a0) ;" + // " cmpeq %v0,%a2,%t0 ;" + // " beq %t0,20f ;" + // " mb ;" + // " mov %a1,%t0 ;" + // " stl_c %t0,(%a0) ;" + // " beq %t0,30f ;" + // "20: ret ;" + // "30: br 10b;", + // mem, with, cmp); + // + // But as the compiler always transforms this into the form where a backward + // branch is taken on failure, we can as well implement it in the straight + // forward form, as this is what it will end up in anyway. + + return asm( + "10: ldl_l %v0,(%a0) ;" // load prev value from mem and lock mem + " cmpeq %v0,%a2,%t0 ;" // compare with given value + " beq %t0,20f ;" // if not equal, we're done + " mb ;" // memory barrier + " mov %a1,%t0 ;" // load new value into scratch register + " stl_c %t0,(%a0) ;" // store new value to locked mem (overwriting scratch) + " beq %t0,10b ;" // store failed because lock has been stolen, retry + "20: ", + mem, with, cmp); +} + +} //namespace detail{ +} //namespace interprocess{ +} //namespace boost{ + +#else + +#error No atomic operations implemented for this platform, sorry! + +#endif + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP diff --git a/win32/include/boost/interprocess/detail/cast_tags.hpp b/win32/include/boost/interprocess/detail/cast_tags.hpp new file mode 100755 index 000000000..c361333a9 --- /dev/null +++ b/win32/include/boost/interprocess/detail/cast_tags.hpp @@ -0,0 +1,29 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_CAST_TAGS_HPP +#define BOOST_INTERPROCESS_CAST_TAGS_HPP + +#include +#include + +namespace boost { namespace interprocess { namespace detail { + +struct static_cast_tag {}; +struct const_cast_tag {}; +struct dynamic_cast_tag {}; +struct reinterpret_cast_tag {}; + +}}} //namespace boost { namespace interprocess { namespace detail { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_CAST_TAGS_HPP + diff --git a/win32/include/boost/interprocess/detail/config_begin.hpp b/win32/include/boost/interprocess/detail/config_begin.hpp new file mode 100755 index 000000000..897090321 --- /dev/null +++ b/win32/include/boost/interprocess/detail/config_begin.hpp @@ -0,0 +1,43 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTERPROCESS_CONFIG_INCLUDED +#define BOOST_INTERPROCESS_CONFIG_INCLUDED +#include +#endif + +#ifdef BOOST_MSVC + #ifndef _CRT_SECURE_NO_DEPRECATE + #define BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE + #define _CRT_SECURE_NO_DEPRECATE + #endif + #pragma warning (push) + #pragma warning (disable : 4702) // unreachable code + #pragma warning (disable : 4706) // assignment within conditional expression + #pragma warning (disable : 4127) // conditional expression is constant + #pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned + #pragma warning (disable : 4284) // odd return type for operator-> + #pragma warning (disable : 4244) // possible loss of data + #pragma warning (disable : 4251) // "identifier" : class "type" needs to have dll-interface to be used by clients of class "type2" + #pragma warning (disable : 4267) // conversion from "X" to "Y", possible loss of data + #pragma warning (disable : 4275) // non DLL-interface classkey "identifier" used as base for DLL-interface classkey "identifier" + #pragma warning (disable : 4355) // "this" : used in base member initializer list + #pragma warning (disable : 4503) // "identifier" : decorated name length exceeded, name was truncated + #pragma warning (disable : 4511) // copy constructor could not be generated + #pragma warning (disable : 4512) // assignment operator could not be generated + #pragma warning (disable : 4514) // unreferenced inline removed + #pragma warning (disable : 4521) // Disable "multiple copy constructors specified" + #pragma warning (disable : 4522) // "class" : multiple assignment operators specified + #pragma warning (disable : 4675) // "method" should be declared "static" and have exactly one parameter + #pragma warning (disable : 4710) // function not inlined + #pragma warning (disable : 4711) // function selected for automatic inline expansion + #pragma warning (disable : 4786) // identifier truncated in debug info + #pragma warning (disable : 4996) // "function": was declared deprecated + #pragma warning (disable : 4197) // top-level volatile in cast is ignored +#endif diff --git a/win32/include/boost/interprocess/detail/config_end.hpp b/win32/include/boost/interprocess/detail/config_end.hpp new file mode 100755 index 000000000..67c75169a --- /dev/null +++ b/win32/include/boost/interprocess/detail/config_end.hpp @@ -0,0 +1,17 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#if defined BOOST_MSVC + #pragma warning (pop) + #ifdef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE + #undef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE + #undef _CRT_SECURE_NO_DEPRECATE + #endif +#endif + diff --git a/win32/include/boost/interprocess/detail/file_wrapper.hpp b/win32/include/boost/interprocess/detail/file_wrapper.hpp new file mode 100755 index 000000000..fe870dfcd --- /dev/null +++ b/win32/include/boost/interprocess/detail/file_wrapper.hpp @@ -0,0 +1,213 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP +#define BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace detail{ + +class file_wrapper +{ + public: + + //!Default constructor. + //!Represents an empty file_wrapper. + file_wrapper(); + + //!Creates a file object with name "name" and mode "mode", with the access mode "mode" + //!If the file previously exists, throws an error. + file_wrapper(create_only_t, const char *name, mode_t mode) + { this->priv_open_or_create(detail::DoCreate, name, mode); } + + //!Tries to create a file with name "name" and mode "mode", with the + //!access mode "mode". If the file previously exists, it tries to open it with mode "mode". + //!Otherwise throws an error. + file_wrapper(open_or_create_t, const char *name, mode_t mode) + { this->priv_open_or_create(detail::DoOpenOrCreate, name, mode); } + + //!Tries to open a file with name "name", with the access mode "mode". + //!If the file does not previously exist, it throws an error. + file_wrapper(open_only_t, const char *name, mode_t mode) + { this->priv_open_or_create(detail::DoOpen, name, mode); } + + //!Moves the ownership of "moved"'s file to *this. + //!After the call, "moved" does not represent any file. + //!Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + file_wrapper + (detail::moved_object moved) + { this->swap(moved.get()); } + #else + file_wrapper(file_wrapper &&moved) + { this->swap(moved); } + #endif + + //!Moves the ownership of "moved"'s file to *this. + //!After the call, "moved" does not represent any file. + //!Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + file_wrapper &operator= + (detail::moved_object moved) + { + file_wrapper tmp(moved); + this->swap(tmp); + return *this; + } + #else + file_wrapper &operator=(file_wrapper &&moved) + { + file_wrapper tmp(detail::move_impl(moved)); + this->swap(tmp); + return *this; + } + #endif + + //!Swaps to file_wrappers. + //!Does not throw + void swap(file_wrapper &other); + + //!Erases a file from the system. + //!Returns false on error. Never throws + static bool remove(const char *name); + + //!Sets the size of the file + void truncate(offset_t length); + + //!Closes the + //!file + ~file_wrapper(); + + //!Returns the name of the file + //!used in the constructor + const char *get_name() const; + + //!Returns the name of the file + //!used in the constructor + bool get_size(offset_t &size) const; + + //!Returns access mode + //!used in the constructor + mode_t get_mode() const; + + //!Get mapping handle + //!to use with mapped_region + mapping_handle_t get_mapping_handle() const; + + private: + //!Closes a previously opened file mapping. Never throws. + void priv_close(); + //!Closes a previously opened file mapping. Never throws. + bool priv_open_or_create(detail::create_enum_t type, const char *filename, mode_t mode); + + file_handle_t m_handle; + mode_t m_mode; + std::string m_filename; +}; + +inline file_wrapper::file_wrapper() + : m_handle(file_handle_t(detail::invalid_file())) +{} + +inline file_wrapper::~file_wrapper() +{ this->priv_close(); } + +inline const char *file_wrapper::get_name() const +{ return m_filename.c_str(); } + +inline bool file_wrapper::get_size(offset_t &size) const +{ return get_file_size((file_handle_t)m_handle, size); } + +inline void file_wrapper::swap(file_wrapper &other) +{ + std::swap(m_handle, other.m_handle); + std::swap(m_mode, other.m_mode); + m_filename.swap(other.m_filename); +} + +inline mapping_handle_t file_wrapper::get_mapping_handle() const +{ return mapping_handle_from_file_handle(m_handle); } + +inline mode_t file_wrapper::get_mode() const +{ return m_mode; } + +inline bool file_wrapper::priv_open_or_create + (detail::create_enum_t type, + const char *filename, + mode_t mode) +{ + m_filename = filename; + + if(mode != read_only && mode != read_write){ + error_info err(mode_error); + throw interprocess_exception(err); + } + + //Open file existing native API to obtain the handle + switch(type){ + case detail::DoOpen: + m_handle = open_existing_file(filename, mode); + break; + case detail::DoCreate: + m_handle = create_new_file(filename, mode); + break; + case detail::DoOpenOrCreate: + m_handle = create_or_open_file(filename, mode); + break; + default: + { + error_info err = other_error; + throw interprocess_exception(err); + } + } + + //Check for error + if(m_handle == invalid_file()){ + throw interprocess_exception(error_info(system_error_code())); + } + + m_mode = mode; + return true; +} + +inline bool file_wrapper::remove(const char *filename) +{ return delete_file(filename); } + +inline void file_wrapper::truncate(offset_t length) +{ + if(!truncate_file(m_handle, length)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +inline void file_wrapper::priv_close() +{ + if(m_handle != invalid_file()){ + close_file(m_handle); + m_handle = invalid_file(); + } +} + +} //namespace detail{ +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP diff --git a/win32/include/boost/interprocess/detail/in_place_interface.hpp b/win32/include/boost/interprocess/detail/in_place_interface.hpp new file mode 100755 index 000000000..148f1a235 --- /dev/null +++ b/win32/include/boost/interprocess/detail/in_place_interface.hpp @@ -0,0 +1,72 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP +#define BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include //typeid + +//!\file +//!Describes an abstract interface for placement construction and destruction. + +namespace boost { +namespace interprocess { +namespace detail { + +struct in_place_interface +{ + in_place_interface(std::size_t alignm, std::size_t sz, const char *tname) + : alignment(alignm), size(sz), type_name(tname) + {} + + std::size_t alignment; + std::size_t size; + const char *type_name; + + virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed) = 0; + virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed) = 0; + virtual ~in_place_interface(){} +}; + +template +struct placement_destroy : public in_place_interface +{ + placement_destroy() + : in_place_interface(detail::alignment_of::value, sizeof(T), typeid(T).name()) + {} + + virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed) + { + T* memory = static_cast(mem); + for(destroyed = 0; destroyed < num; ++destroyed) + (memory++)->~T(); + } + + virtual void construct_n(void *, std::size_t, std::size_t &) {} + + private: + void destroy(void *mem) + { static_cast(mem)->~T(); } +}; + +} +} +} //namespace boost { namespace interprocess { namespace detail { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP diff --git a/win32/include/boost/interprocess/detail/interprocess_tester.hpp b/win32/include/boost/interprocess/detail/interprocess_tester.hpp new file mode 100755 index 000000000..679d0f1ab --- /dev/null +++ b/win32/include/boost/interprocess/detail/interprocess_tester.hpp @@ -0,0 +1,31 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP +#define BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP + +namespace boost{ +namespace interprocess{ +namespace detail{ + +class interprocess_tester +{ + public: + template + static void dont_close_on_destruction(T &t) + { t.dont_close_on_destruction(); } +}; + +} //namespace detail{ +} //namespace interprocess{ +} //namespace boost{ + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP + diff --git a/win32/include/boost/interprocess/detail/intersegment_ptr.hpp b/win32/include/boost/interprocess/detail/intersegment_ptr.hpp new file mode 100755 index 000000000..58f0d6850 --- /dev/null +++ b/win32/include/boost/interprocess/detail/intersegment_ptr.hpp @@ -0,0 +1,1054 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP +#define BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include //vector +#include //set +#include +#include +#include +#include +#include //BOOST_STATIC_ASSERT +#include //CHAR_BIT +#include +#include //assert +#include + +//!\file +//! +namespace boost { + +//Predeclarations +template +struct has_trivial_constructor; + +template +struct has_trivial_destructor; + +namespace interprocess { + +template +struct is_multisegment_ptr; + +struct intersegment_base +{ + typedef intersegment_base self_t; + BOOST_STATIC_ASSERT((sizeof(std::size_t) == sizeof(void*))); + BOOST_STATIC_ASSERT((sizeof(void*)*CHAR_BIT == 32 || sizeof(void*)*CHAR_BIT == 64)); + static const std::size_t size_t_bits = (sizeof(void*)*CHAR_BIT == 32) ? 32 : 64; + static const std::size_t ctrl_bits = 2; + static const std::size_t align_bits = 12; + static const std::size_t align = std::size_t(1) << align_bits; + static const std::size_t max_segment_size_bits = size_t_bits - 2; + static const std::size_t max_segment_size = std::size_t(1) << max_segment_size_bits; + + static const std::size_t begin_bits = max_segment_size_bits - align_bits; + static const std::size_t pow_size_bits_helper = static_log2::value; + static const std::size_t pow_size_bits = + (max_segment_size_bits == (std::size_t(1) << pow_size_bits_helper)) ? + pow_size_bits_helper : pow_size_bits_helper + 1; + static const std::size_t frc_size_bits = + size_t_bits - ctrl_bits - begin_bits - pow_size_bits; + + BOOST_STATIC_ASSERT(((size_t_bits - pow_size_bits - frc_size_bits) >= ctrl_bits )); + + static const std::size_t relative_size_bits = + size_t_bits - max_segment_size_bits - ctrl_bits; + + static const std::size_t is_pointee_outside = 0; + static const std::size_t is_in_stack = 1; + static const std::size_t is_relative = 2; + static const std::size_t is_segmented = 3; + static const std::size_t is_max_mode = 4; + + intersegment_base() + { + this->set_mode(is_pointee_outside); + this->set_null(); + } + + struct relative_addressing + { + std::size_t ctrl : 2; + std::size_t pow : pow_size_bits; + std::size_t frc : frc_size_bits; + std::size_t beg : begin_bits; + std::ptrdiff_t off : sizeof(ptrdiff_t)*CHAR_BIT - 2; + std::ptrdiff_t bits : 2; + }; + + struct direct_addressing + { + std::size_t ctrl : 2; + std::size_t dummy : sizeof(std::size_t)*CHAR_BIT - 2; + void * addr; + }; + + struct segmented_addressing + { + std::size_t ctrl : 2; + std::size_t segment : sizeof(std::size_t)*CHAR_BIT - 2; + std::size_t off : sizeof(std::size_t)*CHAR_BIT - 2; + std::size_t bits : 2; + }; + + union members_t{ + relative_addressing relative; + direct_addressing direct; + segmented_addressing segmented; + } members; + + BOOST_STATIC_ASSERT(sizeof(members_t) == 2*sizeof(std::size_t)); + + void *relative_calculate_begin_addr() const + { + const std::size_t mask = ~(align - 1); + std::size_t beg = this->members.relative.beg; + return (void*)((((std::size_t)this) & mask) - (beg << align_bits)); + } + + void relative_set_begin_from_base(void *addr) + { + assert(addr < (void*)this); + std::size_t off = (char*)this - (char*)addr; + members.relative.beg = off >> align_bits; + } + + //!Obtains the address pointed by the + //!object + std::size_t relative_size() const + { + std::size_t pow = members.relative.pow; + std::size_t size = (std::size_t(1u) << pow); + assert(pow >= frc_size_bits); + size |= members.relative.frc << (pow - frc_size_bits); + return size; + } + + static std::size_t calculate_size(std::size_t orig_size, std::size_t &pow, std::size_t &frc) + { + if(orig_size < align) + orig_size = align; + orig_size = detail::get_rounded_size_po2(orig_size, align); + pow = detail::floor_log2(orig_size); + std::size_t low_size = (std::size_t(1) << pow); + std::size_t diff = orig_size - low_size; + assert(pow >= frc_size_bits); + std::size_t rounded = detail::get_rounded_size_po2 + (diff, (1u << (pow - frc_size_bits))); + if(rounded == low_size){ + ++pow; + frc = 0; + rounded = 0; + } + else{ + frc = rounded >> (pow - frc_size_bits); + } + assert(((frc << (pow - frc_size_bits)) & (align-1))==0); + return low_size + rounded; + } + + std::size_t get_mode()const + { return members.direct.ctrl; } + + void set_mode(std::size_t mode) + { + assert(mode < is_max_mode); + members.direct.ctrl = mode; + } + + //!Returns true if object represents + //!null pointer + bool is_null() const + { + return (this->get_mode() < is_relative) && + !members.direct.dummy && + !members.direct.addr; + } + + //!Sets the object to represent + //!the null pointer + void set_null() + { + if(this->get_mode() >= is_relative){ + this->set_mode(is_pointee_outside); + } + members.direct.dummy = 0; + members.direct.addr = 0; + } + + static std::size_t round_size(std::size_t orig_size) + { + std::size_t pow, frc; + return calculate_size(orig_size, pow, frc); + } +}; + + + +//!Configures intersegment_ptr with the capability to address: +//!2^(sizeof(std::size_t)*CHAR_BIT/2) segment groups +//!2^(sizeof(std::size_t)*CHAR_BIT/2) segments per group. +//!2^(sizeof(std::size_t)*CHAR_BIT/2)-1 bytes maximum per segment. +//!The mapping is implemented through flat_maps synchronized with mutexes. +template +struct flat_map_intersegment + : public intersegment_base +{ + typedef flat_map_intersegment self_t; + + void set_from_pointer(const volatile void *ptr) + { this->set_from_pointer((const void *)ptr); } + + //!Obtains the address pointed + //!by the object + void *get_pointer() const + { + if(is_null()){ + return 0; + } + switch(this->get_mode()){ + case is_relative: + return (char*)this + members.relative.off; + break; + case is_segmented: + { + segment_info_t segment_info; + std::size_t offset; + void *this_base; + get_segment_info_and_offset(this, segment_info, offset, this_base); + char *base = (char*)segment_info.group->address_of(this->members.segmented.segment); + return base + this->members.segmented.off; + } + break; + case is_in_stack: + case is_pointee_outside: + return members.direct.addr; + break; + default: + return 0; + break; + } + } + + //!Calculates the distance between two basic_intersegment_ptr-s. + //!This only works with two basic_intersegment_ptr pointing + //!to the same segment. Otherwise undefined + std::ptrdiff_t diff(const self_t &other) const + { return (char*)this->get_pointer() - (char*)other.get_pointer(); } + + //!Returns true if both point to + //!the same object + bool equal(const self_t &y) const + { return this->get_pointer() == y.get_pointer(); } + + //!Returns true if *this is less than other. + //!This only works with two basic_intersegment_ptr pointing + //!to the same segment group. Otherwise undefined. Never throws + bool less(const self_t &y) const + { return this->get_pointer() < y.get_pointer(); } + + void swap(self_t &other) + { + void *ptr_this = this->get_pointer(); + void *ptr_other = other.get_pointer(); + other.set_from_pointer(ptr_this); + this->set_from_pointer(ptr_other); + } + + //!Sets the object internals to represent the + //!address pointed by ptr + void set_from_pointer(const void *ptr) + { + if(!ptr){ + this->set_null(); + return; + } + + std::size_t mode = this->get_mode(); + if(mode == is_in_stack){ + members.direct.addr = (void*)ptr; + return; + } + if(mode == is_relative){ + char *beg_addr = (char*)this->relative_calculate_begin_addr(); + std::size_t seg_size = this->relative_size(); + if(ptr >= beg_addr && ptr < (beg_addr + seg_size)){ + members.relative.off = (char*)ptr - (char*)this; + return; + } + } + std::size_t ptr_offset; + std::size_t this_offset; + segment_info_t ptr_info; + segment_info_t this_info; + void *ptr_base; + void *this_base; + get_segment_info_and_offset(this, this_info, this_offset, this_base); + + if(!this_info.group){ + this->set_mode(is_in_stack); + this->members.direct.addr = (void*)ptr; + } + else{ + get_segment_info_and_offset(ptr, ptr_info, ptr_offset, ptr_base); + + if(ptr_info.group != this_info.group){ + this->set_mode(is_pointee_outside); + this->members.direct.addr = (void*)ptr; + } + else if(ptr_info.id == this_info.id){ + this->set_mode(is_relative); + members.relative.off = ((char*)ptr - (char*)this); + this->relative_set_begin_from_base(this_base); + std::size_t pow, frc; + std::size_t s = calculate_size(this_info.size, pow, frc); + assert(this_info.size == s); + this->members.relative.pow = pow; + this->members.relative.frc = frc; + } + else{ + this->set_mode(is_segmented); + this->members.segmented.segment = ptr_info.id; + this->members.segmented.off = ptr_offset; + } + } + } + + //!Sets the object internals to represent the address pointed + //!by another flat_map_intersegment + void set_from_other(const self_t &other) + { + this->set_from_pointer(other.get_pointer()); + } + + //!Increments internal + //!offset + void inc_offset(std::ptrdiff_t bytes) + { + this->set_from_pointer((char*)this->get_pointer()+bytes); + } + + //!Decrements internal + //!offset + void dec_offset(std::ptrdiff_t bytes) + { + this->set_from_pointer((char*)this->get_pointer()-bytes); + } + + ////////////////////////////////////// + ////////////////////////////////////// + ////////////////////////////////////// + + flat_map_intersegment() + : intersegment_base() + {} + + ~flat_map_intersegment() + {} + + private: + + class segment_group_t + { + struct segment_data + { + void *addr; + std::size_t size; + }; + vector m_segments; + multi_segment_services &m_ms_services; + + public: + segment_group_t(multi_segment_services &ms_services) + : m_ms_services(ms_services) + {} + + void push_back(void *addr, std::size_t size) + { + segment_data d = { addr, size }; + m_segments.push_back(d); + } + + void pop_back() + { + assert(!m_segments.empty()); + m_segments.erase(--m_segments.end()); + } + + + void *address_of(std::size_t segment_id) + { + assert(segment_id < (std::size_t)m_segments.size()); + return m_segments[segment_id].addr; + } + + void clear_segments() + { m_segments.clear(); } + + std::size_t get_size() const + { return m_segments.size(); } + + multi_segment_services &get_multi_segment_services() const + { return m_ms_services; } + + friend bool operator< (const segment_group_t&l, const segment_group_t &r) + { return &l.m_ms_services < &r.m_ms_services; } + }; + + struct segment_info_t + { + std::size_t size; + std::size_t id; + segment_group_t *group; + segment_info_t() + : size(0), id(0), group(0) + {} + }; + + typedef set segment_groups_t; + + typedef boost::interprocess::flat_map + > ptr_to_segment_info_t; + + struct mappings_t : Mutex + { + //!Mutex to preserve integrity in multi-threaded + //!enviroments + typedef Mutex mutex_type; + //!Maps base addresses and segment information + //!(size and segment group and id)* + + ptr_to_segment_info_t m_ptr_to_segment_info; + + ~mappings_t() + { + //Check that all mappings have been erased + assert(m_ptr_to_segment_info.empty()); + } + }; + + //Static members + static mappings_t s_map; + static segment_groups_t s_groups; + public: + + typedef segment_group_t* segment_group_id; + + //!Returns the segment and offset + //!of an address + static void get_segment_info_and_offset(const void *ptr, segment_info_t &segment, std::size_t &offset, void *&base) + { + //------------------------------------------------------------------ + boost::interprocess::scoped_lock lock(s_map); + //------------------------------------------------------------------ + base = 0; + if(s_map.m_ptr_to_segment_info.empty()){ + segment = segment_info_t(); + offset = detail::char_ptr_cast(ptr) - detail::char_ptr_cast(); + return; + } + //Find the first base address greater than ptr + typename ptr_to_segment_info_t::iterator it + = s_map.m_ptr_to_segment_info.upper_bound(ptr); + if(it == s_map.m_ptr_to_segment_info.begin()){ + segment = segment_info_t(); + offset = detail::char_ptr_cast(ptr) - detail::char_ptr_cast(); + } + //Go to the previous one + --it; + char * segment_base = detail::char_ptr_cast(it->first); + std::size_t segment_size = it->second.size; + + if(segment_base <= detail::char_ptr_cast(ptr) && + (segment_base + segment_size) >= detail::char_ptr_cast(ptr)){ + segment = it->second; + offset = detail::char_ptr_cast(ptr) - segment_base; + base = segment_base; + } + else{ + segment = segment_info_t(); + offset = detail::char_ptr_cast(ptr) - detail::char_ptr_cast(); + } + } + + //!Associates a segment defined by group/id with a base address and size. + //!Returns false if the group is not found or there is an error + static void insert_mapping(segment_group_id group_id, void *ptr, std::size_t size) + { + //------------------------------------------------------------------ + boost::interprocess::scoped_lock lock(s_map); + //------------------------------------------------------------------ + + typedef typename ptr_to_segment_info_t::value_type value_type; + typedef typename ptr_to_segment_info_t::iterator iterator; + typedef std::pair it_b_t; + + segment_info_t info; + info.group = group_id; + info.size = size; + info.id = group_id->get_size(); + + it_b_t ret = s_map.m_ptr_to_segment_info.insert(value_type(ptr, info)); + assert(ret.second); + + value_eraser v_eraser(s_map.m_ptr_to_segment_info, ret.first); + group_id->push_back(ptr, size); + v_eraser.release(); + } + + static bool erase_last_mapping(segment_group_id group_id) + { + //------------------------------------------------------------------ + boost::interprocess::scoped_lock lock(s_map); + //------------------------------------------------------------------ + if(!group_id->get_size()){ + return false; + } + else{ + void *addr = group_id->address_of(group_id->get_size()-1); + group_id->pop_back(); + std::size_t erased = s_map.m_ptr_to_segment_info.erase(addr); + assert(erased); + return true; + } + } + + static segment_group_id new_segment_group(multi_segment_services *services) + { + { //------------------------------------------------------------------ + boost::interprocess::scoped_lock lock(s_map); + //------------------------------------------------------------------ + typedef typename segment_groups_t::iterator iterator; + std::pair ret = + s_groups.insert(segment_group_t(*services)); + assert(ret.second); + return &*ret.first; + } + } + + static bool delete_group(segment_group_id id) + { + { //------------------------------------------------------------------ + boost::interprocess::scoped_lock lock(s_map); + //------------------------------------------------------------------ + bool success = 1u == s_groups.erase(segment_group_t(*id)); + if(success){ + typedef typename ptr_to_segment_info_t::iterator ptr_to_segment_info_it; + ptr_to_segment_info_it it(s_map.m_ptr_to_segment_info.begin()); + while(it != s_map.m_ptr_to_segment_info.end()){ + if(it->second.group == id){ + it = s_map.m_ptr_to_segment_info.erase(it); + } + else{ + ++it; + } + } + } + return success; + } + } +}; + +//!Static map-segment_info associated with +//!flat_map_intersegment<> +template +typename flat_map_intersegment::mappings_t + flat_map_intersegment::s_map; + +//!Static segment group container associated with +//!flat_map_intersegment<> +template +typename flat_map_intersegment::segment_groups_t + flat_map_intersegment::s_groups; + +//!A smart pointer that can point to a pointee that resides in another memory +//!memory mapped or shared memory segment. +template +class intersegment_ptr : public flat_map_intersegment +{ + typedef flat_map_intersegment PT; + typedef intersegment_ptr self_t; + typedef PT base_t; + + void unspecified_bool_type_func() const {} + typedef void (self_t::*unspecified_bool_type)() const; + + public: + typedef T * pointer; + typedef typename detail::add_reference::type reference; + typedef T value_type; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; + + public: //Public Functions + + //!Constructor from raw pointer (allows "0" pointer conversion). + //!Never throws. + intersegment_ptr(pointer ptr = 0) + { base_t::set_from_pointer(ptr); } + + //!Constructor from other pointer. + //!Never throws. + template + intersegment_ptr(U *ptr){ base_t::set_from_pointer(pointer(ptr)); } + + //!Constructor from other intersegment_ptr + //!Never throws + intersegment_ptr(const intersegment_ptr& ptr) + { base_t::set_from_other(ptr); } + + //!Constructor from other intersegment_ptr. If pointers of pointee types are + //!convertible, intersegment_ptrs will be convertibles. Never throws. + template + intersegment_ptr(const intersegment_ptr &ptr) + { pointer p(ptr.get()); (void)p; base_t::set_from_other(ptr); } + + //!Emulates static_cast operator. + //!Never throws. + template + intersegment_ptr(const intersegment_ptr &r, detail::static_cast_tag) + { base_t::set_from_pointer(static_cast(r.get())); } +/* + { + if(r.is_null()){ + base_t::set_from_pointer(0); + } + else{ + //Some dirty tricks to safe segment operations. + //Calculate pointer adjustment and adjust offset. + pointer ptr = reinterpret_cast(this); + std::ptrdiff_t difference = detail::char_ptr_cast(static_cast(ptr)) - + detail::char_ptr_cast(ptr); + base_t::set_from_other(r); + base_t::inc_offset(difference*sizeof(T)); + } + }*/ + + //!Emulates const_cast operator. + //!Never throws. + template + intersegment_ptr(const intersegment_ptr &r, detail::const_cast_tag) + { base_t::set_from_pointer(const_cast(r.get())); } + + //!Emulates dynamic_cast operator. + //!Never throws. + template + intersegment_ptr(const intersegment_ptr &r, detail::dynamic_cast_tag) + { base_t::set_from_pointer(dynamic_cast(r.get())); } + + //!Emulates reinterpret_cast operator. + //!Never throws. + template + intersegment_ptr(const intersegment_ptr &r, detail::reinterpret_cast_tag) + { base_t::set_from_pointer(reinterpret_cast(r.get())); } + + //!Obtains raw pointer from offset. + //!Never throws. + pointer get()const + { return (pointer)base_t::get_pointer(); } + + //!Pointer-like -> operator. It can return 0 pointer. + //!Never throws. + pointer operator->() const + { return self_t::get(); } + + //!Dereferencing operator, if it is a null intersegment_ptr behavior + //!is undefined. Never throws. + reference operator* () const + { return *(self_t::get()); } + + //!Indexing operator. + //!Never throws. + reference operator[](std::ptrdiff_t idx) const + { return self_t::get()[idx]; } + + //!Assignment from pointer (saves extra conversion). + //!Never throws. + intersegment_ptr& operator= (pointer from) + { base_t::set_from_pointer(from); return *this; } + + //!Assignment from other intersegment_ptr. + //!Never throws. + intersegment_ptr& operator= (const intersegment_ptr &ptr) + { base_t::set_from_other(ptr); return *this; } + + //!Assignment from related intersegment_ptr. If pointers of pointee types + //!are assignable, intersegment_ptrs will be assignable. Never throws. + template + intersegment_ptr& operator= (const intersegment_ptr & ptr) + { + pointer p(ptr.get()); (void)p; + base_t::set_from_other(ptr); return *this; + } + + //!intersegment_ptr + std::ptrdiff_t. + //!Never throws. + intersegment_ptr operator+ (std::ptrdiff_t idx) const + { + intersegment_ptr result (*this); + result.inc_offset(idx*sizeof(T)); + return result; + } + + //!intersegment_ptr - std::ptrdiff_t. + //!Never throws. + intersegment_ptr operator- (std::ptrdiff_t idx) const + { + intersegment_ptr result (*this); + result.dec_offset(idx*sizeof(T)); + return result; + } + + //!intersegment_ptr += std::ptrdiff_t. + //!Never throws. + intersegment_ptr &operator+= (std::ptrdiff_t offset) + { base_t::inc_offset(offset*sizeof(T)); return *this; } + + //!intersegment_ptr -= std::ptrdiff_t. + //!Never throws. + intersegment_ptr &operator-= (std::ptrdiff_t offset) + { base_t::dec_offset(offset*sizeof(T)); return *this; } + + //!++intersegment_ptr. + //!Never throws. + intersegment_ptr& operator++ (void) + { base_t::inc_offset(sizeof(T)); return *this; } + + //!intersegment_ptr++. + //!Never throws. + intersegment_ptr operator++ (int) + { intersegment_ptr temp(*this); ++*this; return temp; } + + //!--intersegment_ptr. + //!Never throws. + intersegment_ptr& operator-- (void) + { base_t::dec_offset(sizeof(T)); return *this; } + + //!intersegment_ptr--. + //!Never throws. + intersegment_ptr operator-- (int) + { intersegment_ptr temp(*this); --*this; return temp; } + + //!Safe bool conversion operator. + //!Never throws. + operator unspecified_bool_type() const + { return base_t::is_null()? 0 : &self_t::unspecified_bool_type_func; } + + //!Not operator. Not needed in theory, but improves portability. + //!Never throws. + bool operator! () const + { return base_t::is_null(); } + + //!Swaps two intersegment_ptr-s. More efficient than std::swap. + //!Never throws. + void swap(intersegment_ptr &other) + { base_t::swap(other); } + + //!Calculates the distance between two intersegment_ptr-s. + //!This only works with two basic_intersegment_ptr pointing + //!to the same segment. Otherwise undefined + template + ptrdiff_t _diff(const intersegment_ptr &other) const + { return base_t::diff(other); } + + //!Returns true if both point to the + //!same object + template + bool _equal(const intersegment_ptr&other) const + { return base_t::equal(other); } + + //!Returns true if *this is less than other. + //!This only works with two basic_intersegment_ptr pointing + //!to the same segment group. Otherwise undefined. Never throws + template + bool _less(const intersegment_ptr &other) const + { return base_t::less(other); } +}; + +//!Compares the equality of two intersegment_ptr-s. +//!Never throws. +template inline +bool operator ==(const intersegment_ptr &left, + const intersegment_ptr &right) +{ + //Make sure both pointers can be compared + bool e = typename intersegment_ptr::pointer(0) == + typename intersegment_ptr::pointer(0); + (void)e; + return left._equal(right); +} + +//!Returns true if *this is less than other. +//!This only works with two basic_intersegment_ptr pointing +//!to the same segment group. Otherwise undefined. Never throws +template inline +bool operator <(const intersegment_ptr &left, + const intersegment_ptr &right) +{ + //Make sure both pointers can be compared + bool e = typename intersegment_ptr::pointer(0) < + typename intersegment_ptr::pointer(0); + (void)e; + return left._less(right); +} + +template inline +bool operator!= (const intersegment_ptr &pt1, + const intersegment_ptr &pt2) +{ return !(pt1 ==pt2); } + +//!intersegment_ptr <= intersegment_ptr. +//!Never throws. +template inline +bool operator<= (const intersegment_ptr &pt1, + const intersegment_ptr &pt2) +{ return !(pt1 > pt2); } + +//!intersegment_ptr > intersegment_ptr. +//!Never throws. +template inline +bool operator> (const intersegment_ptr &pt1, + const intersegment_ptr &pt2) +{ return (pt2 < pt1); } + +//!intersegment_ptr >= intersegment_ptr. +//!Never throws. +template inline +bool operator>= (const intersegment_ptr &pt1, + const intersegment_ptr &pt2) +{ return !(pt1 < pt2); } + +//!operator<< +template inline +std::basic_ostream & operator<< + (std::basic_ostream & os, const intersegment_ptr & p) +{ return os << p.get(); } + +//!operator>> +template inline +std::basic_istream & operator>> + (std::basic_istream & os, intersegment_ptr & p) +{ U * tmp; return os >> tmp; p = tmp; } + +//!std::ptrdiff_t + intersegment_ptr. +//!The result is another pointer of the same segment +template inline +intersegment_ptr operator+ + (std::ptrdiff_t diff, const intersegment_ptr& right) +{ return right + diff; } + +//!intersegment_ptr - intersegment_ptr. +//!This only works with two intersegment_ptr-s that point to the +//!same segment +template inline +std::ptrdiff_t operator- (const intersegment_ptr &pt, + const intersegment_ptr &pt2) +{ return pt._diff(pt2)/sizeof(T); } + +//! swap specialization +template inline +void swap (boost::interprocess::intersegment_ptr &pt, + boost::interprocess::intersegment_ptr &pt2) +{ pt.swap(pt2); } + +//!get_pointer() enables boost::mem_fn to recognize intersegment_ptr. +//!Never throws. +template inline +T * get_pointer(boost::interprocess::intersegment_ptr const & p) +{ return p.get(); } + +//!Simulation of static_cast between pointers. +//!Never throws. +template inline +boost::interprocess::intersegment_ptr static_pointer_cast(const boost::interprocess::intersegment_ptr &r) +{ return boost::interprocess::intersegment_ptr(r, boost::interprocess::detail::static_cast_tag()); } + +//!Simulation of const_cast between pointers. +//!Never throws. +template inline +boost::interprocess::intersegment_ptr const_pointer_cast(const boost::interprocess::intersegment_ptr &r) +{ return boost::interprocess::intersegment_ptr(r, boost::interprocess::detail::const_cast_tag()); } + +//!Simulation of dynamic_cast between pointers. +//!Never throws. +template inline +boost::interprocess::intersegment_ptr dynamic_pointer_cast(const boost::interprocess::intersegment_ptr &r) +{ return boost::interprocess::intersegment_ptr(r, boost::interprocess::detail::dynamic_cast_tag()); } + +//!Simulation of reinterpret_cast between pointers. +//!Never throws. +template inline +boost::interprocess::intersegment_ptr reinterpret_pointer_cast(const boost::interprocess::intersegment_ptr &r) +{ return boost::interprocess::intersegment_ptr(r, boost::interprocess::detail::reinterpret_cast_tag()); } + +//!Trait class to detect if an smart pointer has +//!multi-segment addressing capabilities. +template +struct is_multisegment_ptr + > +{ + static const bool value = true; +}; + +} //namespace interprocess { + +#if defined(_MSC_VER) && (_MSC_VER < 1400) +//!get_pointer() enables boost::mem_fn to recognize intersegment_ptr. +//!Never throws. +template inline +T * get_pointer(boost::interprocess::intersegment_ptr const & p) +{ return p.get(); } +#endif + +//!has_trivial_constructor<> == true_type specialization +//!for optimizations +template +struct has_trivial_constructor + < boost::interprocess::intersegment_ptr > + : public true_type{}; + +//!has_trivial_destructor<> == true_type specialization +//!for optimizations +template +struct has_trivial_destructor + < boost::interprocess::intersegment_ptr > + : public true_type{}; + +} //namespace boost { + +#include + +#if 0 + +//bits +//-> is_segmented +//-> is_relative +//-> is_in_stack +//-> is_pointee_outside + +//Data + + + + +//segmented: +// +// std::size_t ctrl : CTRL_BITS; +// std::size_t segment : MAX_SEGMENT_BITS; +// std::size_t offset; + +//RELATIVE_SIZE_BITS = SIZE_T_BITS - +// MAX_SEGMENT_BITS - +// CTRL_BITS 10 10 +//MAX_SEGMENT_SIZE = SIZE_T_BITS - ALIGN_BITS 20 52 + +//SIZE_T_BITS - 1 - ALIGN_BITS 19 51 +//POW_SIZE_BITS = upper_log2 +// (SIZE_T_BITS - 1 - ALIGN_BITS) 5 6 +//FRC_SIZE_BITS = SIZE_T_BITS - CTRL_BITS +// MAX_SEGMENT_SIZE_ALIGNBITS - POW_SIZE_BITS 6 5 + +//relative: +// +// std::size_t ctrl : CTRL_BITS; 2 2 +// std::size_t size_pow : POW_SIZE_BITS 5 6 +// std::size_t size_frc : FRC_SIZE_BITS; 6 5 +// std::size_t start : MAX_SEGMENT_SIZE_ALIGNBITS;19 51 +// std::ptrdiff_t distance : SIZE_T_BITS; 32 64 + +//direct: +// +// std::size_t ctrl : CTRL_BITS; 2 2 +// std::size_t dummy : SIZE_T_BITS - CTRL_BITS 30 62 +// void *addr : SIZE_T_BITS; 32 64 + +//32 bits systems: +//Page alignment: 2**12 +// + +//!Obtains the address pointed by the +//!object +void *get_pointer() const +{ + if(this->is_pointee_outside() || this->is_in_stack()){ + return raw_address(); + } + else if(this->is_relative()){ + return ((char*)this) + this->relative_pointee_offset(); + } + else{ + group_manager *m = get_segment_group_manager(addr); + char *base = (char*)m->get_id_address(this->segmented_id()); + return base + this->segmented_offset(); + } +} + +void set_from_pointer(const void *ptr) +{ + if(!ptr){ + this->set_pointee_outside(); + this->raw_address(ptr); + } + else if(this->is_in_stack()){ + this->raw_address(ptr); + } + else if(this->is_relative() && + ( (ptr >= this->relative_start()) + &&(ptr < this->relative_start() + this->relative_size())) + ){ + this->relative_offset(ptr - this); + } + else{ + segment_info_t ptr_info = get_id_from_addr(ptr); + segment_info_t this_info = get_id_from_addr(this); + if(ptr_info.segment_group != this_info.segment_group){ + if(!ptr_info.segment_group){ + this->set_in_stack(); + } + else{ + this->set_pointee_outside(); + } + } + else if(ptr_info.segment_id == this_info.segment_id){ + set_relative(); + this->relative_size (ptr_info.size); + this->relative_offset((char*)ptr - (char*)this); + this->relative_start (ptr_info.base); + } + } +} + +void set_from_other(const self_t &other) +{ this->set_from_pointer(other.get_pointer()); } + +#endif + +#endif //#ifndef BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP + diff --git a/win32/include/boost/interprocess/detail/iterators.hpp b/win32/include/boost/interprocess/detail/iterators.hpp new file mode 100755 index 000000000..0601193fe --- /dev/null +++ b/win32/include/boost/interprocess/detail/iterators.hpp @@ -0,0 +1,475 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. +// (C) Copyright Gennaro Prota 2003 - 2004. +// +// 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_ITERATORS_HPP +#define BOOST_INTERPROCESS_DETAIL_ITERATORS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include + +#include +#include + +namespace boost { +namespace interprocess { + +template +class constant_iterator + : public std::iterator + +{ + typedef constant_iterator this_type; + + public: + explicit constant_iterator(const T &ref, Difference range_size) + : m_ptr(&ref), m_num(range_size){} + + //Constructors + constant_iterator() + : m_ptr(0), m_num(0){} + + constant_iterator& operator++() + { increment(); return *this; } + + constant_iterator operator++(int) + { + constant_iterator result (*this); + increment(); + return result; + } + + friend bool operator== (const constant_iterator& i, const constant_iterator& i2) + { return i.equal(i2); } + + friend bool operator!= (const constant_iterator& i, const constant_iterator& i2) + { return !(i == i2); } + + friend bool operator< (const constant_iterator& i, const constant_iterator& i2) + { return i.less(i2); } + + friend bool operator> (const constant_iterator& i, const constant_iterator& i2) + { return i2 < i; } + + friend bool operator<= (const constant_iterator& i, const constant_iterator& i2) + { return !(i > i2); } + + friend bool operator>= (const constant_iterator& i, const constant_iterator& i2) + { return !(i < i2); } + + friend Difference operator- (const constant_iterator& i, const constant_iterator& i2) + { return i2.distance_to(i); } + + //Arithmetic + constant_iterator& operator+=(Difference off) + { this->advance(off); return *this; } + + constant_iterator operator+(Difference off) const + { + constant_iterator other(*this); + other.advance(off); + return other; + } + + friend constant_iterator operator+(Difference off, const constant_iterator& right) + { return right + off; } + + constant_iterator& operator-=(Difference off) + { this->advance(-off); return *this; } + + constant_iterator operator-(Difference off) const + { return *this + (-off); } + + const T& operator*() const + { return dereference(); } + + const T* operator->() const + { return &(dereference()); } + + private: + const T * m_ptr; + Difference m_num; + + void increment() + { --m_num; } + + void decrement() + { ++m_num; } + + bool equal(const this_type &other) const + { return m_num == other.m_num; } + + bool less(const this_type &other) const + { return other.m_num < m_num; } + + const T & dereference() const + { return *m_ptr; } + + void advance(Difference n) + { m_num -= n; } + + Difference distance_to(const this_type &other)const + { return m_num - other.m_num; } +}; + +template +class default_construct_iterator + : public std::iterator + +{ + typedef default_construct_iterator this_type; + + public: + explicit default_construct_iterator(Difference range_size) + : m_num(range_size){} + + //Constructors + default_construct_iterator() + : m_num(0){} + + default_construct_iterator& operator++() + { increment(); return *this; } + + default_construct_iterator operator++(int) + { + default_construct_iterator result (*this); + increment(); + return result; + } + + friend bool operator== (const default_construct_iterator& i, const default_construct_iterator& i2) + { return i.equal(i2); } + + friend bool operator!= (const default_construct_iterator& i, const default_construct_iterator& i2) + { return !(i == i2); } + + friend bool operator< (const default_construct_iterator& i, const default_construct_iterator& i2) + { return i.less(i2); } + + friend bool operator> (const default_construct_iterator& i, const default_construct_iterator& i2) + { return i2 < i; } + + friend bool operator<= (const default_construct_iterator& i, const default_construct_iterator& i2) + { return !(i > i2); } + + friend bool operator>= (const default_construct_iterator& i, const default_construct_iterator& i2) + { return !(i < i2); } + + friend Difference operator- (const default_construct_iterator& i, const default_construct_iterator& i2) + { return i2.distance_to(i); } + + //Arithmetic + default_construct_iterator& operator+=(Difference off) + { this->advance(off); return *this; } + + default_construct_iterator operator+(Difference off) const + { + default_construct_iterator other(*this); + other.advance(off); + return other; + } + + friend default_construct_iterator operator+(Difference off, const default_construct_iterator& right) + { return right + off; } + + default_construct_iterator& operator-=(Difference off) + { this->advance(-off); return *this; } + + default_construct_iterator operator-(Difference off) const + { return *this + (-off); } + + const T& operator*() const + { return dereference(); } + + const T* operator->() const + { return &(dereference()); } + + private: + Difference m_num; + + void increment() + { --m_num; } + + void decrement() + { ++m_num; } + + bool equal(const this_type &other) const + { return m_num == other.m_num; } + + bool less(const this_type &other) const + { return other.m_num < m_num; } + + const T & dereference() const + { + static T dummy; + return dummy; + } + + void advance(Difference n) + { m_num -= n; } + + Difference distance_to(const this_type &other)const + { return m_num - other.m_num; } +}; + +template +class repeat_iterator + : public std::iterator + +{ + typedef repeat_iterator this_type; + public: + explicit repeat_iterator(T &ref, Difference range_size) + : m_ptr(&ref), m_num(range_size){} + + //Constructors + repeat_iterator() + : m_ptr(0), m_num(0){} + + this_type& operator++() + { increment(); return *this; } + + this_type operator++(int) + { + this_type result (*this); + increment(); + return result; + } + + friend bool operator== (const this_type& i, const this_type& i2) + { return i.equal(i2); } + + friend bool operator!= (const this_type& i, const this_type& i2) + { return !(i == i2); } + + friend bool operator< (const this_type& i, const this_type& i2) + { return i.less(i2); } + + friend bool operator> (const this_type& i, const this_type& i2) + { return i2 < i; } + + friend bool operator<= (const this_type& i, const this_type& i2) + { return !(i > i2); } + + friend bool operator>= (const this_type& i, const this_type& i2) + { return !(i < i2); } + + friend Difference operator- (const this_type& i, const this_type& i2) + { return i2.distance_to(i); } + + //Arithmetic + this_type& operator+=(Difference off) + { this->advance(off); return *this; } + + this_type operator+(Difference off) const + { + this_type other(*this); + other.advance(off); + return other; + } + + friend this_type operator+(Difference off, const this_type& right) + { return right + off; } + + this_type& operator-=(Difference off) + { this->advance(-off); return *this; } + + this_type operator-(Difference off) const + { return *this + (-off); } + + T& operator*() const + { return dereference(); } + + T *operator->() const + { return &(dereference()); } + + private: + T * m_ptr; + Difference m_num; + + void increment() + { --m_num; } + + void decrement() + { ++m_num; } + + bool equal(const this_type &other) const + { return m_num == other.m_num; } + + bool less(const this_type &other) const + { return other.m_num < m_num; } + + T & dereference() const + { return *m_ptr; } + + void advance(Difference n) + { m_num -= n; } + + Difference distance_to(const this_type &other)const + { return m_num - other.m_num; } +}; + +template +struct operator_arrow_proxy +{ + operator_arrow_proxy(const PseudoReference &px) + : m_value(px) + {} + + PseudoReference* operator->() const { return &m_value; } + // This function is needed for MWCW and BCC, which won't call operator-> + // again automatically per 13.3.1.2 para 8 +// operator T*() const { return &m_value; } + mutable PseudoReference m_value; +}; + +template +struct operator_arrow_proxy +{ + operator_arrow_proxy(T &px) + : m_value(px) + {} + + T* operator->() const { return &m_value; } + // This function is needed for MWCW and BCC, which won't call operator-> + // again automatically per 13.3.1.2 para 8 +// operator T*() const { return &m_value; } + mutable T &m_value; +}; + +template +class transform_iterator + : public UnaryFunction + , public std::iterator + < typename Iterator::iterator_category + , typename detail::remove_reference::type + , typename Iterator::difference_type + , operator_arrow_proxy + , typename UnaryFunction::result_type> +{ + public: + explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction()) + : UnaryFunction(f), m_it(it) + {} + + explicit transform_iterator() + : UnaryFunction(), m_it() + {} + + //Constructors + transform_iterator& operator++() + { increment(); return *this; } + + transform_iterator operator++(int) + { + transform_iterator result (*this); + increment(); + return result; + } + + friend bool operator== (const transform_iterator& i, const transform_iterator& i2) + { return i.equal(i2); } + + friend bool operator!= (const transform_iterator& i, const transform_iterator& i2) + { return !(i == i2); } + +/* + friend bool operator> (const transform_iterator& i, const transform_iterator& i2) + { return i2 < i; } + + friend bool operator<= (const transform_iterator& i, const transform_iterator& i2) + { return !(i > i2); } + + friend bool operator>= (const transform_iterator& i, const transform_iterator& i2) + { return !(i < i2); } +*/ + friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2) + { return i2.distance_to(i); } + + //Arithmetic + transform_iterator& operator+=(typename Iterator::difference_type off) + { this->advance(off); return *this; } + + transform_iterator operator+(typename Iterator::difference_type off) const + { + transform_iterator other(*this); + other.advance(off); + return other; + } + + friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right) + { return right + off; } + + transform_iterator& operator-=(typename Iterator::difference_type off) + { this->advance(-off); return *this; } + + transform_iterator operator-(typename Iterator::difference_type off) const + { return *this + (-off); } + + typename UnaryFunction::result_type operator*() const + { return dereference(); } + + operator_arrow_proxy + operator->() const + { return operator_arrow_proxy(dereference()); } + + Iterator & base() + { return m_it; } + + const Iterator & base() const + { return m_it; } + + private: + Iterator m_it; + + void increment() + { ++m_it; } + + void decrement() + { --m_it; } + + bool equal(const transform_iterator &other) const + { return m_it == other.m_it; } + + bool less(const transform_iterator &other) const + { return other.m_it < m_it; } + + typename UnaryFunction::result_type dereference() const + { return UnaryFunction::operator()(*m_it); } + + void advance(typename Iterator::difference_type n) + { std::advance(m_it, n); } + + typename Iterator::difference_type distance_to(const transform_iterator &other)const + { return std::distance(other.m_it, m_it); } +}; + +template +transform_iterator +make_transform_iterator(Iterator it, UnaryFunc fun) +{ + return transform_iterator(it, fun); +} + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_ITERATORS_HPP + diff --git a/win32/include/boost/interprocess/detail/managed_memory_impl.hpp b/win32/include/boost/interprocess/detail/managed_memory_impl.hpp new file mode 100755 index 000000000..83b7dc76c --- /dev/null +++ b/win32/include/boost/interprocess/detail/managed_memory_impl.hpp @@ -0,0 +1,739 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP +#define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// +#include +// +#include +#include +#include +#include + +//!\file +//!Describes a named shared memory allocation user class. +//! + +namespace boost { +namespace interprocess { +namespace detail { + +template +class create_open_func; + +template< + class CharType, + class MemoryAlgorithm, + template class IndexType + > +struct segment_manager_type +{ + typedef segment_manager type; +}; + +//!This class is designed to be a base class to classes that manage +//!creation of objects in a fixed size memory buffer. Apart +//!from allocating raw memory, the user can construct named objects. To +//!achieve this, this class uses the reserved space provided by the allocation +//!algorithm to place a named_allocator_algo, who takes care of name mappings. +//!The class can be customized with the char type used for object names +//!and the memory allocation algorithm to be used.*/ +template < class CharType + , class MemoryAlgorithm + , template class IndexType + , std::size_t Offset = 0 + > +class basic_managed_memory_impl +{ + //Non-copyable + basic_managed_memory_impl(const basic_managed_memory_impl &); + basic_managed_memory_impl &operator=(const basic_managed_memory_impl &); + + template + friend class create_open_func; + + public: + typedef typename segment_manager_type + ::type segment_manager; + typedef CharType char_type; + typedef MemoryAlgorithm memory_algorithm; + typedef typename MemoryAlgorithm::mutex_family mutex_family; + typedef CharType char_t; + typedef std::ptrdiff_t handle_t; + typedef typename segment_manager:: + const_named_iterator const_named_iterator; + typedef typename segment_manager:: + const_unique_iterator const_unique_iterator; + + /// @cond + + typedef typename + segment_manager::char_ptr_holder_t char_ptr_holder_t; + //Experimental. Don't use. + + typedef typename segment_manager::multiallocation_iterator multiallocation_iterator; + + /// @endcond + + static const std::size_t PayloadPerAllocation = segment_manager::PayloadPerAllocation; + + private: + typedef basic_managed_memory_impl + self_t; + protected: + template + static bool grow(const char *filename, std::size_t extra_bytes) + { + typedef typename ManagedMemory::device_type device_type; + //Increase file size + try{ + offset_t old_size; + { + device_type f(open_or_create, filename, read_write); + if(!f.get_size(old_size)) + return false; + f.truncate(old_size + extra_bytes); + } + ManagedMemory managed_memory(open_only, filename); + //Grow always works + managed_memory.self_t::grow(extra_bytes); + } + catch(...){ + return false; + } + return true; + } + + template + static bool shrink_to_fit(const char *filename) + { + typedef typename ManagedMemory::device_type device_type; + std::size_t new_size, old_size; + try{ + ManagedMemory managed_memory(open_only, filename); + old_size = managed_memory.get_size(); + managed_memory.self_t::shrink_to_fit(); + new_size = managed_memory.get_size(); + } + catch(...){ + return false; + } + + //Decrease file size + { + device_type f(open_or_create, filename, read_write); + f.truncate(new_size); + } + return true; + } + + //!Constructor. Allocates basic resources. Never throws. + basic_managed_memory_impl() + : mp_header(0){} + + //!Destructor. Calls close. Never throws. + ~basic_managed_memory_impl() + { this->close_impl(); } + + //!Places segment manager in the reserved space. This can throw. + bool create_impl (void *addr, std::size_t size) + { + if(mp_header) return false; + + //Check if there is enough space + if(size < segment_manager::get_min_size()) + return false; + + //This function should not throw. The index construction can + //throw if constructor allocates memory. So we must catch it. + BOOST_TRY{ + //Let's construct the allocator in memory + mp_header = new(addr) segment_manager(size); + } + BOOST_CATCH(...){ + return false; + } + BOOST_CATCH_END + return true; + } + + //!Connects to a segment manager in the reserved buffer. Never throws. + bool open_impl (void *addr, std::size_t) + { + if(mp_header) return false; + mp_header = static_cast(addr); + return true; + } + + //!Frees resources. Never throws. + bool close_impl() + { + bool ret = mp_header != 0; + mp_header = 0; + return ret; + } + + //!Frees resources and destroys common resources. Never throws. + bool destroy_impl() + { + if(mp_header == 0) + return false; + mp_header->~segment_manager(); + this->close_impl(); + return true; + } + + //! + void grow(std::size_t extra_bytes) + { mp_header->grow(extra_bytes); } + + void shrink_to_fit() + { mp_header->shrink_to_fit(); } + + public: + + //!Returns segment manager. Never throws. + segment_manager *get_segment_manager() const + { return mp_header; } + + //!Returns the base address of the memory in this process. Never throws. + void * get_address () const + { return (char*)mp_header - Offset; } + + //!Returns the size of memory segment. Never throws. + std::size_t get_size () const + { return mp_header->get_size() + Offset; } + + //!Returns the number of free bytes of the memory + //!segment + std::size_t get_free_memory() const + { return mp_header->get_free_memory(); } + + //!Returns the result of "all_memory_deallocated()" function + //!of the used memory algorithm + bool all_memory_deallocated() + { return mp_header->all_memory_deallocated(); } + + //!Returns the result of "check_sanity()" function + //!of the used memory algorithm + bool check_sanity() + { return mp_header->check_sanity(); } + + //!Writes to zero free memory (memory not yet allocated) of + //!the memory algorithm + void zero_free_memory() + { mp_header->zero_free_memory(); } + + //!Transforms an absolute address into an offset from base address. + //!The address must belong to the memory segment. Never throws. + handle_t get_handle_from_address (const void *ptr) const + { + return detail::char_ptr_cast(ptr) - + detail::char_ptr_cast(this->get_address()); + } + + //!Returns true if the address belongs to the managed memory segment + bool belongs_to_segment (const void *ptr) const + { + return ptr >= this->get_address() && + ptr < (detail::char_ptr_cast(ptr) + this->get_size()); + } + + //!Transforms previously obtained offset into an absolute address in the + //!process space of the current process. Never throws.*/ + void * get_address_from_handle (handle_t offset) const + { return detail::char_ptr_cast(this->get_address()) + offset; } + + //!Searches for nbytes of free memory in the segment, marks the + //!memory as used and return the pointer to the memory. If no + //!memory is available throws a boost::interprocess::bad_alloc exception + void* allocate (std::size_t nbytes) + { return mp_header->allocate(nbytes); } + + //!Searches for nbytes of free memory in the segment, marks the + //!memory as used and return the pointer to the memory. If no memory + //!is available returns 0. Never throws. + void* allocate (std::size_t nbytes, std::nothrow_t nothrow) + { return mp_header->allocate(nbytes, nothrow); } + + //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment" + //!must be power of two. If no memory + //!is available returns 0. Never throws. + void * allocate_aligned (std::size_t nbytes, std::size_t alignment, std::nothrow_t nothrow) + { return mp_header->allocate_aligned(nbytes, alignment, nothrow); } + + template + std::pair + allocation_command (allocation_type command, std::size_t limit_size, + std::size_t preferred_size,std::size_t &received_size, + T *reuse_ptr = 0) + { + return mp_header->allocation_command + (command, limit_size, preferred_size, received_size, reuse_ptr); + } + + //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment" + //!must be power of two. If no + //!memory is available throws a boost::interprocess::bad_alloc exception + void * allocate_aligned(std::size_t nbytes, std::size_t alignment) + { return mp_header->allocate_aligned(nbytes, alignment); } + + /// @cond + + //Experimental. Don't use. + + //!Allocates n_elements of elem_size bytes. + multiallocation_iterator allocate_many(std::size_t elem_bytes, std::size_t num_elements) + { return mp_header->allocate_many(elem_bytes, num_elements); } + + //!Allocates n_elements, each one of elem_sizes[i] bytes. + multiallocation_iterator allocate_many(const std::size_t *elem_sizes, std::size_t n_elements) + { return mp_header->allocate_many(elem_sizes, n_elements); } + + //!Allocates n_elements of elem_size bytes. + multiallocation_iterator allocate_many(std::size_t elem_bytes, std::size_t num_elements, std::nothrow_t nothrow) + { return mp_header->allocate_many(elem_bytes, num_elements, nothrow); } + + //!Allocates n_elements, each one of elem_sizes[i] bytes. + multiallocation_iterator allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::nothrow_t nothrow) + { return mp_header->allocate_many(elem_sizes, n_elements, nothrow); } + + /// @endcond + + //!Marks previously allocated memory as free. Never throws. + void deallocate (void *addr) + { if (mp_header) mp_header->deallocate(addr); } + + //!Tries to find a previous named allocation address. Returns a memory + //!buffer and the object count. If not found returned pointer is 0. + //!Never throws. + template + std::pair find (char_ptr_holder_t name) + { return mp_header->template find(name); } + + //!Creates a named object or array in memory + //! + //!Allocates and constructs a T object or an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. If an array is being constructed all objects are + //!created using the same parameters given to this function. + //! + //!-> If the name was previously used, returns 0. + //! + //!-> Throws boost::interprocess::bad_alloc if there is no available memory + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and if an + //!array was being constructed, destructors of created objects are called + //!before freeing the memory. + template + typename segment_manager::template construct_proxy::type + construct(char_ptr_holder_t name) + { return mp_header->template construct(name); } + + //!Finds or creates a named object or array in memory + //! + //!Tries to find an object with the given name in memory. If + //!found, returns the pointer to this pointer. If the object is not found, + //!allocates and constructs a T object or an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. If an array is being constructed all objects are + //!created using the same parameters given to this function. + //! + //!-> Throws boost::interprocess::bad_alloc if there is no available memory + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and if an + //!array was being constructed, destructors of created objects are called + //!before freeing the memory. + template + typename segment_manager::template construct_proxy::type + find_or_construct(char_ptr_holder_t name) + { return mp_header->template find_or_construct(name); } + + //!Creates a named object or array in memory + //! + //!Allocates and constructs a T object or an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. If an array is being constructed all objects are + //!created using the same parameters given to this function. + //! + //!-> If the name was previously used, returns 0. + //! + //!-> Returns 0 if there is no available memory + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and if an + //!array was being constructed, destructors of created objects are called + //!before freeing the memory. + template + typename segment_manager::template construct_proxy::type + construct(char_ptr_holder_t name, std::nothrow_t nothrow) + { return mp_header->template construct(name, nothrow); } + + //!Finds or creates a named object or array in memory + //! + //!Tries to find an object with the given name in memory. If + //!found, returns the pointer to this pointer. If the object is not found, + //!allocates and constructs a T object or an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. If an array is being constructed all objects are + //!created using the same parameters given to this function. + //! + //!-> Returns 0 if there is no available memory + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and if an + //!array was being constructed, destructors of created objects are called + //!before freeing the memory. + template + typename segment_manager::template construct_proxy::type + find_or_construct(char_ptr_holder_t name, std::nothrow_t nothrow) + { return mp_header->template find_or_construct(name, nothrow); } + + //!Creates a named array from iterators in memory + //! + //!Allocates and constructs an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. Each element in the array is created using the + //!objects returned when dereferencing iterators as parameters + //!and incrementing all iterators for each element. + //! + //!-> If the name was previously used, returns 0. + //! + //!-> Throws boost::interprocess::bad_alloc if there is no available memory + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and + //!destructors of created objects are called before freeing the memory. + template + typename segment_manager::template construct_iter_proxy::type + construct_it(char_ptr_holder_t name) + { return mp_header->template construct_it(name); } + + //!Finds or creates a named array from iterators in memory + //! + //!Tries to find an object with the given name in memory. If + //!found, returns the pointer to this pointer. If the object is not found, + //!allocates and constructs an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. Each element in the array is created using the + //!objects returned when dereferencing iterators as parameters + //!and incrementing all iterators for each element. + //! + //!-> If the name was previously used, returns 0. + //! + //!-> Throws boost::interprocess::bad_alloc if there is no available memory + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and + //!destructors of created objects are called before freeing the memory. + template + typename segment_manager::template construct_iter_proxy::type + find_or_construct_it(char_ptr_holder_t name) + { return mp_header->template find_or_construct_it(name); } + + //!Creates a named array from iterators in memory + //! + //!Allocates and constructs an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. Each element in the array is created using the + //!objects returned when dereferencing iterators as parameters + //!and incrementing all iterators for each element. + //! + //!-> If the name was previously used, returns 0. + //! + //!-> If there is no available memory, returns 0. + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and + //!destructors of created objects are called before freeing the memory.*/ + template + typename segment_manager::template construct_iter_proxy::type + construct_it(char_ptr_holder_t name, std::nothrow_t nothrow) + { return mp_header->template construct_it(name, nothrow); } + + //!Finds or creates a named array from iterators in memory + //! + //!Tries to find an object with the given name in memory. If + //!found, returns the pointer to this pointer. If the object is not found, + //!allocates and constructs an array of T in memory, + //!associates this with the given name and returns a pointer to the + //!created object. Each element in the array is created using the + //!objects returned when dereferencing iterators as parameters + //!and incrementing all iterators for each element. + //! + //!-> If the name was previously used, returns 0. + //! + //!-> If there is no available memory, returns 0. + //! + //!-> If T's constructor throws, the function throws that exception. + //! + //!Memory is freed automatically if T's constructor throws and + //!destructors of created objects are called before freeing the memory.*/ + template + typename segment_manager::template construct_iter_proxy::type + find_or_construct_it(char_ptr_holder_t name, std::nothrow_t nothrow) + { return mp_header->template find_or_construct_it(name, nothrow); } + + //!Calls a functor and guarantees that no new construction, search or + //!destruction will be executed by any process while executing the object + //!function call. If the functor throws, this function throws. + template + void atomic_func(Func &f) + { mp_header->atomic_func(f); } + + //!Destroys a named memory object or array. + //! + //!Finds the object with the given name, calls its destructors, + //!frees used memory and returns true. + //! + //!-> If the object is not found, it returns false. + //! + //!Exception Handling: + //! + //!When deleting a dynamically object or array, the Standard + //!does not guarantee that dynamically allocated memory, will be released. + //!Also, when deleting arrays, the Standard doesn't require calling + //!destructors for the rest of the objects if for one of them the destructor + //!terminated with an exception. + //! + //!Destroying an object: + //! + //!If the destructor throws, the memory will be freed and that exception + //!will be thrown. + //! + //!Destroying an array: + //! + //!When destroying an array, if a destructor throws, the rest of + //!destructors are called. If any of these throws, the exceptions are + //!ignored. The name association will be erased, memory will be freed and + //!the first exception will be thrown. This guarantees the unlocking of + //!mutexes and other resources. + //! + //!For all theses reasons, classes with throwing destructors are not + //!recommended. + template + bool destroy(const CharType *name) + { return mp_header->template destroy(name); } + + //!Destroys the unique instance of type T + //! + //!Calls the destructor, frees used memory and returns true. + //! + //!Exception Handling: + //! + //!When deleting a dynamically object, the Standard does not + //!guarantee that dynamically allocated memory will be released. + //! + //!Destroying an object: + //! + //!If the destructor throws, the memory will be freed and that exception + //!will be thrown. + //! + //!For all theses reasons, classes with throwing destructors are not + //!recommended for memory. + template + bool destroy(const detail::unique_instance_t *const ) + { return mp_header->template destroy(unique_instance); } + + //!Destroys the object (named, unique, or anonymous) + //! + //!Calls the destructor, frees used memory and returns true. + //! + //!Exception Handling: + //! + //!When deleting a dynamically object, the Standard does not + //!guarantee that dynamically allocated memory will be released. + //! + //!Destroying an object: + //! + //!If the destructor throws, the memory will be freed and that exception + //!will be thrown. + //! + //!For all theses reasons, classes with throwing destructors are not + //!recommended for memory. + template + void destroy_ptr(const T *ptr) + { mp_header->template destroy_ptr(ptr); } + + //!Returns the name of an object created with construct/find_or_construct + //!functions. Does not throw + template + static const char_type *get_instance_name(const T *ptr) + { return segment_manager::get_instance_name(ptr); } + + //!Returns is the type an object created with construct/find_or_construct + //!functions. Does not throw. + template + static instance_type get_instance_type(const T *ptr) + { return segment_manager::get_instance_type(ptr); } + + //!Returns the length of an object created with construct/find_or_construct + //!functions (1 if is a single element, >=1 if it's an array). Does not throw. + template + static std::size_t get_instance_length(const T *ptr) + { return segment_manager::get_instance_length(ptr); } + + //!Preallocates needed index resources to optimize the + //!creation of "num" named objects in the memory segment. + //!Can throw boost::interprocess::bad_alloc if there is no enough memory. + void reserve_named_objects(std::size_t num) + { mp_header->reserve_named_objects(num); } + + //!Preallocates needed index resources to optimize the + //!creation of "num" unique objects in the memory segment. + //!Can throw boost::interprocess::bad_alloc if there is no enough memory. + void reserve_unique_objects(std::size_t num) + { mp_header->reserve_unique_objects(num); } + + //!Calls shrink_to_fit in both named and unique object indexes + //to try to free unused memory from those indexes. + void shrink_to_fit_indexes() + { mp_header->shrink_to_fit_indexes(); } + + //!Returns the number of named objects stored + //!in the managed segment. + std::size_t get_num_named_objects() + { return mp_header->get_num_named_objects(); } + + //!Returns the number of unique objects stored + //!in the managed segment. + std::size_t get_num_unique_objects() + { return mp_header->get_num_unique_objects(); } + + //!Returns a constant iterator to the index storing the + //!named allocations. NOT thread-safe. Never throws. + const_named_iterator named_begin() const + { return mp_header->named_begin(); } + + //!Returns a constant iterator to the end of the index + //!storing the named allocations. NOT thread-safe. Never throws. + const_named_iterator named_end() const + { return mp_header->named_end(); } + + //!Returns a constant iterator to the index storing the + //!unique allocations. NOT thread-safe. Never throws. + const_unique_iterator unique_begin() const + { return mp_header->unique_begin(); } + + //!Returns a constant iterator to the end of the index + //!storing the unique allocations. NOT thread-safe. Never throws. + const_unique_iterator unique_end() const + { return mp_header->unique_end(); } + + //!This is the default allocator to allocate types T + //!from this managed segment + template + struct allocator + { + typedef typename segment_manager::template allocator::type type; + }; + + //!Returns an instance of the default allocator for type T + //!initialized that allocates memory from this segment manager. + template + typename allocator::type + get_allocator() + { return mp_header->get_allocator(); } + + //!This is the default deleter to delete types T + //!from this managed segment. + template + struct deleter + { + typedef typename segment_manager::template deleter::type type; + }; + + //!Returns an instance of the default allocator for type T + //!initialized that allocates memory from this segment manager. + template + typename deleter::type + get_deleter() + { return mp_header->get_deleter(); } + + /// @cond + //!Tries to find a previous named allocation address. Returns a memory + //!buffer and the object count. If not found returned pointer is 0. + //!Never throws. + template + std::pair find_no_lock (char_ptr_holder_t name) + { return mp_header->template find_no_lock(name); } + /// @endcond + + protected: + //!Swaps the segment manager's managed by this managed memory segment. + //!NOT thread-safe. Never throws. + void swap(basic_managed_memory_impl &other) + { std::swap(mp_header, other.mp_header); } + + private: + segment_manager *mp_header; +}; + +template +class create_open_func +{ + public: + create_open_func(BasicManagedMemoryImpl * const frontend, detail::create_enum_t type) + : m_frontend(frontend), m_type(type){} + + bool operator()(void *addr, std::size_t size, bool created) const + { + if(((m_type == detail::DoOpen) && created) || + ((m_type == detail::DoCreate) && !created)) + return false; + + if(created) + return m_frontend->create_impl(addr, size); + else + return m_frontend->open_impl (addr, size); + } + + private: + BasicManagedMemoryImpl *m_frontend; + detail::create_enum_t m_type; +}; + +} //namespace detail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP + diff --git a/win32/include/boost/interprocess/detail/managed_multi_shared_memory.hpp b/win32/include/boost/interprocess/detail/managed_multi_shared_memory.hpp new file mode 100755 index 000000000..771cbc6f9 --- /dev/null +++ b/win32/include/boost/interprocess/detail/managed_multi_shared_memory.hpp @@ -0,0 +1,389 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2007. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP +#define BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include //list +#include //mapped_region +#include +#include //managed_open_or_create_impl +#include +#include +#include +#include + +//!\file +//!Describes a named shared memory object allocation user class. + +namespace boost { + +namespace interprocess { + +//!A basic shared memory named object creation class. Initializes the +//!shared memory segment. Inherits all basic functionality from +//!basic_managed_memory_impl +template + < + class CharType, + class MemoryAlgorithm, + template class IndexType + > +class basic_managed_multi_shared_memory + : public detail::basic_managed_memory_impl + +{ + + typedef basic_managed_multi_shared_memory + self_t; + typedef typename MemoryAlgorithm::void_pointer void_pointer; + typedef typename detail:: + managed_open_or_create_impl managed_impl; + typedef typename void_pointer::segment_group_id segment_group_id; + //////////////////////////////////////////////////////////////////////// + // + // Some internal helper structs/functors + // + //////////////////////////////////////////////////////////////////////// + //!This class defines an operator() that creates a shared memory + //!of the requested size. The rest of the parameters are + //!passed in the constructor. The class a template parameter + //!to be used with create_from_file/create_from_istream functions + //!of basic_named_object classes + +// class segment_creator +// { +// public: +// segment_creator(shared_memory &shmem, +// const char *mem_name, +// const void *addr) +// : m_shmem(shmem), m_mem_name(mem_name), m_addr(addr){} +// +// void *operator()(std::size_t size) +// { +// if(!m_shmem.create(m_mem_name, size, m_addr)) +// return 0; +// return m_shmem.get_address(); +// } +// private: +// shared_memory &m_shmem; +// const char *m_mem_name; +// const void *m_addr; +// }; + + class group_services + : public multi_segment_services + { + public: + typedef std::pair result_type; + typedef basic_managed_multi_shared_memory frontend_t; + typedef typename + basic_managed_multi_shared_memory::void_pointer void_pointer; + typedef typename void_pointer::segment_group_id segment_group_id; + group_services(frontend_t *const frontend) + : mp_frontend(frontend), m_group(0), m_min_segment_size(0){} + + virtual std::pair create_new_segment(std::size_t alloc_size) + { + //We should allocate an extra byte so that the + //[base_addr + alloc_size] byte belongs to this segment + alloc_size += 1; + + //If requested size is less than minimum, update that + alloc_size = (m_min_segment_size > alloc_size) ? + m_min_segment_size : alloc_size; + if(mp_frontend->priv_new_segment(create_open_func::DoCreate, + alloc_size, 0)){ + shmem_list_t::value_type &m_impl = *mp_frontend->m_shmem_list.rbegin(); + return result_type(m_impl.get_real_address(), m_impl.get_real_size()-1); + } + return result_type((void *)0, 0); + } + + virtual bool update_segments () + { return true; } + + virtual ~group_services(){} + + void set_group(segment_group_id group) + { m_group = group; } + + segment_group_id get_group() const + { return m_group; } + + void set_min_segment_size(std::size_t min_segment_size) + { m_min_segment_size = min_segment_size; } + + std::size_t get_min_segment_size() const + { return m_min_segment_size; } + + private: + + frontend_t * const mp_frontend; + segment_group_id m_group; + std::size_t m_min_segment_size; + }; + + //!Functor to execute atomically when opening or creating a shared memory + //!segment. + struct create_open_func + { + enum type_t { DoCreate, DoOpen, DoOpenOrCreate }; + typedef typename + basic_managed_multi_shared_memory::void_pointer void_pointer; + + create_open_func(self_t * const frontend, + type_t type, std::size_t segment_number) + : mp_frontend(frontend), m_type(type), m_segment_number(segment_number){} + + bool operator()(void *addr, std::size_t size, bool created) const + { + if(((m_type == DoOpen) && created) || + ((m_type == DoCreate) && !created)) + return false; + segment_group_id group = mp_frontend->m_group_services.get_group(); + bool mapped = false; + bool impl_done = false; + + //Associate this newly created segment as the + //segment id = 0 of this group + void_pointer::insert_mapping + ( group + , (char*)addr - managed_impl::ManagedOpenOrCreateUserOffset + , size + managed_impl::ManagedOpenOrCreateUserOffset); + //Check if this is the master segment + if(!m_segment_number){ + //Create or open the Interprocess machinery + if((impl_done = created ? + mp_frontend->create_impl(addr, size) : mp_frontend->open_impl(addr, size))){ + return true; + } + } + else{ + return true; + } + + //This is the cleanup part + //--------------- + if(impl_done){ + mp_frontend->close_impl(); + } + if(mapped){ + bool ret = void_pointer::erase_last_mapping(group); + assert(ret);(void)ret; + } + return false; + } + self_t * const mp_frontend; + type_t m_type; + std::size_t m_segment_number; + }; + + //!Functor to execute atomically when closing a shared memory segment. + struct close_func + { + typedef typename + basic_managed_multi_shared_memory::void_pointer void_pointer; + + close_func(self_t * const frontend) + : mp_frontend(frontend){} + + void operator()(const mapped_region ®ion, bool last) const + { + if(last) mp_frontend->destroy_impl(); + else mp_frontend->close_impl(); + } + self_t * const mp_frontend; + }; + + typedef detail::basic_managed_memory_impl + base_t; + + //Friend declarations + friend struct basic_managed_multi_shared_memory::create_open_func; + friend struct basic_managed_multi_shared_memory::close_func; + friend class basic_managed_multi_shared_memory::group_services; + + typedef list shmem_list_t; + + basic_managed_multi_shared_memory *get_this_pointer() + { return this; } + + public: + + basic_managed_multi_shared_memory(create_only_t, + const char *name, + std::size_t size) + : m_group_services(get_this_pointer()) + { + priv_open_or_create(create_open_func::DoCreate,name, size); + } + + basic_managed_multi_shared_memory(open_or_create_t, + const char *name, + std::size_t size) + : m_group_services(get_this_pointer()) + { + priv_open_or_create(create_open_func::DoOpenOrCreate, name, size); + } + + basic_managed_multi_shared_memory(open_only_t, const char *name) + : m_group_services(get_this_pointer()) + { + priv_open_or_create(create_open_func::DoOpen, name, 0); + } + + ~basic_managed_multi_shared_memory() + { this->priv_close(); } + + private: + bool priv_open_or_create(typename create_open_func::type_t type, + const char *name, + std::size_t size) + { + if(!m_shmem_list.empty()) + return false; + typename void_pointer::segment_group_id group = 0; + BOOST_TRY{ + m_root_name = name; + //Insert multi segment services and get a group identifier + group = void_pointer::new_segment_group(&m_group_services); + size = void_pointer::round_size(size); + m_group_services.set_group(group); + m_group_services.set_min_segment_size(size); + + if(group){ + if(this->priv_new_segment(type, size, 0)){ + return true; + } + } + } + BOOST_CATCH(const std::bad_alloc&){ + } + BOOST_CATCH_END + if(group){ + void_pointer::delete_group(group); + } + return false; + } + + bool priv_new_segment(typename create_open_func::type_t type, + std::size_t size, + const void *addr) + { + BOOST_TRY{ + //Get the number of groups of this multi_segment group + std::size_t segment_id = m_shmem_list.size(); + //Format the name of the shared memory: append segment number. + boost::interprocess::basic_ovectorstream formatter; + //Pre-reserve string size + std::size_t str_size = m_root_name.length()+10; + if(formatter.vector().size() < str_size){ + //This can throw. + formatter.reserve(str_size); + } + //Format segment's name + formatter << m_root_name + << static_cast(segment_id) << std::ends; + //This functor will be executed when constructing + create_open_func func(this, type, segment_id); + const char *name = formatter.vector().c_str(); + //This can throw. + managed_impl mshm; + + switch(type){ + case create_open_func::DoCreate: + { + managed_impl shm(create_only, name, size, read_write, addr, func); + mshm = detail::move_impl(shm); + } + break; + + case create_open_func::DoOpen: + { + managed_impl shm(open_only, name,read_write, addr, func); + mshm = detail::move_impl(shm); + } + break; + + case create_open_func::DoOpenOrCreate: + { + managed_impl shm(open_or_create, name, size, read_write, addr, func); + mshm = detail::move_impl(shm); + } + break; + + default: + return false; + break; + } + + //This can throw. + m_shmem_list.push_back(detail::move_impl(mshm)); + return true; + } + BOOST_CATCH(const std::bad_alloc&){ + } + BOOST_CATCH_END + return false; + } + + //!Frees resources. Never throws. + void priv_close() + { + if(!m_shmem_list.empty()){ + bool ret; + //Obtain group identifier + segment_group_id group = m_group_services.get_group(); + //Erase main segment and its resources + shmem_list_t::iterator itbeg = m_shmem_list.begin(), + itend = m_shmem_list.end(), + it = itbeg; + //(*itbeg)->close_with_func(close_func(this)); + //Delete group. All mappings are erased too. + ret = void_pointer::delete_group(group); + assert(ret); + m_shmem_list.clear(); + } + } + + private: + shmem_list_t m_shmem_list; + group_services m_group_services; + std::string m_root_name; +}; + +typedef basic_managed_multi_shared_memory + < char + , rbtree_best_fit > + , iset_index> + managed_multi_shared_memory; + +} //namespace interprocess { + +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP + diff --git a/win32/include/boost/interprocess/detail/managed_open_or_create_impl.hpp b/win32/include/boost/interprocess/detail/managed_open_or_create_impl.hpp new file mode 100755 index 000000000..6eaaf06a6 --- /dev/null +++ b/win32/include/boost/interprocess/detail/managed_open_or_create_impl.hpp @@ -0,0 +1,457 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL +#define BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { + +/// @cond +namespace detail{ class interprocess_tester; } +/// @endcond + +namespace detail { + +template +class managed_open_or_create_impl +{ + //Non-copyable + managed_open_or_create_impl(const managed_open_or_create_impl &); + managed_open_or_create_impl &operator=(const managed_open_or_create_impl &); + + enum + { + UninitializedSegment, + InitializingSegment, + InitializedSegment, + CorruptedSegment + }; + + public: + + static const std::size_t + ManagedOpenOrCreateUserOffset = + detail::ct_rounded_size + < sizeof(boost::uint32_t) + , detail::alignment_of::value>::value; + + managed_open_or_create_impl() + {} + + managed_open_or_create_impl(create_only_t, + const char *name, + std::size_t size, + mode_t mode = read_write, + const void *addr = 0) + { + m_name = name; + priv_open_or_create + ( detail::DoCreate + , size + , mode + , addr + , null_mapped_region_function()); + } + + managed_open_or_create_impl(open_only_t, + const char *name, + mode_t mode = read_write, + const void *addr = 0) + { + m_name = name; + priv_open_or_create + ( detail::DoOpen + , 0 + , mode + , addr + , null_mapped_region_function()); + } + + + managed_open_or_create_impl(open_or_create_t, + const char *name, + std::size_t size, + mode_t mode = read_write, + const void *addr = 0) + { + m_name = name; + priv_open_or_create + ( detail::DoOpenOrCreate + , size + , mode + , addr + , null_mapped_region_function()); + } + + template + managed_open_or_create_impl(create_only_t, + const char *name, + std::size_t size, + mode_t mode, + const void *addr, + const ConstructFunc &construct_func) + { + m_name = name; + priv_open_or_create + (detail::DoCreate + , size + , mode + , addr + , construct_func); + } + + template + managed_open_or_create_impl(open_only_t, + const char *name, + mode_t mode, + const void *addr, + const ConstructFunc &construct_func) + { + m_name = name; + priv_open_or_create + ( detail::DoOpen + , 0 + , mode + , addr + , construct_func); + } + + template + managed_open_or_create_impl(open_or_create_t, + const char *name, + std::size_t size, + mode_t mode, + const void *addr, + const ConstructFunc &construct_func) + { + m_name = name; + priv_open_or_create + ( detail::DoOpenOrCreate + , size + , mode + , addr + , construct_func); + } + + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + managed_open_or_create_impl(detail::moved_object moved) + { this->swap(moved.get()); } + #else + managed_open_or_create_impl(managed_open_or_create_impl &&moved) + { this->swap(moved); } + #endif + + //!Move assignment. If *this owns a memory mapped region, it will be + //!destroyed and it will take ownership of "other"'s memory mapped region. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + managed_open_or_create_impl &operator=(detail::moved_object moved) + { + managed_open_or_create_impl tmp(moved); + this->swap(tmp); + return *this; + } + + #else + managed_open_or_create_impl &operator=(managed_open_or_create_impl &&moved) + { + managed_open_or_create_impl tmp(detail::move_impl(moved)); + this->swap(tmp); + return *this; + } + #endif + + ~managed_open_or_create_impl() + {} + + std::size_t get_user_size() const + { return m_mapped_region.get_size() - ManagedOpenOrCreateUserOffset; } + + void *get_user_address() const + { return (char*)m_mapped_region.get_address() + ManagedOpenOrCreateUserOffset; } + + std::size_t get_real_size() const + { return m_mapped_region.get_size(); } + + void *get_real_address() const + { return (char*)m_mapped_region.get_address(); } + + void swap(managed_open_or_create_impl &other) + { + this->m_name.swap(other.m_name); + this->m_mapped_region.swap(other.m_mapped_region); + } + + const char *get_name() const + { return m_name.c_str(); } + + bool flush() + { return m_mapped_region.flush(); } + + + const mapped_region &get_mapped_region() const + { return m_mapped_region; } + + private: + + //These are templatized to allow explicit instantiations + template + static void write_whole_device(DeviceAbstraction &, std::size_t, detail::false_) + {} //Empty + + template + static void write_whole_device(DeviceAbstraction &dev, std::size_t size, detail::true_) + { + file_handle_t hnd = detail::file_handle_from_mapping_handle(dev.get_mapping_handle()); + + if(size <= ManagedOpenOrCreateUserOffset){ + throw interprocess_exception(error_info(system_error_code())); + } + + size -= ManagedOpenOrCreateUserOffset; + + if(!detail::set_file_pointer(hnd, ManagedOpenOrCreateUserOffset, file_begin)){ + throw interprocess_exception(error_info(system_error_code())); + } + + //We will write zeros in the file + for(std::size_t remaining = size, write_size = 0 + ;remaining > 0 + ;remaining -= write_size){ + const std::size_t DataSize = 512; + static char data [DataSize]; + write_size = DataSize < remaining ? DataSize : remaining; + if(!detail::write_file(hnd, data, write_size)){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + } + } + + //These are templatized to allow explicit instantiations + template + static void truncate_device(DeviceAbstraction &, std::size_t, detail::false_) + {} //Empty + + template + static void truncate_device(DeviceAbstraction &dev, std::size_t size, detail::true_) + { dev.truncate(size); } + + //These are templatized to allow explicit instantiations + template + static void create_device(DeviceAbstraction &dev, const char *name, std::size_t size, detail::false_) + { + DeviceAbstraction tmp(create_only, name, read_write, size); + tmp.swap(dev); + } + + template + static void create_device(DeviceAbstraction &dev, const char *name, std::size_t, detail::true_) + { + DeviceAbstraction tmp(create_only, name, read_write); + tmp.swap(dev); + } + + template inline + void priv_open_or_create + (detail::create_enum_t type, std::size_t size, + mode_t mode, const void *addr, + ConstructFunc construct_func) + { + typedef detail::bool_ file_like_t; + (void)mode; + error_info err; + bool created = false; + bool ronly = false; + bool cow = false; + DeviceAbstraction dev; + + if(type != detail::DoOpen && size < ManagedOpenOrCreateUserOffset){ + throw interprocess_exception(error_info(size_error)); + } + + if(type == detail::DoOpen && mode == read_write){ + DeviceAbstraction tmp(open_only, m_name.c_str(), read_write); + tmp.swap(dev); + created = false; + } + else if(type == detail::DoOpen && mode == read_only){ + DeviceAbstraction tmp(open_only, m_name.c_str(), read_only); + tmp.swap(dev); + created = false; + ronly = true; + } + else if(type == detail::DoOpen && mode == copy_on_write){ + DeviceAbstraction tmp(open_only, m_name.c_str(), read_only); + tmp.swap(dev); + created = false; + cow = true; + } + else if(type == detail::DoCreate){ + create_device(dev, m_name.c_str(), size, file_like_t()); + created = true; + } + else if(type == detail::DoOpenOrCreate){ + //This loop is very ugly, but brute force is sometimes better + //than diplomacy. If someone knows how to open or create a + //file and know if we have really created it or just open it + //drop me a e-mail! + bool completed = false; + while(!completed){ + try{ + create_device(dev, m_name.c_str(), size, file_like_t()); + created = true; + completed = true; + } + catch(interprocess_exception &ex){ + if(ex.get_error_code() != already_exists_error){ + throw; + } + else{ + try{ + DeviceAbstraction tmp(open_only, m_name.c_str(), read_write); + dev.swap(tmp); + created = false; + completed = true; + } + catch(interprocess_exception &ex){ + if(ex.get_error_code() != not_found_error){ + throw; + } + } + } + } + detail::thread_yield(); + } + } + + if(created){ + try{ + //If this throws, we are lost + truncate_device(dev, size, file_like_t()); + + //If the following throws, we will truncate the file to 1 + mapped_region region(dev, read_write, 0, 0, addr); + boost::uint32_t *patomic_word = 0; //avoid gcc warning + patomic_word = static_cast(region.get_address()); + boost::uint32_t previous = detail::atomic_cas32(patomic_word, InitializingSegment, UninitializedSegment); + + if(previous == UninitializedSegment){ + try{ + write_whole_device(dev, size, file_like_t()); + construct_func((char*)region.get_address() + ManagedOpenOrCreateUserOffset, size - ManagedOpenOrCreateUserOffset, true); + //All ok, just move resources to the external mapped region + m_mapped_region.swap(region); + } + catch(...){ + detail::atomic_write32(patomic_word, CorruptedSegment); + throw; + } + detail::atomic_write32(patomic_word, InitializedSegment); + } + else if(previous == InitializingSegment || previous == InitializedSegment){ + throw interprocess_exception(error_info(already_exists_error)); + } + else{ + throw interprocess_exception(error_info(corrupted_error)); + } + } + catch(...){ + try{ + truncate_device(dev, 1u, file_like_t()); + } + catch(...){ + } + throw; + } + } + else{ + if(FileBased){ + offset_t filesize = 0; + while(filesize == 0){ + if(!detail::get_file_size(detail::file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){ + throw interprocess_exception(error_info(system_error_code())); + } + detail::thread_yield(); + } + if(filesize == 1){ + throw interprocess_exception(error_info(corrupted_error)); + } + } + + mapped_region region(dev, ronly ? read_only : (cow ? copy_on_write : read_write), 0, 0, addr); + + boost::uint32_t *patomic_word = static_cast(region.get_address()); + boost::uint32_t value = detail::atomic_read32(patomic_word); + + while(value == InitializingSegment || value == UninitializedSegment){ + detail::thread_yield(); + value = detail::atomic_read32(patomic_word); + } + + if(value != InitializedSegment) + throw interprocess_exception(error_info(corrupted_error)); + + construct_func( (char*)region.get_address() + ManagedOpenOrCreateUserOffset + , region.get_size() - ManagedOpenOrCreateUserOffset + , false); + //All ok, just move resources to the external mapped region + m_mapped_region.swap(region); + } + } + + private: + friend class detail::interprocess_tester; + void dont_close_on_destruction() + { detail::interprocess_tester::dont_close_on_destruction(m_mapped_region); } + + mapped_region m_mapped_region; + std::string m_name; +}; + +template +inline void swap(managed_open_or_create_impl &x + ,managed_open_or_create_impl &y) +{ x.swap(y); } + +} //namespace detail { + + +///@cond + +//!Trait class to detect if a type is +//!movable +template + +struct is_movable > +{ + enum { value = true }; +}; + +///@endcond + +} //namespace interprocess { +} //namespace boost { + +#endif //#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL diff --git a/win32/include/boost/interprocess/detail/math_functions.hpp b/win32/include/boost/interprocess/detail/math_functions.hpp new file mode 100755 index 000000000..335ab4ccc --- /dev/null +++ b/win32/include/boost/interprocess/detail/math_functions.hpp @@ -0,0 +1,110 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Stephen Cleary 2000. +// (C) Copyright Ion Gaztanaga 2007-2008. +// +// 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +// This file is a slightly modified file from Boost.Pool +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP +#define BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP + +#include +#include + +namespace boost { +namespace interprocess { +namespace detail { + +// Greatest common divisor and least common multiple + +// +// gcd is an algorithm that calculates the greatest common divisor of two +// integers, using Euclid's algorithm. +// +// Pre: A > 0 && B > 0 +// Recommended: A > B +template +inline Integer gcd(Integer A, Integer B) +{ + do + { + const Integer tmp(B); + B = A % B; + A = tmp; + } while (B != 0); + + return A; +} + +// +// lcm is an algorithm that calculates the least common multiple of two +// integers. +// +// Pre: A > 0 && B > 0 +// Recommended: A > B +template +inline Integer lcm(const Integer & A, const Integer & B) +{ + Integer ret = A; + ret /= gcd(A, B); + ret *= B; + return ret; +} + +template +inline Integer log2_ceil(const Integer & A) +{ + Integer i = 0; + Integer power_of_2 = 1; + + while(power_of_2 < A){ + power_of_2 <<= 1; + ++i; + } + return i; +} + +template +inline Integer upper_power_of_2(const Integer & A) +{ + Integer power_of_2 = 1; + + while(power_of_2 < A){ + power_of_2 <<= 1; + } + return power_of_2; +} + +//This function uses binary search to discover the +//highest set bit of the integer +inline std::size_t floor_log2 (std::size_t x) +{ + const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT; + const bool Size_t_Bits_Power_2= !(Bits & (Bits-1)); + BOOST_STATIC_ASSERT(((Size_t_Bits_Power_2)== true)); + + std::size_t n = x; + std::size_t log2 = 0; + + for(std::size_t shift = Bits >> 1; shift; shift >>= 1){ + std::size_t tmp = n >> shift; + if (tmp) + log2 += shift, n = tmp; + } + + return log2; +} + +} // namespace detail +} // namespace interprocess +} // namespace boost + +#endif diff --git a/win32/include/boost/interprocess/detail/min_max.hpp b/win32/include/boost/interprocess/detail/min_max.hpp new file mode 100755 index 000000000..45c04e6a1 --- /dev/null +++ b/win32/include/boost/interprocess/detail/min_max.hpp @@ -0,0 +1,40 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. +// +// 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP +#define BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +namespace boost { +namespace interprocess { + +template +const T &max_value(const T &a, const T &b) +{ return a > b ? a : b; } + +template +const T &min_value(const T &a, const T &b) +{ return a < b ? a : b; } + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP + diff --git a/win32/include/boost/interprocess/detail/move.hpp b/win32/include/boost/interprocess/detail/move.hpp new file mode 100755 index 000000000..d89243dde --- /dev/null +++ b/win32/include/boost/interprocess/detail/move.hpp @@ -0,0 +1,163 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MOVE_HPP +#define BOOST_INTERPROCESS_MOVE_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include + +//!\file +//!Describes a function and a type to emulate move semantics. + +namespace boost { +namespace interprocess { + +//!Trait class to detect if a type is +//!movable +template +struct is_movable +{ + enum { value = false }; +}; + +} //namespace interprocess { +} //namespace boost { + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + +#include +#include + +namespace boost { +namespace interprocess { +namespace detail { + +//!An object that represents a +//!moved object. +template +struct moved_object +{ + moved_object(const T &obj) + : m_obj(const_cast(&obj)) + {} + + T &get() const + { return *m_obj; } + + private: + T *m_obj; +}; + +// Metafunction that, given movable T, provides move_source, else T&. +template +struct move_type +{ + public: // metafunction result + typedef typename if_, moved_object, T&>::type type; +}; + +template +class move_return +{ + typedef moved_object moved_type; + private: + mutable T m_moved; + + + public: + typedef T type; + + move_return(const T& returned) + : m_moved(moved_object(returned)) + {} + + move_return(const move_return& operand) + : m_moved(const_cast(operand)) + {} + + operator moved_type() const + { return moved_type(m_moved); } +}; + +template +struct return_type +{ + public: // metafunction result + + typedef typename if_, move_return, T>::type type; +}; + +} //namespace detail { +} //namespace interprocess { +} //namespace boost { + +namespace boost { +namespace interprocess { + +namespace detail{ + +//!A function that converts an object to a moved object so that +//!it can match a function taking a detail::moved_object object. +template +typename detail::move_type::type move_impl(const Object &object) +{ + typedef typename detail::move_type::type type; + return type(object); +} + +} //namespace detail { + +//!A function that converts an object to a moved object so that +//!it can match a function taking a detail::moved_object object. +template +typename detail::move_type::type move(const Object &object) +{ return detail::move_impl(object); } + +} //namespace interprocess { +} //namespace boost { + +#else //#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE + +#include + +namespace boost { +namespace interprocess { + +namespace detail { + +template +inline typename detail::remove_reference::type&& move_impl(T&& t) +{ return t; } + +template +inline T&& forward_impl(typename detail::identity::type&& t) +{ return t; } + +} //namespace detail { + +template +inline typename detail::remove_reference::type&& move(T&& t) +{ return t; } + +} //namespace interprocess { +} //namespace boost { + +#endif //#ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE + +#include + +#endif //#ifndef BOOST_INTERPROCESS_MOVE_HPP diff --git a/win32/include/boost/interprocess/detail/move_iterator.hpp b/win32/include/boost/interprocess/detail/move_iterator.hpp new file mode 100755 index 000000000..f3d732bf1 --- /dev/null +++ b/win32/include/boost/interprocess/detail/move_iterator.hpp @@ -0,0 +1,138 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MOVE_ITERATOR_HPP_INCLUDED +#define BOOST_INTERPROCESS_MOVE_ITERATOR_HPP_INCLUDED + +#include +#include + +namespace boost{ +namespace interprocess{ +namespace detail{ + +template +class move_iterator +{ + public: + typedef It iterator_type; + typedef typename std::iterator_traits::value_type value_type; + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + typedef typename move_type::type reference; + #else + typedef value_type && reference; + #endif + typedef typename std::iterator_traits::pointer pointer; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename std::iterator_traits::iterator_category iterator_category; + + move_iterator() + {} + + explicit move_iterator(It i) + : m_it(i) + {} + + template + move_iterator(const move_iterator& u) + : m_it(u.base()) + {} + + const iterator_type &base() const + { return m_it; } + + iterator_type &base() + { return m_it; } + + reference operator*() const + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + { return detail::move_impl(*m_it); } + #else + { return *m_it; } + #endif + + pointer operator->() const + { return m_it; } + + move_iterator& operator++() + { ++m_it; return *this; } + + move_iterator operator++(int) + { move_iterator tmp(*this); ++(*this); return tmp; } + + move_iterator& operator--() + { --m_it; return *this; } + + move_iterator operator--(int) + { move_iterator tmp(*this); --(*this); return tmp; } + + move_iterator operator+ (difference_type n) const + { return move_iterator(m_it + n); } + + move_iterator& operator+=(difference_type n) + { m_it += n; return *this; } + + move_iterator operator- (difference_type n) const + { return move_iterator(m_it - n); } + + move_iterator& operator-=(difference_type n) + { m_it -= n; return *this; } + + reference operator[](difference_type n) const + { return detail::move_impl(m_it[n]); } + + private: + It m_it; +}; + +template inline +bool operator==(const move_iterator& x, const move_iterator& y) +{ return x.base() == y.base(); } + +template inline +bool operator!=(const move_iterator& x, const move_iterator& y) +{ return x.base() != y.base(); } + +template inline +bool operator< (const move_iterator& x, const move_iterator& y) +{ return x.base() < y.base(); } + +template inline +bool operator<=(const move_iterator& x, const move_iterator& y) +{ return x.base() <= y.base(); } + +template inline +bool operator> (const move_iterator& x, const move_iterator& y) +{ return x.base() > y.base(); } + +template inline +bool operator>=(const move_iterator& x, const move_iterator& y) +{ return x.base() >= y.base(); } + +template inline +typename move_iterator::difference_type + operator-(const move_iterator& x, const move_iterator& y) +{ return x.base() - y.base(); } + +template inline +move_iterator + operator+(typename move_iterator::difference_type n + ,const move_iterator& x) +{ return move_iterator(x.base() + n); } + +template +move_iterator make_move_iterator(const It &it) +{ return move_iterator(it); } + +} //namespace detail{ +} //namespace interprocess{ +} //namespace boost{ + +#endif //#ifndef BOOST_INTERPROCESS_MOVE_ITERATOR_HPP_INCLUDED diff --git a/win32/include/boost/interprocess/detail/mpl.hpp b/win32/include/boost/interprocess/detail/mpl.hpp new file mode 100755 index 000000000..121c3baf3 --- /dev/null +++ b/win32/include/boost/interprocess/detail/mpl.hpp @@ -0,0 +1,148 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. +// +// 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP +#define BOOST_INTERPROCESS_DETAIL_MPL_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include + +namespace boost { +namespace interprocess { +namespace detail { + +template +struct integral_constant +{ + static const T value = val; + typedef integral_constant type; +}; + +template< bool C_ > +struct bool_ : integral_constant +{ + static const bool value = C_; +}; + +typedef bool_ true_; +typedef bool_ false_; + +typedef true_ true_type; +typedef false_ false_type; + +typedef char yes_type; +struct no_type +{ + char padding[8]; +}; + +template +struct enable_if_c { + typedef T type; +}; + +template +struct enable_if_c {}; + +template +struct enable_if : public enable_if_c {}; + +template +class is_convertible +{ + typedef char true_t; + class false_t { char dummy[2]; }; + static true_t dispatch(U); + static false_t dispatch(...); + static T trigger(); + public: + enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) }; +}; + +template< + bool C + , typename T1 + , typename T2 + > +struct if_c +{ + typedef T1 type; +}; + +template< + typename T1 + , typename T2 + > +struct if_c +{ + typedef T2 type; +}; + +template< + typename T1 + , typename T2 + , typename T3 + > +struct if_ +{ + typedef typename if_c<0 != T1::value, T2, T3>::type type; +}; + + +template +struct select1st +// : public std::unary_function +{ + const typename Pair::first_type& operator()(const Pair& x) const + { return x.first; } + + const typename Pair::first_type& operator()(const typename Pair::first_type& x) const + { return x; } +}; + +// identity is an extension: it is not part of the standard. +template +struct identity +// : public std::unary_function +{ + typedef T type; + const T& operator()(const T& x) const + { return x; } +}; + +template +struct ls_zeros +{ + static const std::size_t value = (S & std::size_t(1)) ? 0 : (1u + ls_zeros<(S >> 1u)>::value); +}; + +template<> +struct ls_zeros<0> +{ + static const std::size_t value = 0; +}; + +template<> +struct ls_zeros<1> +{ + static const std::size_t value = 0; +}; + +} //namespace detail { +} //namespace interprocess { +} //namespace boost { + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP + diff --git a/win32/include/boost/interprocess/detail/multi_segment_services.hpp b/win32/include/boost/interprocess/detail/multi_segment_services.hpp new file mode 100755 index 000000000..4f6d3f42b --- /dev/null +++ b/win32/include/boost/interprocess/detail/multi_segment_services.hpp @@ -0,0 +1,46 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP +#define BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + + +/*!\file + Describes a named shared memory allocation user class. +*/ + +namespace boost { + +namespace interprocess { + +class multi_segment_services +{ + public: + virtual std::pair create_new_segment(std::size_t mem) = 0; + virtual bool update_segments () = 0; + virtual ~multi_segment_services() = 0; +}; + +inline multi_segment_services::~multi_segment_services() +{} + + +}} //namespace boost { namespace interprocess { + +#include + +#endif //#ifdef BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP diff --git a/win32/include/boost/interprocess/detail/named_proxy.hpp b/win32/include/boost/interprocess/detail/named_proxy.hpp new file mode 100755 index 000000000..4f52801d9 --- /dev/null +++ b/win32/include/boost/interprocess/detail/named_proxy.hpp @@ -0,0 +1,279 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP +#define BOOST_INTERPROCESS_NAMED_PROXY_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a proxy class that implements named allocation syntax. + +namespace boost { +namespace interprocess { +namespace detail { + +//!Function object that makes placement new +//!without arguments +template +struct Ctor0Arg : public placement_destroy +{ + typedef Ctor0Arg self_t; + + Ctor0Arg(){} + + self_t& operator++() { return *this; } + self_t operator++(int) { return *this; } + + void construct(void *mem) + { new((void*)mem)T; } + + virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed) + { + T* memory = (T*)(mem); + for(constructed = 0; constructed < num; ++constructed) + new((void*)memory++)T; + } +}; + +#ifndef BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS +# define BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS 10 +#endif + +//////////////////////////////////////////////////////////////// +// What the macro should generate (n == 2): +// +// template +// struct Ctor2Arg +// { +// typedef detail::bool_ IsIterator; +// typedef Ctor2Arg self_t; +// +// void do_increment(detail::false_) +// { ++m_p1; ++m_p2; } +// +// void do_increment(detail::true_){} +// +// self_t& operator++() +// { +// this->do_increment(IsIterator()); +// return *this; +// } +// +// self_t operator++(int) { return ++*this; *this; } +// +// Ctor2Arg(const P1 &p1, const P2 &p2) +// : p1((P1 &)p_1), p2((P2 &)p_2) {} +// +// void construct(void *mem) +// { new((void*)object)T(m_p1, m_p2); } +// +// virtual void construct_n(void *mem +// , std::size_t num +// , std::size_t &constructed) +// { +// T* memory = (T*)(mem); +// for(constructed = 0; constructed < num; ++constructed){ +// this->construct(memory++, IsIterator()); +// this->do_increment(IsIterator()); +// } +// } +// +// private: +// void construct(void *mem, detail::true_) +// { new((void*)mem)T(*m_p1, *m_p2); } +// +// void construct(void *mem, detail::false_) +// { new((void*)mem)T(m_p1, m_p2); } +// +// P1 &m_p1; P2 &m_p2; +// }; +//////////////////////////////////////////////////////////////// + +//Note: +//We define template parameters as const references to +//be able to bind temporaries. After that we will un-const them. +//This cast is ugly but it is necessary until "perfect forwarding" +//is achieved in C++0x. Meanwhile, if we want to be able to +//bind rvalues with non-const references, we have to be ugly +#define BOOST_INTERPROCESS_AUX_PARAM_LIST(z, n, data) \ + const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \ +//! + +#define BOOST_INTERPROCESS_AUX_PARAM_INIT(z, n, data) \ + BOOST_PP_CAT(m_p, n) (const_cast(BOOST_PP_CAT(p, n))) \ +//! + +#define BOOST_INTERPROCESS_AUX_PARAM_INC(z, n, data) \ + BOOST_PP_CAT(++m_p, n) \ +//! + +#define BOOST_INTERPROCESS_AUX_PARAM_DEFINE(z, n, data) \ + BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \ +//! + +#define BOOST_PP_LOCAL_MACRO(n) \ + template \ + struct BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \ + : public placement_destroy \ + { \ + typedef detail::bool_ IsIterator; \ + typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) self_t; \ + \ + void do_increment(detail::true_) \ + { BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INC, _); } \ + \ + void do_increment(detail::false_){} \ + \ + self_t& operator++() \ + { \ + this->do_increment(IsIterator()); \ + return *this; \ + } \ + \ + self_t operator++(int) { return ++*this; *this; } \ + \ + BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \ + ( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_LIST, _) ) \ + : BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INIT, _) {} \ + \ + virtual void construct_n(void *mem \ + , std::size_t num \ + , std::size_t &constructed) \ + { \ + T* memory = (T*)(mem); \ + for(constructed = 0; constructed < num; ++constructed){ \ + this->construct(memory++, IsIterator()); \ + this->do_increment(IsIterator()); \ + } \ + } \ + \ + private: \ + void construct(void *mem, detail::true_) \ + { new((void*)mem)T(BOOST_PP_ENUM_PARAMS(n, *m_p)); } \ + \ + void construct(void *mem, detail::false_) \ + { new((void*)mem)T(BOOST_PP_ENUM_PARAMS(n, m_p)); } \ + \ + BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_AUX_PARAM_DEFINE, _) \ + }; \ +//! + + +#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS) +#include BOOST_PP_LOCAL_ITERATE() + +#undef BOOST_INTERPROCESS_AUX_PARAM_LIST +#undef BOOST_INTERPROCESS_AUX_PARAM_INIT +#undef BOOST_INTERPROCESS_AUX_PARAM_DEFINE +#undef BOOST_INTERPROCESS_AUX_PARAM_INC + +//!Describes a proxy class that implements named +//!allocation syntax. +template + < class SegmentManager //segment manager to construct the object + , class T //type of object to build + , bool is_iterator //passing parameters are normal object or iterators? + > +class named_proxy +{ + typedef typename SegmentManager::char_type char_type; + const char_type * mp_name; + SegmentManager * mp_mngr; + mutable std::size_t m_num; + const bool m_find; + const bool m_dothrow; + + public: + named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow) + : mp_name(name), mp_mngr(mngr), m_num(1) + , m_find(find), m_dothrow(dothrow) + {} + + //!makes a named allocation and calls the + //!default constructor + T *operator()() const + { + Ctor0Arg ctor_obj; + return mp_mngr->template + generic_construct(mp_name, m_num, m_find, m_dothrow, ctor_obj); + } + //! + + // Boost preprocessor used to create operator() overloads + #define BOOST_INTERPROCESS_AUX_TYPE_LIST(z, n, data) \ + BOOST_PP_CAT(P, n) \ + //! + + #define BOOST_INTERPROCESS_AUX_PARAM_LIST(z, n, data) \ + const BOOST_PP_CAT(P, n) BOOST_PP_CAT(&p, n) \ + //! + + #define BOOST_PP_LOCAL_MACRO(n) \ + template \ + T *operator()(BOOST_PP_ENUM (n, BOOST_INTERPROCESS_AUX_PARAM_LIST, _)) const \ + { \ + typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \ + \ + ctor_obj_t; \ + ctor_obj_t ctor_obj (BOOST_PP_ENUM_PARAMS(n, p)); \ + return mp_mngr->template generic_construct \ + (mp_name, m_num, m_find, m_dothrow, ctor_obj); \ + } \ + //! + + #define BOOST_PP_LOCAL_LIMITS ( 1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS ) + #include BOOST_PP_LOCAL_ITERATE() + #undef BOOST_INTERPROCESS_AUX_PARAM_LIST + #undef BOOST_INTERPROCESS_AUX_TYPE_LIST + + //////////////////////////////////////////////////////////////////////// + // What the macro should generate (n == 2) + //////////////////////////////////////////////////////////////////////// + // + // template + // T *operator()(P1 &p1, P2 &p2) const + // { + // typedef Ctor2Arg + // + // ctor_obj_t; + // ctor_obj_t ctor_obj(p1, p2); + // + // return mp_mngr->template generic_construct + // (mp_name, m_num, m_find, m_dothrow, ctor_obj); + // } + // + ////////////////////////////////////////////////////////////////////////// + + //This operator allows --> named_new("Name")[3]; <-- syntax + const named_proxy &operator[](std::size_t num) const + { m_num *= num; return *this; } +}; + +}}} //namespace boost { namespace interprocess { namespace detail { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP diff --git a/win32/include/boost/interprocess/detail/os_file_functions.hpp b/win32/include/boost/interprocess/detail/os_file_functions.hpp new file mode 100755 index 000000000..67a9c7a17 --- /dev/null +++ b/win32/include/boost/interprocess/detail/os_file_functions.hpp @@ -0,0 +1,367 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP +#define BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP + +#include +#include +//#include + +#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) +# include +#else +# ifdef BOOST_HAS_UNISTD_H +# include +# include +# include +# include +# include +# else +# error Unknown platform +# endif +#endif + +#include +#include + +namespace boost { +namespace interprocess { + +#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +typedef void * file_handle_t; +typedef long long offset_t; +typedef struct{ + void * handle; + bool is_shm; +} mapping_handle_t; + +typedef enum { read_only = winapi::generic_read + , read_write = winapi::generic_read | winapi::generic_write + , copy_on_write + , invalid_mode = 0xffff + } mode_t; + +typedef enum { file_begin = winapi::file_begin + , file_end = winapi::file_end + , file_current = winapi::file_current + } file_pos_t; + +namespace detail{ + +inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd) +{ + mapping_handle_t ret; + ret.handle = hnd; + ret.is_shm = false; + return ret; +} + +inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd) +{ return hnd.handle; } + +inline bool create_directory(const char *path) +{ return winapi::create_directory(path, 0); } + +inline const char *get_temporary_path() +{ return std::getenv("TMP"); } + +inline file_handle_t create_new_file + (const char *name, mode_t mode = read_write, bool temporary = false) +{ + unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; + return winapi::create_file + (name, (unsigned int)mode, winapi::create_new, attr); +} + +inline file_handle_t create_or_open_file + (const char *name, mode_t mode = read_write, bool temporary = false) +{ + unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; + return winapi::create_file + (name, (unsigned int)mode, winapi::open_always, attr); +} + +inline file_handle_t open_existing_file + (const char *name, mode_t mode = read_write, bool temporary = false) +{ + unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; + return winapi::create_file + (name, (unsigned int)mode, winapi::open_existing, attr); +} + +inline bool delete_file(const char *name) +{ return winapi::delete_file(name); } + +inline bool truncate_file (file_handle_t hnd, std::size_t size) +{ + if(!winapi::set_file_pointer_ex(hnd, size, 0, winapi::file_begin)){ + return false; + } + + if(!winapi::set_end_of_file(hnd)){ + return false; + } + return true; +} + +inline bool get_file_size(file_handle_t hnd, offset_t &size) +{ return winapi::get_file_size(hnd, size); } + +inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos) +{ return winapi::set_file_pointer_ex(hnd, off, 0, (unsigned long) pos); } + +inline bool get_file_pointer(file_handle_t hnd, offset_t &off) +{ return winapi::set_file_pointer_ex(hnd, 0, &off, winapi::file_current); } + +inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata) +{ + unsigned long written; + return 0 != winapi::write_file(hnd, data, (unsigned long)numdata, &written, 0); +} + +inline file_handle_t invalid_file() +{ return winapi::invalid_handle_value; } + +inline bool close_file(file_handle_t hnd) +{ return 0 != winapi::close_handle(hnd); } + +inline bool acquire_file_lock(file_handle_t hnd) +{ + static winapi::interprocess_overlapped overlapped; + const unsigned long len = 0xffffffff; +// winapi::interprocess_overlapped overlapped; +// std::memset(&overlapped, 0, sizeof(overlapped)); + return winapi::lock_file_ex + (hnd, winapi::lockfile_exclusive_lock, 0, len, len, &overlapped); +} + +inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired) +{ + const unsigned long len = 0xffffffff; + winapi::interprocess_overlapped overlapped; + std::memset(&overlapped, 0, sizeof(overlapped)); + if(!winapi::lock_file_ex + (hnd, winapi::lockfile_exclusive_lock | winapi::lockfile_fail_immediately, + 0, len, len, &overlapped)){ + return winapi::get_last_error() == winapi::error_lock_violation ? + acquired = false, true : false; + + } + return (acquired = true); +} + +inline bool release_file_lock(file_handle_t hnd) +{ + const unsigned long len = 0xffffffff; + winapi::interprocess_overlapped overlapped; + std::memset(&overlapped, 0, sizeof(overlapped)); + return winapi::unlock_file_ex(hnd, 0, len, len, &overlapped); +} + +inline bool acquire_file_lock_sharable(file_handle_t hnd) +{ + const unsigned long len = 0xffffffff; + winapi::interprocess_overlapped overlapped; + std::memset(&overlapped, 0, sizeof(overlapped)); + return winapi::lock_file_ex(hnd, 0, 0, len, len, &overlapped); +} + +inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired) +{ + const unsigned long len = 0xffffffff; + winapi::interprocess_overlapped overlapped; + std::memset(&overlapped, 0, sizeof(overlapped)); + if(!winapi::lock_file_ex + (hnd, winapi::lockfile_fail_immediately, 0, len, len, &overlapped)){ + return winapi::get_last_error() == winapi::error_lock_violation ? + acquired = false, true : false; + } + return (acquired = true); +} + + + +inline bool release_file_lock_sharable(file_handle_t hnd) +{ return release_file_lock(hnd); } + +#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +typedef int file_handle_t; +typedef off_t offset_t; +typedef file_handle_t mapping_handle_t; + +typedef enum { read_only = O_RDONLY + , read_write = O_RDWR + , copy_on_write + , invalid_mode = 0xffff + } mode_t; + +typedef enum { file_begin = SEEK_SET + , file_end = SEEK_END + , file_current = SEEK_CUR + } file_pos_t; + +namespace detail{ + +inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd) +{ return hnd; } + +inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd) +{ return hnd; } + +inline bool create_directory(const char *path) +{ return ::mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0; } + +inline const char *get_temporary_path() +{ + const char *dir = std::getenv("TMPDIR"); + if(!dir){ + dir = std::getenv("TMP"); + if(!dir){ + dir = std::getenv("TEMP"); + if(!dir){ + dir = "/tmp"; + } + } + } + return dir; +} + +inline file_handle_t create_new_file + (const char *name, mode_t mode = read_write, bool temporary = false) +{ + (void)temporary; + return ::open(name, ((int)mode) | O_EXCL | O_CREAT, S_IRWXG | S_IRWXO | S_IRWXU); +} + +inline file_handle_t create_or_open_file + (const char *name, mode_t mode = read_write, bool temporary = false) +{ + (void)temporary; + return ::open(name, ((int)mode) | O_CREAT, S_IRWXG | S_IRWXO | S_IRWXU); +} + +inline file_handle_t open_existing_file + (const char *name, mode_t mode = read_write, bool temporary = false) +{ + (void)temporary; + return ::open(name, (int)mode, S_IRWXG | S_IRWXO | S_IRWXU); +} + +inline bool delete_file(const char *name) +{ return ::unlink(name) == 0; } + +inline bool truncate_file (file_handle_t hnd, std::size_t size) +{ return 0 == ::ftruncate(hnd, size); } + +inline bool get_file_size(file_handle_t hnd, offset_t &size) +{ + struct stat data; + bool ret = 0 == ::fstat(hnd, &data); + if(ret){ + size = data.st_size; + } + return ret; +} + +inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos) +{ return off == lseek(hnd, off, (int)pos); } + +inline bool get_file_pointer(file_handle_t hnd, offset_t &off) +{ + off = lseek(hnd, 0, SEEK_CUR); + return off != ((off_t)-1); +} + +inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata) +{ return (ssize_t(numdata)) == ::write(hnd, data, numdata); } + +inline file_handle_t invalid_file() +{ return -1; } + +inline bool close_file(file_handle_t hnd) +{ return ::close(hnd) == 0; } + +inline bool acquire_file_lock(file_handle_t hnd) +{ + struct ::flock lock; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + return -1 != ::fcntl(hnd, F_SETLKW, &lock); +} + +inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired) +{ + struct ::flock lock; + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + int ret = ::fcntl(hnd, F_SETLK, &lock); + if(ret == -1){ + return (errno == EAGAIN || errno == EACCES) ? + acquired = false, true : false; + } + return (acquired = true); +} + +inline bool release_file_lock(file_handle_t hnd) +{ + struct ::flock lock; + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + return -1 != ::fcntl(hnd, F_SETLK, &lock); +} + +inline bool acquire_file_lock_sharable(file_handle_t hnd) +{ + struct ::flock lock; + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + return -1 != ::fcntl(hnd, F_SETLKW, &lock); +} + +inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired) +{ + struct flock lock; + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + int ret = ::fcntl(hnd, F_SETLK, &lock); + if(ret == -1){ + return (errno == EAGAIN || errno == EACCES) ? + acquired = false, true : false; + } + return (acquired = true); +} + + + +inline bool release_file_lock_sharable(file_handle_t hnd) +{ return release_file_lock(hnd); } + +#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +} //namespace detail{ +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP diff --git a/win32/include/boost/interprocess/detail/os_thread_functions.hpp b/win32/include/boost/interprocess/detail/os_thread_functions.hpp new file mode 100755 index 000000000..400d3732d --- /dev/null +++ b/win32/include/boost/interprocess/detail/os_thread_functions.hpp @@ -0,0 +1,84 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP +#define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP + +#include +#include + +#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) +# include +#else +# ifdef BOOST_HAS_UNISTD_H +# include +# include +# include +# else +# error Unknown platform +# endif +#endif + +namespace boost { +namespace interprocess { +namespace detail{ + +#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +typedef unsigned long OS_process_id_t; +typedef unsigned long OS_thread_id_t; + +inline OS_process_id_t get_current_process_id() +{ return winapi::get_current_process_id(); } + +inline OS_thread_id_t get_current_thread_id() +{ return winapi::get_current_thread_id(); } + +inline OS_thread_id_t get_invalid_thread_id() +{ return OS_thread_id_t(0xffffffff); } + +inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2) +{ return id1 == id2; } + +inline void thread_yield() +{ winapi::sched_yield(); } + +#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +typedef pthread_t OS_thread_id_t; +typedef int OS_process_id_t; + +inline OS_process_id_t get_current_process_id() +{ return getpid(); } + +inline pthread_t get_current_thread_id() +{ return pthread_self(); } + +inline OS_thread_id_t get_invalid_thread_id() +{ + static pthread_t invalid_id; + return invalid_id; +} + +inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2) +{ return 0 != pthread_equal(id1, id2); } + +inline void thread_yield() +{ sched_yield(); } + +#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +} //namespace detail{ +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP diff --git a/win32/include/boost/interprocess/detail/pointer_type.hpp b/win32/include/boost/interprocess/detail/pointer_type.hpp new file mode 100755 index 000000000..249680b29 --- /dev/null +++ b/win32/include/boost/interprocess/detail/pointer_type.hpp @@ -0,0 +1,74 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. +// (C) Copyright Gennaro Prota 2003 - 2004. +// +// 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP +#define BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace detail { + +struct two {char _[2];}; + +namespace pointer_type_imp { + +template static two test(...); +template static char test(typename U::pointer* = 0); + +} //namespace pointer_type_imp { + +template +struct has_pointer_type +{ + static const bool value = sizeof(pointer_type_imp::test(0)) == 1; +}; + +namespace pointer_type_imp { + +template ::value> +struct pointer_type +{ + typedef typename D::pointer type; +}; + +template +struct pointer_type +{ + typedef T* type; +}; + +} //namespace pointer_type_imp { + +template +struct pointer_type +{ + typedef typename pointer_type_imp::pointer_type::type>::type type; +}; + +} //namespace detail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP + diff --git a/win32/include/boost/interprocess/detail/posix_time_types_wrk.hpp b/win32/include/boost/interprocess/detail/posix_time_types_wrk.hpp new file mode 100755 index 000000000..3acef90fc --- /dev/null +++ b/win32/include/boost/interprocess/detail/posix_time_types_wrk.hpp @@ -0,0 +1,43 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP +#define BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP + +//workaround to avoid winsock redefines when using date-time + +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#define BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN +#endif //#ifndef WIN32_LEAN_AND_MEAN +#endif //#ifdef _WIN32 + +//#include +//#include +#include + +namespace boost { +namespace interprocess { + +typedef boost::date_time::microsec_clock microsec_clock; + +} +} + +#ifdef _WIN32 +#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN +#undef WIN32_LEAN_AND_MEAN +#undef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN +#endif //#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN +#endif //#ifdef _WIN32 + +#endif //#ifndef BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP + diff --git a/win32/include/boost/interprocess/detail/ptime_wrk.hpp b/win32/include/boost/interprocess/detail/ptime_wrk.hpp new file mode 100755 index 000000000..dbe8177f6 --- /dev/null +++ b/win32/include/boost/interprocess/detail/ptime_wrk.hpp @@ -0,0 +1,33 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_PTIME_WRK_HPP +#define BOOST_INTERPROCESS_PTIME_WRK_HPP + +//workaround to avoid winsock redefines when using date-time + +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#define BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN +#endif //#ifndef WIN32_LEAN_AND_MEAN +#endif //#ifdef _WIN32 + +#include + +#ifdef _WIN32 +#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN +#undef WIN32_LEAN_AND_MEAN +#undef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN +#endif //#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN +#endif //#ifdef _WIN32 + +#endif //#ifndef BOOST_INTERPROCESS_PTIME_WRK_HPP + diff --git a/win32/include/boost/interprocess/detail/segment_manager_helper.hpp b/win32/include/boost/interprocess/detail/segment_manager_helper.hpp new file mode 100755 index 000000000..70a31ca91 --- /dev/null +++ b/win32/include/boost/interprocess/detail/segment_manager_helper.hpp @@ -0,0 +1,477 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP +#define BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include //std::size_t +#include //char_traits +#include //std::nothrow +#include //std::pair +#ifndef BOOST_NO_EXCEPTIONS +#include +#endif + +//!\file +//!Describes the object placed in a memory segment that provides +//!named object allocation capabilities. + +namespace boost{ +namespace interprocess{ + +template +class segment_manager_base; + +//!An integer that describes the type of the +//!instance constructed in memory +enum instance_type { anonymous_type, named_type, unique_type, max_allocation_type }; + +namespace detail{ + +template +class mem_algo_deallocator +{ + void * m_ptr; + MemoryAlgorithm & m_algo; + + public: + mem_algo_deallocator(void *ptr, MemoryAlgorithm &algo) + : m_ptr(ptr), m_algo(algo) + {} + + void release() + { m_ptr = 0; } + + ~mem_algo_deallocator() + { if(m_ptr) m_algo.deallocate(m_ptr); } +}; + +/// @cond +struct block_header +{ + std::size_t m_value_bytes; + unsigned short m_num_char; + unsigned char m_value_alignment; + unsigned char m_alloc_type_sizeof_char; + + block_header(std::size_t value_bytes + ,std::size_t value_alignment + ,std::size_t allocation_type + ,std::size_t sizeof_char + ,std::size_t num_char + ) + : m_value_bytes(value_bytes) + , m_num_char(num_char) + , m_value_alignment(value_alignment) + , m_alloc_type_sizeof_char + ( ((unsigned char)allocation_type << 5u) | + ((unsigned char)sizeof_char & 0x1F) ) + {}; + + + template + block_header &operator= (const T& ) + { return *this; } + + std::size_t total_size() const + { + if(allocation_type() != anonymous_type){ + return name_offset() + (m_num_char+1)*sizeof_char(); + } + else{ + return value_offset() + m_value_bytes; + } + } + + std::size_t value_bytes() const + { return m_value_bytes; } + + template + std::size_t total_size_with_header() const + { + return get_rounded_size + ( sizeof(Header) + , detail::alignment_of::value) + + total_size(); + } + + std::size_t allocation_type() const + { return (m_alloc_type_sizeof_char >> 5u)&(unsigned char)0x7; } + + std::size_t sizeof_char() const + { return m_alloc_type_sizeof_char & (unsigned char)0x1F; } + + template + CharType *name() const + { + return reinterpret_cast + (detail::char_ptr_cast(this) + name_offset()); + } + + std::size_t name_length() const + { return m_num_char; } + + std::size_t name_offset() const + { + return value_offset() + get_rounded_size(m_value_bytes, sizeof_char()); + } + + void *value() const + { + return detail::char_ptr_cast(this) + value_offset(); + } + + std::size_t value_offset() const + { + return get_rounded_size(sizeof(block_header), m_value_alignment); + } + + template + bool less_comp(const block_header &b) const + { + return m_num_char < b.m_num_char || + (m_num_char < b.m_num_char && + std::char_traits::compare + (name(), b.name(), m_num_char) < 0); + } + + template + bool equal_comp(const block_header &b) const + { + return m_num_char == b.m_num_char && + std::char_traits::compare + (name(), b.name(), m_num_char) == 0; + } + + template + static block_header *block_header_from_value(T *value) + { return block_header_from_value(value, sizeof(T), detail::alignment_of::value); } + + static block_header *block_header_from_value(const void *value, std::size_t sz, std::size_t algn) + { + block_header * hdr = + reinterpret_cast(detail::char_ptr_cast(value) - + get_rounded_size(sizeof(block_header), algn)); + (void)sz; + //Some sanity checks + assert(hdr->m_value_alignment == algn); + assert(hdr->m_value_bytes % sz == 0); + return hdr; + } + + template + static block_header *from_first_header(Header *header) + { + block_header * hdr = + reinterpret_cast(detail::char_ptr_cast(header) + + get_rounded_size(sizeof(Header), detail::alignment_of::value)); + //Some sanity checks + return hdr; + } + + template + static Header *to_first_header(block_header *bheader) + { + Header * hdr = + reinterpret_cast(detail::char_ptr_cast(bheader) - + get_rounded_size(sizeof(Header), detail::alignment_of::value)); + //Some sanity checks + return hdr; + } +}; + +inline void array_construct(void *mem, std::size_t num, detail::in_place_interface &table) +{ + //Try constructors + std::size_t constructed = 0; + BOOST_TRY{ + table.construct_n(mem, num, constructed); + } + //If there is an exception call destructors and erase index node + BOOST_CATCH(...){ + std::size_t destroyed = 0; + table.destroy_n(mem, constructed, destroyed); + BOOST_RETHROW + } + BOOST_CATCH_END +} + +template +struct intrusive_compare_key +{ + typedef CharT char_type; + + intrusive_compare_key(const CharT *str, std::size_t len) + : mp_str(str), m_len(len) + {} + + const CharT * mp_str; + std::size_t m_len; +}; + +//!This struct indicates an anonymous object creation +//!allocation +template +class instance_t +{ + instance_t(){} +}; + +template +struct char_if_void +{ + typedef T type; +}; + +template<> +struct char_if_void +{ + typedef char type; +}; + +typedef instance_t anonymous_instance_t; +typedef instance_t unique_instance_t; + +template +struct intrusive_value_type_impl + : public Hook +{ + private: + //Non-copyable + intrusive_value_type_impl(const intrusive_value_type_impl &); + intrusive_value_type_impl& operator=(const intrusive_value_type_impl &); + + public: + typedef CharType char_type; + + intrusive_value_type_impl(){} + + enum { BlockHdrAlignment = detail::alignment_of::value }; + + block_header *get_block_header() const + { + return (block_header *)(detail::char_ptr_cast(this) + + get_rounded_size(sizeof(*this), BlockHdrAlignment)); + } + + bool operator <(const intrusive_value_type_impl & other) const + { return (this->get_block_header())->template less_comp(*other.get_block_header()); } + + bool operator ==(const intrusive_value_type_impl & other) const + { return (this->get_block_header())->template equal_comp(*other.get_block_header()); } + + static intrusive_value_type_impl *get_intrusive_value_type(block_header *hdr) + { + return (intrusive_value_type_impl *)(detail::char_ptr_cast(hdr) - + get_rounded_size(sizeof(intrusive_value_type_impl), BlockHdrAlignment)); + } + + CharType *name() const + { return get_block_header()->template name(); } + + std::size_t name_length() const + { return get_block_header()->name_length(); } + + void *value() const + { return get_block_header()->value(); } +}; + +template +class char_ptr_holder +{ + public: + char_ptr_holder(const CharType *name) + : m_name(name) + {} + + char_ptr_holder(const detail::anonymous_instance_t *) + : m_name((CharType*)0) + {} + + char_ptr_holder(const detail::unique_instance_t *) + : m_name((CharType*)-1) + {} + + operator const CharType *() + { return m_name; } + + private: + const CharType *m_name; +}; + +//!The key of the the named allocation information index. Stores an offset pointer +//!to a null terminated string and the length of the string to speed up sorting +template +struct index_key +{ + typedef typename detail:: + pointer_to_other::type const_char_ptr_t; + typedef CharT char_type; + + private: + //Offset pointer to the object's name + const_char_ptr_t mp_str; + //Length of the name buffer (null NOT included) + std::size_t m_len; + public: + + //!Constructor of the key + index_key (const char_type *name, std::size_t length) + : mp_str(name), m_len(length) {} + + //!Less than function for index ordering + bool operator < (const index_key & right) const + { + return (m_len < right.m_len) || + (m_len == right.m_len && + std::char_traits::compare + (detail::get_pointer(mp_str) + ,detail::get_pointer(right.mp_str), m_len) < 0); + } + + //!Equal to function for index ordering + bool operator == (const index_key & right) const + { + return m_len == right.m_len && + std::char_traits::compare + (detail::get_pointer(mp_str), + detail::get_pointer(right.mp_str), m_len) == 0; + } + + void name(const CharT *name) + { mp_str = name; } + + void name_length(std::size_t len) + { m_len = len; } + + const CharT *name() const + { return detail::get_pointer(mp_str); } + + std::size_t name_length() const + { return m_len; } +}; + +//!The index_data stores a pointer to a buffer and the element count needed +//!to know how many destructors must be called when calling destroy +template +struct index_data +{ + typedef VoidPointer void_pointer; + void_pointer m_ptr; + index_data(void *ptr) : m_ptr(ptr){} + + void *value() const + { return (void*)detail::get_pointer(m_ptr); } +}; + +template +struct segment_manager_base_type +{ typedef segment_manager_base type; }; + +template +struct index_config +{ + typedef typename MemoryAlgorithm::void_pointer void_pointer; + typedef CharT char_type; + typedef detail::index_key key_type; + typedef detail::index_data mapped_type; + typedef typename segment_manager_base_type + ::type segment_manager_base; + + template + struct intrusive_value_type + { typedef detail::intrusive_value_type_impl type; }; + + typedef intrusive_compare_key intrusive_compare_key_type; +}; + +template +class segment_manager_iterator_value_adaptor +{ + typedef typename Iterator::value_type iterator_val_t; + typedef typename iterator_val_t::char_type char_type; + + public: + segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val) + : m_val(&val) + {} + + const char_type *name() const + { return m_val->name(); } + + std::size_t name_length() const + { return m_val->name_length(); } + + const void *value() const + { return m_val->value(); } + + const typename Iterator::value_type *m_val; +}; + + +template +class segment_manager_iterator_value_adaptor +{ + typedef typename Iterator::value_type iterator_val_t; + typedef typename iterator_val_t::first_type first_type; + typedef typename iterator_val_t::second_type second_type; + typedef typename first_type::char_type char_type; + + public: + segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val) + : m_val(&val) + {} + + const char_type *name() const + { return m_val->first.name(); } + + std::size_t name_length() const + { return m_val->first.name_length(); } + + const void *value() const + { + return reinterpret_cast + (detail::get_pointer(m_val->second.m_ptr))->value(); + } + + const typename Iterator::value_type *m_val; +}; + +template +struct segment_manager_iterator_transform + : std::unary_function< typename Iterator::value_type + , segment_manager_iterator_value_adaptor > +{ + typedef segment_manager_iterator_value_adaptor result_type; + + result_type operator()(const typename Iterator::value_type &arg) const + { return result_type(arg); } +}; + +} //namespace detail { + +}} //namespace boost { namespace interprocess + +#include + +#endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP + diff --git a/win32/include/boost/interprocess/detail/tmp_dir_helpers.hpp b/win32/include/boost/interprocess/detail/tmp_dir_helpers.hpp new file mode 100755 index 000000000..8663ab291 --- /dev/null +++ b/win32/include/boost/interprocess/detail/tmp_dir_helpers.hpp @@ -0,0 +1,78 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP +#define BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace detail { + +inline void tmp_filename(const char *filename, std::string &tmp_name) +{ + const char *tmp_dir = get_temporary_path(); + if(!tmp_dir){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + tmp_name = tmp_dir; + + //Remove final null. + tmp_name += "/boost_interprocess/"; + tmp_name += filename; +} + +inline void create_tmp_dir_and_get_filename(const char *filename, std::string &tmp_name) +{ + const char *tmp_path = get_temporary_path(); + if(!tmp_path){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + + tmp_name = tmp_path; + tmp_name += "/boost_interprocess"; + + //Create the temporary directory. + //If fails, check that it's because already exists + if(!create_directory(tmp_name.c_str())){ + error_info info(system_error_code()); + if(info.get_error_code() != already_exists_error){ + throw interprocess_exception(info); + } + } + + //Add filename + tmp_name += '/'; + tmp_name += filename; +} + +inline void add_leading_slash(const char *name, std::string &new_name) +{ + if(name[0] != '/'){ + new_name = '/'; + } + new_name += name; +} + +} //namespace boost { +} //namespace interprocess { +} //namespace detail { + +#include + +#endif //ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP diff --git a/win32/include/boost/interprocess/detail/type_traits.hpp b/win32/include/boost/interprocess/detail/type_traits.hpp new file mode 100755 index 000000000..b10705114 --- /dev/null +++ b/win32/include/boost/interprocess/detail/type_traits.hpp @@ -0,0 +1,189 @@ +////////////////////////////////////////////////////////////////////////////// +// (C) Copyright John Maddock 2000. +// (C) Copyright Ion Gaztanaga 2005-2008. +// +// 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +// The alignment_of implementation comes from John Maddock's boost::alignment_of code +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP +#define BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include + +namespace boost { +namespace interprocess { +namespace detail { + +struct nat{}; + +//boost::alignment_of yields to 10K lines of preprocessed code, so we +//need an alternative +template struct alignment_of; + +template +struct alignment_of_hack +{ + char c; + T t; + alignment_of_hack(); +}; + +template +struct alignment_logic +{ + enum{ value = A < S ? A : S }; +}; + +template< typename T > +struct alignment_of +{ + enum{ value = alignment_logic + < sizeof(alignment_of_hack) - sizeof(T) + , sizeof(T)>::value }; +}; + +//This is not standard, but should work with all compilers +union max_align +{ + char char_; + short short_; + int int_; + long long_; + #ifdef BOOST_HAS_LONG_LONG + long long long_long_; + #endif + float float_; + double double_; + long double long_double_; + void * void_ptr_; +}; + +template +struct remove_reference +{ + typedef T type; +}; + +template +struct remove_reference +{ + typedef T type; +}; + +template +struct is_reference +{ + enum { value = false }; +}; + +template +struct is_reference +{ + enum { value = true }; +}; + +template +struct is_pointer +{ + enum { value = false }; +}; + +template +struct is_pointer +{ + enum { value = true }; +}; + +template +struct add_reference +{ + typedef T& type; +}; + +template +struct add_reference +{ + typedef T& type; +}; + +template<> +struct add_reference +{ + typedef nat& type; +}; + +template<> +struct add_reference +{ + typedef const nat& type; +}; +template +struct is_same +{ + typedef char yes_type; + struct no_type + { + char padding[8]; + }; + + template + static yes_type is_same_tester(V*, V*); + static no_type is_same_tester(...); + + static T *t; + static U *u; + + static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u)); +}; +/* +template typename T, template typename U> +struct is_same +{ + typedef char yes_type; + struct no_type + { + char padding[8]; + }; + + template typename V> + static yes_type is_same_tester(V*, V*); + static no_type is_same_tester(...); + + static T *t; + static U *u; + + static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u)); +};*/ +/* +template< typename T > +struct is_pointer_impl +{ + static const bool value = + (::boost::type_traits::ice_and< + ::boost::detail::is_pointer_helper::type>::value + , ::boost::type_traits::ice_not< + ::boost::is_member_pointer::value + >::value + >::value) + ); +};*/ + +} // namespace detail +} //namespace interprocess { +} //namespace boost { + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP + +#include + diff --git a/win32/include/boost/interprocess/detail/utilities.hpp b/win32/include/boost/interprocess/detail/utilities.hpp new file mode 100755 index 000000000..1e86226e2 --- /dev/null +++ b/win32/include/boost/interprocess/detail/utilities.hpp @@ -0,0 +1,824 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. +// (C) Copyright Gennaro Prota 2003 - 2004. +// +// 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP +#define BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace detail { + +template +struct smart_ptr_type +{ + typedef typename SmartPtr::value_type value_type; + typedef value_type *pointer; + static pointer get (const SmartPtr &smartptr) + { return smartptr.get();} +}; + +template +struct smart_ptr_type +{ + typedef T value_type; + typedef value_type *pointer; + static pointer get (pointer ptr) + { return ptr;} +}; + +//!Overload for smart pointers to avoid ADL problems with get_pointer +template +inline typename smart_ptr_type::pointer +get_pointer(const Ptr &ptr) +{ return smart_ptr_type::get(ptr); } + +//!To avoid ADL problems with swap +template +inline void do_swap(T& x, T& y) +{ + using std::swap; + swap(x, y); +} + +//!A deleter for scoped_ptr that deallocates the memory +//!allocated for an object using a STL allocator. +template +struct scoped_ptr_dealloc_functor +{ + typedef typename Allocator::pointer pointer; + typedef detail::integral_constant::value> alloc_version; + typedef detail::integral_constant allocator_v1; + typedef detail::integral_constant allocator_v2; + + private: + void priv_deallocate(const typename Allocator::pointer &p, allocator_v1) + { m_alloc.deallocate(p, 1); } + + void priv_deallocate(const typename Allocator::pointer &p, allocator_v2) + { m_alloc.deallocate_one(p); } + + public: + Allocator& m_alloc; + + scoped_ptr_dealloc_functor(Allocator& a) + : m_alloc(a) {} + + void operator()(pointer ptr) + { if (ptr) priv_deallocate(ptr, alloc_version()); } +}; + +//!A deleter for scoped_ptr that deallocates the memory +//!allocated for an object using a STL allocator. +template +struct scoped_deallocator +{ + typedef typename Allocator::pointer pointer; + typedef detail::integral_constant::value> alloc_version; + typedef detail::integral_constant allocator_v1; + typedef detail::integral_constant allocator_v2; + + private: + void priv_deallocate(allocator_v1) + { m_alloc.deallocate(m_ptr, 1); } + + void priv_deallocate(allocator_v2) + { m_alloc.deallocate_one(m_ptr); } + + public: + pointer m_ptr; + Allocator& m_alloc; + + scoped_deallocator(pointer p, Allocator& a) + : m_ptr(p), m_alloc(a) {} + + ~scoped_deallocator() + { if (m_ptr)priv_deallocate(alloc_version()); } + + void release() + { m_ptr = 0; } +}; + +//!A deleter for scoped_ptr that deallocates the memory +//!allocated for an array of objects using a STL allocator. +template +struct scoped_array_deallocator +{ + typedef typename Allocator::pointer pointer; + typedef typename Allocator::size_type size_type; + + scoped_array_deallocator(pointer p, Allocator& a, size_type length) + : m_ptr(p), m_alloc(a), m_length(length) {} + + ~scoped_array_deallocator() + { if (m_ptr) m_alloc.deallocate(m_ptr, m_length); } + + void release() + { m_ptr = 0; } + + private: + pointer m_ptr; + Allocator& m_alloc; + size_type m_length; +}; + +template +struct null_scoped_array_deallocator +{ + typedef typename Allocator::pointer pointer; + typedef typename Allocator::size_type size_type; + + null_scoped_array_deallocator(pointer, Allocator&, size_type) + {} + + void release() + {} +}; + +//!A deleter for scoped_ptr that destroys +//!an object using a STL allocator. +template +struct scoped_destructor_n +{ + typedef typename Allocator::pointer pointer; + typedef typename Allocator::value_type value_type; + typedef typename Allocator::size_type size_type; + + pointer m_p; + size_type m_n; + + scoped_destructor_n(pointer p, size_type n) + : m_p(p), m_n(n) + {} + + void release() + { m_p = 0; } + + void increment_size(size_type inc) + { m_n += inc; } + + ~scoped_destructor_n() + { + if(!m_p) return; + value_type *raw_ptr = detail::get_pointer(m_p); + for(std::size_t i = 0; i < m_n; ++i, ++raw_ptr) + raw_ptr->~value_type(); + } +}; + +//!A deleter for scoped_ptr that destroys +//!an object using a STL allocator. +template +struct null_scoped_destructor_n +{ + typedef typename Allocator::pointer pointer; + typedef typename Allocator::size_type size_type; + + null_scoped_destructor_n(pointer, size_type) + {} + + void increment_size(size_type) + {} + + void release() + {} +}; + +template +class allocator_destroyer +{ + typedef typename A::value_type value_type; + typedef detail::integral_constant::value> alloc_version; + typedef detail::integral_constant allocator_v1; + typedef detail::integral_constant allocator_v2; + + private: + A & a_; + + private: + void priv_deallocate(const typename A::pointer &p, allocator_v1) + { a_.deallocate(p, 1); } + + void priv_deallocate(const typename A::pointer &p, allocator_v2) + { a_.deallocate_one(p); } + + public: + allocator_destroyer(A &a) + : a_(a) + {} + + void operator()(const typename A::pointer &p) + { + detail::get_pointer(p)->~value_type(); + priv_deallocate(p, alloc_version()); + } +}; + +template +class allocator_destroyer_and_chain_builder +{ + typedef typename A::value_type value_type; + typedef typename A::multiallocation_iterator multiallocation_iterator; + typedef typename A::multiallocation_chain multiallocation_chain; + + A & a_; + multiallocation_chain &c_; + + public: + allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c) + : a_(a), c_(c) + {} + + void operator()(const typename A::pointer &p) + { + value_type *vp = detail::get_pointer(p); + vp->~value_type(); + c_.push_back(vp); + } +}; + +template +class allocator_multialloc_chain_node_deallocator +{ + typedef typename A::value_type value_type; + typedef typename A::multiallocation_iterator multiallocation_iterator; + typedef typename A::multiallocation_chain multiallocation_chain; + typedef allocator_destroyer_and_chain_builder chain_builder; + + A & a_; + multiallocation_chain c_; + + public: + allocator_multialloc_chain_node_deallocator(A &a) + : a_(a), c_() + {} + + chain_builder get_chain_builder() + { return chain_builder(a_, c_); } + + ~allocator_multialloc_chain_node_deallocator() + { + multiallocation_iterator it(c_.get_it()); + if(it != multiallocation_iterator()) + a_.deallocate_individual(it); + } +}; + +template +class allocator_multialloc_chain_array_deallocator +{ + typedef typename A::value_type value_type; + typedef typename A::multiallocation_iterator multiallocation_iterator; + typedef typename A::multiallocation_chain multiallocation_chain; + typedef allocator_destroyer_and_chain_builder chain_builder; + + A & a_; + multiallocation_chain c_; + + public: + allocator_multialloc_chain_array_deallocator(A &a) + : a_(a), c_() + {} + + chain_builder get_chain_builder() + { return chain_builder(a_, c_); } + + ~allocator_multialloc_chain_array_deallocator() + { + multiallocation_iterator it(c_.get_it()); + if(it != multiallocation_iterator()) + a_.deallocate_many(it); + } +}; + +//!A class used for exception-safe multi-allocation + construction. +template +struct multiallocation_destroy_dealloc +{ + typedef typename Allocator::multiallocation_iterator multiallocation_iterator; + typedef typename Allocator::value_type value_type; + + multiallocation_iterator m_itbeg; + Allocator& m_alloc; + + multiallocation_destroy_dealloc(multiallocation_iterator itbeg, Allocator& a) + : m_itbeg(itbeg), m_alloc(a) {} + + ~multiallocation_destroy_dealloc() + { + multiallocation_iterator endit; + while(m_itbeg != endit){ + detail::get_pointer(&*m_itbeg)->~value_type(); + m_alloc.deallocate(&*m_itbeg, 1); + ++m_itbeg; + } + } + + void next() + { ++m_itbeg; } + + void release() + { m_itbeg = multiallocation_iterator(); } +}; + +//!Forces a cast from any pointer to char *pointer +template +inline char* char_ptr_cast(T *ptr) +{ + //This is nasty, but we like it a lot! + return (char*)(ptr); +} + +inline char* char_ptr_cast() +{ + //This is nasty, but we like it a lot! + return (char*)(0); +} + +//Rounds "orig_size" by excess to round_to bytes +inline std::size_t get_rounded_size(std::size_t orig_size, std::size_t round_to) +{ + return ((orig_size-1)/round_to+1)*round_to; +} + +//Truncates "orig_size" to a multiple of "multiple" bytes. +inline std::size_t get_truncated_size(std::size_t orig_size, std::size_t multiple) +{ + return orig_size/multiple*multiple; +} + +//Rounds "orig_size" by excess to round_to bytes. round_to must be power of two +inline std::size_t get_rounded_size_po2(std::size_t orig_size, std::size_t round_to) +{ + return ((orig_size-1)&(~(round_to-1))) + round_to; +} + +//Truncates "orig_size" to a multiple of "multiple" bytes. multiple must be power of two +inline std::size_t get_truncated_size_po2(std::size_t orig_size, std::size_t multiple) +{ + return (orig_size & (~(multiple-1))); +} + +template +struct ct_rounded_size +{ + enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo }; +}; + +template +struct ct_min +{ + enum { value = (Value1 < Value2)? Value1 : Value2 }; +}; + +template +struct ct_max +{ + enum { value = (Value1 > Value2)? Value1 : Value2 }; +}; + +// Gennaro Prota wrote this. Thanks! +template +struct ct_max_pow2_less +{ + enum { c = 2*n < p }; + + static const std::size_t value = + c ? (ct_max_pow2_less< c*p, 2*c*n>::value) : n; +}; + +template <> +struct ct_max_pow2_less<0, 0> +{ + static const std::size_t value = 0; +}; + +//!Obtains a generic pointer of the same type that +//!can point to other pointed type: Ptr -> Ptr +template +struct pointer_to_other; + +template class Sp> +struct pointer_to_other< Sp, U > +{ + typedef Sp type; +}; + +template class Sp> +struct pointer_to_other< Sp, U > +{ + typedef Sp type; +}; + +template class Sp> +struct pointer_to_other< Sp, U > +{ + typedef Sp type; +}; + +template +struct pointer_to_other< T*, U > +{ + typedef U* type; +}; + +} //namespace detail { + +//!Trait class to detect if an index is a node +//!index. This allows more efficient operations +//!when deallocating named objects. +template +struct is_node_index +{ + enum { value = false }; +}; + + +//!Trait class to detect if an index is an intrusive +//!index. This will embed the derivation hook in each +//!allocation header, to provide memory for the intrusive +//!container. +template +struct is_intrusive_index +{ + enum { value = false }; +}; + +template +SizeType + get_next_capacity(const SizeType max_size + ,const SizeType capacity + ,const SizeType n) +{ +// if (n > max_size - capacity) +// throw std::length_error("get_next_capacity"); + + const SizeType m3 = max_size/3; + + if (capacity < m3) + return capacity + max_value(3*(capacity+1)/5, n); + + if (capacity < m3*2) + return capacity + max_value((capacity+1)/2, n); + + return max_size; +} + +namespace detail { + +template +struct pair +{ + typedef T1 first_type; + typedef T2 second_type; + + T1 first; + T2 second; + + pair() + : first(), second() + {} + + pair(const T1& x, const T2& y) + : first(x), second(y) + {} + + template + pair(const std::pair& p) + : first(p.first), second(p.second) + {} + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + pair(const detail::moved_object >& p) + : first(detail::move_impl(p.get().first)), second(detail::move_impl(p.get().second)) + {} + #else + template + pair(std::pair && p) + : first(detail::move_impl(p.first)), second(detail::move_impl(p.second)) + {} + #endif + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + pair(const detail::moved_object >& p) + : first(detail::move_impl(p.get().first)), second(detail::move_impl(p.get().second)) + {} + #else + template + pair(pair && p) + : first(detail::move_impl(p.first)), second(detail::move_impl(p.second)) + {} + #endif + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + pair(const detail::moved_object &x, const detail::moved_object &y) + : first(detail::move_impl(x.get())), second(detail::move_impl(y.get())) + {} + #else + template + pair(U &&x, V &&y) + : first(detail::move_impl(x)), second(detail::move_impl(y)) + {} + #endif + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + pair(const detail::moved_object &p) + : first(detail::move_impl(p.get().first)), second(detail::move_impl(p.get().second)) + {} + #else + pair(pair &&p) + : first(detail::move_impl(p.first)), second(detail::move_impl(p.second)) + {} + #endif + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + pair& operator=(const detail::moved_object &p) + { + first = detail::move_impl(p.get().first); + second = detail::move_impl(p.get().second); + return *this; + } + #else + pair& operator=(pair &&p) + { + first = detail::move_impl(p.first); + second = detail::move_impl(p.second); + return *this; + } + #endif + + pair& operator=(const pair &p) + { + first = p.first; + second = p.second; + return *this; + } + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + pair& operator=(const detail::moved_object > &p) + { + first = detail::move_impl(p.get().first); + second = detail::move_impl(p.get().second); + return *this; + } + #else + template + pair& operator=(std::pair &&p) + { + first = detail::move_impl(p.first); + second = detail::move_impl(p.second); + return *this; + } + #endif + + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(const detail::moved_object &p) + { std::swap(*this, p.get()); } + + void swap(pair& p) + { std::swap(*this, p); } + + #else + void swap(pair &&p) + { std::swap(*this, p); } + #endif +}; + +template +inline bool operator==(const pair& x, const pair& y) +{ return static_cast(x.first == y.first && x.second == y.second); } + +template +inline bool operator< (const pair& x, const pair& y) +{ return static_cast(x.first < y.first || + (!(y.first < x.first) && x.second < y.second)); } + +template +inline bool operator!=(const pair& x, const pair& y) +{ return static_cast(!(x == y)); } + +template +inline bool operator> (const pair& x, const pair& y) +{ return y < x; } + +template +inline bool operator>=(const pair& x, const pair& y) +{ return static_cast(!(x < y)); } + +template +inline bool operator<=(const pair& x, const pair& y) +{ return static_cast(!(y < x)); } + +template +inline pair make_pair(T1 x, T2 y) +{ return pair(x, y); } + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +template +inline void swap(const detail::moved_object > &x, pair& y) +{ + swap(x.get().first, y.first); + swap(x.get().second, y.second); +} + +template +inline void swap(pair& x, const detail::moved_object > &y) +{ + swap(x.first, y.get().first); + swap(x.second, y.get().second); +} + +template +inline void swap(pair& x, pair& y) +{ + swap(x.first, y.first); + swap(x.second, y.second); +} + +#else +template +inline void swap(pair&&x, pair&&y) +{ + swap(x.first, y.first); + swap(x.second, y.second); +} +#endif + +template +struct cast_functor +{ + typedef typename detail::add_reference::type result_type; + result_type operator()(char &ptr) const + { return *static_cast(static_cast(&ptr)); } +}; + +template +class multiallocation_chain_adaptor +{ + private: + MultiallocChain chain_; + + multiallocation_chain_adaptor + (const multiallocation_chain_adaptor &); + multiallocation_chain_adaptor &operator= + (const multiallocation_chain_adaptor &); + + public: + typedef transform_iterator + < typename MultiallocChain:: + multiallocation_iterator + , detail::cast_functor > multiallocation_iterator; + + multiallocation_chain_adaptor() + : chain_() + {} + + void push_back(T *mem) + { chain_.push_back(mem); } + + void push_front(T *mem) + { chain_.push_front(mem); } + + void swap(multiallocation_chain_adaptor &other_chain) + { chain_.swap(other_chain.chain_); } + + void splice_back(multiallocation_chain_adaptor &other_chain) + { chain_.splice_back(other_chain.chain_); } + + T *pop_front() + { return static_cast(chain_.pop_front()); } + + bool empty() const + { return chain_.empty(); } + + multiallocation_iterator get_it() const + { return multiallocation_iterator(chain_.get_it()); } + + std::size_t size() const + { return chain_.size(); } +}; + +} //namespace detail { + +//!The pair is movable if any of its members is movable +template +struct is_movable > +{ + enum { value = is_movable::value || is_movable::value }; +}; + +//!The pair is movable if any of its members is movable +template +struct is_movable > +{ + enum { value = is_movable::value || is_movable::value }; +}; + +///has_trivial_destructor_after_move<> == true_type +///specialization for optimizations +template +struct has_trivial_destructor_after_move + : public boost::has_trivial_destructor +{}; + +template T* +addressof(T& v) +{ + return reinterpret_cast( + &const_cast(reinterpret_cast(v))); +} + +//Anti-exception node eraser +template +class value_eraser +{ + public: + value_eraser(Cont & cont, typename Cont::iterator it) + : m_cont(cont), m_index_it(it), m_erase(true){} + ~value_eraser() + { if(m_erase) m_cont.erase(m_index_it); } + + void release() { m_erase = false; } + + private: + Cont &m_cont; + typename Cont::iterator m_index_it; + bool m_erase; +}; + +template +struct sizeof_value +{ + static const std::size_t value = sizeof(T); +}; + +template <> +struct sizeof_value +{ + static const std::size_t value = sizeof(void*); +}; + +template <> +struct sizeof_value +{ + static const std::size_t value = sizeof(void*); +}; + +template <> +struct sizeof_value +{ + static const std::size_t value = sizeof(void*); +}; + +template <> +struct sizeof_value +{ + static const std::size_t value = sizeof(void*); +}; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP + diff --git a/win32/include/boost/interprocess/detail/version_type.hpp b/win32/include/boost/interprocess/detail/version_type.hpp new file mode 100755 index 000000000..bab67315b --- /dev/null +++ b/win32/include/boost/interprocess/detail/version_type.hpp @@ -0,0 +1,89 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This code comes from N1953 document by Howard E. Hinnant +// +////////////////////////////////////////////////////////////////////////////// + + +#ifndef BOOST_INTERPROCESS_DETAIL_VERSION_TYPE_HPP +#define BOOST_INTERPROCESS_DETAIL_VERSION_TYPE_HPP + +#include +#include + + +namespace boost{ +namespace interprocess{ +namespace detail{ + +//using namespace boost; + +template +struct version_type + : public detail::integral_constant +{ + typedef T type; + + version_type(const version_type&); +}; + +namespace impl{ + +template , typename T::version>::value> +struct extract_version +{ + static const unsigned value = 1; +}; + +template +struct extract_version +{ + static const unsigned value = T::version::value; +}; + +template +struct has_version +{ + private: + struct two {char _[2];}; + template static two test(...); + template static char test(const typename U::version*); + public: + static const bool value = sizeof(test(0)) == 1; + void dummy(){} +}; + +template ::value> +struct version +{ + static const unsigned value = 1; +}; + +template +struct version +{ + static const unsigned value = extract_version::value; +}; + +} //namespace impl + +template +struct version + : public detail::integral_constant::value> +{ +}; + +} //namespace detail{ +} //namespace interprocess{ +} //namespace boost{ + +#endif //#define BOOST_INTERPROCESS_DETAIL_VERSION_TYPE_HPP diff --git a/win32/include/boost/interprocess/detail/win32_api.hpp b/win32/include/boost/interprocess/detail/win32_api.hpp new file mode 100755 index 000000000..3ee2dc3ef --- /dev/null +++ b/win32/include/boost/interprocess/detail/win32_api.hpp @@ -0,0 +1,414 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_WIN32_SYNC_PRIMITIVES_HPP +#define BOOST_INTERPROCESS_WIN32_SYNC_PRIMITIVES_HPP + +#include +#include +#include + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +# pragma comment( lib, "advapi32.lib" ) +#endif + +#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) +# include +# include +#else +# error "This file can only be included in Windows OS" +#endif + +//The structures used in Interprocess with the +//same binary interface as windows ones +namespace boost { +namespace interprocess { +namespace winapi { + +//Some used constants +static const unsigned long infinite_time = 0xFFFFFFFF; +static const unsigned long error_already_exists = 183L; +static const unsigned long error_file_not_found = 2u; + +static const unsigned long semaphore_all_access = (0x000F0000L)|(0x00100000L)|0x3; +static const unsigned long mutex_all_access = (0x000F0000L)|(0x00100000L)|0x0001; + +static const unsigned long page_readonly = 0x02; +static const unsigned long page_readwrite = 0x04; +static const unsigned long page_writecopy = 0x08; + +static const unsigned long standard_rights_required = 0x000F0000L; +static const unsigned long section_query = 0x0001; +static const unsigned long section_map_write = 0x0002; +static const unsigned long section_map_read = 0x0004; +static const unsigned long section_map_execute = 0x0008; +static const unsigned long section_extend_size = 0x0010; +static const unsigned long section_all_access = standard_rights_required | + section_query | + section_map_write | + section_map_read | + section_map_execute | + section_extend_size; + +static const unsigned long file_map_copy = section_query; +static const unsigned long file_map_write = section_map_write; +static const unsigned long file_map_read = section_map_read; +static const unsigned long file_map_all_access = section_all_access; + +static const unsigned long file_share_read = 0x00000001; +static const unsigned long file_share_write = 0x00000002; + +static const unsigned long generic_read = 0x80000000L; +static const unsigned long generic_write = 0x40000000L; + +static const unsigned long wait_object_0 = 0; +static const unsigned long wait_abandoned = 0x00000080L; +static const unsigned long wait_timeout = 258L; +static const unsigned long wait_failed = (unsigned long)0xFFFFFFFF; + +static const unsigned long duplicate_close_source = (unsigned long)0x00000001; +static const unsigned long duplicate_same_access = (unsigned long)0x00000002; + +static const unsigned long format_message_allocate_buffer + = (unsigned long)0x00000100; +static const unsigned long format_message_ignore_inserts + = (unsigned long)0x00000200; +static const unsigned long format_message_from_string + = (unsigned long)0x00000400; +static const unsigned long format_message_from_hmodule + = (unsigned long)0x00000800; +static const unsigned long format_message_from_system + = (unsigned long)0x00001000; +static const unsigned long format_message_argument_array + = (unsigned long)0x00002000; +static const unsigned long format_message_max_width_mask + = (unsigned long)0x000000FF; +static const unsigned long lang_neutral = (unsigned long)0x00; +static const unsigned long sublang_default = (unsigned long)0x01; +static const unsigned long invalid_file_size = (unsigned long)0xFFFFFFFF; +static void * const invalid_handle_value = (void*)(long*)-1; +static const unsigned long create_new = 1; +static const unsigned long create_always = 2; +static const unsigned long open_existing = 3; +static const unsigned long open_always = 4; +static const unsigned long truncate_existing = 5; + +static const unsigned long file_attribute_temporary = 0x00000100; + +static const unsigned long file_begin = 0; +static const unsigned long file_current = 1; +static const unsigned long file_end = 2; + +static const unsigned long lockfile_fail_immediately = 1; +static const unsigned long lockfile_exclusive_lock = 2; +static const unsigned long error_lock_violation = 33; +static const unsigned long security_descriptor_revision = 1; + +} //namespace winapi { +} //namespace interprocess { +} //namespace boost { + +#if !defined( BOOST_USE_WINDOWS_H ) + +namespace boost { +namespace interprocess { +namespace winapi { + +struct interprocess_overlapped +{ + unsigned long *internal; + unsigned long *internal_high; + union { + struct { + unsigned long offset; + unsigned long offset_high; + }dummy; + void *pointer; + }; + + void *h_event; +}; + +struct interprocess_filetime +{ + unsigned long dwLowDateTime; + unsigned long dwHighDateTime; +}; + +struct interprocess_security_attributes +{ + unsigned long nLength; + void *lpSecurityDescriptor; + int bInheritHandle; +}; + +struct system_info { + union { + unsigned long dwOemId; // Obsolete field...do not use + struct { + unsigned short wProcessorArchitecture; + unsigned short wReserved; + } dummy; + }; + unsigned long dwPageSize; + void * lpMinimumApplicationAddress; + void * lpMaximumApplicationAddress; + unsigned long * dwActiveProcessorMask; + unsigned long dwNumberOfProcessors; + unsigned long dwProcessorType; + unsigned long dwAllocationGranularity; + unsigned short wProcessorLevel; + unsigned short wProcessorRevision; +}; + +struct interprocess_memory_basic_information +{ + void * BaseAddress; + void * AllocationBase; + unsigned long AllocationProtect; + unsigned long RegionSize; + unsigned long State; + unsigned long Protect; + unsigned long Type; +}; + +typedef struct _interprocess_acl +{ + unsigned char AclRevision; + unsigned char Sbz1; + unsigned short AclSize; + unsigned short AceCount; + unsigned short Sbz2; +} interprocess_acl; + +typedef struct _interprocess_security_descriptor +{ + unsigned char Revision; + unsigned char Sbz1; + unsigned short Control; + void *Owner; + void *Group; + interprocess_acl *Sacl; + interprocess_acl *Dacl; +} interprocess_security_descriptor; + +//Some windows API declarations +extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId(); +extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId(); +extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long); +extern "C" __declspec(dllimport) unsigned long __stdcall GetLastError(); +extern "C" __declspec(dllimport) void * __stdcall GetCurrentProcess(); +extern "C" __declspec(dllimport) int __stdcall CloseHandle(void*); +extern "C" __declspec(dllimport) int __stdcall DuplicateHandle + ( void *hSourceProcessHandle, void *hSourceHandle + , void *hTargetProcessHandle, void **lpTargetHandle + , unsigned long dwDesiredAccess, int bInheritHandle + , unsigned long dwOptions); +extern "C" __declspec(dllimport) void __stdcall GetSystemTimeAsFileTime(interprocess_filetime*); +extern "C" __declspec(dllimport) int __stdcall FileTimeToLocalFileTime(const interprocess_filetime *in, const interprocess_filetime *out); +extern "C" __declspec(dllimport) void * __stdcall CreateMutexA(interprocess_security_attributes*, int, const char *); +extern "C" __declspec(dllimport) void * __stdcall OpenMutexA(unsigned long, int, const char *); +extern "C" __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void *, unsigned long); +extern "C" __declspec(dllimport) int __stdcall ReleaseMutex(void *); +extern "C" __declspec(dllimport) int __stdcall UnmapViewOfFile(void *); +extern "C" __declspec(dllimport) void * __stdcall CreateSemaphoreA(interprocess_security_attributes*, long, long, const char *); +extern "C" __declspec(dllimport) int __stdcall ReleaseSemaphore(void *, long, long *); +extern "C" __declspec(dllimport) void * __stdcall OpenSemaphoreA(unsigned long, int, const char *); +extern "C" __declspec(dllimport) void * __stdcall CreateFileMappingA (void *, interprocess_security_attributes*, unsigned long, unsigned long, unsigned long, const char *); +extern "C" __declspec(dllimport) void * __stdcall MapViewOfFileEx (void *, unsigned long, unsigned long, unsigned long, std::size_t, void*); +extern "C" __declspec(dllimport) void * __stdcall OpenFileMappingA (unsigned long, int, const char *); +extern "C" __declspec(dllimport) void * __stdcall CreateFileA (const char *, unsigned long, unsigned long, struct interprocess_security_attributes*, unsigned long, unsigned long, void *); +extern "C" __declspec(dllimport) int __stdcall DeleteFileA (const char *); +extern "C" __declspec(dllimport) void __stdcall GetSystemInfo (struct system_info *); +extern "C" __declspec(dllimport) int __stdcall FlushViewOfFile (void *, std::size_t); +extern "C" __declspec(dllimport) int __stdcall GetFileSizeEx (void *, __int64 *size); +extern "C" __declspec(dllimport) unsigned long __stdcall FormatMessageA + (unsigned long dwFlags, const void *lpSource, unsigned long dwMessageId, + unsigned long dwLanguageId, char *lpBuffer, unsigned long nSize, + std::va_list *Arguments); +extern "C" __declspec(dllimport) void *__stdcall LocalFree (void *); +extern "C" __declspec(dllimport) int __stdcall CreateDirectoryA(const char *, interprocess_security_attributes*); +extern "C" __declspec(dllimport) int __stdcall GetTempPathA(unsigned long length, char *buffer); +extern "C" __declspec(dllimport) int __stdcall CreateDirectory(const char *, interprocess_security_attributes*); +extern "C" __declspec(dllimport) int __stdcall SetFileValidData(void *, __int64 size); +extern "C" __declspec(dllimport) int __stdcall SetEndOfFile(void *); +extern "C" __declspec(dllimport) int __stdcall SetFilePointerEx(void *, __int64 distance, __int64 *new_file_pointer, unsigned long move_method); +extern "C" __declspec(dllimport) int __stdcall LockFile (void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high); +extern "C" __declspec(dllimport) int __stdcall UnlockFile(void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high); +extern "C" __declspec(dllimport) int __stdcall LockFileEx(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped); +extern "C" __declspec(dllimport) int __stdcall UnlockFileEx(void *hnd, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped); +extern "C" __declspec(dllimport) int __stdcall WriteFile(void *hnd, const void *buffer, unsigned long bytes_to_write, unsigned long *bytes_written, interprocess_overlapped* overlapped); +extern "C" __declspec(dllimport) int __stdcall InitializeSecurityDescriptor(interprocess_security_descriptor *pSecurityDescriptor, unsigned long dwRevision); +extern "C" __declspec(dllimport) int __stdcall SetSecurityDescriptorDacl(interprocess_security_descriptor *pSecurityDescriptor, int bDaclPresent, interprocess_acl *pDacl, int bDaclDefaulted); + +} //namespace winapi { +} //namespace interprocess { +} //namespace boost { + +#else +# include +#endif //#if !defined( BOOST_USE_WINDOWS_H ) + +namespace boost { +namespace interprocess { +namespace winapi { + +static inline unsigned long format_message + (unsigned long dwFlags, const void *lpSource, + unsigned long dwMessageId, unsigned long dwLanguageId, + char *lpBuffer, unsigned long nSize, std::va_list *Arguments) +{ + return FormatMessageA + (dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments); +} + +//And now, wrapper functions +static inline void * local_free(void *hmem) +{ return LocalFree(hmem); } + +static inline unsigned long make_lang_id(unsigned long p, unsigned long s) +{ return ((((unsigned short)(s)) << 10) | (unsigned short)(p)); } + +static inline void sched_yield() +{ Sleep(1); } + +static inline unsigned long get_current_thread_id() +{ return GetCurrentThreadId(); } + +static inline unsigned long get_current_process_id() +{ return GetCurrentProcessId(); } + +static inline unsigned int close_handle(void* handle) +{ return CloseHandle(handle); } + +static inline bool duplicate_current_process_handle + (void *hSourceHandle, void **lpTargetHandle) +{ + return 0 != DuplicateHandle + ( GetCurrentProcess(), hSourceHandle, GetCurrentProcess() + , lpTargetHandle, 0, 0 + , duplicate_same_access); +} + +static inline unsigned long get_last_error() +{ return GetLastError(); } + +static inline void get_system_time_as_file_time(interprocess_filetime *filetime) +{ GetSystemTimeAsFileTime(filetime); } + +static inline bool file_time_to_local_file_time + (const interprocess_filetime *in, const interprocess_filetime *out) +{ return 0 != FileTimeToLocalFileTime(in, out); } + +static inline void *create_mutex(const char *name) +{ return CreateMutexA(0, 0, name); } + +static inline void *open_mutex(const char *name) +{ return OpenMutexA(mutex_all_access, 0, name); } + +static inline unsigned long wait_for_single_object(void *handle, unsigned long time) +{ return WaitForSingleObject(handle, time); } + +static inline int release_mutex(void *handle) +{ return ReleaseMutex(handle); } + +static inline int unmap_view_of_file(void *address) +{ return UnmapViewOfFile(address); } + +static inline void *create_semaphore(long initialCount, const char *name) +{ return CreateSemaphoreA(0, initialCount, (long)(((unsigned long)(-1))>>1), name); } + +static inline int release_semaphore(void *handle, long release_count, long *prev_count) +{ return ReleaseSemaphore(handle, release_count, prev_count); } + +static inline void *open_semaphore(const char *name) +{ return OpenSemaphoreA(semaphore_all_access, 1, name); } + +static inline void * create_file_mapping (void * handle, unsigned long access, unsigned long high_size, unsigned long low_size, const char * name) +{ + interprocess_security_attributes sa; + interprocess_security_descriptor sd; + + if(!InitializeSecurityDescriptor(&sd, security_descriptor_revision)) + return 0; + if(!SetSecurityDescriptorDacl(&sd, true, 0, false)) + return 0; + sa.lpSecurityDescriptor = &sd; + sa.nLength = sizeof(interprocess_security_attributes); + sa.bInheritHandle = false; + return CreateFileMappingA (handle, &sa, access, high_size, low_size, name); + //return CreateFileMappingA (handle, 0, access, high_size, low_size, name); +} + +static inline void * open_file_mapping (unsigned long access, const char *name) +{ return OpenFileMappingA (access, 0, name); } + +static inline void *map_view_of_file_ex(void *handle, unsigned long file_access, unsigned long highoffset, unsigned long lowoffset, std::size_t numbytes, void *base_addr) +{ return MapViewOfFileEx(handle, file_access, highoffset, lowoffset, numbytes, base_addr); } + +static inline void *create_file(const char *name, unsigned long access, unsigned long creation_flags, unsigned long attributes = 0) +{ return CreateFileA(name, access, file_share_read | file_share_write, 0, creation_flags, attributes, 0); } + +static inline bool delete_file(const char *name) +{ return 0 != DeleteFileA(name); } + +static inline void get_system_info(system_info *info) +{ GetSystemInfo(info); } + +static inline int flush_view_of_file(void *base_addr, std::size_t numbytes) +{ return FlushViewOfFile(base_addr, numbytes); } + +static inline bool get_file_size(void *handle, __int64 &size) +{ return 0 != GetFileSizeEx(handle, &size); } + +static inline bool create_directory(const char *name, interprocess_security_attributes* security) +{ return 0 != CreateDirectoryA(name, security); } + +static inline unsigned long get_temp_path(unsigned long length, char *buffer) +{ return GetTempPathA(length, buffer); } + +static inline int set_end_of_file(void *handle) +{ return 0 != SetEndOfFile(handle); } + +static inline bool set_file_pointer_ex(void *handle, __int64 distance, __int64 *new_file_pointer, unsigned long move_method) +{ return 0 != SetFilePointerEx(handle, distance, new_file_pointer, move_method); } + +static inline bool lock_file_ex(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped *overlapped) +{ return 0 != LockFileEx(hnd, flags, reserved, size_low, size_high, overlapped); } + +static inline bool unlock_file_ex(void *hnd, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped *overlapped) +{ return 0 != UnlockFileEx(hnd, reserved, size_low, size_high, overlapped); } + +static inline bool write_file(void *hnd, const void *buffer, unsigned long bytes_to_write, unsigned long *bytes_written, interprocess_overlapped* overlapped) +{ return 0 != WriteFile(hnd, buffer, bytes_to_write, bytes_written, overlapped); } + +static inline long interlocked_increment(long volatile *addr) +{ return BOOST_INTERLOCKED_INCREMENT(addr); } + +static inline long interlocked_decrement(long volatile *addr) +{ return BOOST_INTERLOCKED_DECREMENT(addr); } + +static inline long interlocked_compare_exchange(long volatile *addr, long val1, long val2) +{ return BOOST_INTERLOCKED_COMPARE_EXCHANGE(addr, val1, val2); } + +static inline long interlocked_exchange_add(long volatile* addend, long value) +{ return BOOST_INTERLOCKED_EXCHANGE_ADD((long*)addend, value); } + +static inline long interlocked_exchange(long volatile* addend, long value) +{ return BOOST_INTERLOCKED_EXCHANGE((long*)addend, value); } + +} //namespace winapi +} //namespace interprocess +} //namespace boost + +#include + +#endif //#ifdef BOOST_INTERPROCESS_WIN32_SYNC_PRIMITIVES_HPP diff --git a/win32/include/boost/interprocess/detail/workaround.hpp b/win32/include/boost/interprocess/detail/workaround.hpp new file mode 100755 index 000000000..e2e76cdab --- /dev/null +++ b/win32/include/boost/interprocess/detail/workaround.hpp @@ -0,0 +1,139 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_PTR_WRKRND_HPP +#define BOOST_INTERPROCESS_PTR_WRKRND_HPP + +#include + +#undef BOOST_DISABLE_WIN32 + +#if !(defined BOOST_WINDOWS) || (defined BOOST_DISABLE_WIN32) + + #include + + #if defined(_POSIX_THREAD_PROCESS_SHARED) + # if !((_XOPEN_VERSION >= 600) && (_POSIX_THREAD_PROCESS_SHARED - 0 <= 0)) + //Cygwin defines _POSIX_THREAD_PROCESS_SHARED but does not implement it. + //Mac Os X >= Leopard defines _POSIX_THREAD_PROCESS_SHARED but does not seems to work. + # if !defined(__CYGWIN__) && !defined(__APPLE__) + # define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED + # endif + # endif + #endif + + #if defined(_POSIX_BARRIERS) + # if !((_XOPEN_VERSION >= 600) && (_POSIX_BARRIERS - 0 <= 0)) + # define BOOST_INTERPROCESS_POSIX_BARRIERS + # endif + #endif + + #if defined(_POSIX_SEMAPHORES) + # if !((_XOPEN_VERSION >= 600) && (_POSIX_SEMAPHORES - 0 <= 0)) + # define BOOST_INTERPROCESS_POSIX_SEMAPHORES + # if defined(__CYGWIN__) + #define BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK + # endif + # endif + #endif + + #if ((defined _V6_ILP32_OFFBIG) &&(_V6_ILP32_OFFBIG - 0 > 0)) ||\ + ((defined _V6_LP64_OFF64) &&(_V6_LP64_OFF64 - 0 > 0)) ||\ + ((defined _V6_LPBIG_OFFBIG) &&(_V6_LPBIG_OFFBIG - 0 > 0)) ||\ + ((defined _XBS5_ILP32_OFFBIG)&&(_XBS5_ILP32_OFFBIG - 0 > 0)) ||\ + ((defined _XBS5_LP64_OFF64) &&(_XBS5_LP64_OFF64 - 0 > 0)) ||\ + ((defined _XBS5_LPBIG_OFFBIG)&&(_XBS5_LPBIG_OFFBIG - 0 > 0)) ||\ + ((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))||\ + ((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64)) + #define BOOST_INTERPROCESS_UNIX_64_BIT_OR_BIGGER_OFF_T + #else + #endif + + #if defined(_POSIX_SHARED_MEMORY_OBJECTS) + # if !((_XOPEN_VERSION >= 600) && (_POSIX_SHARED_MEMORY_OBJECTS - 0 <= 0)) + # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS + # endif + #else + # if defined(__vms) + # if __CRTL_VER >= 70200000 + # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS + # endif + # endif + #endif + + #if defined(_POSIX_TIMEOUTS) + # if !((_XOPEN_VERSION >= 600) && (_POSIX_TIMEOUTS - 0 <= 0)) + # define BOOST_INTERPROCESS_POSIX_TIMEOUTS + # endif + #endif + + #ifdef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS + //Some systems have filesystem-based shared memory, so the + //portable "/shmname" format does not work due to permission issues + //For those systems we need to form a path to a temporary directory: + // hp-ux tru64 vms + #if defined(__hpux) || defined(__osf__) || defined(__vms) + #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY + #endif + #endif + + #ifdef BOOST_INTERPROCESS_POSIX_SEMAPHORES + //Some systems have filesystem-based shared memory, so the + //portable "/semname" format does not work due to permission issues + //For those systems we need to form a path to a temporary directory: + // hp-ux tru64 vms + #if defined(__hpux) || defined(__osf__) || defined(__vms) + #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES + #endif + #endif + + #if ((_POSIX_VERSION + 0)>= 200112L || (_XOPEN_VERSION + 0)>= 500) + #define BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES + #endif + +#endif + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2) +// C++0x features are only enabled when -std=c++0x or -std=gnu++0x are +// passed on the command line, which in turn defines +// __GXX_EXPERIMENTAL_CXX0X__. Note: __GXX_EXPERIMENTAL_CPP0X__ is +// defined by some very early development versions of GCC 4.3; we will +// remove this part of the check in the near future. +# if defined(__GXX_EXPERIMENTAL_CPP0X__) || defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_INTERPROCESS_RVALUE_REFERENCE +# define BOOST_INTERPROCESS_VARIADIC_TEMPLATES +# if defined(__GLIBCPP__) || defined(__GLIBCXX__) +# define BOOST_INTERPROCESS_RVALUE_PAIR +# endif +# endif +#endif + +#if defined(BOOST_INTERPROCESS_RVALUE_REFERENCE) && defined(BOOST_INTERPROCESS_VARIADIC_TEMPLATES) +#define BOOST_INTERPROCESS_PERFECT_FORWARDING +#endif + +//Now declare some Boost.Interprocess features depending on the implementation + +#if defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK) + +#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES + +#endif + +#if defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK) + +#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES +#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES + +#endif + +#include + +#endif //#ifndef BOOST_INTERPROCESS_PTR_WRKRND_HPP diff --git a/win32/include/boost/interprocess/errors.hpp b/win32/include/boost/interprocess/errors.hpp new file mode 100755 index 000000000..065a8f5fe --- /dev/null +++ b/win32/include/boost/interprocess/errors.hpp @@ -0,0 +1,229 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +// Parts of this code are taken from boost::filesystem library +// +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2002 Beman Dawes +// Copyright (C) 2001 Dietmar Kuehl +// Use, modification, and distribution is subject to 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) +// +// See library home page at http://www.boost.org/libs/filesystem +// +////////////////////////////////////////////////////////////////////////////// + + +#ifndef BOOST_INTERPROCESS_ERRORS_HPP +#define BOOST_INTERPROCESS_ERRORS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include + +#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) +# include +#else +# ifdef BOOST_HAS_UNISTD_H +# include //Errors +# include //strerror +# else //ifdef BOOST_HAS_UNISTD_H +# error Unknown platform +# endif //ifdef BOOST_HAS_UNISTD_H +#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +//!\file +//!Describes the error numbering of interprocess classes + +namespace boost { +namespace interprocess { +/// @cond +static inline int system_error_code() // artifact of POSIX and WINDOWS error reporting +{ + #if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + return winapi::get_last_error(); + #else + return errno; // GCC 3.1 won't accept ::errno + #endif +} + + +#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) +inline void fill_system_message(int sys_err_code, std::string &str) +{ + void *lpMsgBuf; + winapi::format_message( + winapi::format_message_allocate_buffer | + winapi::format_message_from_system | + winapi::format_message_ignore_inserts, + 0, + sys_err_code, + winapi::make_lang_id(winapi::lang_neutral, winapi::sublang_default), // Default language + (char *) &lpMsgBuf, + 0, + 0 + ); + str += static_cast(lpMsgBuf); + winapi::local_free( lpMsgBuf ); // free the buffer + while ( str.size() + && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r') ) + str.erase( str.size()-1 ); +} +# else +static inline void fill_system_message( int system_error, std::string &str) +{ str = std::strerror(system_error); } +# endif +/// @endcond + +enum error_code_t +{ + no_error = 0, + system_error, // system generated error; if possible, is translated + // to one of the more specific errors below. + other_error, // library generated error + security_error, // includes access rights, permissions failures + read_only_error, + io_error, + path_error, + not_found_error, +// not_directory_error, + busy_error, // implies trying again might succeed + already_exists_error, + not_empty_error, + is_directory_error, + out_of_space_error, + out_of_memory_error, + out_of_resource_error, + lock_error, + sem_error, + mode_error, + size_error, + corrupted_error +}; + +typedef int native_error_t; + +/// @cond +struct ec_xlate +{ + native_error_t sys_ec; + error_code_t ec; +}; + +static const ec_xlate ec_table[] = +{ + #if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + { /*ERROR_ACCESS_DENIED*/5L, security_error }, + { /*ERROR_INVALID_ACCESS*/12L, security_error }, + { /*ERROR_SHARING_VIOLATION*/32L, security_error }, + { /*ERROR_LOCK_VIOLATION*/33L, security_error }, + { /*ERROR_LOCKED*/212L, security_error }, + { /*ERROR_NOACCESS*/998L, security_error }, + { /*ERROR_WRITE_PROTECT*/19L, read_only_error }, + { /*ERROR_NOT_READY*/21L, io_error }, + { /*ERROR_SEEK*/25L, io_error }, + { /*ERROR_READ_FAULT*/30L, io_error }, + { /*ERROR_WRITE_FAULT*/29L, io_error }, + { /*ERROR_CANTOPEN*/1011L, io_error }, + { /*ERROR_CANTREAD*/1012L, io_error }, + { /*ERROR_CANTWRITE*/1013L, io_error }, + { /*ERROR_DIRECTORY*/267L, path_error }, + { /*ERROR_INVALID_NAME*/123L, path_error }, + { /*ERROR_FILE_NOT_FOUND*/2L, not_found_error }, + { /*ERROR_PATH_NOT_FOUND*/3L, not_found_error }, + { /*ERROR_DEV_NOT_EXIST*/55L, not_found_error }, + { /*ERROR_DEVICE_IN_USE*/2404L, busy_error }, + { /*ERROR_OPEN_FILES*/2401L, busy_error }, + { /*ERROR_BUSY_DRIVE*/142L, busy_error }, + { /*ERROR_BUSY*/170L, busy_error }, + { /*ERROR_FILE_EXISTS*/80L, already_exists_error }, + { /*ERROR_ALREADY_EXISTS*/183L, already_exists_error }, + { /*ERROR_DIR_NOT_EMPTY*/145L, not_empty_error }, + { /*ERROR_HANDLE_DISK_FULL*/39L, out_of_space_error }, + { /*ERROR_DISK_FULL*/112L, out_of_space_error }, + { /*ERROR_OUTOFMEMORY*/14L, out_of_memory_error }, + { /*ERROR_NOT_ENOUGH_MEMORY*/8L, out_of_memory_error }, + { /*ERROR_TOO_MANY_OPEN_FILES*/4L, out_of_resource_error } + #else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + { EACCES, security_error }, + { EROFS, read_only_error }, + { EIO, io_error }, + { ENAMETOOLONG, path_error }, + { ENOENT, not_found_error }, + // { ENOTDIR, not_directory_error }, + { EAGAIN, busy_error }, + { EBUSY, busy_error }, + { ETXTBSY, busy_error }, + { EEXIST, already_exists_error }, + { ENOTEMPTY, not_empty_error }, + { EISDIR, is_directory_error }, + { ENOSPC, out_of_space_error }, + { ENOMEM, out_of_memory_error }, + { EMFILE, out_of_resource_error } + #endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) +}; + +static inline error_code_t lookup_error(native_error_t err) +{ + const ec_xlate *cur = &ec_table[0], + *end = cur + sizeof(ec_table)/sizeof(ec_xlate); + for (;cur != end; ++cur ){ + if ( err == cur->sys_ec ) return cur->ec; + } + return system_error; // general system error code +} + +struct error_info +{ + error_info(error_code_t ec = other_error ) + : m_nat(0), m_ec(ec) + {} + + error_info(native_error_t sys_err_code) + : m_nat(sys_err_code), m_ec(lookup_error(sys_err_code)) + {} + + error_info & operator =(error_code_t ec) + { + m_nat = 0; + m_ec = ec; + return *this; + } + + error_info & operator =(native_error_t sys_err_code) + { + m_nat = sys_err_code; + m_ec = lookup_error(sys_err_code); + return *this; + } + + native_error_t get_native_error()const + { return m_nat; } + + error_code_t get_error_code()const + { return m_ec; } + + private: + native_error_t m_nat; + error_code_t m_ec; +}; +/// @endcond + +} // namespace interprocess { +} // namespace boost + +#include + +#endif // BOOST_INTERPROCESS_ERRORS_HPP diff --git a/win32/include/boost/interprocess/exceptions.hpp b/win32/include/boost/interprocess/exceptions.hpp new file mode 100755 index 000000000..2889321cb --- /dev/null +++ b/win32/include/boost/interprocess/exceptions.hpp @@ -0,0 +1,145 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_EXCEPTIONS_HPP +#define BOOST_INTERPROCESS_EXCEPTIONS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include + +//!\file +//!Describes exceptions thrown by interprocess classes + +namespace boost { + +namespace interprocess { + +//!This class is the base class of all exceptions +//!thrown by boost::interprocess +class interprocess_exception : public std::exception +{ + public: + interprocess_exception(error_code_t ec = other_error ) + : m_err(ec) + { + try { m_str = "boost::interprocess_exception::library_error"; } + catch (...) {} + } + + interprocess_exception(native_error_t sys_err_code) + : m_err(sys_err_code) + { + try { fill_system_message(m_err.get_native_error(), m_str); } + catch (...) {} + } + + interprocess_exception(const error_info &err_info) + : m_err(err_info) + { + try{ + if(m_err.get_native_error() != 0){ + fill_system_message(m_err.get_native_error(), m_str); + }/* + else{ + m_str = "boost::interprocess_exception::library_error"; + }*/ + } + catch(...){} + } + + virtual ~interprocess_exception() throw(){} + + virtual const char * what() const throw() + { return m_str.c_str(); } + + native_error_t get_native_error()const { return m_err.get_native_error(); } + + // Note: a value of other_error implies a library (rather than system) error + error_code_t get_error_code() const { return m_err.get_error_code(); } + + /// @cond + private: + error_info m_err; + std::string m_str; + /// @endcond +}; + +//!This is the exception thrown by shared interprocess_mutex family when a deadlock situation +//!is detected or when using a interprocess_condition the interprocess_mutex is not locked +class lock_exception : public interprocess_exception +{ + public: + lock_exception() + : interprocess_exception(lock_error) + {} + + virtual const char* what() const throw() + { return "boost::interprocess::lock_exception"; } +}; + +//!This is the exception thrown by named interprocess_semaphore when a deadlock situation +//!is detected or when an error is detected in the post/wait operation +/* +class sem_exception : public interprocess_exception +{ + public: + sem_exception() + : interprocess_exception(lock_error) + {} + + virtual const char* what() const throw() + { return "boost::interprocess::sem_exception"; } +}; +*/ +//!This is the exception thrown by synchronization objects when there is +//!an error in a wait() function +/* +class wait_exception : public interprocess_exception +{ + public: + virtual const char* what() const throw() + { return "boost::interprocess::wait_exception"; } +}; +*/ + +//!This exception is thrown when a named object is created +//!in "open_only" mode and the resource was not already created +/* +class not_previously_created : public interprocess_exception +{ + public: + virtual const char* what() const throw() + { return "boost::interprocess::not_previously_created"; } +}; +*/ + +//!This exception is thrown when a memory request can't be +//!fulfilled. +class bad_alloc : public interprocess_exception +{ + public: + virtual const char* what() const throw() + { return "boost::interprocess::bad_alloc"; } +}; + +} // namespace interprocess { + +} // namespace boost + +#include + +#endif // BOOST_INTERPROCESS_EXCEPTIONS_HPP diff --git a/win32/include/boost/interprocess/file_mapping.hpp b/win32/include/boost/interprocess/file_mapping.hpp new file mode 100755 index 000000000..dd67d1892 --- /dev/null +++ b/win32/include/boost/interprocess/file_mapping.hpp @@ -0,0 +1,205 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MAPPED_FILE_HPP +#define BOOST_INTERPROCESS_MAPPED_FILE_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include +#include //std::string +#include //std::remove +#include + +//!\file +//!Describes file_mapping and mapped region classes + +namespace boost { + +namespace interprocess { + +//!A class that wraps a file-mapping that can be used to +//!create mapped regions from the mapped files +class file_mapping +{ + /// @cond + //Non-copyable and non-assignable + file_mapping(const file_mapping &); + file_mapping &operator=(const file_mapping &); + /// @endcond + + public: + //!Constructs an empty file mapping. + //!Does not throw + file_mapping(); + + //!Opens a file mapping of file "filename", starting in offset + //!"file_offset", and the mapping's size will be "size". The mapping + //!can be opened for read-only "read_only" or read-write "read_write" + //!modes. Throws interprocess_exception on error. + file_mapping(const char *filename, mode_t mode); + + //!Moves the ownership of "moved"'s shared memory object to *this. + //!After the call, "moved" does not represent any shared memory object. + //!Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + file_mapping(detail::moved_object moved) + : m_handle(file_handle_t(detail::invalid_file())) + { this->swap(moved.get()); } + #else + file_mapping(file_mapping &&moved) + : m_handle(file_handle_t(detail::invalid_file())) + { this->swap(moved); } + #endif + + //!Moves the ownership of "moved"'s shared memory to *this. + //!After the call, "moved" does not represent any shared memory. + //!Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + file_mapping &operator= + (detail::moved_object moved) + { + file_mapping tmp(moved); + this->swap(tmp); + return *this; + } + #else + file_mapping &operator=(file_mapping &&moved) + { + file_mapping tmp(detail::move_impl(moved)); + this->swap(tmp); + return *this; + } + #endif + + //!Swaps to file_mappings. + //!Does not throw. + void swap(file_mapping &other); + + //!Returns access mode + //!used in the constructor + mode_t get_mode() const; + + //!Obtains the mapping handle + //!to be used with mapped_region + mapping_handle_t get_mapping_handle() const; + + //!Destroys the file mapping. All mapped regions created from this are still + //!valid. Does not throw + ~file_mapping(); + + //!Returns the name of the file + //!used in the constructor. + const char *get_name() const; + + /// @cond + private: + //!Closes a previously opened file mapping. Never throws. + void priv_close(); + file_handle_t m_handle; + mode_t m_mode; + std::string m_filename; + /// @endcond +}; + +inline file_mapping::file_mapping() + : m_handle(file_handle_t(detail::invalid_file())) +{} + +inline file_mapping::~file_mapping() +{ this->priv_close(); } + +inline const char *file_mapping::get_name() const +{ return m_filename.c_str(); } + +inline void file_mapping::swap(file_mapping &other) +{ + std::swap(m_handle, other.m_handle); + std::swap(m_mode, other.m_mode); + m_filename.swap(other.m_filename); +} + +inline mapping_handle_t file_mapping::get_mapping_handle() const +{ return detail::mapping_handle_from_file_handle(m_handle); } + +inline mode_t file_mapping::get_mode() const +{ return m_mode; } + +inline file_mapping::file_mapping + (const char *filename, mode_t mode) + : m_filename(filename) +{ + //Check accesses + if (mode != read_write && mode != read_only){ + error_info err = other_error; + throw interprocess_exception(err); + } + + //Open file + m_handle = detail::open_existing_file(filename, mode); + + //Check for error + if(m_handle == detail::invalid_file()){ + error_info err = system_error_code(); + this->priv_close(); + throw interprocess_exception(err); + } + m_mode = mode; +} + +///@cond + +inline void file_mapping::priv_close() +{ + if(m_handle != detail::invalid_file()){ + detail::close_file(m_handle); + m_handle = detail::invalid_file(); + } +} + + +//!Trait class to detect if a type is +//!movable +template<> +struct is_movable +{ + enum { value = true }; +}; + +///@endcond + +//!A class that stores the name of a a file +//!and call std::remove(name) in its destructor +//!Useful to remove temporary files in the presence +//!of exceptions +class remove_file_on_destroy +{ + const char * m_name; + public: + remove_file_on_destroy(const char *name) + : m_name(name) + {} + + ~remove_file_on_destroy() + { std::remove(m_name); } +}; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MAPPED_FILE_HPP diff --git a/win32/include/boost/interprocess/indexes/flat_map_index.hpp b/win32/include/boost/interprocess/indexes/flat_map_index.hpp new file mode 100755 index 000000000..aa03b5d0d --- /dev/null +++ b/win32/include/boost/interprocess/indexes/flat_map_index.hpp @@ -0,0 +1,78 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP +#define BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP + +#include +#include + +#include +#include +#include +#include + +//!\file +//!Describes index adaptor of boost::map container, to use it +//!as name/shared memory index + +//[flat_map_index +namespace boost { namespace interprocess { + +//!Helper class to define typedefs from IndexTraits +template +struct flat_map_index_aux +{ + typedef typename MapConfig::key_type key_type; + typedef typename MapConfig::mapped_type mapped_type; + typedef typename MapConfig:: + segment_manager_base segment_manager_base; + typedef std::less key_less; + typedef std::pair value_type; + typedef allocator allocator_type; + typedef flat_map index_t; +}; + +//!Index type based in flat_map. Just derives from flat_map and +//!defines the interface needed by managed memory segments. +template +class flat_map_index + //Derive class from flat_map specialization + : public flat_map_index_aux::index_t +{ + /// @cond + typedef flat_map_index_aux index_aux; + typedef typename index_aux::index_t base_type; + typedef typename index_aux:: + segment_manager_base segment_manager_base; + /// @endcond + + public: + //!Constructor. Takes a pointer to the segment manager. Can throw + flat_map_index(segment_manager_base *segment_mngr) + : base_type(typename index_aux::key_less(), + typename index_aux::allocator_type(segment_mngr)) + {} + + //!This reserves memory to optimize the insertion of n elements in the index + void reserve(std::size_t n) + { base_type::reserve(n); } + + //!This frees all unnecessary memory + void shrink_to_fit() + { base_type::shrink_to_fit(); } +}; + +}} //namespace boost { namespace interprocess +//] +#include + +#endif //#ifndef BOOST_INTERPROCESS_FLAT_MAP_INDEX_HPP diff --git a/win32/include/boost/interprocess/indexes/iset_index.hpp b/win32/include/boost/interprocess/indexes/iset_index.hpp new file mode 100755 index 000000000..dd71a75bf --- /dev/null +++ b/win32/include/boost/interprocess/indexes/iset_index.hpp @@ -0,0 +1,150 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_ISET_INDEX_HPP +#define BOOST_INTERPROCESS_ISET_INDEX_HPP + +#include +#include + +#include +#include +#include +#include +#include + + +//!\file +//!Describes index adaptor of boost::intrusive::set container, to use it +//!as name/shared memory index + +namespace boost { +namespace interprocess { + +/// @cond + +//!Helper class to define typedefs from IndexTraits +template +struct iset_index_aux +{ + typedef typename + MapConfig::segment_manager_base segment_manager_base; + + typedef typename + segment_manager_base::void_pointer void_pointer; + typedef typename bi::make_set_base_hook + < bi::void_pointer + , bi::optimize_size + >::type derivation_hook; + + typedef typename MapConfig::template + intrusive_value_type::type value_type; + typedef std::less value_compare; + typedef typename bi::make_set + < value_type + , bi::base_hook + >::type index_t; +}; +/// @endcond + +//!Index type based in boost::intrusive::set. +//!Just derives from boost::intrusive::set +//!and defines the interface needed by managed memory segments*/ +template +class iset_index + //Derive class from map specialization + : public iset_index_aux::index_t +{ + /// @cond + typedef iset_index_aux index_aux; + typedef typename index_aux::index_t index_type; + typedef typename MapConfig:: + intrusive_compare_key_type intrusive_compare_key_type; + typedef typename MapConfig::char_type char_type; + /// @endcond + + public: + typedef typename index_type::iterator iterator; + typedef typename index_type::const_iterator const_iterator; + typedef typename index_type::insert_commit_data insert_commit_data; + typedef typename index_type::value_type value_type; + + /// @cond + private: + + struct intrusive_key_value_less + { + bool operator()(const intrusive_compare_key_type &i, const value_type &b) const + { + std::size_t blen = b.name_length(); + return (i.m_len < blen) || + (i.m_len == blen && + std::char_traits::compare + (i.mp_str, b.name(), i.m_len) < 0); + } + + bool operator()(const value_type &b, const intrusive_compare_key_type &i) const + { + std::size_t blen = b.name_length(); + return (blen < i.m_len) || + (blen == i.m_len && + std::char_traits::compare + (b.name(), i.mp_str, i.m_len) < 0); + } + }; + + /// @endcond + + public: + + //!Constructor. Takes a pointer to the + //!segment manager. Can throw + iset_index(typename MapConfig::segment_manager_base *) + : index_type(/*typename index_aux::value_compare()*/) + {} + + //!This reserves memory to optimize the insertion of n + //!elements in the index + void reserve(std::size_t) + { /*Does nothing, map has not reserve or rehash*/ } + + //!This frees all unnecessary memory + void shrink_to_fit() + { /*Does nothing, this intrusive index does not allocate memory;*/ } + + iterator find(const intrusive_compare_key_type &key) + { return index_type::find(key, intrusive_key_value_less()); } + + const_iterator find(const intrusive_compare_key_type &key) const + { return index_type::find(key, intrusive_key_value_less()); } + + std::pairinsert_check + (const intrusive_compare_key_type &key, insert_commit_data &commit_data) + { return index_type::insert_check(key, intrusive_key_value_less(), commit_data); } +}; + +/// @cond + +//!Trait class to detect if an index is an intrusive +//!index. +template +struct is_intrusive_index + > +{ + enum{ value = true }; +}; +/// @endcond + +} //namespace interprocess { +} //namespace boost + +#include + +#endif //#ifndef BOOST_INTERPROCESS_ISET_INDEX_HPP diff --git a/win32/include/boost/interprocess/indexes/iunordered_set_index.hpp b/win32/include/boost/interprocess/indexes/iunordered_set_index.hpp new file mode 100755 index 000000000..26fee56ae --- /dev/null +++ b/win32/include/boost/interprocess/indexes/iunordered_set_index.hpp @@ -0,0 +1,367 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP +#define BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes index adaptor of boost::intrusive::unordered_set container, to use it +//!as name/shared memory index + +namespace boost { namespace interprocess { + +/// @cond + +//!Helper class to define typedefs +//!from IndexTraits +template +struct iunordered_set_index_aux +{ + typedef typename + MapConfig::segment_manager_base segment_manager_base; + + typedef typename + segment_manager_base::void_pointer void_pointer; + + typedef typename bi::make_unordered_set_base_hook + < bi::void_pointer + >::type derivation_hook; + + typedef typename MapConfig::template + intrusive_value_type::type value_type; + + typedef typename MapConfig:: + intrusive_compare_key_type intrusive_compare_key_type; + + typedef std::equal_to value_equal; + + typedef typename MapConfig::char_type char_type; + + struct equal_function + { + bool operator()(const intrusive_compare_key_type &i, const value_type &b) const + { + return (i.m_len == b.name_length()) && + (std::char_traits::compare + (i.mp_str, b.name(), i.m_len) == 0); + } + + bool operator()(const value_type &b, const intrusive_compare_key_type &i) const + { + return (i.m_len == b.name_length()) && + (std::char_traits::compare + (i.mp_str, b.name(), i.m_len) == 0); + } + + bool operator()(const value_type &b1, const value_type &b2) const + { + return (b1.name_length() == b2.name_length()) && + (std::char_traits::compare + (b1.name(), b2.name(), b1.name_length()) == 0); + } + }; + + struct hash_function + : std::unary_function + { + std::size_t operator()(const value_type &val) const + { + const char_type *beg = detail::get_pointer(val.name()), + *end = beg + val.name_length(); + return boost::hash_range(beg, end); + } + + std::size_t operator()(const intrusive_compare_key_type &i) const + { + const char_type *beg = i.mp_str, + *end = beg + i.m_len; + return boost::hash_range(beg, end); + } + }; + + typedef typename bi::make_unordered_set + < value_type + , bi::hash + , bi::equal + >::type index_t; + typedef typename index_t::bucket_type bucket_type; + typedef allocator + allocator_type; + + struct allocator_holder + { + allocator_holder(segment_manager_base *mngr) + : alloc(mngr) + {} + allocator_type alloc; + bucket_type init_bucket; + }; +}; +/// @endcond + +//!Index type based in boost::intrusive::set. +//!Just derives from boost::intrusive::set +//!and defines the interface needed by managed memory segments +template +class iunordered_set_index + //Derive class from map specialization + : private iunordered_set_index_aux::allocator_holder + , public iunordered_set_index_aux::index_t +{ + /// @cond + typedef iunordered_set_index_aux index_aux; + typedef typename index_aux::index_t index_type; + typedef typename MapConfig:: + intrusive_compare_key_type intrusive_compare_key_type; + typedef typename index_aux::equal_function equal_function; + typedef typename index_aux::hash_function hash_function; + typedef typename MapConfig::char_type char_type; + typedef typename + iunordered_set_index_aux::allocator_type allocator_type; + typedef typename + iunordered_set_index_aux::allocator_holder allocator_holder; + /// @endcond + + public: + typedef typename index_type::iterator iterator; + typedef typename index_type::const_iterator const_iterator; + typedef typename index_type::insert_commit_data insert_commit_data; + typedef typename index_type::value_type value_type; + typedef typename index_type::bucket_ptr bucket_ptr; + typedef typename index_type::bucket_type bucket_type; + typedef typename index_type::bucket_traits bucket_traits; + typedef typename index_type::size_type size_type; + + /// @cond + private: + typedef typename index_aux:: + segment_manager_base segment_manager_base; + + enum { InitBufferSize = 64}; + + static bucket_ptr create_buckets(allocator_type &alloc, std::size_t num) + { + num = index_type::suggested_upper_bucket_count(num); + bucket_ptr buckets = alloc.allocate(num); + bucket_ptr buckets_init = buckets; + for(std::size_t i = 0; i < num; ++i){ + new(get_pointer(buckets_init++))bucket_type(); + } + return buckets; + } + + static std::size_t shrink_buckets + ( bucket_ptr buckets, std::size_t old_size + , allocator_type &alloc, std::size_t new_size) + { + if(old_size <= new_size ) + return old_size; + std::size_t received_size; + if(!alloc.allocation_command + (try_shrink_in_place | nothrow_allocation, old_size, new_size, received_size, buckets).first){ + return old_size; + } + + for( bucket_type *p = detail::get_pointer(buckets) + received_size + , *pend = detail::get_pointer(buckets) + old_size + ; p != pend + ; ++p){ + p->~bucket_type(); + } + + bucket_ptr shunk_p = alloc.allocation_command + (shrink_in_place | nothrow_allocation, received_size, received_size, received_size, buckets).first; + BOOST_ASSERT(buckets == shunk_p); + + bucket_ptr buckets_init = buckets + received_size; + for(std::size_t i = 0; i < (old_size - received_size); ++i){ + get_pointer(buckets_init++)->~bucket_type(); + } + return received_size; + } + + static bucket_ptr expand_or_create_buckets + ( bucket_ptr old_buckets, const std::size_t old_num + , allocator_type &alloc, const std::size_t new_num) + { + std::size_t received_size; + std::pair ret = + alloc.allocation_command + (expand_fwd | allocate_new, new_num, new_num, received_size, old_buckets); + if(ret.first == old_buckets){ + bucket_ptr buckets_init = old_buckets + old_num; + for(std::size_t i = 0; i < (new_num - old_num); ++i){ + new(get_pointer(buckets_init++))bucket_type(); + } + } + else{ + bucket_ptr buckets_init = ret.first; + for(std::size_t i = 0; i < new_num; ++i){ + new(get_pointer(buckets_init++))bucket_type(); + } + } + + return ret.first; + } + + static void destroy_buckets + (allocator_type &alloc, bucket_ptr buckets, std::size_t num) + { + bucket_ptr buckets_destroy = buckets; + for(std::size_t i = 0; i < num; ++i){ + get_pointer(buckets_destroy++)->~bucket_type(); + } + alloc.deallocate(buckets, num); + } + + iunordered_set_index* get_this_pointer() + { return this; } + + /// @endcond + + public: + //!Constructor. Takes a pointer to the + //!segment manager. Can throw + iunordered_set_index(segment_manager_base *mngr) + : allocator_holder(mngr) + , index_type(bucket_traits(&get_this_pointer()->init_bucket, 1)) + {} + + ~iunordered_set_index() + { + index_type::clear(); + if(index_type::bucket_pointer() != bucket_ptr(&this->init_bucket)){ + destroy_buckets(this->alloc, index_type::bucket_pointer(), index_type::bucket_count()); + } + } + + //!This reserves memory to optimize the insertion of n + //!elements in the index + void reserve(std::size_t new_n) + { + //Let's maintain a 1.0f load factor + size_type old_n = this->bucket_count(); + if(new_n <= old_n) + return; + bucket_ptr old_p = this->bucket_pointer(); + new_n = index_type::suggested_upper_bucket_count(new_n); + bucket_ptr new_p; + //This can throw + try{ + if(old_p != bucket_ptr(&this->init_bucket)) + new_p = expand_or_create_buckets(old_p, old_n, this->alloc, new_n); + else + new_p = create_buckets(this->alloc, new_n); + } + catch(...){ + return; + } + //Rehashing does not throw, since neither the hash nor the + //comparison function can throw + this->rehash(bucket_traits(new_p, new_n)); + if(new_p != old_p && old_p != bucket_ptr(&this->init_bucket)){ + destroy_buckets(this->alloc, old_p, old_n); + } + } + + //!This tries to free unused memory + //!previously allocated. + void shrink_to_fit() + { + size_type cur_size = this->size(); + size_type cur_count = this->bucket_count(); + bucket_ptr old_p = this->bucket_pointer(); + + if(!this->size() && old_p != bucket_ptr(&this->init_bucket)){ + this->rehash(bucket_traits(bucket_ptr(&this->init_bucket), 1)); + destroy_buckets(this->alloc, old_p, cur_count); + } + else{ + size_type sug_count = 0; //gcc warning + sug_count = index_type::suggested_upper_bucket_count(cur_size); + + if(sug_count >= cur_count) + return; + + try{ + shrink_buckets(old_p, cur_count, this->alloc, sug_count); + } + catch(...){ + return; + } + + //Rehashing does not throw, since neither the hash nor the + //comparison function can throw + this->rehash(bucket_traits(old_p, sug_count)); + } + } + + iterator find(const intrusive_compare_key_type &key) + { return index_type::find(key, hash_function(), equal_function()); } + + const_iterator find(const intrusive_compare_key_type &key) const + { return index_type::find(key, hash_function(), equal_function()); } + + std::pairinsert_check + (const intrusive_compare_key_type &key, insert_commit_data &commit_data) + { return index_type::insert_check(key, hash_function(), equal_function(), commit_data); } + + iterator insert_commit(value_type &val, insert_commit_data &commit_data) + { + iterator it = index_type::insert_commit(val, commit_data); + size_type cur_size = this->size(); + if(cur_size > this->bucket_count()){ + try{ + this->reserve(cur_size); + } + catch(...){ + //Strong guarantee: if something goes wrong + //we should remove the insertion. + // + //We can use the iterator because the hash function + //can't throw and this means that "reserve" will + //throw only because of the memory allocation: + //the iterator has not been invalidated. + index_type::erase(it); + throw; + } + } + return it; + } +}; + +/// @cond + +//!Trait class to detect if an index is an intrusive +//!index +template +struct is_intrusive_index + > +{ + enum{ value = true }; +}; +/// @endcond + +}} //namespace boost { namespace interprocess { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP diff --git a/win32/include/boost/interprocess/indexes/map_index.hpp b/win32/include/boost/interprocess/indexes/map_index.hpp new file mode 100755 index 000000000..062a80f30 --- /dev/null +++ b/win32/include/boost/interprocess/indexes/map_index.hpp @@ -0,0 +1,100 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MAP_INDEX_HPP +#define BOOST_INTERPROCESS_MAP_INDEX_HPP + +#include +#include + +#include +#include +#include +#include + +//!\file +//!Describes index adaptor of boost::map container, to use it +//!as name/shared memory index + +namespace boost { +namespace interprocess { +namespace detail{ + +//!Helper class to define typedefs from IndexTraits +template +struct map_index_aux +{ + typedef typename MapConfig::key_type key_type; + typedef typename MapConfig::mapped_type mapped_type; + typedef std::less key_less; + typedef std::pair value_type; + + typedef private_adaptive_pool + allocator_type; + + typedef boost::interprocess::map + index_t; +}; + +} //namespace detail { + +//!Index type based in boost::interprocess::map. Just derives from boost::interprocess::map +//!and defines the interface needed by managed memory segments +template +class map_index + //Derive class from map specialization + : public detail::map_index_aux::index_t +{ + /// @cond + typedef detail::map_index_aux index_aux; + typedef typename index_aux::index_t base_type; + typedef typename MapConfig:: + segment_manager_base segment_manager_base; + /// @endcond + + public: + //!Constructor. Takes a pointer to the + //!segment manager. Can throw + map_index(segment_manager_base *segment_mngr) + : base_type(typename index_aux::key_less(), + segment_mngr){} + + //!This reserves memory to optimize the insertion of n + //!elements in the index + void reserve(std::size_t) + { /*Does nothing, map has not reserve or rehash*/ } + + //!This tries to free previously allocate + //!unused memory. + void shrink_to_fit() + { base_type::get_stored_allocator().deallocate_free_blocks(); } +}; + +/// @cond + +//!Trait class to detect if an index is a node +//!index. This allows more efficient operations +//!when deallocating named objects. +template +struct is_node_index + > +{ + enum { value = true }; +}; +/// @endcond + +}} //namespace boost { namespace interprocess { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_MAP_INDEX_HPP diff --git a/win32/include/boost/interprocess/indexes/null_index.hpp b/win32/include/boost/interprocess/indexes/null_index.hpp new file mode 100755 index 000000000..1d9a2e7fa --- /dev/null +++ b/win32/include/boost/interprocess/indexes/null_index.hpp @@ -0,0 +1,68 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTERPROCESS_NULL_INDEX_HPP +#define BOOST_INTERPROCESS_NULL_INDEX_HPP + +#include +#include + +#include + +//!\file +//!Describes a null index adaptor, so that if we don't want to construct +//!named objects, we can use this null index type to save resources. + +namespace boost { +namespace interprocess { + +//!Null index type +//!used to save compilation time when +//!named indexes are not needed. +template +class null_index +{ + /// @cond + typedef typename MapConfig:: + segment_manager_base segment_manager_base; + /// @endcond + + public: + typedef void * iterator; + typedef const void * const_iterator; + + //!begin() is equal + //!to end() + const_iterator begin() const + { return const_iterator(0); } + + //!begin() is equal + //!to end() + iterator begin() + { return iterator(0); } + + //!begin() is equal + //!to end() + const_iterator end() const + { return const_iterator(0); } + + //!begin() is equal + //!to end() + iterator end() + { return iterator(0); } + + //!Empty constructor + null_index(segment_manager_base *){} +}; + +}} //namespace boost { namespace interprocess { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_NULL_INDEX_HPP diff --git a/win32/include/boost/interprocess/indexes/unordered_map_index.hpp b/win32/include/boost/interprocess/indexes/unordered_map_index.hpp new file mode 100755 index 000000000..8e7a9824c --- /dev/null +++ b/win32/include/boost/interprocess/indexes/unordered_map_index.hpp @@ -0,0 +1,113 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_UNORDERED_MAP_INDEX_HPP +#define BOOST_INTERPROCESS_UNORDERED_MAP_INDEX_HPP + +#include +#include + +#include +#include +#include +#include +#include + +//!\file +//!Describes index adaptor of boost::unordered_map container, to use it +//!as name/shared memory index + +namespace boost { +namespace interprocess { + +///@cond + +//!Helper class to define typedefs from +//!IndexTraits +template +struct unordered_map_index_aux +{ + typedef typename MapConfig::key_type key_type; + typedef typename MapConfig::mapped_type mapped_type; + typedef std::equal_to key_equal; + typedef std::pair value_type; + typedef private_adaptive_pool + allocator_type; + struct hasher + : std::unary_function + { + std::size_t operator()(const key_type &val) const + { + typedef typename key_type::char_type char_type; + const char_type *beg = detail::get_pointer(val.mp_str), + *end = beg + val.m_len; + return boost::hash_range(beg, end); + } + }; + typedef unordered_map index_t; +}; + +///@endcond + +//!Index type based in unordered_map. Just derives from unordered_map and +//!defines the interface needed by managed memory segments +template +class unordered_map_index + //Derive class from unordered_map specialization + : public unordered_map_index_aux::index_t +{ + /// @cond + typedef unordered_map_index_aux index_aux; + typedef typename index_aux::index_t base_type; + typedef typename + MapConfig::segment_manager_base segment_manager_base; + /// @endcond + + public: + //!Constructor. Takes a pointer to the + //!segment manager. Can throw + unordered_map_index(segment_manager_base *segment_mngr) + : base_type(0, + typename index_aux::hasher(), + typename index_aux::key_equal(), + segment_mngr){} + + //!This reserves memory to optimize the insertion of n + //!elements in the index + void reserve(std::size_t n) + { base_type::rehash(n); } + + //!This tries to free previously allocate + //!unused memory. + void shrink_to_fit() + { base_type::rehash(base_type::size()); } +}; + +/// @cond + +//!Trait class to detect if an index is a node +//!index. This allows more efficient operations +//!when deallocating named objects. +template +struct is_node_index + > +{ + enum { value = true }; +}; +/// @endcond + +}} //namespace boost { namespace interprocess { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_UNORDERED_MAP_INDEX_HPP diff --git a/win32/include/boost/interprocess/interprocess_fwd.hpp b/win32/include/boost/interprocess/interprocess_fwd.hpp new file mode 100755 index 000000000..296d090b4 --- /dev/null +++ b/win32/include/boost/interprocess/interprocess_fwd.hpp @@ -0,0 +1,474 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_FWD_HPP +#define BOOST_INTERPROCESS_FWD_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +//#include +//#include + +#include + +////////////////////////////////////////////////////////////////////////////// +// Standard predeclarations +////////////////////////////////////////////////////////////////////////////// + +/// @cond + +namespace boost{ +namespace intrusive{ +}} + +namespace boost{ +namespace interprocess{ +namespace bi = boost::intrusive; +}} + +namespace std { + +template +class allocator; + +template +struct less; + +template +struct pair; + +template +struct char_traits; + +} //namespace std { + +/// @endcond + +namespace boost { namespace interprocess { + +////////////////////////////////////////////////////////////////////////////// +// shared_memory +////////////////////////////////////////////////////////////////////////////// + +class shared_memory_object; + +#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) +class windows_shared_memory; +#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +////////////////////////////////////////////////////////////////////////////// +// mapped file/mapped region/mapped_file +////////////////////////////////////////////////////////////////////////////// + +class file_mapping; +class mapped_region; +class mapped_file; + +////////////////////////////////////////////////////////////////////////////// +// Mutexes +////////////////////////////////////////////////////////////////////////////// + +class null_mutex; + +class interprocess_mutex; +class interprocess_recursive_mutex; + +class named_mutex; +class named_recursive_mutex; + +class interprocess_semaphore; +class named_semaphore; + +////////////////////////////////////////////////////////////////////////////// +// Mutex families +////////////////////////////////////////////////////////////////////////////// + +struct mutex_family; +struct null_mutex_family; + +////////////////////////////////////////////////////////////////////////////// +// Other synchronization classes +////////////////////////////////////////////////////////////////////////////// + +class barrier; +class interprocess_sharable_mutex; +class interprocess_condition; + +////////////////////////////////////////////////////////////////////////////// +// Locks +////////////////////////////////////////////////////////////////////////////// + +template +class scoped_lock; + +template +class sharable_lock; + +////////////////////////////////////////////////////////////////////////////// +// STL compatible allocators +////////////////////////////////////////////////////////////////////////////// + +template +class allocator; + +template +class node_allocator; + +template +class private_node_allocator; + +template +class cached_node_allocator; + +template +class adaptive_pool; + +template +class private_adaptive_pool; + +template +class cached_adaptive_pool; + + +////////////////////////////////////////////////////////////////////////////// +// offset_ptr +////////////////////////////////////////////////////////////////////////////// + +template +class offset_ptr; + +////////////////////////////////////////////////////////////////////////////// +// Memory allocation algorithms +////////////////////////////////////////////////////////////////////////////// + +//Single segment memory allocation algorithms +template > +class simple_seq_fit; + +template, std::size_t MemAlignment = 0> +class rbtree_best_fit; + +////////////////////////////////////////////////////////////////////////////// +// Index Types +////////////////////////////////////////////////////////////////////////////// + +template class flat_map_index; +template class iset_index; +template class iunordered_set_index; +template class map_index; +template class null_index; +template class unordered_map_index; + +////////////////////////////////////////////////////////////////////////////// +// Segment manager +////////////////////////////////////////////////////////////////////////////// + +template class IndexType> +class segment_manager; + +////////////////////////////////////////////////////////////////////////////// +// External buffer managed memory classes +////////////////////////////////////////////////////////////////////////////// + +template class IndexType> +class basic_managed_external_buffer; + +typedef basic_managed_external_buffer + + ,iset_index> +managed_external_buffer; + +typedef basic_managed_external_buffer + + ,iset_index> +wmanaged_external_buffer; + +////////////////////////////////////////////////////////////////////////////// +// managed memory classes +////////////////////////////////////////////////////////////////////////////// + +template class IndexType> +class basic_managed_shared_memory; + +typedef basic_managed_shared_memory + + ,iset_index> +managed_shared_memory; + +typedef basic_managed_shared_memory + + ,iset_index> +wmanaged_shared_memory; + + +////////////////////////////////////////////////////////////////////////////// +// Windows shared memory managed memory classes +////////////////////////////////////////////////////////////////////////////// + +#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +template class IndexType> +class basic_managed_windows_shared_memory; + +typedef basic_managed_windows_shared_memory + + ,iset_index> +managed_windows_shared_memory; + +typedef basic_managed_windows_shared_memory + + ,iset_index> +wmanaged_windows_shared_memory; + +#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +////////////////////////////////////////////////////////////////////////////// +// Fixed address shared memory +////////////////////////////////////////////////////////////////////////////// + +typedef basic_managed_shared_memory + + ,iset_index> +fixed_managed_shared_memory; + +typedef basic_managed_shared_memory + + ,iset_index> +wfixed_managed_shared_memory; + +////////////////////////////////////////////////////////////////////////////// +// Heap memory managed memory classes +////////////////////////////////////////////////////////////////////////////// + +template + class IndexType> +class basic_managed_heap_memory; + +typedef basic_managed_heap_memory + + ,iset_index> +managed_heap_memory; + +typedef basic_managed_heap_memory + + ,iset_index> +wmanaged_heap_memory; + +////////////////////////////////////////////////////////////////////////////// +// Mapped file managed memory classes +////////////////////////////////////////////////////////////////////////////// + +template + class IndexType> +class basic_managed_mapped_file; + +typedef basic_managed_mapped_file + + ,iset_index> +managed_mapped_file; + +typedef basic_managed_mapped_file + + ,iset_index> +wmanaged_mapped_file; + +////////////////////////////////////////////////////////////////////////////// +// Exceptions +////////////////////////////////////////////////////////////////////////////// + +class interprocess_exception; +class lock_exception; +class bad_alloc; + +////////////////////////////////////////////////////////////////////////////// +// Bufferstream +////////////////////////////////////////////////////////////////////////////// + +//bufferstream +template > +class basic_bufferbuf; + +template > +class basic_ibufferstream; + +template > +class basic_obufferstream; + +template > +class basic_bufferstream; + +////////////////////////////////////////////////////////////////////////////// +// Vectorstream +////////////////////////////////////////////////////////////////////////////// + +template > +class basic_vectorbuf; + +template > +class basic_ivectorstream; + +template > +class basic_ovectorstream; + +template > +class basic_vectorstream; + +////////////////////////////////////////////////////////////////////////////// +// Smart pointers +////////////////////////////////////////////////////////////////////////////// + +template +class scoped_ptr; + +template +class intrusive_ptr; + +template +class shared_ptr; + +template +class weak_ptr; + +////////////////////////////////////////////////////////////////////////////// +// IPC +////////////////////////////////////////////////////////////////////////////// + +class message_queue; + +////////////////////////////////////////////////////////////////////////////// +// Containers +////////////////////////////////////////////////////////////////////////////// + +//vector class +template > +class vector; + +//list class +template > +class list; + +//slist class +template > +class slist; + +//set class +template + ,class Alloc = std::allocator > +class set; + +//multiset class +template + ,class Alloc = std::allocator > +class multiset; + +//map class +template + ,class Alloc = std::allocator > > +class map; + +//multimap class +template + ,class Alloc = std::allocator > > +class multimap; + +//flat_set class +template + ,class Alloc = std::allocator > +class flat_set; + +//flat_multiset class +template + ,class Alloc = std::allocator > +class flat_multiset; + +//flat_map class +template + ,class Alloc = std::allocator > > +class flat_map; + +//flat_multimap class +template + ,class Alloc = std::allocator > > +class flat_multimap; + +//basic_string class +template + ,class Alloc = std::allocator > +class basic_string; + +//string class +typedef basic_string + + ,std::allocator > +string; + +}} //namespace boost { namespace interprocess { + +//#include + +#endif //#ifndef BOOST_INTERPROCESS_FWD_HPP + diff --git a/win32/include/boost/interprocess/ipc/message_queue.hpp b/win32/include/boost/interprocess/ipc/message_queue.hpp new file mode 100755 index 000000000..89ffd9d82 --- /dev/null +++ b/win32/include/boost/interprocess/ipc/message_queue.hpp @@ -0,0 +1,619 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP +#define BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include //std::lower_bound +#include //std::size_t +#include //memcpy + + +//!\file +//!Describes an inter-process message queue. This class allows sending +//!messages between processes and allows blocking, non-blocking and timed +//!sending and receiving. + +namespace boost{ namespace interprocess{ + +//!A class that allows sending messages +//!between processes. +class message_queue +{ + /// @cond + //Blocking modes + enum block_t { blocking, timed, non_blocking }; + + message_queue(); + /// @endcond + + public: + + //!Creates a process shared message queue with name "name". For this message queue, + //!the maximum number of messages will be "max_num_msg" and the maximum message size + //!will be "max_msg_size". + message_queue(create_only_t create_only, + const char *name, + std::size_t max_num_msg, + std::size_t max_msg_size); + + //!Opens or creates a process shared message queue with name "name". + //!If the queue is created, the maximum number of messages will be "max_num_msg" + //!and the maximum message size will be "max_msg_size". If queue was previously + //!created the queue will be opened and "max_num_msg" and "max_msg_size" parameters + //!are ignored. + message_queue(open_or_create_t open_or_create, + const char *name, + std::size_t max_num_msg, + std::size_t max_msg_size); + + //!Opens a previously created process shared message queue with name "name". + //!If the was not previously created or there are no free resources, the + //!function returns false. + message_queue(open_only_t open_only, + const char *name); + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. All opened message queues are still + //!valid after destruction. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the message queue from the system + //!use remove(). + ~message_queue(); + + //!Sends a message stored in buffer "buffer" with size "buffer_size" in the + //!message queue with priority "priority". If the message queue is full + //!the sender is blocked. Throws interprocess_error on error.*/ + void send (const void *buffer, std::size_t buffer_size, + unsigned int priority); + + //!Sends a message stored in buffer "buffer" with size "buffer_size" through the + //!message queue with priority "priority". If the message queue is full + //!the sender is not blocked and returns false, otherwise returns true. + //!Throws interprocess_error on error. + bool try_send (const void *buffer, std::size_t buffer_size, + unsigned int priority); + + //!Sends a message stored in buffer "buffer" with size "buffer_size" in the + //!message queue with priority "priority". If the message queue is full + //!the sender retries until time "abs_time" is reached. Returns true if + //!the message has been successfully sent. Returns false if timeout is reached. + //!Throws interprocess_error on error. + bool timed_send (const void *buffer, std::size_t buffer_size, + unsigned int priority, const boost::posix_time::ptime& abs_time); + + //!Receives a message from the message queue. The message is stored in buffer + //!"buffer", which has size "buffer_size". The received message has size + //!"recvd_size" and priority "priority". If the message queue is empty + //!the receiver is blocked. Throws interprocess_error on error. + void receive (void *buffer, std::size_t buffer_size, + std::size_t &recvd_size,unsigned int &priority); + + //!Receives a message from the message queue. The message is stored in buffer + //!"buffer", which has size "buffer_size". The received message has size + //!"recvd_size" and priority "priority". If the message queue is empty + //!the receiver is not blocked and returns false, otherwise returns true. + //!Throws interprocess_error on error. + bool try_receive (void *buffer, std::size_t buffer_size, + std::size_t &recvd_size,unsigned int &priority); + + //!Receives a message from the message queue. The message is stored in buffer + //!"buffer", which has size "buffer_size". The received message has size + //!"recvd_size" and priority "priority". If the message queue is empty + //!the receiver retries until time "abs_time" is reached. Returns true if + //!the message has been successfully sent. Returns false if timeout is reached. + //!Throws interprocess_error on error. + bool timed_receive (void *buffer, std::size_t buffer_size, + std::size_t &recvd_size,unsigned int &priority, + const boost::posix_time::ptime &abs_time); + + //!Returns the maximum number of messages allowed by the queue. The message + //!queue must be opened or created previously. Otherwise, returns 0. + //!Never throws + std::size_t get_max_msg() const; + + //!Returns the maximum size of message allowed by the queue. The message + //!queue must be opened or created previously. Otherwise, returns 0. + //!Never throws + std::size_t get_max_msg_size() const; + + //!Returns the number of messages currently stored. + //!Never throws + std::size_t get_num_msg(); + + //!Removes the message queue from the system. + //!Returns false on error. Never throws + static bool remove(const char *name); + + /// @cond + private: + typedef boost::posix_time::ptime ptime; + bool do_receive(block_t block, + void *buffer, std::size_t buffer_size, + std::size_t &recvd_size, unsigned int &priority, + const ptime &abs_time); + + bool do_send(block_t block, + const void *buffer, std::size_t buffer_size, + unsigned int priority, const ptime &abs_time); + + //!Returns the needed memory size for the shared message queue. + //!Never throws + static std::size_t get_mem_size(std::size_t max_msg_size, std::size_t max_num_msg); + + detail::managed_open_or_create_impl m_shmem; + /// @endcond +}; + +/// @cond + +namespace detail { + +//!This header is the prefix of each message in the queue +class msg_hdr_t +{ + public: + std::size_t len; // Message length + unsigned int priority;// Message priority + //!Returns the data buffer associated with this this message + void * data(){ return this+1; } // +}; + +//!This functor is the predicate to order stored messages by priority +class priority_functor +{ + public: + bool operator()(const offset_ptr &msg1, + const offset_ptr &msg2) const + { return msg1->priority < msg2->priority; } +}; + +//!This header is placed in the beginning of the shared memory and contains +//!the data to control the queue. This class initializes the shared memory +//!in the following way: in ascending memory address with proper alignment +//!fillings: +//! +//!-> mq_hdr_t: +//! Main control block that controls the rest of the elements +//! +//!-> offset_ptr index [max_num_msg] +//! An array of pointers with size "max_num_msg" called index. Each pointer +//! points to a preallocated message. The elements of this array are +//! reordered in runtime in the following way: +//! +//! When the current number of messages is "cur_num_msg", the first +//! "cur_num_msg" pointers point to inserted messages and the rest +//! point to free messages. The first "cur_num_msg" pointers are +//! ordered by the priority of the pointed message and by insertion order +//! if two messages have the same priority. So the next message to be +//! used in a "receive" is pointed by index [cur_num_msg-1] and the first free +//! message ready to be used in a "send" operation is index [cur_num_msg]. +//! This transforms index in a fixed size priority queue with an embedded free +//! message queue. +//! +//!-> struct message_t +//! { +//! msg_hdr_t header; +//! char[max_msg_size] data; +//! } messages [max_num_msg]; +//! +//! An array of buffers of preallocated messages, each one prefixed with the +//! msg_hdr_t structure. Each of this message is pointed by one pointer of +//! the index structure. +class mq_hdr_t + : public detail::priority_functor +{ + typedef offset_ptr msg_hdr_ptr_t; + public: + //!Constructor. This object must be constructed in the beginning of the + //!shared memory of the size returned by the function "get_mem_size". + //!This constructor initializes the needed resources and creates + //!the internal structures like the priority index. This can throw.*/ + mq_hdr_t(std::size_t max_num_msg, std::size_t max_msg_size) + : m_max_num_msg(max_num_msg), + m_max_msg_size(max_msg_size), + m_cur_num_msg(0) + { this->initialize_memory(); } + + //!Returns the inserted message with top priority + msg_hdr_t * top_msg() + { return mp_index[m_cur_num_msg-1].get(); } + + //!Returns true if the message queue is full + bool is_full() const + { return m_cur_num_msg == m_max_num_msg; } + + //!Returns true if the message queue is empty + bool is_empty() const + { return !m_cur_num_msg; } + + //!Frees the top priority message and saves it in the free message list + void free_top_msg() + { --m_cur_num_msg; } + + //!Returns the first free msg of the free message queue + msg_hdr_t * free_msg() + { return mp_index[m_cur_num_msg].get(); } + + //!Inserts the first free message in the priority queue + void queue_free_msg() + { + //Get free msg + msg_hdr_ptr_t free = mp_index[m_cur_num_msg]; + //Get priority queue's range + msg_hdr_ptr_t *it = &mp_index[0], *it_end = &mp_index[m_cur_num_msg]; + //Check where the free message should be placed + it = std::lower_bound(it, it_end, free, static_cast(*this)); + //Make room in that position + std::copy_backward(it, it_end, it_end+1); + //Insert the free message in the correct position + *it = free; + ++m_cur_num_msg; + } + + //!Returns the number of bytes needed to construct a message queue with + //!"max_num_size" maximum number of messages and "max_msg_size" maximum + //!message size. Never throws. + static std::size_t get_mem_size + (std::size_t max_msg_size, std::size_t max_num_msg) + { + const std::size_t + msg_hdr_align = detail::alignment_of::value, + index_align = detail::alignment_of::value, + r_hdr_size = detail::ct_rounded_size::value, + r_index_size = detail::get_rounded_size(sizeof(msg_hdr_ptr_t)*max_num_msg, msg_hdr_align), + r_max_msg_size = detail::get_rounded_size(max_msg_size, msg_hdr_align) + sizeof(detail::msg_hdr_t); + return r_hdr_size + r_index_size + (max_num_msg*r_max_msg_size) + + detail::managed_open_or_create_impl::ManagedOpenOrCreateUserOffset; + } + + //!Initializes the memory structures to preallocate messages and constructs the + //!message index. Never throws. + void initialize_memory() + { + const std::size_t + msg_hdr_align = detail::alignment_of::value, + index_align = detail::alignment_of::value, + r_hdr_size = detail::ct_rounded_size::value, + r_index_size = detail::get_rounded_size(sizeof(msg_hdr_ptr_t)*m_max_num_msg, msg_hdr_align), + r_max_msg_size = detail::get_rounded_size(m_max_msg_size, msg_hdr_align) + sizeof(detail::msg_hdr_t); + + //Pointer to the index + msg_hdr_ptr_t *index = reinterpret_cast + (detail::char_ptr_cast(this)+r_hdr_size); + + //Pointer to the first message header + detail::msg_hdr_t *msg_hdr = reinterpret_cast + (detail::char_ptr_cast(this)+r_hdr_size+r_index_size); + + //Initialize the pointer to the index + mp_index = index; + + //Initialize the index so each slot points to a preallocated message + for(std::size_t i = 0; i < m_max_num_msg; ++i){ + index[i] = msg_hdr; + msg_hdr = reinterpret_cast + (detail::char_ptr_cast(msg_hdr)+r_max_msg_size); + } + } + + public: + //Pointer to the index + offset_ptr mp_index; + //Maximum number of messages of the queue + const std::size_t m_max_num_msg; + //Maximum size of messages of the queue + const std::size_t m_max_msg_size; + //Current number of messages + std::size_t m_cur_num_msg; + //Mutex to protect data structures + interprocess_mutex m_mutex; + //Condition block receivers when there are no messages + interprocess_condition m_cond_recv; + //Condition block senders when the queue is full + interprocess_condition m_cond_send; +}; + + +//!This is the atomic functor to be executed when creating or opening +//!shared memory. Never throws +class initialization_func_t +{ + public: + initialization_func_t(std::size_t maxmsg = 0, + std::size_t maxmsgsize = 0) + : m_maxmsg (maxmsg), m_maxmsgsize(maxmsgsize) {} + + bool operator()(void *address, std::size_t, bool created) + { + char *mptr; + + if(created){ + mptr = reinterpret_cast(address); + //Construct the message queue header at the beginning + BOOST_TRY{ + new (mptr) mq_hdr_t(m_maxmsg, m_maxmsgsize); + } + BOOST_CATCH(...){ + return false; + } + BOOST_CATCH_END + } + return true; + } + const std::size_t m_maxmsg; + const std::size_t m_maxmsgsize; +}; + +} //namespace detail { + +inline message_queue::~message_queue() +{} + +inline std::size_t message_queue::get_mem_size + (std::size_t max_msg_size, std::size_t max_num_msg) +{ return detail::mq_hdr_t::get_mem_size(max_msg_size, max_num_msg); } + +inline message_queue::message_queue(create_only_t create_only, + const char *name, + std::size_t max_num_msg, + std::size_t max_msg_size) + //Create shared memory and execute functor atomically + : m_shmem(create_only, + name, + get_mem_size(max_msg_size, max_num_msg), + read_write, + (void*)0, + //Prepare initialization functor + detail::initialization_func_t (max_num_msg, max_msg_size)) +{} + +inline message_queue::message_queue(open_or_create_t open_or_create, + const char *name, + std::size_t max_num_msg, + std::size_t max_msg_size) + //Create shared memory and execute functor atomically + : m_shmem(open_or_create, + name, + get_mem_size(max_msg_size, max_num_msg), + read_write, + (void*)0, + //Prepare initialization functor + detail::initialization_func_t (max_num_msg, max_msg_size)) +{} + +inline message_queue::message_queue(open_only_t open_only, + const char *name) + //Create shared memory and execute functor atomically + : m_shmem(open_only, + name, + read_write, + (void*)0, + //Prepare initialization functor + detail::initialization_func_t ()) +{} + +inline void message_queue::send + (const void *buffer, std::size_t buffer_size, unsigned int priority) +{ this->do_send(blocking, buffer, buffer_size, priority, ptime()); } + +inline bool message_queue::try_send + (const void *buffer, std::size_t buffer_size, unsigned int priority) +{ return this->do_send(non_blocking, buffer, buffer_size, priority, ptime()); } + +inline bool message_queue::timed_send + (const void *buffer, std::size_t buffer_size + ,unsigned int priority, const boost::posix_time::ptime &abs_time) +{ return this->do_send(timed, buffer, buffer_size, priority, abs_time); } + +inline bool message_queue::do_send(block_t block, + const void *buffer, std::size_t buffer_size, + unsigned int priority, const boost::posix_time::ptime &abs_time) +{ + detail::mq_hdr_t *p_hdr = static_cast(m_shmem.get_user_address()); + //Check if buffer is smaller than maximum allowed + if (buffer_size > p_hdr->m_max_msg_size) { + throw interprocess_exception(size_error); + } + + //--------------------------------------------- + scoped_lock lock(p_hdr->m_mutex); + //--------------------------------------------- + { + //If the queue is full execute blocking logic + if (p_hdr->is_full()) { + + switch(block){ + case non_blocking : + return false; + break; + + case blocking : + do{ + p_hdr->m_cond_send.wait(lock); + } + while (p_hdr->is_full()); + break; + + case timed : + do{ + if(!p_hdr->m_cond_send.timed_wait(lock, abs_time)) + return !p_hdr->is_full(); + } + while (p_hdr->is_full()); + break; + default: + throw interprocess_exception(); + } + } + + //Get the first free message from free message queue + detail::msg_hdr_t *free_msg = p_hdr->free_msg(); + if (free_msg == 0) { + throw interprocess_exception(); + } + + //Copy control data to the free message + free_msg->priority = priority; + free_msg->len = buffer_size; + + //Copy user buffer to the message + std::memcpy(free_msg->data(), buffer, buffer_size); + +// bool was_empty = p_hdr->is_empty(); + //Insert the first free message in the priority queue + p_hdr->queue_free_msg(); + + //If this message changes the queue empty state, notify it to receivers +// if (was_empty){ + p_hdr->m_cond_recv.notify_one(); +// } + } // Lock end + + return true; +} + +inline void message_queue::receive(void *buffer, std::size_t buffer_size, + std::size_t &recvd_size, unsigned int &priority) +{ this->do_receive(blocking, buffer, buffer_size, recvd_size, priority, ptime()); } + +inline bool + message_queue::try_receive(void *buffer, std::size_t buffer_size, + std::size_t &recvd_size, unsigned int &priority) +{ return this->do_receive(non_blocking, buffer, buffer_size, recvd_size, priority, ptime()); } + +inline bool + message_queue::timed_receive(void *buffer, std::size_t buffer_size, + std::size_t &recvd_size, unsigned int &priority, + const boost::posix_time::ptime &abs_time) +{ return this->do_receive(timed, buffer, buffer_size, recvd_size, priority, abs_time); } + +inline bool + message_queue::do_receive(block_t block, + void *buffer, std::size_t buffer_size, + std::size_t &recvd_size, unsigned int &priority, + const boost::posix_time::ptime &abs_time) +{ + detail::mq_hdr_t *p_hdr = static_cast(m_shmem.get_user_address()); + //Check if buffer is big enough for any message + if (buffer_size < p_hdr->m_max_msg_size) { + throw interprocess_exception(size_error); + } + + //--------------------------------------------- + scoped_lock lock(p_hdr->m_mutex); + //--------------------------------------------- + { + //If there are no messages execute blocking logic + if (p_hdr->is_empty()) { + switch(block){ + case non_blocking : + return false; + break; + + case blocking : + do{ + p_hdr->m_cond_recv.wait(lock); + } + while (p_hdr->is_empty()); + break; + + case timed : + do{ + if(!p_hdr->m_cond_recv.timed_wait(lock, abs_time)) + return !p_hdr->is_empty(); + } + while (p_hdr->is_empty()); + break; + + //Paranoia check + default: + throw interprocess_exception(); + } + } + + //Thre is at least message ready to pick, get the top one + detail::msg_hdr_t *top_msg = p_hdr->top_msg(); + + //Paranoia check + if (top_msg == 0) { + throw interprocess_exception(); + } + + //Get data from the message + recvd_size = top_msg->len; + priority = top_msg->priority; + + //Copy data to receiver's bufers + std::memcpy(buffer, top_msg->data(), recvd_size); + +// bool was_full = p_hdr->is_full(); + + //Free top message and put it in the free message list + p_hdr->free_top_msg(); + + //If this reception changes the queue full state, notify senders +// if (was_full){ + p_hdr->m_cond_send.notify_one(); +// } + } //Lock end + + return true; +} + +inline std::size_t message_queue::get_max_msg() const +{ + detail::mq_hdr_t *p_hdr = static_cast(m_shmem.get_user_address()); + return p_hdr ? p_hdr->m_max_num_msg : 0; } + +inline std::size_t message_queue::get_max_msg_size() const +{ + detail::mq_hdr_t *p_hdr = static_cast(m_shmem.get_user_address()); + return p_hdr ? p_hdr->m_max_msg_size : 0; +} + +inline std::size_t message_queue::get_num_msg() +{ + detail::mq_hdr_t *p_hdr = static_cast(m_shmem.get_user_address()); + if(p_hdr){ + //--------------------------------------------- + scoped_lock lock(p_hdr->m_mutex); + //--------------------------------------------- + return p_hdr->m_cur_num_msg; + } + + return 0; +} + +inline bool message_queue::remove(const char *name) +{ return shared_memory_object::remove(name); } + +/// @endcond + +}} //namespace boost{ namespace interprocess{ + +#include + +#endif //#ifndef BOOST_INTERPROCESS_MESSAGE_QUEUE_HPP diff --git a/win32/include/boost/interprocess/managed_external_buffer.hpp b/win32/include/boost/interprocess/managed_external_buffer.hpp new file mode 100755 index 000000000..ea405f588 --- /dev/null +++ b/win32/include/boost/interprocess/managed_external_buffer.hpp @@ -0,0 +1,135 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MANAGED_EXTERNAL_BUFFER_HPP +#define BOOST_INTERPROCESS_MANAGED_EXTERNAL_BUFFER_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a named user memory allocation user class. + +namespace boost { +namespace interprocess { + +//!A basic user memory named object creation class. Inherits all +//!basic functionality from +//!basic_managed_memory_impl*/ +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +class basic_managed_external_buffer + : public detail::basic_managed_memory_impl +{ + /// @cond + typedef detail::basic_managed_memory_impl + base_t; + /// @endcond + + public: + + //!Default constructor. Does nothing. + //!Useful in combination with move semantics + basic_managed_external_buffer() + {} + + //!Creates and places the segment manager. This can throw + basic_managed_external_buffer + (create_only_t, void *addr, std::size_t size) + { + //Check if alignment is correct + assert((0 == (((std::size_t)addr) & (AllocationAlgorithm::Alignment - std::size_t(1u))))); + if(!base_t::create_impl(addr, size)){ + throw interprocess_exception(); + } + } + + //!Creates and places the segment manager. This can throw + basic_managed_external_buffer + (open_only_t, void *addr, std::size_t size) + { + //Check if alignment is correct + assert((0 == (((std::size_t)addr) & (AllocationAlgorithm::Alignment - std::size_t(1u))))); + if(!base_t::open_impl(addr, size)){ + throw interprocess_exception(); + } + } + + //!Moves the ownership of "moved"'s managed memory to *this. Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_managed_external_buffer + (detail::moved_object moved) + { this->swap(moved.get()); } + #else + basic_managed_external_buffer + (basic_managed_external_buffer &&moved) + { this->swap(moved); } + #endif + + //!Moves the ownership of "moved"'s managed memory to *this. Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_managed_external_buffer &operator= + (detail::moved_object moved) + { this->swap(moved.get()); return *this; } + #else + basic_managed_external_buffer &operator= + (basic_managed_external_buffer &&moved) + { this->swap(moved); return *this; } + #endif + + void grow(std::size_t extra_bytes) + { base_t::grow(extra_bytes); } + + //!Swaps the ownership of the managed heap memories managed by *this and other. + //!Never throws. + void swap(basic_managed_external_buffer &other) + { base_t::swap(other); } + +}; + +///@cond + +//!Trait class to detect if a type is +//!movable +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +struct is_movable +> +{ + static const bool value = true; +}; + +///@endcond + + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MANAGED_EXTERNAL_BUFFER_HPP + diff --git a/win32/include/boost/interprocess/managed_heap_memory.hpp b/win32/include/boost/interprocess/managed_heap_memory.hpp new file mode 100755 index 000000000..ba67f025e --- /dev/null +++ b/win32/include/boost/interprocess/managed_heap_memory.hpp @@ -0,0 +1,169 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MANAGED_HEAP_MEMORY_HPP +#define BOOST_INTERPROCESS_MANAGED_HEAP_MEMORY_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a named heap memory allocation user class. + +namespace boost { +namespace interprocess { + +//!A basic heap memory named object creation class. Initializes the +//!heap memory segment. Inherits all basic functionality from +//!basic_managed_memory_impl*/ +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +class basic_managed_heap_memory + : public detail::basic_managed_memory_impl +{ + /// @cond + private: + + typedef detail::basic_managed_memory_impl + base_t; + /// @endcond + + public: //functions + + //!Default constructor. Does nothing. + //!Useful in combination with move semantics + basic_managed_heap_memory(){} + + //!Destructor. Liberates the heap memory holding the managed data. + //!Never throws. + ~basic_managed_heap_memory() + { this->priv_close(); } + + //!Creates heap memory and initializes the segment manager. + //!This can throw. + basic_managed_heap_memory(std::size_t size) + : m_heapmem(size, char(0)) + { + if(!base_t::create_impl(&m_heapmem[0], size)){ + this->priv_close(); + throw interprocess_exception(); + } + } + + //!Moves the ownership of "moved"'s managed memory to *this. Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_managed_heap_memory + (detail::moved_object moved) + { this->swap(moved.get()); } + #else + basic_managed_heap_memory(basic_managed_heap_memory &&moved) + { this->swap(moved); } + #endif + + //!Moves the ownership of "moved"'s managed memory to *this. Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_managed_heap_memory &operator= + (detail::moved_object moved) + { this->swap(moved.get()); return *this; } + #else + basic_managed_heap_memory &operator= + (basic_managed_heap_memory &&moved) + { this->swap(moved); return *this; } + #endif + + //!Tries to resize internal heap memory so that + //!we have room for more objects. + //!WARNING: If memory is reallocated, all the objects will + //!be binary-copied to the new buffer. To be able to use + //!this function, all pointers constructed in this buffer + //!must be offset pointers. Otherwise, the result is undefined. + //!Returns true if the growth has been successful, so you will + //!have some extra bytes to allocate new objects. If returns + //!false, the heap allocation has failed. + bool grow(std::size_t extra_bytes) + { + //If memory is reallocated, data will + //be automatically copied + BOOST_TRY{ + m_heapmem.resize(m_heapmem.size()+extra_bytes); + } + BOOST_CATCH(...){ + return false; + } + BOOST_CATCH_END + + //Grow always works + base_t::close_impl(); + base_t::open_impl(&m_heapmem[0], m_heapmem.size()); + base_t::grow(extra_bytes); + return true; + } + + //!Swaps the ownership of the managed heap memories managed by *this and other. + //!Never throws. + void swap(basic_managed_heap_memory &other) + { + base_t::swap(other); + m_heapmem.swap(other.m_heapmem); + } + + /// @cond + private: + //!Frees resources. Never throws. + void priv_close() + { + base_t::destroy_impl(); + std::vector().swap(m_heapmem); + } + + std::vector m_heapmem; + /// @endcond +}; + +///@cond + +//!Trait class to detect if a type is +//!movable +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +struct is_movable +> +{ + static const bool value = true; +}; + +///@endcond + +} //namespace interprocess { + +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MANAGED_HEAP_MEMORY_HPP + diff --git a/win32/include/boost/interprocess/managed_mapped_file.hpp b/win32/include/boost/interprocess/managed_mapped_file.hpp new file mode 100755 index 000000000..eb0319030 --- /dev/null +++ b/win32/include/boost/interprocess/managed_mapped_file.hpp @@ -0,0 +1,230 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MANAGED_MAPPED_FILE_HPP +#define BOOST_INTERPROCESS_MANAGED_MAPPED_FILE_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { + +//!A basic mapped file named object creation class. Initializes the +//!mapped file. Inherits all basic functionality from +//!basic_managed_memory_impl +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +class basic_managed_mapped_file + : public detail::basic_managed_memory_impl + ::ManagedOpenOrCreateUserOffset> +{ + /// @cond + public: + typedef detail::basic_managed_memory_impl + ::ManagedOpenOrCreateUserOffset> base_t; + typedef detail::file_wrapper device_type; + + private: + + typedef detail::create_open_func create_open_func_t; + typedef detail::managed_open_or_create_impl managed_open_or_create_type; + + basic_managed_mapped_file *get_this_pointer() + { return this; } + + private: + typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; + /// @endcond + + public: //functions + + //!Creates mapped file and creates and places the segment manager. + //!This can throw. + basic_managed_mapped_file() + {} + + //!Creates mapped file and creates and places the segment manager. + //!This can throw. + basic_managed_mapped_file(create_only_t create_only, const char *name, + std::size_t size, const void *addr = 0) + : m_mfile(create_only, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), detail::DoCreate)) + {} + + //!Creates mapped file and creates and places the segment manager if + //!segment was not created. If segment was created it connects to the + //!segment. + //!This can throw. + basic_managed_mapped_file (open_or_create_t open_or_create, + const char *name, std::size_t size, + const void *addr = 0) + : m_mfile(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), + detail::DoOpenOrCreate)) + {} + + //!Connects to a created mapped file and its segment manager. + //!This can throw. + basic_managed_mapped_file (open_only_t open_only, const char* name, + const void *addr = 0) + : m_mfile(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), + detail::DoOpen)) + {} + + //!Connects to a created mapped file and its segment manager + //!in copy_on_write mode. + //!This can throw. + basic_managed_mapped_file (open_copy_on_write_t, const char* name, + const void *addr = 0) + : m_mfile(open_only, name, copy_on_write, addr, + create_open_func_t(get_this_pointer(), + detail::DoOpen)) + {} + + //!Connects to a created mapped file and its segment manager + //!in read-only mode. + //!This can throw. + basic_managed_mapped_file (open_read_only_t, const char* name, + const void *addr = 0) + : m_mfile(open_only, name, read_only, addr, + create_open_func_t(get_this_pointer(), + detail::DoOpen)) + {} + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_managed_mapped_file + (detail::moved_object moved) + { this->swap(moved.get()); } + #else + basic_managed_mapped_file(basic_managed_mapped_file &&moved) + { this->swap(moved); } + #endif + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_managed_mapped_file &operator= + (detail::moved_object moved) + { this->swap(moved.get()); return *this; } + #else + basic_managed_mapped_file &operator=(basic_managed_mapped_file &&moved) + { this->swap(moved); return *this; } + #endif + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~basic_managed_mapped_file() + {} + + //!Swaps the ownership of the managed mapped memories managed by *this and other. + //!Never throws. + void swap(basic_managed_mapped_file &other) + { + base_t::swap(other); + m_mfile.swap(other.m_mfile); + } + + //!Flushes cached data to file. + //!Never throws + bool flush() + { return m_mfile.flush(); } + + //!Tries to resize mapped file so that we have room for + //!more objects. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + static bool grow(const char *filename, std::size_t extra_bytes) + { + return base_t::template grow + (filename, extra_bytes); + } + + //!Tries to resize mapped file to minimized the size of the file. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + static bool shrink_to_fit(const char *filename) + { + return base_t::template shrink_to_fit + (filename); + } + + /// @cond + + //!Tries to find a previous named allocation address. Returns a memory + //!buffer and the object count. If not found returned pointer is 0. + //!Never throws. + template + std::pair find (char_ptr_holder_t name) + { + if(m_mfile.get_mapped_region().get_mode() == read_only){ + return base_t::template find_no_lock(name); + } + else{ + return base_t::template find(name); + } + } + + private: + managed_open_or_create_type m_mfile; + /// @endcond +}; + +///@cond + +//!Trait class to detect if a type is +//!movable +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +struct is_movable +> +{ + static const bool value = true; +}; + +///@endcond + +} //namespace interprocess { + +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MANAGED_MAPPED_FILE_HPP diff --git a/win32/include/boost/interprocess/managed_shared_memory.hpp b/win32/include/boost/interprocess/managed_shared_memory.hpp new file mode 100755 index 000000000..8cdfccb4e --- /dev/null +++ b/win32/include/boost/interprocess/managed_shared_memory.hpp @@ -0,0 +1,230 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP +#define BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include + +namespace boost { + +namespace interprocess { + +//!A basic shared memory named object creation class. Initializes the +//!shared memory segment. Inherits all basic functionality from +//!basic_managed_memory_impl*/ +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +class basic_managed_shared_memory + : public detail::basic_managed_memory_impl + ::ManagedOpenOrCreateUserOffset> + , private detail::managed_open_or_create_impl +{ + /// @cond + public: + typedef shared_memory_object device_type; + + private: + typedef detail::basic_managed_memory_impl + ::ManagedOpenOrCreateUserOffset> base_t; + typedef detail::managed_open_or_create_impl + base2_t; + + typedef detail::create_open_func create_open_func_t; + + basic_managed_shared_memory *get_this_pointer() + { return this; } + + private: + typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; + /// @endcond + + public: //functions + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~basic_managed_shared_memory() + {} + + //!Default constructor. Does nothing. + //!Useful in combination with move semantics + basic_managed_shared_memory() + {} + + //!Creates shared memory and creates and places the segment manager. + //!This can throw. + basic_managed_shared_memory(create_only_t create_only, const char *name, + std::size_t size, const void *addr = 0) + : base_t() + , base2_t(create_only, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), detail::DoCreate)) + {} + + //!Creates shared memory and creates and places the segment manager if + //!segment was not created. If segment was created it connects to the + //!segment. + //!This can throw. + basic_managed_shared_memory (open_or_create_t open_or_create, + const char *name, std::size_t size, + const void *addr = 0) + : base_t() + , base2_t(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), + detail::DoOpenOrCreate)) + {} + + //!Connects to a created shared memory and its segment manager. + //!in copy_on_write mode. + //!This can throw. + basic_managed_shared_memory (open_copy_on_write_t, const char* name, + const void *addr = 0) + : base_t() + , base2_t(open_only, name, copy_on_write, addr, + create_open_func_t(get_this_pointer(), + detail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager. + //!in read-only mode. + //!This can throw. + basic_managed_shared_memory (open_read_only_t, const char* name, + const void *addr = 0) + : base_t() + , base2_t(open_only, name, read_only, addr, + create_open_func_t(get_this_pointer(), + detail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager. + //!This can throw. + basic_managed_shared_memory (open_only_t open_only, const char* name, + const void *addr = 0) + : base_t() + , base2_t(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), + detail::DoOpen)) + {} + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_managed_shared_memory + (detail::moved_object moved) + { this->swap(moved.get()); } + #else + basic_managed_shared_memory(basic_managed_shared_memory &&moved) + { this->swap(moved); } + #endif + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_managed_shared_memory &operator= + (detail::moved_object moved) + { this->swap(moved.get()); return *this; } + #else + basic_managed_shared_memory &operator=(basic_managed_shared_memory &&moved) + { this->swap(moved); return *this; } + #endif + + //!Swaps the ownership of the managed shared memories managed by *this and other. + //!Never throws. + void swap(basic_managed_shared_memory &other) + { + base_t::swap(other); + base2_t::swap(other); + } + + //!Tries to resize the managed shared memory object so that we have + //!room for more objects. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + static bool grow(const char *filename, std::size_t extra_bytes) + { + return base_t::template grow + (filename, extra_bytes); + } + + //!Tries to resize the managed shared memory to minimized the size of the file. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + static bool shrink_to_fit(const char *filename) + { + return base_t::template shrink_to_fit + (filename); + } + + /// @cond + + //!Tries to find a previous named allocation address. Returns a memory + //!buffer and the object count. If not found returned pointer is 0. + //!Never throws. + template + std::pair find (char_ptr_holder_t name) + { + if(base2_t::get_mapped_region().get_mode() == read_only){ + return base_t::template find_no_lock(name); + } + else{ + return base_t::template find(name); + } + } + + /// @endcond +}; + +///@cond + +//!Trait class to detect if a type is +//!movable +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +struct is_movable +> +{ + static const bool value = true; +}; + +///@endcond + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MANAGED_SHARED_MEMORY_HPP + diff --git a/win32/include/boost/interprocess/managed_windows_shared_memory.hpp b/win32/include/boost/interprocess/managed_windows_shared_memory.hpp new file mode 100755 index 000000000..149007492 --- /dev/null +++ b/win32/include/boost/interprocess/managed_windows_shared_memory.hpp @@ -0,0 +1,205 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MANAGED_WINDOWS_SHARED_MEMORY_HPP +#define BOOST_INTERPROCESS_MANAGED_WINDOWS_SHARED_MEMORY_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { + +//!A basic managed windows shared memory creation class. Initializes the +//!shared memory segment. Inherits all basic functionality from +//!basic_managed_memory_impl +//!Unlike basic_managed_shared_memory, it has +//!no kernel persistence and the shared memory is destroyed +//!when all processes destroy all their windows_shared_memory +//!objects and mapped regions for the same shared memory +//!or the processes end/crash. +//! +//!Warning: basic_managed_windows_shared_memory and +//!basic_managed_shared_memory can't communicate between them. +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +class basic_managed_windows_shared_memory + : public detail::basic_managed_memory_impl + ::ManagedOpenOrCreateUserOffset> +{ + /// @cond + private: + typedef detail::basic_managed_memory_impl + ::ManagedOpenOrCreateUserOffset> base_t; + typedef detail::create_open_func create_open_func_t; + + basic_managed_windows_shared_memory *get_this_pointer() + { return this; } + + private: + typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; + /// @endcond + + public: //functions + + //!Default constructor. Does nothing. + //!Useful in combination with move semantics + basic_managed_windows_shared_memory() + {} + + //!Creates shared memory and creates and places the segment manager. + //!This can throw. + basic_managed_windows_shared_memory + (create_only_t create_only, const char *name, + std::size_t size, const void *addr = 0) + : m_wshm(create_only, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), detail::DoCreate)) + {} + + //!Creates shared memory and creates and places the segment manager if + //!segment was not created. If segment was created it connects to the + //!segment. + //!This can throw. + basic_managed_windows_shared_memory + (open_or_create_t open_or_create, + const char *name, std::size_t size, + const void *addr = 0) + : m_wshm(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), + detail::DoOpenOrCreate)) + {} + + //!Connects to a created shared memory and its segment manager. + //!This can throw. + basic_managed_windows_shared_memory + (open_only_t open_only, const char* name, const void *addr = 0) + : m_wshm(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), + detail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager + //!in copy_on_write mode. + //!This can throw. + basic_managed_windows_shared_memory + (open_copy_on_write_t, const char* name, const void *addr = 0) + : m_wshm(open_only, name, copy_on_write, addr, + create_open_func_t(get_this_pointer(), detail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager + //!in read-only mode. + //!This can throw. + basic_managed_windows_shared_memory + (open_read_only_t, const char* name, const void *addr = 0) + : base_t() + , m_wshm(open_only, name, read_only, addr, + create_open_func_t(get_this_pointer(), detail::DoOpen)) + {} + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_managed_windows_shared_memory + (detail::moved_object moved) + { this->swap(moved.get()); } + #else + basic_managed_windows_shared_memory(basic_managed_windows_shared_memory &&moved) + { this->swap(moved); } + #endif + + //!Moves the ownership of "moved"'s managed memory to *this. + //!Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + basic_managed_windows_shared_memory &operator= + (detail::moved_object moved) + { this->swap(moved.get()); return *this; } + #else + basic_managed_windows_shared_memory &operator= + (basic_managed_windows_shared_memory &&moved) + { this->swap(moved); return *this; } + #endif + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. All mapped regions are still valid after + //!destruction. When all mapped regions and basic_managed_windows_shared_memory + //!objects referring the shared memory are destroyed, the + //!operating system will destroy the shared memory. + ~basic_managed_windows_shared_memory() + {} + + //!Swaps the ownership of the managed mapped memories managed by *this and other. + //!Never throws. + void swap(basic_managed_windows_shared_memory &other) + { + base_t::swap(other); + m_wshm.swap(other.m_wshm); + } + /// @cond + + //!Tries to find a previous named allocation address. Returns a memory + //!buffer and the object count. If not found returned pointer is 0. + //!Never throws. + template + std::pair find (char_ptr_holder_t name) + { + if(m_wshm.get_mapped_region().get_mode() == read_only){ + return base_t::template find_no_lock(name); + } + else{ + return base_t::template find(name); + } + } + + private: + detail::managed_open_or_create_impl m_wshm; + /// @endcond +}; + +///@cond + +//!Trait class to detect if a type is +//!movable +template + < + class CharType, + class AllocationAlgorithm, + template class IndexType + > +struct is_movable +> +{ + static const bool value = true; +}; + +///@endcond + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MANAGED_WINDOWS_SHARED_MEMORY_HPP diff --git a/win32/include/boost/interprocess/mapped_region.hpp b/win32/include/boost/interprocess/mapped_region.hpp new file mode 100755 index 000000000..9b904f909 --- /dev/null +++ b/win32/include/boost/interprocess/mapped_region.hpp @@ -0,0 +1,583 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MAPPED_REGION_HPP +#define BOOST_INTERPROCESS_MAPPED_REGION_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) +# include +#else +# ifdef BOOST_HAS_UNISTD_H +# include +# include //mmap +# include +# include +# include +# else +# error Unknown platform +# endif + +#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +//!\file +//!Describes memory_mappable and mapped region classes + +namespace boost { +namespace interprocess { + +/// @cond +namespace detail{ class interprocess_tester; } +namespace detail{ class raw_mapped_region_creator; } + +/// @endcond + +//!The mapped_region class represents a portion or region created from a +//!memory_mappable object. +class mapped_region +{ + /// @cond + //Non-copyable + mapped_region(const mapped_region &); + mapped_region &operator=(const mapped_region &); + /// @endcond + + public: + + //!Creates a mapping region of the mapped memory "mapping", starting in + //!offset "offset", and the mapping's size will be "size". The mapping + //!can be opened for read-only "read_only" or read-write + //!"read_write. + template + mapped_region(const MemoryMappable& mapping + ,mode_t mode + ,offset_t offset = 0 + ,std::size_t size = 0 + ,const void *address = 0); + + //!Default constructor. Address and size and offset will be 0. + //!Does not throw + mapped_region(); + + //!Move constructor. *this will be constructed taking ownership of "other"'s + //!region and "other" will be left in default constructor state. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + mapped_region(detail::moved_object other); + #else + mapped_region(mapped_region &&other); + #endif + + //!Destroys the mapped region. + //!Does not throw + ~mapped_region(); + + //!Move assignment. If *this owns a memory mapped region, it will be + //!destroyed and it will take ownership of "other"'s memory mapped region. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + mapped_region &operator=(detail::moved_object other); + #else + mapped_region &operator=(mapped_region &&other); + #endif + + //!Returns the size of the mapping. Note for windows users: If + //!windows_shared_memory is mapped using 0 as the size, it returns 0 + //!because the size is unknown. Never throws. + std::size_t get_size() const; + + //!Returns the base address of the mapping. + //!Never throws. + void* get_address() const; + + //!Returns the offset of the mapping from the beginning of the + //!mapped memory. Never throws. + offset_t get_offset() const; + + //!Returns the mode of the mapping used to contruct the mapped file. + //!Never throws. + mode_t get_mode() const; + + //!Flushes to the disk a byte range within the mapped memory. + //!Never throws + bool flush(std::size_t mapping_offset = 0, std::size_t numbytes = 0); + + //!Swaps the mapped_region with another + //!mapped region + void swap(mapped_region &other); + + //!Returns the size of the page. This size is the minimum memory that + //!will be used by the system when mapping a memory mappable source. + static std::size_t get_page_size(); + + /// @cond + private: + //!Closes a previously opened memory mapping. Never throws + void priv_close(); + + template + struct page_size_holder + { + static const std::size_t PageSize; + static std::size_t get_page_size(); + }; + + void* m_base; + std::size_t m_size; + offset_t m_offset; + offset_t m_extra_offset; + mode_t m_mode; + #if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + file_handle_t m_file_mapping_hnd; + #endif + + friend class detail::interprocess_tester; + friend class detail::raw_mapped_region_creator; + void dont_close_on_destruction(); + /// @endcond +}; + +///@cond + +inline void swap(mapped_region &x, mapped_region &y) +{ x.swap(y); } + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +inline mapped_region &mapped_region::operator=(detail::moved_object other) +{ this->swap(other.get()); return *this; } +#else +inline mapped_region &mapped_region::operator=(mapped_region &&other) +{ this->swap(other); return *this; } +#endif + +inline mapped_region::~mapped_region() +{ this->priv_close(); } + +inline std::size_t mapped_region::get_size() const +{ return m_size; } + +inline offset_t mapped_region::get_offset() const +{ return m_offset; } + +inline mode_t mapped_region::get_mode() const +{ return m_mode; } + +inline void* mapped_region::get_address() const +{ return m_base; } + +#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +inline mapped_region::mapped_region() + : m_base(0), m_size(0), m_offset(0), m_extra_offset(0), m_mode(read_only) + , m_file_mapping_hnd(detail::invalid_file()) +{} + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +inline mapped_region::mapped_region(detail::moved_object other) + : m_base(0), m_size(0), m_offset(0) + , m_extra_offset(0) + , m_mode(read_only) + , m_file_mapping_hnd(detail::invalid_file()) +{ this->swap(other.get()); } +#else +inline mapped_region::mapped_region(mapped_region &&other) + : m_base(0), m_size(0), m_offset(0) + , m_extra_offset(0) + , m_mode(read_only) + , m_file_mapping_hnd(detail::invalid_file()) +{ this->swap(other); } +#endif + +template +inline std::size_t mapped_region::page_size_holder::get_page_size() +{ + winapi::system_info info; + get_system_info(&info); + return std::size_t(info.dwAllocationGranularity); +} + +template +inline mapped_region::mapped_region + (const MemoryMappable &mapping + ,mode_t mode + ,offset_t offset + ,std::size_t size + ,const void *address) + : m_base(0), m_size(0), m_offset(0), m_extra_offset(0), m_mode(mode) + , m_file_mapping_hnd(detail::invalid_file()) +{ + mapping_handle_t mhandle = mapping.get_mapping_handle(); + file_handle_t native_mapping_handle = 0; + + //Set accesses + unsigned long file_map_access = 0; + unsigned long map_access = 0; + + switch(mode) + { + case read_only: + file_map_access |= winapi::page_readonly; + map_access |= winapi::file_map_read; + break; + case read_write: + file_map_access |= winapi::page_readwrite; + map_access |= winapi::file_map_write; + break; + case copy_on_write: + file_map_access |= winapi::page_writecopy; + map_access |= winapi::file_map_copy; + break; + default: + { + error_info err(mode_error); + throw interprocess_exception(err); + } + break; + } + + if(!mhandle.is_shm){ + //Update mapping size if the user does not specify it + if(size == 0){ + __int64 total_size; + if(!winapi::get_file_size(detail::file_handle_from_mapping_handle(mapping.get_mapping_handle()), total_size)){ + error_info err(winapi::get_last_error()); + throw interprocess_exception(err); + } + #ifdef max + #undef max + #endif + + if(static_cast(total_size) > + std::numeric_limits::max()){ + error_info err(size_error); + throw interprocess_exception(err); + } + size = static_cast(total_size - offset); + } + + //Create file mapping + native_mapping_handle = + winapi::create_file_mapping + (detail::file_handle_from_mapping_handle(mapping.get_mapping_handle()), file_map_access, 0, 0, 0); + + //Check if all is correct + if(!native_mapping_handle){ + error_info err = winapi::get_last_error(); + this->priv_close(); + throw interprocess_exception(err); + } + } + + //We can't map any offset so we have to obtain system's + //memory granularity + unsigned long granularity = 0; + unsigned long foffset_low; + unsigned long foffset_high; + + winapi::system_info info; + get_system_info(&info); + granularity = info.dwAllocationGranularity; + + //Now we calculate valid offsets + foffset_low = (unsigned long)(offset / granularity) * granularity; + foffset_high = (unsigned long)(((offset / granularity) * granularity) >> 32); + + //We calculate the difference between demanded and valid offset + m_extra_offset = (offset - (offset / granularity) * granularity); + + //Store user values in memory + m_offset = offset; + m_size = size; + + //Update the mapping address + if(address){ + address = static_cast(address) - m_extra_offset; + } + + if(mhandle.is_shm){ + //Windows shared memory needs the duplication of the handle if we want to + //make mapped_region independent from the mappable device + if(!winapi::duplicate_current_process_handle(mhandle.handle, &m_file_mapping_hnd)){ + error_info err = winapi::get_last_error(); + this->priv_close(); + throw interprocess_exception(err); + } + native_mapping_handle = m_file_mapping_hnd; + } + + //Map with new offsets and size + m_base = winapi::map_view_of_file_ex + (native_mapping_handle, + map_access, + foffset_high, + foffset_low, + m_size ? static_cast(m_extra_offset + m_size) : 0, + (void*)address); + + if(!mhandle.is_shm){ + //For files we don't need the file mapping anymore + winapi::close_handle(native_mapping_handle); + } + + //Check error + if(!m_base){ + error_info err = winapi::get_last_error(); + this->priv_close(); + throw interprocess_exception(err); + } + + //Calculate new base for the user + m_base = static_cast(m_base) + m_extra_offset; +} + +inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes) +{ + //Check some errors + if(m_base == 0) + return false; + + if(mapping_offset >= m_size || (mapping_offset + numbytes) > m_size){ + return false; + } + + //Update flush size if the user does not provide it + if(m_size == 0){ + numbytes = 0; + } + else if(numbytes == 0){ + numbytes = m_size - mapping_offset; + } + + //Flush it all + return 0 == winapi::flush_view_of_file + (static_cast(m_base)+mapping_offset, + static_cast(numbytes)); +} + +inline void mapped_region::priv_close() +{ + if(m_base){ + this->flush(); + winapi::unmap_view_of_file(static_cast(m_base) - m_extra_offset); + m_base = 0; + } + #if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + if(m_file_mapping_hnd != detail::invalid_file()){ + winapi::close_handle(m_file_mapping_hnd); + m_file_mapping_hnd = detail::invalid_file(); + } + #endif +} + +inline void mapped_region::dont_close_on_destruction() +{} + +#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +inline mapped_region::mapped_region() + : m_base(MAP_FAILED), m_size(0), m_offset(0), m_extra_offset(0), m_mode(read_only) +{} + +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +inline mapped_region::mapped_region(detail::moved_object other) + : m_base(MAP_FAILED), m_size(0), m_offset(0), m_extra_offset(0), m_mode(read_only) +{ this->swap(other.get()); } +#else +inline mapped_region::mapped_region(mapped_region &&other) + : m_base(MAP_FAILED), m_size(0), m_offset(0), m_mode(read_only) + , m_extra_offset(0) +{ this->swap(other); } +#endif + +template +inline std::size_t mapped_region::page_size_holder::get_page_size() +{ return std::size_t(sysconf(_SC_PAGESIZE)); } + +template +inline mapped_region::mapped_region + (const MemoryMappable &mapping, + mode_t mode, + offset_t offset, + std::size_t size, + const void *address) + : m_base(MAP_FAILED), m_size(0), m_offset(0), m_extra_offset(0), m_mode(mode) +{ + if(size == 0){ +// offset_t filesize = lseek64 + offset_t filesize = lseek + (mapping.get_mapping_handle(), offset, SEEK_END); + + if(filesize == -1 ){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } + if(offset >= filesize){ + error_info err(size_error); + throw interprocess_exception(err); + } + filesize -= offset; + + size = (size_t)filesize; + if((offset_t)size != filesize){ + error_info err(size_error); + throw interprocess_exception(err); + } + } + + //Create new mapping + int prot = 0; + int flags = 0; + + switch(mode) + { + case read_only: + prot |= PROT_READ; + flags |= MAP_SHARED; + break; + + case read_write: + prot |= (PROT_WRITE | PROT_READ); + flags |= MAP_SHARED; + break; + + case copy_on_write: + prot |= (PROT_WRITE | PROT_READ); + flags |= MAP_PRIVATE; + break; + + default: + { + error_info err(mode_error); + throw interprocess_exception(err); + } + break; + } + + //We calculate the difference between demanded and valid offset + std::size_t page_size = this->get_page_size(); + m_extra_offset = (offset - (offset / page_size) * page_size); + + //Store user values in memory + m_offset = offset; + m_size = size; + + //Update the mapping address + if(address){ + address = static_cast(address) - m_extra_offset; + } + + //Map it to the address space +// m_base = mmap64( (void*)address + m_base = mmap ( (void*)address + , static_cast(m_extra_offset + m_size) + , prot + , flags + , mapping.get_mapping_handle() + , offset - m_extra_offset); + + //Check if mapping was successful + if(m_base == MAP_FAILED){ + error_info err = system_error_code(); + this->priv_close(); + throw interprocess_exception(err); + } + + //Calculate new base for the user + void *old_base = m_base; + m_base = static_cast(m_base) + m_extra_offset; + m_offset = offset; + m_size = size; + + //Check for fixed mapping error + if(address && (old_base != (void*)address)){ + error_info err = system_error_code(); + this->priv_close(); + throw interprocess_exception(err); + } +} + +inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes) +{ + if(mapping_offset >= m_size || (mapping_offset+numbytes)> m_size){ + return false; + } + + if(numbytes == 0){ + numbytes = m_size - mapping_offset; + } + //Flush it all + return msync(static_cast(m_base)+mapping_offset, + numbytes, MS_SYNC) == 0; +} + +inline void mapped_region::priv_close() +{ + if(m_base != MAP_FAILED){ + this->flush(); + munmap(static_cast(m_base) - m_extra_offset, m_size + m_extra_offset); + m_base = MAP_FAILED; + } +} + +inline void mapped_region::dont_close_on_destruction() +{ m_base = MAP_FAILED; } + +#endif //##if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + +template +const std::size_t mapped_region::page_size_holder::PageSize + = mapped_region::page_size_holder::get_page_size(); + +inline std::size_t mapped_region::get_page_size() +{ return page_size_holder<0>::PageSize; } + +inline void mapped_region::swap(mapped_region &other) +{ + detail::do_swap(this->m_base, other.m_base); + detail::do_swap(this->m_size, other.m_size); + detail::do_swap(this->m_offset, other.m_offset); + detail::do_swap(this->m_extra_offset, other.m_extra_offset); + detail::do_swap(this->m_mode, other.m_mode); + #if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + detail::do_swap(this->m_file_mapping_hnd, other.m_file_mapping_hnd); + #endif +} + +//!No-op functor +struct null_mapped_region_function +{ + bool operator()(void *, std::size_t , bool) const + { return true; } +}; + +//!Trait class to detect if a type is +//!movable +template<> +struct is_movable +{ + enum { value = true }; +}; +/// @endcond + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_MAPPED_REGION_HPP + diff --git a/win32/include/boost/interprocess/mem_algo/detail/mem_algo_common.hpp b/win32/include/boost/interprocess/mem_algo/detail/mem_algo_common.hpp new file mode 100755 index 000000000..a5194a973 --- /dev/null +++ b/win32/include/boost/interprocess/mem_algo/detail/mem_algo_common.hpp @@ -0,0 +1,751 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP +#define BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Implements common operations for memory algorithms. + +namespace boost { +namespace interprocess { +namespace detail { + +template +struct multi_allocation_next +{ + typedef typename detail:: + pointer_to_other::type + multi_allocation_next_ptr; + + multi_allocation_next(multi_allocation_next_ptr n) + : next_(n) + {} + multi_allocation_next_ptr next_; +}; + +//!This iterator is returned by "allocate_many" functions so that +//!the user can access the multiple buffers allocated in a single call +template +class basic_multiallocation_iterator + : public std::iterator +{ + void unspecified_bool_type_func() const {} + typedef void (basic_multiallocation_iterator::*unspecified_bool_type)() const; + typedef typename detail:: + pointer_to_other + >::type + multi_allocation_next_ptr; + + public: + typedef char value_type; + typedef value_type & reference; + typedef value_type * pointer; + + basic_multiallocation_iterator() + : next_alloc_(0) + {} + + basic_multiallocation_iterator(multi_allocation_next_ptr next) + : next_alloc_(next) + {} + + basic_multiallocation_iterator &operator=(const basic_multiallocation_iterator &other) + { next_alloc_ = other.next_alloc_; return *this; } + + public: + basic_multiallocation_iterator& operator++() + { next_alloc_.next_ = detail::get_pointer(next_alloc_.next_->next_); return *this; } + + basic_multiallocation_iterator operator++(int) + { + basic_multiallocation_iterator result(next_alloc_.next_); + ++*this; + return result; + } + + bool operator== (const basic_multiallocation_iterator& other) const + { return next_alloc_.next_ == other.next_alloc_.next_; } + + bool operator!= (const basic_multiallocation_iterator& other) const + { return !operator== (other); } + + reference operator*() const + { return *((char*)detail::get_pointer(next_alloc_.next_)); } + + operator unspecified_bool_type() const + { return next_alloc_.next_? &basic_multiallocation_iterator::unspecified_bool_type_func : 0; } + + pointer operator->() const + { return &(*(*this)); } + + static basic_multiallocation_iterator create_simple_range(void *mem) + { + basic_multiallocation_iterator it; + typedef multi_allocation_next next_impl_t; + next_impl_t * tmp_mem = static_cast(mem); + it = basic_multiallocation_iterator(tmp_mem); + tmp_mem->next_ = 0; + return it; + } + + private: + multi_allocation_next next_alloc_; +}; + +template +class basic_multiallocation_chain +{ + private: + basic_multiallocation_iterator it_; + VoidPointer last_mem_; + std::size_t num_mem_; + + basic_multiallocation_chain(const basic_multiallocation_chain &); + basic_multiallocation_chain &operator=(const basic_multiallocation_chain &); + + public: + typedef basic_multiallocation_iterator multiallocation_iterator; + + basic_multiallocation_chain() + : it_(0), last_mem_(0), num_mem_(0) + {} + + void reset() + { + this->it_ = multiallocation_iterator(); + this->last_mem_ = 0; + this->num_mem_ = 0; + } + + void push_back(void *mem) + { + typedef multi_allocation_next next_impl_t; + next_impl_t * tmp_mem = static_cast(mem); + + if(!this->last_mem_){ + this->it_ = basic_multiallocation_iterator(tmp_mem); + } + else{ + static_cast(detail::get_pointer(this->last_mem_))->next_ = tmp_mem; + } + tmp_mem->next_ = 0; + this->last_mem_ = tmp_mem; + ++num_mem_; + } + + void push_front(void *mem) + { + typedef multi_allocation_next next_impl_t; + next_impl_t * tmp_mem = static_cast(mem); + ++num_mem_; + + if(!this->last_mem_){ + this->it_ = basic_multiallocation_iterator(tmp_mem); + tmp_mem->next_ = 0; + this->last_mem_ = tmp_mem; + } + else{ + next_impl_t * old_first = (next_impl_t*)(&*this->it_); + tmp_mem->next_ = old_first; + this->it_ = basic_multiallocation_iterator(tmp_mem); + } + } + + void swap(basic_multiallocation_chain &other_chain) + { + std::swap(this->it_, other_chain.it_); + std::swap(this->last_mem_, other_chain.last_mem_); + std::swap(this->num_mem_, other_chain.num_mem_); + } + + void splice_back(basic_multiallocation_chain &other_chain) + { + typedef multi_allocation_next next_impl_t; + multiallocation_iterator end_it; + multiallocation_iterator other_it = other_chain.get_it(); + multiallocation_iterator this_it = this->get_it(); + if(end_it == other_it){ + return; + } + else if(end_it == this_it){ + this->swap(other_chain); + } + else{ + static_cast(detail::get_pointer(this->last_mem_))->next_ + = (next_impl_t*)&*other_chain.it_; + this->last_mem_ = other_chain.last_mem_; + this->num_mem_ += other_chain.num_mem_; + } + } + + void *pop_front() + { + multiallocation_iterator itend; + if(this->it_ == itend){ + this->last_mem_= 0; + this->num_mem_ = 0; + return 0; + } + else{ + void *addr = &*it_; + ++it_; + --num_mem_; + if(!num_mem_){ + this->last_mem_ = 0; + this->it_ = multiallocation_iterator(); + } + return addr; + } + } + + bool empty() const + { return !num_mem_; } + + multiallocation_iterator get_it() const + { return it_; } + + std::size_t size() const + { return num_mem_; } +}; + + +//!This class implements several allocation functions shared by different algorithms +//!(aligned allocation, multiple allocation...). +template +class memory_algorithm_common +{ + public: + typedef typename MemoryAlgorithm::void_pointer void_pointer; + typedef typename MemoryAlgorithm::block_ctrl block_ctrl; + typedef typename MemoryAlgorithm::multiallocation_iterator multiallocation_iterator; + typedef multi_allocation_next multi_allocation_next_t; + typedef typename multi_allocation_next_t:: + multi_allocation_next_ptr multi_allocation_next_ptr; + typedef memory_algorithm_common this_type; + + static const std::size_t Alignment = MemoryAlgorithm::Alignment; + static const std::size_t MinBlockUnits = MemoryAlgorithm::MinBlockUnits; + static const std::size_t AllocatedCtrlBytes = MemoryAlgorithm::AllocatedCtrlBytes; + static const std::size_t AllocatedCtrlUnits = MemoryAlgorithm::AllocatedCtrlUnits; + static const std::size_t BlockCtrlBytes = MemoryAlgorithm::BlockCtrlBytes; + static const std::size_t BlockCtrlUnits = MemoryAlgorithm::BlockCtrlUnits; + static const std::size_t UsableByPreviousChunk = MemoryAlgorithm::UsableByPreviousChunk; + + static void assert_alignment(const void *ptr) + { assert_alignment((std::size_t)ptr); } + + static void assert_alignment(std::size_t uint_ptr) + { + (void)uint_ptr; + BOOST_ASSERT(uint_ptr % Alignment == 0); + } + + static bool check_alignment(const void *ptr) + { return (((std::size_t)ptr) % Alignment == 0); } + + static std::size_t ceil_units(std::size_t size) + { return detail::get_rounded_size(size, Alignment)/Alignment; } + + static std::size_t floor_units(std::size_t size) + { return size/Alignment; } + + static std::size_t multiple_of_units(std::size_t size) + { return detail::get_rounded_size(size, Alignment); } + + static multiallocation_iterator allocate_many + (MemoryAlgorithm *memory_algo, std::size_t elem_bytes, std::size_t n_elements) + { + return this_type::priv_allocate_many(memory_algo, &elem_bytes, n_elements, 0); + } + + static bool calculate_lcm_and_needs_backwards_lcmed + (std::size_t backwards_multiple, std::size_t received_size, std::size_t size_to_achieve, + std::size_t &lcm_out, std::size_t &needs_backwards_lcmed_out) + { + // Now calculate lcm + std::size_t max = backwards_multiple; + std::size_t min = Alignment; + std::size_t needs_backwards; + std::size_t needs_backwards_lcmed; + std::size_t lcm; + std::size_t current_forward; + //Swap if necessary + if(max < min){ + std::size_t tmp = min; + min = max; + max = tmp; + } + //Check if it's power of two + if((backwards_multiple & (backwards_multiple-1)) == 0){ + if(0 != (size_to_achieve & ((backwards_multiple-1)))){ + return false; + } + + lcm = max; + //If we want to use minbytes data to get a buffer between maxbytes + //and minbytes if maxbytes can't be achieved, calculate the + //biggest of all possibilities + current_forward = detail::get_truncated_size_po2(received_size, backwards_multiple); + needs_backwards = size_to_achieve - current_forward; + assert((needs_backwards % backwards_multiple) == 0); + needs_backwards_lcmed = detail::get_rounded_size_po2(needs_backwards, lcm); + lcm_out = lcm; + needs_backwards_lcmed_out = needs_backwards_lcmed; + return true; + } + //Check if it's multiple of alignment + else if((backwards_multiple & (Alignment - 1u)) == 0){ + lcm = backwards_multiple; + current_forward = detail::get_truncated_size(received_size, backwards_multiple); + //No need to round needs_backwards because backwards_multiple == lcm + needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward; + assert((needs_backwards_lcmed & (Alignment - 1u)) == 0); + lcm_out = lcm; + needs_backwards_lcmed_out = needs_backwards_lcmed; + return true; + } + //Check if it's multiple of the half of the alignmment + else if((backwards_multiple & ((Alignment/2u) - 1u)) == 0){ + lcm = backwards_multiple*2u; + current_forward = detail::get_truncated_size(received_size, backwards_multiple); + needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward; + if(0 != (needs_backwards_lcmed & (Alignment-1))) + //while(0 != (needs_backwards_lcmed & (Alignment-1))) + needs_backwards_lcmed += backwards_multiple; + assert((needs_backwards_lcmed % lcm) == 0); + lcm_out = lcm; + needs_backwards_lcmed_out = needs_backwards_lcmed; + return true; + } + //Check if it's multiple of the half of the alignmment + else if((backwards_multiple & ((Alignment/4u) - 1u)) == 0){ + std::size_t remainder; + lcm = backwards_multiple*4u; + current_forward = detail::get_truncated_size(received_size, backwards_multiple); + needs_backwards_lcmed = needs_backwards = size_to_achieve - current_forward; + //while(0 != (needs_backwards_lcmed & (Alignment-1))) + //needs_backwards_lcmed += backwards_multiple; + if(0 != (remainder = ((needs_backwards_lcmed & (Alignment-1))>>(Alignment/8u)))){ + if(backwards_multiple & Alignment/2u){ + needs_backwards_lcmed += (remainder)*backwards_multiple; + } + else{ + needs_backwards_lcmed += (4-remainder)*backwards_multiple; + } + } + assert((needs_backwards_lcmed % lcm) == 0); + lcm_out = lcm; + needs_backwards_lcmed_out = needs_backwards_lcmed; + return true; + } + else{ + lcm = detail::lcm(max, min); + } + //If we want to use minbytes data to get a buffer between maxbytes + //and minbytes if maxbytes can't be achieved, calculate the + //biggest of all possibilities + current_forward = detail::get_truncated_size(received_size, backwards_multiple); + needs_backwards = size_to_achieve - current_forward; + assert((needs_backwards % backwards_multiple) == 0); + needs_backwards_lcmed = detail::get_rounded_size(needs_backwards, lcm); + lcm_out = lcm; + needs_backwards_lcmed_out = needs_backwards_lcmed; + return true; + } + + static multiallocation_iterator allocate_many + ( MemoryAlgorithm *memory_algo + , const std::size_t *elem_sizes + , std::size_t n_elements + , std::size_t sizeof_element) + { + return this_type::priv_allocate_many(memory_algo, elem_sizes, n_elements, sizeof_element); + } + + static void* allocate_aligned + (MemoryAlgorithm *memory_algo, std::size_t nbytes, std::size_t alignment) + { + + //Ensure power of 2 + if ((alignment & (alignment - std::size_t(1u))) != 0){ + //Alignment is not power of two + BOOST_ASSERT((alignment & (alignment - std::size_t(1u))) == 0); + return 0; + } + + std::size_t real_size; + if(alignment <= Alignment){ + return memory_algo->priv_allocate(allocate_new, nbytes, nbytes, real_size).first; + } + + if(nbytes > UsableByPreviousChunk) + nbytes -= UsableByPreviousChunk; + + //We can find a aligned portion if we allocate a block that has alignment + //nbytes + alignment bytes or more. + std::size_t minimum_allocation = max_value + (nbytes + alignment, std::size_t(MinBlockUnits*Alignment)); + //Since we will split that block, we must request a bit more memory + //if the alignment is near the beginning of the buffer, because otherwise, + //there is no space for a new block before the alignment. + // + // ____ Aligned here + // | + // ----------------------------------------------------- + // | MBU | + // ----------------------------------------------------- + std::size_t request = + minimum_allocation + (2*MinBlockUnits*Alignment - AllocatedCtrlBytes + //prevsize - UsableByPreviousChunk + ); + + //Now allocate the buffer + void *buffer = memory_algo->priv_allocate(allocate_new, request, request, real_size).first; + if(!buffer){ + return 0; + } + else if ((((std::size_t)(buffer)) % alignment) == 0){ + //If we are lucky and the buffer is aligned, just split it and + //return the high part + block_ctrl *first = memory_algo->priv_get_block(buffer); + std::size_t old_size = first->m_size; + const std::size_t first_min_units = + max_value(ceil_units(nbytes) + AllocatedCtrlUnits, std::size_t(MinBlockUnits)); + //We can create a new block in the end of the segment + if(old_size >= (first_min_units + MinBlockUnits)){ + //block_ctrl *second = new((char*)first + Alignment*first_min_units) block_ctrl; + block_ctrl *second = (block_ctrl *)((char*)first + Alignment*first_min_units); + first->m_size = first_min_units; + second->m_size = old_size - first->m_size; + BOOST_ASSERT(second->m_size >= MinBlockUnits); + memory_algo->priv_mark_new_allocated_block(first); + //memory_algo->priv_tail_size(first, first->m_size); + memory_algo->priv_mark_new_allocated_block(second); + memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(second)); + } + return buffer; + } + + //Buffer not aligned, find the aligned part. + // + // ____ Aligned here + // | + // ----------------------------------------------------- + // | MBU +more | ACB | + // ----------------------------------------------------- + char *pos = (char*) + ((std::size_t)((char*)buffer + + //This is the minimum size of (2) + (MinBlockUnits*Alignment - AllocatedCtrlBytes) + + //This is the next MBU for the aligned memory + AllocatedCtrlBytes + + //This is the alignment trick + alignment - 1) & -alignment); + + //Now obtain the address of the blocks + block_ctrl *first = memory_algo->priv_get_block(buffer); + block_ctrl *second = memory_algo->priv_get_block(pos); + assert(pos <= ((char*)first + first->m_size*Alignment)); + assert(first->m_size >= 2*MinBlockUnits); + assert((pos + MinBlockUnits*Alignment - AllocatedCtrlBytes + nbytes*Alignment/Alignment) <= ((char*)first + first->m_size*Alignment)); + //Set the new size of the first block + std::size_t old_size = first->m_size; + first->m_size = ((char*)second - (char*)first)/Alignment; + memory_algo->priv_mark_new_allocated_block(first); + + //Now check if we can create a new buffer in the end + // + // __"second" block + // | __Aligned here + // | | __"third" block + // -----------|-----|-----|------------------------------ + // | MBU +more | ACB | (3) | BCU | + // ----------------------------------------------------- + //This size will be the minimum size to be able to create a + //new block in the end. + const std::size_t second_min_units = max_value(std::size_t(MinBlockUnits), + ceil_units(nbytes) + AllocatedCtrlUnits ); + + //Check if we can create a new block (of size MinBlockUnits) in the end of the segment + if((old_size - first->m_size) >= (second_min_units + MinBlockUnits)){ + //Now obtain the address of the end block + block_ctrl *third = new ((char*)second + Alignment*second_min_units)block_ctrl; + second->m_size = second_min_units; + third->m_size = old_size - first->m_size - second->m_size; + BOOST_ASSERT(third->m_size >= MinBlockUnits); + memory_algo->priv_mark_new_allocated_block(second); + memory_algo->priv_mark_new_allocated_block(third); + memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(third)); + } + else{ + second->m_size = old_size - first->m_size; + assert(second->m_size >= MinBlockUnits); + memory_algo->priv_mark_new_allocated_block(second); + } + + memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(first)); + return memory_algo->priv_get_user_buffer(second); + } + + static bool try_shrink + (MemoryAlgorithm *memory_algo, void *ptr + ,const std::size_t max_size, const std::size_t preferred_size + ,std::size_t &received_size) + { + (void)memory_algo; + //Obtain the real block + block_ctrl *block = memory_algo->priv_get_block(ptr); + std::size_t old_block_units = block->m_size; + + //The block must be marked as allocated + BOOST_ASSERT(memory_algo->priv_is_allocated_block(block)); + + //Check if alignment and block size are right + assert_alignment(ptr); + + //Put this to a safe value + received_size = (old_block_units - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; + + //Now translate it to Alignment units + const std::size_t max_user_units = floor_units(max_size - UsableByPreviousChunk); + const std::size_t preferred_user_units = ceil_units(preferred_size - UsableByPreviousChunk); + + //Check if rounded max and preferred are possible correct + if(max_user_units < preferred_user_units) + return false; + + //Check if the block is smaller than the requested minimum + std::size_t old_user_units = old_block_units - AllocatedCtrlUnits; + + if(old_user_units < preferred_user_units) + return false; + + //If the block is smaller than the requested minimum + if(old_user_units == preferred_user_units) + return true; + + std::size_t shrunk_user_units = + ((BlockCtrlUnits - AllocatedCtrlUnits) > preferred_user_units) + ? (BlockCtrlUnits - AllocatedCtrlUnits) + : preferred_user_units; + + //Some parameter checks + if(max_user_units < shrunk_user_units) + return false; + + //We must be able to create at least a new empty block + if((old_user_units - shrunk_user_units) < BlockCtrlUnits ){ + return false; + } + + //Update new size + received_size = shrunk_user_units*Alignment + UsableByPreviousChunk; + return true; + } + + static bool shrink + (MemoryAlgorithm *memory_algo, void *ptr + ,const std::size_t max_size, const std::size_t preferred_size + ,std::size_t &received_size) + { + //Obtain the real block + block_ctrl *block = memory_algo->priv_get_block(ptr); + std::size_t old_block_units = block->m_size; + + if(!try_shrink + (memory_algo, ptr, max_size, preferred_size, received_size)){ + return false; + } + + //Check if the old size was just the shrunk size (no splitting) + if((old_block_units - AllocatedCtrlUnits) == ceil_units(preferred_size - UsableByPreviousChunk)) + return true; + + //Now we can just rewrite the size of the old buffer + block->m_size = (received_size-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits; + BOOST_ASSERT(block->m_size >= BlockCtrlUnits); + + //We create the new block +// block_ctrl *new_block = new(reinterpret_cast +// (detail::char_ptr_cast(block) + block->m_size*Alignment)) block_ctrl; + block_ctrl *new_block = reinterpret_cast + (detail::char_ptr_cast(block) + block->m_size*Alignment); + //Write control data to simulate this new block was previously allocated + //and deallocate it + new_block->m_size = old_block_units - block->m_size; + BOOST_ASSERT(new_block->m_size >= BlockCtrlUnits); + memory_algo->priv_mark_new_allocated_block(block); + memory_algo->priv_mark_new_allocated_block(new_block); + memory_algo->priv_deallocate(memory_algo->priv_get_user_buffer(new_block)); + return true; + } + + private: + static multiallocation_iterator priv_allocate_many + ( MemoryAlgorithm *memory_algo + , const std::size_t *elem_sizes + , std::size_t n_elements + , std::size_t sizeof_element) + { + //Note: sizeof_element == 0 indicates that we want to + //allocate n_elements of the same size "*elem_sizes" + + //Calculate the total size of all requests + std::size_t total_request_units = 0; + std::size_t elem_units = 0; + const std::size_t ptr_size_units = memory_algo->priv_get_total_units(sizeof(multi_allocation_next_ptr)); + if(!sizeof_element){ + elem_units = memory_algo->priv_get_total_units(*elem_sizes); + elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; + total_request_units = n_elements*elem_units; + } + else{ + for(std::size_t i = 0; i < n_elements; ++i){ + elem_units = memory_algo->priv_get_total_units(elem_sizes[i]*sizeof_element); + elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; + total_request_units += elem_units; + } + } + + multi_allocation_next_ptr first = 0, previous = 0; + std::size_t low_idx = 0; + while(low_idx < n_elements){ + std::size_t total_bytes = total_request_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; + std::size_t min_allocation = (!sizeof_element) + ? elem_units + : memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); + min_allocation = min_allocation*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; + + std::size_t received_size; + std::pair ret = memory_algo->priv_allocate + (allocate_new, min_allocation, total_bytes, received_size, 0); + if(!ret.first){ + break; + } + + block_ctrl *block = memory_algo->priv_get_block(ret.first); + std::size_t received_units = block->m_size; + char *block_address = (char*)block; + + std::size_t total_used_units = 0; +// block_ctrl *prev_block = 0; + while(total_used_units < received_units){ + if(sizeof_element){ + elem_units = memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); + elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; + } + if(total_used_units + elem_units > received_units) + break; + total_request_units -= elem_units; + //This is the position where the new block must be created +// if(prev_block) +// memory_algo->priv_mark_new_allocated_block(prev_block); + block_ctrl *new_block = (block_ctrl *)(block_address); +// block_ctrl *new_block = new(block_address)block_ctrl; + assert_alignment(new_block); + + //The last block should take all the remaining space + if((low_idx + 1) == n_elements || + (total_used_units + elem_units + + ((!sizeof_element) + ? elem_units + : memory_algo->priv_get_total_units(elem_sizes[low_idx+1]*sizeof_element)) + ) > received_units){ + //By default, the new block will use the rest of the buffer + new_block->m_size = received_units - total_used_units; + memory_algo->priv_mark_new_allocated_block(new_block); + + //If the remaining units are bigger than needed and we can + //split it obtaining a new free memory block do it. + if((received_units - total_used_units) >= (elem_units + MemoryAlgorithm::BlockCtrlUnits)){ + std::size_t shrunk_received; + std::size_t shrunk_request = elem_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; + bool shrink_ok = shrink + (memory_algo + ,memory_algo->priv_get_user_buffer(new_block) + ,shrunk_request + ,shrunk_request + ,shrunk_received); + (void)shrink_ok; + //Shrink must always succeed with passed parameters + BOOST_ASSERT(shrink_ok); + //Some sanity checks + BOOST_ASSERT(shrunk_request == shrunk_received); + BOOST_ASSERT(elem_units == ((shrunk_request-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits)); + //"new_block->m_size" must have been reduced to elem_units by "shrink" + BOOST_ASSERT(new_block->m_size == elem_units); + //Now update the total received units with the reduction + received_units = elem_units + total_used_units; + } + } + else{ + new_block->m_size = elem_units; + memory_algo->priv_mark_new_allocated_block(new_block); + } + + block_address += new_block->m_size*Alignment; + total_used_units += new_block->m_size; + //Check we have enough room to overwrite the intrusive pointer + assert((new_block->m_size*Alignment - AllocatedCtrlUnits) >= sizeof(multi_allocation_next_t)); + multi_allocation_next_ptr p = new(memory_algo->priv_get_user_buffer(new_block))multi_allocation_next_t(0); + + if(!first){ + first = p; + } + else{ + previous->next_ = p; + } + previous = p; + ++low_idx; + //prev_block = new_block; + } + //Sanity check + BOOST_ASSERT(total_used_units == received_units); + } + + if(low_idx != n_elements){ + while(first){ + multi_allocation_next_ptr prev = first; + first = first->next_; + memory_algo->priv_deallocate(detail::get_pointer(prev)); + } + return multiallocation_iterator(); + } + else{ + return multiallocation_iterator(first); + } + } +}; + +} //namespace detail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MEM_ALGO_COMMON_HPP diff --git a/win32/include/boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp b/win32/include/boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp new file mode 100755 index 000000000..716b15747 --- /dev/null +++ b/win32/include/boost/interprocess/mem_algo/detail/multi_simple_seq_fit.hpp @@ -0,0 +1,61 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2007. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MULTI_SIMPLE_SEQ_FIT_HPP +#define BOOST_INTERPROCESS_MULTI_SIMPLE_SEQ_FIT_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include + +/*!\file + Describes sequential fit algorithm used to allocate objects in shared memory. +*/ + +namespace boost { + +namespace interprocess { + +/*!This class implements the simple sequential fit algorithm with a simply + linked list of free buffers.*/ +template +class multi_simple_seq_fit + : public detail::simple_seq_fit_impl +{ + typedef detail::simple_seq_fit_impl base_t; + public: + /*!Constructor. "size" is the total size of the managed memory segment, + "extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(multi_simple_seq_fit) + offset that the allocator should not use at all.*/ + multi_simple_seq_fit (std::size_t size, std::size_t extra_hdr_bytes) + : base_t(size, extra_hdr_bytes){} + + /*!Allocates bytes from existing segments. If there is no memory, it uses + the growing functor associated with the group to allocate a new segment. + If this fails, returns 0.*/ + void* allocate (std::size_t nbytes) + { return base_t::multi_allocate(nbytes); } +}; + +} //namespace interprocess { + +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_MULTI_SIMPLE_SEQ_FIT_HPP + diff --git a/win32/include/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp b/win32/include/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp new file mode 100755 index 000000000..132eced4a --- /dev/null +++ b/win32/include/boost/interprocess/mem_algo/detail/multi_simple_seq_fit_impl.hpp @@ -0,0 +1,973 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2007. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP +#define BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/*!\file + Describes sequential fit algorithm used to allocate objects in shared memory. + This class is intended as a base class for single segment and multi-segment + implementations. +*/ + +namespace boost { + +namespace interprocess { + +namespace detail { + +/*!This class implements the simple sequential fit algorithm with a simply + linked list of free buffers. + This class is intended as a base class for single segment and multi-segment + implementations.*/ +template +class simple_seq_fit_impl +{ + //Non-copyable + simple_seq_fit_impl(); + simple_seq_fit_impl(const simple_seq_fit_impl &); + simple_seq_fit_impl &operator=(const simple_seq_fit_impl &); + + public: + /*!Shared interprocess_mutex family used for the rest of the Interprocess framework*/ + typedef MutexFamily mutex_family; + /*!Pointer type to be used with the rest of the Interprocess framework*/ + typedef VoidPointer void_pointer; + + private: + struct block_ctrl; + typedef typename detail:: + pointer_to_other::type block_ctrl_ptr; + + /*!Block control structure*/ + struct block_ctrl + { + /*!Offset pointer to the next block.*/ + block_ctrl_ptr m_next; + /*!This block's memory size (including block_ctrl + header) in BasicSize units*/ + std::size_t m_size; + + std::size_t get_user_bytes() const + { return this->m_size*Alignment - BlockCtrlBytes; } + + std::size_t get_total_bytes() const + { return this->m_size*Alignment; } + + static block_ctrl *get_block_from_addr(void *addr) + { + return reinterpret_cast + (detail::char_ptr_cast(addr) - BlockCtrlBytes); + } + + void *get_addr() const + { + return reinterpret_cast + (detail::char_ptr_cast(this) + BlockCtrlBytes); + } + + }; + + /*!Shared interprocess_mutex to protect memory allocate/deallocate*/ + typedef typename MutexFamily::mutex_type interprocess_mutex; + + /*!This struct includes needed data and derives from + interprocess_mutex to allow EBO when using null interprocess_mutex*/ + struct header_t : public interprocess_mutex + { + /*!Pointer to the first free block*/ + block_ctrl m_root; + /*!Allocated bytes for internal checking*/ + std::size_t m_allocated; + /*!The size of the memory segment*/ + std::size_t m_size; + } m_header; + + public: + /*!Constructor. "size" is the total size of the managed memory segment, + "extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(simple_seq_fit_impl) + offset that the allocator should not use at all.*/ + simple_seq_fit_impl (std::size_t size, std::size_t extra_hdr_bytes); + /*!Destructor.*/ + ~simple_seq_fit_impl(); + /*!Obtains the minimum size needed by the algorithm*/ + static std::size_t get_min_size (std::size_t extra_hdr_bytes); + + //Functions for single segment management + + /*!Allocates bytes, returns 0 if there is not more memory*/ + void* allocate (std::size_t nbytes); + + /*!Deallocates previously allocated bytes*/ + void deallocate (void *addr); + + /*!Returns the size of the memory segment*/ + std::size_t get_size() const; + + /*!Increases managed memory in extra_size bytes more*/ + void grow(std::size_t extra_size); + + /*!Returns true if all allocated memory has been deallocated*/ + bool all_memory_deallocated(); + + /*!Makes an internal sanity check and returns true if success*/ + bool check_sanity(); + + //!Initializes to zero all the memory that's not in use. + //!This function is normally used for security reasons. + void clear_free_memory(); + + std::pair + allocation_command (allocation_type command, std::size_t limit_size, + std::size_t preferred_size,std::size_t &received_size, + void *reuse_ptr = 0, std::size_t backwards_multiple = 1); + + /*!Returns the size of the buffer previously allocated pointed by ptr*/ + std::size_t size(void *ptr) const; + + /*!Allocates aligned bytes, returns 0 if there is not more memory. + Alignment must be power of 2*/ + void* allocate_aligned (std::size_t nbytes, std::size_t alignment); + + /*!Allocates bytes, if there is no more memory, it executes functor + f(std::size_t) to allocate a new segment to manage. The functor returns + std::pair indicating the base address and size of + the new segment. If the new segment can't be allocated, allocate + it will return 0.*/ + void* multi_allocate(std::size_t nbytes); + + private: + /*!Real allocation algorithm with min allocation option*/ + std::pair priv_allocate(allocation_type command + ,std::size_t min_size + ,std::size_t preferred_size + ,std::size_t &received_size + ,void *reuse_ptr = 0); + /*!Returns next block if it's free. + Returns 0 if next block is not free.*/ + block_ctrl *priv_next_block_if_free(block_ctrl *ptr); + + /*!Returns previous block's if it's free. + Returns 0 if previous block is not free.*/ + std::pairpriv_prev_block_if_free(block_ctrl *ptr); + + /*!Real expand function implementation*/ + bool priv_expand(void *ptr + ,std::size_t min_size, std::size_t preferred_size + ,std::size_t &received_size); + + /*!Real expand to both sides implementation*/ + void* priv_expand_both_sides(allocation_type command + ,std::size_t min_size + ,std::size_t preferred_size + ,std::size_t &received_size + ,void *reuse_ptr + ,bool only_preferred_backwards); + + /*!Real shrink function implementation*/ + bool priv_shrink(void *ptr + ,std::size_t max_size, std::size_t preferred_size + ,std::size_t &received_size); + + //!Real private aligned allocation function + void* priv_allocate_aligned (std::size_t nbytes, std::size_t alignment); + + /*!Checks if block has enough memory and splits/unlinks the block + returning the address to the users*/ + void* priv_check_and_allocate(std::size_t units + ,block_ctrl* prev + ,block_ctrl* block + ,std::size_t &received_size); + /*!Real deallocation algorithm*/ + void priv_deallocate(void *addr); + + /*!Makes a new memory portion available for allocation*/ + void priv_add_segment(void *addr, std::size_t size); + + enum { Alignment = boost::alignment_of::value }; + enum { BlockCtrlBytes = detail::ct_rounded_size::value }; + enum { BlockCtrlSize = BlockCtrlBytes/Alignment }; + enum { MinBlockSize = BlockCtrlSize + Alignment }; + + public: + enum { PayloadPerAllocation = BlockCtrlBytes }; +}; + +template +inline simple_seq_fit_impl:: + simple_seq_fit_impl(std::size_t size, std::size_t extra_hdr_bytes) +{ + //Initialize sizes and counters + m_header.m_allocated = 0; + m_header.m_size = size; + + //Initialize pointers + std::size_t block1_off = detail::get_rounded_size(sizeof(*this)+extra_hdr_bytes, Alignment); + m_header.m_root.m_next = reinterpret_cast + (detail::char_ptr_cast(this) + block1_off); + m_header.m_root.m_next->m_size = (size - block1_off)/Alignment; + m_header.m_root.m_next->m_next = &m_header.m_root; +} + +template +inline simple_seq_fit_impl::~simple_seq_fit_impl() +{ + //There is a memory leak! +// assert(m_header.m_allocated == 0); +// assert(m_header.m_root.m_next->m_next == block_ctrl_ptr(&m_header.m_root)); +} + +template +inline void simple_seq_fit_impl::grow(std::size_t extra_size) +{ + //Old highest address block's end offset + std::size_t old_end = m_header.m_size/Alignment*Alignment; + + //Update managed buffer's size + m_header.m_size += extra_size; + + //We need at least MinBlockSize blocks to create a new block + if((m_header.m_size - old_end) < MinBlockSize){ + return; + } + + //We'll create a new free block with extra_size bytes + block_ctrl *new_block = reinterpret_cast + (detail::char_ptr_cast(this) + old_end); + + new_block->m_next = 0; + new_block->m_size = (m_header.m_size - old_end)/Alignment; + m_header.m_allocated += new_block->m_size*Alignment; + this->priv_deallocate(detail::char_ptr_cast(new_block) + BlockCtrlBytes); +} + +template +inline void simple_seq_fit_impl::priv_add_segment(void *addr, std::size_t size) +{ + //Check size + assert(!(size < MinBlockSize)); + if(size < MinBlockSize) + return; + //Construct big block using the new segment + block_ctrl *new_block = static_cast(addr); + new_block->m_size = size/Alignment; + new_block->m_next = 0; + //Simulate this block was previously allocated + m_header.m_allocated += new_block->m_size*Alignment; + //Return block and insert it in the free block list + this->priv_deallocate(detail::char_ptr_cast(new_block) + BlockCtrlBytes); +} + +template +inline std::size_t simple_seq_fit_impl::get_size() const + { return m_header.m_size; } + +template +inline std::size_t simple_seq_fit_impl:: + get_min_size (std::size_t extra_hdr_bytes) +{ + return detail::get_rounded_size(sizeof(simple_seq_fit_impl)+extra_hdr_bytes + ,Alignment) + + MinBlockSize; +} + +template +inline bool simple_seq_fit_impl:: + all_memory_deallocated() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return m_header.m_allocated == 0 && + detail::get_pointer(m_header.m_root.m_next->m_next) == &m_header.m_root; +} + +template +inline void simple_seq_fit_impl::clear_free_memory() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + block_ctrl *block = detail::get_pointer(m_header.m_root.m_next); + + //Iterate through all free portions + do{ + //Just clear user the memory part reserved for the user + std::memset( detail::char_ptr_cast(block) + BlockCtrlBytes + , 0 + , block->m_size*Alignment - BlockCtrlBytes); + block = detail::get_pointer(block->m_next); + } + while(block != &m_header.m_root); +} + +template +inline bool simple_seq_fit_impl:: + check_sanity() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + block_ctrl *block = detail::get_pointer(m_header.m_root.m_next); + + std::size_t free_memory = 0; + + //Iterate through all blocks obtaining their size + do{ + //Free blocks's next must be always valid + block_ctrl *next = detail::get_pointer(block->m_next); + if(!next){ + return false; + } + free_memory += block->m_size*Alignment; + block = next; + } + while(block != &m_header.m_root); + + //Check allocated bytes are less than size + if(m_header.m_allocated > m_header.m_size){ + return false; + } + + //Check free bytes are less than size + if(free_memory > m_header.m_size){ + return false; + } + return true; +} + +template +inline void* simple_seq_fit_impl:: + allocate(std::size_t nbytes) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + std::size_t ignore; + return priv_allocate(allocate_new, nbytes, nbytes, ignore).first; +} + +template +inline void* simple_seq_fit_impl:: + allocate_aligned(std::size_t nbytes, std::size_t alignment) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return priv_allocate_aligned(nbytes, alignment); +} + +template +inline std::pair simple_seq_fit_impl:: + allocation_command (allocation_type command, std::size_t min_size, + std::size_t preferred_size,std::size_t &received_size, + void *reuse_ptr, std::size_t backwards_multiple) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + (void)backwards_multiple; + command &= ~expand_bwd; + if(!command) + return std::pair(0, false); + return priv_allocate(command, min_size, preferred_size, received_size, reuse_ptr); +} + +template +inline std::size_t simple_seq_fit_impl:: + size(void *ptr) const +{ + //We need no synchronization since this block is not going + //to be modified + //Obtain the real size of the block + block_ctrl *block = reinterpret_cast + (detail::char_ptr_cast(ptr) - BlockCtrlBytes); + return block->m_size*Alignment - BlockCtrlBytes; +} + +template +inline void* simple_seq_fit_impl:: + multi_allocate(std::size_t nbytes) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + //Multisegment pointer. Let's try first the normal allocation + //since it's faster. + std::size_t ignore; + void *addr = this->priv_allocate(allocate_new, nbytes, nbytes, ignore).first; + if(!addr){ + //If this fails we will try the allocation through the segment + //creator. + std::size_t group, id; + //Obtain the segment group of this segment + void_pointer::get_group_and_id(this, group, id); + if(group == 0){ + //Ooops, group 0 is not valid. + return 0; + } + //Now obtain the polymorphic functor that creates + //new segments and try to allocate again. + boost::interprocess::multi_segment_services *p_services = + static_cast + (void_pointer::find_group_data(group)); + assert(p_services); + std::pair ret = + p_services->create_new_segment(MinBlockSize > nbytes ? MinBlockSize : nbytes); + if(ret.first){ + priv_add_segment(ret.first, ret.second); + addr = this->priv_allocate(allocate_new, nbytes, nbytes, ignore).first; + } + } + return addr; +} + +template +void* simple_seq_fit_impl:: + priv_expand_both_sides(allocation_type command + ,std::size_t min_size + ,std::size_t preferred_size + ,std::size_t &received_size + ,void *reuse_ptr + ,bool only_preferred_backwards) +{ + typedef std::pair prev_block_t; + block_ctrl *reuse = block_ctrl::get_block_from_addr(reuse_ptr); + received_size = 0; + + if(this->size(reuse_ptr) > min_size){ + received_size = this->size(reuse_ptr); + return reuse_ptr; + } + + if(command & expand_fwd){ + if(priv_expand(reuse_ptr, min_size, preferred_size, received_size)) + return reuse_ptr; + } + else{ + received_size = this->size(reuse_ptr); + } + if(command & expand_bwd){ + std::size_t extra_forward = !received_size ? 0 : received_size + BlockCtrlBytes; + prev_block_t prev_pair = priv_prev_block_if_free(reuse); + block_ctrl *prev = prev_pair.second; + if(!prev){ + return 0; + } + + std::size_t needs_backwards = + detail::get_rounded_size(preferred_size - extra_forward, Alignment); + + if(!only_preferred_backwards){ + needs_backwards = + max_value(detail::get_rounded_size(min_size - extra_forward, Alignment) + ,min_value(prev->get_user_bytes(), needs_backwards)); + } + + //Check if previous block has enough size + if((prev->get_user_bytes()) >= needs_backwards){ + //Now take all next space. This will succeed + if(!priv_expand(reuse_ptr, received_size, received_size, received_size)){ + assert(0); + } + + //We need a minimum size to split the previous one + if((prev->get_user_bytes() - needs_backwards) > 2*BlockCtrlBytes){ + block_ctrl *new_block = reinterpret_cast + (detail::char_ptr_cast(reuse) - needs_backwards - BlockCtrlBytes); + new_block->m_next = 0; + new_block->m_size = + BlockCtrlSize + (needs_backwards + extra_forward)/Alignment; + prev->m_size = + (prev->get_total_bytes() - needs_backwards)/Alignment - BlockCtrlSize; + received_size = needs_backwards + extra_forward; + m_header.m_allocated += needs_backwards + BlockCtrlBytes; + return new_block->get_addr(); + } + else{ + //Just merge the whole previous block + block_ctrl *prev_2_block = prev_pair.first; + //Update received size and allocation + received_size = extra_forward + prev->get_user_bytes(); + m_header.m_allocated += prev->get_total_bytes(); + //Now unlink it from previous block + prev_2_block->m_next = prev->m_next; + prev->m_size = reuse->m_size + prev->m_size; + prev->m_next = 0; + return prev->get_addr(); + } + } + } + return 0; +} + +template +std::pair simple_seq_fit_impl:: + priv_allocate(allocation_type command + ,std::size_t limit_size + ,std::size_t preferred_size + ,std::size_t &received_size + ,void *reuse_ptr) +{ + if(command & shrink_in_place){ + bool success = + this->priv_shrink(reuse_ptr, limit_size, preferred_size, received_size); + return std::pair ((success ? reuse_ptr : 0), true); + } + typedef std::pair return_type; + received_size = 0; + + if(limit_size > preferred_size) + return return_type(0, false); + + //Number of units to request (including block_ctrl header) + std::size_t nunits = detail::get_rounded_size(preferred_size, Alignment)/Alignment + BlockCtrlSize; + + //Get the root and the first memory block + block_ctrl *prev = &m_header.m_root; + block_ctrl *block = detail::get_pointer(prev->m_next); + block_ctrl *root = &m_header.m_root; + block_ctrl *biggest_block = 0; + block_ctrl *prev_biggest_block = 0; + std::size_t biggest_size = limit_size; + + //Expand in place + //reuse_ptr, limit_size, preferred_size, received_size + // + if(reuse_ptr && (command & (expand_fwd | expand_bwd))){ + void *ret = priv_expand_both_sides + (command, limit_size, preferred_size, received_size, reuse_ptr, true); + if(ret) + return return_type(ret, true); + } + + if(command & allocate_new){ + received_size = 0; + while(block != root){ + //Update biggest block pointers + if(block->m_size > biggest_size){ + prev_biggest_block = prev; + biggest_size = block->m_size; + biggest_block = block; + } + void *addr = this->priv_check_and_allocate(nunits, prev, block, received_size); + if(addr) return return_type(addr, false); + //Bad luck, let's check next block + prev = block; + block = detail::get_pointer(block->m_next); + } + + //Bad luck finding preferred_size, now if we have any biggest_block + //try with this block + if(biggest_block){ + received_size = biggest_block->m_size*Alignment - BlockCtrlSize; + nunits = detail::get_rounded_size(limit_size, Alignment)/Alignment + BlockCtrlSize; + void *ret = this->priv_check_and_allocate + (nunits, prev_biggest_block, biggest_block, received_size); + if(ret) + return return_type(ret, false); + } + } + //Now try to expand both sides with min size + if(reuse_ptr && (command & (expand_fwd | expand_bwd))){ + return return_type(priv_expand_both_sides + (command, limit_size, preferred_size, received_size, reuse_ptr, false), true); + } + return return_type(0, false); +} + +template +inline typename simple_seq_fit_impl::block_ctrl * + simple_seq_fit_impl:: + priv_next_block_if_free + (typename simple_seq_fit_impl::block_ctrl *ptr) +{ + //Take the address where the next block should go + block_ctrl *next_block = reinterpret_cast + (detail::char_ptr_cast(ptr) + ptr->m_size*Alignment); + + //Check if the adjacent block is in the managed segment + std::size_t distance = (detail::char_ptr_cast(next_block) - detail::char_ptr_cast(this))/Alignment; + if(distance >= (m_header.m_size/Alignment)){ + //"next_block" does not exist so we can't expand "block" + return 0; + } + + if(!next_block->m_next) + return 0; + + return next_block; +} + +template +inline + std::pair::block_ctrl * + ,typename simple_seq_fit_impl::block_ctrl *> + simple_seq_fit_impl:: + priv_prev_block_if_free + (typename simple_seq_fit_impl::block_ctrl *ptr) +{ + typedef std::pair prev_pair_t; + //Take the address where the previous block should go + block_ctrl *root = &m_header.m_root; + block_ctrl *prev_2_block = root; + block_ctrl *prev_block = detail::get_pointer(root->m_next); + while((detail::char_ptr_cast(prev_block) + prev_block->m_size*Alignment) + != (detail::char_ptr_cast(ptr)) + && prev_block != root){ + prev_2_block = prev_block; + prev_block = detail::get_pointer(prev_block->m_next); + } + + if(prev_block == root || !prev_block->m_next) + return prev_pair_t(0, 0); + + //Check if the previous block is in the managed segment + std::size_t distance = (detail::char_ptr_cast(prev_block) - detail::char_ptr_cast(this))/Alignment; + if(distance >= (m_header.m_size/Alignment)){ + //"previous_block" does not exist so we can't expand "block" + return prev_pair_t(0, 0); + } + return prev_pair_t(prev_2_block, prev_block); +} + + +template +inline bool simple_seq_fit_impl:: + priv_expand (void *ptr + ,std::size_t min_size + ,std::size_t preferred_size + ,std::size_t &received_size) +{ + //Obtain the real size of the block + block_ctrl *block = reinterpret_cast + (detail::char_ptr_cast(ptr) - BlockCtrlBytes); + std::size_t old_block_size = block->m_size; + + //All used blocks' next is marked with 0 so check it + assert(block->m_next == 0); + + //Put this to a safe value + received_size = old_block_size*Alignment - BlockCtrlBytes; + + //Now translate it to Alignment units + min_size = detail::get_rounded_size(min_size, Alignment)/Alignment; + preferred_size = detail::get_rounded_size(preferred_size, Alignment)/Alignment; + + //Some parameter checks + if(min_size > preferred_size) + return false; + + std::size_t data_size = old_block_size - BlockCtrlSize; + + if(data_size >= min_size) + return true; + + block_ctrl *next_block = priv_next_block_if_free(block); + if(!next_block){ + return false; + } + + //Is "block" + "next_block" big enough? + std::size_t merged_size = old_block_size + next_block->m_size; + + //Now we can expand this block further than before + received_size = merged_size*Alignment - BlockCtrlBytes; + + if(merged_size < (min_size + BlockCtrlSize)){ + return false; + } + + //We can fill expand. Merge both blocks, + block->m_next = next_block->m_next; + block->m_size = merged_size; + + //Find the previous free block of next_block + block_ctrl *prev = &m_header.m_root; + while(detail::get_pointer(prev->m_next) != next_block){ + prev = detail::get_pointer(prev->m_next); + } + + //Now insert merged block in the free list + //This allows reusing allocation logic in this function + m_header.m_allocated -= old_block_size*Alignment; + prev->m_next = block; + + //Now use check and allocate to do the allocation logic + preferred_size += BlockCtrlSize; + std::size_t nunits = preferred_size < merged_size ? preferred_size : merged_size; + + //This must success since nunits is less than merged_size! + if(!this->priv_check_and_allocate (nunits, prev, block, received_size)){ + //Something very ugly is happening here. This is a bug + //or there is memory corruption + assert(0); + return false; + } + return true; +} + +template +inline bool simple_seq_fit_impl:: + priv_shrink (void *ptr + ,std::size_t max_size + ,std::size_t preferred_size + ,std::size_t &received_size) +{ + //Obtain the real size of the block + block_ctrl *block = reinterpret_cast + (detail::char_ptr_cast(ptr) - BlockCtrlBytes); + std::size_t block_size = block->m_size; + + //All used blocks' next is marked with 0 so check it + assert(block->m_next == 0); + + //Put this to a safe value + received_size = block_size*Alignment - BlockCtrlBytes; + + //Now translate it to Alignment units + max_size = max_size/Alignment; + preferred_size = detail::get_rounded_size(preferred_size, Alignment)/Alignment; + + //Some parameter checks + if(max_size < preferred_size) + return false; + + std::size_t data_size = block_size - BlockCtrlSize; + + if(data_size < preferred_size) + return false; + + if(data_size == preferred_size) + return true; + + //We must be able to create at least a new empty block + if((data_size - preferred_size) < BlockCtrlSize){ + return false; + } + + //Now we can just rewrite the size of the old buffer + block->m_size = preferred_size + BlockCtrlSize; + + //Update new size + received_size = preferred_size*Alignment; + + //We create the new block + block = reinterpret_cast + (detail::char_ptr_cast(block) + block->m_size*Alignment); + + //Write control data to simulate this new block was previously allocated + block->m_next = 0; + block->m_size = data_size - preferred_size; + + //Now deallocate the new block to insert it in the free list + this->priv_deallocate(detail::char_ptr_cast(block)+BlockCtrlBytes); + return true; +} + +template +inline void* simple_seq_fit_impl:: + priv_allocate_aligned(std::size_t nbytes, std::size_t alignment) +{ + //Ensure power of 2 + if ((alignment & (alignment - std::size_t(1u))) != 0){ + //Alignment is not power of two + assert((alignment & (alignment - std::size_t(1u))) != 0); + return 0; + } + + std::size_t ignore; + if(alignment <= Alignment){ + return priv_allocate(allocate_new, nbytes, nbytes, ignore).first; + } + + std::size_t request = + nbytes + alignment + MinBlockSize*Alignment - BlockCtrlBytes; + void *buffer = priv_allocate(allocate_new, request, request, ignore).first; + if(!buffer) + return 0; + else if ((((std::size_t)(buffer)) % alignment) == 0) + return buffer; + + char *aligned_portion = (char*) + ((std::size_t)((char*)buffer + alignment - 1) & -alignment); + + char *pos = ((aligned_portion - (char*)buffer) >= (MinBlockSize*Alignment)) ? + aligned_portion : (aligned_portion + alignment); + + + block_ctrl *first = reinterpret_cast + (detail::char_ptr_cast(buffer) - BlockCtrlBytes); + + block_ctrl *second = reinterpret_cast + (detail::char_ptr_cast(pos) - BlockCtrlBytes); + + std::size_t old_size = first->m_size; + + first->m_size = ((char*)second - (char*)first)/Alignment; + second->m_size = old_size - first->m_size; + + //Write control data to simulate this new block was previously allocated + second->m_next = 0; + + //Now deallocate the new block to insert it in the free list + this->priv_deallocate(detail::char_ptr_cast(first) + BlockCtrlBytes); + return detail::char_ptr_cast(second) + BlockCtrlBytes; +} + +template inline +void* simple_seq_fit_impl::priv_check_and_allocate + (std::size_t nunits + ,typename simple_seq_fit_impl::block_ctrl* prev + ,typename simple_seq_fit_impl::block_ctrl* block + ,std::size_t &received_size) +{ + std::size_t upper_nunits = nunits + BlockCtrlSize; + bool found = false; + + if (block->m_size > upper_nunits){ + //This block is bigger than needed, split it in + //two blocks, the first's size will be (block->m_size-units) + //the second's size (units) + std::size_t total_size = block->m_size; + block->m_size = nunits; + block_ctrl *new_block = reinterpret_cast + (detail::char_ptr_cast(block) + Alignment*nunits); + new_block->m_size = total_size - nunits; + new_block->m_next = block->m_next; + prev->m_next = new_block; + found = true; + } + else if (block->m_size >= nunits){ + //This block has exactly the right size with an extra + //unusable extra bytes. + prev->m_next = block->m_next; + found = true; + } + + if(found){ + //We need block_ctrl for deallocation stuff, so + //return memory user can overwrite + m_header.m_allocated += block->m_size*Alignment; + received_size = block->m_size*Alignment - BlockCtrlBytes; + //Mark the block as allocated + block->m_next = 0; + //Check alignment + assert(((detail::char_ptr_cast(block) - detail::char_ptr_cast(this)) + % Alignment) == 0 ); + return detail::char_ptr_cast(block)+BlockCtrlBytes; + } + return 0; +} + +template +void simple_seq_fit_impl::deallocate(void* addr) +{ + if(!addr) return; + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return this->priv_deallocate(addr); +} + +template +void simple_seq_fit_impl::priv_deallocate(void* addr) +{ + if(!addr) return; + + //Let's get free block list. List is always sorted + //by memory address to allow block merging. + //Pointer next always points to the first + //(lower address) block + block_ctrl_ptr prev = &m_header.m_root; + block_ctrl_ptr pos = m_header.m_root.m_next; + block_ctrl_ptr block = reinterpret_cast + (detail::char_ptr_cast(addr) - BlockCtrlBytes); + + //All used blocks' next is marked with 0 so check it + assert(block->m_next == 0); + + //Check if alignment and block size are right + assert((detail::char_ptr_cast(addr) - detail::char_ptr_cast(this)) + % Alignment == 0 ); + + std::size_t total_size = Alignment*block->m_size; + assert(m_header.m_allocated >= total_size); + + //Update used memory count + m_header.m_allocated -= total_size; + + //Let's find the previous and the next block of the block to deallocate + //This ordering comparison must be done with original pointers + //types since their mapping to raw pointers can be different + //in each process + while((detail::get_pointer(pos) != &m_header.m_root) && (block > pos)){ + prev = pos; + pos = pos->m_next; + } + + //Try to combine with upper block + if ((detail::char_ptr_cast(detail::get_pointer(block)) + + Alignment*block->m_size) == + detail::char_ptr_cast(detail::get_pointer(pos))){ + + block->m_size += pos->m_size; + block->m_next = pos->m_next; + } + else{ + block->m_next = pos; + } + + //Try to combine with lower block + if ((detail::char_ptr_cast(detail::get_pointer(prev)) + + Alignment*prev->m_size) == + detail::char_ptr_cast(detail::get_pointer(block))){ + prev->m_size += block->m_size; + prev->m_next = block->m_next; + } + else{ + prev->m_next = block; + } +} + +} //namespace detail { + +} //namespace interprocess { + +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP + diff --git a/win32/include/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp b/win32/include/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp new file mode 100755 index 000000000..be7f3446d --- /dev/null +++ b/win32/include/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp @@ -0,0 +1,1098 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP +#define BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes sequential fit algorithm used to allocate objects in shared memory. +//!This class is intended as a base class for single segment and multi-segment +//!implementations. + +namespace boost { +namespace interprocess { +namespace detail { + +//!This class implements the simple sequential fit algorithm with a simply +//!linked list of free buffers. +//!This class is intended as a base class for single segment and multi-segment +//!implementations. +template +class simple_seq_fit_impl +{ + //Non-copyable + simple_seq_fit_impl(); + simple_seq_fit_impl(const simple_seq_fit_impl &); + simple_seq_fit_impl &operator=(const simple_seq_fit_impl &); + + public: + + //!Shared interprocess_mutex family used for the rest of the Interprocess framework + typedef MutexFamily mutex_family; + //!Pointer type to be used with the rest of the Interprocess framework + typedef VoidPointer void_pointer; + + typedef detail::basic_multiallocation_iterator + multiallocation_iterator; + typedef detail::basic_multiallocation_chain + multiallocation_chain; + + private: + class block_ctrl; + typedef typename detail:: + pointer_to_other::type block_ctrl_ptr; + + class block_ctrl; + friend class block_ctrl; + + //!Block control structure + class block_ctrl + { + public: + //!Offset pointer to the next block. + block_ctrl_ptr m_next; + //!This block's memory size (including block_ctrl + //!header) in BasicSize units + std::size_t m_size; + + std::size_t get_user_bytes() const + { return this->m_size*Alignment - BlockCtrlBytes; } + + std::size_t get_total_bytes() const + { return this->m_size*Alignment; } + }; + + //!Shared interprocess_mutex to protect memory allocate/deallocate + typedef typename MutexFamily::mutex_type interprocess_mutex; + + //!This struct includes needed data and derives from + //!interprocess_mutex to allow EBO when using null interprocess_mutex + struct header_t : public interprocess_mutex + { + //!Pointer to the first free block + block_ctrl m_root; + //!Allocated bytes for internal checking + std::size_t m_allocated; + //!The size of the memory segment + std::size_t m_size; + //!The extra size required by the segment + std::size_t m_extra_hdr_bytes; + } m_header; + + friend class detail::basic_multiallocation_iterator; + friend class detail::memory_algorithm_common; + + typedef detail::memory_algorithm_common algo_impl_t; + + public: + //!Constructor. "size" is the total size of the managed memory segment, + //!"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(simple_seq_fit_impl) + //!offset that the allocator should not use at all. + simple_seq_fit_impl (std::size_t size, std::size_t extra_hdr_bytes); + + //!Destructor + ~simple_seq_fit_impl(); + + //!Obtains the minimum size needed by the algorithm + static std::size_t get_min_size (std::size_t extra_hdr_bytes); + + //Functions for single segment management + + //!Allocates bytes, returns 0 if there is not more memory + void* allocate (std::size_t nbytes); + + /// @cond + + //!Multiple element allocation, same size + multiallocation_iterator allocate_many(std::size_t elem_bytes, std::size_t num_elements); + + //!Multiple element allocation, different size + multiallocation_iterator allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element); + + //!Multiple element deallocation + void deallocate_many(multiallocation_iterator it); + + /// @endcond + + //!Deallocates previously allocated bytes + void deallocate (void *addr); + + //!Returns the size of the memory segment + std::size_t get_size() const; + + //!Returns the number of free bytes of the memory segment + std::size_t get_free_memory() const; + + //!Increases managed memory in extra_size bytes more + void grow(std::size_t extra_size); + + //!Decreases managed memory as much as possible + void shrink_to_fit(); + + //!Returns true if all allocated memory has been deallocated + bool all_memory_deallocated(); + + //!Makes an internal sanity check and returns true if success + bool check_sanity(); + + //!Initializes to zero all the memory that's not in use. + //!This function is normally used for security reasons. + void zero_free_memory(); + + template + std::pair + allocation_command (allocation_type command, std::size_t limit_size, + std::size_t preferred_size,std::size_t &received_size, + T *reuse_ptr = 0); + + std::pair + raw_allocation_command (allocation_type command, std::size_t limit_size, + std::size_t preferred_size,std::size_t &received_size, + void *reuse_ptr = 0, std::size_t sizeof_object = 1); + + //!Returns the size of the buffer previously allocated pointed by ptr + std::size_t size(const void *ptr) const; + + //!Allocates aligned bytes, returns 0 if there is not more memory. + //!Alignment must be power of 2 + void* allocate_aligned (std::size_t nbytes, std::size_t alignment); + + private: + + //!Obtains the pointer returned to the user from the block control + static void *priv_get_user_buffer(const block_ctrl *block); + + //!Obtains the block control structure of the user buffer + static block_ctrl *priv_get_block(const void *ptr); + + //!Real allocation algorithm with min allocation option + std::pair priv_allocate(allocation_type command + ,std::size_t min_size + ,std::size_t preferred_size + ,std::size_t &received_size + ,void *reuse_ptr = 0); + + std::pair priv_allocation_command(allocation_type command + ,std::size_t min_size + ,std::size_t preferred_size + ,std::size_t &received_size + ,void *reuse_ptr + ,std::size_t sizeof_object); + + //!Returns the number of total units that a user buffer + //!of "userbytes" bytes really occupies (including header) + static std::size_t priv_get_total_units(std::size_t userbytes); + + static std::size_t priv_first_block_offset(const void *this_ptr, std::size_t extra_hdr_bytes); + std::size_t priv_block_end_offset() const; + + //!Returns next block if it's free. + //!Returns 0 if next block is not free. + block_ctrl *priv_next_block_if_free(block_ctrl *ptr); + + //!Check if this block is free (not allocated) + bool priv_is_allocated_block(block_ctrl *ptr); + + //!Returns previous block's if it's free. + //!Returns 0 if previous block is not free. + std::pairpriv_prev_block_if_free(block_ctrl *ptr); + + //!Real expand function implementation + bool priv_expand(void *ptr + ,std::size_t min_size, std::size_t preferred_size + ,std::size_t &received_size); + + //!Real expand to both sides implementation + void* priv_expand_both_sides(allocation_type command + ,std::size_t min_size + ,std::size_t preferred_size + ,std::size_t &received_size + ,void *reuse_ptr + ,bool only_preferred_backwards); + + //!Real private aligned allocation function + //void* priv_allocate_aligned (std::size_t nbytes, std::size_t alignment); + + //!Checks if block has enough memory and splits/unlinks the block + //!returning the address to the users + void* priv_check_and_allocate(std::size_t units + ,block_ctrl* prev + ,block_ctrl* block + ,std::size_t &received_size); + //!Real deallocation algorithm + void priv_deallocate(void *addr); + + //!Makes a new memory portion available for allocation + void priv_add_segment(void *addr, std::size_t size); + + void priv_mark_new_allocated_block(block_ctrl *block); + + public: + static const std::size_t Alignment = detail::alignment_of::value; + private: + static const std::size_t BlockCtrlBytes = detail::ct_rounded_size::value; + static const std::size_t BlockCtrlUnits = BlockCtrlBytes/Alignment; + static const std::size_t MinBlockUnits = BlockCtrlUnits; + static const std::size_t MinBlockSize = MinBlockUnits*Alignment; + static const std::size_t AllocatedCtrlBytes = BlockCtrlBytes; + static const std::size_t AllocatedCtrlUnits = BlockCtrlUnits; + static const std::size_t UsableByPreviousChunk = 0; + + public: + static const std::size_t PayloadPerAllocation = BlockCtrlBytes; +}; + +template +inline std::size_t simple_seq_fit_impl + ::priv_first_block_offset(const void *this_ptr, std::size_t extra_hdr_bytes) +{ + //First align "this" pointer + std::size_t uint_this = (std::size_t)this_ptr; + std::size_t uint_aligned_this = uint_this/Alignment*Alignment; + std::size_t this_disalignment = (uint_this - uint_aligned_this); + std::size_t block1_off = + detail::get_rounded_size(sizeof(simple_seq_fit_impl) + extra_hdr_bytes + this_disalignment, Alignment) + - this_disalignment; + algo_impl_t::assert_alignment(this_disalignment + block1_off); + return block1_off; +} + +template +inline std::size_t simple_seq_fit_impl + ::priv_block_end_offset() const +{ + //First align "this" pointer + std::size_t uint_this = (std::size_t)this; + std::size_t uint_aligned_this = uint_this/Alignment*Alignment; + std::size_t this_disalignment = (uint_this - uint_aligned_this); + std::size_t old_end = + detail::get_truncated_size(m_header.m_size + this_disalignment, Alignment) + - this_disalignment; + algo_impl_t::assert_alignment(old_end + this_disalignment); + return old_end; +} + +template +inline simple_seq_fit_impl:: + simple_seq_fit_impl(std::size_t size, std::size_t extra_hdr_bytes) +{ + //Initialize sizes and counters + m_header.m_allocated = 0; + m_header.m_size = size; + m_header.m_extra_hdr_bytes = extra_hdr_bytes; + + //Initialize pointers + std::size_t block1_off = priv_first_block_offset(this, extra_hdr_bytes); + m_header.m_root.m_next = reinterpret_cast + (detail::char_ptr_cast(this) + block1_off); + algo_impl_t::assert_alignment(detail::get_pointer(m_header.m_root.m_next)); + m_header.m_root.m_next->m_size = (size - block1_off)/Alignment; + m_header.m_root.m_next->m_next = &m_header.m_root; +} + +template +inline simple_seq_fit_impl::~simple_seq_fit_impl() +{ + //There is a memory leak! +// assert(m_header.m_allocated == 0); +// assert(m_header.m_root.m_next->m_next == block_ctrl_ptr(&m_header.m_root)); +} + +template +inline void simple_seq_fit_impl::grow(std::size_t extra_size) +{ + //Old highest address block's end offset + std::size_t old_end = this->priv_block_end_offset(); + + //Update managed buffer's size + m_header.m_size += extra_size; + + //We need at least MinBlockSize blocks to create a new block + if((m_header.m_size - old_end) < MinBlockSize){ + return; + } + + //We'll create a new free block with extra_size bytes + block_ctrl *new_block = reinterpret_cast + (detail::char_ptr_cast(this) + old_end); + + algo_impl_t::assert_alignment(new_block); + new_block->m_next = 0; + new_block->m_size = (m_header.m_size - old_end)/Alignment; + m_header.m_allocated += new_block->m_size*Alignment; + this->priv_deallocate(priv_get_user_buffer(new_block)); +} + +template +void simple_seq_fit_impl::shrink_to_fit() +{ + //Get the root and the first memory block + block_ctrl *prev = &m_header.m_root; + block_ctrl *last = &m_header.m_root; + block_ctrl *block = detail::get_pointer(last->m_next); + block_ctrl *root = &m_header.m_root; + + //No free block? + if(block == root) return; + + //Iterate through the free block list + while(block != root){ + prev = last; + last = block; + block = detail::get_pointer(block->m_next); + } + + char *last_free_end_address = (char*)last + last->m_size*Alignment; + if(last_free_end_address != ((char*)this + priv_block_end_offset())){ + //there is an allocated block in the end of this block + //so no shrinking is possible + return; + } + + //Check if have only 1 big free block + void *unique_block = 0; + if(!m_header.m_allocated){ + assert(prev == root); + std::size_t ignore; + unique_block = priv_allocate(allocate_new, 0, 0, ignore).first; + if(!unique_block) + return; + last = detail::get_pointer(m_header.m_root.m_next); + assert(last_free_end_address == ((char*)last + last->m_size*Alignment)); + } + std::size_t last_units = last->m_size; + + std::size_t received_size; + void *addr = priv_check_and_allocate(last_units, prev, last, received_size); + (void)addr; + assert(addr); + assert(received_size == last_units*Alignment - AllocatedCtrlBytes); + + //Shrink it + m_header.m_size /= Alignment; + m_header.m_size -= last->m_size; + m_header.m_size *= Alignment; + m_header.m_allocated -= last->m_size*Alignment; + + if(unique_block) + priv_deallocate(unique_block); +} + +template +inline void simple_seq_fit_impl:: + priv_mark_new_allocated_block(block_ctrl *new_block) +{ + new_block->m_next = 0; +} + +template +inline +typename simple_seq_fit_impl::block_ctrl * + simple_seq_fit_impl::priv_get_block(const void *ptr) +{ + return reinterpret_cast(detail::char_ptr_cast(ptr) - AllocatedCtrlBytes); +} + +template +inline +void *simple_seq_fit_impl:: + priv_get_user_buffer(const typename simple_seq_fit_impl::block_ctrl *block) +{ return detail::char_ptr_cast(block) + AllocatedCtrlBytes; } + +template +inline void simple_seq_fit_impl::priv_add_segment(void *addr, std::size_t size) +{ + algo_impl_t::assert_alignment(addr); + //Check size + assert(!(size < MinBlockSize)); + if(size < MinBlockSize) + return; + //Construct big block using the new segment + block_ctrl *new_block = static_cast(addr); + new_block->m_size = size/Alignment; + new_block->m_next = 0; + //Simulate this block was previously allocated + m_header.m_allocated += new_block->m_size*Alignment; + //Return block and insert it in the free block list + this->priv_deallocate(priv_get_user_buffer(new_block)); +} + +template +inline std::size_t simple_seq_fit_impl::get_size() const + { return m_header.m_size; } + +template +inline std::size_t simple_seq_fit_impl::get_free_memory() const +{ + return m_header.m_size - m_header.m_allocated - + algo_impl_t::multiple_of_units(sizeof(*this) + m_header.m_extra_hdr_bytes); +} + +template +inline std::size_t simple_seq_fit_impl:: + get_min_size (std::size_t extra_hdr_bytes) +{ + return detail::get_rounded_size(sizeof(simple_seq_fit_impl),Alignment) + + detail::get_rounded_size(extra_hdr_bytes,Alignment) + + MinBlockSize; +} + +template +inline bool simple_seq_fit_impl:: + all_memory_deallocated() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return m_header.m_allocated == 0 && + detail::get_pointer(m_header.m_root.m_next->m_next) == &m_header.m_root; +} + +template +inline void simple_seq_fit_impl::zero_free_memory() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + block_ctrl *block = detail::get_pointer(m_header.m_root.m_next); + + //Iterate through all free portions + do{ + //Just clear user the memory part reserved for the user + std::memset( priv_get_user_buffer(block) + , 0 + , block->get_user_bytes()); + block = detail::get_pointer(block->m_next); + } + while(block != &m_header.m_root); +} + +template +inline bool simple_seq_fit_impl:: + check_sanity() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + block_ctrl *block = detail::get_pointer(m_header.m_root.m_next); + + std::size_t free_memory = 0; + + //Iterate through all blocks obtaining their size + while(block != &m_header.m_root){ + algo_impl_t::assert_alignment(block); + if(!algo_impl_t::check_alignment(block)) + return false; + //Free blocks's next must be always valid + block_ctrl *next = detail::get_pointer(block->m_next); + if(!next){ + return false; + } + free_memory += block->m_size*Alignment; + block = next; + } + + //Check allocated bytes are less than size + if(m_header.m_allocated > m_header.m_size){ + return false; + } + + //Check free bytes are less than size + if(free_memory > m_header.m_size){ + return false; + } + return true; +} + +template +inline void* simple_seq_fit_impl:: + allocate(std::size_t nbytes) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + std::size_t ignore; + return priv_allocate(allocate_new, nbytes, nbytes, ignore).first; +} + +template +inline void* simple_seq_fit_impl:: + allocate_aligned(std::size_t nbytes, std::size_t alignment) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return algo_impl_t:: + allocate_aligned(this, nbytes, alignment); +} + +template +template +inline std::pair simple_seq_fit_impl:: + allocation_command (allocation_type command, std::size_t limit_size, + std::size_t preferred_size,std::size_t &received_size, + T *reuse_ptr) +{ + std::pair ret = priv_allocation_command + (command, limit_size, preferred_size, received_size, (void*)reuse_ptr, sizeof(T)); + + BOOST_ASSERT(0 == ((std::size_t)ret.first % detail::alignment_of::value)); + return std::pair(static_cast(ret.first), ret.second); +} + +template +inline std::pair simple_seq_fit_impl:: + raw_allocation_command (allocation_type command, std::size_t limit_objects, + std::size_t preferred_objects,std::size_t &received_objects, + void *reuse_ptr, std::size_t sizeof_object) +{ + if(!sizeof_object) + return std::pair((void*)0, 0); + if(command & try_shrink_in_place){ + bool success = algo_impl_t::try_shrink + ( this, reuse_ptr, limit_objects*sizeof_object + , preferred_objects*sizeof_object, received_objects); + received_objects /= sizeof_object; + return std::pair ((success ? reuse_ptr : 0), true); + } + return priv_allocation_command + (command, limit_objects, preferred_objects, received_objects, reuse_ptr, sizeof_object); +} + +template +inline std::pair simple_seq_fit_impl:: + priv_allocation_command (allocation_type command, std::size_t limit_size, + std::size_t preferred_size, std::size_t &received_size, + void *reuse_ptr, std::size_t sizeof_object) +{ + command &= ~expand_bwd; + if(!command) return std::pair((void*)0, false); + + std::pair ret; + std::size_t max_count = m_header.m_size/sizeof_object; + if(limit_size > max_count || preferred_size > max_count){ + ret.first = 0; return ret; + } + std::size_t l_size = limit_size*sizeof_object; + std::size_t p_size = preferred_size*sizeof_object; + std::size_t r_size; + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + ret = priv_allocate(command, l_size, p_size, r_size, reuse_ptr); + } + received_size = r_size/sizeof_object; + return ret; +} + +template +inline std::size_t simple_seq_fit_impl:: + size(const void *ptr) const +{ + //We need no synchronization since this block is not going + //to be modified + //Obtain the real size of the block + block_ctrl *block = reinterpret_cast + (priv_get_block(detail::char_ptr_cast(const_cast(ptr)))); + return block->get_user_bytes(); +} + +template +void* simple_seq_fit_impl:: + priv_expand_both_sides(allocation_type command + ,std::size_t min_size + ,std::size_t preferred_size + ,std::size_t &received_size + ,void *reuse_ptr + ,bool only_preferred_backwards) +{ + typedef std::pair prev_block_t; + block_ctrl *reuse = priv_get_block(reuse_ptr); + received_size = 0; + + if(this->size(reuse_ptr) > min_size){ + received_size = this->size(reuse_ptr); + return reuse_ptr; + } + + if(command & expand_fwd){ + if(priv_expand(reuse_ptr, min_size, preferred_size, received_size)) + return reuse_ptr; + } + else{ + received_size = this->size(reuse_ptr); + } + if(command & expand_bwd){ + std::size_t extra_forward = !received_size ? 0 : received_size + BlockCtrlBytes; + prev_block_t prev_pair = priv_prev_block_if_free(reuse); + block_ctrl *prev = prev_pair.second; + if(!prev){ + return 0; + } + + std::size_t needs_backwards = + detail::get_rounded_size(preferred_size - extra_forward, Alignment); + + if(!only_preferred_backwards){ + max_value(detail::get_rounded_size(min_size - extra_forward, Alignment) + ,min_value(prev->get_user_bytes(), needs_backwards)); + } + + //Check if previous block has enough size + if((prev->get_user_bytes()) >= needs_backwards){ + //Now take all next space. This will succeed + if(!priv_expand(reuse_ptr, received_size, received_size, received_size)){ + assert(0); + } + + //We need a minimum size to split the previous one + if((prev->get_user_bytes() - needs_backwards) > 2*BlockCtrlBytes){ + block_ctrl *new_block = reinterpret_cast + (detail::char_ptr_cast(reuse) - needs_backwards - BlockCtrlBytes); + new_block->m_next = 0; + new_block->m_size = + BlockCtrlUnits + (needs_backwards + extra_forward)/Alignment; + prev->m_size = + (prev->get_total_bytes() - needs_backwards)/Alignment - BlockCtrlUnits; + received_size = needs_backwards + extra_forward; + m_header.m_allocated += needs_backwards + BlockCtrlBytes; + return priv_get_user_buffer(new_block); + } + else{ + //Just merge the whole previous block + block_ctrl *prev_2_block = prev_pair.first; + //Update received size and allocation + received_size = extra_forward + prev->get_user_bytes(); + m_header.m_allocated += prev->get_total_bytes(); + //Now unlink it from previous block + prev_2_block->m_next = prev->m_next; + prev->m_size = reuse->m_size + prev->m_size; + prev->m_next = 0; + priv_get_user_buffer(prev); + } + } + } + return 0; +} + +template +inline typename simple_seq_fit_impl::multiallocation_iterator + simple_seq_fit_impl:: + allocate_many(std::size_t elem_bytes, std::size_t num_elements) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return algo_impl_t:: + allocate_many(this, elem_bytes, num_elements); +} + +template +inline void simple_seq_fit_impl:: + deallocate_many(typename simple_seq_fit_impl::multiallocation_iterator it) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + while(it){ + void *addr = &*it; + ++it; + this->priv_deallocate(addr); + } +} + +template +inline typename simple_seq_fit_impl::multiallocation_iterator + simple_seq_fit_impl:: + allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element); +} + +template +inline std::size_t simple_seq_fit_impl:: + priv_get_total_units(std::size_t userbytes) +{ + std::size_t s = detail::get_rounded_size(userbytes, Alignment)/Alignment; + if(!s) ++s; + return BlockCtrlUnits + s; +} + +template +std::pair simple_seq_fit_impl:: + priv_allocate(allocation_type command + ,std::size_t limit_size + ,std::size_t preferred_size + ,std::size_t &received_size + ,void *reuse_ptr) +{ + if(command & shrink_in_place){ + bool success = + algo_impl_t::shrink(this, reuse_ptr, limit_size, preferred_size, received_size); + return std::pair ((success ? reuse_ptr : 0), true); + } + typedef std::pair return_type; + received_size = 0; + + if(limit_size > preferred_size) + return return_type((void*)0, false); + + //Number of units to request (including block_ctrl header) + std::size_t nunits = detail::get_rounded_size(preferred_size, Alignment)/Alignment + BlockCtrlUnits; + + //Get the root and the first memory block + block_ctrl *prev = &m_header.m_root; + block_ctrl *block = detail::get_pointer(prev->m_next); + block_ctrl *root = &m_header.m_root; + block_ctrl *biggest_block = 0; + block_ctrl *prev_biggest_block = 0; + std::size_t biggest_size = 0; + + //Expand in place + //reuse_ptr, limit_size, preferred_size, received_size + // + if(reuse_ptr && (command & (expand_fwd | expand_bwd))){ + void *ret = priv_expand_both_sides + (command, limit_size, preferred_size, received_size, reuse_ptr, true); + if(ret){ + algo_impl_t::assert_alignment(ret); + return return_type(ret, true); + } + } + + if(command & allocate_new){ + received_size = 0; + while(block != root){ + //Update biggest block pointers + if(block->m_size > biggest_size){ + prev_biggest_block = prev; + biggest_size = block->m_size; + biggest_block = block; + } + algo_impl_t::assert_alignment(block); + void *addr = this->priv_check_and_allocate(nunits, prev, block, received_size); + if(addr){ + algo_impl_t::assert_alignment(addr); + return return_type(addr, false); + } + //Bad luck, let's check next block + prev = block; + block = detail::get_pointer(block->m_next); + } + + //Bad luck finding preferred_size, now if we have any biggest_block + //try with this block + if(biggest_block){ + std::size_t limit_units = detail::get_rounded_size(limit_size, Alignment)/Alignment + BlockCtrlUnits; + if(biggest_block->m_size < limit_units) + return return_type((void*)0, false); + + received_size = biggest_block->m_size*Alignment - BlockCtrlUnits; + void *ret = this->priv_check_and_allocate + (biggest_block->m_size, prev_biggest_block, biggest_block, received_size); + assert(ret != 0); + algo_impl_t::assert_alignment(ret); + return return_type(ret, false); + } + } + //Now try to expand both sides with min size + if(reuse_ptr && (command & (expand_fwd | expand_bwd))){ + return_type ret (priv_expand_both_sides + (command, limit_size, preferred_size, received_size, reuse_ptr, false), true); + algo_impl_t::assert_alignment(ret.first); + return ret; + } + return return_type((void*)0, false); +} + +template inline +bool simple_seq_fit_impl::priv_is_allocated_block + (typename simple_seq_fit_impl::block_ctrl *block) +{ return block->m_next == 0; } + +template +inline typename simple_seq_fit_impl::block_ctrl * + simple_seq_fit_impl:: + priv_next_block_if_free + (typename simple_seq_fit_impl::block_ctrl *ptr) +{ + //Take the address where the next block should go + block_ctrl *next_block = reinterpret_cast + (detail::char_ptr_cast(ptr) + ptr->m_size*Alignment); + + //Check if the adjacent block is in the managed segment + std::size_t distance = (detail::char_ptr_cast(next_block) - detail::char_ptr_cast(this))/Alignment; + if(distance >= (m_header.m_size/Alignment)){ + //"next_block" does not exist so we can't expand "block" + return 0; + } + + if(!next_block->m_next) + return 0; + + return next_block; +} + +template +inline + std::pair::block_ctrl * + ,typename simple_seq_fit_impl::block_ctrl *> + simple_seq_fit_impl:: + priv_prev_block_if_free + (typename simple_seq_fit_impl::block_ctrl *ptr) +{ + typedef std::pair prev_pair_t; + //Take the address where the previous block should go + block_ctrl *root = &m_header.m_root; + block_ctrl *prev_2_block = root; + block_ctrl *prev_block = detail::get_pointer(root->m_next); + while((detail::char_ptr_cast(prev_block) + prev_block->m_size*Alignment) + != (detail::char_ptr_cast(ptr)) + && prev_block != root){ + prev_2_block = prev_block; + prev_block = detail::get_pointer(prev_block->m_next); + } + + if(prev_block == root || !prev_block->m_next) + return prev_pair_t((block_ctrl*)0, (block_ctrl*)0); + + //Check if the previous block is in the managed segment + std::size_t distance = (detail::char_ptr_cast(prev_block) - detail::char_ptr_cast(this))/Alignment; + if(distance >= (m_header.m_size/Alignment)){ + //"previous_block" does not exist so we can't expand "block" + return prev_pair_t((block_ctrl*)0, (block_ctrl*)0); + } + return prev_pair_t(prev_2_block, prev_block); +} + + +template +inline bool simple_seq_fit_impl:: + priv_expand (void *ptr + ,std::size_t min_size + ,std::size_t preferred_size + ,std::size_t &received_size) +{ + //Obtain the real size of the block + block_ctrl *block = reinterpret_cast(priv_get_block(ptr)); + std::size_t old_block_size = block->m_size; + + //All used blocks' next is marked with 0 so check it + assert(block->m_next == 0); + + //Put this to a safe value + received_size = old_block_size*Alignment - BlockCtrlBytes; + + //Now translate it to Alignment units + min_size = detail::get_rounded_size(min_size, Alignment)/Alignment; + preferred_size = detail::get_rounded_size(preferred_size, Alignment)/Alignment; + + //Some parameter checks + if(min_size > preferred_size) + return false; + + std::size_t data_size = old_block_size - BlockCtrlUnits; + + if(data_size >= min_size) + return true; + + block_ctrl *next_block = priv_next_block_if_free(block); + if(!next_block){ + return false; + } + + //Is "block" + "next_block" big enough? + std::size_t merged_size = old_block_size + next_block->m_size; + + //Now we can expand this block further than before + received_size = merged_size*Alignment - BlockCtrlBytes; + + if(merged_size < (min_size + BlockCtrlUnits)){ + return false; + } + + //We can fill expand. Merge both blocks, + block->m_next = next_block->m_next; + block->m_size = merged_size; + + //Find the previous free block of next_block + block_ctrl *prev = &m_header.m_root; + while(detail::get_pointer(prev->m_next) != next_block){ + prev = detail::get_pointer(prev->m_next); + } + + //Now insert merged block in the free list + //This allows reusing allocation logic in this function + m_header.m_allocated -= old_block_size*Alignment; + prev->m_next = block; + + //Now use check and allocate to do the allocation logic + preferred_size += BlockCtrlUnits; + std::size_t nunits = preferred_size < merged_size ? preferred_size : merged_size; + + //This must success since nunits is less than merged_size! + if(!this->priv_check_and_allocate (nunits, prev, block, received_size)){ + //Something very ugly is happening here. This is a bug + //or there is memory corruption + assert(0); + return false; + } + return true; +} + +template inline +void* simple_seq_fit_impl::priv_check_and_allocate + (std::size_t nunits + ,typename simple_seq_fit_impl::block_ctrl* prev + ,typename simple_seq_fit_impl::block_ctrl* block + ,std::size_t &received_size) +{ + std::size_t upper_nunits = nunits + BlockCtrlUnits; + bool found = false; + + if (block->m_size > upper_nunits){ + //This block is bigger than needed, split it in + //two blocks, the first's size will be "units" + //the second's size will be "block->m_size-units" + std::size_t total_size = block->m_size; + block->m_size = nunits; + block_ctrl *new_block = reinterpret_cast + (detail::char_ptr_cast(block) + Alignment*nunits); + new_block->m_size = total_size - nunits; + new_block->m_next = block->m_next; + prev->m_next = new_block; + found = true; + } + else if (block->m_size >= nunits){ + //This block has exactly the right size with an extra + //unusable extra bytes. + prev->m_next = block->m_next; + found = true; + } + + if(found){ + //We need block_ctrl for deallocation stuff, so + //return memory user can overwrite + m_header.m_allocated += block->m_size*Alignment; + received_size = block->get_user_bytes(); + //Mark the block as allocated + block->m_next = 0; + //Check alignment + algo_impl_t::assert_alignment(block); + return priv_get_user_buffer(block); + } + return 0; +} + +template +void simple_seq_fit_impl::deallocate(void* addr) +{ + if(!addr) return; + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return this->priv_deallocate(addr); +} + +template +void simple_seq_fit_impl::priv_deallocate(void* addr) +{ + if(!addr) return; + + //Let's get free block list. List is always sorted + //by memory address to allow block merging. + //Pointer next always points to the first + //(lower address) block + block_ctrl * prev = &m_header.m_root; + block_ctrl * pos = detail::get_pointer(m_header.m_root.m_next); + block_ctrl * block = reinterpret_cast(priv_get_block(addr)); + + //All used blocks' next is marked with 0 so check it + assert(block->m_next == 0); + + //Check if alignment and block size are right + algo_impl_t::assert_alignment(addr); + + std::size_t total_size = Alignment*block->m_size; + assert(m_header.m_allocated >= total_size); + + //Update used memory count + m_header.m_allocated -= total_size; + + //Let's find the previous and the next block of the block to deallocate + //This ordering comparison must be done with original pointers + //types since their mapping to raw pointers can be different + //in each process + while((detail::get_pointer(pos) != &m_header.m_root) && (block > pos)){ + prev = pos; + pos = detail::get_pointer(pos->m_next); + } + + //Try to combine with upper block + if ((detail::char_ptr_cast(detail::get_pointer(block)) + + Alignment*block->m_size) == + detail::char_ptr_cast(detail::get_pointer(pos))){ + + block->m_size += pos->m_size; + block->m_next = pos->m_next; + } + else{ + block->m_next = pos; + } + + //Try to combine with lower block + if ((detail::char_ptr_cast(detail::get_pointer(prev)) + + Alignment*prev->m_size) == + detail::char_ptr_cast(detail::get_pointer(block))){ + prev->m_size += block->m_size; + prev->m_next = block->m_next; + } + else{ + prev->m_next = block; + } +} + +} //namespace detail { + +} //namespace interprocess { + +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_MEM_ALGO_DETAIL_SIMPLE_SEQ_FIT_IMPL_HPP + diff --git a/win32/include/boost/interprocess/mem_algo/rbtree_best_fit.hpp b/win32/include/boost/interprocess/mem_algo/rbtree_best_fit.hpp new file mode 100755 index 000000000..36176aeee --- /dev/null +++ b/win32/include/boost/interprocess/mem_algo/rbtree_best_fit.hpp @@ -0,0 +1,1344 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MEM_ALGO_RBTREE_BEST_FIT_HPP +#define BOOST_INTERPROCESS_MEM_ALGO_RBTREE_BEST_FIT_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//#define BOOST_INTERPROCESS_RBTREE_BEST_FIT_USE_SPLAY + +#ifndef BOOST_INTERPROCESS_RBTREE_BEST_FIT_USE_SPLAY +#include +#else +//#include +//#include +#include +#endif + +//!\file +//!Describes a best-fit algorithm based in an intrusive red-black tree used to allocate +//!objects in shared memory. This class is intended as a base class for single segment +//!and multi-segment implementations. + +namespace boost { +namespace interprocess { + +//!This class implements an algorithm that stores the free nodes in a red-black tree +//!to have logarithmic search/insert times. +template +class rbtree_best_fit +{ + /// @cond + //Non-copyable + rbtree_best_fit(); + rbtree_best_fit(const rbtree_best_fit &); + rbtree_best_fit &operator=(const rbtree_best_fit &); + /// @endcond + + public: + //!Shared interprocess_mutex family used for the rest of the Interprocess framework + typedef MutexFamily mutex_family; + //!Pointer type to be used with the rest of the Interprocess framework + typedef VoidPointer void_pointer; + typedef detail::basic_multiallocation_iterator + multiallocation_iterator; + typedef detail::basic_multiallocation_chain + multiallocation_chain; + + /// @cond + + private: + struct block_ctrl; + typedef typename detail:: + pointer_to_other::type block_ctrl_ptr; + typedef typename detail:: + pointer_to_other::type char_ptr; + +#ifndef BOOST_INTERPROCESS_RBTREE_BEST_FIT_USE_SPLAY + typedef typename bi::make_set_base_hook +#else +// typedef typename bi::make_splay_set_base_hook +// typedef typename bi::make_avl_set_base_hook + typedef typename bi::make_sg_set_base_hook +#endif + < bi::void_pointer + , bi::optimize_size + , bi::link_mode >::type TreeHook; + + typedef detail::multi_allocation_next multi_allocation_next_t; + typedef typename multi_allocation_next_t:: + multi_allocation_next_ptr multi_allocation_next_ptr; + + struct SizeHolder + { + //!This block's memory size (including block_ctrl + //!header) in Alignment units + std::size_t m_prev_size : sizeof(std::size_t)*CHAR_BIT; + std::size_t m_size : sizeof(std::size_t)*CHAR_BIT - 2; + std::size_t m_prev_allocated : 1; + std::size_t m_allocated : 1; + }; + + //!Block control structure + struct block_ctrl + : public SizeHolder, public TreeHook + { + block_ctrl() + { this->m_size = 0; this->m_allocated = 0, this->m_prev_allocated = 0; } + + friend bool operator<(const block_ctrl &a, const block_ctrl &b) + { return a.m_size < b.m_size; } + friend bool operator==(const block_ctrl &a, const block_ctrl &b) + { return a.m_size == b.m_size; } + }; + + struct size_block_ctrl_compare + { + bool operator()(std::size_t size, const block_ctrl &block) const + { return size < block.m_size; } + + bool operator()(const block_ctrl &block, std::size_t size) const + { return block.m_size < size; } + }; + + //!Shared interprocess_mutex to protect memory allocate/deallocate + typedef typename MutexFamily::mutex_type interprocess_mutex; +#ifndef BOOST_INTERPROCESS_RBTREE_BEST_FIT_USE_SPLAY + typedef typename bi::make_multiset +#else + //typedef typename bi::make_splay_multiset + //typedef typename bi::make_avl_multiset + typedef typename bi::make_sg_multiset +#endif + >::type Imultiset; + + typedef typename Imultiset::iterator imultiset_iterator; + + //!This struct includes needed data and derives from + //!interprocess_mutex to allow EBO when using null interprocess_mutex + struct header_t : public interprocess_mutex + { + Imultiset m_imultiset; + + //!The extra size required by the segment + std::size_t m_extra_hdr_bytes; + //!Allocated bytes for internal checking + std::size_t m_allocated; + //!The size of the memory segment + std::size_t m_size; + } m_header; + + friend class detail::basic_multiallocation_iterator; + friend class detail::memory_algorithm_common; + + typedef detail::memory_algorithm_common algo_impl_t; + + public: + /// @endcond + + //!Constructor. "size" is the total size of the managed memory segment, + //!"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(rbtree_best_fit) + //!offset that the allocator should not use at all. + rbtree_best_fit (std::size_t size, std::size_t extra_hdr_bytes); + + //!Destructor. + ~rbtree_best_fit(); + + //!Obtains the minimum size needed by the algorithm + static std::size_t get_min_size (std::size_t extra_hdr_bytes); + + //Functions for single segment management + + //!Allocates bytes, returns 0 if there is not more memory + void* allocate (std::size_t nbytes); + + /// @cond + + //Experimental. Dont' use + + //!Multiple element allocation, same size + multiallocation_iterator allocate_many(std::size_t elem_bytes, std::size_t num_elements); + + //!Multiple element allocation, different size + multiallocation_iterator allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element); + + //!Multiple element allocation, different size + void deallocate_many(multiallocation_iterator it); + + /// @endcond + + //!Deallocates previously allocated bytes + void deallocate (void *addr); + + //!Returns the size of the memory segment + std::size_t get_size() const; + + //!Returns the number of free bytes of the segment + std::size_t get_free_memory() const; + + //!Initializes to zero all the memory that's not in use. + //!This function is normally used for security reasons. + void zero_free_memory(); + + //!Increases managed memory in + //!extra_size bytes more + void grow(std::size_t extra_size); + + //!Decreases managed memory as much as possible + void shrink_to_fit(); + + //!Returns true if all allocated memory has been deallocated + bool all_memory_deallocated(); + + //!Makes an internal sanity check + //!and returns true if success + bool check_sanity(); + + template + std::pair + allocation_command (allocation_type command, std::size_t limit_size, + std::size_t preferred_size,std::size_t &received_size, + T *reuse_ptr = 0); + + std::pair + raw_allocation_command (allocation_type command, std::size_t limit_object, + std::size_t preferred_object,std::size_t &received_object, + void *reuse_ptr = 0, std::size_t sizeof_object = 1); + + //!Returns the size of the buffer previously allocated pointed by ptr + std::size_t size(const void *ptr) const; + + //!Allocates aligned bytes, returns 0 if there is not more memory. + //!Alignment must be power of 2 + void* allocate_aligned (std::size_t nbytes, std::size_t alignment); + + /// @cond + private: + static std::size_t priv_first_block_offset(const void *this_ptr, std::size_t extra_hdr_bytes); + + std::pair + priv_allocation_command(allocation_type command, std::size_t limit_size, + std::size_t preferred_size,std::size_t &received_size, + void *reuse_ptr, std::size_t sizeof_object); + + + //!Real allocation algorithm with min allocation option + std::pair priv_allocate(allocation_type command + ,std::size_t limit_size + ,std::size_t preferred_size + ,std::size_t &received_size + ,void *reuse_ptr = 0 + ,std::size_t backwards_multiple = 1); + + //!Obtains the block control structure of the user buffer + static block_ctrl *priv_get_block(const void *ptr); + + //!Obtains the pointer returned to the user from the block control + static void *priv_get_user_buffer(const block_ctrl *block); + + //!Returns the number of total units that a user buffer + //!of "userbytes" bytes really occupies (including header) + static std::size_t priv_get_total_units(std::size_t userbytes); + + //!Real expand function implementation + bool priv_expand(void *ptr + ,const std::size_t min_size, const std::size_t preferred_size + ,std::size_t &received_size); + + //!Real expand to both sides implementation + void* priv_expand_both_sides(allocation_type command + ,std::size_t min_size + ,std::size_t preferred_size + ,std::size_t &received_size + ,void *reuse_ptr + ,bool only_preferred_backwards + ,std::size_t backwards_multiple); + + //!Get poitner of the previous block (previous block must be free) + block_ctrl * priv_prev_block(block_ctrl *ptr); + + //!Returns true if the previous block is allocated + bool priv_is_prev_allocated(block_ctrl *ptr); + + //!Get a pointer of the "end" block from the first block of the segment + block_ctrl * priv_end_block(block_ctrl *first_segment_block); + + //!Get the size in the tail of the previous block + block_ctrl * priv_next_block(block_ctrl *ptr); + + //!Check if this block is free (not allocated) + bool priv_is_allocated_block(block_ctrl *ptr); + + //!Marks the block as allocated + void priv_mark_as_allocated_block(block_ctrl *ptr); + + //!Marks the block as allocated + void priv_mark_as_free_block(block_ctrl *ptr); + + //!Checks if block has enough memory and splits/unlinks the block + //!returning the address to the users + void* priv_check_and_allocate(std::size_t units + ,block_ctrl* block + ,std::size_t &received_size); + //!Real deallocation algorithm + void priv_deallocate(void *addr); + + //!Makes a new memory portion available for allocation + void priv_add_segment(void *addr, std::size_t size); + + void priv_mark_new_allocated_block(block_ctrl *block); + + public: + + static const std::size_t Alignment = !MemAlignment + ? detail::alignment_of::value + : MemAlignment + ; + + private: + //Due to embedded bits in size, Alignment must be at least 2 + BOOST_STATIC_ASSERT((Alignment >= 4)); + //Due to rbtree size optimizations, Alignment must have at least pointer alignment + BOOST_STATIC_ASSERT((Alignment >= detail::alignment_of::value)); + static const std::size_t AlignmentMask = (Alignment - 1); + static const std::size_t BlockCtrlBytes = detail::ct_rounded_size::value; + static const std::size_t BlockCtrlUnits = BlockCtrlBytes/Alignment; + static const std::size_t AllocatedCtrlBytes = detail::ct_rounded_size::value; + static const std::size_t AllocatedCtrlUnits = AllocatedCtrlBytes/Alignment; + static const std::size_t EndCtrlBlockBytes = detail::ct_rounded_size::value; + static const std::size_t EndCtrlBlockUnits = EndCtrlBlockBytes/Alignment; + static const std::size_t MinBlockUnits = BlockCtrlUnits; + static const std::size_t UsableByPreviousChunk = sizeof(std::size_t); + + //Make sure the maximum alignment is power of two + BOOST_STATIC_ASSERT((0 == (Alignment & (Alignment - std::size_t(1u))))); + /// @endcond + public: + static const std::size_t PayloadPerAllocation = AllocatedCtrlBytes - UsableByPreviousChunk; +}; + +/// @cond + +template +inline std::size_t rbtree_best_fit + ::priv_first_block_offset(const void *this_ptr, std::size_t extra_hdr_bytes) +{ + std::size_t uint_this = (std::size_t)this_ptr; + std::size_t main_hdr_end = uint_this + sizeof(rbtree_best_fit) + extra_hdr_bytes; + std::size_t aligned_main_hdr_end = detail::get_rounded_size(main_hdr_end, Alignment); + std::size_t block1_off = aligned_main_hdr_end - uint_this; + algo_impl_t::assert_alignment(aligned_main_hdr_end); + algo_impl_t::assert_alignment(uint_this + block1_off); + return block1_off; +} + +template +inline rbtree_best_fit:: + rbtree_best_fit(std::size_t size, std::size_t extra_hdr_bytes) +{ + //Initialize the header + m_header.m_allocated = 0; + m_header.m_size = size; + m_header.m_extra_hdr_bytes = extra_hdr_bytes; + + //Now write calculate the offset of the first big block that will + //cover the whole segment + assert(get_min_size(extra_hdr_bytes) <= size); + std::size_t block1_off = priv_first_block_offset(this, extra_hdr_bytes); + priv_add_segment(detail::char_ptr_cast(this) + block1_off, size - block1_off); +} + +template +inline rbtree_best_fit::~rbtree_best_fit() +{ + //There is a memory leak! +// assert(m_header.m_allocated == 0); +// assert(m_header.m_root.m_next->m_next == block_ctrl_ptr(&m_header.m_root)); +} + +template +void rbtree_best_fit::grow(std::size_t extra_size) +{ + //Get the address of the first block + std::size_t block1_off = + priv_first_block_offset(this, m_header.m_extra_hdr_bytes); + + block_ctrl *first_block = reinterpret_cast + (detail::char_ptr_cast(this) + block1_off); + block_ctrl *old_end_block = priv_end_block(first_block); + assert(priv_is_allocated_block(old_end_block)); + std::size_t old_border_offset = (detail::char_ptr_cast(old_end_block) - + detail::char_ptr_cast(this)) + EndCtrlBlockBytes; + + //Update managed buffer's size + m_header.m_size += extra_size; + + //We need at least MinBlockUnits blocks to create a new block +// assert((m_header.m_size - old_end) >= MinBlockUnits); + if((m_header.m_size - old_border_offset) < MinBlockUnits){ + return; + } + + //Now create a new block between the old end and the new end + std::size_t align_offset = (m_header.m_size - old_border_offset)/Alignment; + block_ctrl *new_end_block = reinterpret_cast + (detail::char_ptr_cast(old_end_block) + align_offset*Alignment); + new_end_block->m_size = (detail::char_ptr_cast(first_block) - + detail::char_ptr_cast(new_end_block))/Alignment; + first_block->m_prev_size = new_end_block->m_size; + assert(first_block == priv_next_block(new_end_block)); + priv_mark_new_allocated_block(new_end_block); + + assert(new_end_block == priv_end_block(first_block)); + + //The old end block is the new block + block_ctrl *new_block = old_end_block; + new_block->m_size = (detail::char_ptr_cast(new_end_block) - + detail::char_ptr_cast(new_block))/Alignment; + assert(new_block->m_size >= BlockCtrlUnits); + priv_mark_new_allocated_block(new_block); + assert(priv_next_block(new_block) == new_end_block); + + m_header.m_allocated += new_block->m_size*Alignment; + + //Now deallocate the newly created block + this->priv_deallocate(priv_get_user_buffer(new_block)); +} + +template +void rbtree_best_fit::shrink_to_fit() +{ + //Get the address of the first block + std::size_t block1_off = + priv_first_block_offset(this, m_header.m_extra_hdr_bytes); + + block_ctrl *first_block = reinterpret_cast + (detail::char_ptr_cast(this) + block1_off); + algo_impl_t::assert_alignment(first_block); + + block_ctrl *old_end_block = priv_end_block(first_block); + algo_impl_t::assert_alignment(old_end_block); + assert(priv_is_allocated_block(old_end_block)); + + algo_impl_t::assert_alignment(old_end_block); + + std::size_t old_end_block_size = old_end_block->m_size; + + void *unique_buffer = 0; + block_ctrl *last_block; + if(priv_next_block(first_block) == old_end_block){ + std::size_t ignore; + unique_buffer = priv_allocate(allocate_new, 0, 0, ignore).first; + if(!unique_buffer) + return; + algo_impl_t::assert_alignment(unique_buffer); + block_ctrl *unique_block = priv_get_block(unique_buffer); + assert(priv_is_allocated_block(unique_block)); + algo_impl_t::assert_alignment(unique_block); + last_block = priv_next_block(unique_block); + assert(!priv_is_allocated_block(last_block)); + algo_impl_t::assert_alignment(last_block); + } + else{ + if(priv_is_prev_allocated(old_end_block)) + return; + last_block = priv_prev_block(old_end_block); + } + + std::size_t last_block_size = last_block->m_size; + + //Erase block from the free tree, since we will erase it + m_header.m_imultiset.erase(Imultiset::s_iterator_to(*last_block)); + + std::size_t shrunk_border_offset = (detail::char_ptr_cast(last_block) - + detail::char_ptr_cast(this)) + EndCtrlBlockBytes; + + block_ctrl *new_end_block = last_block; + algo_impl_t::assert_alignment(new_end_block); + new_end_block->m_size = old_end_block_size + last_block_size; + priv_mark_as_allocated_block(new_end_block); + + //Although the first block might be allocated, we'll + //store the offset to the end block since in the previous + //offset can't be overwritten by a previous block + first_block->m_prev_size = new_end_block->m_size; + assert(priv_end_block(first_block) == new_end_block); + + //Update managed buffer's size + m_header.m_size = shrunk_border_offset; + if(unique_buffer) + priv_deallocate(unique_buffer); +} + +template +void rbtree_best_fit:: + priv_add_segment(void *addr, std::size_t size) +{ + //Check alignment + algo_impl_t::check_alignment(addr); + //Check size + assert(size >= (BlockCtrlBytes + EndCtrlBlockBytes)); + + //Initialize the first big block and the "end" node + block_ctrl *first_big_block = new(addr)block_ctrl; + first_big_block->m_size = size/Alignment - EndCtrlBlockUnits; + assert(first_big_block->m_size >= BlockCtrlUnits); + + //The "end" node is just a node of size 0 with the "end" bit set + block_ctrl *end_block = static_cast + (new (reinterpret_cast + (detail::char_ptr_cast(addr) + first_big_block->m_size*Alignment))SizeHolder); + + //This will overwrite the prev part of the "end" node + priv_mark_as_free_block (first_big_block); + first_big_block->m_prev_size = end_block->m_size = + (detail::char_ptr_cast(first_big_block) - detail::char_ptr_cast(end_block))/Alignment; + priv_mark_as_allocated_block(end_block); + + assert(priv_next_block(first_big_block) == end_block); + assert(priv_next_block(end_block) == first_big_block); + assert(priv_end_block(first_big_block) == end_block); + assert(priv_prev_block(end_block) == first_big_block); + + //Some check to validate the algorithm, since it makes some assumptions + //to optimize the space wasted in bookkeeping: + + //Check that the sizes of the header are placed before the rbtree + assert((void*)(SizeHolder*)first_big_block < (void*)(TreeHook*)first_big_block); + + //Check that the alignment is power of two (we use some optimizations based on this) + //assert((Alignment % 2) == 0); + //Insert it in the intrusive containers + m_header.m_imultiset.insert(*first_big_block); +} + +template +inline void rbtree_best_fit:: + priv_mark_new_allocated_block(block_ctrl *new_block) +{ priv_mark_as_allocated_block(new_block); } + +template +inline std::size_t rbtree_best_fit::get_size() const +{ return m_header.m_size; } + +template +inline std::size_t rbtree_best_fit::get_free_memory() const +{ + return m_header.m_size - m_header.m_allocated - + priv_first_block_offset(this, m_header.m_extra_hdr_bytes); +} + +template +inline std::size_t rbtree_best_fit:: + get_min_size (std::size_t extra_hdr_bytes) +{ + return (algo_impl_t::ceil_units(sizeof(rbtree_best_fit)) + + algo_impl_t::ceil_units(extra_hdr_bytes) + + MinBlockUnits + EndCtrlBlockUnits)*Alignment; +} + +template +inline bool rbtree_best_fit:: + all_memory_deallocated() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + std::size_t block1_off = + priv_first_block_offset(this, m_header.m_extra_hdr_bytes); + + return m_header.m_allocated == 0 && + m_header.m_imultiset.begin() != m_header.m_imultiset.end() && + (++m_header.m_imultiset.begin()) == m_header.m_imultiset.end() + && m_header.m_imultiset.begin()->m_size == + (m_header.m_size - block1_off - EndCtrlBlockBytes)/Alignment; +} + +template +bool rbtree_best_fit:: + check_sanity() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + imultiset_iterator ib(m_header.m_imultiset.begin()), ie(m_header.m_imultiset.end()); + + std::size_t free_memory = 0; + + //Iterate through all blocks obtaining their size + for(; ib != ie; ++ib){ + free_memory += ib->m_size*Alignment; + algo_impl_t::assert_alignment(&*ib); + if(!algo_impl_t::check_alignment(&*ib)) + return false; + } + + //Check allocated bytes are less than size + if(m_header.m_allocated > m_header.m_size){ + return false; + } + + std::size_t block1_off = + priv_first_block_offset(this, m_header.m_extra_hdr_bytes); + + //Check free bytes are less than size + if(free_memory > (m_header.m_size - block1_off)){ + return false; + } + return true; +} + +template +inline void* rbtree_best_fit:: + allocate(std::size_t nbytes) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + std::size_t ignore; + void * ret = priv_allocate(allocate_new, nbytes, nbytes, ignore).first; + return ret; +} + +template +inline void* rbtree_best_fit:: + allocate_aligned(std::size_t nbytes, std::size_t alignment) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return algo_impl_t::allocate_aligned(this, nbytes, alignment); +} + +template +template +inline std::pair rbtree_best_fit:: + allocation_command (allocation_type command, std::size_t limit_size, + std::size_t preferred_size,std::size_t &received_size, + T *reuse_ptr) +{ + std::pair ret = priv_allocation_command + (command, limit_size, preferred_size, received_size, (void*)reuse_ptr, sizeof(T)); + + BOOST_ASSERT(0 == ((std::size_t)ret.first % detail::alignment_of::value)); + return std::pair(static_cast(ret.first), ret.second); +} + +template +inline std::pair rbtree_best_fit:: + raw_allocation_command (allocation_type command, std::size_t limit_objects, + std::size_t preferred_objects,std::size_t &received_objects, + void *reuse_ptr, std::size_t sizeof_object) +{ + if(!sizeof_object) + return std::pair((void *)0, 0); + if(command & try_shrink_in_place){ + bool success = algo_impl_t::try_shrink + ( this, reuse_ptr, limit_objects*sizeof_object + , preferred_objects*sizeof_object, received_objects); + received_objects /= sizeof_object; + return std::pair ((success ? reuse_ptr : 0), true); + } + return priv_allocation_command + (command, limit_objects, preferred_objects, received_objects, reuse_ptr, sizeof_object); +} + + +template +inline std::pair rbtree_best_fit:: + priv_allocation_command (allocation_type command, std::size_t limit_size, + std::size_t preferred_size,std::size_t &received_size, + void *reuse_ptr, std::size_t sizeof_object) +{ + std::pair ret; + std::size_t max_count = m_header.m_size/sizeof_object; + if(limit_size > max_count || preferred_size > max_count){ + ret.first = 0; return ret; + } + std::size_t l_size = limit_size*sizeof_object; + std::size_t p_size = preferred_size*sizeof_object; + std::size_t r_size; + { + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + ret = priv_allocate(command, l_size, p_size, r_size, reuse_ptr, sizeof_object); + } + received_size = r_size/sizeof_object; + return ret; +} + +template +inline std::size_t rbtree_best_fit:: + size(const void *ptr) const +{ + //We need no synchronization since this block's size is not going + //to be modified by anyone else + //Obtain the real size of the block + return (priv_get_block(ptr)->m_size - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; +} + +template +inline void rbtree_best_fit::zero_free_memory() +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + imultiset_iterator ib(m_header.m_imultiset.begin()), ie(m_header.m_imultiset.end()); + + //Iterate through all blocks obtaining their size + for(; ib != ie; ++ib){ + //Just clear user the memory part reserved for the user + std::memset( detail::char_ptr_cast(&*ib) + BlockCtrlBytes + , 0 + , ib->m_size*Alignment - BlockCtrlBytes); + } +} + +template +void* rbtree_best_fit:: + priv_expand_both_sides(allocation_type command + ,std::size_t min_size + ,std::size_t preferred_size + ,std::size_t &received_size + ,void *reuse_ptr + ,bool only_preferred_backwards + ,std::size_t backwards_multiple) +{ + algo_impl_t::assert_alignment(reuse_ptr); + if(command & expand_fwd){ + if(priv_expand(reuse_ptr, min_size, preferred_size, received_size)) + return reuse_ptr; + } + else{ + received_size = this->size(reuse_ptr); + if(received_size >= preferred_size || received_size >= min_size) + return reuse_ptr; + } + + if(backwards_multiple){ + BOOST_ASSERT(0 == (min_size % backwards_multiple)); + BOOST_ASSERT(0 == (preferred_size % backwards_multiple)); + } + + if(command & expand_bwd){ + //Obtain the real size of the block + block_ctrl *reuse = priv_get_block(reuse_ptr); + + //Sanity check + //assert(reuse->m_size == priv_tail_size(reuse)); + algo_impl_t::assert_alignment(reuse); + + block_ctrl *prev_block; + + //If the previous block is not free, there is nothing to do + if(priv_is_prev_allocated(reuse)){ + return 0; + } + + prev_block = priv_prev_block(reuse); + assert(!priv_is_allocated_block(prev_block)); + + //Some sanity checks + assert(prev_block->m_size == reuse->m_prev_size); + algo_impl_t::assert_alignment(prev_block); + + std::size_t needs_backwards_aligned; + std::size_t lcm; + if(!algo_impl_t::calculate_lcm_and_needs_backwards_lcmed + ( backwards_multiple + , received_size + , only_preferred_backwards ? preferred_size : min_size + , lcm, needs_backwards_aligned)){ + return 0; + } + + //Check if previous block has enough size + if(std::size_t(prev_block->m_size*Alignment) >= needs_backwards_aligned){ + //Now take all next space. This will succeed + if(command & expand_fwd){ + std::size_t received_size2; + if(!priv_expand(reuse_ptr, received_size, received_size, received_size2)){ + assert(0); + } + assert(received_size = received_size2); + } + //We need a minimum size to split the previous one + if(prev_block->m_size >= (needs_backwards_aligned/Alignment + BlockCtrlUnits)){ + block_ctrl *new_block = reinterpret_cast + (detail::char_ptr_cast(reuse) - needs_backwards_aligned); + + //Free old previous buffer + new_block->m_size = + AllocatedCtrlUnits + (needs_backwards_aligned + (received_size - UsableByPreviousChunk))/Alignment; + assert(new_block->m_size >= BlockCtrlUnits); + priv_mark_new_allocated_block(new_block); + + prev_block->m_size = (detail::char_ptr_cast(new_block) - + detail::char_ptr_cast(prev_block))/Alignment; + assert(prev_block->m_size >= BlockCtrlUnits); + priv_mark_as_free_block(prev_block); + + //Update the old previous block in the free blocks tree + //If the new size fulfills tree invariants do nothing, + //otherwise erase() + insert() + { + imultiset_iterator prev_block_it(Imultiset::s_iterator_to(*prev_block)); + imultiset_iterator was_smaller_it(prev_block_it); + if(prev_block_it != m_header.m_imultiset.begin() && + (--(was_smaller_it = prev_block_it))->m_size > prev_block->m_size){ + m_header.m_imultiset.erase(prev_block_it); + m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *prev_block); + } + } + + received_size = needs_backwards_aligned + received_size; + m_header.m_allocated += needs_backwards_aligned; + + //Check alignment + algo_impl_t::assert_alignment(new_block); + + //If the backwards expansion has remaining bytes in the + //first bytes, fill them with a pattern + void *p = priv_get_user_buffer(new_block); + void *user_ptr = detail::char_ptr_cast(p); + assert(((char*)reuse_ptr - (char*)user_ptr) % backwards_multiple == 0); + algo_impl_t::assert_alignment(user_ptr); + return user_ptr; + } + //Check if there is no place to create a new block and + //the whole new block is multiple of the backwards expansion multiple + else if(prev_block->m_size >= needs_backwards_aligned/Alignment && + 0 == ((prev_block->m_size*Alignment) % lcm)) { + //Erase old previous block, since we will change it + m_header.m_imultiset.erase(Imultiset::s_iterator_to(*prev_block)); + + //Just merge the whole previous block + //prev_block->m_size*Alignment is multiple of lcm (and backwards_multiple) + received_size = received_size + prev_block->m_size*Alignment; + + m_header.m_allocated += prev_block->m_size*Alignment; + //Now update sizes + prev_block->m_size = prev_block->m_size + reuse->m_size; + assert(prev_block->m_size >= BlockCtrlUnits); + priv_mark_new_allocated_block(prev_block); + + //If the backwards expansion has remaining bytes in the + //first bytes, fill them with a pattern + void *p = priv_get_user_buffer(prev_block); + void *user_ptr = detail::char_ptr_cast(p); + assert(((char*)reuse_ptr - (char*)user_ptr) % backwards_multiple == 0); + algo_impl_t::assert_alignment(user_ptr); + return user_ptr; + } + else{ + //Alignment issues + } + } + } + return 0; +} + +template +inline typename rbtree_best_fit::multiallocation_iterator + rbtree_best_fit:: + allocate_many(std::size_t elem_bytes, std::size_t num_elements) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return algo_impl_t::allocate_many(this, elem_bytes, num_elements); +} + +template +inline void rbtree_best_fit:: + deallocate_many(typename rbtree_best_fit::multiallocation_iterator it) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + while(it){ + void *addr = &*it; + ++it; + this->priv_deallocate(addr); + } +} + +template +inline typename rbtree_best_fit::multiallocation_iterator + rbtree_best_fit:: + allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element) +{ + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return algo_impl_t::allocate_many(this, elem_sizes, n_elements, sizeof_element); +} + +template +std::pair rbtree_best_fit:: + priv_allocate(allocation_type command + ,std::size_t limit_size + ,std::size_t preferred_size + ,std::size_t &received_size + ,void *reuse_ptr + ,std::size_t backwards_multiple) +{ + //Remove me. Forbid backwards allocation + //command &= (~expand_bwd); + + if(command & shrink_in_place){ + bool success = + algo_impl_t::shrink(this, reuse_ptr, limit_size, preferred_size, received_size); + return std::pair ((success ? reuse_ptr : 0), true); + } + + typedef std::pair return_type; + received_size = 0; + + if(limit_size > preferred_size) + return return_type((void*)0, false); + + //Number of units to request (including block_ctrl header) + std::size_t preferred_units = priv_get_total_units(preferred_size); + + //Number of units to request (including block_ctrl header) + std::size_t limit_units = priv_get_total_units(limit_size); + + //Expand in place + if(reuse_ptr && (command & (expand_fwd | expand_bwd))){ + void *ret = priv_expand_both_sides + (command, limit_size, preferred_size, received_size, reuse_ptr, true, backwards_multiple); + if(ret) + return return_type(ret, true); + } + + if(command & allocate_new){ + size_block_ctrl_compare comp; + imultiset_iterator it(m_header.m_imultiset.lower_bound(preferred_units, comp)); + + if(it != m_header.m_imultiset.end()){ + return return_type(this->priv_check_and_allocate + (preferred_units, detail::get_pointer(&*it), received_size), false); + } + + if(it != m_header.m_imultiset.begin()&& + (--it)->m_size >= limit_units){ + return return_type(this->priv_check_and_allocate + (it->m_size, detail::get_pointer(&*it), received_size), false); + } + } + + + //Now try to expand both sides with min size + if(reuse_ptr && (command & (expand_fwd | expand_bwd))){ + return return_type(priv_expand_both_sides + (command, limit_size, preferred_size, received_size, reuse_ptr, false, backwards_multiple), true); + } + + return return_type((void*)0, false); +} + +template +inline +typename rbtree_best_fit::block_ctrl * + rbtree_best_fit::priv_get_block(const void *ptr) +{ + return reinterpret_cast(detail::char_ptr_cast(ptr) - AllocatedCtrlBytes); +} + +template +inline +void *rbtree_best_fit:: + priv_get_user_buffer(const typename rbtree_best_fit::block_ctrl *block) +{ return detail::char_ptr_cast(block) + AllocatedCtrlBytes; } + +template +inline +std::size_t rbtree_best_fit:: + priv_get_total_units(std::size_t userbytes) +{ + if(userbytes < UsableByPreviousChunk) + userbytes = UsableByPreviousChunk; + std::size_t units = detail::get_rounded_size(userbytes - UsableByPreviousChunk, Alignment)/Alignment + AllocatedCtrlUnits; + if(units < BlockCtrlUnits) units = BlockCtrlUnits; + return units; +} + +template +bool rbtree_best_fit:: + priv_expand (void *ptr + ,const std::size_t min_size + ,const std::size_t preferred_size + ,std::size_t &received_size) +{ + //Obtain the real size of the block + block_ctrl *block = priv_get_block(ptr); + std::size_t old_block_units = block->m_size; + + //The block must be marked as allocated and the sizes must be equal + assert(priv_is_allocated_block(block)); + //assert(old_block_units == priv_tail_size(block)); + + //Put this to a safe value + received_size = (old_block_units - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; + if(received_size >= preferred_size || received_size >= min_size) + return true; + + //Now translate it to Alignment units + const std::size_t min_user_units = algo_impl_t::ceil_units(min_size - UsableByPreviousChunk); + const std::size_t preferred_user_units = algo_impl_t::ceil_units(preferred_size - UsableByPreviousChunk); + + //Some parameter checks + assert(min_user_units <= preferred_user_units); + + block_ctrl *next_block; + + if(priv_is_allocated_block(next_block = priv_next_block(block))){ + return received_size >= min_size ? true : false; + } + algo_impl_t::assert_alignment(next_block); + + //Is "block" + "next_block" big enough? + const std::size_t merged_units = old_block_units + next_block->m_size; + + //Now get the expansion size + const std::size_t merged_user_units = merged_units - AllocatedCtrlUnits; + + if(merged_user_units < min_user_units){ + received_size = merged_units*Alignment - UsableByPreviousChunk; + return false; + } + + //Now get the maximum size the user can allocate + std::size_t intended_user_units = (merged_user_units < preferred_user_units) ? + merged_user_units : preferred_user_units; + + //These are total units of the merged block (supposing the next block can be split) + const std::size_t intended_units = AllocatedCtrlUnits + intended_user_units; + + //Check if we can split the next one in two parts + if((merged_units - intended_units) >= BlockCtrlUnits){ + //This block is bigger than needed, split it in + //two blocks, the first one will be merged and + //the second's size will be the remaining space + assert(next_block->m_size == priv_next_block(next_block)->m_prev_size); + const std::size_t rem_units = merged_units - intended_units; + + //Check if we we need to update the old next block in the free blocks tree + //If the new size fulfills tree invariants, we just need to replace the node + //(the block start has been displaced), otherwise erase() + insert(). + // + //This fixup must be done in two parts, because the new next block might + //overwrite the tree hook of the old next block. So we first erase the + //old if needed and we'll insert the new one after creating the new next + imultiset_iterator old_next_block_it(Imultiset::s_iterator_to(*next_block)); + const bool size_invariants_broken = + (next_block->m_size - rem_units ) < BlockCtrlUnits || + (old_next_block_it != m_header.m_imultiset.begin() && + (--imultiset_iterator(old_next_block_it))->m_size > rem_units); + if(size_invariants_broken){ + m_header.m_imultiset.erase(old_next_block_it); + } + //This is the remaining block + block_ctrl *rem_block = new(reinterpret_cast + (detail::char_ptr_cast(block) + intended_units*Alignment))block_ctrl; + rem_block->m_size = rem_units; + algo_impl_t::assert_alignment(rem_block); + assert(rem_block->m_size >= BlockCtrlUnits); + priv_mark_as_free_block(rem_block); + + //Now the second part of the fixup + if(size_invariants_broken) + m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *rem_block); + else + m_header.m_imultiset.replace_node(old_next_block_it, *rem_block); + + //Write the new length + block->m_size = intended_user_units + AllocatedCtrlUnits; + assert(block->m_size >= BlockCtrlUnits); + m_header.m_allocated += (intended_units - old_block_units)*Alignment; + } + //There is no free space to create a new node: just merge both blocks + else{ + //Now we have to update the data in the tree + m_header.m_imultiset.erase(Imultiset::s_iterator_to(*next_block)); + + //Write the new length + block->m_size = merged_units; + assert(block->m_size >= BlockCtrlUnits); + m_header.m_allocated += (merged_units - old_block_units)*Alignment; + } + priv_mark_as_allocated_block(block); + received_size = (block->m_size - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; + return true; +} + +template inline +typename rbtree_best_fit::block_ctrl * + rbtree_best_fit::priv_prev_block + (typename rbtree_best_fit::block_ctrl *ptr) +{ + assert(!ptr->m_prev_allocated); + return reinterpret_cast + (detail::char_ptr_cast(ptr) - ptr->m_prev_size*Alignment); +} + +template inline +bool rbtree_best_fit::priv_is_prev_allocated + (typename rbtree_best_fit::block_ctrl *ptr) +{ + if(ptr->m_prev_allocated){ + return true; + } + else{ + block_ctrl *prev = priv_prev_block(ptr); + (void)prev; + assert(!priv_is_allocated_block(prev)); + return false; + } +} + +template inline +typename rbtree_best_fit::block_ctrl * + rbtree_best_fit::priv_end_block + (typename rbtree_best_fit::block_ctrl *first_segment_block) +{ + assert(first_segment_block->m_prev_allocated); + block_ctrl *end_block = reinterpret_cast + (detail::char_ptr_cast(first_segment_block) - first_segment_block->m_prev_size*Alignment); + (void)end_block; + assert(priv_is_allocated_block(end_block)); + assert(end_block > first_segment_block); + return end_block; +} + +template inline +typename rbtree_best_fit::block_ctrl * + rbtree_best_fit::priv_next_block + (typename rbtree_best_fit::block_ctrl *ptr) +{ + return reinterpret_cast + (detail::char_ptr_cast(ptr) + ptr->m_size*Alignment); +} + +template inline +bool rbtree_best_fit::priv_is_allocated_block + (typename rbtree_best_fit::block_ctrl *block) +{ + bool allocated = block->m_allocated != 0; + block_ctrl *next_block = (block_ctrl *) + (detail::char_ptr_cast(block) + block->m_size*Alignment); + bool next_block_prev_allocated = next_block->m_prev_allocated != 0; + (void)next_block_prev_allocated; + assert(allocated == next_block_prev_allocated); + return allocated; +} + +template inline +void rbtree_best_fit::priv_mark_as_allocated_block + (typename rbtree_best_fit::block_ctrl *block) +{ + //assert(!priv_is_allocated_block(block)); + block->m_allocated = 1; + ((block_ctrl *)(((char*)block) + block->m_size*Alignment))->m_prev_allocated = 1; +} + +template inline +void rbtree_best_fit::priv_mark_as_free_block + (typename rbtree_best_fit::block_ctrl *block) +{ + block->m_allocated = 0; + ((block_ctrl *)(((char*)block) + block->m_size*Alignment))->m_prev_allocated = 0; + //assert(!priv_is_allocated_block(ptr)); + priv_next_block(block)->m_prev_size = block->m_size; +} + +template inline +void* rbtree_best_fit::priv_check_and_allocate + (std::size_t nunits + ,typename rbtree_best_fit::block_ctrl* block + ,std::size_t &received_size) +{ + std::size_t upper_nunits = nunits + BlockCtrlUnits; + imultiset_iterator it_old = Imultiset::s_iterator_to(*block); + algo_impl_t::assert_alignment(block); + + if (block->m_size >= upper_nunits){ + //This block is bigger than needed, split it in + //two blocks, the first's size will be "units" and + //the second's size "block->m_size-units" + std::size_t block_old_size = block->m_size; + block->m_size = nunits; + assert(block->m_size >= BlockCtrlUnits); + + //This is the remaining block + block_ctrl *rem_block = new(reinterpret_cast + (detail::char_ptr_cast(block) + Alignment*nunits))block_ctrl; + algo_impl_t::assert_alignment(rem_block); + rem_block->m_size = block_old_size - nunits; + assert(rem_block->m_size >= BlockCtrlUnits); + priv_mark_as_free_block(rem_block); + + imultiset_iterator it_hint; + if(it_old == m_header.m_imultiset.begin() + || (--imultiset_iterator(it_old))->m_size < rem_block->m_size){ + //option a: slow but secure + //m_header.m_imultiset.insert(m_header.m_imultiset.erase(it_old), *rem_block); + //option b: Construct an empty node and swap + //Imultiset::init_node(*rem_block); + //block->swap_nodes(*rem_block); + //option c: replace the node directly + m_header.m_imultiset.replace_node(Imultiset::s_iterator_to(*it_old), *rem_block); + } + else{ + //Now we have to update the data in the tree + m_header.m_imultiset.erase(it_old); + m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *rem_block); + } + + } + else if (block->m_size >= nunits){ + m_header.m_imultiset.erase(it_old); + } + else{ + assert(0); + return 0; + } + //We need block_ctrl for deallocation stuff, so + //return memory user can overwrite + m_header.m_allocated += block->m_size*Alignment; + received_size = (block->m_size - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; + + //Mark the block as allocated + priv_mark_as_allocated_block(block); + + //Clear the memory occupied by the tree hook, since this won't be + //cleared with zero_free_memory + TreeHook *t = static_cast(block); + std::memset(t, 0, sizeof(*t)); + this->priv_next_block(block)->m_prev_size = 0; + return priv_get_user_buffer(block); +} + +template +void rbtree_best_fit::deallocate(void* addr) +{ + if(!addr) return; + //----------------------- + boost::interprocess::scoped_lock guard(m_header); + //----------------------- + return this->priv_deallocate(addr); +} + +template +void rbtree_best_fit::priv_deallocate(void* addr) +{ + if(!addr) return; + + block_ctrl *block = priv_get_block(addr); + + //The blocks must be marked as allocated and the sizes must be equal + assert(priv_is_allocated_block(block)); +// assert(block->m_size == priv_tail_size(block)); + + //Check if alignment and block size are right + algo_impl_t::assert_alignment(addr); + + std::size_t block_old_size = Alignment*block->m_size; + assert(m_header.m_allocated >= block_old_size); + + //Update used memory count + m_header.m_allocated -= block_old_size; + + //The block to insert in the tree + block_ctrl *block_to_insert = block; + + //Get the next block + block_ctrl *next_block = priv_next_block(block); + bool merge_with_prev = !priv_is_prev_allocated(block); + bool merge_with_next = !priv_is_allocated_block(next_block); + + //Merge logic. First just update block sizes, then fix free blocks tree + if(merge_with_prev || merge_with_next){ + //Merge if the previous is free + if(merge_with_prev){ + //Get the previous block + block_ctrl *prev_block = priv_prev_block(block); + prev_block->m_size += block->m_size; + assert(prev_block->m_size >= BlockCtrlUnits); + block_to_insert = prev_block; + } + //Merge if the next is free + if(merge_with_next){ + block_to_insert->m_size += next_block->m_size; + assert(block_to_insert->m_size >= BlockCtrlUnits); + if(merge_with_prev) + m_header.m_imultiset.erase(Imultiset::s_iterator_to(*next_block)); + } + + bool only_merge_next = !merge_with_prev && merge_with_next; + imultiset_iterator free_block_to_check_it + (Imultiset::s_iterator_to(only_merge_next ? *next_block : *block_to_insert)); + imultiset_iterator was_bigger_it(free_block_to_check_it); + + //Now try to shortcut erasure + insertion (O(log(N))) with + //a O(1) operation if merging does not alter tree positions + if(++was_bigger_it != m_header.m_imultiset.end() && + block_to_insert->m_size > was_bigger_it->m_size ){ + m_header.m_imultiset.erase(free_block_to_check_it); + m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *block_to_insert); + } + else if(only_merge_next){ + m_header.m_imultiset.replace_node(free_block_to_check_it, *block_to_insert); + } + } + else{ + m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *block_to_insert); + } + priv_mark_as_free_block(block_to_insert); +} + +/// @endcond + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_MEM_ALGO_RBTREE_BEST_FIT_HPP diff --git a/win32/include/boost/interprocess/mem_algo/simple_seq_fit.hpp b/win32/include/boost/interprocess/mem_algo/simple_seq_fit.hpp new file mode 100755 index 000000000..bc6be5a74 --- /dev/null +++ b/win32/include/boost/interprocess/mem_algo/simple_seq_fit.hpp @@ -0,0 +1,56 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_SIMPLE_SEQ_FIT_HPP +#define BOOST_INTERPROCESS_SIMPLE_SEQ_FIT_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include + +//!\file +//!Describes sequential fit algorithm used to allocate objects in shared memory. + +namespace boost { +namespace interprocess { + +//!This class implements the simple sequential fit algorithm with a simply +//!linked list of free buffers. +template +class simple_seq_fit + : public detail::simple_seq_fit_impl +{ + /// @cond + typedef detail::simple_seq_fit_impl base_t; + /// @endcond + + public: + //!Constructor. "size" is the total size of the managed memory segment, + //!"extra_hdr_bytes" indicates the extra bytes beginning in the sizeof(simple_seq_fit) + //!offset that the allocator should not use at all.*/ + simple_seq_fit (std::size_t size, std::size_t extra_hdr_bytes) + : base_t(size, extra_hdr_bytes){} +}; + +} //namespace interprocess { + +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_SIMPLE_SEQ_FIT_HPP + diff --git a/win32/include/boost/interprocess/offset_ptr.hpp b/win32/include/boost/interprocess/offset_ptr.hpp new file mode 100755 index 000000000..2d1f8d6f4 --- /dev/null +++ b/win32/include/boost/interprocess/offset_ptr.hpp @@ -0,0 +1,454 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_OFFSET_PTR_HPP +#define BOOST_OFFSET_PTR_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a smart pointer that stores the offset between this pointer and +//!target pointee, called offset_ptr. + +namespace boost { + +//Predeclarations +template +struct has_trivial_constructor; + +template +struct has_trivial_destructor; + +namespace interprocess { + +//!A smart pointer that stores the offset between between the pointer and the +//!the object it points. This allows offset allows special properties, since +//!the pointer is independent from the address address of the pointee, if the +//!pointer and the pointee are still separated by the same offset. This feature +//!converts offset_ptr in a smart pointer that can be placed in shared memory and +//!memory mapped files mapped in different addresses in every process. +template +class offset_ptr +{ + /// @cond + typedef offset_ptr self_t; + + void unspecified_bool_type_func() const {} + typedef void (self_t::*unspecified_bool_type)() const; + + #if defined(_MSC_VER) && (_MSC_VER >= 1400) + __declspec(noinline) //this workaround is needed for msvc-8.0 and msvc-9.0 + #endif + void set_offset(const volatile void *ptr) + { set_offset((const void*)ptr); } + + void set_offset(const void *ptr) + { + const char *p = static_cast(const_cast(ptr)); + //offset == 1 && ptr != 0 is not legal for this pointer + if(!ptr){ + m_offset = 1; + } + else{ + m_offset = p - detail::char_ptr_cast(this); + BOOST_ASSERT(m_offset != 1); + } + } + + #if defined(_MSC_VER) && (_MSC_VER >= 1400) + __declspec(noinline) //this workaround is needed for msvc-8.0 and msvc-9.0 + #endif + void* get_pointer() const + { return (m_offset == 1) ? 0 : (detail::char_ptr_cast(this) + m_offset); } + + void inc_offset(std::ptrdiff_t bytes) + { m_offset += bytes; } + + void dec_offset(std::ptrdiff_t bytes) + { m_offset -= bytes; } + + std::ptrdiff_t m_offset; //Distance between this object and pointed address + /// @endcond + + public: + typedef PointedType * pointer; + typedef typename detail:: + add_reference::type reference; + typedef PointedType value_type; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; + + public: //Public Functions + + //!Constructor from raw pointer (allows "0" pointer conversion). + //!Never throws. + offset_ptr(pointer ptr = 0) { this->set_offset(ptr); } + + //!Constructor from other pointer. + //!Never throws. + template + offset_ptr(T *ptr) + { pointer p (ptr); (void)p; this->set_offset(p); } + + //!Constructor from other offset_ptr + //!Never throws. + offset_ptr(const offset_ptr& ptr) + { this->set_offset(ptr.get()); } + + //!Constructor from other offset_ptr. If pointers of pointee types are + //!convertible, offset_ptrs will be convertibles. Never throws. + template + offset_ptr(const offset_ptr &ptr) + { pointer p(ptr.get()); (void)p; this->set_offset(p); } + + //!Emulates static_cast operator. + //!Never throws. + template + offset_ptr(const offset_ptr & r, detail::static_cast_tag) + { this->set_offset(static_cast(r.get())); } + + //!Emulates const_cast operator. + //!Never throws. + template + offset_ptr(const offset_ptr & r, detail::const_cast_tag) + { this->set_offset(const_cast(r.get())); } + + //!Emulates dynamic_cast operator. + //!Never throws. + template + offset_ptr(const offset_ptr & r, detail::dynamic_cast_tag) + { this->set_offset(dynamic_cast(r.get())); } + + //!Emulates reinterpret_cast operator. + //!Never throws. + template + offset_ptr(const offset_ptr & r, detail::reinterpret_cast_tag) + { this->set_offset(reinterpret_cast(r.get())); } + + //!Obtains raw pointer from offset. + //!Never throws. + pointer get()const + { return (pointer)this->get_pointer(); } + + std::ptrdiff_t get_offset() + { return m_offset; } + + //!Pointer-like -> operator. It can return 0 pointer. + //!Never throws. + pointer operator->() const + { return this->get(); } + + //!Dereferencing operator, if it is a null offset_ptr behavior + //! is undefined. Never throws. + reference operator* () const + { return *(this->get()); } + + //!Indexing operator. + //!Never throws. + reference operator[](std::ptrdiff_t idx) const + { return this->get()[idx]; } + + //!Assignment from pointer (saves extra conversion). + //!Never throws. + offset_ptr& operator= (pointer from) + { this->set_offset(from); return *this; } + + //!Assignment from other offset_ptr. + //!Never throws. + offset_ptr& operator= (const offset_ptr & pt) + { pointer p(pt.get()); (void)p; this->set_offset(p); return *this; } + + //!Assignment from related offset_ptr. If pointers of pointee types + //! are assignable, offset_ptrs will be assignable. Never throws. + template + offset_ptr& operator= (const offset_ptr & pt) + { pointer p(pt.get()); this->set_offset(p); return *this; } + + //!offset_ptr + std::ptrdiff_t. + //!Never throws. + offset_ptr operator+ (std::ptrdiff_t offset) const + { return offset_ptr(this->get()+offset); } + + //!offset_ptr - std::ptrdiff_t. + //!Never throws. + offset_ptr operator- (std::ptrdiff_t offset) const + { return offset_ptr(this->get()-offset); } + + //!offset_ptr += std::ptrdiff_t. + //!Never throws. + offset_ptr &operator+= (std::ptrdiff_t offset) + { this->inc_offset(offset * sizeof (PointedType)); return *this; } + + //!offset_ptr -= std::ptrdiff_t. + //!Never throws. + offset_ptr &operator-= (std::ptrdiff_t offset) + { this->dec_offset(offset * sizeof (PointedType)); return *this; } + + //!++offset_ptr. + //!Never throws. + offset_ptr& operator++ (void) + { this->inc_offset(sizeof (PointedType)); return *this; } + + //!offset_ptr++. + //!Never throws. + offset_ptr operator++ (int) + { offset_ptr temp(*this); ++*this; return temp; } + + //!--offset_ptr. + //!Never throws. + offset_ptr& operator-- (void) + { this->dec_offset(sizeof (PointedType)); return *this; } + + //!offset_ptr--. + //!Never throws. + offset_ptr operator-- (int) + { offset_ptr temp(*this); --*this; return temp; } + + //!safe bool conversion operator. + //!Never throws. + operator unspecified_bool_type() const + { return this->get()? &self_t::unspecified_bool_type_func : 0; } + + //!Not operator. Not needed in theory, but improves portability. + //!Never throws + bool operator! () const + { return this->get() == 0; } +/* + friend void swap (offset_ptr &pt, offset_ptr &pt2) + { + value_type *ptr = pt.get(); + pt = pt2; + pt2 = ptr; + } +*/ +}; + +//!offset_ptr == offset_ptr. +//!Never throws. +template +inline bool operator== (const offset_ptr &pt1, + const offset_ptr &pt2) +{ return pt1.get() == pt2.get(); } + +//!offset_ptr != offset_ptr. +//!Never throws. +template +inline bool operator!= (const offset_ptr &pt1, + const offset_ptr &pt2) +{ return pt1.get() != pt2.get(); } + +//!offset_ptr < offset_ptr. +//!Never throws. +template +inline bool operator< (const offset_ptr &pt1, + const offset_ptr &pt2) +{ return pt1.get() < pt2.get(); } + +//!offset_ptr <= offset_ptr. +//!Never throws. +template +inline bool operator<= (const offset_ptr &pt1, + const offset_ptr &pt2) +{ return pt1.get() <= pt2.get(); } + +//!offset_ptr > offset_ptr. +//!Never throws. +template +inline bool operator> (const offset_ptr &pt1, + const offset_ptr &pt2) +{ return pt1.get() > pt2.get(); } + +//!offset_ptr >= offset_ptr. +//!Never throws. +template +inline bool operator>= (const offset_ptr &pt1, + const offset_ptr &pt2) +{ return pt1.get() >= pt2.get(); } + +//!operator<< +//!for offset ptr +template +inline std::basic_ostream & operator<< + (std::basic_ostream & os, offset_ptr const & p) +{ return os << p.get_offset(); } + +//!operator>> +//!for offset ptr +template +inline std::basic_istream & operator>> + (std::basic_istream & is, offset_ptr & p) +{ return is >> p.get_offset(); } + +//!std::ptrdiff_t + offset_ptr +//!operation +template +inline offset_ptr operator+(std::ptrdiff_t diff, const offset_ptr& right) +{ return right + diff; } + +//!offset_ptr - offset_ptr +//!operation +template +inline std::ptrdiff_t operator- (const offset_ptr &pt, const offset_ptr &pt2) +{ return pt.get()- pt2.get(); } + +//!swap specialization +//!for offset_ptr +template +inline void swap (boost::interprocess::offset_ptr &pt, + boost::interprocess::offset_ptr &pt2) +{ + typename offset_ptr::value_type *ptr = pt.get(); + pt = pt2; + pt2 = ptr; +} + +//!Simulation of static_cast between pointers. Never throws. +template +inline boost::interprocess::offset_ptr + static_pointer_cast(boost::interprocess::offset_ptr const & r) +{ + return boost::interprocess::offset_ptr + (r, boost::interprocess::detail::static_cast_tag()); +} + +//!Simulation of const_cast between pointers. Never throws. +template +inline boost::interprocess::offset_ptr + const_pointer_cast(boost::interprocess::offset_ptr const & r) +{ + return boost::interprocess::offset_ptr + (r, boost::interprocess::detail::const_cast_tag()); +} + +//!Simulation of dynamic_cast between pointers. Never throws. +template +inline boost::interprocess::offset_ptr + dynamic_pointer_cast(boost::interprocess::offset_ptr const & r) +{ + return boost::interprocess::offset_ptr + (r, boost::interprocess::detail::dynamic_cast_tag()); +} + +//!Simulation of reinterpret_cast between pointers. Never throws. +template +inline boost::interprocess::offset_ptr + reinterpret_pointer_cast(boost::interprocess::offset_ptr const & r) +{ + return boost::interprocess::offset_ptr + (r, boost::interprocess::detail::reinterpret_cast_tag()); +} + +} //namespace interprocess { + +/// @cond + +//!has_trivial_constructor<> == true_type specialization for optimizations +template +struct has_trivial_constructor< boost::interprocess::offset_ptr > +{ + enum { value = true }; +}; + +///has_trivial_destructor<> == true_type specialization for optimizations +template +struct has_trivial_destructor< boost::interprocess::offset_ptr > +{ + enum { value = true }; +}; + +//#if !defined(_MSC_VER) || (_MSC_VER >= 1400) +namespace interprocess { +//#endif +//!get_pointer() enables boost::mem_fn to recognize offset_ptr. +//!Never throws. +template +inline T * get_pointer(boost::interprocess::offset_ptr const & p) +{ return p.get(); } +//#if !defined(_MSC_VER) || (_MSC_VER >= 1400) +} //namespace interprocess +//#endif + +/// @endcond +} //namespace boost { + +/// @cond + +namespace boost{ + +//This is to support embedding a bit in the pointer +//for intrusive containers, saving space +namespace intrusive { + +//Predeclaration to avoid including header +template +struct max_pointer_plus_bits; + +template +struct max_pointer_plus_bits, Alignment> +{ + //The offset ptr can embed one bit less than the alignment since it + //uses offset == 1 to store the null pointer. + static const std::size_t value = ::boost::interprocess::detail::ls_zeros::value - 1; +}; + +//Predeclaration +template +struct pointer_plus_bits; + +template +struct pointer_plus_bits, NumBits> +{ + typedef boost::interprocess::offset_ptr pointer; + //Bits are stored in the lower bits of the pointer except the LSB, + //because this bit is used to represent the null pointer. + static const std::size_t Mask = ((std::size_t(1) << NumBits)-1)<<1u; + + static pointer get_pointer(const pointer &n) + { return (T*)(std::size_t(n.get()) & ~std::size_t(Mask)); } + + static void set_pointer(pointer &n, pointer p) + { + std::size_t pint = std::size_t(p.get()); + assert(0 == (std::size_t(pint) & Mask)); + n = (T*)(pint | (std::size_t(n.get()) & std::size_t(Mask))); + } + + static std::size_t get_bits(const pointer &n) + { return(std::size_t(n.get()) & std::size_t(Mask)) >> 1u; } + + static void set_bits(pointer &n, std::size_t b) + { + assert(b < (std::size_t(1) << NumBits)); + n = (T*)(std::size_t(get_pointer(n).get()) | (b << 1u)); + } +}; + +} //namespace intrusive +} //namespace boost{ +/// @endcond + +#include + +#endif //#ifndef BOOST_OFFSET_PTR_HPP + diff --git a/win32/include/boost/interprocess/segment_manager.hpp b/win32/include/boost/interprocess/segment_manager.hpp new file mode 100755 index 000000000..d95201428 --- /dev/null +++ b/win32/include/boost/interprocess/segment_manager.hpp @@ -0,0 +1,1348 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP +#define BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //std::size_t +#include //char_traits +#include //std::nothrow +#include //std::pair +#ifndef BOOST_NO_EXCEPTIONS +#include +#endif + +//!\file +//!Describes the object placed in a memory segment that provides +//!named object allocation capabilities for single-segment and +//!multi-segment allocations. + +namespace boost{ +namespace interprocess{ + +//!This object is the public base class of segment manager. +//!This class only depends on the memory allocation algorithm +//!and implements all the allocation features not related +//!to named or unique objects. +//! +//!Storing a reference to segment_manager forces +//!the holder class to be dependent on index types and character types. +//!When such dependence is not desirable and only anonymous and raw +//!allocations are needed, segment_manager_base is the correct answer. +template +class segment_manager_base + : private MemoryAlgorithm +{ + public: + typedef segment_manager_base segment_manager_base_type; + typedef typename MemoryAlgorithm::void_pointer void_pointer; + typedef typename MemoryAlgorithm::mutex_family mutex_family; + typedef MemoryAlgorithm memory_algorithm; + + /// @cond + + //Experimental. Don't use + typedef typename MemoryAlgorithm::multiallocation_iterator multiallocation_iterator; + typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain; + + /// @endcond + + //!This constant indicates the payload size + //!associated with each allocation of the memory algorithm + static const std::size_t PayloadPerAllocation = MemoryAlgorithm::PayloadPerAllocation; + + //!Constructor of the segment_manager_base + //! + //!"size" is the size of the memory segment where + //!the basic segment manager is being constructed. + //! + //!"reserved_bytes" is the number of bytes + //!after the end of the memory algorithm object itself + //!that the memory algorithm will exclude from + //!dynamic allocation + //! + //!Can throw + segment_manager_base(std::size_t size, std::size_t reserved_bytes) + : MemoryAlgorithm(size, reserved_bytes) + { + assert((sizeof(segment_manager_base) == sizeof(MemoryAlgorithm))); + } + + //!Returns the size of the memory + //!segment + std::size_t get_size() const + { return MemoryAlgorithm::get_size(); } + + //!Returns the number of free bytes of the memory + //!segment + std::size_t get_free_memory() const + { return MemoryAlgorithm::get_free_memory(); } + + //!Obtains the minimum size needed by + //!the segment manager + static std::size_t get_min_size (std::size_t size) + { return MemoryAlgorithm::get_min_size(size); } + + //!Allocates nbytes bytes. This function is only used in + //!single-segment management. Never throws + void * allocate (std::size_t nbytes, std::nothrow_t) + { return MemoryAlgorithm::allocate(nbytes); } + + /// @cond + + //Experimental. Dont' use. + //!Allocates n_elements of + //!elem_size bytes. Throws bad_alloc on failure. + multiallocation_iterator allocate_many(std::size_t elem_bytes, std::size_t num_elements) + { + multiallocation_iterator ret = MemoryAlgorithm::allocate_many(elem_bytes, num_elements); + if(!ret) throw bad_alloc(); + return ret; + } + + //!Allocates n_elements, each one of + //!element_lenghts[i]*sizeof_element bytes. Throws bad_alloc on failure. + multiallocation_iterator allocate_many + (const std::size_t *element_lenghts, std::size_t n_elements, std::size_t sizeof_element = 1) + { + multiallocation_iterator ret = MemoryAlgorithm::allocate_many(element_lenghts, n_elements, sizeof_element); + if(!ret) throw bad_alloc(); + return ret; + } + + //!Allocates n_elements of + //!elem_size bytes. Returns a default constructed iterator on failure. + multiallocation_iterator allocate_many(std::size_t elem_bytes, std::size_t num_elements, std::nothrow_t) + { return MemoryAlgorithm::allocate_many(elem_bytes, num_elements); } + + //!Allocates n_elements, each one of + //!element_lenghts[i]*sizeof_element bytes. + //!Returns a default constructed iterator on failure. + multiallocation_iterator allocate_many(const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element, std::nothrow_t) + { return MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element); } + + //!Deallocates elements pointed by the + //!multiallocation iterator range. + void deallocate_many(multiallocation_iterator it) + { MemoryAlgorithm::deallocate_many(it); } + + /// @endcond + + //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc + //!on failure + void * allocate(std::size_t nbytes) + { + void * ret = MemoryAlgorithm::allocate(nbytes); + if(!ret) + throw bad_alloc(); + return ret; + } + + //!Allocates nbytes bytes. This function is only used in + //!single-segment management. Never throws + void * allocate_aligned (std::size_t nbytes, std::size_t alignment, std::nothrow_t) + { return MemoryAlgorithm::allocate_aligned(nbytes, alignment); } + + //!Allocates nbytes bytes. This function is only used in + //!single-segment management. Throws bad_alloc when fails + void * allocate_aligned(std::size_t nbytes, std::size_t alignment) + { + void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment); + if(!ret) + throw bad_alloc(); + return ret; + } + + template + std::pair + allocation_command (allocation_type command, std::size_t limit_size, + std::size_t preferred_size,std::size_t &received_size, + T *reuse_ptr = 0) + { + std::pair ret = MemoryAlgorithm::allocation_command + ( command | nothrow_allocation, limit_size, preferred_size, received_size + , reuse_ptr); + if(!(command & nothrow_allocation) && !ret.first) + throw bad_alloc(); + return ret; + } + + std::pair + raw_allocation_command (allocation_type command, std::size_t limit_objects, + std::size_t preferred_objects,std::size_t &received_objects, + void *reuse_ptr = 0, std::size_t sizeof_object = 1) + { + std::pair ret = MemoryAlgorithm::raw_allocation_command + ( command | nothrow_allocation, limit_objects, preferred_objects, received_objects + , reuse_ptr, sizeof_object); + if(!(command & nothrow_allocation) && !ret.first) + throw bad_alloc(); + return ret; + } + + //!Deallocates the bytes allocated with allocate/allocate_many() + //!pointed by addr + void deallocate (void *addr) + { MemoryAlgorithm::deallocate(addr); } + + //!Increases managed memory in extra_size bytes more. This only works + //!with single-segment management. + void grow(std::size_t extra_size) + { MemoryAlgorithm::grow(extra_size); } + + //!Decreases managed memory to the minimum. This only works + //!with single-segment management. + void shrink_to_fit() + { MemoryAlgorithm::shrink_to_fit(); } + + //!Returns the result of "all_memory_deallocated()" function + //!of the used memory algorithm + bool all_memory_deallocated() + { return MemoryAlgorithm::all_memory_deallocated(); } + + //!Returns the result of "check_sanity()" function + //!of the used memory algorithm + bool check_sanity() + { return MemoryAlgorithm::check_sanity(); } + + //!Writes to zero free memory (memory not yet allocated) + //!of the memory algorithm + void zero_free_memory() + { MemoryAlgorithm::zero_free_memory(); } + + //!Returns the size of the buffer previously allocated pointed by ptr + std::size_t size(const void *ptr) const + { return MemoryAlgorithm::size(ptr); } + + /// @cond + protected: + void * prot_anonymous_construct + (std::size_t num, bool dothrow, detail::in_place_interface &table) + { + typedef detail::block_header block_header_t; + block_header_t block_info ( table.size*num + , table.alignment + , anonymous_type + , 1 + , 0); + + //Allocate memory + void *ptr_struct = this->allocate(block_info.total_size(), std::nothrow_t()); + + //Check if there is enough memory + if(!ptr_struct){ + if(dothrow){ + throw bad_alloc(); + } + else{ + return 0; + } + } + + //Build scoped ptr to avoid leaks with constructor exception + detail::mem_algo_deallocator mem(ptr_struct, *this); + + //Now construct the header + block_header_t * hdr = new(ptr_struct) block_header_t(block_info); + void *ptr = 0; //avoid gcc warning + ptr = hdr->value(); + + //Now call constructors + detail::array_construct(ptr, num, table); + + //All constructors successful, we don't want erase memory + mem.release(); + return ptr; + } + + //!Calls the destructor and makes an anonymous deallocate + void prot_anonymous_destroy(const void *object, detail::in_place_interface &table) + { + + //Get control data from associated with this object + typedef detail::block_header block_header_t; + block_header_t *ctrl_data = block_header_t::block_header_from_value(object, table.size, table.alignment); + + //------------------------------- + //scoped_lock guard(m_header); + //------------------------------- + + if(ctrl_data->allocation_type() != anonymous_type){ + //This is not an anonymous object, the pointer is wrong! + assert(0); + } + + //Call destructors and free memory + //Build scoped ptr to avoid leaks with destructor exception + std::size_t destroyed = 0; + table.destroy_n((void*)object, ctrl_data->m_value_bytes/table.size, destroyed); + this->deallocate(ctrl_data); + } + /// @endcond +}; + +//These pointers are the ones the user will use to +//indicate previous allocation types +static const detail::anonymous_instance_t * anonymous_instance = 0; +static const detail::unique_instance_t * unique_instance = 0; + +//!This object is placed in the beginning of memory segment and +//!implements the allocation (named or anonymous) of portions +//!of the segment. This object contains two indexes that +//!maintain an association between a name and a portion of the segment. +//! +//!The first index contains the mappings for normal named objects using the +//!char type specified in the template parameter. +//! +//!The second index contains the association for unique instances. The key will +//!be the const char * returned from type_info.name() function for the unique +//!type to be constructed. +//! +//!segment_manager inherits publicly +//!from segment_manager_base and inherits from it +//!many public functions related to anonymous object and raw memory allocation. +//!See segment_manager_base reference to know about those functions. +template class IndexType> +class segment_manager + : public segment_manager_base +{ + /// @cond + //Non-copyable + segment_manager(); + segment_manager(const segment_manager &); + segment_manager &operator=(const segment_manager &); + typedef segment_manager_base Base; + typedef detail::block_header block_header_t; + /// @endcond + + public: + typedef MemoryAlgorithm memory_algorithm; + typedef typename Base::void_pointer void_pointer; + typedef CharType char_type; + typedef typename Base::multiallocation_iterator multiallocation_iterator; + + typedef segment_manager_base segment_manager_base_type; + + static const std::size_t PayloadPerAllocation = Base::PayloadPerAllocation; + + /// @cond + private: + typedef detail::index_config index_config_named; + typedef detail::index_config index_config_unique; + typedef IndexType index_type; + typedef detail::bool_::value > is_intrusive_t; + typedef detail::bool_::value> is_node_index_t; + + public: + typedef IndexType named_index_t; + typedef IndexType unique_index_t; + typedef detail::char_ptr_holder char_ptr_holder_t; + typedef detail::segment_manager_iterator_transform + ::value> named_transform; + + typedef detail::segment_manager_iterator_transform + ::value> unique_transform; + /// @endcond + + typedef typename Base::mutex_family mutex_family; + + typedef transform_iterator + const_named_iterator; + typedef transform_iterator + const_unique_iterator; + + /// @cond + + //!Constructor proxy object definition helper class + template + struct construct_proxy + { + typedef detail::named_proxy type; + }; + + //!Constructor proxy object definition helper class + template + struct construct_iter_proxy + { + typedef detail::named_proxy type; + }; + + /// @endcond + + //!Constructor of the segment manager + //!"size" is the size of the memory segment where + //!the segment manager is being constructed. + //!Can throw + segment_manager(std::size_t size) + : Base(size, priv_get_reserved_bytes()) + , m_header(static_cast(get_this_pointer())) + { (void) anonymous_instance; (void) unique_instance; } + + //!Tries to find a previous named allocation. Returns the address + //!and the object count. On failure the first member of the + //!returned pair is 0. + template + std::pair find (const CharType* name) + { + //The name can't be null, no anonymous object can be found by name + assert(name != 0); + detail::placement_destroy table; + std::size_t size; + void *ret; + + if(name == reinterpret_cast(-1)){ + ret = priv_generic_find (typeid(T).name(), m_header.m_unique_index, table, size, is_intrusive_t(), true); + } + else{ + ret = priv_generic_find (name, m_header.m_named_index, table, size, is_intrusive_t(), true); + } + return std::pair(static_cast(ret), size); + } + + //!Tries to find a previous unique allocation. Returns the address + //!and the object count. On failure the first member of the + //!returned pair is 0. + template + std::pair find (const detail::unique_instance_t* name) + { + detail::placement_destroy table; + std::size_t size; + void *ret = priv_generic_find(name, m_header.m_unique_index, table, size, is_intrusive_t(), true); + return std::pair(static_cast(ret), size); + } + + //!Returns throwing "construct" proxy + //!object + template + typename construct_proxy::type + construct(char_ptr_holder_t name) + { return typename construct_proxy::type (this, name, false, true); } + + //!Returns throwing "search or construct" proxy + //!object + template + typename construct_proxy::type find_or_construct(char_ptr_holder_t name) + { return typename construct_proxy::type (this, name, true, true); } + + //!Returns no throwing "construct" proxy + //!object + template + typename construct_proxy::type + construct(char_ptr_holder_t name, std::nothrow_t) + { return typename construct_proxy::type (this, name, false, false); } + + //!Returns no throwing "search or construct" + //!proxy object + template + typename construct_proxy::type + find_or_construct(char_ptr_holder_t name, std::nothrow_t) + { return typename construct_proxy::type (this, name, true, false); } + + //!Returns throwing "construct from iterators" proxy object + template + typename construct_iter_proxy::type + construct_it(char_ptr_holder_t name) + { return typename construct_iter_proxy::type (this, name, false, true); } + + //!Returns throwing "search or construct from iterators" + //!proxy object + template + typename construct_iter_proxy::type + find_or_construct_it(char_ptr_holder_t name) + { return typename construct_iter_proxy::type (this, name, true, true); } + + //!Returns no throwing "construct from iterators" + //!proxy object + template + typename construct_iter_proxy::type + construct_it(char_ptr_holder_t name, std::nothrow_t) + { return typename construct_iter_proxy::type (this, name, false, false); } + + //!Returns no throwing "search or construct from iterators" + //!proxy object + template + typename construct_iter_proxy::type + find_or_construct_it(char_ptr_holder_t name, std::nothrow_t) + { return typename construct_iter_proxy::type (this, name, true, false); } + + //!Calls object function blocking recursive interprocess_mutex and guarantees that + //!no new named_alloc or destroy will be executed by any process while + //!executing the object function call*/ + template + void atomic_func(Func &f) + { scoped_lock guard(m_header); f(); } + + //!Destroys a previously created unique instance. + //!Returns false if the object was not present. + template + bool destroy(const detail::unique_instance_t *) + { + detail::placement_destroy dtor; + return this->priv_generic_named_destroy + (typeid(T).name(), m_header.m_unique_index, dtor, is_intrusive_t()); + } + + //!Destroys the named object with + //!the given name. Returns false if that object can't be found. + template + bool destroy(const CharType *name) + { + detail::placement_destroy dtor; + return this->priv_generic_named_destroy + (name, m_header.m_named_index, dtor, is_intrusive_t()); + } + + //!Destroys an anonymous, unique or named object + //!using it's address + template + void destroy_ptr(const T *p) + { + //If T is void transform it to char + typedef typename detail::char_if_void::type data_t; + detail::placement_destroy dtor; + priv_destroy_ptr(p, dtor); + } + + //!Returns the name of an object created with construct/find_or_construct + //!functions. Does not throw + template + static const CharType *get_instance_name(const T *ptr) + { return priv_get_instance_name(block_header_t::block_header_from_value(ptr)); } + + //!Returns the length of an object created with construct/find_or_construct + //!functions. Does not throw. + template + static std::size_t get_instance_length(const T *ptr) + { return priv_get_instance_length(block_header_t::block_header_from_value(ptr), sizeof(T)); } + + //!Returns is the the name of an object created with construct/find_or_construct + //!functions. Does not throw + template + static instance_type get_instance_type(const T *ptr) + { return priv_get_instance_type(block_header_t::block_header_from_value(ptr)); } + + //!Preallocates needed index resources to optimize the + //!creation of "num" named objects in the managed memory segment. + //!Can throw boost::interprocess::bad_alloc if there is no enough memory. + void reserve_named_objects(std::size_t num) + { + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + m_header.m_named_index.reserve(num); + } + + //!Preallocates needed index resources to optimize the + //!creation of "num" unique objects in the managed memory segment. + //!Can throw boost::interprocess::bad_alloc if there is no enough memory. + void reserve_unique_objects(std::size_t num) + { + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + m_header.m_unique_index.reserve(num); + } + + //!Calls shrink_to_fit in both named and unique object indexes + //!to try to free unused memory from those indexes. + void shrink_to_fit_indexes() + { + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + m_header.m_named_index.shrink_to_fit(); + m_header.m_unique_index.shrink_to_fit(); + } + + //!Returns the number of named objects stored in + //!the segment. + std::size_t get_num_named_objects() + { + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + return m_header.m_named_index.size(); + } + + //!Returns the number of unique objects stored in + //!the segment. + std::size_t get_num_unique_objects() + { + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + return m_header.m_unique_index.size(); + } + + //!Obtains the minimum size needed by the + //!segment manager + static std::size_t get_min_size() + { return Base::get_min_size(priv_get_reserved_bytes()); } + + //!Returns a constant iterator to the beginning of the information about + //!the named allocations performed in this segment manager + const_named_iterator named_begin() const + { + return make_transform_iterator + (m_header.m_named_index.begin(), named_transform()); + } + + //!Returns a constant iterator to the end of the information about + //!the named allocations performed in this segment manager + const_named_iterator named_end() const + { + return make_transform_iterator + (m_header.m_named_index.end(), named_transform()); + } + + //!Returns a constant iterator to the beginning of the information about + //!the unique allocations performed in this segment manager + const_unique_iterator unique_begin() const + { + return make_transform_iterator + (m_header.m_unique_index.begin(), unique_transform()); + } + + //!Returns a constant iterator to the end of the information about + //!the unique allocations performed in this segment manager + const_unique_iterator unique_end() const + { + return make_transform_iterator + (m_header.m_unique_index.end(), unique_transform()); + } + + //!This is the default allocator to allocate types T + //!from this managed segment + template + struct allocator + { + typedef boost::interprocess::allocator type; + }; + + //!Returns an instance of the default allocator for type T + //!initialized that allocates memory from this segment manager. + template + typename allocator::type + get_allocator() + { return typename allocator::type(this); } + + //!This is the default deleter to delete types T + //!from this managed segment. + template + struct deleter + { + typedef boost::interprocess::deleter type; + }; + + //!Returns an instance of the default allocator for type T + //!initialized that allocates memory from this segment manager. + template + typename deleter::type + get_deleter() + { return typename deleter::type(this); } + /// @cond + + //!Generic named/anonymous new function. Offers all the possibilities, + //!such as throwing, search before creating, and the constructor is + //!encapsulated in an object function. + template + T *generic_construct(const CharType *name, + std::size_t num, + bool try2find, + bool dothrow, + detail::in_place_interface &table) + { + return static_cast + (priv_generic_construct(name, num, try2find, dothrow, table)); + } + + //!Tries to find a previous named allocation. Returns the address + //!and the object count. On failure the first member of the + //!returned pair is 0. + template + std::pair find_no_lock (const CharType* name) + { + //The name can't be null, no anonymous object can be found by name + assert(name != 0); + detail::placement_destroy table; + std::size_t size; + void *ret; + + if(name == reinterpret_cast(-1)){ + ret = priv_generic_find (typeid(T).name(), m_header.m_unique_index, table, size, is_intrusive_t(), false); + } + else{ + ret = priv_generic_find (name, m_header.m_named_index, table, size, is_intrusive_t(), false); + } + return std::pair(static_cast(ret), size); + } + + //!Tries to find a previous unique allocation. Returns the address + //!and the object count. On failure the first member of the + //!returned pair is 0. + template + std::pair find_no_lock (const detail::unique_instance_t* name) + { + detail::placement_destroy table; + std::size_t size; + void *ret = priv_generic_find(name, m_header.m_unique_index, table, size, is_intrusive_t(), false); + return std::pair(static_cast(ret), size); + } + + private: + void *priv_generic_construct(const CharType *name, + std::size_t num, + bool try2find, + bool dothrow, + detail::in_place_interface &table) + { + void *ret; + //Security overflow check + if(num > ((std::size_t)-1)/table.size){ + if(dothrow) + throw bad_alloc(); + else + return 0; + } + if(name == 0){ + ret = this->prot_anonymous_construct(num, dothrow, table); + } + else if(name == reinterpret_cast(-1)){ + ret = this->priv_generic_named_construct + (unique_type, table.type_name, num, try2find, dothrow, table, m_header.m_unique_index, is_intrusive_t()); + } + else{ + ret = this->priv_generic_named_construct + (named_type, name, num, try2find, dothrow, table, m_header.m_named_index, is_intrusive_t()); + } + return ret; + } + + void priv_destroy_ptr(const void *ptr, detail::in_place_interface &dtor) + { + block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr, dtor.size, dtor.alignment); + switch(ctrl_data->allocation_type()){ + case anonymous_type: + this->prot_anonymous_destroy(ptr, dtor); + break; + + case named_type: + this->priv_generic_named_destroy + (ctrl_data, m_header.m_named_index, dtor, is_node_index_t()); + break; + + case unique_type: + this->priv_generic_named_destroy + (ctrl_data, m_header.m_unique_index, dtor, is_node_index_t()); + break; + + default: + //This type is unknown, bad pointer passed to this function! + assert(0); + break; + } + } + + //!Returns the name of an object created with construct/find_or_construct + //!functions. Does not throw + static const CharType *priv_get_instance_name(block_header_t *ctrl_data) + { + allocation_type type = ctrl_data->allocation_type(); + if(type != named_type){ + assert((type == anonymous_type && ctrl_data->m_num_char == 0) || + (type == unique_type && ctrl_data->m_num_char != 0) ); + return 0; + } + CharType *name = static_cast(ctrl_data->template name()); + + //Sanity checks + assert(ctrl_data->sizeof_char() == sizeof(CharType)); + assert(ctrl_data->m_num_char == std::char_traits::length(name)); + return name; + } + + static std::size_t priv_get_instance_length(block_header_t *ctrl_data, std::size_t sizeofvalue) + { + //Get header + assert((ctrl_data->value_bytes() %sizeofvalue) == 0); + return ctrl_data->value_bytes()/sizeofvalue; + } + + //!Returns is the the name of an object created with construct/find_or_construct + //!functions. Does not throw + static instance_type priv_get_instance_type(block_header_t *ctrl_data) + { + //Get header + assert((instance_type)ctrl_data->allocation_type() < max_allocation_type); + return (instance_type)ctrl_data->allocation_type(); + } + + static std::size_t priv_get_reserved_bytes() + { + //Get the number of bytes until the end of (*this) + //beginning in the end of the Base base. + return (detail::char_ptr_cast((segment_manager*)0) + sizeof(segment_manager)) - + (detail::char_ptr_cast(static_cast((segment_manager*)0)) + sizeof(Base)); + } + + template + void *priv_generic_find + (const CharT* name, + IndexType > &index, + detail::in_place_interface &table, + std::size_t &length, + detail::true_ is_intrusive, + bool use_lock) + { + (void)is_intrusive; + typedef IndexType > index_type; + typedef detail::index_key index_key_t; + typedef typename index_type::iterator index_it; + + //------------------------------- + scoped_lock guard(priv_get_lock(use_lock)); + //------------------------------- + //Find name in index + detail::intrusive_compare_key key + (name, std::char_traits::length(name)); + index_it it = index.find(key); + + //Initialize return values + void *ret_ptr = 0; + length = 0; + + //If found, assign values + if(it != index.end()){ + //Get header + block_header_t *ctrl_data = it->get_block_header(); + + //Sanity check + assert((ctrl_data->m_value_bytes % table.size) == 0); + assert(ctrl_data->sizeof_char() == sizeof(CharT)); + ret_ptr = ctrl_data->value(); + length = ctrl_data->m_value_bytes/table.size; + } + return ret_ptr; + } + + template + void *priv_generic_find + (const CharT* name, + IndexType > &index, + detail::in_place_interface &table, + std::size_t &length, + detail::false_ is_intrusive, + bool use_lock) + { + (void)is_intrusive; + typedef IndexType > index_type; + typedef typename index_type::key_type key_type; + typedef typename index_type::iterator index_it; + + //------------------------------- + scoped_lock guard(priv_get_lock(use_lock)); + //------------------------------- + //Find name in index + index_it it = index.find(key_type(name, std::char_traits::length(name))); + + //Initialize return values + void *ret_ptr = 0; + length = 0; + + //If found, assign values + if(it != index.end()){ + //Get header + block_header_t *ctrl_data = reinterpret_cast + (detail::get_pointer(it->second.m_ptr)); + + //Sanity check + assert((ctrl_data->m_value_bytes % table.size) == 0); + assert(ctrl_data->sizeof_char() == sizeof(CharT)); + ret_ptr = ctrl_data->value(); + length = ctrl_data->m_value_bytes/table.size; + } + return ret_ptr; + } + + template + bool priv_generic_named_destroy + (block_header_t *block_header, + IndexType > &index, + detail::in_place_interface &table, + detail::true_ is_node_index) + { + (void)is_node_index; + typedef typename IndexType >::iterator index_it; + + index_it *ihdr = block_header_t::to_first_header(block_header); + return this->priv_generic_named_destroy_impl(*ihdr, index, table); + } + + template + bool priv_generic_named_destroy + (block_header_t *block_header, + IndexType > &index, + detail::in_place_interface &table, + detail::false_ is_node_index) + { + (void)is_node_index; + CharT *name = static_cast(block_header->template name()); + return this->priv_generic_named_destroy(name, index, table, is_intrusive_t()); + } + + template + bool priv_generic_named_destroy(const CharT *name, + IndexType > &index, + detail::in_place_interface &table, + detail::true_ is_intrusive_index) + { + (void)is_intrusive_index; + typedef IndexType > index_type; + typedef detail::index_key index_key_t; + typedef typename index_type::iterator index_it; + typedef typename index_type::value_type intrusive_value_type; + + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + //Find name in index + detail::intrusive_compare_key key + (name, std::char_traits::length(name)); + index_it it = index.find(key); + + //If not found, return false + if(it == index.end()){ + //This name is not present in the index, wrong pointer or name! + //assert(0); + return false; + } + + block_header_t *ctrl_data = it->get_block_header(); + intrusive_value_type *iv = intrusive_value_type::get_intrusive_value_type(ctrl_data); + void *memory = iv; + void *values = ctrl_data->value(); + std::size_t num = ctrl_data->m_value_bytes/table.size; + + //Sanity check + assert((ctrl_data->m_value_bytes % table.size) == 0); + assert(sizeof(CharT) == ctrl_data->sizeof_char()); + + //Erase node from index + index.erase(it); + + //Destroy the headers + ctrl_data->~block_header_t(); + iv->~intrusive_value_type(); + + //Call destructors and free memory + std::size_t destroyed; + table.destroy_n(values, num, destroyed); + this->deallocate(memory); + return true; + } + + template + bool priv_generic_named_destroy(const CharT *name, + IndexType > &index, + detail::in_place_interface &table, + detail::false_ is_intrusive_index) + { + (void)is_intrusive_index; + typedef IndexType > index_type; + typedef typename index_type::iterator index_it; + typedef typename index_type::key_type key_type; + + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + //Try to find the name in the index + index_it it = index.find(key_type (name, + std::char_traits::length(name))); + + //If not found, return false + if(it == index.end()){ + //This name is not present in the index, wrong pointer or name! + assert(0); + return false; + } + return this->priv_generic_named_destroy_impl(it, index, table); + } + + template + bool priv_generic_named_destroy_impl + (const typename IndexType >::iterator &it, + IndexType > &index, + detail::in_place_interface &table) + { + typedef IndexType > index_type; + typedef typename index_type::iterator index_it; + + //Get allocation parameters + block_header_t *ctrl_data = reinterpret_cast + (detail::get_pointer(it->second.m_ptr)); + char *stored_name = detail::char_ptr_cast(it->first.name()); + (void)stored_name; + + //Check if the distance between the name pointer and the memory pointer + //is correct (this can detect incorrect type in destruction) + std::size_t num = ctrl_data->m_value_bytes/table.size; + void *values = ctrl_data->value(); + + //Sanity check + assert((ctrl_data->m_value_bytes % table.size) == 0); + assert((void*)stored_name == ctrl_data->template name()); + assert(sizeof(CharT) == ctrl_data->sizeof_char()); + + //Erase node from index + index.erase(it); + + //Destroy the header + ctrl_data->~block_header_t(); + + void *memory; + if(is_node_index_t::value){ + index_it *ihdr = block_header_t:: + to_first_header(ctrl_data); + ihdr->~index_it(); + memory = ihdr; + } + else{ + memory = ctrl_data; + } + + //Call destructors and free memory + std::size_t destroyed; + table.destroy_n(values, num, destroyed); + this->deallocate(memory); + return true; + } + + template + void * priv_generic_named_construct(std::size_t type, + const CharT *name, + std::size_t num, + bool try2find, + bool dothrow, + detail::in_place_interface &table, + IndexType > &index, + detail::true_ is_intrusive) + { + (void)is_intrusive; + std::size_t namelen = std::char_traits::length(name); + + block_header_t block_info ( table.size*num + , table.alignment + , type + , sizeof(CharT) + , namelen); + + typedef IndexType > index_type; + typedef typename index_type::iterator index_it; + typedef std::pair index_ib; + + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + //Insert the node. This can throw. + //First, we want to know if the key is already present before + //we allocate any memory, and if the key is not present, we + //want to allocate all memory in a single buffer that will + //contain the name and the user buffer. + // + //Since equal_range(key) + insert(hint, value) approach is + //quite inefficient in container implementations + //(they re-test if the position is correct), I've chosen + //to insert the node, do an ugly un-const cast and modify + //the key (which is a smart pointer) to an equivalent one + index_ib insert_ret; + + typename index_type::insert_commit_data commit_data; + typedef typename index_type::value_type intrusive_value_type; + + BOOST_TRY{ + detail::intrusive_compare_key key(name, namelen); + insert_ret = index.insert_check(key, commit_data); + } + //Ignore exceptions + BOOST_CATCH(...){ + if(dothrow) + BOOST_RETHROW + return 0; + } + BOOST_CATCH_END + + index_it it = insert_ret.first; + + //If found and this is find or construct, return data + //else return null + if(!insert_ret.second){ + if(try2find){ + return it->get_block_header()->value(); + } + return 0; + } + + //Allocates buffer for name + data, this can throw (it hurts) + void *buffer_ptr; + + //Check if there is enough memory + if(dothrow){ + buffer_ptr = this->allocate + (block_info.total_size_with_header()); + } + else{ + buffer_ptr = this->allocate + (block_info.total_size_with_header(), std::nothrow_t()); + if(!buffer_ptr) + return 0; + } + + //Now construct the intrusive hook plus the header + intrusive_value_type * intrusive_hdr = new(buffer_ptr) intrusive_value_type(); + block_header_t * hdr = new(intrusive_hdr->get_block_header())block_header_t(block_info); + void *ptr = 0; //avoid gcc warning + ptr = hdr->value(); + + //Copy name to memory segment and insert data + CharT *name_ptr = static_cast(hdr->template name()); + std::char_traits::copy(name_ptr, name, namelen+1); + + BOOST_TRY{ + //Now commit the insertion using previous context data + it = index.insert_commit(*intrusive_hdr, commit_data); + } + //Ignore exceptions + BOOST_CATCH(...){ + if(dothrow) + BOOST_RETHROW + return 0; + } + BOOST_CATCH_END + + //Initialize the node value_eraser to erase inserted node + //if something goes wrong + value_eraser v_eraser(index, it); + + //Avoid constructions if constructor is trivial + //Build scoped ptr to avoid leaks with constructor exception + detail::mem_algo_deallocator mem + (buffer_ptr, *static_cast(this)); + + //Construct array, this can throw + detail::array_construct(ptr, num, table); + + //All constructors successful, we don't want to release memory + mem.release(); + //Release node v_eraser since construction was successful + v_eraser.release(); + return ptr; + } + + //!Generic named new function for + //!named functions + template + void * priv_generic_named_construct(std::size_t type, + const CharT *name, + std::size_t num, + bool try2find, + bool dothrow, + detail::in_place_interface &table, + IndexType > &index, + detail::false_ is_intrusive) + { + (void)is_intrusive; + std::size_t namelen = std::char_traits::length(name); + + block_header_t block_info ( table.size*num + , table.alignment + , type + , sizeof(CharT) + , namelen); + + typedef IndexType > index_type; + typedef typename index_type::key_type key_type; + typedef typename index_type::mapped_type mapped_type; + typedef typename index_type::value_type value_type; + typedef typename index_type::iterator index_it; + typedef std::pair index_ib; + + //------------------------------- + scoped_lock guard(m_header); + //------------------------------- + //Insert the node. This can throw. + //First, we want to know if the key is already present before + //we allocate any memory, and if the key is not present, we + //want to allocate all memory in a single buffer that will + //contain the name and the user buffer. + // + //Since equal_range(key) + insert(hint, value) approach is + //quite inefficient in container implementations + //(they re-test if the position is correct), I've chosen + //to insert the node, do an ugly un-const cast and modify + //the key (which is a smart pointer) to an equivalent one + index_ib insert_ret; + BOOST_TRY{ + insert_ret = index.insert(value_type(key_type (name, namelen), + mapped_type(0))); + } + //Ignore exceptions + BOOST_CATCH(...){ + if(dothrow) + BOOST_RETHROW; + return 0; + } + BOOST_CATCH_END + + index_it it = insert_ret.first; + + //If found and this is find or construct, return data + //else return null + if(!insert_ret.second){ + if(try2find){ + block_header_t *hdr = static_cast + (detail::get_pointer(it->second.m_ptr)); + return hdr->value(); + } + return 0; + } + //Initialize the node value_eraser to erase inserted node + //if something goes wrong + value_eraser v_eraser(index, it); + + //Allocates buffer for name + data, this can throw (it hurts) + void *buffer_ptr; + block_header_t * hdr; + + //Allocate and construct the headers + if(is_node_index_t::value){ + std::size_t total_size = block_info.total_size_with_header(); + if(dothrow){ + buffer_ptr = this->allocate(total_size); + } + else{ + buffer_ptr = this->allocate(total_size, std::nothrow_t()); + if(!buffer_ptr) + return 0; + } + index_it *idr = new(buffer_ptr) index_it(it); + hdr = block_header_t::from_first_header(idr); + } + else{ + if(dothrow){ + buffer_ptr = this->allocate(block_info.total_size()); + } + else{ + buffer_ptr = this->allocate(block_info.total_size(), std::nothrow_t()); + if(!buffer_ptr) + return 0; + } + hdr = static_cast(buffer_ptr); + } + + hdr = new(hdr)block_header_t(block_info); + void *ptr = 0; //avoid gcc warning + ptr = hdr->value(); + + //Copy name to memory segment and insert data + CharT *name_ptr = static_cast(hdr->template name()); + std::char_traits::copy(name_ptr, name, namelen+1); + + //Do the ugly cast, please mama, forgive me! + //This new key points to an identical string, so it must have the + //same position than the overwritten key according to the predicate + const_cast(it->first).name(name_ptr); + it->second.m_ptr = hdr; + + //Build scoped ptr to avoid leaks with constructor exception + detail::mem_algo_deallocator mem + (buffer_ptr, *static_cast(this)); + + //Construct array, this can throw + detail::array_construct(ptr, num, table); + + //All constructors successful, we don't want to release memory + mem.release(); + + //Release node v_eraser since construction was successful + v_eraser.release(); + return ptr; + } + + private: + //!Returns the this pointer + segment_manager *get_this_pointer() + { return this; } + + typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type rmutex; + + #ifdef BOOST_INTERPROCESS_RVALUE_REFERENCE + scoped_lock + #else + detail::move_return > + #endif + priv_get_lock(bool use_lock) + { + scoped_lock local(m_header, defer_lock); + if(use_lock){ + local.lock(); + } + return local; + } + + //!This struct includes needed data and derives from + //!rmutex to allow EBO when using null interprocess_mutex + struct header_t + : public rmutex + { + named_index_t m_named_index; + unique_index_t m_unique_index; + + header_t(Base *restricted_segment_mngr) + : m_named_index (restricted_segment_mngr) + , m_unique_index(restricted_segment_mngr) + {} + } m_header; + /// @endcond +}; + + +}} //namespace boost { namespace interprocess + +#include + +#endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP + diff --git a/win32/include/boost/interprocess/shared_memory_object.hpp b/win32/include/boost/interprocess/shared_memory_object.hpp new file mode 100755 index 000000000..65e302065 --- /dev/null +++ b/win32/include/boost/interprocess/shared_memory_object.hpp @@ -0,0 +1,379 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_SHARED_MEMORY_OBJECT_HPP +#define BOOST_INTERPROCESS_SHARED_MEMORY_OBJECT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //std::remove +#include + +#ifdef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS +# include //O_CREAT, O_*... +# include //shm_xxx +# include //ftruncate, close +# include //mode_t, S_IRWXG, S_IRWXO, S_IRWXU, +#else +// +#endif + +//!\file +//!Describes a shared memory object management class. + +namespace boost { +namespace interprocess { + +//!A class that wraps a shared memory mapping that can be used to +//!create mapped regions from the mapped files +class shared_memory_object +{ + /// @cond + //Non-copyable and non-assignable + shared_memory_object(const shared_memory_object &); + shared_memory_object &operator=(const shared_memory_object &); + /// @endcond + + public: + + //!Default constructor. Represents an empty shared_memory_object. + shared_memory_object(); + + //!Creates a shared memory object with name "name" and mode "mode", with the access mode "mode" + //!If the file previously exists, throws an error.*/ + shared_memory_object(create_only_t, const char *name, mode_t mode) + { this->priv_open_or_create(detail::DoCreate, name, mode); } + + //!Tries to create a shared memory object with name "name" and mode "mode", with the + //!access mode "mode". If the file previously exists, it tries to open it with mode "mode". + //!Otherwise throws an error. + shared_memory_object(open_or_create_t, const char *name, mode_t mode) + { this->priv_open_or_create(detail::DoOpenOrCreate, name, mode); } + + //!Tries to open a shared memory object with name "name", with the access mode "mode". + //!If the file does not previously exist, it throws an error. + shared_memory_object(open_only_t, const char *name, mode_t mode) + { this->priv_open_or_create(detail::DoOpen, name, mode); } + + //!Moves the ownership of "moved"'s shared memory object to *this. + //!After the call, "moved" does not represent any shared memory object. + //!Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + shared_memory_object + (const detail::moved_object moved) + : m_handle(file_handle_t(detail::invalid_file())) + { this->swap(moved.get()); } + #else + shared_memory_object(shared_memory_object &&moved) + : m_handle(file_handle_t(detail::invalid_file())) + { this->swap(moved); } + #endif + + //!Moves the ownership of "moved"'s shared memory to *this. + //!After the call, "moved" does not represent any shared memory. + //!Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + shared_memory_object &operator= + (detail::moved_object moved) + { + shared_memory_object tmp(moved); + this->swap(tmp); + return *this; + } + #else + shared_memory_object &operator=(shared_memory_object &&moved) + { + shared_memory_object tmp(detail::move_impl(moved)); + this->swap(tmp); + return *this; + } + #endif + + //!Swaps the shared_memory_objects. Does not throw + void swap(shared_memory_object &other); + + //!Erases a shared memory object from the system. + //!Returns false on error. Never throws + static bool remove(const char *name); + + //!Sets the size of the shared memory mapping + void truncate(offset_t length); + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. All mapped regions are still + //!valid after destruction. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~shared_memory_object(); + + //!Returns the name of the file. + const char *get_name() const; + + //!Returns the name of the file + //!used in the constructor + bool get_size(offset_t &size) const; + + //!Returns access mode + mode_t get_mode() const; + + //!Returns mapping handle. Never throws. + mapping_handle_t get_mapping_handle() const; + + /// @cond + private: + + //!Closes a previously opened file mapping. Never throws. + void priv_close(); + + //!Closes a previously opened file mapping. Never throws. + bool priv_open_or_create(detail::create_enum_t type, const char *filename, mode_t mode); + + file_handle_t m_handle; + mode_t m_mode; + std::string m_filename; + /// @endcond +}; + +/// @cond + +inline shared_memory_object::shared_memory_object() + : m_handle(file_handle_t(detail::invalid_file())) +{} + +inline shared_memory_object::~shared_memory_object() +{ this->priv_close(); } + + +inline const char *shared_memory_object::get_name() const +{ return m_filename.c_str(); } + +inline bool shared_memory_object::get_size(offset_t &size) const +{ return detail::get_file_size((file_handle_t)m_handle, size); } + +inline void shared_memory_object::swap(shared_memory_object &other) +{ + std::swap(m_handle, other.m_handle); + std::swap(m_mode, other.m_mode); + m_filename.swap(other.m_filename); +} + +inline mapping_handle_t shared_memory_object::get_mapping_handle() const +{ return detail::mapping_handle_from_file_handle(m_handle); } + +inline mode_t shared_memory_object::get_mode() const +{ return m_mode; } + +#if !defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS) + +inline bool shared_memory_object::priv_open_or_create + (detail::create_enum_t type, const char *filename, mode_t mode) +{ + m_filename = filename; + std::string shmfile; + detail::create_tmp_dir_and_get_filename(filename, shmfile); + + //Set accesses + if (mode != read_write && mode != read_only){ + error_info err = other_error; + throw interprocess_exception(err); + } + + switch(type){ + case detail::DoOpen: + m_handle = detail::open_existing_file(shmfile.c_str(), mode, true); + break; + case detail::DoCreate: + m_handle = detail::create_new_file(shmfile.c_str(), mode, true); + break; + case detail::DoOpenOrCreate: + m_handle = detail::create_or_open_file(shmfile.c_str(), mode, true); + break; + default: + { + error_info err = other_error; + throw interprocess_exception(err); + } + } + + //Check for error + if(m_handle == detail::invalid_file()){ + error_info err = system_error_code(); + this->priv_close(); + throw interprocess_exception(err); + } + + m_mode = mode; + return true; +} + +inline bool shared_memory_object::remove(const char *filename) +{ + try{ + //Make sure a temporary path is created for shared memory + std::string shmfile; + detail::tmp_filename(filename, shmfile); + return std::remove(shmfile.c_str()) == 0; + } + catch(...){ + return false; + } +} + +inline void shared_memory_object::truncate(offset_t length) +{ + if(!detail::truncate_file(m_handle, length)){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } +} + +inline void shared_memory_object::priv_close() +{ + if(m_handle != detail::invalid_file()){ + detail::close_file(m_handle); + m_handle = detail::invalid_file(); + } +} + +#else //!defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS) + +inline bool shared_memory_object::priv_open_or_create + (detail::create_enum_t type, + const char *filename, + mode_t mode) +{ + #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY + detail::add_leading_slash(filename, m_filename); + #else + detail::create_tmp_dir_and_get_filename(filename, m_filename); + #endif + + //Create new mapping + int oflag = 0; + if(mode == read_only){ + oflag |= O_RDONLY; + } + else if(mode == read_write){ + oflag |= O_RDWR; + } + else{ + error_info err(mode_error); + throw interprocess_exception(err); + } + + switch(type){ + case detail::DoOpen: + //No addition + break; + case detail::DoCreate: + oflag |= (O_CREAT | O_EXCL); + break; + case detail::DoOpenOrCreate: + oflag |= O_CREAT; + break; + default: + { + error_info err = other_error; + throw interprocess_exception(err); + } + } + + //Open file using POSIX API + m_handle = shm_open(m_filename.c_str(), oflag, S_IRWXO | S_IRWXG | S_IRWXU); + + //Check for error + if(m_handle == -1){ + error_info err = errno; + this->priv_close(); + throw interprocess_exception(err); + } + + m_filename = filename; + m_mode = mode; + return true; +} + +inline bool shared_memory_object::remove(const char *filename) +{ + try{ + std::string file_str; + #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY + detail::add_leading_slash(filename, file_str); + #else + detail::tmp_filename(filename, file_str); + #endif + return 0 != shm_unlink(file_str.c_str()); + } + catch(...){ + return false; + } +} + +inline void shared_memory_object::truncate(offset_t length) +{ + if(0 != ftruncate(m_handle, length)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +inline void shared_memory_object::priv_close() +{ + if(m_handle != -1){ + ::close(m_handle); + m_handle = -1; + } +} + +#endif + +//!Trait class to detect if a type is +//!movable +template<> +struct is_movable +{ + enum { value = true }; +}; + +///@endcond + +//!A class that stores the name of a shared memory +//!and calls shared_memory_object::remove(name) in its destructor +//!Useful to remove temporary shared memory objects in the presence +//!of exceptions +class remove_shared_memory_on_destroy +{ + const char * m_name; + public: + remove_shared_memory_on_destroy(const char *name) + : m_name(name) + {} + + ~remove_shared_memory_on_destroy() + { shared_memory_object::remove(m_name); } +}; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_SHARED_MEMORY_OBJECT_HPP diff --git a/win32/include/boost/interprocess/smart_ptr/deleter.hpp b/win32/include/boost/interprocess/smart_ptr/deleter.hpp new file mode 100755 index 000000000..14fe0cfcb --- /dev/null +++ b/win32/include/boost/interprocess/smart_ptr/deleter.hpp @@ -0,0 +1,61 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2008. +// +// 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DELETER_HPP +#define BOOST_INTERPROCESS_DELETER_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include + +//!\file +//!Describes the functor to delete objects from the segment. + +namespace boost { +namespace interprocess { + +//!A deleter that uses the segment manager's destroy_ptr +//!function to destroy the passed pointer resource. +//! +//!This deleter is used +template +class deleter +{ + public: + typedef typename detail::pointer_to_other + ::type pointer; + + private: + typedef typename detail::pointer_to_other + ::type segment_manager_pointer; + + segment_manager_pointer mp_mngr; + + public: + deleter(segment_manager_pointer pmngr) + : mp_mngr(pmngr) + {} + + void operator()(const pointer &p) + { mp_mngr->destroy_ptr(detail::get_pointer(p)); } +}; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_DELETER_HPP diff --git a/win32/include/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp b/win32/include/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp new file mode 100755 index 000000000..b02912b7e --- /dev/null +++ b/win32/include/boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp @@ -0,0 +1,44 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/detail/bad_weak_ptr.hpp +// +// (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003 +// (C) Copyright Ion Gaztanaga 2006. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTERPROCESS_BAD_WEAK_PTR_HPP_INCLUDED +#define BOOST_INTERPROCESS_BAD_WEAK_PTR_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include + +#ifndef BOOST_NO_EXCEPTIONS +#include +#endif + +namespace boost{ +namespace interprocess{ + +class bad_weak_ptr + : public std::exception +{ + public: + + virtual char const * what() const throw() + { return "boost::interprocess::bad_weak_ptr"; } +}; + +} // namespace interprocess +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_BAD_WEAK_PTR_HPP_INCLUDED diff --git a/win32/include/boost/interprocess/smart_ptr/detail/shared_count.hpp b/win32/include/boost/interprocess/smart_ptr/detail/shared_count.hpp new file mode 100755 index 000000000..3b8e6bb4d --- /dev/null +++ b/win32/include/boost/interprocess/smart_ptr/detail/shared_count.hpp @@ -0,0 +1,320 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/detail/shared_count.hpp +// +// (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003 +// (C) Copyright Peter Dimov 2004-2005 +// (C) Copyright Ion Gaztanaga 2006-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED +#define BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include // std::less + +namespace boost { +namespace interprocess { +namespace detail{ + +template +class weak_count; + +template +class shared_count +{ + public: + typedef typename detail::pointer_to_other + ::type pointer; + + private: + typedef sp_counted_impl_pd counted_impl; + typedef typename detail::pointer_to_other + ::type counted_impl_ptr; + typedef typename detail::pointer_to_other + ::type counted_base_ptr; + typedef typename VoidAllocator::template rebind + ::other counted_impl_allocator; + typedef typename detail::pointer_to_other + ::type const_deleter_pointer; + typedef typename detail::pointer_to_other + ::type const_allocator_pointer; + + pointer m_px; + counted_impl_ptr m_pi; + + template + friend class weak_count; + + template + friend class shared_count; + + public: + + shared_count() + : m_px(0), m_pi(0) // nothrow + {} + + template + shared_count(const shared_count &other_shared_count, const Ptr &p) + : m_px(p), m_pi(other_shared_count.m_pi) + {} + + template + shared_count(const Ptr &p, const VoidAllocator &a, Deleter d) + : m_px(p), m_pi(0) + { + BOOST_TRY{ + if(p){ + counted_impl_allocator alloc(a); + m_pi = alloc.allocate(1); + //Anti-exception deallocator + scoped_ptr > + deallocator(m_pi, alloc); + //It's more correct to use VoidAllocator::construct but + //this needs copy constructor and we don't like it + new(detail::get_pointer(m_pi))counted_impl(p, a, d); + deallocator.release(); + } + } + BOOST_CATCH (...){ + d(p); // delete p + BOOST_RETHROW + } + BOOST_CATCH_END + } + + ~shared_count() // nothrow + { + if( m_pi != 0 ) + m_pi->release(); + } + + shared_count(shared_count const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if( m_pi != 0 ) m_pi->add_ref_copy(); } + + //this is a test + template + explicit shared_count(shared_count const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if( m_pi != 0 ) m_pi->add_ref_copy(); } + + //this is a test + template + explicit shared_count(const pointer & ptr, shared_count const & r) + : m_px(ptr), m_pi(r.m_pi) // nothrow + { if( m_pi != 0 ) m_pi->add_ref_copy(); } + +/* + explicit shared_count(weak_count const & r) + // throws bad_weak_ptr when r.use_count() == 0 + : m_pi( r.m_pi ) + { + if( m_pi == 0 || !m_pi->add_ref_lock() ){ + boost::throw_exception( boost::interprocess::bad_weak_ptr() ); + } + } +*/ + template + explicit shared_count(weak_count const & r) + // throws bad_weak_ptr when r.use_count() == 0 + : m_px(r.m_px), m_pi( r.m_pi ) + { + if( m_pi == 0 || !m_pi->add_ref_lock() ){ + throw( boost::interprocess::bad_weak_ptr() ); + } + } + + const pointer &get_pointer() const + { return m_px; } + + pointer &get_pointer() + { return m_px; } + + shared_count & operator= (shared_count const & r) // nothrow + { + m_px = r.m_px; + counted_impl_ptr tmp = r.m_pi; + if( tmp != m_pi ){ + if(tmp != 0) tmp->add_ref_copy(); + if(m_pi != 0) m_pi->release(); + m_pi = tmp; + } + return *this; + } + + template + shared_count & operator= (shared_count const & r) // nothrow + { + m_px = r.m_px; + counted_impl_ptr tmp = r.m_pi; + if( tmp != m_pi ){ + if(tmp != 0) tmp->add_ref_copy(); + if(m_pi != 0) m_pi->release(); + m_pi = tmp; + } + return *this; + } + + void swap(shared_count & r) // nothrow + { detail::do_swap(m_px, r.m_px); detail::do_swap(m_pi, r.m_pi); } + + long use_count() const // nothrow + { return m_pi != 0? m_pi->use_count(): 0; } + + bool unique() const // nothrow + { return use_count() == 1; } + + const_deleter_pointer get_deleter() const + { return m_pi ? m_pi->get_deleter() : 0; } + +// const_allocator_pointer get_allocator() const +// { return m_pi ? m_pi->get_allocator() : 0; } + + template + bool internal_equal (shared_count const & other) const + { return this->m_pi == other.m_pi; } + + template + bool internal_less (shared_count const & other) const + { return std::less()(this->m_pi, other.m_pi); } +}; + +template inline +bool operator==(shared_count const & a, shared_count const & b) +{ return a.internal_equal(b); } + +template inline +bool operator<(shared_count const & a, shared_count const & b) +{ return a.internal_less(b); } + + +template +class weak_count +{ + public: + typedef typename detail::pointer_to_other + ::type pointer; + + private: + typedef sp_counted_impl_pd counted_impl; + typedef typename detail::pointer_to_other + ::type counted_impl_ptr; + typedef typename detail::pointer_to_other + ::type counted_base_ptr; + + pointer m_px; + counted_impl_ptr m_pi; + + template + friend class weak_count; + + template + friend class shared_count; + + public: + + weak_count(): m_px(0), m_pi(0) // nothrow + {} + + template + explicit weak_count(shared_count const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if(m_pi != 0) m_pi->weak_add_ref(); } + + weak_count(weak_count const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if(m_pi != 0) m_pi->weak_add_ref(); } + + template + weak_count(weak_count const & r) + : m_px(r.m_px), m_pi(r.m_pi) // nothrow + { if(m_pi != 0) m_pi->weak_add_ref(); } + + ~weak_count() // nothrow + { if(m_pi != 0) m_pi->weak_release(); } + + template + weak_count & operator= (shared_count const & r) // nothrow + { + m_px = r.m_px; + counted_impl_ptr tmp = r.m_pi; + if(tmp != 0) tmp->weak_add_ref(); + if(m_pi != 0) m_pi->weak_release(); + m_pi = tmp; + return *this; + } + + weak_count & operator= (weak_count const & r) // nothrow + { + counted_impl_ptr tmp = r.m_pi; + if(tmp != 0) tmp->weak_add_ref(); + if(m_pi != 0) m_pi->weak_release(); + m_pi = tmp; + return *this; + } + + void set_pointer(const pointer &ptr) + { m_px = ptr; } + + template + weak_count & operator= (weak_count const& r) // nothrow + { + counted_impl_ptr tmp = r.m_pi; + if(tmp != 0) tmp->weak_add_ref(); + if(m_pi != 0) m_pi->weak_release(); + m_pi = tmp; + return *this; + } + + void swap(weak_count & r) // nothrow + { detail::do_swap(m_px, r.m_px); detail::do_swap(m_pi, r.m_pi); } + + long use_count() const // nothrow + { return m_pi != 0? m_pi->use_count() : 0; } + + template + bool internal_equal (weak_count const & other) const + { return this->m_pi == other.m_pi; } + + template + bool internal_less (weak_count const & other) const + { return std::less()(this->m_pi, other.m_pi); } +}; + +template inline +bool operator==(weak_count const & a, weak_count const & b) +{ return a.internal_equal(b); } + +template inline +bool operator<(weak_count const & a, weak_count const & b) +{ return a.internal_less(b); } + +} // namespace detail +} // namespace interprocess +} // namespace boost + + +#include + + +#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED diff --git a/win32/include/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp b/win32/include/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp new file mode 100755 index 000000000..9a88298e2 --- /dev/null +++ b/win32/include/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp @@ -0,0 +1,18 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2008. +// +// 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED +#define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED + +# include + +#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED + diff --git a/win32/include/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp b/win32/include/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp new file mode 100755 index 000000000..133346870 --- /dev/null +++ b/win32/include/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp @@ -0,0 +1,92 @@ +#ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_ATOMIC_HPP_INCLUDED +#define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_ATOMIC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// Copyright 2007-2008 Ion Gaztanaga +// +// 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) +// +// +// Lock-free algorithm by Alexander Terekhov +// +// Thanks to Ben Hitchings for the #weak + (#shared != 0) +// formulation +// + +#include +#include + +#include +#include + +namespace boost { + +namespace interprocess { + +namespace detail { + +class sp_counted_base +{ +private: + + sp_counted_base( sp_counted_base const & ); + sp_counted_base & operator= ( sp_counted_base const & ); + + boost::uint32_t use_count_; // #shared + boost::uint32_t weak_count_; // #weak + (#shared != 0) + +public: + + sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) + {} + + ~sp_counted_base() // nothrow + {} + + void add_ref_copy() + { + detail::atomic_inc32( &use_count_ ); + } + + bool add_ref_lock() // true on success + { + for( ;; ) + { + boost::uint32_t tmp = static_cast< boost::uint32_t const volatile& >( use_count_ ); + if( tmp == 0 ) return false; + if( detail::atomic_cas32( &use_count_, tmp + 1, tmp ) == tmp ) + return true; + } + } + + bool ref_release() // nothrow + { return 1 == detail::atomic_dec32( &use_count_ ); } + + void weak_add_ref() // nothrow + { detail::atomic_inc32( &weak_count_ ); } + + bool weak_release() // nothrow + { return 1 == detail::atomic_dec32( &weak_count_ ); } + + long use_count() const // nothrow + { return (long)static_cast( use_count_ ); } +}; + +} // namespace detail + +} // namespace interprocess + +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_BASE_ATOMIC_HPP_INCLUDED diff --git a/win32/include/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp b/win32/include/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp new file mode 100755 index 000000000..6410df5e2 --- /dev/null +++ b/win32/include/boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp @@ -0,0 +1,117 @@ +#ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED +#define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// This file is the adaptation for shared memory memory mapped +// files of boost/detail/sp_counted_impl.hpp +// +// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. +// Copyright 2004-2005 Peter Dimov +// Copyright 2006 Ion Gaztanaga +// +// 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) +// + +#include +#include + +#include +#include +#include + +namespace boost { + +namespace interprocess { + +namespace detail { + +template +class sp_counted_impl_pd + : public sp_counted_base + , A::template rebind< sp_counted_impl_pd >::other + , D // copy constructor must not throw +{ + private: + typedef sp_counted_impl_pd this_type; + typedef typename A::template rebind + ::other this_allocator; + typedef typename A::template rebind + ::other const_this_allocator; + typedef typename this_allocator::pointer this_pointer; + + sp_counted_impl_pd( sp_counted_impl_pd const & ); + sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & ); + + typedef typename detail::pointer_to_other + ::type const_deleter_pointer; + + typedef typename detail::pointer_to_other + ::type const_allocator_pointer; + + typedef typename D::pointer pointer; + pointer m_ptr; + + public: + // pre: d(p) must not throw + template + sp_counted_impl_pd(const Ptr & p, const A &a, const D &d ) + : this_allocator(a), D(d), m_ptr(p) + {} + + const_deleter_pointer get_deleter() const + { return const_deleter_pointer(&static_cast(*this)); } + + const_allocator_pointer get_allocator() const + { return const_allocator_pointer(&static_cast(*this)); } + + void dispose() // nothrow + { static_cast(*this)(m_ptr); } + + void destroy() // nothrow + { + //Self destruction, so get a copy of the allocator + //(in the future we could move it) + this_allocator a_copy(*this); + BOOST_ASSERT(a_copy == *this); + this_pointer this_ptr (this); + //Do it now! + scoped_ptr >(this_ptr, a_copy); + typedef typename this_allocator::value_type value_type; + detail::get_pointer(this_ptr)->~value_type(); + } + + void release() // nothrow + { + if(this->ref_release()){ + this->dispose(); + this->weak_release(); + } + } + + void weak_release() // nothrow + { + if(sp_counted_base::weak_release()){ + this->destroy(); + } + } +}; + + +} // namespace detail + +} // namespace interprocess + +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED diff --git a/win32/include/boost/interprocess/smart_ptr/enable_shared_from_this.hpp b/win32/include/boost/interprocess/smart_ptr/enable_shared_from_this.hpp new file mode 100755 index 000000000..272ac61b1 --- /dev/null +++ b/win32/include/boost/interprocess/smart_ptr/enable_shared_from_this.hpp @@ -0,0 +1,79 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/enable_shared_from_this.hpp +// +// (C) Copyright Peter Dimov 2002 +// (C) Copyright Ion Gaztanaga 2006. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED +#define BOOST_INTERPROCESS_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED + +#include +#include + +#include +#include +#include + +//!\file +//!Describes an utility to form a shared pointer from this + +namespace boost{ +namespace interprocess{ + +//!This class is used as a base class that allows a shared_ptr to the current +//!object to be obtained from within a member function. +//!enable_shared_from_this defines two member functions called shared_from_this +//!that return a shared_ptr and shared_ptr, depending on constness, to this. +template +class enable_shared_from_this +{ + /// @cond + protected: + enable_shared_from_this() + {} + + enable_shared_from_this(enable_shared_from_this const &) + {} + + enable_shared_from_this & operator=(enable_shared_from_this const &) + { return *this; } + + ~enable_shared_from_this() + {} + /// @endcond + + public: + shared_ptr shared_from_this() + { + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(detail::get_pointer(p.get()) == this); + return p; + } + + shared_ptr shared_from_this() const + { + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(detail::get_pointer(p.get()) == this); + return p; + } + + /// @cond + typedef T element_type; + mutable weak_ptr _internal_weak_this; + /// @endcond +}; + +} // namespace interprocess +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED + diff --git a/win32/include/boost/interprocess/smart_ptr/intrusive_ptr.hpp b/win32/include/boost/interprocess/smart_ptr/intrusive_ptr.hpp new file mode 100755 index 000000000..b60c58a27 --- /dev/null +++ b/win32/include/boost/interprocess/smart_ptr/intrusive_ptr.hpp @@ -0,0 +1,293 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/intrusive_ptr.hpp +// +// (C) Copyright Peter Dimov 2001, 2002 +// (C) Copyright Ion Gaztanaga 2006. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED +#define BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED + +//!\file +//!Describes an intrusive ownership pointer. + +#include +#include + +#include +#include + +#include // for std::less +#include // for std::basic_ostream + + +namespace boost { +namespace interprocess { + +//!The intrusive_ptr class template stores a pointer to an object +//!with an embedded reference count. intrusive_ptr is parameterized on +//!T (the type of the object pointed to) and VoidPointer(a void pointer type +//!that defines the type of pointer that intrusive_ptr will store). +//!intrusive_ptr defines a class with a T* member whereas +//!intrusive_ptr > defines a class with a offset_ptr member. +//!Relies on unqualified calls to: +//! +//! void intrusive_ptr_add_ref(T * p); +//! void intrusive_ptr_release(T * p); +//! +//! with (p != 0) +//! +//!The object is responsible for destroying itself. +template +class intrusive_ptr +{ + public: + //!Provides the type of the internal stored pointer. + typedef typename detail::pointer_to_other::type pointer; + //!Provides the type of the stored pointer. + typedef T element_type; + + /// @cond + private: + typedef VoidPointer VP; + typedef intrusive_ptr this_type; + typedef pointer this_type::*unspecified_bool_type; + /// @endcond + + public: + //!Constructor. Initializes internal pointer to 0. + //!Does not throw + intrusive_ptr(): m_ptr(0) + {} + + //!Constructor. Copies pointer and if "p" is not zero and + //!"add_ref" is true calls intrusive_ptr_add_ref(get_pointer(p)). + //!Does not throw + intrusive_ptr(const pointer &p, bool add_ref = true): m_ptr(p) + { + if(m_ptr != 0 && add_ref) intrusive_ptr_add_ref(detail::get_pointer(m_ptr)); + } + + //!Copy constructor. Copies the internal pointer and if "p" is not + //!zero calls intrusive_ptr_add_ref(get_pointer(p)). Does not throw + intrusive_ptr(intrusive_ptr const & rhs) + : m_ptr(rhs.m_ptr) + { + if(m_ptr != 0) intrusive_ptr_add_ref(detail::get_pointer(m_ptr)); + } + + //!Constructor from related. Copies the internal pointer and if "p" is not + //!zero calls intrusive_ptr_add_ref(get_pointer(p)). Does not throw + template intrusive_ptr + (intrusive_ptr const & rhs) + : m_ptr(rhs.get()) + { + if(m_ptr != 0) intrusive_ptr_add_ref(detail::get_pointer(m_ptr)); + } + + //!Destructor. If internal pointer is not 0, calls + //!intrusive_ptr_release(get_pointer(m_ptr)). Does not throw + ~intrusive_ptr() + { + if(m_ptr != 0) intrusive_ptr_release(detail::get_pointer(m_ptr)); + } + + //!Assignment operator. Equivalent to intrusive_ptr(r).swap(*this). + //!Does not throw + intrusive_ptr & operator=(intrusive_ptr const & rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + //!Assignment from related. Equivalent to intrusive_ptr(r).swap(*this). + //!Does not throw + template intrusive_ptr & operator= + (intrusive_ptr const & rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + //!Assignment from pointer. Equivalent to intrusive_ptr(r).swap(*this). + //!Does not throw + intrusive_ptr & operator=(pointer rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + //!Returns a reference to the internal pointer. + //!Does not throw + pointer &get() + { return m_ptr; } + + //!Returns a reference to the internal pointer. + //!Does not throw + const pointer &get() const + { return m_ptr; } + + //!Returns *get(). + //!Does not throw + T & operator*() const + { return *m_ptr; } + + //!Returns *get(). + //!Does not throw + const pointer &operator->() const + { return m_ptr; } + + //!Returns get(). + //!Does not throw + pointer &operator->() + { return m_ptr; } + + //!Conversion to boolean. + //!Does not throw + operator unspecified_bool_type () const + { return m_ptr == 0? 0: &this_type::m_ptr; } + + //!Not operator. + //!Does not throw + bool operator! () const + { return m_ptr == 0; } + + //!Exchanges the contents of the two smart pointers. + //!Does not throw + void swap(intrusive_ptr & rhs) + { detail::do_swap(m_ptr, rhs.m_ptr); } + + /// @cond + private: + pointer m_ptr; + /// @endcond +}; + +//!Returns a.get() == b.get(). +//!Does not throw +template inline +bool operator==(intrusive_ptr const & a, + intrusive_ptr const & b) +{ return a.get() == b.get(); } + +//!Returns a.get() != b.get(). +//!Does not throw +template inline +bool operator!=(intrusive_ptr const & a, + intrusive_ptr const & b) +{ return a.get() != b.get(); } + +//!Returns a.get() == b. +//!Does not throw +template inline +bool operator==(intrusive_ptr const & a, + const typename intrusive_ptr::pointer &b) +{ return a.get() == b; } + +//!Returns a.get() != b. +//!Does not throw +template inline +bool operator!=(intrusive_ptr const & a, + const typename intrusive_ptr::pointer &b) +{ return a.get() != b; } + +//!Returns a == b.get(). +//!Does not throw +template inline +bool operator==(const typename intrusive_ptr::pointer &a, + intrusive_ptr const & b) +{ return a == b.get(); } + +//!Returns a != b.get(). +//!Does not throw +template inline +bool operator!=(const typename intrusive_ptr::pointer &a, + intrusive_ptr const & b) +{ return a != b.get(); } + +//!Returns a.get() < b.get(). +//!Does not throw +template inline +bool operator<(intrusive_ptr const & a, + intrusive_ptr const & b) +{ + return std::less::pointer>() + (a.get(), b.get()); +} + +//!Exchanges the contents of the two intrusive_ptrs. +//!Does not throw +template inline +void swap(intrusive_ptr & lhs, + intrusive_ptr & rhs) +{ lhs.swap(rhs); } + +// operator<< +template +inline std::basic_ostream & operator<< + (std::basic_ostream & os, intrusive_ptr const & p) +{ os << p.get(); return os; } + +//!Returns p.get(). +//!Does not throw +template +inline typename boost::interprocess::intrusive_ptr::pointer + get_pointer(intrusive_ptr p) +{ return p.get(); } + +/*Emulates static cast operator. Does not throw*/ +/* +template +inline boost::interprocess::intrusive_ptr static_pointer_cast + (boost::interprocess::intrusive_ptr const & p) +{ return do_static_cast(p.get()); } +*/ +/*Emulates const cast operator. Does not throw*/ +/* +template +inline boost::interprocess::intrusive_ptr const_pointer_cast + (boost::interprocess::intrusive_ptr const & p) +{ return do_const_cast(p.get()); } +*/ + +/*Emulates dynamic cast operator. Does not throw*/ +/* +template +inline boost::interprocess::intrusive_ptr dynamic_pointer_cast + (boost::interprocess::intrusive_ptr const & p) +{ return do_dynamic_cast(p.get()); } +*/ + +/*Emulates reinterpret cast operator. Does not throw*/ +/* +template +inline boost::interprocess::intrusive_ptrreinterpret_pointer_cast + (boost::interprocess::intrusive_ptr const & p) +{ return do_reinterpret_cast(p.get()); } +*/ + +} // namespace interprocess + +/// @cond + +#if defined(_MSC_VER) && (_MSC_VER < 1400) +//!Returns p.get(). +//!Does not throw +template +inline T *get_pointer(boost::interprocess::intrusive_ptr p) +{ return p.get(); } +#endif + +/// @endcond + +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_INTRUSIVE_PTR_HPP_INCLUDED diff --git a/win32/include/boost/interprocess/smart_ptr/scoped_ptr.hpp b/win32/include/boost/interprocess/smart_ptr/scoped_ptr.hpp new file mode 100755 index 000000000..26a16d819 --- /dev/null +++ b/win32/include/boost/interprocess/smart_ptr/scoped_ptr.hpp @@ -0,0 +1,167 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/scoped_ptr.hpp +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// (C) Copyright Peter Dimov 2001, 2002 +// (C) Copyright Ion Gaztanaga 2006. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_SCOPED_PTR_HPP_INCLUDED +#define BOOST_INTERPROCESS_SCOPED_PTR_HPP_INCLUDED + +#include +#include +#include +#include + +//!\file +//!Describes the smart pointer scoped_ptr + +namespace boost { +namespace interprocess { + +//!scoped_ptr stores a pointer to a dynamically allocated object. +//!The object pointed to is guaranteed to be deleted, either on destruction +//!of the scoped_ptr, or via an explicit reset. The user can avoid this +//!deletion using release(). +//!scoped_ptr is parameterized on T (the type of the object pointed to) and +//!Deleter (the functor to be executed to delete the internal pointer). +//!The internal pointer will be of the same pointer type as typename +//!Deleter::pointer type (that is, if typename Deleter::pointer is +//!offset_ptr, the internal pointer will be offset_ptr). +template +class scoped_ptr + : private Deleter +{ + /// @cond + scoped_ptr(scoped_ptr const &); + scoped_ptr & operator=(scoped_ptr const &); + + typedef scoped_ptr this_type; + typedef typename detail::add_reference::type reference; + /// @endcond + + public: + + typedef T element_type; + typedef Deleter deleter_type; + typedef typename detail::pointer_type::type pointer; + + //!Provides the type of the internal stored pointer +// typedef typename detail::pointer_to_other +// ::type pointer; + + //!Constructs a scoped_ptr, storing a copy of p(which can be 0) and d. + //!Does not throw. + explicit scoped_ptr(const pointer &p = 0, const Deleter &d = Deleter()) + : Deleter(d), m_ptr(p) // throws if pointer/Deleter copy ctor throws + {} + + //!If the stored pointer is not 0, destroys the object pointed to by the stored pointer. + //!calling the operator() of the stored deleter. Never throws + ~scoped_ptr() + { + if(m_ptr){ + Deleter &del = static_cast(*this); + del(m_ptr); + } + } + + //!Deletes the object pointed to by the stored pointer and then + //!stores a copy of p. Never throws + void reset(const pointer &p = 0) // never throws + { BOOST_ASSERT(p == 0 || p != m_ptr); this_type(p).swap(*this); } + + //!Deletes the object pointed to by the stored pointer and then + //!stores a copy of p and a copy of d. + void reset(const pointer &p, const Deleter &d) // never throws + { BOOST_ASSERT(p == 0 || p != m_ptr); this_type(p).swap(*this); } + + //!Assigns internal pointer as 0 and returns previous pointer. This will + //!avoid deletion on destructor + pointer release() + { pointer tmp(m_ptr); m_ptr = 0; return tmp; } + + //!Returns a reference to the object pointed to by the stored pointer. + //!Never throws. + reference operator*() const + { BOOST_ASSERT(m_ptr != 0); return *m_ptr; } + + //!Returns the internal stored pointer. + //!Never throws. + pointer &operator->() + { BOOST_ASSERT(m_ptr != 0); return m_ptr; } + + //!Returns the internal stored pointer. + //!Never throws. + const pointer &operator->() const + { BOOST_ASSERT(m_ptr != 0); return m_ptr; } + + //!Returns the stored pointer. + //!Never throws. + pointer & get() + { return m_ptr; } + + //!Returns the stored pointer. + //!Never throws. + const pointer & get() const + { return m_ptr; } + + typedef pointer this_type::*unspecified_bool_type; + + //!Conversion to bool + //!Never throws + operator unspecified_bool_type() const + { return m_ptr == 0? 0: &this_type::m_ptr; } + + //!Returns true if the stored pointer is 0. + //!Never throws. + bool operator! () const // never throws + { return m_ptr == 0; } + + //!Exchanges the internal pointer and deleter with other scoped_ptr + //!Never throws. + void swap(scoped_ptr & b) // never throws + { detail::do_swap(*this, b); detail::do_swap(m_ptr, b.m_ptr); } + + /// @cond + private: + pointer m_ptr; + /// @endcond +}; + +//!Exchanges the internal pointer and deleter with other scoped_ptr +//!Never throws. +template inline +void swap(scoped_ptr & a, scoped_ptr & b) +{ a.swap(b); } + +//!Returns a copy of the stored pointer +//!Never throws +template inline +typename scoped_ptr::pointer get_pointer(scoped_ptr const & p) +{ return p.get(); } + +} // namespace interprocess + +/// @cond + +#if defined(_MSC_VER) && (_MSC_VER < 1400) +template inline +T *get_pointer(boost::interprocess::scoped_ptr const & p) +{ return p.get(); } +#endif + +/// @endcond + +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_SCOPED_PTR_HPP_INCLUDED diff --git a/win32/include/boost/interprocess/smart_ptr/shared_ptr.hpp b/win32/include/boost/interprocess/smart_ptr/shared_ptr.hpp new file mode 100755 index 000000000..c90914b5e --- /dev/null +++ b/win32/include/boost/interprocess/smart_ptr/shared_ptr.hpp @@ -0,0 +1,411 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/shared_ptr.hpp +// +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// (C) Copyright Peter Dimov 2001, 2002, 2003 +// (C) Copyright Ion Gaztanaga 2006-2008. +// 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED +#define BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // for std::swap +#include // for std::less +#include // for std::bad_cast +#include // for std::basic_ostream + +//!\file +//!Describes the smart pointer shared_ptr + +namespace boost{ +namespace interprocess{ + +template class weak_ptr; +template class enable_shared_from_this; + +namespace detail{ + +template +inline void sp_enable_shared_from_this + (shared_count const & pn + ,enable_shared_from_this *pe + ,T *ptr) + +{ + (void)ptr; + if(pe != 0){ + pe->_internal_weak_this._internal_assign(pn); + } +} + +template +inline void sp_enable_shared_from_this(shared_count const &, ...) +{} + +} // namespace detail + +//!shared_ptr stores a pointer to a dynamically allocated object. +//!The object pointed to is guaranteed to be deleted when the last shared_ptr pointing to +//!it is destroyed or reset. +//! +//!shared_ptr is parameterized on +//!T (the type of the object pointed to), VoidAllocator (the void allocator to be used +//!to allocate the auxiliary data) and Deleter (the deleter whose +//!operator() will be used to delete the object. +//! +//!The internal pointer will be of the same pointer type as typename +//!VoidAllocator::pointer type (that is, if typename VoidAllocator::pointer is +//!offset_ptr, the internal pointer will be offset_ptr). +//! +//!Because the implementation uses reference counting, cycles of shared_ptr +//!instances will not be reclaimed. For example, if main() holds a +//!shared_ptr to A, which directly or indirectly holds a shared_ptr back +//!to A, A's use count will be 2. Destruction of the original shared_ptr +//!will leave A dangling with a use count of 1. +//!Use weak_ptr to "break cycles." +template +class shared_ptr +{ + /// @cond + private: + typedef shared_ptr this_type; + /// @endcond + + public: + + typedef T element_type; + typedef T value_type; + typedef typename detail::pointer_to_other + ::type pointer; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + typedef typename detail::pointer_to_other + ::type const_deleter_pointer; + typedef typename detail::pointer_to_other + ::type const_allocator_pointer; + + public: + //!Constructs an empty shared_ptr. + //!Use_count() == 0 && get()== 0. + shared_ptr() + : m_pn() // never throws + {} + + //!Constructs a shared_ptr that owns the pointer p. Auxiliary data will be allocated + //!with a copy of a and the object will be deleted with a copy of d. + //!Requirements: Deleter and A's copy constructor must not throw. + explicit shared_ptr(const pointer&p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter()) + : m_pn(p, a, d) + { + //Check that the pointer passed is of the same type that + //the pointer the allocator defines or it's a raw pointer + typedef typename detail::pointer_to_other::type ParameterPointer; + BOOST_STATIC_ASSERT((detail::is_same::value) || + (detail::is_pointer::value)); + detail::sp_enable_shared_from_this( m_pn, detail::get_pointer(p), detail::get_pointer(p) ); + } + + + //!Constructs a shared_ptr that shares ownership with r and stores p. + //!Postconditions: get() == p && use_count() == r.use_count(). + //!Throws: nothing. + shared_ptr(const shared_ptr &other, const pointer &p) + : m_pn(other.m_pn, p) + {} + + //!If r is empty, constructs an empty shared_ptr. Otherwise, constructs + //!a shared_ptr that shares ownership with r. Never throws. + template + shared_ptr(shared_ptr const & r) + : m_pn(r.m_pn) // never throws + {} + + //!Constructs a shared_ptr that shares ownership with r and stores + //!a copy of the pointer stored in r. + template + explicit shared_ptr(weak_ptr const & r) + : m_pn(r.m_pn) // may throw + {} + + //!Move-Constructs a shared_ptr that takes ownership of other resource and + //!other is put in default-constructed state. + //!Throws: nothing. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + explicit shared_ptr(detail::moved_object other) + : m_pn() + { this->swap(other.get()); } + #else + explicit shared_ptr(shared_ptr &&other) + : m_pn() + { this->swap(other); } + #endif + + /// @cond + template + shared_ptr(shared_ptr const & r, detail::static_cast_tag) + : m_pn( pointer(static_cast(detail::get_pointer(r.m_pn.get_pointer()))) + , r.m_pn) + {} + + template + shared_ptr(shared_ptr const & r, detail::const_cast_tag) + : m_pn( pointer(const_cast(detail::get_pointer(r.m_pn.get_pointer()))) + , r.m_pn) + {} + + template + shared_ptr(shared_ptr const & r, detail::dynamic_cast_tag) + : m_pn( pointer(dynamic_cast(detail::get_pointer(r.m_pn.get_pointer()))) + , r.m_pn) + { + if(!m_pn.get_pointer()){ // need to allocate new counter -- the cast failed + m_pn = detail::shared_count(); + } + } + /// @endcond + + //!Equivalent to shared_ptr(r).swap(*this). + //!Never throws + template + shared_ptr & operator=(shared_ptr const & r) + { + m_pn = r.m_pn; // shared_count::op= doesn't throw + return *this; + } + + //!Move-assignment. Equivalent to shared_ptr(other).swap(*this). + //!Never throws + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + shared_ptr & operator=(detail::moved_object other) // never throws + { + this_type(other).swap(*this); + return *this; + } + #else + shared_ptr & operator=(shared_ptr &&other) // never throws + { + this_type(other).swap(*this); + return *this; + } + #endif + + //!This is equivalent to: + //!this_type().swap(*this); + void reset() + { + this_type().swap(*this); + } + + //!This is equivalent to: + //!this_type(p, a, d).swap(*this); + template + void reset(const Pointer &p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter()) + { + //Check that the pointer passed is of the same type that + //the pointer the allocator defines or it's a raw pointer + typedef typename detail::pointer_to_other::type ParameterPointer; + BOOST_STATIC_ASSERT((detail::is_same::value) || + (detail::is_pointer::value)); + this_type(p, a, d).swap(*this); + } + + template + void reset(shared_ptr const & r, const pointer &p) + { + this_type(r, p).swap(*this); + } + + //!Returns a reference to the + //!pointed type + reference operator* () const // never throws + { BOOST_ASSERT(m_pn.get_pointer() != 0); return *m_pn.get_pointer(); } + + //!Returns the pointer pointing + //!to the owned object + pointer operator-> () const // never throws + { BOOST_ASSERT(m_pn.get_pointer() != 0); return m_pn.get_pointer(); } + + //!Returns the pointer pointing + //!to the owned object + pointer get() const // never throws + { return m_pn.get_pointer(); } + + /// @cond + // implicit conversion to "bool" + void unspecified_bool_type_func() const {} + typedef void (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { return !m_pn.get_pointer() ? 0 : &this_type::unspecified_bool_type_func; } + /// @endcond + + //!Not operator. + //!Returns true if this->get() != 0, false otherwise + bool operator! () const // never throws + { return !m_pn.get_pointer(); } + + //!Returns use_count() == 1. + //!unique() might be faster than use_count() + bool unique() const // never throws + { return m_pn.unique(); } + + //!Returns the number of shared_ptr objects, *this included, + //!that share ownership with *this, or an unspecified nonnegative + //!value when *this is empty. + //!use_count() is not necessarily efficient. Use only for + //!debugging and testing purposes, not for production code. + long use_count() const // never throws + { return m_pn.use_count(); } + + //!Exchanges the contents of the two + //!smart pointers. + void swap(shared_ptr & other) // never throws + { m_pn.swap(other.m_pn); } + + /// @cond + + template + bool _internal_less(shared_ptr const & rhs) const + { return m_pn < rhs.m_pn; } + + const_deleter_pointer get_deleter() const + { return m_pn.get_deleter(); } + +// const_allocator_pointer get_allocator() const +// { return m_pn.get_allocator(); } + + private: + + template friend class shared_ptr; + template friend class weak_ptr; + + detail::shared_count m_pn; // reference counter + /// @endcond +}; // shared_ptr + +template inline +bool operator==(shared_ptr const & a, shared_ptr const & b) +{ return a.get() == b.get(); } + +template inline +bool operator!=(shared_ptr const & a, shared_ptr const & b) +{ return a.get() != b.get(); } + +template inline +bool operator<(shared_ptr const & a, shared_ptr const & b) +{ return a._internal_less(b); } + +template inline +void swap(shared_ptr & a, shared_ptr & b) +{ a.swap(b); } + +template inline +shared_ptr static_pointer_cast(shared_ptr const & r) +{ return shared_ptr(r, detail::static_cast_tag()); } + +template inline +shared_ptr const_pointer_cast(shared_ptr const & r) +{ return shared_ptr(r, detail::const_cast_tag()); } + +template inline +shared_ptr dynamic_pointer_cast(shared_ptr const & r) +{ return shared_ptr(r, detail::dynamic_cast_tag()); } + +// get_pointer() enables boost::mem_fn to recognize shared_ptr +template inline +T * get_pointer(shared_ptr const & p) +{ return p.get(); } + +// operator<< +template inline +std::basic_ostream & operator<< + (std::basic_ostream & os, shared_ptr const & p) +{ os << p.get(); return os; } + +//!Returns the type of a shared pointer +//!of type T with the allocator boost::interprocess::allocator allocator +//!and boost::interprocess::deleter deleter +//!that can be constructed in the given managed segment type. +template +struct managed_shared_ptr +{ + typedef typename ManagedMemory::template allocator::type void_allocator; + typedef typename ManagedMemory::template deleter::type deleter; + typedef shared_ptr< T, void_allocator, deleter> type; +}; + +//!Returns an instance of a shared pointer constructed +//!with the default allocator and deleter from a pointer +//!of type T that has been allocated in the passed managed segment +template +inline typename managed_shared_ptr::type + make_managed_shared_ptr(T *constructed_object, ManagedMemory &managed_memory) +{ + return typename managed_shared_ptr::type + ( constructed_object + , managed_memory.template get_allocator() + , managed_memory.template get_deleter() + ); +} + + +/* +// get_deleter (experimental) +template +typename detail::pointer_to_other, Deleter>::type + get_deleter(shared_ptr const & p) +{ return static_cast(p._internal_get_deleter(typeid(Deleter))); } +*/ + +/// @cond + +//!This class has move constructor +template +struct is_movable > +{ + enum { value = true }; +}; + +/// @endcond + +} // namespace interprocess + +/// @cond + +#if defined(_MSC_VER) && (_MSC_VER < 1400) +// get_pointer() enables boost::mem_fn to recognize shared_ptr +template inline +T * get_pointer(boost::interprocess::shared_ptr const & p) +{ return p.get(); } +#endif + +/// @endcond + +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_SHARED_PTR_HPP_INCLUDED diff --git a/win32/include/boost/interprocess/smart_ptr/unique_ptr.hpp b/win32/include/boost/interprocess/smart_ptr/unique_ptr.hpp new file mode 100755 index 000000000..9fb282a54 --- /dev/null +++ b/win32/include/boost/interprocess/smart_ptr/unique_ptr.hpp @@ -0,0 +1,621 @@ +////////////////////////////////////////////////////////////////////////////// +// I, Howard Hinnant, hereby place this code in the public domain. +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of +// Howard Hinnant's unique_ptr emulation code. +// +// (C) Copyright Ion Gaztanaga 2006. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED +#define BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes the smart pointer unique_ptr + +namespace boost{ +namespace interprocess{ + +/// @cond +template class unique_ptr; + +namespace detail { + +template struct unique_ptr_error; + +template +struct unique_ptr_error > +{ + typedef unique_ptr type; +}; + +} //namespace detail { +/// @endcond + +//!Template unique_ptr stores a pointer to an object and deletes that object +//!using the associated deleter when it is itself destroyed (such as when +//!leaving block scope. +//! +//!The unique_ptr provides a semantics of strict ownership. A unique_ptr owns the +//!object it holds a pointer to. +//! +//!A unique_ptr is not CopyConstructible, nor CopyAssignable, however it is +//!MoveConstructible and Move-Assignable. +//! +//!The uses of unique_ptr include providing exception safety for dynamically +//!allocated memory, passing ownership of dynamically allocated memory to a +//!function, and returning dynamically allocated memory from a function +//! +//!A client-supplied template argument D must be a +//!function pointer or functor for which, given a value d of type D and a pointer +//!ptr to a type T*, the expression d(ptr) is +//!valid and has the effect of deallocating the pointer as appropriate for that +//!deleter. D may also be an lvalue-reference to a deleter. +//! +//!If the deleter D maintains state, it is intended that this state stay with +//!the associated pointer as ownership is transferred +//!from unique_ptr to unique_ptr. The deleter state need never be copied, +//!only moved or swapped as pointer ownership +//!is moved around. That is, the deleter need only be MoveConstructible, +//!MoveAssignable, and Swappable, and need not be CopyConstructible +//!(unless copied into the unique_ptr) nor CopyAssignable. +template +class unique_ptr +{ + /// @cond + struct nat {int for_bool_;}; + typedef typename detail::add_reference::type deleter_reference; + typedef typename detail::add_reference::type deleter_const_reference; + /// @endcond + + public: + typedef T element_type; + typedef D deleter_type; + typedef typename detail::pointer_type::type pointer; + + //!Requires: D must be default constructible, and that construction must not + //!throw an exception. D must not be a reference type. + //! + //!Effects: Constructs a unique_ptr which owns nothing. + //! + //!Postconditions: get() == 0. get_deleter() returns a reference to a + //!default constructed deleter D. + //! + //!Throws: nothing. + unique_ptr() + : ptr_(pointer(0)) + {} + + //!Requires: The expression D()(p) must be well formed. The default constructor + //!of D must not throw an exception. + //! + //!D must not be a reference type. + //! + //!Effects: Constructs a unique_ptr which owns p. + //! + //!Postconditions: get() == p. get_deleter() returns a reference to a default constructed deleter D. + //! + //!Throws: nothing. + explicit unique_ptr(pointer p) + : ptr_(p) + {} + + //!Requires: The expression d(p) must be well formed. + //! + //!Postconditions: get() == p. get_deleter() returns a reference to the + //!internally stored deleter. If D is a + //!reference type then get_deleter() returns a reference to the lvalue d. + //! + //!Throws: nothing. + unique_ptr(pointer p + ,typename detail::if_ + ,D + ,typename detail::add_reference::type>::type d) + : ptr_(p, d) + {} + + //!Requires: If the deleter is not a reference type, construction of the + //!deleter D from an lvalue D must not throw an exception. + //! + //!Effects: Constructs a unique_ptr which owns the pointer which u owns + //!(if any). If the deleter is not a reference type, it is move constructed + //!from u's deleter, otherwise the reference is copy constructed from u's deleter. + //! + //!After the construction, u no longer owns a pointer. + //![ Note: The deleter constructor can be implemented with + //!std::detail::forward_impl. -end note ] + //! + //!Postconditions: get() == value u.get() had before the construction. + //!get_deleter() returns a reference to the internally stored deleter which + //!was constructed from u.get_deleter(). If D is a reference type then get_- + //!deleter() and u.get_deleter() both reference the same lvalue deleter. + //! + //!Throws: nothing. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + unique_ptr(detail::moved_object u) + : ptr_(u.get().release(), detail::move_impl(u.get().get_deleter())) + {} + #else + unique_ptr(unique_ptr &&u) + : ptr_(u.release(), detail::forward_impl(u.get_deleter())) + {} + #endif + + //!Requires: If D is not a reference type, construction of the deleter + //!D from an rvalue of type E must be well formed + //!and not throw an exception. If D is a reference type, then E must be + //!the same type as D (diagnostic required). unique_ptr::pointer + //!must be implicitly convertible to pointer. + //! + //!Effects: Constructs a unique_ptr which owns the pointer which u owns + //!(if any). If the deleter is not a reference + //!type, it is move constructed from u's deleter, otherwise the reference + //!is copy constructed from u's deleter. + //! + //!After the construction, u no longer owns a pointer. + //! + //!postconditions get() == value u.get() had before the construction, + //!modulo any required offset adjustments + //!resulting from the cast from U* to T*. get_deleter() returns a reference to the internally stored deleter which + //!was constructed from u.get_deleter(). + //! + //!Throws: nothing. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + template + unique_ptr(detail::moved_object > u, + typename detail::enable_if_c< + detail::is_convertible::pointer, pointer>::value && + detail::is_convertible::value && + ( + !detail::is_reference::value || + detail::is_same::value + ) + , + nat + >::type = nat()) + : ptr_(const_cast&>(u.get()).release(), detail::move_impl(u.get().get_deleter())) + {} + #else + template + unique_ptr(unique_ptr && u, + typename detail::enable_if_c< + detail::is_convertible::pointer, pointer>::value && + detail::is_convertible::value && + ( + !detail::is_reference::value || + detail::is_same::value + ) + , + nat + >::type = nat()) + : ptr_(const_cast&>(u).release(), detail::forward_impl(u.get_deleter())) + {} + #endif + + //!Effects: If get() == 0 there are no effects. Otherwise get_deleter()(get()). + //! + //!Throws: nothing. + ~unique_ptr() + { reset(); } + + // assignment + + //!Requires: Assignment of the deleter D from an rvalue D must not throw an exception. + //! + //!Effects: reset(u.release()) followed by a move assignment from u's deleter to + //!this deleter. + //! + //!Postconditions: This unique_ptr now owns the pointer which u owned, and u no + //!longer owns it. + //! + //!Returns: *this. + //! + //!Throws: nothing. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + unique_ptr& operator=(detail::moved_object u) + { + reset(u.get().release()); + ptr_.second() = detail::move_impl(u.get().get_deleter()); + return *this; + } + #else + unique_ptr& operator=(unique_ptr && u) + { + reset(u.release()); + ptr_.second() = detail::move_impl(u.get_deleter()); + return *this; + } + #endif + + //!Requires: Assignment of the deleter D from an rvalue D must not + //!throw an exception. U* must be implicitly convertible to T*. + //! + //!Effects: reset(u.release()) followed by a move assignment from + //!u's deleter to this deleter. If either D or E is + //!a reference type, then the referenced lvalue deleter participates + //!in the move assignment. + //! + //!Postconditions: This unique_ptr now owns the pointer which u owned, + //!and u no longer owns it. + //! + //!Returns: *this. + //! + //!Throws: nothing. + template + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + unique_ptr& operator=(detail::moved_object > mu) + { + reset(mu.get().release()); + ptr_.second() = detail::move_impl(mu.get().get_deleter()); + return *this; + } + #else + unique_ptr& operator=(unique_ptr && u) + { + reset(u.release()); + ptr_.second() = detail::move_impl(u.get_deleter()); + return *this; + } + #endif + + //!Assigns from the literal 0 or NULL. + //! + //!Effects: reset(). + //! + //!Postcondition: get() == 0 + //! + //!Returns: *this. + //! + //!Throws: nothing. + unique_ptr& operator=(int nat::*) + { + reset(); + return *this; + } + + //!Requires: get() != 0. + //!Returns: *get(). + //!Throws: nothing. + typename detail::add_reference::type operator*() const + { return *ptr_.first(); } + + //!Requires: get() != 0. + //!Returns: get(). + //!Throws: nothing. + pointer operator->() const + { return ptr_.first(); } + + //!Returns: The stored pointer. + //!Throws: nothing. + pointer get() const + { return ptr_.first(); } + + //!Returns: A reference to the stored deleter. + //! + //!Throws: nothing. + deleter_reference get_deleter() + { return ptr_.second(); } + + //!Returns: A const reference to the stored deleter. + //! + //!Throws: nothing. + deleter_const_reference get_deleter() const + { return ptr_.second(); } + + //!Returns: An unspecified value that, when used in boolean + //!contexts, is equivalent to get() != 0. + //! + //!Throws: nothing. + operator int nat::*() const + { return ptr_.first() ? &nat::for_bool_ : 0; } + + //!Postcondition: get() == 0. + //! + //!Returns: The value get() had at the start of the call to release. + //! + //!Throws: nothing. + pointer release() + { + pointer tmp = ptr_.first(); + ptr_.first() = 0; + return tmp; + } + + //!Effects: If p == get() there are no effects. Otherwise get_deleter()(get()). + //! + //!Postconditions: get() == p. + //! + //!Throws: nothing. + void reset(pointer p = 0) + { + if (ptr_.first() != p){ + if (ptr_.first()) + ptr_.second()(ptr_.first()); + ptr_.first() = p; + } + } + + //!Requires: The deleter D is Swappable and will not throw an exception under swap. + //! + //!Effects: The stored pointers of this and u are exchanged. + //! The stored deleters are swapped (unqualified). + //!Throws: nothing. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(unique_ptr& u) + { ptr_.swap(u.ptr_); } + + void swap(detail::moved_object mu) + { ptr_.swap(mu.get().ptr_); } + #else + void swap(unique_ptr&&u) + { ptr_.swap(u.ptr_); } + #endif + + /// @cond + private: + boost::compressed_pair ptr_; + + //This private constructor avoids moving from non-const lvalues + unique_ptr(const unique_ptr&); + template unique_ptr(unique_ptr&); + template unique_ptr(U&, typename detail::unique_ptr_error::type = 0); + + unique_ptr& operator=(unique_ptr&); + template unique_ptr& operator=(unique_ptr&); + template typename detail::unique_ptr_error::type operator=(U&); + /// @endcond +}; +/* +template +class unique_ptr +{ + struct nat {int for_bool_;}; + typedef typename detail::add_reference::type deleter_reference; + typedef typename detail::add_reference::type deleter_const_reference; +public: + typedef T element_type; + typedef D deleter_type; + typedef typename detail::pointer_type::type pointer; + + // constructors + unique_ptr() : ptr_(pointer()) {} + explicit unique_ptr(pointer p) : ptr_(p) {} + unique_ptr(pointer p, typename if_< + boost::is_reference, + D, + typename detail::add_reference::type>::type d) + : ptr_(p, d) {} + unique_ptr(const unique_ptr& u) + : ptr_(const_cast(u).release(), u.get_deleter()) {} + + // destructor + ~unique_ptr() {reset();} + + // assignment + unique_ptr& operator=(const unique_ptr& cu) + { + unique_ptr& u = const_cast(cu); + reset(u.release()); + ptr_.second() = u.get_deleter(); + return *this; + } + unique_ptr& operator=(int nat::*) + { + reset(); + return *this; + } + + // observers + typename detail::add_reference::type operator[](std::size_t i) const {return ptr_.first()[i];} + pointer get() const {return ptr_.first();} + deleter_reference get_deleter() {return ptr_.second();} + deleter_const_reference get_deleter() const {return ptr_.second();} + operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;} + + // modifiers + pointer release() + { + pointer tmp = ptr_.first(); + ptr_.first() = 0; + return tmp; + } + void reset(pointer p = 0) + { + if (ptr_.first() != p) + { + if (ptr_.first()) + ptr_.second()(ptr_.first()); + ptr_.first() = p; + } + } + void swap(unique_ptr& u) {ptr_.swap(u.ptr_);} +private: + boost::compressed_pair ptr_; + + template unique_ptr(U p, E, + typename boost::enable_if >::type* = 0); + template explicit unique_ptr(U, + typename boost::enable_if >::type* = 0); + + unique_ptr(unique_ptr&); + template unique_ptr(U&, typename detail::unique_ptr_error::type = 0); + + unique_ptr& operator=(unique_ptr&); + template typename detail::unique_ptr_error::type operator=(U&); +}; + +template +class unique_ptr +{ + struct nat {int for_bool_;}; + typedef typename detail::add_reference::type deleter_reference; + typedef typename detail::add_reference::type deleter_const_reference; +public: + typedef T element_type; + typedef D deleter_type; + typedef typename detail::pointer_type::type pointer; + static const std::size_t size = N; + + // constructors + unique_ptr() : ptr_(0) {} + explicit unique_ptr(pointer p) : ptr_(p) {} + unique_ptr(pointer p, typename if_< + boost::is_reference, + D, + typename detail::add_reference::type>::type d) + : ptr_(p, d) {} + unique_ptr(const unique_ptr& u) + : ptr_(const_cast(u).release(), u.get_deleter()) {} + + // destructor + ~unique_ptr() {reset();} + + // assignment + unique_ptr& operator=(const unique_ptr& cu) + { + unique_ptr& u = const_cast(cu); + reset(u.release()); + ptr_.second() = u.get_deleter(); + return *this; + } + unique_ptr& operator=(int nat::*) + { + reset(); + return *this; + } + + // observers + typename detail::add_reference::type operator[](std::size_t i) const {return ptr_.first()[i];} + pointer get() const {return ptr_.first();} + deleter_reference get_deleter() {return ptr_.second();} + deleter_const_reference get_deleter() const {return ptr_.second();} + operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;} + + // modifiers + pointer release() + { + pointer tmp = ptr_.first(); + ptr_.first() = 0; + return tmp; + } + void reset(pointer p = 0) + { + if (ptr_.first() != p) + { + if (ptr_.first()) + ptr_.second()(ptr_.first(), N); + ptr_.first() = p; + } + } + void swap(unique_ptr& u) {ptr_.swap(u.ptr_);} +private: + boost::compressed_pair ptr_; + + template unique_ptr(U p, E, + typename boost::enable_if >::type* = 0); + template explicit unique_ptr(U, + typename boost::enable_if >::type* = 0); + + unique_ptr(unique_ptr&); + template unique_ptr(U&, typename detail::unique_ptr_error::type = 0); + + unique_ptr& operator=(unique_ptr&); + template typename detail::unique_ptr_error::type operator=(U&); +}; +*/ +template inline +void swap(unique_ptr& x, unique_ptr& y) +{ x.swap(y); } + +template inline +bool operator==(const unique_ptr& x, const unique_ptr& y) +{ return x.get() == y.get(); } + +template inline +bool operator!=(const unique_ptr& x, const unique_ptr& y) +{ return x.get() != y.get(); } + +template inline +bool operator <(const unique_ptr& x, const unique_ptr& y) +{ return x.get() < y.get(); } + +template inline +bool operator<=(const unique_ptr& x, const unique_ptr& y) +{ return x.get() <= y.get(); } + +template inline +bool operator >(const unique_ptr& x, const unique_ptr& y) +{ return x.get() > y.get(); } + +template inline +bool operator>=(const unique_ptr& x, const unique_ptr& y) +{ return x.get() >= y.get(); } + +/// @cond + +//!This class has move constructor +template +struct is_movable > +{ + enum { value = true }; +}; +/// @endcond + + +//!Returns the type of a unique pointer +//!of type T with boost::interprocess::deleter deleter +//!that can be constructed in the given managed segment type. +template +struct managed_unique_ptr +{ + typedef unique_ptr + < T + , typename ManagedMemory::template deleter::type + > type; +}; + +//!Returns an instance of the a unique pointer constructed +//!with boost::interproces::deleter from a pointer +//!of type T that has been allocated in the passed managed segment +template +#ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE +inline typename detail::return_type + ::type + >::type +#else +typename managed_unique_ptr::type +#endif + make_managed_unique_ptr(T *constructed_object, ManagedMemory &managed_memory) +{ + typename managed_unique_ptr::type to_return + ( constructed_object + , managed_memory.template get_deleter() + ); + return to_return; +} + +} //namespace interprocess{ +} //namespace boost{ + +#include + +#endif //#ifndef BOOST_INTERPROCESS_UNIQUE_PTR_HPP_INCLUDED diff --git a/win32/include/boost/interprocess/smart_ptr/weak_ptr.hpp b/win32/include/boost/interprocess/smart_ptr/weak_ptr.hpp new file mode 100755 index 000000000..04fd742fa --- /dev/null +++ b/win32/include/boost/interprocess/smart_ptr/weak_ptr.hpp @@ -0,0 +1,258 @@ +////////////////////////////////////////////////////////////////////////////// +// +// This file is the adaptation for Interprocess of boost/weak_ptr.hpp +// +// (C) Copyright Peter Dimov 2001, 2002, 2003 +// (C) Copyright Ion Gaztanaga 2006-2008. +// 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_WEAK_PTR_HPP_INCLUDED +#define BOOST_INTERPROCESS_WEAK_PTR_HPP_INCLUDED + +#include +#include + +#include +#include +#include +#include + +//!\file +//!Describes the smart pointer weak_ptr. + +namespace boost{ +namespace interprocess{ + +//!The weak_ptr class template stores a "weak reference" to an object +//!that's already managed by a shared_ptr. To access the object, a weak_ptr +//!can be converted to a shared_ptr using the shared_ptr constructor or the +//!member function lock. When the last shared_ptr to the object goes away +//!and the object is deleted, the attempt to obtain a shared_ptr from the +//!weak_ptr instances that refer to the deleted object will fail: the constructor +//!will throw an exception of type bad_weak_ptr, and weak_ptr::lock will +//!return an empty shared_ptr. +//! +//!Every weak_ptr meets the CopyConstructible and Assignable requirements +//!of the C++ Standard Library, and so can be used in standard library containers. +//!Comparison operators are supplied so that weak_ptr works with the standard +//!library's associative containers. +//! +//!weak_ptr operations never throw exceptions. +//! +//!The class template is parameterized on T, the type of the object pointed to. +template +class weak_ptr +{ + /// @cond + private: + // Borland 5.5.1 specific workarounds + typedef weak_ptr this_type; + typedef typename detail::pointer_to_other + ::type pointer; + typedef typename detail::add_reference + ::type reference; + typedef typename detail::add_reference + ::type const_reference; + /// @endcond + + public: + typedef T element_type; + typedef T value_type; + + //!Effects: Constructs an empty weak_ptr. + //!Postconditions: use_count() == 0. + weak_ptr() + : m_pn() // never throws + {} + // generated copy constructor, assignment, destructor are fine + // + // The "obvious" converting constructor implementation: + // + // template + // weak_ptr(weak_ptr const & r): m_px(r.m_px), m_pn(r.m_pn) // never throws + // { + // } + // + // has a serious problem. + // + // r.m_px may already have been invalidated. The m_px(r.m_px) + // conversion may require access to *r.m_px (virtual inheritance). + // + // It is not possible to avoid spurious access violations since + // in multithreaded programs r.m_px may be invalidated at any point. + + //!Effects: If r is empty, constructs an empty weak_ptr; otherwise, + //!constructs a weak_ptr that shares ownership with r as if by storing a + //!copy of the pointer stored in r. + //! + //!Postconditions: use_count() == r.use_count(). + //! + //!Throws: nothing. + template + weak_ptr(weak_ptr const & r) + : m_pn(r.m_pn) // never throws + { + //Construct a temporary shared_ptr so that nobody + //can destroy the value while constructing this + const shared_ptr &ref = r.lock(); + m_pn.set_pointer(ref.get()); + } + + //!Effects: If r is empty, constructs an empty weak_ptr; otherwise, + //!constructs a weak_ptr that shares ownership with r as if by storing a + //!copy of the pointer stored in r. + //! + //!Postconditions: use_count() == r.use_count(). + //! + //!Throws: nothing. + template + weak_ptr(shared_ptr const & r) + : m_pn(r.m_pn) // never throws + {} + + //!Effects: Equivalent to weak_ptr(r).swap(*this). + //! + //!Throws: nothing. + //! + //!Notes: The implementation is free to meet the effects (and the + //!implied guarantees) via different means, without creating a temporary. + template + weak_ptr & operator=(weak_ptr const & r) // never throws + { + //Construct a temporary shared_ptr so that nobody + //can destroy the value while constructing this + const shared_ptr &ref = r.lock(); + m_pn = r.m_pn; + m_pn.set_pointer(ref.get()); + return *this; + } + + //!Effects: Equivalent to weak_ptr(r).swap(*this). + //! + //!Throws: nothing. + //! + //!Notes: The implementation is free to meet the effects (and the + //!implied guarantees) via different means, without creating a temporary. + template + weak_ptr & operator=(shared_ptr const & r) // never throws + { m_pn = r.m_pn; return *this; } + + //!Returns: expired()? shared_ptr(): shared_ptr(*this). + //! + //!Throws: nothing. + shared_ptr lock() const // never throws + { + // optimization: avoid throw overhead + if(expired()){ + return shared_ptr(); + } + BOOST_TRY{ + return shared_ptr(*this); + } + BOOST_CATCH(bad_weak_ptr const &){ + // Q: how can we get here? + // A: another thread may have invalidated r after the use_count test above. + return shared_ptr(); + } + BOOST_CATCH_END + } + + //!Returns: 0 if *this is empty; otherwise, the number of shared_ptr objects + //!that share ownership with *this. + //! + //!Throws: nothing. + //! + //!Notes: use_count() is not necessarily efficient. Use only for debugging and + //!testing purposes, not for production code. + long use_count() const // never throws + { return m_pn.use_count(); } + + //!Returns: Returns: use_count() == 0. + //! + //!Throws: nothing. + //! + //!Notes: expired() may be faster than use_count(). + bool expired() const // never throws + { return m_pn.use_count() == 0; } + + //!Effects: Equivalent to: + //!weak_ptr().swap(*this). + void reset() // never throws in 1.30+ + { this_type().swap(*this); } + + //!Effects: Exchanges the contents of the two + //!smart pointers. + //! + //!Throws: nothing. + void swap(this_type & other) // never throws + { detail::do_swap(m_pn, other.m_pn); } + + /// @cond + template + bool _internal_less(weak_ptr const & rhs) const + { return m_pn < rhs.m_pn; } + + template + void _internal_assign(const detail::shared_count & pn2) + { + + m_pn = pn2; + } + + private: + + template friend class shared_ptr; + template friend class weak_ptr; + + detail::weak_count m_pn; // reference counter + /// @endcond +}; // weak_ptr + +template inline +bool operator<(weak_ptr const & a, weak_ptr const & b) +{ return a._internal_less(b); } + +template inline +void swap(weak_ptr & a, weak_ptr & b) +{ a.swap(b); } + +//!Returns the type of a weak pointer +//!of type T with the allocator boost::interprocess::allocator allocator +//!and boost::interprocess::deleter deleter +//!that can be constructed in the given managed segment type. +template +struct managed_weak_ptr +{ + typedef weak_ptr + < T + , typename ManagedMemory::template allocator::type + , typename ManagedMemory::template deleter::type + > type; +}; + +//!Returns an instance of the a weak pointer constructed +//!with the default allocator and deleter from a pointer +//!of type T that has been allocated in the passed managed segment +template +inline typename managed_weak_ptr::type + make_managed_weak_ptr(T *constructed_object, ManagedMemory &managed_memory) +{ + return typename managed_weak_ptr::type + ( constructed_object + , managed_memory.template get_allocator() + , managed_memory.template get_deleter() + ); +} + +} // namespace interprocess +} // namespace boost + +#include + +#endif // #ifndef BOOST_INTERPROCESS_WEAK_PTR_HPP_INCLUDED diff --git a/win32/include/boost/interprocess/streams/bufferstream.hpp b/win32/include/boost/interprocess/streams/bufferstream.hpp new file mode 100755 index 000000000..3e5cfc17e --- /dev/null +++ b/win32/include/boost/interprocess/streams/bufferstream.hpp @@ -0,0 +1,444 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005. +// Changed internal SGI string to a buffer. Added efficient +// internal buffer get/set/swap functions, so that we can obtain/establish the +// internal buffer without any reallocation or copy. Kill those temporaries! +/////////////////////////////////////////////////////////////////////////////// +/* + * Copyright (c) 1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +//!\file +//!This file defines basic_bufferbuf, basic_ibufferstream, +//!basic_obufferstream, and basic_bufferstream classes. These classes +//!represent streamsbufs and streams whose sources or destinations +//!are fixed size character buffers. + +#ifndef BOOST_INTERPROCESS_BUFFERSTREAM_HPP +#define BOOST_INTERPROCESS_BUFFERSTREAM_HPP + +#include +#include + +#include +#include +#include +#include +#include // char traits +#include // ptrdiff_t +#include +#include + +namespace boost { namespace interprocess { + +//!A streambuf class that controls the transmission of elements to and from +//!a basic_xbufferstream. The elements are transmitted from a to a fixed +//!size buffer +template +class basic_bufferbuf + : public std::basic_streambuf +{ + public: + typedef CharT char_type; + typedef typename CharTraits::int_type int_type; + typedef typename CharTraits::pos_type pos_type; + typedef typename CharTraits::off_type off_type; + typedef CharTraits traits_type; + typedef std::basic_streambuf base_t; + + public: + //!Constructor. + //!Does not throw. + explicit basic_bufferbuf(std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + : base_t(), m_mode(mode), m_buffer(0), m_length(0) + {} + + //!Constructor. Assigns formatting buffer. + //!Does not throw. + explicit basic_bufferbuf(CharT *buffer, std::size_t length, + std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + : base_t(), m_mode(mode), m_buffer(buffer), m_length(length) + { this->set_pointers(); } + + virtual ~basic_bufferbuf(){} + + public: + //!Returns the pointer and size of the internal buffer. + //!Does not throw. + std::pair buffer() const + { return std::pair(m_buffer, m_length); } + + //!Sets the underlying buffer to a new value + //!Does not throw. + void buffer(CharT *buffer, std::size_t length) + { m_buffer = buffer; m_length = length; this->set_pointers(); } + + /// @cond + private: + void set_pointers() + { + // The initial read position is the beginning of the buffer. + if(m_mode & std::ios_base::in) + this->setg(m_buffer, m_buffer, m_buffer + m_length); + + // The initial write position is the beginning of the buffer. + if(m_mode & std::ios_base::out) + this->setp(m_buffer, m_buffer + m_length); + } + + protected: + virtual int_type underflow() + { + // Precondition: gptr() >= egptr(). Returns a character, if available. + return this->gptr() != this->egptr() ? + CharTraits::to_int_type(*this->gptr()) : CharTraits::eof(); + } + + virtual int_type pbackfail(int_type c = CharTraits::eof()) + { + if(this->gptr() != this->eback()) { + if(!CharTraits::eq_int_type(c, CharTraits::eof())) { + if(CharTraits::eq(CharTraits::to_char_type(c), this->gptr()[-1])) { + this->gbump(-1); + return c; + } + else if(m_mode & std::ios_base::out) { + this->gbump(-1); + *this->gptr() = c; + return c; + } + else + return CharTraits::eof(); + } + else { + this->gbump(-1); + return CharTraits::not_eof(c); + } + } + else + return CharTraits::eof(); + } + + virtual int_type overflow(int_type c = CharTraits::eof()) + { + if(m_mode & std::ios_base::out) { + if(!CharTraits::eq_int_type(c, CharTraits::eof())) { +// if(!(m_mode & std::ios_base::in)) { +// if(this->pptr() != this->epptr()) { +// *this->pptr() = CharTraits::to_char_type(c); +// this->pbump(1); +// return c; +// } +// else +// return CharTraits::eof(); +// } +// else { + if(this->pptr() == this->epptr()) { + //We can't append to a static buffer + return CharTraits::eof(); + } + else { + *this->pptr() = CharTraits::to_char_type(c); + this->pbump(1); + return c; + } +// } + } + else // c is EOF, so we don't have to do anything + return CharTraits::not_eof(c); + } + else // Overflow always fails if it's read-only. + return CharTraits::eof(); + } + + virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, + std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + { + bool in = false; + bool out = false; + + const std::ios_base::openmode inout = + std::ios_base::in | std::ios_base::out; + + if((mode & inout) == inout) { + if(dir == std::ios_base::beg || dir == std::ios_base::end) + in = out = true; + } + else if(mode & std::ios_base::in) + in = true; + else if(mode & std::ios_base::out) + out = true; + + if(!in && !out) + return pos_type(off_type(-1)); + else if((in && (!(m_mode & std::ios_base::in) || this->gptr() == 0)) || + (out && (!(m_mode & std::ios_base::out) || this->pptr() == 0))) + return pos_type(off_type(-1)); + + std::streamoff newoff; + switch(dir) { + case std::ios_base::beg: + newoff = 0; + break; + case std::ios_base::end: + newoff = static_cast(m_length); + break; + case std::ios_base::cur: + newoff = in ? static_cast(this->gptr() - this->eback()) + : static_cast(this->pptr() - this->pbase()); + break; + default: + return pos_type(off_type(-1)); + } + + off += newoff; + + if(in) { + std::ptrdiff_t n = this->egptr() - this->eback(); + + if(off < 0 || off > n) + return pos_type(off_type(-1)); + else + this->setg(this->eback(), this->eback() + off, this->eback() + n); + } + + if(out) { + std::ptrdiff_t n = this->epptr() - this->pbase(); + + if(off < 0 || off > n) + return pos_type(off_type(-1)); + else { + this->setp(this->pbase(), this->pbase() + n); + this->pbump(off); + } + } + + return pos_type(off); + } + + virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + { return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); } + + private: + std::ios_base::openmode m_mode; + CharT * m_buffer; + std::size_t m_length; + /// @endcond +}; + +//!A basic_istream class that uses a fixed size character buffer +//!as its formatting buffer. +template +class basic_ibufferstream + : public std::basic_istream +{ + public: // Typedefs + typedef typename std::basic_ios + ::char_type char_type; + typedef typename std::basic_ios::int_type int_type; + typedef typename std::basic_ios::pos_type pos_type; + typedef typename std::basic_ios::off_type off_type; + typedef typename std::basic_ios::traits_type traits_type; + + private: + typedef std::basic_ios basic_ios_t; + typedef std::basic_istream base_t; + + public: + //!Constructor. + //!Does not throw. + basic_ibufferstream(std::ios_base::openmode mode = std::ios_base::in) + : basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::in) + { basic_ios_t::init(&m_buf); } + + //!Constructor. Assigns formatting buffer. + //!Does not throw. + basic_ibufferstream(const CharT *buffer, std::size_t length, + std::ios_base::openmode mode = std::ios_base::in) + : basic_ios_t(), base_t(0), + m_buf(const_cast(buffer), length, mode | std::ios_base::in) + { basic_ios_t::init(&m_buf); } + + ~basic_ibufferstream(){}; + + public: + //!Returns the address of the stored + //!stream buffer. + basic_bufferbuf* rdbuf() const + { return const_cast*>(&m_buf); } + + //!Returns the pointer and size of the internal buffer. + //!Does not throw. + std::pair buffer() const + { return m_buf.buffer(); } + + //!Sets the underlying buffer to a new value. Resets + //!stream position. Does not throw. + void buffer(const CharT *buffer, std::size_t length) + { m_buf.buffer(const_cast(buffer), length); } + + /// @cond + private: + basic_bufferbuf m_buf; + /// @endcond +}; + +//!A basic_ostream class that uses a fixed size character buffer +//!as its formatting buffer. +template +class basic_obufferstream + : public std::basic_ostream +{ + public: + typedef typename std::basic_ios + ::char_type char_type; + typedef typename std::basic_ios::int_type int_type; + typedef typename std::basic_ios::pos_type pos_type; + typedef typename std::basic_ios::off_type off_type; + typedef typename std::basic_ios::traits_type traits_type; + + /// @cond + private: + typedef std::basic_ios basic_ios_t; + typedef std::basic_ostream base_t; + /// @endcond + public: + //!Constructor. + //!Does not throw. + basic_obufferstream(std::ios_base::openmode mode = std::ios_base::out) + : basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::out) + { basic_ios_t::init(&m_buf); } + + //!Constructor. Assigns formatting buffer. + //!Does not throw. + basic_obufferstream(CharT *buffer, std::size_t length, + std::ios_base::openmode mode = std::ios_base::out) + : basic_ios_t(), base_t(0), + m_buf(buffer, length, mode | std::ios_base::out) + { basic_ios_t::init(&m_buf); } + + ~basic_obufferstream(){} + + public: + //!Returns the address of the stored + //!stream buffer. + basic_bufferbuf* rdbuf() const + { return const_cast*>(&m_buf); } + + //!Returns the pointer and size of the internal buffer. + //!Does not throw. + std::pair buffer() const + { return m_buf.buffer(); } + + //!Sets the underlying buffer to a new value. Resets + //!stream position. Does not throw. + void buffer(CharT *buffer, std::size_t length) + { m_buf.buffer(buffer, length); } + + /// @cond + private: + basic_bufferbuf m_buf; + /// @endcond +}; + + +//!A basic_iostream class that uses a fixed size character buffer +//!as its formatting buffer. +template +class basic_bufferstream + : public std::basic_iostream + +{ + public: // Typedefs + typedef typename std::basic_ios + ::char_type char_type; + typedef typename std::basic_ios::int_type int_type; + typedef typename std::basic_ios::pos_type pos_type; + typedef typename std::basic_ios::off_type off_type; + typedef typename std::basic_ios::traits_type traits_type; + + /// @cond + private: + typedef std::basic_ios basic_ios_t; + typedef std::basic_iostream base_t; + /// @endcond + + public: + //!Constructor. + //!Does not throw. + basic_bufferstream(std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + : basic_ios_t(), base_t(0), m_buf(mode) + { basic_ios_t::init(&m_buf); } + + //!Constructor. Assigns formatting buffer. + //!Does not throw. + basic_bufferstream(CharT *buffer, std::size_t length, + std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + : basic_ios_t(), base_t(0), m_buf(buffer, length, mode) + { basic_ios_t::init(&m_buf); } + + ~basic_bufferstream(){} + + public: + //!Returns the address of the stored + //!stream buffer. + basic_bufferbuf* rdbuf() const + { return const_cast*>(&m_buf); } + + //!Returns the pointer and size of the internal buffer. + //!Does not throw. + std::pair buffer() const + { return m_buf.buffer(); } + + //!Sets the underlying buffer to a new value. Resets + //!stream position. Does not throw. + void buffer(CharT *buffer, std::size_t length) + { m_buf.buffer(buffer, length); } + + /// @cond + private: + basic_bufferbuf m_buf; + /// @endcond +}; + +//Some typedefs to simplify usage +typedef basic_bufferbuf bufferbuf; +typedef basic_bufferstream bufferstream; +typedef basic_ibufferstream ibufferstream; +typedef basic_obufferstream obufferstream; + +typedef basic_bufferbuf wbufferbuf; +typedef basic_bufferstream wbufferstream; +typedef basic_ibufferstream wibufferstream; +typedef basic_obufferstream wobufferstream; + + +}} //namespace boost { namespace interprocess { + +#include + +#endif /* BOOST_INTERPROCESS_BUFFERSTREAM_HPP */ diff --git a/win32/include/boost/interprocess/streams/vectorstream.hpp b/win32/include/boost/interprocess/streams/vectorstream.hpp new file mode 100755 index 000000000..8785cbcd8 --- /dev/null +++ b/win32/include/boost/interprocess/streams/vectorstream.hpp @@ -0,0 +1,593 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005. +// Changed internal SGI string to a generic, templatized vector. Added efficient +// internal buffer get/set/swap functions, so that we can obtain/establish the +// internal buffer without any reallocation or copy. Kill those temporaries! +/////////////////////////////////////////////////////////////////////////////// +/* + * Copyright (c) 1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +//!\file +//!This file defines basic_vectorbuf, basic_ivectorstream, +//!basic_ovectorstream, and basic_vectorstreamclasses. These classes +//!represent streamsbufs and streams whose sources or destinations are +//!STL-like vectors that can be swapped with external vectors to avoid +//!unnecessary allocations/copies. + +#ifndef BOOST_INTERPROCESS_VECTORSTREAM_HPP +#define BOOST_INTERPROCESS_VECTORSTREAM_HPP + +#include +#include + +#include +#include +#include +#include +#include // char traits +#include // ptrdiff_t +#include +#include + +namespace boost { namespace interprocess { + +//!A streambuf class that controls the transmission of elements to and from +//!a basic_ivectorstream, basic_ovectorstream or basic_vectorstream. +//!It holds a character vector specified by CharVector template parameter +//!as its formatting buffer. The vector must have contiguous storage, like +//!std::vector, boost::interprocess::vector or boost::interprocess::basic_string +template +class basic_vectorbuf + : public std::basic_streambuf +{ + public: + typedef CharVector vector_type; + typedef typename CharVector::value_type char_type; + typedef typename CharTraits::int_type int_type; + typedef typename CharTraits::pos_type pos_type; + typedef typename CharTraits::off_type off_type; + typedef CharTraits traits_type; + + /// @cond + private: + typedef std::basic_streambuf base_t; + + basic_vectorbuf(const basic_vectorbuf&); + basic_vectorbuf & operator =(const basic_vectorbuf&); + /// @endcond + + public: + //!Constructor. Throws if vector_type default + //!constructor throws. + explicit basic_vectorbuf(std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + : base_t(), m_mode(mode) + { this->initialize_pointers(); } + + //!Constructor. Throws if + //!vector_type(const VectorParameter ¶m) throws. + template + explicit basic_vectorbuf(const VectorParameter ¶m, + std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + : base_t(), m_mode(mode), m_vect(param) + { this->initialize_pointers(); } + + virtual ~basic_vectorbuf(){} + + public: + + //!Swaps the underlying vector with the passed vector. + //!This function resets the read/write position in the stream. + //!Does not throw. + void swap_vector(vector_type &vect) + { + if (this->m_mode & std::ios_base::out){ + //Update high water if necessary + //And resize vector to remove extra size + if (mp_high_water < base_t::pptr()){ + //Restore the vector's size if necessary + mp_high_water = base_t::pptr(); + } + m_vect.resize(mp_high_water - (m_vect.size() ? &m_vect[0] : 0)); + + //Now swap vector + m_vect.swap(vect); + + //If the stream is writable put the high water mark + //and maximize the size. + typename vector_type::size_type old_size = m_vect.size(); + m_vect.resize(m_vect.capacity()); + this->initialize_pointers(); + mp_high_water = old_size ? &m_vect[0] + old_size : 0; + } + else{ + //Now swap vector + m_vect.swap(vect); + this->initialize_pointers(); + } + } + + //!Returns a const reference to the internal vector. + //!Does not throw. + const vector_type &vector() const + { + if (this->m_mode & std::ios_base::out){ + if (mp_high_water < base_t::pptr()){ + //Restore the vector's size if necessary + mp_high_water = base_t::pptr(); + } + m_vect.resize(mp_high_water - (m_vect.size() ? &m_vect[0] : 0)); + const_cast(this)->initialize_pointers(); + } + return m_vect; + } + + //!Preallocates memory from the internal vector. + //!Resets the stream to the first position. + //!Throws if the internals vector's memory allocation throws. + void reserve(typename vector_type::size_type size) + { + m_vect.reserve(size); + //Now update pointer data + typename vector_type::size_type old_size = m_vect.size(); + m_vect.resize(m_vect.capacity()); + this->initialize_pointers(); + mp_high_water = old_size ? &m_vect[0] + old_size : 0; + } + + //!Calls clear() method of the internal vector. + //!Resets the stream to the first position. + void clear() + { m_vect.clear(); this->initialize_pointers(); } + + /// @cond + private: + void initialize_pointers() + { + // The initial read position is the beginning of the vector. + if(m_mode & std::ios_base::in){ + if(m_vect.empty()){ + this->setg(0, 0, 0); + } + else{ + this->setg(&m_vect[0], &m_vect[0], &m_vect[0] + m_vect.size()); + } + } + + // The initial write position is the beginning of the vector. + if(m_mode & std::ios_base::out){ + if(m_vect.empty()){ + this->setp(0, 0); + } + else{ + this->setp(&m_vect[0], &m_vect[0] + m_vect.size()); + } + + if (m_mode & (std::ios_base::app | std::ios_base::ate)) + base_t::pbump((int)m_vect.size()); + } + mp_high_water = m_vect.empty() ? 0 : (&m_vect[0] + m_vect.size()); + } + + protected: + virtual int_type underflow() + { + if (base_t::gptr() == 0) + return CharTraits::eof(); + if (mp_high_water < base_t::pptr()) + mp_high_water = base_t::pptr(); + if (base_t::egptr() < mp_high_water) + base_t::setg(base_t::eback(), base_t::gptr(), mp_high_water); + if (base_t::gptr() < base_t::egptr()) + return CharTraits::to_int_type(*base_t::gptr()); + return CharTraits::eof(); + } + + virtual int_type pbackfail(int_type c = CharTraits::eof()) + { + if(this->gptr() != this->eback()) { + if(!CharTraits::eq_int_type(c, CharTraits::eof())) { + if(CharTraits::eq(CharTraits::to_char_type(c), this->gptr()[-1])) { + this->gbump(-1); + return c; + } + else if(m_mode & std::ios_base::out) { + this->gbump(-1); + *this->gptr() = c; + return c; + } + else + return CharTraits::eof(); + } + else { + this->gbump(-1); + return CharTraits::not_eof(c); + } + } + else + return CharTraits::eof(); + } + + virtual int_type overflow(int_type c = CharTraits::eof()) + { + if(m_mode & std::ios_base::out) { + if(!CharTraits::eq_int_type(c, CharTraits::eof())) { +// if(!(m_mode & std::ios_base::in)) { +// if(this->pptr() < this->epptr()) { +// *this->pptr() = CharTraits::to_char_type(c); +// this->pbump(1); +// if (mp_high_water < base_t::pptr()) +// mp_high_water = base_t::pptr(); +// if ((m_mode & std::ios_base::in) && base_t::egptr() < mp_high_water) +// base_t::setg(base_t::eback(), base_t::gptr(), mp_high_water); +// return c; +// } +// else +// return CharTraits::eof(); +// } +// else { +// try{ + typedef typename vector_type::difference_type dif_t; + dif_t inpos = base_t::gptr() - base_t::eback(); + //The new output position is the previous one plus one + //because 'overflow' requires putting 'c' on the buffer + dif_t new_outpos = base_t::pptr() - base_t::pbase() + 1; + //Adjust high water if necessary + dif_t hipos = mp_high_water - base_t::pbase(); + if (hipos < new_outpos) + hipos = new_outpos; + //Insert the new data + m_vect.push_back(CharTraits::to_char_type(c)); + m_vect.resize(m_vect.capacity()); + char_type* p = const_cast(&m_vect[0]); + //A reallocation has happened, update pointers + if (m_mode & std::ios_base::in) + base_t::setg(p, p + inpos, p + hipos); + base_t::setp(p, p + (dif_t)m_vect.size()); + //Update write position to the old position + 1 + base_t::pbump((int)new_outpos); + //Update high water pointer, since the buffer has been reallocated + mp_high_water = base_t::pbase() + hipos; + return c; +// } +// catch(...){ +// return CharTraits::eof(); +// } +// } + } + else // c is EOF, so we don't have to do anything + return CharTraits::not_eof(c); + } + else // Overflow always fails if it's read-only. + return CharTraits::eof(); + } + + virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, + std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + { + bool in = false, out = false; + + const std::ios_base::openmode inout = + std::ios_base::in | std::ios_base::out; + + if((mode & inout) == inout) { + if(dir == std::ios_base::beg || dir == std::ios_base::end) + in = out = true; + } + else if(mode & std::ios_base::in) + in = true; + else if(mode & std::ios_base::out) + out = true; + + if(!in && !out) + return pos_type(off_type(-1)); + else if((in && (!(m_mode & std::ios_base::in) || this->gptr() == 0)) || + (out && (!(m_mode & std::ios_base::out) || this->pptr() == 0))) + return pos_type(off_type(-1)); + + off_type newoff; + //Just calculate the end of the stream. If the stream is read-only + //the limit is the size of the vector. Otherwise, the high water mark + //will mark the real size. + off_type limit = static_cast (mode & std::ios_base::out ? + mp_high_water - base_t::pbase() : m_vect.size()/*mp_high_water - base_t::eback()*/); + + switch(dir) { + case std::ios_base::beg: + newoff = 0; + break; + case std::ios_base::end: + newoff = limit; + break; + case std::ios_base::cur: + newoff = in ? static_cast(this->gptr() - this->eback()) + : static_cast(this->pptr() - this->pbase()); + break; + default: + return pos_type(off_type(-1)); + } + + newoff += off; + + if (newoff < 0 || newoff > limit) + return pos_type(-1); + if (m_mode & std::ios_base::app && mode & std::ios_base::out && newoff != limit) + return pos_type(-1); + if (in) + base_t::setg(base_t::eback(), base_t::eback() + newoff, base_t::egptr()); + if (out){ + base_t::setp(base_t::pbase(), base_t::epptr()); + base_t::pbump(newoff); + } + return pos_type(newoff); + } + + virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + { return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); } + + private: + std::ios_base::openmode m_mode; + mutable vector_type m_vect; + mutable char_type* mp_high_water; + /// @endcond +}; + +//!A basic_istream class that holds a character vector specified by CharVector +//!template parameter as its formatting buffer. The vector must have +//!contiguous storage, like std::vector, boost::interprocess::vector or +//!boost::interprocess::basic_string +template +class basic_ivectorstream + : public std::basic_istream +{ + public: + typedef CharVector vector_type; + typedef typename std::basic_ios + ::char_type char_type; + typedef typename std::basic_ios::int_type int_type; + typedef typename std::basic_ios::pos_type pos_type; + typedef typename std::basic_ios::off_type off_type; + typedef typename std::basic_ios::traits_type traits_type; + + /// @cond + private: + typedef std::basic_ios basic_ios_t; + typedef std::basic_istream base_t; + /// @endcond + + public: + //!Constructor. Throws if vector_type default + //!constructor throws. + basic_ivectorstream(std::ios_base::openmode mode = std::ios_base::in) + : basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::in) + { basic_ios_t::init(&m_buf); } + + //!Constructor. Throws if vector_type(const VectorParameter ¶m) + //!throws. + template + basic_ivectorstream(const VectorParameter ¶m, + std::ios_base::openmode mode = std::ios_base::in) + : basic_ios_t(), base_t(0), + m_buf(param, mode | std::ios_base::in) + { basic_ios_t::init(&m_buf); } + + ~basic_ivectorstream(){}; + + public: + //!Returns the address of the stored + //!stream buffer. + basic_vectorbuf* rdbuf() const + { return const_cast*>(&m_buf); } + + //!Swaps the underlying vector with the passed vector. + //!This function resets the read position in the stream. + //!Does not throw. + void swap_vector(vector_type &vect) + { m_buf.swap_vector(vect); } + + //!Returns a const reference to the internal vector. + //!Does not throw. + const vector_type &vector() const + { return m_buf.vector(); } + + //!Calls reserve() method of the internal vector. + //!Resets the stream to the first position. + //!Throws if the internals vector's reserve throws. + void reserve(typename vector_type::size_type size) + { m_buf.reserve(size); } + + //!Calls clear() method of the internal vector. + //!Resets the stream to the first position. + void clear() + { m_buf.clear(); } + + /// @cond + private: + basic_vectorbuf m_buf; + /// @endcond +}; + +//!A basic_ostream class that holds a character vector specified by CharVector +//!template parameter as its formatting buffer. The vector must have +//!contiguous storage, like std::vector, boost::interprocess::vector or +//!boost::interprocess::basic_string +template +class basic_ovectorstream + : public std::basic_ostream +{ + public: + typedef CharVector vector_type; + typedef typename std::basic_ios + ::char_type char_type; + typedef typename std::basic_ios::int_type int_type; + typedef typename std::basic_ios::pos_type pos_type; + typedef typename std::basic_ios::off_type off_type; + typedef typename std::basic_ios::traits_type traits_type; + + /// @cond + private: + typedef std::basic_ios basic_ios_t; + typedef std::basic_ostream base_t; + /// @endcond + + public: + //!Constructor. Throws if vector_type default + //!constructor throws. + basic_ovectorstream(std::ios_base::openmode mode = std::ios_base::out) + : basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::out) + { basic_ios_t::init(&m_buf); } + + //!Constructor. Throws if vector_type(const VectorParameter ¶m) + //!throws. + template + basic_ovectorstream(const VectorParameter ¶m, + std::ios_base::openmode mode = std::ios_base::out) + : basic_ios_t(), base_t(0), m_buf(param, mode | std::ios_base::out) + { basic_ios_t::init(&m_buf); } + + ~basic_ovectorstream(){} + + public: + //!Returns the address of the stored + //!stream buffer. + basic_vectorbuf* rdbuf() const + { return const_cast*>(&m_buf); } + + //!Swaps the underlying vector with the passed vector. + //!This function resets the write position in the stream. + //!Does not throw. + void swap_vector(vector_type &vect) + { m_buf.swap_vector(vect); } + + //!Returns a const reference to the internal vector. + //!Does not throw. + const vector_type &vector() const + { return m_buf.vector(); } + + //!Calls reserve() method of the internal vector. + //!Resets the stream to the first position. + //!Throws if the internals vector's reserve throws. + void reserve(typename vector_type::size_type size) + { m_buf.reserve(size); } + + /// @cond + private: + basic_vectorbuf m_buf; + /// @endcond +}; + + +//!A basic_iostream class that holds a character vector specified by CharVector +//!template parameter as its formatting buffer. The vector must have +//!contiguous storage, like std::vector, boost::interprocess::vector or +//!boost::interprocess::basic_string +template +class basic_vectorstream + : public std::basic_iostream + +{ + public: + typedef CharVector vector_type; + typedef typename std::basic_ios + ::char_type char_type; + typedef typename std::basic_ios::int_type int_type; + typedef typename std::basic_ios::pos_type pos_type; + typedef typename std::basic_ios::off_type off_type; + typedef typename std::basic_ios::traits_type traits_type; + + /// @cond + private: + typedef std::basic_ios basic_ios_t; + typedef std::basic_iostream base_t; + /// @endcond + + public: + //!Constructor. Throws if vector_type default + //!constructor throws. + basic_vectorstream(std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + : basic_ios_t(), base_t(0), m_buf(mode) + { basic_ios_t::init(&m_buf); } + + //!Constructor. Throws if vector_type(const VectorParameter ¶m) + //!throws. + template + basic_vectorstream(const VectorParameter ¶m, std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out) + : basic_ios_t(), base_t(0), m_buf(param, mode) + { basic_ios_t::init(&m_buf); } + + ~basic_vectorstream(){} + + public: + //Returns the address of the stored stream buffer. + basic_vectorbuf* rdbuf() const + { return const_cast*>(&m_buf); } + + //!Swaps the underlying vector with the passed vector. + //!This function resets the read/write position in the stream. + //!Does not throw. + void swap_vector(vector_type &vect) + { m_buf.swap_vector(vect); } + + //!Returns a const reference to the internal vector. + //!Does not throw. + const vector_type &vector() const + { return m_buf.vector(); } + + //!Calls reserve() method of the internal vector. + //!Resets the stream to the first position. + //!Throws if the internals vector's reserve throws. + void reserve(typename vector_type::size_type size) + { m_buf.reserve(size); } + + //!Calls clear() method of the internal vector. + //!Resets the stream to the first position. + void clear() + { m_buf.clear(); } + + /// @cond + private: + basic_vectorbuf m_buf; + /// @endcond +}; + +//Some typedefs to simplify usage +//! +//!typedef basic_vectorbuf > vectorbuf; +//!typedef basic_vectorstream > vectorstream; +//!typedef basic_ivectorstream > ivectorstream; +//!typedef basic_ovectorstream > ovectorstream; +//! +//!typedef basic_vectorbuf > wvectorbuf; +//!typedef basic_vectorstream > wvectorstream; +//!typedef basic_ivectorstream > wivectorstream; +//!typedef basic_ovectorstream > wovectorstream; + +}} //namespace boost { namespace interprocess { + +#include + +#endif /* BOOST_INTERPROCESS_VECTORSTREAM_HPP */ diff --git a/win32/include/boost/interprocess/sync/emulation/interprocess_barrier.hpp b/win32/include/boost/interprocess/sync/emulation/interprocess_barrier.hpp new file mode 100755 index 000000000..2a889df7f --- /dev/null +++ b/win32/include/boost/interprocess/sync/emulation/interprocess_barrier.hpp @@ -0,0 +1,46 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +namespace boost { +namespace interprocess { + +inline barrier::barrier(unsigned int count) + : m_threshold(count), m_count(count), m_generation(0) +{ + if (count == 0) + throw std::invalid_argument("count cannot be zero."); +} + +inline barrier::~barrier(){} + +inline bool barrier::wait() +{ + scoped_lock lock(m_mutex); + unsigned int gen = m_generation; + + if (--m_count == 0){ + m_generation++; + m_count = m_threshold; + m_cond.notify_all(); + return true; + } + + while (gen == m_generation){ + m_cond.wait(lock); + } + return false; +} + +} //namespace interprocess { +} //namespace boost { diff --git a/win32/include/boost/interprocess/sync/emulation/interprocess_condition.hpp b/win32/include/boost/interprocess/sync/emulation/interprocess_condition.hpp new file mode 100755 index 000000000..d6d6ff885 --- /dev/null +++ b/win32/include/boost/interprocess/sync/emulation/interprocess_condition.hpp @@ -0,0 +1,216 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +namespace boost { +namespace interprocess { + +inline interprocess_condition::interprocess_condition() +{ + //Note that this class is initialized to zero. + //So zeroed memory can be interpreted as an initialized + //condition variable + m_command = SLEEP; + m_num_waiters = 0; +} + +inline interprocess_condition::~interprocess_condition() +{ + //Trivial destructor +} + +inline void interprocess_condition::notify_one() +{ + this->notify(NOTIFY_ONE); +} + +inline void interprocess_condition::notify_all() +{ + this->notify(NOTIFY_ALL); +} + +inline void interprocess_condition::notify(boost::uint32_t command) +{ + //This interprocess_mutex guarantees that no other thread can enter to the + //do_timed_wait method logic, so that thread count will be + //constant until the function writes a NOTIFY_ALL command. + //It also guarantees that no other notification can be signaled + //on this interprocess_condition before this one ends + m_enter_mut.lock(); + + //Return if there are no waiters + if(!detail::atomic_read32(&m_num_waiters)) { + m_enter_mut.unlock(); + return; + } + + //Notify that all threads should execute wait logic + while(SLEEP != detail::atomic_cas32((boost::uint32_t*)&m_command, command, SLEEP)){ + detail::thread_yield(); + } +/* + //Wait until the threads are woken + while(SLEEP != detail::atomic_cas32((boost::uint32_t*)&m_command, 0)){ + detail::thread_yield(); + } +*/ + //The enter interprocess_mutex will rest locked until the last waiting thread unlocks it +} + +inline void interprocess_condition::do_wait(interprocess_mutex &mut) +{ + this->do_timed_wait(false, boost::posix_time::ptime(), mut); +} + +inline bool interprocess_condition::do_timed_wait + (const boost::posix_time::ptime &abs_time, interprocess_mutex &mut) +{ + return this->do_timed_wait(true, abs_time, mut); +} + +inline bool interprocess_condition::do_timed_wait(bool tout_enabled, + const boost::posix_time::ptime &abs_time, + interprocess_mutex &mut) +{ + boost::posix_time::ptime now = microsec_clock::universal_time(); + + if(tout_enabled){ + if(now >= abs_time) return false; + } + + typedef boost::interprocess::scoped_lock InternalLock; + //The enter interprocess_mutex guarantees that while executing a notification, + //no other thread can execute the do_timed_wait method. + { + //--------------------------------------------------------------- + InternalLock lock; + if(tout_enabled){ + InternalLock dummy(m_enter_mut, abs_time); + lock = detail::move_impl(dummy); + } + else{ + InternalLock dummy(m_enter_mut); + lock = detail::move_impl(dummy); + } + + if(!lock) + return false; + //--------------------------------------------------------------- + //We increment the waiting thread count protected so that it will be + //always constant when another thread enters the notification logic. + //The increment marks this thread as "waiting on interprocess_condition" + detail::atomic_inc32((boost::uint32_t*)&m_num_waiters); + + //We unlock the external interprocess_mutex atomically with the increment + mut.unlock(); + } + + //By default, we suppose that no timeout has happened + bool timed_out = false, unlock_enter_mut= false; + + //Loop until a notification indicates that the thread should + //exit or timeout occurs + while(1){ + //The thread sleeps/spins until a interprocess_condition commands a notification + //Notification occurred, we will lock the checking interprocess_mutex so that + while(detail::atomic_read32(&m_command) == SLEEP){ + detail::thread_yield(); + + //Check for timeout + if(tout_enabled){ + now = microsec_clock::universal_time(); + + if(now >= abs_time){ + //If we can lock the interprocess_mutex it means that no notification + //is being executed in this interprocess_condition variable + timed_out = m_enter_mut.try_lock(); + + //If locking fails, indicates that another thread is executing + //notification, so we play the notification game + if(!timed_out){ + //There is an ongoing notification, we will try again later + continue; + } + //No notification in execution, since enter interprocess_mutex is locked. + //We will execute time-out logic, so we will decrement count, + //release the enter interprocess_mutex and return false. + break; + } + } + } + + //If a timeout occurred, the interprocess_mutex will not execute checking logic + if(tout_enabled && timed_out){ + //Decrement wait count + detail::atomic_dec32((boost::uint32_t*)&m_num_waiters); + unlock_enter_mut = true; + break; + } + else{ + //Notification occurred, we will lock the checking interprocess_mutex so that + //if a notify_one notification occurs, only one thread can exit + //--------------------------------------------------------------- + InternalLock lock; + if(tout_enabled){ + InternalLock dummy(m_check_mut, abs_time); + lock = detail::move_impl(dummy); + } + else{ + InternalLock dummy(m_check_mut); + lock = detail::move_impl(dummy); + } + + if(!lock) + return false; + //--------------------------------------------------------------- + boost::uint32_t result = detail::atomic_cas32 + ((boost::uint32_t*)&m_command, SLEEP, NOTIFY_ONE); + if(result == SLEEP){ + //Other thread has been notified and since it was a NOTIFY one + //command, this thread must sleep again + continue; + } + else if(result == NOTIFY_ONE){ + //If it was a NOTIFY_ONE command, only this thread should + //exit. This thread has atomically marked command as sleep before + //so no other thread will exit. + //Decrement wait count. + unlock_enter_mut = true; + detail::atomic_dec32((boost::uint32_t*)&m_num_waiters); + break; + } + else{ + //If it is a NOTIFY_ALL command, all threads should return + //from do_timed_wait function. Decrement wait count. + unlock_enter_mut = 1 == detail::atomic_dec32((boost::uint32_t*)&m_num_waiters); + //Check if this is the last thread of notify_all waiters + //Only the last thread will release the interprocess_mutex + if(unlock_enter_mut){ + detail::atomic_cas32((boost::uint32_t*)&m_command, SLEEP, NOTIFY_ALL); + } + break; + } + } + } + + //Unlock the enter interprocess_mutex if it is a single notification, if this is + //the last notified thread in a notify_all or a timeout has occurred + if(unlock_enter_mut){ + m_enter_mut.unlock(); + } + + //Lock external again before returning from the method + mut.lock(); + return !timed_out; +} + +} //namespace interprocess +} // namespace boost diff --git a/win32/include/boost/interprocess/sync/emulation/interprocess_mutex.hpp b/win32/include/boost/interprocess/sync/emulation/interprocess_mutex.hpp new file mode 100755 index 000000000..36dc4e621 --- /dev/null +++ b/win32/include/boost/interprocess/sync/emulation/interprocess_mutex.hpp @@ -0,0 +1,77 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include + +namespace boost { + +namespace interprocess { + +inline interprocess_mutex::interprocess_mutex() + : m_s(0) +{ + //Note that this class is initialized to zero. + //So zeroed memory can be interpreted as an + //initialized mutex +} + +inline interprocess_mutex::~interprocess_mutex() +{ + //Trivial destructor +} + +inline void interprocess_mutex::lock(void) +{ + do{ + boost::uint32_t prev_s = detail::atomic_cas32((boost::uint32_t*)&m_s, 1, 0); + + if (m_s == 1 && prev_s == 0){ + break; + } + // relinquish current timeslice + detail::thread_yield(); + }while (true); +} + +inline bool interprocess_mutex::try_lock(void) +{ + boost::uint32_t prev_s = detail::atomic_cas32((boost::uint32_t*)&m_s, 1, 0); + return m_s == 1 && prev_s == 0; +} + +inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time) +{ + //Obtain current count and target time + boost::posix_time::ptime now = microsec_clock::universal_time(); + + if(now >= abs_time) return false; + + do{ + if(this->try_lock()){ + break; + } + now = microsec_clock::universal_time(); + + if(now >= abs_time){ + return false; + } + // relinquish current time slice + detail::thread_yield(); + }while (true); + + return true; +} + +inline void interprocess_mutex::unlock(void) +{ detail::atomic_cas32((boost::uint32_t*)&m_s, 0, 1); } + +} //namespace interprocess { + +} //namespace boost { diff --git a/win32/include/boost/interprocess/sync/emulation/interprocess_recursive_mutex.hpp b/win32/include/boost/interprocess/sync/emulation/interprocess_recursive_mutex.hpp new file mode 100755 index 000000000..bec57bd58 --- /dev/null +++ b/win32/include/boost/interprocess/sync/emulation/interprocess_recursive_mutex.hpp @@ -0,0 +1,108 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// Parts of the pthread code come from Boost Threads code: +// +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001-2003 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +namespace boost { + +namespace interprocess { + +inline interprocess_recursive_mutex::interprocess_recursive_mutex() + : m_nLockCount(0), m_nOwner(detail::get_invalid_thread_id()){} + +inline interprocess_recursive_mutex::~interprocess_recursive_mutex(){} + +inline void interprocess_recursive_mutex::lock() +{ + detail::OS_thread_id_t th_id = detail::get_current_thread_id(); + if(detail::equal_thread_id(th_id, m_nOwner)){ + if((unsigned int)(m_nLockCount+1) == 0){ + //Overflow, throw an exception + throw interprocess_exception(); + } + ++m_nLockCount; + } + else{ + m_mutex.lock(); + m_nOwner = th_id; + m_nLockCount = 1; + } +} + +inline bool interprocess_recursive_mutex::try_lock() +{ + detail::OS_thread_id_t th_id = detail::get_current_thread_id(); + if(detail::equal_thread_id(th_id, m_nOwner)) { // we own it + if((unsigned int)(m_nLockCount+1) == 0){ + //Overflow, throw an exception + throw interprocess_exception(); + } + ++m_nLockCount; + return true; + } + if(m_mutex.try_lock()){ + m_nOwner = th_id; + m_nLockCount = 1; + return true; + } + return false; +} + +inline bool interprocess_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time) +{ + detail::OS_thread_id_t th_id = detail::get_current_thread_id(); + if(detail::equal_thread_id(th_id, m_nOwner)) { // we own it + if((unsigned int)(m_nLockCount+1) == 0){ + //Overflow, throw an exception + throw interprocess_exception(); + } + ++m_nLockCount; + return true; + } + if(m_mutex.timed_lock(abs_time)){ + m_nOwner = th_id; + m_nLockCount = 1; + return true; + } + return false; +} + +inline void interprocess_recursive_mutex::unlock() +{ + assert(detail::equal_thread_id(detail::get_current_thread_id(), m_nOwner)); + --m_nLockCount; + if(!m_nLockCount){ + m_nOwner = detail::get_invalid_thread_id(); + m_mutex.unlock(); + } +} + +} //namespace interprocess { + +} //namespace boost { + diff --git a/win32/include/boost/interprocess/sync/emulation/interprocess_semaphore.hpp b/win32/include/boost/interprocess/sync/emulation/interprocess_semaphore.hpp new file mode 100755 index 000000000..3cc93450f --- /dev/null +++ b/win32/include/boost/interprocess/sync/emulation/interprocess_semaphore.hpp @@ -0,0 +1,71 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +namespace boost { +namespace interprocess { + +inline interprocess_semaphore::~interprocess_semaphore() +{} + +inline interprocess_semaphore::interprocess_semaphore(int initialCount) + : m_mut(), m_cond(), m_count(initialCount) +{} + +inline void interprocess_semaphore::post() +{ + scoped_lock lock(m_mut); + if(m_count == 0){ + m_cond.notify_one(); + } + ++m_count; +} + +inline void interprocess_semaphore::wait() +{ + scoped_lock lock(m_mut); + while(m_count == 0){ + m_cond.wait(lock); + } + --m_count; +} + +inline bool interprocess_semaphore::try_wait() +{ + scoped_lock lock(m_mut); + if(m_count == 0){ + return false; + } + --m_count; + return true; +} + +inline bool interprocess_semaphore::timed_wait(const boost::posix_time::ptime &abs_time) +{ + scoped_lock lock(m_mut); + while(m_count == 0){ + if(!m_cond.timed_wait(lock, abs_time)) + return m_count != 0; + } + --m_count; + return true; +} +/* +inline int interprocess_semaphore::get_count() const +{ + scoped_lock lock(m_mut); + return count; +}*/ + +} //namespace interprocess { +} //namespace boost { diff --git a/win32/include/boost/interprocess/sync/emulation/named_creation_functor.hpp b/win32/include/boost/interprocess/sync/emulation/named_creation_functor.hpp new file mode 100755 index 000000000..85e4b1e01 --- /dev/null +++ b/win32/include/boost/interprocess/sync/emulation/named_creation_functor.hpp @@ -0,0 +1,68 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP +#define BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP + +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace detail { + +struct named_creation_functor_no_arg{}; + +template +class named_creation_functor +{ + typedef named_creation_functor_no_arg no_arg_t; + public: + named_creation_functor(detail::create_enum_t type, Arg arg = Arg()) + : m_creation_type(type), m_arg(arg){} + + template + void construct(void *address, typename enable_if_c::value>::type * = 0) const + { new(address)T; } + + template + void construct(void *address, typename enable_if_c::value>::type * = 0) const + { new(address)T(m_arg); } + + bool operator()(void *address, std::size_t, bool created) const + { + switch(m_creation_type){ + case detail::DoOpen: + return true; + break; + case detail::DoCreate: + case detail::DoOpenOrCreate: + if(created){ + construct(address); + } + return true; + break; + + default: + return false; + break; + } + } + private: + detail::create_enum_t m_creation_type; + Arg m_arg; +}; + +} //namespace detail { +} //namespace interprocess { +} //namespace boost { + +#endif //BOOST_INTERPROCESS_SYNC_NAMED_CREATION_FUNCTOR_HPP diff --git a/win32/include/boost/interprocess/sync/file_lock.hpp b/win32/include/boost/interprocess/sync/file_lock.hpp new file mode 100755 index 000000000..3f0bcae05 --- /dev/null +++ b/win32/include/boost/interprocess/sync/file_lock.hpp @@ -0,0 +1,266 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_FILE_LOCK_HPP +#define BOOST_INTERPROCESS_FILE_LOCK_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a class that wraps file locking capabilities. + +namespace boost { +namespace interprocess { + +//!A file lock, is a mutual exclusion utility similar to a mutex using a +//!file. A file lock has sharable and exclusive locking capabilities and +//!can be used with scoped_lock and sharable_lock classes. +//!A file lock can't guarantee synchronization between threads of the same +//!process so just use file locks to synchronize threads from different processes. +class file_lock +{ + /// @cond + //Non-copyable + file_lock(); + file_lock(const file_lock &); + file_lock &operator=(const file_lock &); + /// @endcond + public: + //!Opens a file lock. Throws interprocess_exception if the file does not + //!exist or there are no operating system resources. + file_lock(const char *name); + + //!Closes a file lock. Does not throw. + ~file_lock(); + + //Exclusive locking + + //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, + //! and if another thread has exclusive, or sharable ownership of + //! the mutex, it waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! without waiting. If no other thread has exclusive, or sharable + //! ownership of the mutex this succeeds. + //!Returns: If it can acquire exclusive ownership immediately returns true. + //! If it has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! waiting if necessary until no other thread has has exclusive, or sharable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock(); + + //Sharable locking + + //!Effects: The calling thread tries to obtain sharable ownership of the mutex, + //! and if another thread has exclusive ownership of the mutex, waits until + //! it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! without waiting. If no other thread has has exclusive ownership of the + //! mutex this succeeds. + //!Returns: If it can acquire sharable ownership immediately returns true. If it + //! has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! waiting if necessary until no other thread has has exclusive ownership of + //! the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock_sharable(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_sharable(); + /// @cond + private: + file_handle_t m_file_hnd; + + bool timed_acquire_file_lock + (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time) + { + //Obtain current count and target time + boost::posix_time::ptime now = microsec_clock::universal_time(); + using namespace boost::detail; + + if(now >= abs_time) return false; + + do{ + if(!detail::try_acquire_file_lock(hnd, acquired)) + return false; + + if(acquired) + return true; + else{ + now = microsec_clock::universal_time(); + + if(now >= abs_time){ + acquired = false; + return true; + } + // relinquish current time slice + detail::thread_yield(); + } + }while (true); + } + + bool timed_acquire_file_lock_sharable + (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time) + { + //Obtain current count and target time + boost::posix_time::ptime now = microsec_clock::universal_time(); + using namespace boost::detail; + + if(now >= abs_time) return false; + + do{ + if(!detail::try_acquire_file_lock_sharable(hnd, acquired)) + return false; + + if(acquired) + return true; + else{ + now = microsec_clock::universal_time(); + + if(now >= abs_time){ + acquired = false; + return true; + } + // relinquish current time slice + detail::thread_yield(); + } + }while (true); + } + /// @endcond +}; + +inline file_lock::file_lock(const char *name) +{ + m_file_hnd = detail::open_existing_file(name); + + if(m_file_hnd == detail::invalid_file()){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +inline file_lock::~file_lock() +{ + if(m_file_hnd != detail::invalid_file()){ + detail::close_file(m_file_hnd); + m_file_hnd = detail::invalid_file(); + } +} + +inline void file_lock::lock() +{ + if(!detail::acquire_file_lock(m_file_hnd)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +inline bool file_lock::try_lock() +{ + bool result; + if(!detail::try_acquire_file_lock(m_file_hnd, result)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } + return result; +} + +inline bool file_lock::timed_lock(const boost::posix_time::ptime &abs_time) +{ + bool result; + if(!this->timed_acquire_file_lock(m_file_hnd, result, abs_time)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } + return result; +} + +inline void file_lock::unlock() +{ + if(!detail::release_file_lock(m_file_hnd)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +inline void file_lock::lock_sharable() +{ + if(!detail::acquire_file_lock_sharable(m_file_hnd)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +inline bool file_lock::try_lock_sharable() +{ + bool result; + if(!detail::try_acquire_file_lock_sharable(m_file_hnd, result)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } + return result; +} + +inline bool file_lock::timed_lock_sharable(const boost::posix_time::ptime &abs_time) +{ + bool result; + if(!this->timed_acquire_file_lock_sharable(m_file_hnd, result, abs_time)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } + return result; +} + +inline void file_lock::unlock_sharable() +{ + if(!detail::release_file_lock_sharable(m_file_hnd)){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +} //namespace interprocess { + +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_FILE_LOCK_HPP diff --git a/win32/include/boost/interprocess/sync/interprocess_barrier.hpp b/win32/include/boost/interprocess/sync/interprocess_barrier.hpp new file mode 100755 index 000000000..b8bab2bdc --- /dev/null +++ b/win32/include/boost/interprocess/sync/interprocess_barrier.hpp @@ -0,0 +1,111 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// barrier is a modified version of Boost Threads barrier +// +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2002-2003 +// David Moore, William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. + +#ifndef BOOST_INTERPROCESS_BARRIER_HPP +#define BOOST_INTERPROCESS_BARRIER_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED && defined BOOST_INTERPROCESS_POSIX_BARRIERS +# include +# include +# include +# define BOOST_INTERPROCESS_USE_POSIX +#else +# include +# include +# include +# include +# define BOOST_INTERPROCESS_USE_GENERIC_EMULATION +#endif + +# include + +namespace boost { +namespace interprocess { + +//!An object of class barrier is a synchronization primitive that +//!can be placed in shared memory used to cause a set of threads from +//!different processes to wait until they each perform a certain +//!function or each reach a particular point in their execution. +class barrier +{ + public: + //!Constructs a barrier object that will cause count threads + //!to block on a call to wait(). + barrier(unsigned int count); + + //!Destroys *this. If threads are still executing their wait() + //!operations, the behavior for these threads is undefined. + ~barrier(); + + //!Effects: Wait until N threads call wait(), where N equals the count + //!provided to the constructor for the barrier object. + //!Note that if the barrier is destroyed before wait() can return, + //!the behavior is undefined. + //!Returns: Exactly one of the N threads will receive a return value + //!of true, the others will receive a value of false. Precisely which + //!thread receives the return value of true will be implementation-defined. + //!Applications can use this value to designate one thread as a leader that + //!will take a certain action, and the other threads emerging from the barrier + //!can wait for that action to take place. + bool wait(); + + /// @cond + private: + #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION) + interprocess_mutex m_mutex; + interprocess_condition m_cond; + unsigned int m_threshold; + unsigned int m_count; + unsigned int m_generation; + #else //#if defined BOOST_INTERPROCESS_USE_POSIX + pthread_barrier_t m_barrier; + #endif//#if defined BOOST_INTERPROCESS_USE_POSIX + /// @endcond +}; + +} // namespace interprocess +} // namespace boost + + +#ifdef BOOST_INTERPROCESS_USE_GENERIC_EMULATION +# undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION +# include +#endif + +#ifdef BOOST_INTERPROCESS_USE_POSIX +# undef BOOST_INTERPROCESS_USE_POSIX +# include +#endif + +#include + +#endif diff --git a/win32/include/boost/interprocess/sync/interprocess_condition.hpp b/win32/include/boost/interprocess/sync/interprocess_condition.hpp new file mode 100755 index 000000000..8b51a063d --- /dev/null +++ b/win32/include/boost/interprocess/sync/interprocess_condition.hpp @@ -0,0 +1,169 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_CONDITION_HPP +#define BOOST_INTERPROCESS_CONDITION_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED + #include + #include + #include + #define BOOST_INTERPROCESS_USE_POSIX +#else + #include + #include + #include + #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION +#endif + +//!\file +//!Describes process-shared variables interprocess_condition class + +namespace boost { + +namespace posix_time +{ class ptime; } + +namespace interprocess { + +class named_condition; + +//!This class is a condition variable that can be placed in shared memory or +//!memory mapped files. +class interprocess_condition +{ + /// @cond + //Non-copyable + interprocess_condition(const interprocess_condition &); + interprocess_condition &operator=(const interprocess_condition &); + friend class named_condition; + /// @endcond + public: + //!Constructs a interprocess_condition. On error throws interprocess_exception. + interprocess_condition(); + + //!Destroys *this + //!liberating system resources. + ~interprocess_condition(); + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect. + void notify_one(); + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all(); + + //!Releases the lock on the interprocess_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template + void wait(L& lock) + { + if (!lock) + throw lock_exception(); + do_wait(*lock.mutex()); + } + + //!The same as: + //!while (!pred()) wait(lock) + template + void wait(L& lock, Pr pred) + { + if (!lock) + throw lock_exception(); + + while (!pred()) + do_wait(*lock.mutex()); + } + + //!Releases the lock on the interprocess_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), or until time abs_time is reached, + //!and then reacquires the lock. + //!Returns: false if time abs_time is reached, otherwise true. + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) + { + if (!lock) + throw lock_exception(); + + return do_timed_wait(abs_time, *lock.mutex()); + } + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) + { + if (!lock) + throw lock_exception(); + + while (!pred()){ + if (!do_timed_wait(abs_time, *lock.mutex())) + return pred(); + } + + return true; + } + + /// @cond + private: + void do_wait(interprocess_mutex &mut); + + bool do_timed_wait(const boost::posix_time::ptime &abs_time, interprocess_mutex &mut); + + #if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION) + enum { SLEEP = 0, NOTIFY_ONE, NOTIFY_ALL }; + interprocess_mutex m_enter_mut; + interprocess_mutex m_check_mut; + volatile boost::uint32_t m_command; + volatile boost::uint32_t m_num_waiters; + bool do_timed_wait(bool tout_enabled, const boost::posix_time::ptime &abs_time, interprocess_mutex &mut); + void notify(boost::uint32_t command); + #elif defined(BOOST_INTERPROCESS_USE_POSIX) + pthread_cond_t m_condition; + #endif + /// @endcond +}; + +} //namespace interprocess + +} // namespace boost + +#ifdef BOOST_INTERPROCESS_USE_GENERIC_EMULATION +# undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION +# include +#endif + +#ifdef BOOST_INTERPROCESS_USE_POSIX +# undef BOOST_INTERPROCESS_USE_POSIX +# include +#endif + +#include + +#endif // BOOST_INTERPROCESS_CONDITION_HPP diff --git a/win32/include/boost/interprocess/sync/interprocess_mutex.hpp b/win32/include/boost/interprocess/sync/interprocess_mutex.hpp new file mode 100755 index 000000000..0989c76b7 --- /dev/null +++ b/win32/include/boost/interprocess/sync/interprocess_mutex.hpp @@ -0,0 +1,133 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// Parts of the pthread code come from Boost Threads code. +// +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001-2003 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MUTEX_HPP +#define BOOST_INTERPROCESS_MUTEX_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include + +#if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED + #include + #include + #include + #define BOOST_INTERPROCESS_USE_POSIX +#else + #include + #include + #include + #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION +#endif + +//!\file +//!Describes a mutex class that can be placed in memory shared by +//!several processes. + +namespace boost { +namespace interprocess { + +class interprocess_condition; + +//!Wraps a interprocess_mutex that can be placed in shared memory and can be +//!shared between processes. Allows timed lock tries +class interprocess_mutex +{ + /// @cond + //Non-copyable + interprocess_mutex(const interprocess_mutex &); + interprocess_mutex &operator=(const interprocess_mutex &); + friend class interprocess_condition; + /// @endcond + public: + + //!Constructor. + //!Throws interprocess_exception on error. + interprocess_mutex(); + + //!Destructor. If any process uses the mutex after the destructor is called + //!the result is undefined. Does not throw. + ~interprocess_mutex(); + + //!Effects: The calling thread tries to obtain ownership of the mutex, and + //! if another thread has ownership of the mutex, it waits until it can + //! obtain the ownership. If a thread takes ownership of the mutex the + //! mutex must be unlocked by the same mutex. + //!Throws: interprocess_exception on error. + void lock(); + + //!Effects: The calling thread tries to obtain ownership of the mutex, and + //! if another thread has ownership of the mutex returns immediately. + //!Returns: If the thread acquires ownership of the mutex, returns true, if + //! the another thread has ownership of the mutex, returns false. + //!Throws: interprocess_exception on error. + bool try_lock(); + + //!Effects: The calling thread will try to obtain exclusive ownership of the + //! mutex if it can do so in until the specified time is reached. If the + //! mutex supports recursive locking, the mutex must be unlocked the same + //! number of times it is locked. + //!Returns: If the thread acquires ownership of the mutex, returns true, if + //! the timeout expires returns false. + //!Throws: interprocess_exception on error. + bool timed_lock(const boost::posix_time::ptime &abs_time); + + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Throws: interprocess_exception on error. + void unlock(); + /// @cond + private: + + #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION) + volatile boost::uint32_t m_s; + #elif defined(BOOST_INTERPROCESS_USE_POSIX) + pthread_mutex_t m_mut; + #endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + /// @endcond +}; + +} //namespace interprocess { + +} //namespace boost { + +#ifdef BOOST_INTERPROCESS_USE_GENERIC_EMULATION +# undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION +# include +#endif + +#ifdef BOOST_INTERPROCESS_USE_POSIX +# undef BOOST_INTERPROCESS_USE_POSIX +# include +#endif + +#include + +#endif //BOOST_INTERPROCESS_MUTEX_HPP diff --git a/win32/include/boost/interprocess/sync/interprocess_recursive_mutex.hpp b/win32/include/boost/interprocess/sync/interprocess_recursive_mutex.hpp new file mode 100755 index 000000000..4aaad4467 --- /dev/null +++ b/win32/include/boost/interprocess/sync/interprocess_recursive_mutex.hpp @@ -0,0 +1,131 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// Parts of the pthread code come from Boost Threads code: +// +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001-2003 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP +#define BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include + +#if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED && defined BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES + #include + #include + #include + #define BOOST_INTERPROCESS_USE_POSIX +#else + #include + #include + #include + #include + #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION +#endif + +//!\file +//!Describes interprocess_recursive_mutex and shared_recursive_try_mutex classes + +namespace boost { + +namespace interprocess { + +//!Wraps a interprocess_mutex that can be placed in shared memory and can be +//!shared between processes. Allows several locking calls by the same +//!process. Allows timed lock tries +class interprocess_recursive_mutex +{ + /// @cond + //Non-copyable + interprocess_recursive_mutex(const interprocess_recursive_mutex &); + interprocess_recursive_mutex &operator=(const interprocess_recursive_mutex &); + /// @endcond + public: + //!Constructor. + //!Throws interprocess_exception on error. + interprocess_recursive_mutex(); + + //!Destructor. If any process uses the mutex after the destructor is called + //!the result is undefined. Does not throw. + ~interprocess_recursive_mutex(); + + //!Effects: The calling thread tries to obtain ownership of the mutex, and + //! if another thread has ownership of the mutex, it waits until it can + //! obtain the ownership. If a thread takes ownership of the mutex the + //! mutex must be unlocked by the same mutex. The mutex must be unlocked + //! the same number of times it is locked. + //!Throws: interprocess_exception on error. + void lock(void); + + //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex + //!is already locked, returns true when success. The mutex must be unlocked + //!the same number of times it is locked. + //!Throws: interprocess_exception if a severe error is found + bool try_lock(void); + + //!Tries to lock the interprocess_mutex, if interprocess_mutex can't be locked before + //!abs_time time, returns false. The mutex must be unlocked + //! the same number of times it is locked. + //!Throws: interprocess_exception if a severe error is found + bool timed_lock(const boost::posix_time::ptime &abs_time); + + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //! If the mutex supports recursive locking, the mutex must be unlocked the + //! same number of times it is locked. + //!Throws: interprocess_exception on error. + void unlock(void); + /// @cond + private: + #if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION) + interprocess_mutex m_mutex; + unsigned int m_nLockCount; + detail::OS_thread_id_t m_nOwner; + #else //#if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION) + pthread_mutex_t m_mut; + #endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32) + /// @endcond +}; + +} //namespace interprocess { + +} //namespace boost { + +#ifdef BOOST_INTERPROCESS_USE_GENERIC_EMULATION +# undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION +# include +#endif + +#ifdef BOOST_INTERPROCESS_USE_POSIX +# undef BOOST_INTERPROCESS_USE_POSIX +# include +#endif + +#include + +#endif //BOOST_INTERPROCESS_RECURSIVE_MUTEX_HPP diff --git a/win32/include/boost/interprocess/sync/interprocess_semaphore.hpp b/win32/include/boost/interprocess/sync/interprocess_semaphore.hpp new file mode 100755 index 000000000..f9f6dcdca --- /dev/null +++ b/win32/include/boost/interprocess/sync/interprocess_semaphore.hpp @@ -0,0 +1,119 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_SEMAPHORE_HPP +#define BOOST_INTERPROCESS_SEMAPHORE_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include + +#if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED &&\ + defined BOOST_INTERPROCESS_POSIX_SEMAPHORES + #include //O_CREAT, O_*... + #include //close + #include //std::string + #include //sem_* family, SEM_VALUE_MAX + #include //mode_t, S_IRWXG, S_IRWXO, S_IRWXU, + #include + #define BOOST_INTERPROCESS_USE_POSIX +#else + #include + #include + #include + #include + #include + #define BOOST_INTERPROCESS_USE_GENERIC_EMULATION +#endif + +//!\file +//!Describes a interprocess_semaphore class for inter-process synchronization + +namespace boost { + +namespace interprocess { + +//!Wraps a interprocess_semaphore that can be placed in shared memory and can be +//!shared between processes. Allows timed lock tries +class interprocess_semaphore +{ + /// @cond + //Non-copyable + interprocess_semaphore(const interprocess_semaphore &); + interprocess_semaphore &operator=(const interprocess_semaphore &); + /// @endcond + public: + //!Creates a interprocess_semaphore with the given initial count. + //!interprocess_exception if there is an error.*/ + interprocess_semaphore(int initialCount); + + //!Destroys the interprocess_semaphore. + //!Does not throw + ~interprocess_semaphore(); + + //!Increments the interprocess_semaphore count. If there are processes/threads blocked waiting + //!for the interprocess_semaphore, then one of these processes will return successfully from + //!its wait function. If there is an error an interprocess_exception exception is thrown. + void post(); + + //!Decrements the interprocess_semaphore. If the interprocess_semaphore value is not greater than zero, + //!then the calling process/thread blocks until it can decrement the counter. + //!If there is an error an interprocess_exception exception is thrown. + void wait(); + + //!Decrements the interprocess_semaphore if the interprocess_semaphore's value is greater than zero + //!and returns true. If the value is not greater than zero returns false. + //!If there is an error an interprocess_exception exception is thrown. + bool try_wait(); + + //!Decrements the interprocess_semaphore if the interprocess_semaphore's value is greater + //!than zero and returns true. Otherwise, waits for the interprocess_semaphore + //!to the posted or the timeout expires. If the timeout expires, the + //!function returns false. If the interprocess_semaphore is posted the function + //!returns true. If there is an error throws sem_exception + bool timed_wait(const boost::posix_time::ptime &abs_time); + + //!Returns the interprocess_semaphore count +// int get_count() const; + /// @cond + private: + #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION) + interprocess_mutex m_mut; + interprocess_condition m_cond; + int m_count; + #else + detail::semaphore_wrapper m_sem; + #endif //#if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION) + /// @endcond +}; + +} //namespace interprocess { + +} //namespace boost { + +#ifdef BOOST_INTERPROCESS_USE_GENERIC_EMULATION +# undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION +# include +#endif + +#ifdef BOOST_INTERPROCESS_USE_POSIX +# undef BOOST_INTERPROCESS_USE_POSIX +# include +#endif + +#include + +#endif //BOOST_INTERPROCESS_SEMAPHORE_HPP diff --git a/win32/include/boost/interprocess/sync/interprocess_upgradable_mutex.hpp b/win32/include/boost/interprocess/sync/interprocess_upgradable_mutex.hpp new file mode 100755 index 000000000..ffeb98522 --- /dev/null +++ b/win32/include/boost/interprocess/sync/interprocess_upgradable_mutex.hpp @@ -0,0 +1,646 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP +#define BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include + + +//!\file +//!Describes interprocess_upgradable_mutex class + +namespace boost { +namespace interprocess { + +//!Wraps a interprocess_upgradable_mutex that can be placed in shared memory and can be +//!shared between processes. Allows timed lock tries +class interprocess_upgradable_mutex +{ + //Non-copyable + interprocess_upgradable_mutex(const interprocess_upgradable_mutex &); + interprocess_upgradable_mutex &operator=(const interprocess_upgradable_mutex &); + + friend class interprocess_condition; + public: + + //!Constructs the upgradable lock. + //!Throws interprocess_exception on error. + interprocess_upgradable_mutex(); + + //!Destroys the upgradable lock. + //!Does not throw. + ~interprocess_upgradable_mutex(); + + //Exclusive locking + + //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, + //! and if another thread has exclusive, sharable or upgradable ownership of + //! the mutex, it waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! without waiting. If no other thread has exclusive, sharable or upgradable + //! ownership of the mutex this succeeds. + //!Returns: If it can acquire exclusive ownership immediately returns true. + //! If it has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! waiting if necessary until no other thread has has exclusive, sharable or + //! upgradable ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock(); + + //Sharable locking + + //!Effects: The calling thread tries to obtain sharable ownership of the mutex, + //! and if another thread has exclusive or upgradable ownership of the mutex, + //! waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! without waiting. If no other thread has has exclusive or upgradable ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire sharable ownership immediately returns true. If it + //! has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! waiting if necessary until no other thread has has exclusive or upgradable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock_sharable(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_sharable(); + + //Upgradable locking + + //!Effects: The calling thread tries to obtain upgradable ownership of the mutex, + //! and if another thread has exclusive or upgradable ownership of the mutex, + //! waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock_upgradable(); + + //!Effects: The calling thread tries to acquire upgradable ownership of the mutex + //! without waiting. If no other thread has has exclusive or upgradable ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire upgradable ownership immediately returns true. + //! If it has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock_upgradable(); + + //!Effects: The calling thread tries to acquire upgradable ownership of the mutex + //! waiting if necessary until no other thread has has exclusive or upgradable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The calling thread releases the upgradable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable(); + + //Demotions + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The thread atomically releases exclusive ownership and acquires + //! upgradable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_and_lock_upgradable(); + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The thread atomically releases exclusive ownership and acquires + //! sharable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_and_lock_sharable(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and acquires + //! sharable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable_and_lock_sharable(); + + //Promotions + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and acquires + //! exclusive ownership. This operation will block until all threads with + //! sharable ownership release their sharable lock. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable_and_lock(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and tries to + //! acquire exclusive ownership. This operation will fail if there are threads + //! with sharable ownership, but it will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + bool try_unlock_upgradable_and_lock(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and tries to acquire + //! exclusive ownership, waiting if necessary until abs_time. This operation will + //! fail if there are threads with sharable ownership or timeout reaches, but it + //! will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. */ + bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The thread atomically releases sharable ownership and tries to acquire + //! exclusive ownership. This operation will fail if there are threads with sharable + //! or upgradable ownership, but it will maintain sharable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + bool try_unlock_sharable_and_lock(); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The thread atomically releases sharable ownership and tries to acquire + //! upgradable ownership. This operation will fail if there are threads with sharable + //! or upgradable ownership, but it will maintain sharable ownership. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + bool try_unlock_sharable_and_lock_upgradable(); + + /// @cond + private: + typedef scoped_lock scoped_lock_t; + + //Pack all the control data in a word to be able + //to use atomic instructions in the future + struct control_word_t + { + unsigned exclusive_in : 1; + unsigned upgradable_in : 1; + unsigned num_upr_shar : sizeof(unsigned)*CHAR_BIT-2; + } m_ctrl; + + interprocess_mutex m_mut; + interprocess_condition m_first_gate; + interprocess_condition m_second_gate; + + private: + //Rollback structures for exceptions or failure return values + struct exclusive_rollback + { + exclusive_rollback(control_word_t &ctrl + ,interprocess_condition &first_gate) + : mp_ctrl(&ctrl), m_first_gate(first_gate) + {} + + void release() + { mp_ctrl = 0; } + + ~exclusive_rollback() + { + if(mp_ctrl){ + mp_ctrl->exclusive_in = 0; + m_first_gate.notify_all(); + } + } + control_word_t *mp_ctrl; + interprocess_condition &m_first_gate; + }; + + struct upgradable_to_exclusive_rollback + { + upgradable_to_exclusive_rollback(control_word_t &ctrl) + : mp_ctrl(&ctrl) + {} + + void release() + { mp_ctrl = 0; } + + ~upgradable_to_exclusive_rollback() + { + if(mp_ctrl){ + //Recover upgradable lock + mp_ctrl->upgradable_in = 1; + ++mp_ctrl->num_upr_shar; + //Execute the second half of exclusive locking + mp_ctrl->exclusive_in = 0; + } + } + control_word_t *mp_ctrl; + }; + + template + struct base_constants_t + { + static const unsigned max_readers + = ~(unsigned(3) << (sizeof(unsigned)*CHAR_BIT-2)); + }; + typedef base_constants_t<0> constants; + /// @endcond +}; + +/// @cond + +template +const unsigned interprocess_upgradable_mutex::base_constants_t::max_readers; + +inline interprocess_upgradable_mutex::interprocess_upgradable_mutex() +{ + this->m_ctrl.exclusive_in = 0; + this->m_ctrl.upgradable_in = 0; + this->m_ctrl.num_upr_shar = 0; +} + +inline interprocess_upgradable_mutex::~interprocess_upgradable_mutex() +{} + +inline void interprocess_upgradable_mutex::lock() +{ + scoped_lock_t lock(m_mut); + + //The exclusive lock must block in the first gate + //if an exclusive or upgradable lock has been acquired + while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ + this->m_first_gate.wait(lock); + } + + //Mark that exclusive lock has been acquired + this->m_ctrl.exclusive_in = 1; + + //Prepare rollback + exclusive_rollback rollback(this->m_ctrl, this->m_first_gate); + + //Now wait until all readers are gone + while (this->m_ctrl.num_upr_shar){ + this->m_second_gate.wait(lock); + } + rollback.release(); +} + +inline bool interprocess_upgradable_mutex::try_lock() +{ + scoped_lock_t lock(m_mut, try_to_lock); + + //If we can't lock or any has there is any exclusive, upgradable + //or sharable mark return false; + if(!lock.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.num_upr_shar){ + return false; + } + this->m_ctrl.exclusive_in = 1; + return true; +} + +inline bool interprocess_upgradable_mutex::timed_lock + (const boost::posix_time::ptime &abs_time) +{ + scoped_lock_t lock(m_mut, abs_time); + if(!lock.owns()) return false; + + //The exclusive lock must block in the first gate + //if an exclusive or upgradable lock has been acquired + while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ + if(!this->m_first_gate.timed_wait(lock, abs_time)) + return !(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in); + } + + //Mark that exclusive lock has been acquired + this->m_ctrl.exclusive_in = 1; + + //Prepare rollback + exclusive_rollback rollback(this->m_ctrl, this->m_first_gate); + + //Now wait until all readers are gone + while (this->m_ctrl.num_upr_shar){ + if(!this->m_second_gate.timed_wait(lock, abs_time)){ + return !(this->m_ctrl.num_upr_shar); + } + } + rollback.release(); + return true; +} + +inline void interprocess_upgradable_mutex::unlock() +{ + scoped_lock_t lock(m_mut); + this->m_ctrl.exclusive_in = 0; + this->m_first_gate.notify_all(); +} + +//Upgradable locking + +inline void interprocess_upgradable_mutex::lock_upgradable() +{ + scoped_lock_t lock(m_mut); + + //The upgradable lock must block in the first gate + //if an exclusive or upgradable lock has been acquired + //or there are too many sharable locks + while(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + this->m_first_gate.wait(lock); + } + + //Mark that upgradable lock has been acquired + //And add upgradable to the sharable count + this->m_ctrl.upgradable_in = 1; + ++this->m_ctrl.num_upr_shar; +} + +inline bool interprocess_upgradable_mutex::try_lock_upgradable() +{ + scoped_lock_t lock(m_mut, try_to_lock); + + //The upgradable lock must fail + //if an exclusive or upgradable lock has been acquired + //or there are too many sharable locks + if(!lock.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + return false; + } + + //Mark that upgradable lock has been acquired + //And add upgradable to the sharable count + this->m_ctrl.upgradable_in = 1; + ++this->m_ctrl.num_upr_shar; + return true; +} + +inline bool interprocess_upgradable_mutex::timed_lock_upgradable + (const boost::posix_time::ptime &abs_time) +{ + scoped_lock_t lock(m_mut, abs_time); + if(!lock.owns()) return false; + + //The upgradable lock must block in the first gate + //if an exclusive or upgradable lock has been acquired + //or there are too many sharable locks + while(this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + if(!this->m_first_gate.timed_wait(lock, abs_time)){ + return!(this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in + || this->m_ctrl.num_upr_shar == constants::max_readers); + } + } + + //Mark that upgradable lock has been acquired + //And add upgradable to the sharable count + this->m_ctrl.upgradable_in = 1; + ++this->m_ctrl.num_upr_shar; + return true; +} + +inline void interprocess_upgradable_mutex::unlock_upgradable() +{ + scoped_lock_t lock(m_mut); + //Mark that upgradable lock has been acquired + //And add upgradable to the sharable count + this->m_ctrl.upgradable_in = 0; + --this->m_ctrl.num_upr_shar; + this->m_first_gate.notify_all(); +} + +//Sharable locking + +inline void interprocess_upgradable_mutex::lock_sharable() +{ + scoped_lock_t lock(m_mut); + + //The sharable lock must block in the first gate + //if an exclusive lock has been acquired + //or there are too many sharable locks + while(this->m_ctrl.exclusive_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + this->m_first_gate.wait(lock); + } + + //Increment sharable count + ++this->m_ctrl.num_upr_shar; +} + +inline bool interprocess_upgradable_mutex::try_lock_sharable() +{ + scoped_lock_t lock(m_mut, try_to_lock); + + //The sharable lock must fail + //if an exclusive lock has been acquired + //or there are too many sharable locks + if(!lock.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + return false; + } + + //Increment sharable count + ++this->m_ctrl.num_upr_shar; + return true; +} + +inline bool interprocess_upgradable_mutex::timed_lock_sharable + (const boost::posix_time::ptime &abs_time) +{ + scoped_lock_t lock(m_mut, abs_time); + if(!lock.owns()) return false; + + //The sharable lock must block in the first gate + //if an exclusive lock has been acquired + //or there are too many sharable locks + while (this->m_ctrl.exclusive_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + if(!this->m_first_gate.timed_wait(lock, abs_time)){ + return!(this->m_ctrl.exclusive_in + || this->m_ctrl.num_upr_shar == constants::max_readers); + } + } + + //Increment sharable count + ++this->m_ctrl.num_upr_shar; + return true; +} + +inline void interprocess_upgradable_mutex::unlock_sharable() +{ + scoped_lock_t lock(m_mut); + //Decrement sharable count + --this->m_ctrl.num_upr_shar; + if (this->m_ctrl.num_upr_shar == 0){ + this->m_second_gate.notify_one(); + } + //Check if there are blocked sharables because of + //there were too many sharables + else if(this->m_ctrl.num_upr_shar == (constants::max_readers-1)){ + this->m_first_gate.notify_all(); + } +} + +//Downgrading + +inline void interprocess_upgradable_mutex::unlock_and_lock_upgradable() +{ + scoped_lock_t lock(m_mut); + //Unmark it as exclusive + this->m_ctrl.exclusive_in = 0; + //Mark it as upgradable + this->m_ctrl.upgradable_in = 1; + //The sharable count should be 0 so increment it + this->m_ctrl.num_upr_shar = 1; + //Notify readers that they can enter + m_first_gate.notify_all(); +} + +inline void interprocess_upgradable_mutex::unlock_and_lock_sharable() +{ + scoped_lock_t lock(m_mut); + //Unmark it as exclusive + this->m_ctrl.exclusive_in = 0; + //The sharable count should be 0 so increment it + this->m_ctrl.num_upr_shar = 1; + //Notify readers that they can enter + m_first_gate.notify_all(); +} + +inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock_sharable() +{ + scoped_lock_t lock(m_mut); + //Unmark it as upgradable (we don't have to decrement count) + this->m_ctrl.upgradable_in = 0; + //Notify readers/upgradable that they can enter + m_first_gate.notify_all(); +} + +//Upgrading + +inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock() +{ + scoped_lock_t lock(m_mut); + //Simulate unlock_upgradable() without + //notifying sharables. + this->m_ctrl.upgradable_in = 0; + --this->m_ctrl.num_upr_shar; + //Execute the second half of exclusive locking + this->m_ctrl.exclusive_in = 1; + + //Prepare rollback + upgradable_to_exclusive_rollback rollback(m_ctrl); + + while (this->m_ctrl.num_upr_shar){ + this->m_second_gate.wait(lock); + } + rollback.release(); +} + +inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock() +{ + scoped_lock_t lock(m_mut, try_to_lock); + //Check if there are no readers + if(!lock.owns() + || this->m_ctrl.num_upr_shar != 1){ + return false; + } + //Now unlock upgradable and mark exclusive + this->m_ctrl.upgradable_in = 0; + --this->m_ctrl.num_upr_shar; + this->m_ctrl.exclusive_in = 1; + return true; +} + +inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock + (const boost::posix_time::ptime &abs_time) +{ + scoped_lock_t lock(m_mut, abs_time); + if(!lock.owns()) return false; + + //Simulate unlock_upgradable() without + //notifying sharables. + this->m_ctrl.upgradable_in = 0; + --this->m_ctrl.num_upr_shar; + //Execute the second half of exclusive locking + this->m_ctrl.exclusive_in = 1; + + //Prepare rollback + upgradable_to_exclusive_rollback rollback(m_ctrl); + + while (this->m_ctrl.num_upr_shar){ + if(!this->m_second_gate.timed_wait(lock, abs_time)){ + return !(this->m_ctrl.num_upr_shar); + } + } + rollback.release(); + return true; +} + +inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock() +{ + scoped_lock_t lock(m_mut, try_to_lock); + + //If we can't lock or any has there is any exclusive, upgradable + //or sharable mark return false; + if(!lock.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in + || this->m_ctrl.num_upr_shar != 1){ + return false; + } + this->m_ctrl.exclusive_in = 1; + this->m_ctrl.num_upr_shar = 0; + return true; +} + +inline bool interprocess_upgradable_mutex::try_unlock_sharable_and_lock_upgradable() +{ + scoped_lock_t lock(m_mut, try_to_lock); + + //The upgradable lock must fail + //if an exclusive or upgradable lock has been acquired + if(!lock.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in){ + return false; + } + + //Mark that upgradable lock has been acquired + this->m_ctrl.upgradable_in = 1; + return true; +} + +/// @endcond + +} //namespace interprocess { +} //namespace boost { + + +#include + +#endif //BOOST_INTERPROCESS_UPGRADABLE_MUTEX_HPP diff --git a/win32/include/boost/interprocess/sync/lock_options.hpp b/win32/include/boost/interprocess/sync/lock_options.hpp new file mode 100755 index 000000000..d1929c825 --- /dev/null +++ b/win32/include/boost/interprocess/sync/lock_options.hpp @@ -0,0 +1,57 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_LOCK_OPTIONS_HPP +#define BOOST_INTERPROCESS_LOCK_OPTIONS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +//!\file +//!Describes the lock options with associated with interprocess_mutex lock constructors. + +namespace boost { + +namespace posix_time +{ class ptime; } + +namespace interprocess { + +namespace detail{ + //!Type to indicate to a mutex lock constructor that must not lock the mutex. + struct defer_lock_type{}; + //!Type to indicate to a mutex lock constructor that must try to lock the mutex. + struct try_to_lock_type {}; + //!Type to indicate to a mutex lock constructor that the mutex is already locked. + struct accept_ownership_type{}; +} //namespace detail{ + +//!An object indicating that the locking +//!must be deferred. +static const detail::defer_lock_type defer_lock = detail::defer_lock_type(); + +//!An object indicating that the a try_lock() +//!operation must be executed. +static const detail::try_to_lock_type try_to_lock = detail::try_to_lock_type(); + +//!An object indicating that the ownership of lockable +//!object must be accepted by the new owner. +static const detail::accept_ownership_type accept_ownership = detail::accept_ownership_type(); + +} // namespace interprocess { +} // namespace boost{ + +#include + +#endif // BOOST_INTERPROCESS_LOCK_OPTIONS_HPP diff --git a/win32/include/boost/interprocess/sync/mutex_family.hpp b/win32/include/boost/interprocess/sync/mutex_family.hpp new file mode 100755 index 000000000..e2191b830 --- /dev/null +++ b/win32/include/boost/interprocess/sync/mutex_family.hpp @@ -0,0 +1,56 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_MUTEX_FAMILY_HPP +#define BOOST_INTERPROCESS_MUTEX_FAMILY_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include + +//!\file +//!Describes a shared interprocess_mutex family fit algorithm used to allocate objects in shared memory. + +namespace boost { + +namespace interprocess { + +//!Describes interprocess_mutex family to use with Interprocess framework +//!based on boost::interprocess synchronization objects. +struct mutex_family +{ + typedef boost::interprocess::interprocess_mutex mutex_type; + typedef boost::interprocess::interprocess_recursive_mutex recursive_mutex_type; +}; + +//!Describes interprocess_mutex family to use with Interprocess frameworks +//!based on null operation synchronization objects. +struct null_mutex_family +{ + typedef boost::interprocess::null_mutex mutex_type; + typedef boost::interprocess::null_mutex recursive_mutex_type; +}; + +} //namespace interprocess { + +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTERPROCESS_MUTEX_FAMILY_HPP + + diff --git a/win32/include/boost/interprocess/sync/named_condition.hpp b/win32/include/boost/interprocess/sync/named_condition.hpp new file mode 100755 index 000000000..b5e70491e --- /dev/null +++ b/win32/include/boost/interprocess/sync/named_condition.hpp @@ -0,0 +1,344 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_NAMED_CONDITION_HPP +#define BOOST_INTERPROCESS_NAMED_CONDITION_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES +#include +#include +#endif + + +//!\file +//!Describes process-shared variables interprocess_condition class + +namespace boost { +namespace interprocess { + +/// @cond +namespace detail{ class interprocess_tester; } +/// @endcond + +//! A global condition variable that can be created by name. +//! This condition variable is designed to work with named_mutex and +//! can't be placed in shared memory or memory mapped files. +class named_condition +{ + /// @cond + //Non-copyable + named_condition(); + named_condition(const named_condition &); + named_condition &operator=(const named_condition &); + /// @endcond + public: + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + named_condition(create_only_t create_only, const char *name); + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!named_condition(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!named_condition(open_only_t, ... ) + //!Does not throw + named_condition(open_or_create_t open_or_create, const char *name); + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_condition(open_only_t open_only, const char *name); + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_condition(); + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect.*/ + void notify_one(); + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all(); + + //!Releases the lock on the interprocess_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template + void wait(L& lock); + + //!The same as: + //!while (!pred()) wait(lock) + template + void wait(L& lock, Pr pred); + + //!Releases the lock on the interprocess_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), or until time abs_time is reached, + //!and then reacquires the lock. + //!Returns: false if time abs_time is reached, otherwise true. + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time); + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred); + + //!Erases a named condition from the system. + //!Returns false on error. Never throws. + static bool remove(const char *name); + + /// @cond + private: + + struct condition_holder + { + interprocess_condition cond_; + //If named_mutex is implemented using semaphores + //we need to store an additional mutex + #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + interprocess_mutex mutex_; + #endif + }; + + interprocess_condition *condition() const + { return &static_cast(m_shmem.get_user_address())->cond_; } + + template + class lock_inverter + { + Lock &l_; + public: + lock_inverter(Lock &l) + : l_(l) + {} + void lock() { l_.unlock(); } + void unlock() { l_.lock(); } + }; + + #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + interprocess_mutex *mutex() const + { return &static_cast(m_shmem.get_user_address())->mutex_; } + + template + void do_wait(Lock& lock) + { + //lock internal before unlocking external to avoid race with a notifier + scoped_lock internal_lock(*this->mutex()); + lock_inverter inverted_lock(lock); + scoped_lock > external_unlock(inverted_lock); + + //unlock internal first to avoid deadlock with near simultaneous waits + scoped_lock internal_unlock; + internal_lock.swap(internal_unlock); + this->condition()->wait(internal_unlock); + } + + template + bool do_timed_wait(Lock& lock, const boost::posix_time::ptime &abs_time) + { + //lock internal before unlocking external to avoid race with a notifier + scoped_lock internal_lock(*this->mutex(), abs_time); + if(!internal_lock) return false; + lock_inverter inverted_lock(lock); + scoped_lock > external_unlock(inverted_lock); + + //unlock internal first to avoid deadlock with near simultaneous waits + scoped_lock internal_unlock; + internal_lock.swap(internal_unlock); + return this->condition()->timed_wait(internal_unlock, abs_time); + } + #endif + + friend class detail::interprocess_tester; + void dont_close_on_destruction(); + + detail::managed_open_or_create_impl m_shmem; + + template friend class boost::interprocess::detail::named_creation_functor; + typedef detail::named_creation_functor construct_func_t; + /// @endcond +}; + +/// @cond + +inline named_condition::~named_condition() +{} + +inline named_condition::named_condition(create_only_t, const char *name) + : m_shmem (create_only + ,name + ,sizeof(condition_holder) + + detail::managed_open_or_create_impl:: + ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(detail::DoCreate)) +{} + +inline named_condition::named_condition(open_or_create_t, const char *name) + : m_shmem (open_or_create + ,name + ,sizeof(condition_holder) + + detail::managed_open_or_create_impl:: + ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(detail::DoOpenOrCreate)) +{} + +inline named_condition::named_condition(open_only_t, const char *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(detail::DoOpen)) +{} + +inline void named_condition::dont_close_on_destruction() +{ detail::interprocess_tester::dont_close_on_destruction(m_shmem); } + +#if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + +inline void named_condition::notify_one() +{ + scoped_lock internal_lock(*this->mutex()); + this->condition()->notify_one(); +} + +inline void named_condition::notify_all() +{ + scoped_lock internal_lock(*this->mutex()); + this->condition()->notify_all(); +} + +template +inline void named_condition::wait(L& lock) +{ + if (!lock) + throw lock_exception(); + this->do_wait(lock); +} + +template +inline void named_condition::wait(L& lock, Pr pred) +{ + if (!lock) + throw lock_exception(); + while (!pred()) + this->do_wait(lock); +} + +template +inline bool named_condition::timed_wait + (L& lock, const boost::posix_time::ptime &abs_time) +{ + if (!lock) + throw lock_exception(); + return this->do_timed_wait(lock, abs_time); +} + +template +inline bool named_condition::timed_wait + (L& lock, const boost::posix_time::ptime &abs_time, Pr pred) +{ + if (!lock) + throw lock_exception(); + + while (!pred()){ + if(!this->do_timed_wait(lock, abs_time)){ + return pred(); + } + } + return true; +} + +#else + +inline void named_condition::notify_one() +{ this->condition()->notify_one(); } + +inline void named_condition::notify_all() +{ this->condition()->notify_all(); } + +template +inline void named_condition::wait(L& lock) +{ + if (!lock) + throw lock_exception(); + this->condition()->do_wait(*lock.mutex()->mutex()); +} + +template +inline void named_condition::wait(L& lock, Pr pred) +{ + if (!lock) + throw lock_exception(); + + while (!pred()) + this->condition()->do_wait(*lock.mutex()->mutex()); +} + +template +inline bool named_condition::timed_wait + (L& lock, const boost::posix_time::ptime &abs_time) +{ + if (!lock) + throw lock_exception(); + return this->condition()->do_timed_wait(abs_time, *lock.mutex()->mutex()); +} + +template +inline bool named_condition::timed_wait + (L& lock, const boost::posix_time::ptime &abs_time, Pr pred) +{ + if (!lock) + throw lock_exception(); + + while (!pred()){ + if (!this->condition()->do_timed_wait(abs_time, *lock.mutex()->mutex())) + return pred(); + } + + return true; +} + +#endif + +inline bool named_condition::remove(const char *name) +{ return shared_memory_object::remove(name); } + +/// @endcond + +} //namespace interprocess +} //namespace boost + +#include + +#endif // BOOST_INTERPROCESS_NAMED_CONDITION_HPP diff --git a/win32/include/boost/interprocess/sync/named_mutex.hpp b/win32/include/boost/interprocess/sync/named_mutex.hpp new file mode 100755 index 000000000..e0336463f --- /dev/null +++ b/win32/include/boost/interprocess/sync/named_mutex.hpp @@ -0,0 +1,220 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_NAMED_MUTEX_HPP +#define BOOST_INTERPROCESS_NAMED_MUTEX_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + #include +#else + #include + #include + #include + #include +#endif + +//!\file +//!Describes a named mutex class for inter-process synchronization + +namespace boost { +namespace interprocess { + +class named_condition; + +//!A mutex with a global name, so it can be found from different +//!processes. This mutex can't be placed in shared memory, and +//!each process should have it's own named_mutex. +class named_mutex +{ + /// @cond + + //Non-copyable + named_mutex(); + named_mutex(const named_mutex &); + named_mutex &operator=(const named_mutex &); + friend class named_condition; + /// @endcond + + public: + //!Creates a global interprocess_mutex with a name. + //!Throws interprocess_exception on error. + named_mutex(create_only_t create_only, const char *name); + + //!Opens or creates a global mutex with a name. + //!If the mutex is created, this call is equivalent to + //!named_mutex(create_only_t, ... ) + //!If the mutex is already created, this call is equivalent + //!named_mutex(open_only_t, ... ) + //!Does not throw + named_mutex(open_or_create_t open_or_create, const char *name); + + //!Opens a global mutex with a name if that mutex is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_mutex(open_only_t open_only, const char *name); + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_mutex(); + + //!Unlocks a previously locked + //!interprocess_mutex. + void unlock(); + + //!Locks interprocess_mutex, sleeps when interprocess_mutex is already locked. + //!Throws interprocess_exception if a severe error is found + void lock(); + + //!Tries to lock the interprocess_mutex, returns false when interprocess_mutex + //!is already locked, returns true when success. + //!Throws interprocess_exception if a severe error is found + bool try_lock(); + + //!Tries to lock the interprocess_mutex until time abs_time, + //!Returns false when timeout expires, returns true when locks. + //!Throws interprocess_exception if a severe error is found + bool timed_lock(const boost::posix_time::ptime &abs_time); + + //!Erases a named mutex from the system. + //!Returns false on error. Never throws. + static bool remove(const char *name); + + /// @cond + private: + friend class detail::interprocess_tester; + void dont_close_on_destruction(); + + #if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + detail::named_semaphore_wrapper m_sem; + #else + interprocess_mutex *mutex() const + { return static_cast(m_shmem.get_user_address()); } + + detail::managed_open_or_create_impl m_shmem; + typedef detail::named_creation_functor construct_func_t; + #endif + /// @endcond +}; + +/// @cond + +#if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + +inline named_mutex::named_mutex(create_only_t, const char *name) + : m_sem(detail::DoCreate, name, read_write, 1) +{} + +inline named_mutex::named_mutex(open_or_create_t, const char *name) + : m_sem(detail::DoOpenOrCreate, name, read_write, 1) +{} + +inline named_mutex::named_mutex(open_only_t, const char *name) + : m_sem(detail::DoOpen, name, read_write, 1) +{} + +inline void named_mutex::dont_close_on_destruction() +{ detail::interprocess_tester::dont_close_on_destruction(m_sem); } + +inline named_mutex::~named_mutex() +{} + +inline void named_mutex::lock() +{ m_sem.wait(); } + +inline void named_mutex::unlock() +{ m_sem.post(); } + +inline bool named_mutex::try_lock() +{ return m_sem.try_wait(); } + +inline bool named_mutex::timed_lock(const boost::posix_time::ptime &abs_time) +{ return m_sem.timed_wait(abs_time); } + +inline bool named_mutex::remove(const char *name) +{ return detail::named_semaphore_wrapper::remove(name); } + +#else + +inline void named_mutex::dont_close_on_destruction() +{ detail::interprocess_tester::dont_close_on_destruction(m_shmem); } + +inline named_mutex::~named_mutex() +{} + +inline named_mutex::named_mutex(create_only_t, const char *name) + : m_shmem (create_only + ,name + ,sizeof(interprocess_mutex) + + detail::managed_open_or_create_impl:: + ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(detail::DoCreate)) +{} + +inline named_mutex::named_mutex(open_or_create_t, const char *name) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_mutex) + + detail::managed_open_or_create_impl:: + ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(detail::DoOpenOrCreate)) +{} + +inline named_mutex::named_mutex(open_only_t, const char *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(detail::DoOpen)) +{} + +inline void named_mutex::lock() +{ this->mutex()->lock(); } + +inline void named_mutex::unlock() +{ this->mutex()->unlock(); } + +inline bool named_mutex::try_lock() +{ return this->mutex()->try_lock(); } + +inline bool named_mutex::timed_lock(const boost::posix_time::ptime &abs_time) +{ return this->mutex()->timed_lock(abs_time); } + +inline bool named_mutex::remove(const char *name) +{ return shared_memory_object::remove(name); } + +#endif + +/// @endcond + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_NAMED_MUTEX_HPP diff --git a/win32/include/boost/interprocess/sync/named_recursive_mutex.hpp b/win32/include/boost/interprocess/sync/named_recursive_mutex.hpp new file mode 100755 index 000000000..b35689597 --- /dev/null +++ b/win32/include/boost/interprocess/sync/named_recursive_mutex.hpp @@ -0,0 +1,171 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP +#define BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a named named_recursive_mutex class for inter-process synchronization + +namespace boost { +namespace interprocess { + +/// @cond +namespace detail{ class interprocess_tester; } +/// @endcond + +//!A recursive mutex with a global name, so it can be found from different +//!processes. This mutex can't be placed in shared memory, and +//!each process should have it's own named_recursive_mutex. +class named_recursive_mutex +{ + /// @cond + //Non-copyable + named_recursive_mutex(); + named_recursive_mutex(const named_recursive_mutex &); + named_recursive_mutex &operator=(const named_recursive_mutex &); + /// @endcond + public: + + //!Creates a global recursive_mutex with a name. + //!If the recursive_mutex can't be created throws interprocess_exception + named_recursive_mutex(create_only_t create_only, const char *name); + + //!Opens or creates a global recursive_mutex with a name. + //!If the recursive_mutex is created, this call is equivalent to + //!named_recursive_mutex(create_only_t, ... ) + //!If the recursive_mutex is already created, this call is equivalent + //!named_recursive_mutex(open_only_t, ... ) + //!Does not throw + named_recursive_mutex(open_or_create_t open_or_create, const char *name); + + //!Opens a global recursive_mutex with a name if that recursive_mutex is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_recursive_mutex(open_only_t open_only, const char *name); + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_recursive_mutex(); + + //!Unlocks a previously locked + //!named_recursive_mutex. + void unlock(); + + //!Locks named_recursive_mutex, sleeps when named_recursive_mutex is already locked. + //!Throws interprocess_exception if a severe error is found. + void lock(); + + //!Tries to lock the named_recursive_mutex, returns false when named_recursive_mutex + //!is already locked, returns true when success. + //!Throws interprocess_exception if a severe error is found. + bool try_lock(); + + //!Tries to lock the named_recursive_mutex until time abs_time, + //!Returns false when timeout expires, returns true when locks. + //!Throws interprocess_exception if a severe error is found + bool timed_lock(const boost::posix_time::ptime &abs_time); + + //!Erases a named recursive mutex + //!from the system + static bool remove(const char *name); + + /// @cond + private: + friend class detail::interprocess_tester; + void dont_close_on_destruction(); + + interprocess_recursive_mutex *mutex() const + { return static_cast(m_shmem.get_user_address()); } + + detail::managed_open_or_create_impl m_shmem; + typedef detail::named_creation_functor construct_func_t; + /// @endcond +}; + +/// @cond + +inline named_recursive_mutex::~named_recursive_mutex() +{} + +inline void named_recursive_mutex::dont_close_on_destruction() +{ detail::interprocess_tester::dont_close_on_destruction(m_shmem); } + +inline named_recursive_mutex::named_recursive_mutex(create_only_t, const char *name) + : m_shmem (create_only + ,name + ,sizeof(interprocess_recursive_mutex) + + detail::managed_open_or_create_impl:: + ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(detail::DoCreate)) +{} + +inline named_recursive_mutex::named_recursive_mutex(open_or_create_t, const char *name) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_recursive_mutex) + + detail::managed_open_or_create_impl:: + ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(detail::DoOpenOrCreate)) +{} + +inline named_recursive_mutex::named_recursive_mutex(open_only_t, const char *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(detail::DoOpen)) +{} + +inline void named_recursive_mutex::lock() +{ this->mutex()->lock(); } + +inline void named_recursive_mutex::unlock() +{ this->mutex()->unlock(); } + +inline bool named_recursive_mutex::try_lock() +{ return this->mutex()->try_lock(); } + +inline bool named_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time) +{ return this->mutex()->timed_lock(abs_time); } + +inline bool named_recursive_mutex::remove(const char *name) +{ return shared_memory_object::remove(name); } + +/// @endcond + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_NAMED_RECURSIVE_MUTEX_HPP diff --git a/win32/include/boost/interprocess/sync/named_semaphore.hpp b/win32/include/boost/interprocess/sync/named_semaphore.hpp new file mode 100755 index 000000000..977b88eee --- /dev/null +++ b/win32/include/boost/interprocess/sync/named_semaphore.hpp @@ -0,0 +1,228 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP +#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES) +#include +#else +#include +#include +#include +#include +#endif + +//!\file +//!Describes a named semaphore class for inter-process synchronization + +namespace boost { +namespace interprocess { + +//!A semaphore with a global name, so it can be found from different +//!processes. Allows several resource sharing patterns and efficient +//!acknowledgment mechanisms. +class named_semaphore +{ + /// @cond + + //Non-copyable + named_semaphore(); + named_semaphore(const named_semaphore &); + named_semaphore &operator=(const named_semaphore &); + /// @endcond + + public: + //!Creates a global semaphore with a name, and an initial count. + //!If the semaphore can't be created throws interprocess_exception + named_semaphore(create_only_t, const char *name, int initialCount); + + //!Opens or creates a global semaphore with a name, and an initial count. + //!If the semaphore is created, this call is equivalent to + //!named_semaphore(create_only_t, ...) + //!If the semaphore is already created, this call is equivalent to + //!named_semaphore(open_only_t, ... ) + //!and initialCount is ignored. + named_semaphore(open_or_create_t, const char *name, int initialCount); + + //!Opens a global semaphore with a name if that semaphore is previously. + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_semaphore(open_only_t, const char *name); + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_semaphore(); + + //!Increments the semaphore count. If there are processes/threads blocked waiting + //!for the semaphore, then one of these processes will return successfully from + //!its wait function. If there is an error an interprocess_exception exception is thrown. + void post(); + + //!Decrements the semaphore. If the semaphore value is not greater than zero, + //!then the calling process/thread blocks until it can decrement the counter. + //!If there is an error an interprocess_exception exception is thrown. + void wait(); + + //!Decrements the semaphore if the semaphore's value is greater than zero + //!and returns true. If the value is not greater than zero returns false. + //!If there is an error an interprocess_exception exception is thrown. + bool try_wait(); + + //!Decrements the semaphore if the semaphore's value is greater + //!than zero and returns true. Otherwise, waits for the semaphore + //!to the posted or the timeout expires. If the timeout expires, the + //!function returns false. If the semaphore is posted the function + //!returns true. If there is an error throws sem_exception + bool timed_wait(const boost::posix_time::ptime &abs_time); + + //!Erases a named semaphore from the system. + //!Returns false on error. Never throws. + static bool remove(const char *name); + + /// @cond + private: + friend class detail::interprocess_tester; + void dont_close_on_destruction(); + + #if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES) + detail::named_semaphore_wrapper m_sem; + #else + interprocess_semaphore *semaphore() const + { return static_cast(m_shmem.get_user_address()); } + + detail::managed_open_or_create_impl m_shmem; + typedef detail::named_creation_functor construct_func_t; + #endif + /// @endcond +}; + +/// @cond + +#if defined(BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES) + +inline named_semaphore::named_semaphore + (create_only_t, const char *name, int initialCount) + : m_sem(detail::DoCreate, name, read_write, initialCount) +{} + +inline named_semaphore::named_semaphore + (open_or_create_t, const char *name, int initialCount) + : m_sem(detail::DoOpenOrCreate, name, read_write, initialCount) +{} + +inline named_semaphore::named_semaphore + (open_only_t, const char *name) + : m_sem(detail::DoOpen, name, read_write, 1) +{} + +inline named_semaphore::~named_semaphore() +{} + +inline void named_semaphore::dont_close_on_destruction() +{ detail::interprocess_tester::dont_close_on_destruction(m_sem); } + +inline void named_semaphore::wait() +{ m_sem.wait(); } + +inline void named_semaphore::post() +{ m_sem.post(); } + +inline bool named_semaphore::try_wait() +{ return m_sem.try_wait(); } + +inline bool named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time) +{ return m_sem.timed_wait(abs_time); } + +inline bool named_semaphore::remove(const char *name) +{ return detail::named_semaphore_wrapper::remove(name); } + +#else + +inline named_semaphore::~named_semaphore() +{} + +inline void named_semaphore::dont_close_on_destruction() +{ detail::interprocess_tester::dont_close_on_destruction(m_shmem); } + +inline named_semaphore::named_semaphore + (create_only_t, const char *name, int initialCount) + : m_shmem (create_only + ,name + ,sizeof(interprocess_semaphore) + + detail::managed_open_or_create_impl:: + ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(detail::DoCreate, initialCount)) +{} + +inline named_semaphore::named_semaphore + (open_or_create_t, const char *name, int initialCount) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_semaphore) + + detail::managed_open_or_create_impl:: + ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(detail::DoOpenOrCreate, initialCount)) +{} + +inline named_semaphore::named_semaphore + (open_only_t, const char *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(detail::DoOpen, 0)) +{} + +inline void named_semaphore::post() +{ semaphore()->post(); } + +inline void named_semaphore::wait() +{ semaphore()->wait(); } + +inline bool named_semaphore::try_wait() +{ return semaphore()->try_wait(); } + +inline bool named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time) +{ return semaphore()->timed_wait(abs_time); } + +inline bool named_semaphore::remove(const char *name) +{ return shared_memory_object::remove(name); } + +#endif + +/// @endcond + +} //namespace interprocess { +} //namespace boost { + + +#include + +#endif //BOOST_INTERPROCESS_NAMED_SEMAPHORE_HPP diff --git a/win32/include/boost/interprocess/sync/named_upgradable_mutex.hpp b/win32/include/boost/interprocess/sync/named_upgradable_mutex.hpp new file mode 100755 index 000000000..2aef55825 --- /dev/null +++ b/win32/include/boost/interprocess/sync/named_upgradable_mutex.hpp @@ -0,0 +1,351 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_named_upgradable_mutex_HPP +#define BOOST_INTERPROCESS_named_upgradable_mutex_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a named upgradable mutex class for inter-process synchronization + +namespace boost { +namespace interprocess { + +/// @cond +namespace detail{ class interprocess_tester; } +/// @endcond + +class named_condition; + +//!A upgradable mutex with a global name, so it can be found from different +//!processes. This mutex can't be placed in shared memory, and +//!each process should have it's own named upgradable mutex. +class named_upgradable_mutex +{ + /// @cond + //Non-copyable + named_upgradable_mutex(); + named_upgradable_mutex(const named_upgradable_mutex &); + named_upgradable_mutex &operator=(const named_upgradable_mutex &); + friend class named_condition; + /// @endcond + public: + + //!Creates a global upgradable mutex with a name. + //!If the upgradable mutex can't be created throws interprocess_exception + named_upgradable_mutex(create_only_t create_only, const char *name); + + //!Opens or creates a global upgradable mutex with a name, and an initial count. + //!If the upgradable mutex is created, this call is equivalent to + //!named_upgradable_mutex(create_only_t, ...) + //!If the upgradable mutex is already created, this call is equivalent to + //!named_upgradable_mutex(open_only_t, ... ). + named_upgradable_mutex(open_or_create_t open_or_create, const char *name); + + //!Opens a global upgradable mutex with a name if that upgradable mutex + //!is previously. + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_upgradable_mutex(open_only_t open_only, const char *name); + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_upgradable_mutex(); + + //Exclusive locking + + //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, + //! and if another thread has exclusive, sharable or upgradable ownership of + //! the mutex, it waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! without waiting. If no other thread has exclusive, sharable or upgradable + //! ownership of the mutex this succeeds. + //!Returns: If it can acquire exclusive ownership immediately returns true. + //! If it has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! waiting if necessary until no other thread has has exclusive, sharable or + //! upgradable ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock(); + + //Sharable locking + + //!Effects: The calling thread tries to obtain sharable ownership of the mutex, + //! and if another thread has exclusive or upgradable ownership of the mutex, + //! waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! without waiting. If no other thread has has exclusive or upgradable ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire sharable ownership immediately returns true. If it + //! has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! waiting if necessary until no other thread has has exclusive or upgradable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock_sharable(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_sharable(); + + //Upgradable locking + + //!Effects: The calling thread tries to obtain upgradable ownership of the mutex, + //! and if another thread has exclusive or upgradable ownership of the mutex, + //! waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock_upgradable(); + + //!Effects: The calling thread tries to acquire upgradable ownership of the mutex + //! without waiting. If no other thread has has exclusive or upgradable ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire upgradable ownership immediately returns true. + //! If it has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock_upgradable(); + + //!Effects: The calling thread tries to acquire upgradable ownership of the mutex + //! waiting if necessary until no other thread has has exclusive or upgradable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock_upgradable(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The calling thread releases the upgradable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable(); + + //Demotions + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The thread atomically releases exclusive ownership and acquires + //! upgradable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_and_lock_upgradable(); + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The thread atomically releases exclusive ownership and acquires + //! sharable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_and_lock_sharable(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and acquires + //! sharable ownership. This operation is non-blocking. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable_and_lock_sharable(); + + //Promotions + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and acquires + //! exclusive ownership. This operation will block until all threads with + //! sharable ownership releas it. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_upgradable_and_lock(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and tries to + //! acquire exclusive ownership. This operation will fail if there are threads + //! with sharable ownership, but it will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + bool try_unlock_upgradable_and_lock(); + + //!Precondition: The thread must have upgradable ownership of the mutex. + //!Effects: The thread atomically releases upgradable ownership and tries to acquire + //! exclusive ownership, waiting if necessary until abs_time. This operation will + //! fail if there are threads with sharable ownership or timeout reaches, but it + //! will maintain upgradable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The thread atomically releases sharable ownership and tries to acquire + //! exclusive ownership. This operation will fail if there are threads with sharable + //! or upgradable ownership, but it will maintain sharable ownership. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. + bool try_unlock_sharable_and_lock(); + + bool try_unlock_sharable_and_lock_upgradable(); + + //!Erases a named upgradable mutex from the system. + //!Returns false on error. Never throws. + static bool remove(const char *name); + + /// @cond + private: + friend class detail::interprocess_tester; + void dont_close_on_destruction(); + + interprocess_upgradable_mutex *mutex() const + { return static_cast(m_shmem.get_user_address()); } + + detail::managed_open_or_create_impl m_shmem; + typedef detail::named_creation_functor construct_func_t; + /// @endcond +}; + +/// @cond + +inline named_upgradable_mutex::~named_upgradable_mutex() +{} + +inline named_upgradable_mutex::named_upgradable_mutex + (create_only_t, const char *name) + : m_shmem (create_only + ,name + ,sizeof(interprocess_upgradable_mutex) + + detail::managed_open_or_create_impl:: + ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(detail::DoCreate)) +{} + +inline named_upgradable_mutex::named_upgradable_mutex + (open_or_create_t, const char *name) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_upgradable_mutex) + + detail::managed_open_or_create_impl:: + ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(detail::DoOpenOrCreate)) +{} + +inline named_upgradable_mutex::named_upgradable_mutex + (open_only_t, const char *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(detail::DoOpen)) +{} + +inline void named_upgradable_mutex::dont_close_on_destruction() +{ detail::interprocess_tester::dont_close_on_destruction(m_shmem); } + +inline void named_upgradable_mutex::lock() +{ this->mutex()->lock(); } + +inline void named_upgradable_mutex::unlock() +{ this->mutex()->unlock(); } + +inline bool named_upgradable_mutex::try_lock() +{ return this->mutex()->try_lock(); } + +inline bool named_upgradable_mutex::timed_lock + (const boost::posix_time::ptime &abs_time) +{ return this->mutex()->timed_lock(abs_time); } + +inline void named_upgradable_mutex::lock_upgradable() +{ this->mutex()->lock_upgradable(); } + +inline void named_upgradable_mutex::unlock_upgradable() +{ this->mutex()->unlock_upgradable(); } + +inline bool named_upgradable_mutex::try_lock_upgradable() +{ return this->mutex()->try_lock_upgradable(); } + +inline bool named_upgradable_mutex::timed_lock_upgradable + (const boost::posix_time::ptime &abs_time) +{ return this->mutex()->timed_lock_upgradable(abs_time); } + +inline void named_upgradable_mutex::lock_sharable() +{ this->mutex()->lock_sharable(); } + +inline void named_upgradable_mutex::unlock_sharable() +{ this->mutex()->unlock_sharable(); } + +inline bool named_upgradable_mutex::try_lock_sharable() +{ return this->mutex()->try_lock_sharable(); } + +inline bool named_upgradable_mutex::timed_lock_sharable + (const boost::posix_time::ptime &abs_time) +{ return this->mutex()->timed_lock_sharable(abs_time); } + +inline void named_upgradable_mutex::unlock_and_lock_upgradable() +{ this->mutex()->unlock_and_lock_upgradable(); } + +inline void named_upgradable_mutex::unlock_and_lock_sharable() +{ this->mutex()->unlock_and_lock_sharable(); } + +inline void named_upgradable_mutex::unlock_upgradable_and_lock_sharable() +{ this->mutex()->unlock_upgradable_and_lock_sharable(); } + +inline void named_upgradable_mutex::unlock_upgradable_and_lock() +{ this->mutex()->unlock_upgradable_and_lock(); } + +inline bool named_upgradable_mutex::try_unlock_upgradable_and_lock() +{ return this->mutex()->try_unlock_upgradable_and_lock(); } + +inline bool named_upgradable_mutex::timed_unlock_upgradable_and_lock + (const boost::posix_time::ptime &abs_time) +{ return this->mutex()->timed_unlock_upgradable_and_lock(abs_time); } + +inline bool named_upgradable_mutex::try_unlock_sharable_and_lock() +{ return this->mutex()->try_unlock_sharable_and_lock(); } + +inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable() +{ return this->mutex()->try_unlock_sharable_and_lock_upgradable(); } + +inline bool named_upgradable_mutex::remove(const char *name) +{ return shared_memory_object::remove(name); } + +/// @endcond + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_named_upgradable_mutex_HPP diff --git a/win32/include/boost/interprocess/sync/null_mutex.hpp b/win32/include/boost/interprocess/sync/null_mutex.hpp new file mode 100755 index 000000000..508272ad1 --- /dev/null +++ b/win32/include/boost/interprocess/sync/null_mutex.hpp @@ -0,0 +1,147 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_NULL_MUTEX_HPP +#define BOOST_INTERPROCESS_NULL_MUTEX_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + + +//!\file +//!Describes null_mutex classes + +namespace boost { + +namespace posix_time +{ class ptime; } + +namespace interprocess { + +//!Implements a mutex that simulates a mutex without doing any operation and +//!simulates a successful operation. +class null_mutex +{ + /// @cond + null_mutex(const null_mutex&); + null_mutex &operator= (const null_mutex&); + /// @endcond + public: + + //!Constructor. + //!Empty. + null_mutex(){} + + //!Destructor. + //!Empty. + ~null_mutex(){} + + //!Simulates a mutex lock() operation. Empty function. + void lock(){} + + //!Simulates a mutex try_lock() operation. + //!Equivalent to "return true;" + bool try_lock() + { return true; } + + //!Simulates a mutex timed_lock() operation. + //!Equivalent to "return true;" + bool timed_lock(const boost::posix_time::ptime &) + { return true; } + + //!Simulates a mutex unlock() operation. + //!Empty function. + void unlock(){} + + //!Simulates a mutex lock_sharable() operation. + //!Empty function. + void lock_sharable(){} + + //!Simulates a mutex try_lock_sharable() operation. + //!Equivalent to "return true;" + bool try_lock_sharable() + { return true; } + + //!Simulates a mutex timed_lock_sharable() operation. + //!Equivalent to "return true;" + bool timed_lock_sharable(const boost::posix_time::ptime &) + { return true; } + + //!Simulates a mutex unlock_sharable() operation. + //!Empty function. + void unlock_sharable(){} + + //!Simulates a mutex lock_upgradable() operation. + //!Empty function. + void lock_upgradable(){} + + //!Simulates a mutex try_lock_upgradable() operation. + //!Equivalent to "return true;" + bool try_lock_upgradable() + { return true; } + + //!Simulates a mutex timed_lock_upgradable() operation. + //!Equivalent to "return true;" + bool timed_lock_upgradable(const boost::posix_time::ptime &) + { return true; } + + //!Simulates a mutex unlock_upgradable() operation. + //!Empty function. + void unlock_upgradable(){} + + //!Simulates unlock_and_lock_upgradable(). + //!Empty function. + void unlock_and_lock_upgradable(){} + + //!Simulates unlock_and_lock_sharable(). + //!Empty function. + void unlock_and_lock_sharable(){} + + //!Simulates unlock_upgradable_and_lock_sharable(). + //!Empty function. + void unlock_upgradable_and_lock_sharable(){} + + //Promotions + + //!Simulates unlock_upgradable_and_lock(). + //!Empty function. + void unlock_upgradable_and_lock(){} + + //!Simulates try_unlock_upgradable_and_lock(). + //!Equivalent to "return true;" + bool try_unlock_upgradable_and_lock() + { return true; } + + //!Simulates timed_unlock_upgradable_and_lock(). + //!Equivalent to "return true;" + bool timed_unlock_upgradable_and_lock(const boost::posix_time::ptime &) + { return true; } + + //!Simulates try_unlock_sharable_and_lock(). + //!Equivalent to "return true;" + bool try_unlock_sharable_and_lock() + { return true; } + + //!Simulates try_unlock_sharable_and_lock_upgradable(). + //!Equivalent to "return true;" + bool try_unlock_sharable_and_lock_upgradable() + { return true; } +}; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_NULL_MUTEX_HPP diff --git a/win32/include/boost/interprocess/sync/posix/interprocess_barrier.hpp b/win32/include/boost/interprocess/sync/posix/interprocess_barrier.hpp new file mode 100755 index 000000000..707f6ea43 --- /dev/null +++ b/win32/include/boost/interprocess/sync/posix/interprocess_barrier.hpp @@ -0,0 +1,44 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include + +namespace boost { +namespace interprocess { + +inline barrier::barrier(unsigned int count) +{ + if (count == 0) + throw std::invalid_argument("count cannot be zero."); + detail::barrierattr_wrapper barrier_attr; + detail::barrier_initializer barrier + (m_barrier, barrier_attr, static_cast(count)); + barrier.release(); +} + +inline barrier::~barrier() +{ + int res = pthread_barrier_destroy(&m_barrier); + assert(res == 0);(void)res; +} + +inline bool barrier::wait() +{ + int res = pthread_barrier_wait(&m_barrier); + + if (res != PTHREAD_BARRIER_SERIAL_THREAD && res != 0){ + throw interprocess_exception(res); + } + return res == PTHREAD_BARRIER_SERIAL_THREAD; +} + +} //namespace interprocess { +} //namespace boost { diff --git a/win32/include/boost/interprocess/sync/posix/interprocess_condition.hpp b/win32/include/boost/interprocess/sync/posix/interprocess_condition.hpp new file mode 100755 index 000000000..63cc32dc7 --- /dev/null +++ b/win32/include/boost/interprocess/sync/posix/interprocess_condition.hpp @@ -0,0 +1,81 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include + +namespace boost { + +namespace interprocess { + +inline interprocess_condition::interprocess_condition() +{ + int res; + pthread_condattr_t cond_attr; + res = pthread_condattr_init(&cond_attr); + if(res != 0){ + throw interprocess_exception(); + } + res = pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED); + if(res != 0){ + pthread_condattr_destroy(&cond_attr); + throw interprocess_exception(res); + } + res = pthread_cond_init(&m_condition, &cond_attr); + pthread_condattr_destroy(&cond_attr); + if(res != 0){ + throw interprocess_exception(res); + } +} + +inline interprocess_condition::~interprocess_condition() +{ + int res = 0; + res = pthread_cond_destroy(&m_condition); + assert(res == 0); +} + +inline void interprocess_condition::notify_one() +{ + int res = 0; + res = pthread_cond_signal(&m_condition); + assert(res == 0); +} + +inline void interprocess_condition::notify_all() +{ + int res = 0; + res = pthread_cond_broadcast(&m_condition); + assert(res == 0); +} + +inline void interprocess_condition::do_wait(interprocess_mutex &mut) +{ + pthread_mutex_t* pmutex = &mut.m_mut; + int res = 0; + res = pthread_cond_wait(&m_condition, pmutex); + assert(res == 0); +} + +inline bool interprocess_condition::do_timed_wait + (const boost::posix_time::ptime &abs_time, interprocess_mutex &mut) +{ + timespec ts = detail::ptime_to_timespec(abs_time); + pthread_mutex_t* pmutex = &mut.m_mut; + int res = 0; + res = pthread_cond_timedwait(&m_condition, pmutex, &ts); + assert(res == 0 || res == ETIMEDOUT); + + return res != ETIMEDOUT; +} + +} //namespace interprocess + +} // namespace boost diff --git a/win32/include/boost/interprocess/sync/posix/interprocess_mutex.hpp b/win32/include/boost/interprocess/sync/posix/interprocess_mutex.hpp new file mode 100755 index 000000000..63a20eec6 --- /dev/null +++ b/win32/include/boost/interprocess/sync/posix/interprocess_mutex.hpp @@ -0,0 +1,106 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// Parts of the pthread code come from Boost Threads code: +// +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001-2003 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS +# include +#endif + +namespace boost { +namespace interprocess { + +inline interprocess_mutex::interprocess_mutex() +{ + detail::mutexattr_wrapper mut_attr; + detail::mutex_initializer mut(m_mut, mut_attr); + mut.release(); +} + +inline interprocess_mutex::~interprocess_mutex() +{ + int res = pthread_mutex_destroy(&m_mut); + assert(res == 0);(void)res; +} + +inline void interprocess_mutex::lock() +{ + if (pthread_mutex_lock(&m_mut) != 0) + throw lock_exception(); +} + +inline bool interprocess_mutex::try_lock() +{ + int res = pthread_mutex_trylock(&m_mut); + if (!(res == 0 || res == EBUSY)) + throw lock_exception(); + return res == 0; +} + +inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time) +{ + #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS + + timespec ts = detail::ptime_to_timespec(abs_time); + int res = pthread_mutex_timedlock(&m_mut, &ts); + if (res != 0 && res != ETIMEDOUT) + throw lock_exception(); + return res == 0; + + #else //BOOST_INTERPROCESS_POSIX_TIMEOUTS + + //Obtain current count and target time + boost::posix_time::ptime now = microsec_clock::universal_time(); + + if(now >= abs_time) return false; + + do{ + if(this->try_lock()){ + break; + } + now = microsec_clock::universal_time(); + + if(now >= abs_time){ + return false; + } + // relinquish current time slice + detail::thread_yield(); + }while (true); + return true; + + #endif //BOOST_INTERPROCESS_POSIX_TIMEOUTS +} + +inline void interprocess_mutex::unlock() +{ + int res = 0; + res = pthread_mutex_unlock(&m_mut); + assert(res == 0); +} + +} //namespace interprocess { +} //namespace boost { diff --git a/win32/include/boost/interprocess/sync/posix/interprocess_recursive_mutex.hpp b/win32/include/boost/interprocess/sync/posix/interprocess_recursive_mutex.hpp new file mode 100755 index 000000000..767147214 --- /dev/null +++ b/win32/include/boost/interprocess/sync/posix/interprocess_recursive_mutex.hpp @@ -0,0 +1,107 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// Parts of the pthread code come from Boost Threads code: +// +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2001-2003 +// William E. Kempf +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. William E. Kempf makes no representations +// about the suitability of this software for any purpose. +// It is provided "as is" without express or implied warranty. +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS +# include +#endif + +namespace boost { + +namespace interprocess { + +inline interprocess_recursive_mutex::interprocess_recursive_mutex() +{ + detail::mutexattr_wrapper mut_attr(true); + detail::mutex_initializer mut(m_mut, mut_attr); + mut.release(); +} + +inline interprocess_recursive_mutex::~interprocess_recursive_mutex() +{ + int res = pthread_mutex_destroy(&m_mut); + assert(res == 0);(void)res; +} + +inline void interprocess_recursive_mutex::lock() +{ + if (pthread_mutex_lock(&m_mut) != 0) + throw lock_exception(); +} + +inline bool interprocess_recursive_mutex::try_lock() +{ + int res = pthread_mutex_trylock(&m_mut); + if (!(res == 0 || res == EBUSY)) + throw lock_exception(); + return res == 0; +} + +inline bool interprocess_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time) +{ + #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS + + timespec ts = detail::ptime_to_timespec(abs_time); + int res = pthread_mutex_timedlock(&m_mut, &ts); + if (res != 0 && res != ETIMEDOUT) + throw lock_exception(); + return res == 0; + + #else //BOOST_INTERPROCESS_POSIX_TIMEOUTS + + //Obtain current count and target time + boost::posix_time::ptime now = microsec_clock::universal_time(); + + if(now >= abs_time) return false; + + do{ + if(this->try_lock()){ + break; + } + now = microsec_clock::universal_time(); + + if(now >= abs_time){ + return false; + } + // relinquish current time slice + detail::thread_yield(); + }while (true); + return true; + + #endif //BOOST_INTERPROCESS_POSIX_TIMEOUTS +} + +inline void interprocess_recursive_mutex::unlock() +{ + int res = 0; + res = pthread_mutex_unlock(&m_mut); + assert(res == 0); +} + +} //namespace interprocess { +} //namespace boost { diff --git a/win32/include/boost/interprocess/sync/posix/interprocess_semaphore.hpp b/win32/include/boost/interprocess/sync/posix/interprocess_semaphore.hpp new file mode 100755 index 000000000..ad115e7b2 --- /dev/null +++ b/win32/include/boost/interprocess/sync/posix/interprocess_semaphore.hpp @@ -0,0 +1,43 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include + +namespace boost { + +namespace interprocess { + +inline interprocess_semaphore::~interprocess_semaphore() +{} + +inline interprocess_semaphore::interprocess_semaphore(int initialCount) + : m_sem(initialCount) +{} + +inline void interprocess_semaphore::post() +{ m_sem.post(); } + +inline void interprocess_semaphore::wait() +{ m_sem.wait(); } + +inline bool interprocess_semaphore::try_wait() +{ return m_sem.try_wait(); } + +inline bool interprocess_semaphore::timed_wait(const boost::posix_time::ptime &abs_time) +{ return m_sem.timed_wait(abs_time); } +/* +inline int interprocess_semaphore::get_count() const +{ return m_sem.get_count(); } +*/ +} //namespace interprocess { + +} //namespace boost { + diff --git a/win32/include/boost/interprocess/sync/posix/pthread_helpers.hpp b/win32/include/boost/interprocess/sync/posix/pthread_helpers.hpp new file mode 100755 index 000000000..920e7e9bc --- /dev/null +++ b/win32/include/boost/interprocess/sync/posix/pthread_helpers.hpp @@ -0,0 +1,168 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP +#define BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include + +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace detail{ + + #if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED + + //!Makes pthread_mutexattr_t cleanup easy when using exceptions + struct mutexattr_wrapper + { + //!Constructor + mutexattr_wrapper(bool recursive = false) + { + if(pthread_mutexattr_init(&m_attr)!=0 || + pthread_mutexattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0 || + (recursive && + pthread_mutexattr_settype(&m_attr, PTHREAD_MUTEX_RECURSIVE)!= 0 )) + throw boost::interprocess::interprocess_exception(); + } + + //!Destructor + ~mutexattr_wrapper() { pthread_mutexattr_destroy(&m_attr); } + + //!This allows using mutexattr_wrapper as pthread_mutexattr_t + operator pthread_mutexattr_t&() { return m_attr; } + + pthread_mutexattr_t m_attr; + }; + + //!Makes pthread_condattr_t cleanup easy when using exceptions + struct condattr_wrapper + { + //!Constructor + condattr_wrapper() + { + if(pthread_condattr_init(&m_attr)!=0 || + pthread_condattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0) + throw boost::interprocess::interprocess_exception(); + } + + //!Destructor + ~condattr_wrapper() { pthread_condattr_destroy(&m_attr); } + + //!This allows using condattr_wrapper as pthread_condattr_t + operator pthread_condattr_t&(){ return m_attr; } + + pthread_condattr_t m_attr; + }; + + //!Makes initialized pthread_mutex_t cleanup easy when using exceptions + class mutex_initializer + { + public: + //!Constructor. Takes interprocess_mutex attributes to initialize the interprocess_mutex + mutex_initializer(pthread_mutex_t &mut, pthread_mutexattr_t &mut_attr) + : mp_mut(&mut) + { + if(pthread_mutex_init(mp_mut, &mut_attr) != 0) + throw boost::interprocess::interprocess_exception(); + } + + ~mutex_initializer() { if(mp_mut) pthread_mutex_destroy(mp_mut); } + + void release() {mp_mut = 0; } + + private: + pthread_mutex_t *mp_mut; + }; + + //!Makes initialized pthread_cond_t cleanup easy when using exceptions + class condition_initializer + { + public: + condition_initializer(pthread_cond_t &cond, pthread_condattr_t &cond_attr) + : mp_cond(&cond) + { + if(pthread_cond_init(mp_cond, &cond_attr)!= 0) + throw boost::interprocess::interprocess_exception(); + } + + ~condition_initializer() { if(mp_cond) pthread_cond_destroy(mp_cond); } + + void release() { mp_cond = 0; } + + private: + pthread_cond_t *mp_cond; + }; + + #endif // #if defined BOOST_INTERPROCESS_POSIX_PROCESS_SHARED + + #if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) + + //!Makes pthread_barrierattr_t cleanup easy when using exceptions + struct barrierattr_wrapper + { + //!Constructor + barrierattr_wrapper() + { + if(pthread_barrierattr_init(&m_attr)!=0 || + pthread_barrierattr_setpshared(&m_attr, PTHREAD_PROCESS_SHARED)!= 0) + throw boost::interprocess::interprocess_exception(); + } + + //!Destructor + ~barrierattr_wrapper() { pthread_barrierattr_destroy(&m_attr); } + + //!This allows using mutexattr_wrapper as pthread_barrierattr_t + operator pthread_barrierattr_t&() { return m_attr; } + + pthread_barrierattr_t m_attr; + }; + + //!Makes initialized pthread_barrier_t cleanup easy when using exceptions + class barrier_initializer + { + public: + //!Constructor. Takes barrier attributes to initialize the barrier + barrier_initializer(pthread_barrier_t &mut, + pthread_barrierattr_t &mut_attr, + int count) + : mp_barrier(&mut) + { + if(pthread_barrier_init(mp_barrier, &mut_attr, count) != 0) + throw boost::interprocess::interprocess_exception(); + } + + ~barrier_initializer() { if(mp_barrier) pthread_barrier_destroy(mp_barrier); } + + void release() {mp_barrier = 0; } + + private: + pthread_barrier_t *mp_barrier; + }; + + #endif //#if defined(BOOST_INTERPROCESS_POSIX_BARRIERS) && defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) + +}//namespace detail + +}//namespace interprocess + +}//namespace boost + +#include + +#endif //ifdef BOOST_INTERPROCESS_PTHREAD_HELPERS_HPP diff --git a/win32/include/boost/interprocess/sync/posix/ptime_to_timespec.hpp b/win32/include/boost/interprocess/sync/posix/ptime_to_timespec.hpp new file mode 100755 index 000000000..bc6d21506 --- /dev/null +++ b/win32/include/boost/interprocess/sync/posix/ptime_to_timespec.hpp @@ -0,0 +1,38 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP +#define BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP + +#include + +namespace boost { + +namespace interprocess { + +namespace detail { + +inline timespec ptime_to_timespec (const boost::posix_time::ptime &tm) +{ + const boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1)); + boost::posix_time::time_duration duration (tm - epoch); + timespec ts; + ts.tv_sec = duration.total_seconds(); + ts.tv_nsec = duration.total_nanoseconds() % 1000000000; + return ts; +} + +} //namespace detail { + +} //namespace interprocess { + +} //namespace boost { + +#endif //ifndef BOOST_INTERPROCESS_DETAIL_PTIME_TO_TIMESPEC_HPP diff --git a/win32/include/boost/interprocess/sync/posix/semaphore_wrapper.hpp b/win32/include/boost/interprocess/sync/posix/semaphore_wrapper.hpp new file mode 100755 index 000000000..1dcf9a511 --- /dev/null +++ b/win32/include/boost/interprocess/sync/posix/semaphore_wrapper.hpp @@ -0,0 +1,274 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP +#define BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP + +#include +#include +#include +#include +#include +#include +#include + +#ifdef SEM_FAILED +#define BOOST_INTERPROCESS_POSIX_SEM_FAILED SEM_FAILED +#else +#define BOOST_INTERPROCESS_POSIX_SEM_FAILED ((sem_t*)(-1)) +#endif + +#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS +#include +#else +#include +#endif + +namespace boost { +namespace interprocess { + +/// @cond +namespace detail{ class interprocess_tester; } +/// @endcond + +namespace detail { + +inline bool semaphore_open + (sem_t *&handle, detail::create_enum_t type, const char *origname, mode_t mode, + unsigned int count) +{ + std::string name; + #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES + detail::add_leading_slash(origname, name); + #else + detail::create_tmp_dir_and_get_filename(origname, name); + #endif + + //Create new mapping + int oflag = 0; + if(mode == read_only){ + oflag |= O_RDONLY; + } + else if(mode == read_write){ + oflag |= O_RDWR; + } + else{ + error_info err(mode_error); + throw interprocess_exception(err); + } + + switch(type){ + case detail::DoOpen: + //No addition + break; + case detail::DoCreate: + oflag |= (O_CREAT | O_EXCL); + break; + case detail::DoOpenOrCreate: + oflag |= O_CREAT; + break; + default: + { + error_info err = other_error; + throw interprocess_exception(err); + } + } + + //Open file using POSIX API + if(oflag & O_CREAT) + handle = sem_open(name.c_str(), oflag, S_IRWXO | S_IRWXG | S_IRWXU, count); + else + handle = sem_open(name.c_str(), oflag); + + //Check for error + if(handle == BOOST_INTERPROCESS_POSIX_SEM_FAILED){ + throw interprocess_exception(error_info(errno)); + } + + return true; +} + +inline void semaphore_close(sem_t *handle) +{ + int ret = sem_close(handle); + if(ret != 0){ + assert(0); + } +} + +inline bool semaphore_unlink(const char *semname) +{ + try{ + std::string sem_str; + #ifndef BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES + detail::add_leading_slash(semname, sem_str); + #else + detail::tmp_filename(semname, sem_str); + #endif + return 0 != sem_unlink(sem_str.c_str()); + } + catch(...){ + return false; + } +} + +inline void semaphore_init(sem_t *handle, int initialCount) +{ + int ret = sem_init(handle, 1, initialCount); + //According to SUSV3 version 2003 edition, the return value of a successful + //sem_init call is not defined, but -1 is returned on failure. + //In the future, a successful call might be required to return 0. + if(ret == -1){ + throw interprocess_exception(system_error_code()); + } +} + +inline void semaphore_destroy(sem_t *handle) +{ + int ret = sem_destroy(handle); + if(ret != 0){ + assert(0); + } +} + +inline void semaphore_post(sem_t *handle) +{ + int ret = sem_post(handle); + if(ret != 0){ + throw interprocess_exception(system_error_code()); + } +} + +inline void semaphore_wait(sem_t *handle) +{ + int ret = sem_wait(handle); + if(ret != 0){ + throw interprocess_exception(system_error_code()); + } +} + +inline bool semaphore_try_wait(sem_t *handle) +{ + int res = sem_trywait(handle); + if(res == 0) + return true; + if(system_error_code() == EAGAIN){ + return false; + } + throw interprocess_exception(system_error_code()); + return false; +} + +inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &abs_time) +{ + #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS + timespec tspec = detail::ptime_to_timespec(abs_time); + for (;;){ + int res = sem_timedwait(handle, &tspec); + if(res == 0) + return true; + if (res > 0){ + //buggy glibc, copy the returned error code to errno + errno = res; + } + if(system_error_code() == ETIMEDOUT){ + return false; + } + throw interprocess_exception(system_error_code()); + } + return false; + #else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS + boost::posix_time::ptime now; + while((now = microsec_clock::universal_time()) < abs_time){ + if(semaphore_try_wait(handle)) + return true; + thread_yield(); + } + return false; + #endif //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS +} + + +class named_semaphore_wrapper +{ + named_semaphore_wrapper(); + named_semaphore_wrapper(const named_semaphore_wrapper&); + named_semaphore_wrapper &operator= (const named_semaphore_wrapper &); + + public: + named_semaphore_wrapper + (detail::create_enum_t type, const char *name, mode_t mode, unsigned int count) + { semaphore_open(mp_sem, type, name, mode, count); } + + ~named_semaphore_wrapper() + { + if(mp_sem != BOOST_INTERPROCESS_POSIX_SEM_FAILED) + semaphore_close(mp_sem); + } + + void post() + { semaphore_post(mp_sem); } + + void wait() + { semaphore_wait(mp_sem); } + + bool try_wait() + { return semaphore_try_wait(mp_sem); } + + bool timed_wait(const boost::posix_time::ptime &abs_time) + { return semaphore_timed_wait(mp_sem, abs_time); } + + static bool remove(const char *name) + { return semaphore_unlink(name); } + + private: + friend class detail::interprocess_tester; + void dont_close_on_destruction() + { mp_sem = BOOST_INTERPROCESS_POSIX_SEM_FAILED; } + + sem_t *mp_sem; +}; + +class semaphore_wrapper +{ + semaphore_wrapper(); + semaphore_wrapper(const semaphore_wrapper&); + semaphore_wrapper &operator= (const semaphore_wrapper &); + + public: + semaphore_wrapper(int initialCount) + { semaphore_init(&m_sem, initialCount); } + + ~semaphore_wrapper() + { semaphore_destroy(&m_sem); } + + void post() + { semaphore_post(&m_sem); } + + void wait() + { semaphore_wait(&m_sem); } + + bool try_wait() + { return semaphore_try_wait(&m_sem); } + + bool timed_wait(const boost::posix_time::ptime &abs_time) + { return semaphore_timed_wait(&m_sem, abs_time); } + + private: + sem_t m_sem; +}; + +} //namespace detail { +} //namespace interprocess { +} //namespace boost { + +#undef BOOST_INTERPROCESS_POSIX_SEM_FAILED + +#endif //#ifndef BOOST_INTERPROCESS_POSIX_SEMAPHORE_WRAPPER_HPP diff --git a/win32/include/boost/interprocess/sync/scoped_lock.hpp b/win32/include/boost/interprocess/sync/scoped_lock.hpp new file mode 100755 index 000000000..5e772159b --- /dev/null +++ b/win32/include/boost/interprocess/sync/scoped_lock.hpp @@ -0,0 +1,469 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This interface is inspired by Howard Hinnant's lock proposal. +// http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_SCOPED_LOCK_HPP +#define BOOST_INTERPROCESS_SCOPED_LOCK_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes the scoped_lock class. + +namespace boost { +namespace interprocess { + +template +class sharable_lock; + +template +class upgradable_lock; + +//!scoped_lock is meant to carry out the tasks for locking, unlocking, try-locking +//!and timed-locking (recursive or not) for the Mutex. The Mutex need not supply all +//!of this functionality. If the client of scoped_lock does not use +//!functionality which the Mutex does not supply, no harm is done. Mutex ownership +//!transfer is supported through the syntax of move semantics. Ownership transfer +//!is allowed both by construction and assignment. The scoped_lock does not support +//!copy semantics. A compile time error results if copy construction or copy +//!assignment is attempted. Mutex ownership can also be moved from an +//!upgradable_lock and sharable_lock via constructor. In this role, scoped_lock +//!shares the same functionality as a write_lock. +template +class scoped_lock +{ + /// @cond + private: + typedef scoped_lock this_type; + scoped_lock(scoped_lock const&); + scoped_lock& operator= (scoped_lock const&); + typedef bool this_type::*unspecified_bool_type; + /// @endcond + public: + typedef Mutex mutex_type; + + //!Effects: Default constructs a scoped_lock. + //!Postconditions: owns() == false and mutex() == 0. + scoped_lock() + : mp_mutex(0), m_locked(false) + {} + + //!Effects: m.lock(). + //!Postconditions: owns() == true and mutex() == &m. + //!Notes: The constructor will take ownership of the mutex. If another thread + //! already owns the mutex, this thread will block until the mutex is released. + //! Whether or not this constructor handles recursive locking depends upon the mutex. + explicit scoped_lock(mutex_type& m) + : mp_mutex(&m), m_locked(false) + { mp_mutex->lock(); m_locked = true; } + + //!Postconditions: owns() == false, and mutex() == &m. + //!Notes: The constructor will not take ownership of the mutex. There is no effect + //! required on the referenced mutex. + scoped_lock(mutex_type& m, detail::defer_lock_type) + : mp_mutex(&m), m_locked(false) + {} + + //!Postconditions: owns() == true, and mutex() == &m. + //!Notes: The constructor will suppose that the mutex is already locked. There + //! is no effect required on the referenced mutex. + scoped_lock(mutex_type& m, detail::accept_ownership_type) + : mp_mutex(&m), m_locked(true) + {} + + //!Effects: m.try_lock(). + //!Postconditions: mutex() == &m. owns() == the return value of the + //! m.try_lock() executed within the constructor. + //!Notes: The constructor will take ownership of the mutex if it can do + //! so without waiting. Whether or not this constructor handles recursive + //! locking depends upon the mutex. If the mutex_type does not support try_lock, + //! this constructor will fail at compile time if instantiated, but otherwise + //! have no effect. + scoped_lock(mutex_type& m, detail::try_to_lock_type) + : mp_mutex(&m), m_locked(mp_mutex->try_lock()) + {} + + //!Effects: m.timed_lock(abs_time). + //!Postconditions: mutex() == &m. owns() == the return value of the + //! m.timed_lock(abs_time) executed within the constructor. + //!Notes: The constructor will take ownership of the mutex if it can do + //! it until abs_time is reached. Whether or not this constructor + //! handles recursive locking depends upon the mutex. If the mutex_type + //! does not support try_lock, this constructor will fail at compile + //! time if instantiated, but otherwise have no effect. + scoped_lock(mutex_type& m, const boost::posix_time::ptime& abs_time) + : mp_mutex(&m), m_locked(mp_mutex->timed_lock(abs_time)) + {} + + //!Postconditions: mutex() == the value scop.mutex() had before the + //! constructor executes. s1.mutex() == 0. owns() == the value of + //! scop.owns() before the constructor executes. scop.owns(). + //!Notes: If the scop scoped_lock owns the mutex, ownership is moved + //! to thisscoped_lock with no blocking. If the scop scoped_lock does not + //! own the mutex, then neither will this scoped_lock. Only a moved + //! scoped_lock's will match this signature. An non-moved scoped_lock + //! can be moved with the expression: "detail::move_impl(lock);". This + //! constructor does not alter the state of the mutex, only potentially + //! who owns it. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + scoped_lock(detail::moved_object > scop) + : mp_mutex(0), m_locked(scop.get().owns()) + { mp_mutex = scop.get().release(); } + #else + + scoped_lock(scoped_lock &&scop) + : mp_mutex(0), m_locked(scop.owns()) + { mp_mutex = scop.release(); } + #endif + + //!Effects: If upgr.owns() then calls unlock_upgradable_and_lock() on the + //! referenced mutex. upgr.release() is called. + //!Postconditions: mutex() == the value upgr.mutex() had before the construction. + //! upgr.mutex() == 0. owns() == upgr.owns() before the construction. + //! upgr.owns() == false after the construction. + //!Notes: If upgr is locked, this constructor will lock this scoped_lock while + //! unlocking upgr. If upgr is unlocked, then this scoped_lock will be + //! unlocked as well. Only a moved upgradable_lock's will match this + //! signature. An non-moved upgradable_lock can be moved with + //! the expression: "detail::move_impl(lock);" This constructor may block if + //! other threads hold a sharable_lock on this mutex (sharable_lock's can + //! share ownership with an upgradable_lock). + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + scoped_lock(detail::moved_object > upgr) + : mp_mutex(0), m_locked(false) + { + upgradable_lock &u_lock = upgr.get(); + if(u_lock.owns()){ + u_lock.mutex()->unlock_upgradable_and_lock(); + m_locked = true; + } + mp_mutex = u_lock.release(); + } + #else + scoped_lock(upgradable_lock &&upgr) + : mp_mutex(0), m_locked(false) + { + upgradable_lock &u_lock = upgr; + if(u_lock.owns()){ + u_lock.mutex()->unlock_upgradable_and_lock(); + m_locked = true; + } + mp_mutex = u_lock.release(); + } + #endif + + //!Effects: If upgr.owns() then calls try_unlock_upgradable_and_lock() on the + //!referenced mutex: + //! a)if try_unlock_upgradable_and_lock() returns true then mutex() obtains + //! the value from upgr.release() and owns() is set to true. + //! b)if try_unlock_upgradable_and_lock() returns false then upgr is + //! unaffected and this scoped_lock construction as the same effects as + //! a default construction. + //! c)Else upgr.owns() is false. mutex() obtains the value from upgr.release() + //! and owns() is set to false + //!Notes: This construction will not block. It will try to obtain mutex + //! ownership from upgr immediately, while changing the lock type from a + //! "read lock" to a "write lock". If the "read lock" isn't held in the + //! first place, the mutex merely changes type to an unlocked "write lock". + //! If the "read lock" is held, then mutex transfer occurs only if it can + //! do so in a non-blocking manner.*/ + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + scoped_lock(detail::moved_object > upgr + ,detail::try_to_lock_type) + : mp_mutex(0), m_locked(false) + { + upgradable_lock &u_lock = upgr.get(); + if(u_lock.owns()){ + if((m_locked = u_lock.mutex()->try_unlock_upgradable_and_lock()) == true){ + mp_mutex = u_lock.release(); + } + } + else{ + u_lock.release(); + } + } + #else + scoped_lock(upgradable_lock &&upgr + ,detail::try_to_lock_type) + : mp_mutex(0), m_locked(false) + { + upgradable_lock &u_lock = upgr; + if(u_lock.owns()){ + if((m_locked = u_lock.mutex()->try_unlock_upgradable_and_lock()) == true){ + mp_mutex = u_lock.release(); + } + } + else{ + u_lock.release(); + } + } + #endif + + //!Effects: If upgr.owns() then calls timed_unlock_upgradable_and_lock(abs_time) + //! on the referenced mutex: + //! a)if timed_unlock_upgradable_and_lock(abs_time) returns true then mutex() + //! obtains the value from upgr.release() and owns() is set to true. + //! b)if timed_unlock_upgradable_and_lock(abs_time) returns false then upgr + //! is unaffected and this scoped_lock construction as the same effects + //! as a default construction. + //! c)Else upgr.owns() is false. mutex() obtains the value from upgr.release() + //! and owns() is set to false + //!Notes: This construction will not block. It will try to obtain mutex ownership + //! from upgr immediately, while changing the lock type from a "read lock" to a + //! "write lock". If the "read lock" isn't held in the first place, the mutex + //! merely changes type to an unlocked "write lock". If the "read lock" is held, + //! then mutex transfer occurs only if it can do so in a non-blocking manner. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + scoped_lock(detail::moved_object > upgr + ,boost::posix_time::ptime &abs_time) + : mp_mutex(0), m_locked(false) + { + upgradable_lock &u_lock = upgr.get(); + if(u_lock.owns()){ + if((m_locked = u_lock.mutex()->timed_unlock_upgradable_and_lock(abs_time)) == true){ + mp_mutex = u_lock.release(); + } + } + else{ + u_lock.release(); + } + } + #else + scoped_lock(upgradable_lock &&upgr + ,boost::posix_time::ptime &abs_time) + : mp_mutex(0), m_locked(false) + { + upgradable_lock &u_lock = upgr; + if(u_lock.owns()){ + if((m_locked = u_lock.mutex()->timed_unlock_upgradable_and_lock(abs_time)) == true){ + mp_mutex = u_lock.release(); + } + } + else{ + u_lock.release(); + } + } + #endif + + //!Effects: If shar.owns() then calls try_unlock_sharable_and_lock() on the + //!referenced mutex. + //! a)if try_unlock_sharable_and_lock() returns true then mutex() obtains + //! the value from shar.release() and owns() is set to true. + //! b)if try_unlock_sharable_and_lock() returns false then shar is + //! unaffected and this scoped_lock construction has the same + //! effects as a default construction. + //! c)Else shar.owns() is false. mutex() obtains the value from + //! shar.release() and owns() is set to false + //!Notes: This construction will not block. It will try to obtain mutex + //! ownership from shar immediately, while changing the lock type from a + //! "read lock" to a "write lock". If the "read lock" isn't held in the + //! first place, the mutex merely changes type to an unlocked "write lock". + //! If the "read lock" is held, then mutex transfer occurs only if it can + //! do so in a non-blocking manner. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + scoped_lock(detail::moved_object > shar + ,detail::try_to_lock_type) + : mp_mutex(0), m_locked(false) + { + sharable_lock &s_lock = shar.get(); + if(s_lock.owns()){ + if((m_locked = s_lock.mutex()->try_unlock_sharable_and_lock()) == true){ + mp_mutex = s_lock.release(); + } + } + else{ + s_lock.release(); + } + } + #else + scoped_lock(sharable_lock &&shar + ,detail::try_to_lock_type) + : mp_mutex(0), m_locked(false) + { + sharable_lock &s_lock = shar; + if(s_lock.owns()){ + if((m_locked = s_lock.mutex()->try_unlock_sharable_and_lock()) == true){ + mp_mutex = s_lock.release(); + } + } + else{ + s_lock.release(); + } + } + #endif + + //!Effects: if (owns()) mp_mutex->unlock(). + //!Notes: The destructor behavior ensures that the mutex lock is not leaked.*/ + ~scoped_lock() + { + try{ if(m_locked && mp_mutex) mp_mutex->unlock(); } + catch(...){} + } + + //!Effects: If owns() before the call, then unlock() is called on mutex(). + //! *this gets the state of scop and scop gets set to a default constructed state. + //!Notes: With a recursive mutex it is possible that both this and scop own + //! the same mutex before the assignment. In this case, this will own the + //! mutex after the assignment (and scop will not), but the mutex's lock + //! count will be decremented by one. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + scoped_lock &operator=(detail::moved_object scop) + { + if(this->owns()) + this->unlock(); + m_locked = scop.get().owns(); + mp_mutex = scop.get().release(); + return *this; + } + #else + scoped_lock &operator=(scoped_lock &&scop) + { + if(this->owns()) + this->unlock(); + m_locked = scop.owns(); + mp_mutex = scop.release(); + return *this; + } + #endif + + //!Effects: If mutex() == 0 or if already locked, throws a lock_exception() + //! exception. Calls lock() on the referenced mutex. + //!Postconditions: owns() == true. + //!Notes: The scoped_lock changes from a state of not owning the mutex, to + //! owning the mutex, blocking if necessary. + void lock() + { + if(!mp_mutex || m_locked) + throw lock_exception(); + mp_mutex->lock(); + m_locked = true; + } + + //!Effects: If mutex() == 0 or if already locked, throws a lock_exception() + //! exception. Calls try_lock() on the referenced mutex. + //!Postconditions: owns() == the value returned from mutex()->try_lock(). + //!Notes: The scoped_lock changes from a state of not owning the mutex, to + //! owning the mutex, but only if blocking was not required. If the + //! mutex_type does not support try_lock(), this function will fail at + //! compile time if instantiated, but otherwise have no effect.*/ + bool try_lock() + { + if(!mp_mutex || m_locked) + throw lock_exception(); + m_locked = mp_mutex->try_lock(); + return m_locked; + } + + //!Effects: If mutex() == 0 or if already locked, throws a lock_exception() + //! exception. Calls timed_lock(abs_time) on the referenced mutex. + //!Postconditions: owns() == the value returned from mutex()-> timed_lock(abs_time). + //!Notes: The scoped_lock changes from a state of not owning the mutex, to + //! owning the mutex, but only if it can obtain ownership by the specified + //! time. If the mutex_type does not support timed_lock (), this function + //! will fail at compile time if instantiated, but otherwise have no effect.*/ + bool timed_lock(const boost::posix_time::ptime& abs_time) + { + if(!mp_mutex || m_locked) + throw lock_exception(); + m_locked = mp_mutex->timed_lock(abs_time); + return m_locked; + } + + //!Effects: If mutex() == 0 or if not locked, throws a lock_exception() + //! exception. Calls unlock() on the referenced mutex. + //!Postconditions: owns() == false. + //!Notes: The scoped_lock changes from a state of owning the mutex, to not + //! owning the mutex.*/ + void unlock() + { + if(!mp_mutex || !m_locked) + throw lock_exception(); + mp_mutex->unlock(); + m_locked = false; + } + + //!Effects: Returns true if this scoped_lock has acquired + //!the referenced mutex. + bool owns() const + { return m_locked && mp_mutex; } + + //!Conversion to bool. + //!Returns owns(). + operator unspecified_bool_type() const + { return m_locked? &this_type::m_locked : 0; } + + //!Effects: Returns a pointer to the referenced mutex, or 0 if + //!there is no mutex to reference. + mutex_type* mutex() const + { return mp_mutex; } + + //!Effects: Returns a pointer to the referenced mutex, or 0 if there is no + //! mutex to reference. + //!Postconditions: mutex() == 0 and owns() == false. + mutex_type* release() + { + mutex_type *mut = mp_mutex; + mp_mutex = 0; + m_locked = false; + return mut; + } + + //!Effects: Swaps state with moved lock. + //!Throws: Nothing. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(detail::moved_object > other) + { + std::swap(mp_mutex, other.get().mp_mutex); + std::swap(m_locked, other.get().m_locked); + } + #else + void swap(scoped_lock &&other) + { + std::swap(mp_mutex, other.mp_mutex); + std::swap(m_locked, other.m_locked); + } + #endif + + /// @cond + private: + mutex_type *mp_mutex; + bool m_locked; + /// @endcond +}; + +/// @cond + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; +/// @endcond + +} // namespace interprocess +} // namespace boost + +#include + +#endif // BOOST_INTERPROCESS_SCOPED_LOCK_HPP diff --git a/win32/include/boost/interprocess/sync/sharable_lock.hpp b/win32/include/boost/interprocess/sync/sharable_lock.hpp new file mode 100755 index 000000000..34dfc7a15 --- /dev/null +++ b/win32/include/boost/interprocess/sync/sharable_lock.hpp @@ -0,0 +1,367 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This interface is inspired by Howard Hinnant's lock proposal. +// http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_SHARABLE_LOCK_HPP +#define BOOST_INTERPROCESS_SHARABLE_LOCK_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +//Ig#include +#include + +//!\file +//!Describes the upgradable_lock class that serves to acquire the upgradable +//!lock of a mutex. + +namespace boost { +namespace interprocess { + +template +class scoped_lock; + +template +class upgradable_lock; + +//!sharable_lock is meant to carry out the tasks for sharable-locking +//!(such as read-locking), unlocking, try-sharable-locking and timed-sharable-locking +//!(recursive or not) for the Mutex. The Mutex need not supply all of this +//!functionality. If the client of sharable_lock does not use functionality which +//!the Mutex does not supply, no harm is done. Mutex ownership can be shared among +//!sharable_locks, and a single upgradable_lock. sharable_lock does not support +//!copy semantics. But sharable_lock supports ownership transfer from an sharable_lock, +//!upgradable_lock and scoped_lock via trasfer_lock syntax.*/ +template +class sharable_lock +{ + public: + typedef SharableMutex mutex_type; + /// @cond + private: + typedef sharable_lock this_type; + sharable_lock(sharable_lock const&); + explicit sharable_lock(scoped_lock const&); + typedef bool this_type::*unspecified_bool_type; + sharable_lock& operator=(sharable_lock const&); + sharable_lock& operator=(scoped_lock const&); + /// @endcond + public: + + //!Effects: Default constructs a sharable_lock. + //!Postconditions: owns() == false and mutex() == 0. + sharable_lock() + : mp_mutex(0), m_locked(false) + {} + + //!Effects: m.lock_sharable(). + //!Postconditions: owns() == true and mutex() == &m. + //!Notes: The constructor will take sharable-ownership of the mutex. If + //! another thread already owns the mutex with exclusive ownership + //! (scoped_lock), this thread will block until the mutex is released. + //! If another thread owns the mutex with sharable or upgradable ownership, + //! then no blocking will occur. Whether or not this constructor handles + //! recursive locking depends upon the mutex. + explicit sharable_lock(mutex_type& m) + : mp_mutex(&m), m_locked(false) + { mp_mutex->lock_sharable(); m_locked = true; } + + //!Postconditions: owns() == false, and mutex() == &m. + //!Notes: The constructor will not take ownership of the mutex. There is no effect + //! required on the referenced mutex. + sharable_lock(mutex_type& m, detail::defer_lock_type) + : mp_mutex(&m), m_locked(false) + {} + + //!Postconditions: owns() == true, and mutex() == &m. + //!Notes: The constructor will suppose that the mutex is already sharable + //! locked. There is no effect required on the referenced mutex. + sharable_lock(mutex_type& m, detail::accept_ownership_type) + : mp_mutex(&m), m_locked(true) + {} + + //!Effects: m.try_lock_sharable() + //!Postconditions: mutex() == &m. owns() == the return value of the + //! m.try_lock_sharable() executed within the constructor. + //!Notes: The constructor will take sharable-ownership of the mutex if it + //! can do so without waiting. Whether or not this constructor handles + //! recursive locking depends upon the mutex. If the mutex_type does not + //! support try_lock_sharable, this constructor will fail at compile + //! time if instantiated, but otherwise have no effect. + sharable_lock(mutex_type& m, detail::try_to_lock_type) + : mp_mutex(&m), m_locked(false) + { m_locked = mp_mutex->try_lock_sharable(); } + + //!Effects: m.timed_lock_sharable(abs_time) + //!Postconditions: mutex() == &m. owns() == the return value of the + //! m.timed_lock_sharable() executed within the constructor. + //!Notes: The constructor will take sharable-ownership of the mutex if it + //! can do so within the time specified. Whether or not this constructor + //! handles recursive locking depends upon the mutex. If the mutex_type + //! does not support timed_lock_sharable, this constructor will fail at + //! compile time if instantiated, but otherwise have no effect. + sharable_lock(mutex_type& m, const boost::posix_time::ptime& abs_time) + : mp_mutex(&m), m_locked(false) + { m_locked = mp_mutex->timed_lock_sharable(abs_time); } + + //!Postconditions: mutex() == upgr.mutex(). owns() == the value of upgr.owns() + //! before the construction. upgr.owns() == false after the construction. + //!Notes: If the upgr sharable_lock owns the mutex, ownership is moved to this + //! sharable_lock with no blocking. If the upgr sharable_lock does not own the mutex, then + //! neither will this sharable_lock. Only a moved sharable_lock's will match this + //! signature. An non-moved sharable_lock can be moved with the expression: + //! "detail::move_impl(lock);". This constructor does not alter the state of the mutex, + //! only potentially who owns it. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + sharable_lock(detail::moved_object > upgr) + : mp_mutex(0), m_locked(upgr.get().owns()) + { mp_mutex = upgr.get().release(); } + #else + sharable_lock(sharable_lock &&upgr) + : mp_mutex(0), m_locked(upgr.owns()) + { mp_mutex = upgr.release(); } + #endif + + //!Effects: If upgr.owns() then calls unlock_upgradable_and_lock_sharable() on the + //! referenced mutex. + //!Postconditions: mutex() == the value upgr.mutex() had before the construction. + //! upgr.mutex() == 0 owns() == the value of upgr.owns() before construction. + //! upgr.owns() == false after the construction. + //!Notes: If upgr is locked, this constructor will lock this sharable_lock while + //! unlocking upgr. Only a moved sharable_lock's will match this + //! signature. An non-moved upgradable_lock can be moved with the expression: + //! "detail::move_impl(lock);".*/ + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + sharable_lock(detail::moved_object > upgr) + : mp_mutex(0), m_locked(false) + { + upgradable_lock &u_lock = upgr.get(); + if(u_lock.owns()){ + u_lock.mutex()->unlock_upgradable_and_lock_sharable(); + m_locked = true; + } + mp_mutex = u_lock.release(); + } + #else + sharable_lock(upgradable_lock &&upgr) + : mp_mutex(0), m_locked(false) + { + upgradable_lock &u_lock = upgr; + if(u_lock.owns()){ + u_lock.mutex()->unlock_upgradable_and_lock_sharable(); + m_locked = true; + } + mp_mutex = u_lock.release(); + } + #endif + + //!Effects: If scop.owns() then calls unlock_and_lock_sharable() on the + //! referenced mutex. + //!Postconditions: mutex() == the value scop.mutex() had before the construction. + //! scop.mutex() == 0 owns() == scop.owns() before the constructor. After the + //! construction, scop.owns() == false. + //!Notes: If scop is locked, this constructor will transfer the exclusive ownership + //! to a sharable-ownership of this sharable_lock. + //! Only a moved scoped_lock's will match this + //! signature. An non-moved scoped_lock can be moved with the expression: + //! "detail::move_impl(lock);".*/ + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + sharable_lock(detail::moved_object > scop) + : mp_mutex(0), m_locked(false) + { + scoped_lock &e_lock = scop.get(); + if(e_lock.owns()){ + e_lock.mutex()->unlock_and_lock_sharable(); + m_locked = true; + } + mp_mutex = e_lock.release(); + } + #else + sharable_lock(scoped_lock &&scop) + : mp_mutex(0), m_locked(false) + { + scoped_lock &e_lock = scop; + if(e_lock.owns()){ + e_lock.mutex()->unlock_and_lock_sharable(); + m_locked = true; + } + mp_mutex = e_lock.release(); + } + #endif + + //!Effects: if (owns()) mp_mutex->unlock_sharable(). + //!Notes: The destructor behavior ensures that the mutex lock is not leaked. + ~sharable_lock() + { + try{ + if(m_locked && mp_mutex) mp_mutex->unlock_sharable(); + } + catch(...){} + } + + //!Effects: If owns() before the call, then unlock_sharable() is called on mutex(). + //! *this gets the state of upgr and upgr gets set to a default constructed state. + //!Notes: With a recursive mutex it is possible that both this and upgr own the mutex + //! before the assignment. In this case, this will own the mutex after the assignment + //! (and upgr will not), but the mutex's lock count will be decremented by one. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + sharable_lock &operator=(detail::moved_object > upgr) + { + if(this->owns()) + this->unlock(); + m_locked = upgr.get().owns(); + mp_mutex = upgr.get().release(); + return *this; + } + #else + sharable_lock &operator=(sharable_lock &&upgr) + { + if(this->owns()) + this->unlock(); + m_locked = upgr.owns(); + mp_mutex = upgr.release(); + return *this; + } + #endif + + //!Effects: If mutex() == 0 or already locked, throws a lock_exception() + //! exception. Calls lock_sharable() on the referenced mutex. + //!Postconditions: owns() == true. + //!Notes: The sharable_lock changes from a state of not owning the + //! mutex, to owning the mutex, blocking if necessary. + void lock() + { + if(!mp_mutex || m_locked) + throw lock_exception(); + mp_mutex->lock_sharable(); + m_locked = true; + } + + //!Effects: If mutex() == 0 or already locked, throws a lock_exception() + //! exception. Calls try_lock_sharable() on the referenced mutex. + //!Postconditions: owns() == the value returned from + //! mutex()->try_lock_sharable(). + //!Notes: The sharable_lock changes from a state of not owning the mutex, + //! to owning the mutex, but only if blocking was not required. If the + //! mutex_type does not support try_lock_sharable(), this function will + //! fail at compile time if instantiated, but otherwise have no effect. + bool try_lock() + { + if(!mp_mutex || m_locked) + throw lock_exception(); + m_locked = mp_mutex->try_lock_sharable(); + return m_locked; + } + + //!Effects: If mutex() == 0 or already locked, throws a lock_exception() + //! exception. Calls timed_lock_sharable(abs_time) on the referenced mutex. + //!Postconditions: owns() == the value returned from + //! mutex()->timed_lock_sharable(elps_time). + //!Notes: The sharable_lock changes from a state of not owning the mutex, + //! to owning the mutex, but only if it can obtain ownership within the + //! specified time interval. If the mutex_type does not support + //! timed_lock_sharable(), this function will fail at compile time if + //! instantiated, but otherwise have no effect. + bool timed_lock(const boost::posix_time::ptime& abs_time) + { + if(!mp_mutex || m_locked) + throw lock_exception(); + m_locked = mp_mutex->timed_lock_sharable(abs_time); + return m_locked; + } + + //!Effects: If mutex() == 0 or not locked, throws a lock_exception() exception. + //! Calls unlock_sharable() on the referenced mutex. + //!Postconditions: owns() == false. + //!Notes: The sharable_lock changes from a state of owning the mutex, to + //! not owning the mutex. + void unlock() + { + if(!mp_mutex || !m_locked) + throw lock_exception(); + mp_mutex->unlock_sharable(); + m_locked = false; + } + + //!Effects: Returns true if this scoped_lock has + //!acquired the referenced mutex. + bool owns() const + { return m_locked && mp_mutex; } + + //!Conversion to bool. + //!Returns owns(). + operator unspecified_bool_type() const + { return m_locked? &this_type::m_locked : 0; } + + //!Effects: Returns a pointer to the referenced mutex, or 0 if + //!there is no mutex to reference. + mutex_type* mutex() const + { return mp_mutex; } + + //!Effects: Returns a pointer to the referenced mutex, or 0 if there is no + //! mutex to reference. + //!Postconditions: mutex() == 0 and owns() == false. + mutex_type* release() + { + mutex_type *mut = mp_mutex; + mp_mutex = 0; + m_locked = false; + return mut; + } + + //!Effects: Swaps state with moved lock. + //!Throws: Nothing. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(detail::moved_object > other) + { + std::swap(mp_mutex, other.get().mp_mutex); + std::swap(m_locked, other.get().m_locked); + } + #else + void swap(sharable_lock &&other) + { + std::swap(mp_mutex, other.mp_mutex); + std::swap(m_locked, other.m_locked); + } + #endif + + /// @cond + private: + mutex_type *mp_mutex; + bool m_locked; + /// @endcond +}; + +/// @cond + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; +/// @endcond + +} // namespace interprocess +} // namespace boost + +#include + +#endif // BOOST_INTERPROCESS_SHARABLE_LOCK_HPP diff --git a/win32/include/boost/interprocess/sync/upgradable_lock.hpp b/win32/include/boost/interprocess/sync/upgradable_lock.hpp new file mode 100755 index 000000000..312c2f520 --- /dev/null +++ b/win32/include/boost/interprocess/sync/upgradable_lock.hpp @@ -0,0 +1,375 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +// +// This interface is inspired by Howard Hinnant's lock proposal. +// http://home.twcny.rr.com/hinnant/cpp_extensions/threads_move.html +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP +#define BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes the upgradable_lock class that serves to acquire the upgradable +//!lock of a mutex. + +namespace boost { +namespace interprocess { + +template +class scoped_lock; + +template +class sharable_lock; + +//!upgradable_lock is meant to carry out the tasks for read-locking, unlocking, +//!try-read-locking and timed-read-locking (recursive or not) for the Mutex. +//!Additionally the upgradable_lock can transfer ownership to a scoped_lock +//!using trasfer_lock syntax. The Mutex need not supply all of the functionality. +//!If the client of upgradable_lock does not use functionality which the +//!Mutex does not supply, no harm is done. Mutex ownership can be shared among +//!read_locks, and a single upgradable_lock. upgradable_lock does not support +//!copy semantics. However upgradable_lock supports ownership transfer from +//!a upgradable_locks or scoped_locks via trasfer_lock syntax. +template +class upgradable_lock +{ + public: + typedef UpgradableMutex mutex_type; + /// @cond + private: + typedef upgradable_lock this_type; + upgradable_lock(upgradable_lock const&); + explicit upgradable_lock(scoped_lock const&); + typedef bool this_type::*unspecified_bool_type; + upgradable_lock& operator=(upgradable_lock const&); + upgradable_lock& operator=(scoped_lock const&); + /// @endcond + public: + + //!Effects: Default constructs a upgradable_lock. + //!Postconditions: owns() == false and mutex() == 0. + upgradable_lock() + : mp_mutex(0), m_locked(false) + {} + + explicit upgradable_lock(mutex_type& m) + : mp_mutex(&m), m_locked(false) + { mp_mutex->lock_upgradable(); m_locked = true; } + + //!Postconditions: owns() == false, and mutex() == &m. + //!Notes: The constructor will not take ownership of the mutex. There is no effect + //! required on the referenced mutex. + upgradable_lock(mutex_type& m, detail::defer_lock_type) + : mp_mutex(&m), m_locked(false) + {} + + //!Postconditions: owns() == true, and mutex() == &m. + //!Notes: The constructor will suppose that the mutex is already upgradable + //! locked. There is no effect required on the referenced mutex. + upgradable_lock(mutex_type& m, detail::accept_ownership_type) + : mp_mutex(&m), m_locked(true) + {} + + //!Effects: m.try_lock_upgradable(). + //!Postconditions: mutex() == &m. owns() == the return value of the + //! m.try_lock_upgradable() executed within the constructor. + //!Notes: The constructor will take upgradable-ownership of the mutex + //! if it can do so without waiting. Whether or not this constructor + //! handles recursive locking depends upon the mutex. If the mutex_type + //! does not support try_lock_upgradable, this constructor will fail at + //! compile time if instantiated, but otherwise have no effect. + upgradable_lock(mutex_type& m, detail::try_to_lock_type) + : mp_mutex(&m), m_locked(false) + { m_locked = mp_mutex->try_lock_upgradable(); } + + //!Effects: m.timed_lock_upgradable(abs_time) + //!Postconditions: mutex() == &m. owns() == the return value of the + //! m.timed_lock_upgradable() executed within the constructor. + //!Notes: The constructor will take upgradable-ownership of the mutex if it + //! can do so within the time specified. Whether or not this constructor + //! handles recursive locking depends upon the mutex. If the mutex_type + //! does not support timed_lock_upgradable, this constructor will fail + //! at compile time if instantiated, but otherwise have no effect. + upgradable_lock(mutex_type& m, const boost::posix_time::ptime& abs_time) + : mp_mutex(&m), m_locked(false) + { m_locked = mp_mutex->timed_lock_upgradable(abs_time); } + + //!Effects: No effects on the underlying mutex. + //!Postconditions: mutex() == the value upgr.mutex() had before the + //! construction. upgr.mutex() == 0. owns() == upgr.owns() before the + //! construction. upgr.owns() == false. + //!Notes: If upgr is locked, this constructor will lock this upgradable_lock + //! while unlocking upgr. If upgr is unlocked, then this upgradable_lock will + //! be unlocked as well. Only a moved upgradable_lock's will match this + //! signature. An non-moved upgradable_lock can be moved with the + //! expression: "detail::move_impl(lock);". This constructor does not alter the + //! state of the mutex, only potentially who owns it. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + upgradable_lock(detail::moved_object > upgr) + : mp_mutex(0), m_locked(upgr.get().owns()) + { mp_mutex = upgr.get().release(); } + #else + upgradable_lock(upgradable_lock &&upgr) + : mp_mutex(0), m_locked(upgr.owns()) + { mp_mutex = upgr.release(); } + #endif + + //!Effects: If scop.owns(), m_.unlock_and_lock_upgradable(). + //!Postconditions: mutex() == the value scop.mutex() had before the construction. + //! scop.mutex() == 0. owns() == scop.owns() before the constructor. After the + //! construction, scop.owns() == false. + //!Notes: If scop is locked, this constructor will transfer the exclusive-ownership + //! to an upgradable-ownership of this upgradable_lock. + //! Only a moved sharable_lock's will match this + //! signature. An non-moved sharable_lock can be moved with the + //! expression: "detail::move_impl(lock);". + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + upgradable_lock(detail::moved_object > scop) + : mp_mutex(0), m_locked(false) + { + scoped_lock &u_lock = scop.get(); + if(u_lock.owns()){ + u_lock.mutex()->unlock_and_lock_upgradable(); + m_locked = true; + } + mp_mutex = u_lock.release(); + } + #else + upgradable_lock(scoped_lock &&scop) + : mp_mutex(0), m_locked(false) + { + scoped_lock &u_lock = scop; + if(u_lock.owns()){ + u_lock.mutex()->unlock_and_lock_upgradable(); + m_locked = true; + } + mp_mutex = u_lock.release(); + } + #endif + + //!Effects: If shar.owns() then calls try_unlock_sharable_and_lock_upgradable() + //! on the referenced mutex. + //! a)if try_unlock_sharable_and_lock_upgradable() returns true then mutex() + //! obtains the value from shar.release() and owns() is set to true. + //! b)if try_unlock_sharable_and_lock_upgradable() returns false then shar is + //! unaffected and this upgradable_lock construction has the same + //! effects as a default construction. + //! c)Else shar.owns() is false. mutex() obtains the value from shar.release() + //! and owns() is set to false. + //!Notes: This construction will not block. It will try to obtain mutex + //! ownership from shar immediately, while changing the lock type from a + //! "read lock" to an "upgradable lock". If the "read lock" isn't held + //! in the first place, the mutex merely changes type to an unlocked + //! "upgradable lock". If the "read lock" is held, then mutex transfer + //! occurs only if it can do so in a non-blocking manner. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + upgradable_lock( detail::moved_object > shar + , detail::try_to_lock_type) + : mp_mutex(0), m_locked(false) + { + sharable_lock &s_lock = shar.get(); + if(s_lock.owns()){ + if((m_locked = s_lock.mutex()->try_unlock_sharable_and_lock_upgradable()) == true){ + mp_mutex = s_lock.release(); + } + } + else{ + s_lock.release(); + } + } + #else + upgradable_lock( sharable_lock &&shar + , detail::try_to_lock_type) + : mp_mutex(0), m_locked(false) + { + sharable_lock &s_lock = shar; + if(s_lock.owns()){ + if((m_locked = s_lock.mutex()->try_unlock_sharable_and_lock_upgradable()) == true){ + mp_mutex = s_lock.release(); + } + } + else{ + s_lock.release(); + } + } + #endif + + //!Effects: if (owns()) m_->unlock_upgradable(). + //!Notes: The destructor behavior ensures that the mutex lock is not leaked. + ~upgradable_lock() + { + try{ + if(m_locked && mp_mutex) mp_mutex->unlock_upgradable(); + } + catch(...){} + } + + //!Effects: If owns(), then unlock_upgradable() is called on mutex(). + //! *this gets the state of upgr and upgr gets set to a default constructed state. + //!Notes: With a recursive mutex it is possible that both this and upgr own the + //! mutex before the assignment. In this case, this will own the mutex + //! after the assignment (and upgr will not), but the mutex's upgradable lock + //! count will be decremented by one. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + upgradable_lock &operator=(detail::moved_object > upgr) + { + if(this->owns()) + this->unlock(); + m_locked = upgr.get().owns(); + mp_mutex = upgr.get().release(); + return *this; + } + #else + upgradable_lock &operator=(upgradable_lock &&upgr) + { + if(this->owns()) + this->unlock(); + m_locked = upgr.owns(); + mp_mutex = upgr.release(); + return *this; + } + #endif + + //!Effects: If mutex() == 0 or if already locked, throws a lock_exception() + //! exception. Calls lock_upgradable() on the referenced mutex. + //!Postconditions: owns() == true. + //!Notes: The sharable_lock changes from a state of not owning the mutex, + //! to owning the mutex, blocking if necessary. + void lock() + { + if(!mp_mutex || m_locked) + throw lock_exception(); + mp_mutex->lock_upgradable(); + m_locked = true; + } + + //!Effects: If mutex() == 0 or if already locked, throws a lock_exception() + //! exception. Calls try_lock_upgradable() on the referenced mutex. + //!Postconditions: owns() == the value returned from + //! mutex()->try_lock_upgradable(). + //!Notes: The upgradable_lock changes from a state of not owning the mutex, + //! to owning the mutex, but only if blocking was not required. If the + //! mutex_type does not support try_lock_upgradable(), this function will + //! fail at compile time if instantiated, but otherwise have no effect. + bool try_lock() + { + if(!mp_mutex || m_locked) + throw lock_exception(); + m_locked = mp_mutex->try_lock_upgradable(); + return m_locked; + } + + //!Effects: If mutex() == 0 or if already locked, throws a lock_exception() + //! exception. Calls timed_lock_upgradable(abs_time) on the referenced mutex. + //!Postconditions: owns() == the value returned from + //! mutex()->timed_lock_upgradable(abs_time). + //!Notes: The upgradable_lock changes from a state of not owning the mutex, + //! to owning the mutex, but only if it can obtain ownership within the + //! specified time. If the mutex_type does not support + //! timed_lock_upgradable(abs_time), this function will fail at compile + //! time if instantiated, but otherwise have no effect. + bool timed_lock(const boost::posix_time::ptime& abs_time) + { + if(!mp_mutex || m_locked) + throw lock_exception(); + m_locked = mp_mutex->timed_lock_upgradable(abs_time); + return m_locked; + } + + //!Effects: If mutex() == 0 or if not locked, throws a lock_exception() + //! exception. Calls unlock_upgradable() on the referenced mutex. + //!Postconditions: owns() == false. + //!Notes: The upgradable_lock changes from a state of owning the mutex, + //! to not owning the mutex. + void unlock() + { + if(!mp_mutex || !m_locked) + throw lock_exception(); + mp_mutex->unlock_upgradable(); + m_locked = false; + } + + //!Effects: Returns true if this scoped_lock has acquired the + //!referenced mutex. + bool owns() const + { return m_locked && mp_mutex; } + + //!Conversion to bool. + //!Returns owns(). + operator unspecified_bool_type() const + { return m_locked? &this_type::m_locked : 0; } + + //!Effects: Returns a pointer to the referenced mutex, or 0 if + //!there is no mutex to reference. + mutex_type* mutex() const + { return mp_mutex; } + + //!Effects: Returns a pointer to the referenced mutex, or 0 if there is no + //! mutex to reference. + //!Postconditions: mutex() == 0 and owns() == false. + mutex_type* release() + { + mutex_type *mut = mp_mutex; + mp_mutex = 0; + m_locked = false; + return mut; + } + + //!Effects: Swaps state with moved lock. + //!Throws: Nothing. + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + void swap(detail::moved_object > other) + { + std::swap(mp_mutex, other.get().mp_mutex); + std::swap(m_locked, other.get().m_locked); + } + #else + void swap(upgradable_lock &&other) + { + std::swap(mp_mutex, other.mp_mutex); + std::swap(m_locked, other.m_locked); + } + #endif + + /// @cond + private: + mutex_type *mp_mutex; + bool m_locked; + /// @endcond +}; + +/// @cond + +//!This class is movable +template +struct is_movable > +{ + enum { value = true }; +}; +/// @endcond + +} // namespace interprocess +} // namespace boost + +#include + +#endif // BOOST_INTERPROCESS_UPGRADABLE_LOCK_HPP diff --git a/win32/include/boost/interprocess/windows_shared_memory.hpp b/win32/include/boost/interprocess/windows_shared_memory.hpp new file mode 100755 index 000000000..79e71b07a --- /dev/null +++ b/win32/include/boost/interprocess/windows_shared_memory.hpp @@ -0,0 +1,255 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2008. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP +#define BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP + +#include +#include +#include + +#if !defined(BOOST_WINDOWS) || defined(BOOST_DISABLE_WIN32) +#error "This header can only be used in Windows operating systems" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a class representing a native windows shared memory. + +namespace boost { +namespace interprocess { + +//!A class that wraps the native Windows shared memory +//!that is implemented as a file mapping of the paging file. +//!Unlike shared_memory_object, windows_shared_memory has +//!no kernel persistence and the shared memory is destroyed +//!when all processes destroy all their windows_shared_memory +//!objects and mapped regions for the same shared memory +//!or the processes end/crash. +//! +//!Warning: Windows native shared memory and interprocess portable +//!shared memory (boost::interprocess::shared_memory_object) +//!can't communicate between them. +class windows_shared_memory +{ + /// @cond + //Non-copyable and non-assignable + windows_shared_memory(const windows_shared_memory &); + windows_shared_memory &operator=(const windows_shared_memory &); + /// @endcond + + public: + + //!Default constructor. + //!Represents an empty windows_shared_memory. + windows_shared_memory(); + + //!Creates a new native shared memory with name "name" and mode "mode", + //!with the access mode "mode". + //!If the file previously exists, throws an error. + windows_shared_memory(create_only_t, const char *name, mode_t mode, std::size_t size) + { this->priv_open_or_create(detail::DoCreate, name, mode, size); } + + //!Tries to create a shared memory object with name "name" and mode "mode", with the + //!access mode "mode". If the file previously exists, it tries to open it with mode "mode". + //!Otherwise throws an error. + windows_shared_memory(open_or_create_t, const char *name, mode_t mode, std::size_t size) + { this->priv_open_or_create(detail::DoOpenOrCreate, name, mode, size); } + + //!Tries to open a shared memory object with name "name", with the access mode "mode". + //!If the file does not previously exist, it throws an error. + windows_shared_memory(open_only_t, const char *name, mode_t mode) + { this->priv_open_or_create(detail::DoOpen, name, mode, 0); } + + //!Moves the ownership of "moved"'s shared memory object to *this. + //!After the call, "moved" does not represent any shared memory object. + //!Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + windows_shared_memory + (detail::moved_object moved) + { this->swap(moved.get()); } + #else + windows_shared_memory(windows_shared_memory &&moved) + { this->swap(moved); } + #endif + + //!Moves the ownership of "moved"'s shared memory to *this. + //!After the call, "moved" does not represent any shared memory. + //!Does not throw + #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE + windows_shared_memory &operator= + (detail::moved_object moved) + { + windows_shared_memory tmp(moved); + this->swap(tmp); + return *this; + } + #else + windows_shared_memory &operator=(windows_shared_memory &&moved) + { + windows_shared_memory tmp(detail::move_impl(moved)); + this->swap(tmp); + return *this; + } + #endif + + //!Swaps to shared_memory_objects. Does not throw + void swap(windows_shared_memory &other); + + //!Destroys *this. All mapped regions are still valid after + //!destruction. When all mapped regions and windows_shared_memory + //!objects referring the shared memory are destroyed, the + //!operating system will destroy the shared memory. + ~windows_shared_memory(); + + //!Returns the name of the shared memory. + const char *get_name() const; + + //!Returns access mode + mode_t get_mode() const; + + //!Returns the mapping handle. Never throws + mapping_handle_t get_mapping_handle() const; + + /// @cond + private: + + //!Closes a previously opened file mapping. Never throws. + void priv_close(); + + //!Closes a previously opened file mapping. Never throws. + bool priv_open_or_create(detail::create_enum_t type, const char *filename, mode_t mode, std::size_t size); + + void * m_handle; + mode_t m_mode; + std::string m_name; + /// @endcond +}; + +/// @cond + +inline windows_shared_memory::windows_shared_memory() + : m_handle(0) +{} + +inline windows_shared_memory::~windows_shared_memory() +{ this->priv_close(); } + +inline const char *windows_shared_memory::get_name() const +{ return m_name.c_str(); } + +inline void windows_shared_memory::swap(windows_shared_memory &other) +{ + std::swap(m_handle, other.m_handle); + std::swap(m_mode, other.m_mode); + m_name.swap(other.m_name); +} + +inline mapping_handle_t windows_shared_memory::get_mapping_handle() const +{ mapping_handle_t mhnd = { m_handle, true}; return mhnd; } + +inline mode_t windows_shared_memory::get_mode() const +{ return m_mode; } + +inline bool windows_shared_memory::priv_open_or_create + (detail::create_enum_t type, const char *filename, mode_t mode, std::size_t size) +{ + m_name = filename ? filename : ""; + + unsigned long file_map_access = 0; + unsigned long map_access = 0; + + switch(mode) + { + case read_only: + file_map_access |= winapi::page_readonly; + map_access |= winapi::file_map_read; + break; + case read_write: + file_map_access |= winapi::page_readwrite; + map_access |= winapi::file_map_write; + break; + case copy_on_write: + file_map_access |= winapi::page_writecopy; + map_access |= winapi::file_map_copy; + break; + default: + { + error_info err(mode_error); + throw interprocess_exception(err); + } + break; + } + + switch(type){ + case detail::DoOpen: + m_handle = winapi::open_file_mapping + (map_access, filename); + break; + case detail::DoCreate: + case detail::DoOpenOrCreate: + { + __int64 s = size; + unsigned long high_size(s >> 32), low_size((boost::uint32_t)s); + m_handle = winapi::create_file_mapping + (winapi::invalid_handle_value, file_map_access, high_size, low_size, filename); + } + break; + default: + { + error_info err = other_error; + throw interprocess_exception(err); + } + } + + if(!m_handle || (type == detail::DoCreate && winapi::get_last_error() == winapi::error_already_exists)){ + error_info err = system_error_code(); + this->priv_close(); + throw interprocess_exception(err); + } + + m_mode = mode; + return true; +} + +inline void windows_shared_memory::priv_close() +{ + if(m_handle){ + winapi::close_handle(m_handle); + m_handle = 0; + } +} + +//!Trait class to detect if a type is +//!movable +template<> +struct is_movable +{ + static const bool value = true; +}; + +///@endcond + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_WINDOWS_SHARED_MEMORY_HPP diff --git a/win32/include/boost/intrusive/any_hook.hpp b/win32/include/boost/intrusive/any_hook.hpp new file mode 100755 index 000000000..6f4773e25 --- /dev/null +++ b/win32/include/boost/intrusive/any_hook.hpp @@ -0,0 +1,320 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2008 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_ANY_HOOK_HPP +#define BOOST_INTRUSIVE_ANY_HOOK_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond +template +struct get_any_node_algo +{ + typedef any_algorithms type; +}; +/// @endcond + +//! Helper metafunction to define a \c \c any_base_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_any_base_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3>::type packed_options; + + typedef detail::generic_hook + < get_any_node_algo + , typename packed_options::tag + , packed_options::link_mode + , detail::AnyBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Derive a class from this hook in order to store objects of that class +//! in an intrusive container. +//! +//! The hook admits the following options: \c tag<>, \c void_pointer<> and +//! \c link_mode<>. +//! +//! \c tag<> defines a tag to identify the node. +//! The same tag value can be used in different classes, but if a class is +//! derived from more than one \c any_base_hook, then each \c any_base_hook needs its +//! unique tag. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, \c safe_link). +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class any_base_hook + : public make_any_base_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + public: + //! Effects: If link_mode is or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + any_base_hook(); + + //! Effects: If link_mode is or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + any_base_hook(const any_base_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + any_base_hook& operator=(const any_base_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in a container an assertion is raised. + //! + //! Throws: Nothing. + ~any_base_hook(); + + //! Precondition: link_mode must be \c safe_link. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c container::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + #endif +}; + +//! Helper metafunction to define a \c \c any_member_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_any_member_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3>::type packed_options; + + typedef detail::generic_hook + < get_any_node_algo + , member_tag + , packed_options::link_mode + , detail::NoBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Store this hook in a class to be inserted +//! in an intrusive container. +//! +//! The hook admits the following options: \c void_pointer<> and +//! \c link_mode<>. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link or \c safe_link). +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class any_member_hook + : public make_any_member_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + public: + //! Effects: If link_mode is or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + any_member_hook(); + + //! Effects: If link_mode is or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + any_member_hook(const any_member_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + any_member_hook& operator=(const any_member_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in a container an assertion is raised. + //! + //! Throws: Nothing. + ~any_member_hook(); + + //! Precondition: link_mode must be \c safe_link. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c container::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + #endif +}; + +/// @cond + +namespace detail{ + +template +struct any_to_get_base_pointer_type +{ + typedef typename pointer_to_other + ::type type; +}; + +template +struct any_to_get_member_pointer_type +{ + typedef typename pointer_to_other + ::type type; +}; + +//!This option setter specifies that the container +//!must use the specified base hook +template class NodeTraits> +struct any_to_some_hook +{ + typedef typename BaseHook::template pack::value_traits old_value_traits; + template + struct pack : public Base + { + struct value_traits : public old_value_traits + { + static const bool is_any_hook = true; + typedef typename detail::eval_if_c + < detail::internal_base_hook_bool_is_true::value + , any_to_get_base_pointer_type + , any_to_get_member_pointer_type + >::type void_pointer; + typedef NodeTraits node_traits; + }; + }; +}; + +} //namespace detail{ + +/// @endcond + +//!This option setter specifies that +//!any hook should behave as an slist hook +template +struct any_to_slist_hook +/// @cond + : public detail::any_to_some_hook +/// @endcond +{}; + +//!This option setter specifies that +//!any hook should behave as an list hook +template +struct any_to_list_hook +/// @cond + : public detail::any_to_some_hook +/// @endcond +{}; + +//!This option setter specifies that +//!any hook should behave as a set hook +template +struct any_to_set_hook +/// @cond + : public detail::any_to_some_hook +/// @endcond +{}; + +//!This option setter specifies that +//!any hook should behave as a set hook +template +struct any_to_avl_set_hook +/// @cond + : public detail::any_to_some_hook +/// @endcond +{}; + +//!This option setter specifies that any +//!hook should behave as a set hook +template +struct any_to_bs_set_hook +/// @cond + : public detail::any_to_some_hook +/// @endcond +{}; + +//!This option setter specifies that any hook +//!should behave as an unordered set hook +template +struct any_to_unordered_set_hook +/// @cond + : public detail::any_to_some_hook +/// @endcond +{}; + + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_ANY_HOOK_HPP diff --git a/win32/include/boost/intrusive/avl_set.hpp b/win32/include/boost/intrusive/avl_set.hpp new file mode 100755 index 000000000..e9c862360 --- /dev/null +++ b/win32/include/boost/intrusive/avl_set.hpp @@ -0,0 +1,2137 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_AVL_SET_HPP +#define BOOST_INTRUSIVE_AVL_SET_HPP + +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +//! The class template avl_set is an intrusive container, that mimics most of +//! the interface of std::set as described in the C++ standard. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<> and +//! \c compare<>. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class avl_set_impl +{ + /// @cond + typedef avltree_impl tree_type; + //! This class is + //! non-copyable + avl_set_impl (const avl_set_impl&); + + //! This class is + //! non-assignable + avl_set_impl &operator =(const avl_set_impl&); + + typedef tree_type implementation_defined; + /// @endcond + + public: + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::value_traits value_traits; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::insert_commit_data insert_commit_data; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; + + /// @cond + private: + tree_type tree_; + /// @endcond + + public: + //! Effects: Constructs an empty avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor of the value_compare object throws. + avl_set_impl( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(cmp, v_traits) + {} + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! cmp must be a comparison function that induces a strict weak ordering. + //! + //! Effects: Constructs an empty avl_set and inserts elements from + //! [b, e). + //! + //! Complexity: Linear in N if [b, e) is already sorted using + //! comp and otherwise N * log N, where N is std::distance(last, first). + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor/operator() of the value_compare object throws. + template + avl_set_impl( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(true, b, e, cmp, v_traits) + {} + + //! Effects: Detaches all elements from this. The objects in the avl_set + //! are not deleted (i.e. no destructors are called). + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + ~avl_set_impl() + {} + + //! Effects: Returns an iterator pointing to the beginning of the avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator begin() + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator begin() const + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cbegin() const + { return tree_.cbegin(); } + + //! Effects: Returns an iterator pointing to the end of the avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return tree_.cend(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning of the + //! reversed avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rbegin() + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rbegin() const + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crbegin() const + { return tree_.crbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rend() + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rend() const + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crend() const + { return tree_.crend(); } + + //! Precondition: end_iterator must be a valid end iterator + //! of avl_set. + //! + //! Effects: Returns a const reference to the avl_set associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static avl_set_impl &container_from_end_iterator(iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &avl_set_impl::tree_); + } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of avl_set. + //! + //! Effects: Returns a const reference to the set associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const avl_set_impl &container_from_end_iterator(const_iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &avl_set_impl::tree_); + } + + //! Precondition: it must be a valid iterator of set. + //! + //! Effects: Returns a reference to the set associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static avl_set_impl &container_from_iterator(iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &avl_set_impl::tree_); + } + + //! Precondition: it must be a valid const_iterator of set. + //! + //! Effects: Returns a const reference to the set associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static const avl_set_impl &container_from_iterator(const_iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &avl_set_impl::tree_); + } + + //! Effects: Returns the key_compare object used by the avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: If key_compare copy-constructor throws. + key_compare key_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns the value_compare object used by the avl_set. + //! + //! Complexity: Constant. + //! + //! Throws: If value_compare copy-constructor throws. + value_compare value_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bool empty() const + { return tree_.empty(); } + + //! Effects: Returns the number of elements stored in the avl_set. + //! + //! Complexity: Linear to elements contained in *this if, + //! constant-time size option is enabled. Constant-time otherwise. + //! + //! Throws: Nothing. + size_type size() const + { return tree_.size(); } + + //! Effects: Swaps the contents of two sets. + //! + //! Complexity: Constant. + //! + //! Throws: If the swap() call for the comparison functor + //! found using ADL throws. Strong guarantee. + void swap(avl_set_impl& other) + { tree_.swap(other.tree_); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. + template + void clone_from(const avl_set_impl &src, Cloner cloner, Disposer disposer) + { tree_.clone_from(src.tree_, cloner, disposer); } + + //! Requires: value must be an lvalue + //! + //! Effects: Tries to inserts value into the avl_set. + //! + //! Returns: If the value + //! is not already present inserts it and returns a pair containing the + //! iterator to the new value and true. If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + std::pair insert(reference value) + { return tree_.insert_unique(value); } + + //! Requires: value must be an lvalue + //! + //! Effects: Tries to to insert x into the avl_set, using "hint" + //! as a hint to where it will be inserted. + //! + //! Returns: An iterator that points to the position where the + //! new element was inserted into the avl_set. + //! + //! Complexity: Logarithmic in general, but it's amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert(const_iterator hint, reference value) + { return tree_.insert_unique(hint, value); } + + //! Requires: key_value_comp must be a comparison function that induces + //! the same strict weak ordering as value_compare. The difference is that + //! key_value_comp compares an aavlitrary key with the contained values. + //! + //! Effects: Checks if a value can be inserted in the avl_set, using + //! a user provided key instead of the value itself. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. If the value can be inserted returns true in the returned + //! pair boolean and fills "commit_data" that is meant to be used with + //! the "insert_commit" function. + //! + //! Complexity: Average complexity is at most logarithmic. + //! + //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! + //! Notes: This function is used to improve performance when constructing + //! a value_type is expensive: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the order is much cheaper to construct + //! than the value_type and this function offers the possibility to use that + //! part to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the value_type and use + //! "insert_commit" to insert the object in constant-time. This gives a total + //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_commit" only if no more + //! objects are inserted or erased from the avl_set. + template + std::pair insert_check + (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { return tree_.insert_unique_check(key, key_value_comp, commit_data); } + + //! Requires: key_value_comp must be a comparison function that induces + //! the same strict weak ordering as value_compare. The difference is that + //! key_value_comp compares an aavlitrary key with the contained values. + //! + //! Effects: Checks if a value can be inserted in the avl_set, using + //! a user provided key instead of the value itself, using "hint" + //! as a hint to where it will be inserted. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. If the value can be inserted returns true in the returned + //! pair boolean and fills "commit_data" that is meant to be used with + //! the "insert_commit" function. + //! + //! Complexity: Logarithmic in general, but it's amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! + //! Notes: This function is used to improve performance when constructing + //! a value_type is expensive: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! constructing that is used to impose the order is much cheaper to construct + //! than the value_type and this function offers the possibility to use that key + //! to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the value_type and use + //! "insert_commit" to insert the object in constant-time. This can give a total + //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_commit" only if no more + //! objects are inserted or erased from the avl_set. + template + std::pair insert_check + (const_iterator hint, const KeyType &key + ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { return tree_.insert_unique_check(hint, key, key_value_comp, commit_data); } + + //! Requires: value must be an lvalue of type value_type. commit_data + //! must have been obtained from a previous call to "insert_check". + //! No objects should have been inserted or erased from the avl_set between + //! the "insert_check" that filled "commit_data" and the call to "insert_commit". + //! + //! Effects: Inserts the value in the avl_set using the information obtained + //! from the "commit_data" that a previous "insert_check" filled. + //! + //! Returns: An iterator to the newly inserted object. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function has only sense if a "insert_check" has been + //! previously executed to fill "commit_data". No value should be inserted or + //! erased between the "insert_check" and "insert_commit" calls. + iterator insert_commit(reference value, const insert_commit_data &commit_data) + { return tree_.insert_unique_commit(value, commit_data); } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Inserts a range into the avl_set. + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert(Iterator b, Iterator e) + { tree_.insert_unique(b, e); } + + //! Effects: Erases the element pointed to by pos. + //! + //! Complexity: Average complexity is constant time. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator i) + { return tree_.erase(i); } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator b, iterator e) + { return tree_.erase(b, e); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size()) + this->count(value)). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return tree_.erase(value); } + + //! Effects: Erases all the elements that compare equal with + //! the given key and the given comparison functor. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(key, comp)). + //! + //! Throws: If the comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyValueCompare comp) + { return tree_.erase(key, comp); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element pointed to by pos. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { return tree_.erase_and_dispose(i, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) + { return tree_.erase_and_dispose(b, e, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: If the internal value_compare ordering function throws. + //! + //! Complexity: O(log(size() + this->count(value)). Basic guarantee. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { return tree_.erase_and_dispose(value, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(key, comp)). + //! + //! Throws: If comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) + { return tree_.erase_and_dispose(key, comp, disposer); } + + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { return tree_.clear(); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + void clear_and_dispose(Disposer disposer) + { return tree_.clear_and_dispose(disposer); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If the internal value_compare ordering function throws. + size_type count(const_reference value) const + { return tree_.find(value) != end(); } + + //! Effects: Returns the number of contained elements with the same key + //! compared with the given comparison functor. + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If comp ordering function throws. + template + size_type count(const KeyType& key, KeyValueCompare comp) const + { return tree_.find(key, comp) != end(); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator lower_bound(const_reference value) + { return tree_.lower_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator lower_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.lower_bound(key, comp); } + + //! Effects: Returns a const iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator lower_bound(const_reference value) const + { return tree_.lower_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const + { return tree_.lower_bound(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator upper_bound(const_reference value) + { return tree_.upper_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator upper_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.upper_bound(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator upper_bound(const_reference value) const + { return tree_.upper_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const + { return tree_.upper_bound(key, comp); } + + //! Effects: Finds an iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator find(const_reference value) + { return tree_.find(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds an iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator find(const KeyType& key, KeyValueCompare comp) + { return tree_.find(key, comp); } + + //! Effects: Finds a const_iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator find(const_reference value) const + { return tree_.find(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a const_iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator find(const KeyType& key, KeyValueCompare comp) const + { return tree_.find(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair equal_range(const_reference value) + { return tree_.equal_range(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return tree_.equal_range(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair + equal_range(const_reference value) const + { return tree_.equal_range(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair + equal_range(const KeyType& key, KeyValueCompare comp) const + { return tree_.equal_range(key, comp); } + + //! Requires: value must be an lvalue and shall be in a avl_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the avl_set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a avl_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! avl_set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a avl_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the avl_set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator iterator_to(reference value) + { return tree_.iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a avl_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! avl_set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator iterator_to(const_reference value) const + { return tree_.iterator_to(value); } + + //! Requires: value shall not be in a avl_set/avl_multiset. + //! + //! Effects: init_node puts the hook of a value in a well-known default + //! state. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This function puts the hook in the well-known default state + //! used by auto_unlink and safe hooks. + static void init_node(reference value) + { tree_type::init_node(value); } + + //! Effects: Unlinks the leftmost node from the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + pointer unlink_leftmost_without_rebalance() + { return tree_.unlink_leftmost_without_rebalance(); } + + //! Requires: replace_this must be a valid iterator of *this + //! and with_this must not be inserted in any tree. + //! + //! Effects: Replaces replace_this in its position in the + //! tree with with_this. The tree does not need to be rebalanced. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! with_this is not equivalent to *replace_this according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + void replace_node(iterator replace_this, reference with_this) + { tree_.replace_node(replace_this, with_this); } + + /// @cond + friend bool operator==(const avl_set_impl &x, const avl_set_impl &y) + { return x.tree_ == y.tree_; } + + friend bool operator<(const avl_set_impl &x, const avl_set_impl &y) + { return x.tree_ < y.tree_; } + /// @endcond +}; + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator!= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const avl_set_impl &x, const avl_set_impl &y) +#else +(const avl_set_impl &x, const avl_set_impl &y) +#endif +{ return !(x == y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator> +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const avl_set_impl &x, const avl_set_impl &y) +#else +(const avl_set_impl &x, const avl_set_impl &y) +#endif +{ return y < x; } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator<= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const avl_set_impl &x, const avl_set_impl &y) +#else +(const avl_set_impl &x, const avl_set_impl &y) +#endif +{ return !(y < x); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator>= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const avl_set_impl &x, const avl_set_impl &y) +#else +(const avl_set_impl &x, const avl_set_impl &y) +#endif +{ return !(x < y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline void swap +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(avl_set_impl &x, avl_set_impl &y) +#else +(avl_set_impl &x, avl_set_impl &y) +#endif +{ x.swap(y); } + +//! Helper metafunction to define a \c avl_set that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_avl_set +{ + /// @cond + typedef avl_set_impl + < typename make_avltree_opt::type + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class avl_set + : public make_avl_set::type +{ + typedef typename make_avl_set + ::type Base; + + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + avl_set( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + avl_set( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(b, e, cmp, v_traits) + {} + + static avl_set &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const avl_set &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static avl_set &container_from_iterator(iterator end_iterator) + { return static_cast(Base::container_from_iterator(end_iterator)); } + + static const avl_set &container_from_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_iterator(end_iterator)); } +}; + +#endif + +//! The class template avl_multiset is an intrusive container, that mimics most of +//! the interface of std::avl_multiset as described in the C++ standard. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<> and +//! \c compare<>. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class avl_multiset_impl +{ + /// @cond + typedef avltree_impl tree_type; + + //Non-copyable and non-assignable + avl_multiset_impl (const avl_multiset_impl&); + avl_multiset_impl &operator =(const avl_multiset_impl&); + typedef tree_type implementation_defined; + /// @endcond + + public: + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::value_traits value_traits; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::insert_commit_data insert_commit_data; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; + + /// @cond + private: + tree_type tree_; + /// @endcond + + public: + //! Effects: Constructs an empty avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor/operator() of the value_compare object throws. + avl_multiset_impl( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(cmp, v_traits) + {} + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! cmp must be a comparison function that induces a strict weak ordering. + //! + //! Effects: Constructs an empty avl_multiset and inserts elements from + //! [b, e). + //! + //! Complexity: Linear in N if [b, e) is already sorted using + //! comp and otherwise N * log N, where N is the distance between first and last + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor/operator() of the value_compare object throws. + template + avl_multiset_impl( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(false, b, e, cmp, v_traits) + {} + + //! Effects: Detaches all elements from this. The objects in the avl_multiset + //! are not deleted (i.e. no destructors are called). + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + ~avl_multiset_impl() + {} + + //! Effects: Returns an iterator pointing to the beginning of the avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator begin() + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator begin() const + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cbegin() const + { return tree_.cbegin(); } + + //! Effects: Returns an iterator pointing to the end of the avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return tree_.cend(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning of the + //! reversed avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rbegin() + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rbegin() const + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crbegin() const + { return tree_.crbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rend() + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rend() const + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crend() const + { return tree_.crend(); } + + //! Precondition: end_iterator must be a valid end iterator + //! of avl_multiset. + //! + //! Effects: Returns a const reference to the avl_multiset associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static avl_multiset_impl &container_from_end_iterator(iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &avl_multiset_impl::tree_); + } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of avl_multiset. + //! + //! Effects: Returns a const reference to the avl_multiset associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const avl_multiset_impl &container_from_end_iterator(const_iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &avl_multiset_impl::tree_); + } + + //! Precondition: it must be a valid iterator of multiset. + //! + //! Effects: Returns a const reference to the multiset associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static avl_multiset_impl &container_from_iterator(iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &avl_multiset_impl::tree_); + } + + //! Precondition: it must be a valid const_iterator of multiset. + //! + //! Effects: Returns a const reference to the multiset associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static const avl_multiset_impl &container_from_iterator(const_iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &avl_multiset_impl::tree_); + } + + //! Effects: Returns the key_compare object used by the avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If key_compare copy-constructor throws. + key_compare key_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns the value_compare object used by the avl_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If value_compare copy-constructor throws. + value_compare value_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bool empty() const + { return tree_.empty(); } + + //! Effects: Returns the number of elements stored in the avl_multiset. + //! + //! Complexity: Linear to elements contained in *this if, + //! constant-time size option is enabled. Constant-time otherwise. + //! + //! Throws: Nothing. + size_type size() const + { return tree_.size(); } + + //! Effects: Swaps the contents of two avl_multisets. + //! + //! Complexity: Constant. + //! + //! Throws: If the swap() call for the comparison functor + //! found using ADL throws. Strong guarantee. + void swap(avl_multiset_impl& other) + { tree_.swap(other.tree_); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. Basic guarantee. + template + void clone_from(const avl_multiset_impl &src, Cloner cloner, Disposer disposer) + { tree_.clone_from(src.tree_, cloner, disposer); } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the avl_multiset. + //! + //! Returns: An iterator that points to the position where the new + //! element was inserted. + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert(reference value) + { return tree_.insert_equal(value); } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts x into the avl_multiset, using pos as a hint to + //! where it will be inserted. + //! + //! Returns: An iterator that points to the position where the new + //! element was inserted. + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert(const_iterator hint, reference value) + { return tree_.insert_equal(hint, value); } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Inserts a range into the avl_multiset. + //! + //! Returns: An iterator that points to the position where the new + //! element was inserted. + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert(Iterator b, Iterator e) + { tree_.insert_equal(b, e); } + + //! Effects: Erases the element pointed to by pos. + //! + //! Complexity: Average complexity is constant time. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator i) + { return tree_.erase(i); } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator b, iterator e) + { return tree_.erase(b, e); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(value)). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return tree_.erase(value); } + + //! Effects: Erases all the elements that compare equal with + //! the given key and the given comparison functor. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(key, comp)). + //! + //! Throws: If comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyValueCompare comp) + { return tree_.erase(key, comp); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Effects: Erases the element pointed to by pos. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { return tree_.erase_and_dispose(i, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) + { return tree_.erase_and_dispose(b, e, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(value)). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { return tree_.erase_and_dispose(value, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(key, comp)). + //! + //! Throws: If comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) + { return tree_.erase_and_dispose(key, comp, disposer); } + + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { return tree_.clear(); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + void clear_and_dispose(Disposer disposer) + { return tree_.clear_and_dispose(disposer); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If the internal value_compare ordering function throws. + size_type count(const_reference value) const + { return tree_.count(value); } + + //! Effects: Returns the number of contained elements with the same key + //! compared with the given comparison functor. + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If comp ordering function throws. + template + size_type count(const KeyType& key, KeyValueCompare comp) const + { return tree_.count(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator lower_bound(const_reference value) + { return tree_.lower_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator lower_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.lower_bound(key, comp); } + + //! Effects: Returns a const iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator lower_bound(const_reference value) const + { return tree_.lower_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const + { return tree_.lower_bound(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator upper_bound(const_reference value) + { return tree_.upper_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator upper_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.upper_bound(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator upper_bound(const_reference value) const + { return tree_.upper_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const + { return tree_.upper_bound(key, comp); } + + //! Effects: Finds an iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator find(const_reference value) + { return tree_.find(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds an iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator find(const KeyType& key, KeyValueCompare comp) + { return tree_.find(key, comp); } + + //! Effects: Finds a const_iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator find(const_reference value) const + { return tree_.find(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a const_iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator find(const KeyType& key, KeyValueCompare comp) const + { return tree_.find(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair equal_range(const_reference value) + { return tree_.equal_range(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return tree_.equal_range(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair + equal_range(const_reference value) const + { return tree_.equal_range(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair + equal_range(const KeyType& key, KeyValueCompare comp) const + { return tree_.equal_range(key, comp); } + + //! Requires: value must be an lvalue and shall be in a avl_multiset of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the avl_multiset + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a avl_multiset of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! avl_multiset that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a avl_multiset of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the avl_multiset + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator iterator_to(reference value) + { return tree_.iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a avl_multiset of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! avl_multiset that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator iterator_to(const_reference value) const + { return tree_.iterator_to(value); } + + //! Requires: value shall not be in a avl_multiset/avl_multiset. + //! + //! Effects: init_node puts the hook of a value in a well-known default + //! state. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This function puts the hook in the well-known default state + //! used by auto_unlink and safe hooks. + static void init_node(reference value) + { tree_type::init_node(value); } + + //! Effects: Unlinks the leftmost node from the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + pointer unlink_leftmost_without_rebalance() + { return tree_.unlink_leftmost_without_rebalance(); } + + //! Requires: replace_this must be a valid iterator of *this + //! and with_this must not be inserted in any tree. + //! + //! Effects: Replaces replace_this in its position in the + //! tree with with_this. The tree does not need to be rebalanced. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! with_this is not equivalent to *replace_this according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + void replace_node(iterator replace_this, reference with_this) + { tree_.replace_node(replace_this, with_this); } + + /// @cond + friend bool operator==(const avl_multiset_impl &x, const avl_multiset_impl &y) + { return x.tree_ == y.tree_; } + + friend bool operator<(const avl_multiset_impl &x, const avl_multiset_impl &y) + { return x.tree_ < y.tree_; } + /// @endcond +}; + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator!= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const avl_multiset_impl &x, const avl_multiset_impl &y) +#else +(const avl_multiset_impl &x, const avl_multiset_impl &y) +#endif +{ return !(x == y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator> +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const avl_multiset_impl &x, const avl_multiset_impl &y) +#else +(const avl_multiset_impl &x, const avl_multiset_impl &y) +#endif +{ return y < x; } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator<= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const avl_multiset_impl &x, const avl_multiset_impl &y) +#else +(const avl_multiset_impl &x, const avl_multiset_impl &y) +#endif +{ return !(y < x); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator>= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const avl_multiset_impl &x, const avl_multiset_impl &y) +#else +(const avl_multiset_impl &x, const avl_multiset_impl &y) +#endif +{ return !(x < y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline void swap +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(avl_multiset_impl &x, avl_multiset_impl &y) +#else +(avl_multiset_impl &x, avl_multiset_impl &y) +#endif +{ x.swap(y); } + +//! Helper metafunction to define a \c avl_multiset that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_avl_multiset +{ + /// @cond + typedef avl_multiset_impl + < typename make_avltree_opt::type + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class avl_multiset + : public make_avl_multiset::type +{ + typedef typename make_avl_multiset + ::type Base; + + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + avl_multiset( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + avl_multiset( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(b, e, cmp, v_traits) + {} + + static avl_multiset &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const avl_multiset &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static avl_multiset &container_from_iterator(iterator end_iterator) + { return static_cast(Base::container_from_iterator(end_iterator)); } + + static const avl_multiset &container_from_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_iterator(end_iterator)); } +}; + +#endif + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_AVL_SET_HPP diff --git a/win32/include/boost/intrusive/avl_set_hook.hpp b/win32/include/boost/intrusive/avl_set_hook.hpp new file mode 100755 index 000000000..d00f84fb1 --- /dev/null +++ b/win32/include/boost/intrusive/avl_set_hook.hpp @@ -0,0 +1,273 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_AVL_SET_HOOK_HPP +#define BOOST_INTRUSIVE_AVL_SET_HOOK_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond +template +struct get_avl_set_node_algo +{ + typedef avltree_algorithms > type; +}; +/// @endcond + +//! Helper metafunction to define a \c avl_set_base_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_avl_set_base_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3, O4>::type packed_options; + + typedef detail::generic_hook + < get_avl_set_node_algo + , typename packed_options::tag + , packed_options::link_mode + , detail::AvlSetBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Derive a class from avl_set_base_hook in order to store objects in +//! in an avl_set/avl_multiset. avl_set_base_hook holds the data necessary to maintain +//! the avl_set/avl_multiset and provides an appropriate value_traits class for avl_set/avl_multiset. +//! +//! The hook admits the following options: \c tag<>, \c void_pointer<>, +//! \c link_mode<> and \c optimize_size<>. +//! +//! \c tag<> defines a tag to identify the node. +//! The same tag value can be used in different classes, but if a class is +//! derived from more than one \c list_base_hook, then each \c list_base_hook needs its +//! unique tag. +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, +//! \c auto_unlink or \c safe_link). +//! +//! \c optimize_size<> will tell the hook to optimize the hook for size instead +//! of speed. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class avl_set_base_hook + : public make_avl_set_base_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + avl_set_base_hook(); + + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + avl_set_base_hook(const avl_set_base_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + avl_set_base_hook& operator=(const avl_set_base_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in a set an assertion is raised. If link_mode is + //! \c auto_unlink and \c is_linked() is true, the node is unlinked. + //! + //! Throws: Nothing. + ~avl_set_base_hook(); + + //! Effects: Swapping two nodes swaps the position of the elements + //! related to those nodes in one or two containers. That is, if the node + //! this is part of the element e1, the node x is part of the element e2 + //! and both elements are included in the containers s1 and s2, then after + //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 + //! at the position of e1. If one element is not in a container, then + //! after the swap-operation the other element is not in a container. + //! Iterators to e1 and e2 related to those nodes are invalidated. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + void swap_nodes(avl_set_base_hook &other); + + //! Precondition: link_mode must be \c safe_link or \c auto_unlink. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c set::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + + //! Effects: Removes the node if it's inserted in a container. + //! This function is only allowed if link_mode is \c auto_unlink. + //! + //! Throws: Nothing. + void unlink(); + #endif +}; + +//! Helper metafunction to define a \c avl_set_member_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_avl_set_member_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3, O4>::type packed_options; + + typedef detail::generic_hook + < get_avl_set_node_algo + , member_tag + , packed_options::link_mode + , detail::NoBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Put a public data member avl_set_member_hook in order to store objects of this class in +//! an avl_set/avl_multiset. avl_set_member_hook holds the data necessary for maintaining the +//! avl_set/avl_multiset and provides an appropriate value_traits class for avl_set/avl_multiset. +//! +//! The hook admits the following options: \c void_pointer<>, +//! \c link_mode<> and \c optimize_size<>. +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, +//! \c auto_unlink or \c safe_link). +//! +//! \c optimize_size<> will tell the hook to optimize the hook for size instead +//! of speed. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class avl_set_member_hook + : public make_avl_set_member_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + avl_set_member_hook(); + + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + avl_set_member_hook(const avl_set_member_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + avl_set_member_hook& operator=(const avl_set_member_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in a set an assertion is raised. If link_mode is + //! \c auto_unlink and \c is_linked() is true, the node is unlinked. + //! + //! Throws: Nothing. + ~avl_set_member_hook(); + + //! Effects: Swapping two nodes swaps the position of the elements + //! related to those nodes in one or two containers. That is, if the node + //! this is part of the element e1, the node x is part of the element e2 + //! and both elements are included in the containers s1 and s2, then after + //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 + //! at the position of e1. If one element is not in a container, then + //! after the swap-operation the other element is not in a container. + //! Iterators to e1 and e2 related to those nodes are invalidated. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + void swap_nodes(avl_set_member_hook &other); + + //! Precondition: link_mode must be \c safe_link or \c auto_unlink. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c set::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + + //! Effects: Removes the node if it's inserted in a container. + //! This function is only allowed if link_mode is \c auto_unlink. + //! + //! Throws: Nothing. + void unlink(); + #endif +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_AVL_SET_HOOK_HPP diff --git a/win32/include/boost/intrusive/avltree.hpp b/win32/include/boost/intrusive/avltree.hpp new file mode 100755 index 000000000..5c7d7a966 --- /dev/null +++ b/win32/include/boost/intrusive/avltree.hpp @@ -0,0 +1,1470 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_AVLTREE_HPP +#define BOOST_INTRUSIVE_AVLTREE_HPP + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond + +template +struct internal_default_avl_set_hook +{ + template static detail::one test(...); + template static detail::two test(typename U::default_avl_set_hook* = 0); + static const bool value = sizeof(test(0)) == sizeof(detail::two); +}; + +template +struct get_default_avl_set_hook +{ + typedef typename T::default_avl_set_hook type; +}; + +template +struct avl_setopt +{ + typedef ValueTraits value_traits; + typedef Compare compare; + typedef SizeType size_type; + static const bool constant_time_size = ConstantTimeSize; +}; + +template +struct avl_set_defaults + : pack_options + < none + , base_hook + < typename detail::eval_if_c + < internal_default_avl_set_hook::value + , get_default_avl_set_hook + , detail::identity + >::type + > + , constant_time_size + , size_type + , compare > + >::type +{}; + +/// @endcond + +//! The class template avltree is an intrusive AVL tree container, that +//! is used to construct intrusive avl_set and avl_multiset containers. +//! The no-throw guarantee holds only, if the value_compare object +//! doesn't throw. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<> and +//! \c compare<>. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class avltree_impl +{ + public: + typedef typename Config::value_traits value_traits; + /// @cond + static const bool external_value_traits = + detail::external_value_traits_is_true::value; + typedef typename detail::eval_if_c + < external_value_traits + , detail::eval_value_traits + , detail::identity + >::type real_value_traits; + /// @endcond + typedef typename real_value_traits::pointer pointer; + typedef typename real_value_traits::const_pointer const_pointer; + typedef typename std::iterator_traits::value_type value_type; + typedef value_type key_type; + typedef typename std::iterator_traits::reference reference; + typedef typename std::iterator_traits::reference const_reference; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename Config::size_type size_type; + typedef typename Config::compare value_compare; + typedef value_compare key_compare; + typedef tree_iterator iterator; + typedef tree_iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef typename real_value_traits::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + typedef avltree_algorithms node_algorithms; + + static const bool constant_time_size = Config::constant_time_size; + static const bool stateful_value_traits = detail::store_cont_ptr_on_it::value; + + /// @cond + private: + typedef detail::size_holder size_traits; + + //noncopyable + avltree_impl (const avltree_impl&); + avltree_impl operator =(const avltree_impl&); + + enum { safemode_or_autounlink = + (int)real_value_traits::link_mode == (int)auto_unlink || + (int)real_value_traits::link_mode == (int)safe_link }; + + //Constant-time size is incompatible with auto-unlink hooks! + BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); + + struct header_plus_size : public size_traits + { node header_; }; + + struct node_plus_pred_t : public detail::ebo_functor_holder + { + node_plus_pred_t(const value_compare &comp) + : detail::ebo_functor_holder(comp) + {} + header_plus_size header_plus_size_; + }; + + struct data_t : public avltree_impl::value_traits + { + typedef typename avltree_impl::value_traits value_traits; + data_t(const value_compare & comp, const value_traits &val_traits) + : value_traits(val_traits), node_plus_pred_(comp) + {} + node_plus_pred_t node_plus_pred_; + } data_; + + const value_compare &priv_comp() const + { return data_.node_plus_pred_.get(); } + + value_compare &priv_comp() + { return data_.node_plus_pred_.get(); } + + const node &priv_header() const + { return data_.node_plus_pred_.header_plus_size_.header_; } + + node &priv_header() + { return data_.node_plus_pred_.header_plus_size_.header_; } + + static node_ptr uncast(const_node_ptr ptr) + { + return node_ptr(const_cast(detail::get_pointer(ptr))); + } + + size_traits &priv_size_traits() + { return data_.node_plus_pred_.header_plus_size_; } + + const size_traits &priv_size_traits() const + { return data_.node_plus_pred_.header_plus_size_; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return data_; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return data_.get_value_traits(*this); } + + real_value_traits &get_real_value_traits(detail::bool_) + { return data_; } + + real_value_traits &get_real_value_traits(detail::bool_) + { return data_.get_value_traits(*this); } + + /// @endcond + + public: + + const real_value_traits &get_real_value_traits() const + { return this->get_real_value_traits(detail::bool_()); } + + real_value_traits &get_real_value_traits() + { return this->get_real_value_traits(detail::bool_()); } + + typedef typename node_algorithms::insert_commit_data insert_commit_data; + + //! Effects: Constructs an empty tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing unless the copy constructor of the value_compare object throws. + avltree_impl( value_compare cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : data_(cmp, v_traits) + { + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(size_type(0)); + } + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! cmp must be a comparison function that induces a strict weak ordering. + //! + //! Effects: Constructs an empty tree and inserts elements from + //! [b, e). + //! + //! Complexity: Linear in N if [b, e) is already sorted using + //! comp and otherwise N * log N, where N is the distance between first and last. + //! + //! Throws: Nothing unless the copy constructor of the value_compare object throws. + template + avltree_impl( bool unique, Iterator b, Iterator e + , value_compare cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : data_(cmp, v_traits) + { + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(size_type(0)); + if(unique) + this->insert_unique(b, e); + else + this->insert_equal(b, e); + } + + //! Effects: Detaches all elements from this. The objects in the set + //! are not deleted (i.e. no destructors are called), but the nodes according to + //! the value_traits template parameter are reinitialized and thus can be reused. + //! + //! Complexity: Linear to elements contained in *this. + //! + //! Throws: Nothing. + ~avltree_impl() + { this->clear(); } + + //! Effects: Returns an iterator pointing to the beginning of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator begin() + { return iterator (node_traits::get_left(node_ptr(&priv_header())), this); } + + //! Effects: Returns a const_iterator pointing to the beginning of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator begin() const + { return cbegin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cbegin() const + { return const_iterator (node_traits::get_left(const_node_ptr(&priv_header())), this); } + + //! Effects: Returns an iterator pointing to the end of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return iterator (node_ptr(&priv_header()), this); } + + //! Effects: Returns a const_iterator pointing to the end of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return cend(); } + + //! Effects: Returns a const_iterator pointing to the end of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return const_iterator (uncast(const_node_ptr(&priv_header())), this); } + + //! Effects: Returns a reverse_iterator pointing to the beginning of the + //! reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rbegin() + { return reverse_iterator(end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rbegin() const + { return const_reverse_iterator(end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crbegin() const + { return const_reverse_iterator(end()); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rend() + { return reverse_iterator(begin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rend() const + { return const_reverse_iterator(begin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crend() const + { return const_reverse_iterator(begin()); } + + //! Precondition: end_iterator must be a valid end iterator + //! of avltree. + //! + //! Effects: Returns a const reference to the avltree associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static avltree_impl &container_from_end_iterator(iterator end_iterator) + { return priv_container_from_end_iterator(end_iterator); } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of avltree. + //! + //! Effects: Returns a const reference to the avltree associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const avltree_impl &container_from_end_iterator(const_iterator end_iterator) + { return priv_container_from_end_iterator(end_iterator); } + + //! Precondition: it must be a valid iterator + //! of rbtree. + //! + //! Effects: Returns a const reference to the tree associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static avltree_impl &container_from_iterator(iterator it) + { return priv_container_from_iterator(it); } + + //! Precondition: it must be a valid end const_iterator + //! of rbtree. + //! + //! Effects: Returns a const reference to the tree associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static const avltree_impl &container_from_iterator(const_iterator it) + { return priv_container_from_iterator(it); } + + //! Effects: Returns the value_compare object used by the tree. + //! + //! Complexity: Constant. + //! + //! Throws: If value_compare copy-constructor throws. + value_compare value_comp() const + { return priv_comp(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bool empty() const + { return node_algorithms::unique(const_node_ptr(&priv_header())); } + + //! Effects: Returns the number of elements stored in the tree. + //! + //! Complexity: Linear to elements contained in *this. + //! + //! Throws: Nothing. + size_type size() const + { + if(constant_time_size) + return this->priv_size_traits().get_size(); + else{ + return (size_type)node_algorithms::size(const_node_ptr(&priv_header())); + } + } + + //! Effects: Swaps the contents of two multisets. + //! + //! Complexity: Constant. + //! + //! Throws: If the comparison functor's swap call throws. + void swap(avltree_impl& other) + { + //This can throw + using std::swap; + swap(priv_comp(), priv_comp()); + //These can't throw + node_algorithms::swap_tree(node_ptr(&priv_header()), node_ptr(&other.priv_header())); + if(constant_time_size){ + size_type backup = this->priv_size_traits().get_size(); + this->priv_size_traits().set_size(other.priv_size_traits().get_size()); + other.priv_size_traits().set_size(backup); + } + } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the tree before the upper bound. + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_equal(reference value) + { + detail::key_nodeptr_comp + key_node_comp(priv_comp(), this); + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + return iterator(node_algorithms::insert_equal_upper_bound + (node_ptr(&priv_header()), to_insert, key_node_comp), this); + } + + //! Requires: value must be an lvalue, and "hint" must be + //! a valid iterator. + //! + //! Effects: Inserts x into the tree, using "hint" as a hint to + //! where it will be inserted. If "hint" is the upper_bound + //! the insertion takes constant time (two comparisons in the worst case) + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_equal(const_iterator hint, reference value) + { + detail::key_nodeptr_comp + key_node_comp(priv_comp(), this); + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + return iterator(node_algorithms::insert_equal + (node_ptr(&priv_header()), hint.pointed_node(), to_insert, key_node_comp), this); + } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Inserts a each element of a range into the tree + //! before the upper bound of the key of each element. + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert_equal(Iterator b, Iterator e) + { + iterator end(this->end()); + for (; b != e; ++b) + this->insert_equal(end, *b); + } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the tree if the value + //! is not already present. + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + std::pair insert_unique(reference value) + { + insert_commit_data commit_data; + std::pair ret = insert_unique_check(value, commit_data); + if(!ret.second) + return ret; + return std::pair (insert_unique_commit(value, commit_data), true); + } + + //! Requires: value must be an lvalue, and "hint" must be + //! a valid iterator + //! + //! Effects: Tries to insert x into the tree, using "hint" as a hint + //! to where it will be inserted. + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time (two comparisons in the worst case) + //! if t is inserted immediately before hint. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_unique(const_iterator hint, reference value) + { + insert_commit_data commit_data; + std::pair ret = insert_unique_check(hint, value, commit_data); + if(!ret.second) + return ret.first; + return insert_unique_commit(value, commit_data); + } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Tries to insert each element of a range into the tree. + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert_unique(Iterator b, Iterator e) + { + if(this->empty()){ + iterator end(this->end()); + for (; b != e; ++b) + this->insert_unique(end, *b); + } + else{ + for (; b != e; ++b) + this->insert_unique(*b); + } + } + + std::pair insert_unique_check + (const_reference value, insert_commit_data &commit_data) + { return insert_unique_check(value, priv_comp(), commit_data); } + + template + std::pair insert_unique_check + (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { + detail::key_nodeptr_comp + comp(key_value_comp, this); + std::pair ret = + (node_algorithms::insert_unique_check + (node_ptr(&priv_header()), key, comp, commit_data)); + return std::pair(iterator(ret.first, this), ret.second); + } + + std::pair insert_unique_check + (const_iterator hint, const_reference value, insert_commit_data &commit_data) + { return insert_unique_check(hint, value, priv_comp(), commit_data); } + + template + std::pair insert_unique_check + (const_iterator hint, const KeyType &key + ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { + detail::key_nodeptr_comp + comp(key_value_comp, this); + std::pair ret = + (node_algorithms::insert_unique_check + (node_ptr(&priv_header()), hint.pointed_node(), key, comp, commit_data)); + return std::pair(iterator(ret.first, this), ret.second); + } + + iterator insert_unique_commit(reference value, const insert_commit_data &commit_data) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + node_algorithms::insert_unique_commit + (node_ptr(&priv_header()), to_insert, commit_data); + return iterator(to_insert, this); + } + + //! Effects: Erases the element pointed to by pos. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator i) + { + iterator ret(i); + ++ret; + node_ptr to_erase(i.pointed_node()); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase)); + node_algorithms::erase(&priv_header(), to_erase); + this->priv_size_traits().decrement(); + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + return ret; + } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator b, iterator e) + { size_type n; return private_erase(b, e, n); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return this->erase(value, priv_comp()); } + + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyValueCompare comp) + { + std::pair p = this->equal_range(key, comp); + size_type n; + private_erase(p.first, p.second, n); + return n; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element pointed to by pos. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { + node_ptr to_erase(i.pointed_node()); + iterator ret(this->erase(i)); + disposer(get_real_value_traits().to_value_ptr(to_erase)); + return ret; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) + { size_type n; return private_erase(b, e, n, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { + std::pair p = this->equal_range(value); + size_type n; + private_erase(p.first, p.second, n, disposer); + return n; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) + { + std::pair p = this->equal_range(key, comp); + size_type n; + private_erase(p.first, p.second, n, disposer); + return n; + } + + //! Effects: Erases all of the elements. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { + if(safemode_or_autounlink){ + this->clear_and_dispose(detail::null_disposer()); + } + else{ + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(0); + } + } + + //! Effects: Erases all of the elements calling disposer(p) for + //! each node to be erased. + //! Complexity: Average complexity for is at most O(log(size() + N)), + //! where N is the number of elements in the container. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. Calls N times to disposer functor. + template + void clear_and_dispose(Disposer disposer) + { + node_algorithms::clear_and_dispose(node_ptr(&priv_header()) + , detail::node_disposer(disposer, this)); + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(0); + } + + //! Effects: Returns the number of contained elements with the given value + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given value. + //! + //! Throws: Nothing. + size_type count(const_reference value) const + { return this->count(value, priv_comp()); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: Nothing. + template + size_type count(const KeyType &key, KeyValueCompare comp) const + { + std::pair ret = this->equal_range(key, comp); + return std::distance(ret.first, ret.second); + } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + iterator lower_bound(const_reference value) + { return this->lower_bound(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator lower_bound(const_reference value) const + { return this->lower_bound(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + iterator lower_bound(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return iterator(node_algorithms::lower_bound + (const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Returns a const iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return const_iterator(node_algorithms::lower_bound + (const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + iterator upper_bound(const_reference value) + { return this->upper_bound(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k according to comp or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + iterator upper_bound(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return iterator(node_algorithms::upper_bound + (const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator upper_bound(const_reference value) const + { return this->upper_bound(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k according to comp or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return const_iterator(node_algorithms::upper_bound + (const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Finds an iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + iterator find(const_reference value) + { return this->find(value, priv_comp()); } + + //! Effects: Finds an iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + iterator find(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return iterator + (node_algorithms::find(const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Finds a const_iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator find(const_reference value) const + { return this->find(value, priv_comp()); } + + //! Effects: Finds a const_iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator find(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return const_iterator + (node_algorithms::find(const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + std::pair equal_range(const_reference value) + { return this->equal_range(value, priv_comp()); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + std::pair equal_range(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + std::pair ret + (node_algorithms::equal_range(const_node_ptr(&priv_header()), key, key_node_comp)); + return std::pair(iterator(ret.first, this), iterator(ret.second, this)); + } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + std::pair + equal_range(const_reference value) const + { return this->equal_range(value, priv_comp()); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + std::pair + equal_range(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + std::pair ret + (node_algorithms::equal_range(const_node_ptr(&priv_header()), key, key_node_comp)); + return std::pair(const_iterator(ret.first, this), const_iterator(ret.second, this)); + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. + template + void clone_from(const avltree_impl &src, Cloner cloner, Disposer disposer) + { + this->clear_and_dispose(disposer); + if(!src.empty()){ + node_algorithms::clone + (const_node_ptr(&src.priv_header()) + ,node_ptr(&this->priv_header()) + ,detail::node_cloner(cloner, this) + ,detail::node_disposer(disposer, this)); + this->priv_size_traits().set_size(src.priv_size_traits().get_size()); + } + } + + //! Effects: Unlinks the leftmost node from the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + pointer unlink_leftmost_without_rebalance() + { + node_ptr to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance + (node_ptr(&priv_header()))); + if(!to_be_disposed) + return 0; + this->priv_size_traits().decrement(); + if(safemode_or_autounlink)//If this is commented does not work with normal_link + node_algorithms::init(to_be_disposed); + return get_real_value_traits().to_value_ptr(to_be_disposed); + } + + //! Requires: replace_this must be a valid iterator of *this + //! and with_this must not be inserted in any tree. + //! + //! Effects: Replaces replace_this in its position in the + //! tree with with_this. The tree does not need to be rebalanced. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! with_this is not equivalent to *replace_this according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + void replace_node(iterator replace_this, reference with_this) + { + node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this) + , node_ptr(&priv_header()) + , get_real_value_traits().to_node_ptr(with_this)); + } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + return iterator (value_traits::to_node_ptr(value), 0); + } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), 0); + } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator iterator_to(reference value) + { return iterator (value_traits::to_node_ptr(value), this); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator iterator_to(const_reference value) const + { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this); } + + //! Requires: value shall not be in a tree. + //! + //! Effects: init_node puts the hook of a value in a well-known default + //! state. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This function puts the hook in the well-known default state + //! used by auto_unlink and safe hooks. + static void init_node(reference value) + { node_algorithms::init(value_traits::to_node_ptr(value)); } + +/* + //! Effects: removes x from a tree of the appropriate type. It has no effect, + //! if x is not in such a tree. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This static function is only usable with the "safe mode" + //! hook and non-constant time size lists. Otherwise, the user must use + //! the non-static "erase(reference )" member. If the user calls + //! this function with a non "safe mode" or constant time size list + //! a compilation error will be issued. + template + static void remove_node(T& value) + { + //This function is only usable for safe mode hooks and non-constant + //time lists. + //BOOST_STATIC_ASSERT((!(safemode_or_autounlink && constant_time_size))); + BOOST_STATIC_ASSERT((!constant_time_size)); + BOOST_STATIC_ASSERT((boost::is_convertible::value)); + node_ptr to_remove(value_traits::to_node_ptr(value)); + node_algorithms::unlink_and_rebalance(to_remove); + if(safemode_or_autounlink) + node_algorithms::init(to_remove); + } +*/ + + /// @cond + private: + template + iterator private_erase(iterator b, iterator e, size_type &n, Disposer disposer) + { + for(n = 0; b != e; ++n) + this->erase_and_dispose(b++, disposer); + return b; + } + + iterator private_erase(iterator b, iterator e, size_type &n) + { + for(n = 0; b != e; ++n) + this->erase(b++); + return b; + } + /// @endcond + + private: + static avltree_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) + { + header_plus_size *r = detail::parent_from_member + ( detail::get_pointer(end_iterator.pointed_node()), &header_plus_size::header_); + node_plus_pred_t *n = detail::parent_from_member + (r, &node_plus_pred_t::header_plus_size_); + data_t *d = detail::parent_from_member(n, &data_t::node_plus_pred_); + avltree_impl *avl = detail::parent_from_member(d, &avltree_impl::data_); + return *avl; + } + + static avltree_impl &priv_container_from_iterator(const const_iterator &it) + { return priv_container_from_end_iterator(it.end_iterator_from_it()); } +}; + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator< +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const avltree_impl &x, const avltree_impl &y) +#else +(const avltree_impl &x, const avltree_impl &y) +#endif +{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +bool operator== +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const avltree_impl &x, const avltree_impl &y) +#else +(const avltree_impl &x, const avltree_impl &y) +#endif +{ + typedef avltree_impl tree_type; + typedef typename tree_type::const_iterator const_iterator; + + if(tree_type::constant_time_size && x.size() != y.size()){ + return false; + } + const_iterator end1 = x.end(); + const_iterator i1 = x.begin(); + const_iterator i2 = y.begin(); + if(tree_type::constant_time_size){ + while (i1 != end1 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1; + } + else{ + const_iterator end2 = y.end(); + while (i1 != end1 && i2 != end2 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1 && i2 == end2; + } +} + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator!= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const avltree_impl &x, const avltree_impl &y) +#else +(const avltree_impl &x, const avltree_impl &y) +#endif +{ return !(x == y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator> +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const avltree_impl &x, const avltree_impl &y) +#else +(const avltree_impl &x, const avltree_impl &y) +#endif +{ return y < x; } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator<= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const avltree_impl &x, const avltree_impl &y) +#else +(const avltree_impl &x, const avltree_impl &y) +#endif +{ return !(y < x); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator>= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const avltree_impl &x, const avltree_impl &y) +#else +(const avltree_impl &x, const avltree_impl &y) +#endif +{ return !(x < y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline void swap +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(avltree_impl &x, avltree_impl &y) +#else +(avltree_impl &x, avltree_impl &y) +#endif +{ x.swap(y); } + +/// @cond +template +struct make_avltree_opt +{ + typedef typename pack_options + < avl_set_defaults, O1, O2, O3, O4>::type packed_options; + typedef typename detail::get_value_traits + ::type value_traits; + + typedef avl_setopt + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + > type; +}; +/// @endcond + +//! Helper metafunction to define a \c avltree that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_avltree +{ + /// @cond + typedef avltree_impl + < typename make_avltree_opt::type + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class avltree + : public make_avltree::type +{ + typedef typename make_avltree + ::type Base; + + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::real_value_traits real_value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + avltree( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + avltree( bool unique, Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(unique, b, e, cmp, v_traits) + {} + + static avltree &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const avltree &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static avltree &container_from_iterator(iterator it) + { return static_cast(Base::container_from_iterator(it)); } + + static const avltree &container_from_iterator(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } +}; + +#endif + + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_AVLTREE_HPP diff --git a/win32/include/boost/intrusive/avltree_algorithms.hpp b/win32/include/boost/intrusive/avltree_algorithms.hpp new file mode 100755 index 000000000..080672adc --- /dev/null +++ b/win32/include/boost/intrusive/avltree_algorithms.hpp @@ -0,0 +1,993 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Daniel K. O. 2005. +// (C) Copyright Ion Gaztanaga 2007. +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP +#define BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP + +#include + +#include +#include + +#include +#include +#include + + +namespace boost { +namespace intrusive { + +//! avltree_algorithms is configured with a NodeTraits class, which encapsulates the +//! information about the node to be manipulated. NodeTraits must support the +//! following interface: +//! +//! Typedefs: +//! +//! node: The type of the node that forms the circular list +//! +//! node_ptr: A pointer to a node +//! +//! const_node_ptr: A pointer to a const node +//! +//! balance: The type of the balance factor +//! +//! Static functions: +//! +//! static node_ptr get_parent(const_node_ptr n); +//! +//! static void set_parent(node_ptr n, node_ptr parent); +//! +//! static node_ptr get_left(const_node_ptr n); +//! +//! static void set_left(node_ptr n, node_ptr left); +//! +//! static node_ptr get_right(const_node_ptr n); +//! +//! static void set_right(node_ptr n, node_ptr right); +//! +//! static balance get_balance(const_node_ptr n); +//! +//! static void set_balance(node_ptr n, balance b); +//! +//! static balance negative(); +//! +//! static balance zero(); +//! +//! static balance positive(); +template +class avltree_algorithms +{ + public: + typedef typename NodeTraits::node node; + typedef NodeTraits node_traits; + typedef typename NodeTraits::node_ptr node_ptr; + typedef typename NodeTraits::const_node_ptr const_node_ptr; + typedef typename NodeTraits::balance balance; + + /// @cond + private: + typedef detail::tree_algorithms tree_algorithms; + + template + struct avltree_node_cloner + : private detail::ebo_functor_holder + { + typedef detail::ebo_functor_holder base_t; + + avltree_node_cloner(F f) + : base_t(f) + {} + + node_ptr operator()(node_ptr p) + { + node_ptr n = base_t::get()(p); + NodeTraits::set_balance(n, NodeTraits::get_balance(p)); + return n; + } + }; + + struct avltree_erase_fixup + { + void operator()(node_ptr to_erase, node_ptr successor) + { NodeTraits::set_balance(successor, NodeTraits::get_balance(to_erase)); } + }; + + static node_ptr uncast(const_node_ptr ptr) + { + return node_ptr(const_cast(::boost::intrusive::detail::get_pointer(ptr))); + } + /// @endcond + + public: + static node_ptr begin_node(const_node_ptr header) + { return tree_algorithms::begin_node(header); } + + static node_ptr end_node(const_node_ptr header) + { return tree_algorithms::end_node(header); } + + //! This type is the information that will be + //! filled by insert_unique_check + typedef typename tree_algorithms::insert_commit_data insert_commit_data; + + //! Requires: header1 and header2 must be the header nodes + //! of two trees. + //! + //! Effects: Swaps two trees. After the function header1 will contain + //! links to the second tree and header2 will have links to the first tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static void swap_tree(node_ptr header1, node_ptr header2) + { return tree_algorithms::swap_tree(header1, header2); } + + //! Requires: node1 and node2 can't be header nodes + //! of two trees. + //! + //! Effects: Swaps two nodes. After the function node1 will be inserted + //! in the position node2 before the function. node2 will be inserted in the + //! position node1 had before the function. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! node1 and node2 are not equivalent according to the ordering rules. + //! + //!Experimental function + static void swap_nodes(node_ptr node1, node_ptr node2) + { + if(node1 == node2) + return; + + node_ptr header1(tree_algorithms::get_header(node1)), header2(tree_algorithms::get_header(node2)); + swap_nodes(node1, header1, node2, header2); + } + + //! Requires: node1 and node2 can't be header nodes + //! of two trees with header header1 and header2. + //! + //! Effects: Swaps two nodes. After the function node1 will be inserted + //! in the position node2 before the function. node2 will be inserted in the + //! position node1 had before the function. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! node1 and node2 are not equivalent according to the ordering rules. + //! + //!Experimental function + static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, node_ptr header2) + { + if(node1 == node2) return; + + tree_algorithms::swap_nodes(node1, header1, node2, header2); + //Swap balance + balance c = NodeTraits::get_balance(node1); + NodeTraits::set_balance(node1, NodeTraits::get_balance(node2)); + NodeTraits::set_balance(node2, c); + } + + //! Requires: node_to_be_replaced must be inserted in a tree + //! and new_node must not be inserted in a tree. + //! + //! Effects: Replaces node_to_be_replaced in its position in the + //! tree with new_node. The tree does not need to be rebalanced + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! new_node is not equivalent to node_to_be_replaced according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing and comparison is needed. + //! + //!Experimental function + static void replace_node(node_ptr node_to_be_replaced, node_ptr new_node) + { + if(node_to_be_replaced == new_node) + return; + replace_node(node_to_be_replaced, tree_algorithms::get_header(node_to_be_replaced), new_node); + } + + //! Requires: node_to_be_replaced must be inserted in a tree + //! with header "header" and new_node must not be inserted in a tree. + //! + //! Effects: Replaces node_to_be_replaced in its position in the + //! tree with new_node. The tree does not need to be rebalanced + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! new_node is not equivalent to node_to_be_replaced according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + //! + //!Experimental function + static void replace_node(node_ptr node_to_be_replaced, node_ptr header, node_ptr new_node) + { + tree_algorithms::replace_node(node_to_be_replaced, header, new_node); + NodeTraits::set_balance(new_node, NodeTraits::get_balance(node_to_be_replaced)); + } + + //! Requires: node is a tree node but not the header. + //! + //! Effects: Unlinks the node and rebalances the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + static void unlink(node_ptr node) + { + node_ptr x = NodeTraits::get_parent(node); + if(x){ + while(!is_header(x)) + x = NodeTraits::get_parent(x); + erase(x, node); + } + } + + //! Requires: header is the header of a tree. + //! + //! Effects: Unlinks the leftmost node from the tree, and + //! updates the header link to the new leftmost node. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + static node_ptr unlink_leftmost_without_rebalance(node_ptr header) + { return tree_algorithms::unlink_leftmost_without_rebalance(header); } + + //! Requires: node is a node of the tree or an node initialized + //! by init(...). + //! + //! Effects: Returns true if the node is initialized by init(). + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + static bool unique(const_node_ptr node) + { return tree_algorithms::unique(node); } + + //! Requires: node is a node of the tree but it's not the header. + //! + //! Effects: Returns the number of nodes of the subtree. + //! + //! Complexity: Linear time. + //! + //! Throws: Nothing. + static std::size_t count(const_node_ptr node) + { return tree_algorithms::count(node); } + + //! Requires: header is the header node of the tree. + //! + //! Effects: Returns the number of nodes above the header. + //! + //! Complexity: Linear time. + //! + //! Throws: Nothing. + static std::size_t size(const_node_ptr header) + { return tree_algorithms::size(header); } + + //! Requires: p is a node from the tree except the header. + //! + //! Effects: Returns the next node of the tree. + //! + //! Complexity: Average constant time. + //! + //! Throws: Nothing. + static node_ptr next_node(node_ptr p) + { return tree_algorithms::next_node(p); } + + //! Requires: p is a node from the tree except the leftmost node. + //! + //! Effects: Returns the previous node of the tree. + //! + //! Complexity: Average constant time. + //! + //! Throws: Nothing. + static node_ptr prev_node(node_ptr p) + { return tree_algorithms::prev_node(p); } + + //! Requires: node must not be part of any tree. + //! + //! Effects: After the function unique(node) == true. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Nodes: If node is inserted in a tree, this function corrupts the tree. + static void init(node_ptr node) + { tree_algorithms::init(node); } + + //! Requires: node must not be part of any tree. + //! + //! Effects: Initializes the header to represent an empty tree. + //! unique(header) == true. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Nodes: If node is inserted in a tree, this function corrupts the tree. + static void init_header(node_ptr header) + { + tree_algorithms::init_header(header); + NodeTraits::set_balance(header, NodeTraits::zero()); + } + + //! Requires: header must be the header of a tree, z a node + //! of that tree and z != header. + //! + //! Effects: Erases node "z" from the tree with header "header". + //! + //! Complexity: Amortized constant time. + //! + //! Throws: Nothing. + static node_ptr erase(node_ptr header, node_ptr z) + { + typename tree_algorithms::data_for_rebalance info; + tree_algorithms::erase(header, z, avltree_erase_fixup(), info); + node_ptr x = info.x; + node_ptr x_parent = info.x_parent; + + //Rebalance avltree + rebalance_after_erasure(header, x, x_parent); + return z; + } + + //! Requires: "cloner" must be a function + //! object taking a node_ptr and returning a new cloned node of it. "disposer" must + //! take a node_ptr and shouldn't throw. + //! + //! Effects: First empties target tree calling + //! void disposer::operator()(node_ptr) for every node of the tree + //! except the header. + //! + //! Then, duplicates the entire tree pointed by "source_header" cloning each + //! source node with node_ptr Cloner::operator()(node_ptr) to obtain + //! the nodes of the target tree. If "cloner" throws, the cloned target nodes + //! are disposed using void disposer(node_ptr). + //! + //! Complexity: Linear to the number of element of the source tree plus the. + //! number of elements of tree target tree when calling this function. + //! + //! Throws: If cloner functor throws. If this happens target nodes are disposed. + template + static void clone + (const_node_ptr source_header, node_ptr target_header, Cloner cloner, Disposer disposer) + { + avltree_node_cloner new_cloner(cloner); + tree_algorithms::clone(source_header, target_header, new_cloner, disposer); + } + + //! Requires: "disposer" must be an object function + //! taking a node_ptr parameter and shouldn't throw. + //! + //! Effects: Empties the target tree calling + //! void disposer::operator()(node_ptr) for every node of the tree + //! except the header. + //! + //! Complexity: Linear to the number of element of the source tree plus the. + //! number of elements of tree target tree when calling this function. + //! + //! Throws: If cloner functor throws. If this happens target nodes are disposed. + template + static void clear_and_dispose(node_ptr header, Disposer disposer) + { tree_algorithms::clear_and_dispose(header, disposer); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the first element that is + //! not less than "key" according to "comp" or "header" if that element does + //! not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr lower_bound + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { return tree_algorithms::lower_bound(header, key, comp); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the first element that is greater + //! than "key" according to "comp" or "header" if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr upper_bound + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { return tree_algorithms::upper_bound(header, key, comp); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the element that is equivalent to + //! "key" according to "comp" or "header" if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr find + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { return tree_algorithms::find(header, key, comp); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an a pair of node_ptr delimiting a range containing + //! all elements that are equivalent to "key" according to "comp" or an + //! empty range that indicates the position where those elements would be + //! if they there are no equivalent elements. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static std::pair equal_range + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { return tree_algorithms::equal_range(header, key, comp); } + + //! Requires: "h" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. + //! + //! Effects: Inserts new_node into the tree before the upper bound + //! according to "comp". + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr insert_equal_upper_bound + (node_ptr h, node_ptr new_node, NodePtrCompare comp) + { + tree_algorithms::insert_equal_upper_bound(h, new_node, comp); + rebalance_after_insertion(h, new_node); + return new_node; + } + + //! Requires: "h" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. + //! + //! Effects: Inserts new_node into the tree before the lower bound + //! according to "comp". + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr insert_equal_lower_bound + (node_ptr h, node_ptr new_node, NodePtrCompare comp) + { + tree_algorithms::insert_equal_lower_bound(h, new_node, comp); + rebalance_after_insertion(h, new_node); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from + //! the "header"'s tree. + //! + //! Effects: Inserts new_node into the tree, using "hint" as a hint to + //! where it will be inserted. If "hint" is the upper_bound + //! the insertion takes constant time (two comparisons in the worst case). + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time if new_node is inserted immediately before "hint". + //! + //! Throws: If "comp" throws. + template + static node_ptr insert_equal + (node_ptr header, node_ptr hint, node_ptr new_node, NodePtrCompare comp) + { + tree_algorithms::insert_equal(header, hint, new_node, comp); + rebalance_after_insertion(header, new_node); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares KeyType with a node_ptr. + //! + //! Effects: Checks if there is an equivalent node to "key" in the + //! tree according to "comp" and obtains the needed information to realize + //! a constant-time node insertion if there is no equivalent node. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing a node_ptr to the already present node + //! and false. If there is not equivalent key can be inserted returns true + //! in the returned pair's boolean and fills "commit_data" that is meant to + //! be used with the "insert_commit" function to achieve a constant-time + //! insertion function. + //! + //! Complexity: Average complexity is at most logarithmic. + //! + //! Throws: If "comp" throws. + //! + //! Notes: This function is used to improve performance when constructing + //! a node is expensive and the user does not want to have two equivalent nodes + //! in the tree: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the order is much cheaper to construct + //! than the node and this function offers the possibility to use that part + //! to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the node and use + //! "insert_commit" to insert the node in constant-time. This gives a total + //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_unique_commit" only + //! if no more objects are inserted or erased from the set. + template + static std::pair insert_unique_check + (const_node_ptr header, const KeyType &key + ,KeyNodePtrCompare comp, insert_commit_data &commit_data) + { return tree_algorithms::insert_unique_check(header, key, comp, commit_data); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares KeyType with a node_ptr. + //! "hint" is node from the "header"'s tree. + //! + //! Effects: Checks if there is an equivalent node to "key" in the + //! tree according to "comp" using "hint" as a hint to where it should be + //! inserted and obtains the needed information to realize + //! a constant-time node insertion if there is no equivalent node. + //! If "hint" is the upper_bound the function has constant time + //! complexity (two comparisons in the worst case). + //! + //! Returns: If there is an equivalent value + //! returns a pair containing a node_ptr to the already present node + //! and false. If there is not equivalent key can be inserted returns true + //! in the returned pair's boolean and fills "commit_data" that is meant to + //! be used with the "insert_commit" function to achieve a constant-time + //! insertion function. + //! + //! Complexity: Average complexity is at most logarithmic, but it is + //! amortized constant time if new_node should be inserted immediately before "hint". + //! + //! Throws: If "comp" throws. + //! + //! Notes: This function is used to improve performance when constructing + //! a node is expensive and the user does not want to have two equivalent nodes + //! in the tree: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the order is much cheaper to construct + //! than the node and this function offers the possibility to use that part + //! to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the node and use + //! "insert_commit" to insert the node in constant-time. This gives a total + //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_unique_commit" only + //! if no more objects are inserted or erased from the set. + template + static std::pair insert_unique_check + (const_node_ptr header, node_ptr hint, const KeyType &key + ,KeyNodePtrCompare comp, insert_commit_data &commit_data) + { return tree_algorithms::insert_unique_check(header, hint, key, comp, commit_data); } + + //! Requires: "header" must be the header node of a tree. + //! "commit_data" must have been obtained from a previous call to + //! "insert_unique_check". No objects should have been inserted or erased + //! from the set between the "insert_unique_check" that filled "commit_data" + //! and the call to "insert_commit". + //! + //! + //! Effects: Inserts new_node in the set using the information obtained + //! from the "commit_data" that a previous "insert_check" filled. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function has only sense if a "insert_unique_check" has been + //! previously executed to fill "commit_data". No value should be inserted or + //! erased between the "insert_check" and "insert_commit" calls. + static void insert_unique_commit + (node_ptr header, node_ptr new_value, const insert_commit_data &commit_data) + { + tree_algorithms::insert_unique_commit(header, new_value, commit_data); + rebalance_after_insertion(header, new_value); + } + + //! Requires: "n" must be a node inserted in a tree. + //! + //! Effects: Returns a pointer to the header node of the tree. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + static node_ptr get_header(node_ptr n) + { return tree_algorithms::get_header(n); } + + /// @cond + private: + + //! Requires: p is a node of a tree. + //! + //! Effects: Returns true if p is the header of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static bool is_header(const_node_ptr p) + { return NodeTraits::get_balance(p) == NodeTraits::zero() && tree_algorithms::is_header(p); } + + static void rebalance_after_erasure(node_ptr header, node_ptr x, node_ptr x_parent) + { + node_ptr root = NodeTraits::get_parent(header); + while (x != root) { + const balance x_parent_balance = NodeTraits::get_balance(x_parent); + if(x_parent_balance == NodeTraits::zero()){ + NodeTraits::set_balance(x_parent, + (x == NodeTraits::get_right(x_parent) ? NodeTraits::negative() : NodeTraits::positive())); + break; // the height didn't change, let's stop here + } + else if(x_parent_balance == NodeTraits::negative()){ + if (x == NodeTraits::get_left(x_parent)) { + NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced + x = x_parent; + x_parent = NodeTraits::get_parent(x_parent); + } + else { + // x is right child + // a is left child + node_ptr a = NodeTraits::get_left(x_parent); + assert(a); + if (NodeTraits::get_balance(a) == NodeTraits::positive()) { + // a MUST have a right child + assert(NodeTraits::get_right(a)); + rotate_left_right(x_parent, root); + + x = NodeTraits::get_parent(x_parent); + x_parent = NodeTraits::get_parent(x); + } + else { + rotate_right(x_parent, root); + x = NodeTraits::get_parent(x_parent); + x_parent = NodeTraits::get_parent(x); + + } + + // if changed from negative to NodeTraits::positive(), no need to check above + if (NodeTraits::get_balance(x) == NodeTraits::positive()){ + break; + } + } + } + else if(x_parent_balance == NodeTraits::positive()){ + if (x == NodeTraits::get_right(x_parent)) { + NodeTraits::set_balance(x_parent, NodeTraits::zero()); // balanced + x = x_parent; + x_parent = NodeTraits::get_parent(x_parent); + } + else { + // x is left child + // a is right child + node_ptr a = NodeTraits::get_right(x_parent); + assert(a); + if (NodeTraits::get_balance(a) == NodeTraits::negative()) { + // a MUST have then a left child + assert(NodeTraits::get_left(a)); + rotate_right_left(x_parent, root); + + x = NodeTraits::get_parent(x_parent); + x_parent = NodeTraits::get_parent(x); + } + else { + rotate_left(x_parent, root); + x = NodeTraits::get_parent(x_parent); + x_parent = NodeTraits::get_parent(x); + } + // if changed from NodeTraits::positive() to negative, no need to check above + if (NodeTraits::get_balance(x) == NodeTraits::negative()){ + break; + } + } + } + else{ + assert(false); // never reached + } + } + NodeTraits::set_parent(header, root); + } + + + static void rebalance_after_insertion(node_ptr header, node_ptr x) + { + node_ptr root = NodeTraits::get_parent(header); + NodeTraits::set_balance(x, NodeTraits::zero()); + + // Rebalance. + while (x != root){ + const balance x_parent_balance = NodeTraits::get_balance(NodeTraits::get_parent(x)); + + if(x_parent_balance == NodeTraits::zero()){ + // if x is left, parent will have parent->bal_factor = negative + // else, parent->bal_factor = NodeTraits::positive() + NodeTraits::set_balance( NodeTraits::get_parent(x) + , x == NodeTraits::get_left(NodeTraits::get_parent(x)) + ? NodeTraits::negative() : NodeTraits::positive() ); + x = NodeTraits::get_parent(x); + } + else if(x_parent_balance == NodeTraits::positive()){ + // if x is a left child, parent->bal_factor = zero + if (x == NodeTraits::get_left(NodeTraits::get_parent(x))) + NodeTraits::set_balance(NodeTraits::get_parent(x), NodeTraits::zero()); + else{ // x is a right child, needs rebalancing + if (NodeTraits::get_balance(x) == NodeTraits::negative()) + rotate_right_left(NodeTraits::get_parent(x), root); + else + rotate_left(NodeTraits::get_parent(x), root); + } + break; + } + else if(x_parent_balance == NodeTraits::negative()){ + // if x is a left child, needs rebalancing + if (x == NodeTraits::get_left(NodeTraits::get_parent(x))) { + if (NodeTraits::get_balance(x) == NodeTraits::positive()) + rotate_left_right(NodeTraits::get_parent(x), root); + else + rotate_right(NodeTraits::get_parent(x), root); + } + else + NodeTraits::set_balance(NodeTraits::get_parent(x), NodeTraits::zero()); + break; + } + else{ + assert(false); // never reached + } + } + NodeTraits::set_parent(header, root); + } + + static void rotate_left_right(node_ptr a, node_ptr &root) + { + // | | // + // a(-2) c // + // / \ / \ // + // / \ ==> / \ // + // (pos)b [g] b a // + // / \ / \ / \ // + // [d] c [d] e f [g] // + // / \ // + // e f // + node_ptr b = NodeTraits::get_left(a), c = NodeTraits::get_right(b); + + // switch + NodeTraits::set_left(a, NodeTraits::get_right(c)); + NodeTraits::set_right(b, NodeTraits::get_left(c)); + + NodeTraits::set_right(c, a); + NodeTraits::set_left(c, b); + + // set the parents + NodeTraits::set_parent(c, NodeTraits::get_parent(a)); + NodeTraits::set_parent(a, c); + NodeTraits::set_parent(b, c); + + if (NodeTraits::get_left(a)) // do we have f? + NodeTraits::set_parent(NodeTraits::get_left(a), a); + if (NodeTraits::get_right(b)) // do we have e? + NodeTraits::set_parent(NodeTraits::get_right(b), b); + + if (a==root) root = c; + else // a had a parent, his child is now c + if (a == NodeTraits::get_left(NodeTraits::get_parent(c))) + NodeTraits::set_left(NodeTraits::get_parent(c), c); + else + NodeTraits::set_right(NodeTraits::get_parent(c), c); + + // balancing... + const balance c_balance = NodeTraits::get_balance(c); + if(c_balance == NodeTraits::negative()){ + NodeTraits::set_balance(a, NodeTraits::positive()); + NodeTraits::set_balance(b, NodeTraits::zero()); + } + else if(c_balance == NodeTraits::zero()){ + NodeTraits::set_balance(a, NodeTraits::zero()); + NodeTraits::set_balance(b, NodeTraits::zero()); + } + else if(c_balance == NodeTraits::positive()){ + NodeTraits::set_balance(a, NodeTraits::zero()); + NodeTraits::set_balance(b, NodeTraits::negative()); + } + else{ + assert(false); // never reached + } + NodeTraits::set_balance(c, NodeTraits::zero()); + } + + static void rotate_right_left(node_ptr a, node_ptr &root) + { + // | | // + // a(pos) c // + // / \ / \ // + // / \ / \ // + // [d] b(neg) ==> a b // + // / \ / \ / \ // + // c [g] [d] e f [g] // + // / \ // + // e f // + node_ptr b = NodeTraits::get_right(a), c = NodeTraits::get_left(b); + + // switch + NodeTraits::set_right(a, NodeTraits::get_left(c)); + NodeTraits::set_left(b, NodeTraits::get_right(c)); + + NodeTraits::set_left(c, a); + NodeTraits::set_right(c, b); + + // set the parents + NodeTraits::set_parent(c, NodeTraits::get_parent(a)); + NodeTraits::set_parent(a, c); + NodeTraits::set_parent(b, c); + + if (NodeTraits::get_right(a)) // do we have e? + NodeTraits::set_parent(NodeTraits::get_right(a), a); + if (NodeTraits::get_left(b)) // do we have f? + NodeTraits::set_parent(NodeTraits::get_left(b), b); + + if (a==root) root = c; + else // a had a parent, his child is now c + if (a == NodeTraits::get_left(NodeTraits::get_parent(c))) + NodeTraits::set_left(NodeTraits::get_parent(c), c); + else + NodeTraits::set_right(NodeTraits::get_parent(c), c); + + // balancing... + const balance c_balance = NodeTraits::get_balance(c); + if(c_balance == NodeTraits::negative()){ + NodeTraits::set_balance(a, NodeTraits::zero()); + NodeTraits::set_balance(b, NodeTraits::positive()); + } + else if(c_balance == NodeTraits::zero()){ + NodeTraits::set_balance(a, NodeTraits::zero()); + NodeTraits::set_balance(b, NodeTraits::zero()); + } + else if(c_balance == NodeTraits::positive()){ + NodeTraits::set_balance(a, NodeTraits::negative()); + NodeTraits::set_balance(b, NodeTraits::zero()); + } + else{ + assert(false); + } + NodeTraits::set_balance(c, NodeTraits::zero()); + } + + static void rotate_left(node_ptr x, node_ptr & root) + { + // | | // + // x(2) y(0) // + // / \ ==> / \ // + // n[a] y(1)n+2 n+1(0)x [c]n+1 // + // / \ / \ // + // n[b] [c]n+1 n[a] [b]n // + node_ptr y = NodeTraits::get_right(x); + + // switch + NodeTraits::set_right(x, NodeTraits::get_left(y)); + NodeTraits::set_left(y, x); + + // rearrange parents + NodeTraits::set_parent(y, NodeTraits::get_parent(x)); + NodeTraits::set_parent(x, y); + + // do we have [b]? + if (NodeTraits::get_right(x)) + NodeTraits::set_parent(NodeTraits::get_right(x), x); + + if (x == root) + root = y; + else + // need to reparent y + if (NodeTraits::get_left(NodeTraits::get_parent(y)) == x) + NodeTraits::set_left(NodeTraits::get_parent(y), y); + else + NodeTraits::set_right(NodeTraits::get_parent(y), y); + + // reset the balancing factor + if (NodeTraits::get_balance(y) == NodeTraits::positive()) { + NodeTraits::set_balance(x, NodeTraits::zero()); + NodeTraits::set_balance(y, NodeTraits::zero()); + } + else { // this doesn't happen during insertions + NodeTraits::set_balance(x, NodeTraits::positive()); + NodeTraits::set_balance(y, NodeTraits::negative()); + } + } + + static void rotate_right(node_ptr x, node_ptr &root) + { + node_ptr y = NodeTraits::get_left(x); + + // switch + NodeTraits::set_left(x, NodeTraits::get_right(y)); + NodeTraits::set_right(y, x); + + // rearrange parents + NodeTraits::set_parent(y, NodeTraits::get_parent(x)); + NodeTraits::set_parent(x, y); + + // do we have [b]? + if (NodeTraits::get_left(x)) + NodeTraits::set_parent(NodeTraits::get_left(x), x); + + if (x == root) + root = y; + else + // need to reparent y + if (NodeTraits::get_left(NodeTraits::get_parent(y)) == x) + NodeTraits::set_left(NodeTraits::get_parent(y), y); + else + NodeTraits::set_right(NodeTraits::get_parent(y), y); + + // reset the balancing factor + if (NodeTraits::get_balance(y) == NodeTraits::negative()) { + NodeTraits::set_balance(x, NodeTraits::zero()); + NodeTraits::set_balance(y, NodeTraits::zero()); + } + else { // this doesn't happen during insertions + NodeTraits::set_balance(x, NodeTraits::negative()); + NodeTraits::set_balance(y, NodeTraits::positive()); + } + } + + /// @endcond +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_AVLTREE_ALGORITHMS_HPP diff --git a/win32/include/boost/intrusive/bs_set_hook.hpp b/win32/include/boost/intrusive/bs_set_hook.hpp new file mode 100755 index 000000000..ece46391e --- /dev/null +++ b/win32/include/boost/intrusive/bs_set_hook.hpp @@ -0,0 +1,288 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_BS_SET_HOOK_HPP +#define BOOST_INTRUSIVE_BS_SET_HOOK_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond +template +struct get_bs_set_node_algo +{ + typedef detail::tree_algorithms > type; +}; +/// @endcond + +//! Helper metafunction to define a \c bs_set_base_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_bs_set_base_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3>::type packed_options; + + //Scapegoat trees can't be auto unlink trees + BOOST_STATIC_ASSERT(((int)packed_options::link_mode != (int)auto_unlink)); + + typedef detail::generic_hook + < get_bs_set_node_algo + , typename packed_options::tag + , packed_options::link_mode + , detail::BsSetBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Derive a class from bs_set_base_hook in order to store objects in +//! in a bs_set/bs_multiset. bs_set_base_hook holds the data necessary to maintain +//! the bs_set/bs_multiset and provides an appropriate value_traits class for bs_set/bs_multiset. +//! +//! The hook admits the following options: \c tag<>, \c void_pointer<>, +//! \c link_mode<>. +//! +//! \c tag<> defines a tag to identify the node. +//! The same tag value can be used in different classes, but if a class is +//! derived from more than one \c list_base_hook, then each \c list_base_hook needs its +//! unique tag. +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, +//! \c auto_unlink or \c safe_link). +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class bs_set_base_hook + : public make_bs_set_base_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + bs_set_base_hook(); + + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + bs_set_base_hook(const bs_set_base_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + bs_set_base_hook& operator=(const bs_set_base_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in a set an assertion is raised. If link_mode is + //! \c auto_unlink and \c is_linked() is true, the node is unlinked. + //! + //! Throws: Nothing. + ~bs_set_base_hook(); + + //! Effects: Swapping two nodes swaps the position of the elements + //! related to those nodes in one or two containers. That is, if the node + //! this is part of the element e1, the node x is part of the element e2 + //! and both elements are included in the containers s1 and s2, then after + //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 + //! at the position of e1. If one element is not in a container, then + //! after the swap-operation the other element is not in a container. + //! Iterators to e1 and e2 related to those nodes are invalidated. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + void swap_nodes(bs_set_base_hook &other); + + //! Precondition: link_mode must be \c safe_link or \c auto_unlink. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c set::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + + //! Effects: Removes the node if it's inserted in a container. + //! This function is only allowed if link_mode is \c auto_unlink. + //! + //! Throws: Nothing. + void unlink(); + #endif +}; + +//! Helper metafunction to define a \c bs_set_member_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_bs_set_member_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3>::type packed_options; + + //Scapegoat trees can't be auto unlink trees + BOOST_STATIC_ASSERT(((int)packed_options::link_mode != (int)auto_unlink)); + + typedef detail::generic_hook + < get_bs_set_node_algo + , member_tag + , packed_options::link_mode + , detail::NoBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Put a public data member bs_set_member_hook in order to store objects of this class in +//! a bs_set/bs_multiset. bs_set_member_hook holds the data necessary for maintaining the +//! bs_set/bs_multiset and provides an appropriate value_traits class for bs_set/bs_multiset. +//! +//! The hook admits the following options: \c void_pointer<>, \c link_mode<>. +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, +//! \c auto_unlink or \c safe_link). +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class bs_set_member_hook + : public make_bs_set_member_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + bs_set_member_hook(); + + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + bs_set_member_hook(const bs_set_member_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + bs_set_member_hook& operator=(const bs_set_member_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in a set an assertion is raised. If link_mode is + //! \c auto_unlink and \c is_linked() is true, the node is unlinked. + //! + //! Throws: Nothing. + ~bs_set_member_hook(); + + //! Effects: Swapping two nodes swaps the position of the elements + //! related to those nodes in one or two containers. That is, if the node + //! this is part of the element e1, the node x is part of the element e2 + //! and both elements are included in the containers s1 and s2, then after + //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 + //! at the position of e1. If one element is not in a container, then + //! after the swap-operation the other element is not in a container. + //! Iterators to e1 and e2 related to those nodes are invalidated. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + void swap_nodes(bs_set_member_hook &other); + + //! Precondition: link_mode must be \c safe_link or \c auto_unlink. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c set::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + + //! Effects: Removes the node if it's inserted in a container. + //! This function is only allowed if link_mode is \c auto_unlink. + //! + //! Throws: Nothing. + void unlink(); + #endif +}; + +/// @cond + +template +struct internal_default_bs_set_hook +{ + template static detail::one test(...); + template static detail::two test(typename U::default_bs_set_hook* = 0); + static const bool value = sizeof(test(0)) == sizeof(detail::two); +}; + +template +struct get_default_bs_set_hook +{ + typedef typename T::default_bs_set_hook type; +}; + +/// @endcond + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_BS_SET_HOOK_HPP diff --git a/win32/include/boost/intrusive/circular_list_algorithms.hpp b/win32/include/boost/intrusive/circular_list_algorithms.hpp new file mode 100755 index 000000000..86b1452f4 --- /dev/null +++ b/win32/include/boost/intrusive/circular_list_algorithms.hpp @@ -0,0 +1,407 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_CIRCULAR_LIST_ALGORITHMS_HPP +#define BOOST_INTRUSIVE_CIRCULAR_LIST_ALGORITHMS_HPP + +#include +#include +#include + +namespace boost { +namespace intrusive { + +//! circular_list_algorithms provides basic algorithms to manipulate nodes +//! forming a circular doubly linked list. An empty circular list is formed by a node +//! whose pointers point to itself. +//! +//! circular_list_algorithms is configured with a NodeTraits class, which encapsulates the +//! information about the node to be manipulated. NodeTraits must support the +//! following interface: +//! +//! Typedefs: +//! +//! node: The type of the node that forms the circular list +//! +//! node_ptr: A pointer to a node +//! +//! const_node_ptr: A pointer to a const node +//! +//! Static functions: +//! +//! static node_ptr get_previous(const_node_ptr n); +//! +//! static void set_previous(node_ptr n, node_ptr prev); +//! +//! static node_ptr get_next(const_node_ptr n); +//! +//! static void set_next(node_ptr n, node_ptr next); +template +class circular_list_algorithms +{ + public: + typedef typename NodeTraits::node node; + typedef typename NodeTraits::node_ptr node_ptr; + typedef typename NodeTraits::const_node_ptr const_node_ptr; + typedef NodeTraits node_traits; + + //! Effects: Constructs an non-used list element, so that + //! inited(this_node) == true + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void init(node_ptr this_node) + { + NodeTraits::set_next(this_node, node_ptr(0)); + NodeTraits::set_previous(this_node, node_ptr(0)); + } + + //! Effects: Returns true is "this_node" is in a non-used state + //! as if it was initialized by the "init" function. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static bool inited(const_node_ptr this_node) + { return !NodeTraits::get_next(this_node); } + + //! Effects: Constructs an empty list, making this_node the only + //! node of the circular list: + //! NodeTraits::get_next(this_node) == NodeTraits::get_previous(this_node) + //! == this_node. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void init_header(node_ptr this_node) + { + NodeTraits::set_next(this_node, this_node); + NodeTraits::set_previous(this_node, this_node); + } + + + //! Requires: this_node must be in a circular list or be an empty circular list. + //! + //! Effects: Returns true is "this_node" is the only node of a circular list: + //! return NodeTraits::get_next(this_node) == this_node + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static bool unique(const_node_ptr this_node) + { + node_ptr next = NodeTraits::get_next(this_node); + return !next || next == this_node; + } + + //! Requires: this_node must be in a circular list or be an empty circular list. + //! + //! Effects: Returns the number of nodes in a circular list. If the circular list + //! is empty, returns 1. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static std::size_t count(const_node_ptr this_node) + { + std::size_t result = 0; + const_node_ptr p = this_node; + do{ + p = NodeTraits::get_next(p); + ++result; + }while (p != this_node); + return result; + } + + //! Requires: this_node must be in a circular list or be an empty circular list. + //! + //! Effects: Unlinks the node from the circular list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static node_ptr unlink(node_ptr this_node) + { + if(NodeTraits::get_next(this_node)){ + node_ptr next(NodeTraits::get_next(this_node)); + node_ptr prev(NodeTraits::get_previous(this_node)); + NodeTraits::set_next(prev, next); + NodeTraits::set_previous(next, prev); + return next; + } + else{ + return this_node; + } + } + + //! Requires: b and e must be nodes of the same circular list or an empty range. + //! + //! Effects: Unlinks the node [b, e) from the circular list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void unlink(node_ptr b, node_ptr e) + { + if (b != e) { + node_ptr prevb(NodeTraits::get_previous(b)); + NodeTraits::set_previous(e, prevb); + NodeTraits::set_next(prevb, e); + } + } + + //! Requires: nxt_node must be a node of a circular list. + //! + //! Effects: Links this_node before nxt_node in the circular list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void link_before(node_ptr nxt_node, node_ptr this_node) + { + node_ptr prev(NodeTraits::get_previous(nxt_node)); + NodeTraits::set_previous(this_node, prev); + NodeTraits::set_next(prev, this_node); + NodeTraits::set_previous(nxt_node, this_node); + NodeTraits::set_next(this_node, nxt_node); + } + + //! Requires: prev_node must be a node of a circular list. + //! + //! Effects: Links this_node after prev_node in the circular list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void link_after(node_ptr prev_node, node_ptr this_node) + { + node_ptr next(NodeTraits::get_next(prev_node)); + NodeTraits::set_previous(this_node, prev_node); + NodeTraits::set_next(this_node, next); + NodeTraits::set_previous(next, this_node); + NodeTraits::set_next(prev_node, this_node); + } + + //! Requires: this_node and other_node must be nodes inserted + //! in circular lists or be empty circular lists. + //! + //! Effects: Swaps the position of the nodes: this_node is inserted in + //! other_nodes position in the second circular list and the other_node is inserted + //! in this_node's position in the first circular list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. +/* + static void swap_nodes(node_ptr this_node, node_ptr other_node) + { + + if (other_node == this_node) + return; + bool empty1 = unique(this_node); + bool empty2 = unique(other_node); + + node_ptr next_this(NodeTraits::get_next(this_node)); + node_ptr prev_this(NodeTraits::get_previous(this_node)); + node_ptr next_other(NodeTraits::get_next(other_node)); + node_ptr prev_other(NodeTraits::get_previous(other_node)); + + //Do the swap + NodeTraits::set_next(this_node, next_other); + NodeTraits::set_next(other_node, next_this); + + NodeTraits::set_previous(this_node, prev_other); + NodeTraits::set_previous(other_node, prev_this); + + if (empty2){ + init(this_node); + } + else{ + NodeTraits::set_next(prev_other, this_node); + NodeTraits::set_previous(next_other, this_node); + } + if (empty1){ + init(other_node); + } + else{ + NodeTraits::set_next(prev_this, other_node); + NodeTraits::set_previous(next_this, other_node); + } + } +*/ + + //Watanabe version + private: + static void swap_prev(node_ptr this_node, node_ptr other_node) + { + node_ptr temp(NodeTraits::get_previous(this_node)); + NodeTraits::set_previous(this_node, NodeTraits::get_previous(other_node)); + NodeTraits::set_previous(other_node, temp); + } + static void swap_next(node_ptr this_node, node_ptr other_node) + { + node_ptr temp(NodeTraits::get_next(this_node)); + NodeTraits::set_next(this_node, NodeTraits::get_next(other_node)); + NodeTraits::set_next(other_node, temp); + } + + public: + static void swap_nodes(node_ptr this_node, node_ptr other_node) + { + if (other_node == this_node) + return; + bool this_inited = inited(this_node); + bool other_inited = inited(other_node); + if(this_inited){ + init_header(this_node); + } + if(other_inited){ + init_header(other_node); + } + + node_ptr next_this(NodeTraits::get_next(this_node)); + node_ptr prev_this(NodeTraits::get_previous(this_node)); + node_ptr next_other(NodeTraits::get_next(other_node)); + node_ptr prev_other(NodeTraits::get_previous(other_node)); + //these first two swaps must happen before the other two + swap_prev(next_this, next_other); + swap_next(prev_this, prev_other); + swap_next(this_node, other_node); + swap_prev(this_node, other_node); + + if(this_inited){ + init(other_node); + } + if(other_inited){ + init(this_node); + } + } + + //! Requires: b and e must be nodes of the same circular list or an empty range. + //! and p must be a node of a different circular list or may not be an iterator in + // [b, e). + //! + //! Effects: Removes the nodes from [b, e) range from their circular list and inserts + //! them before p in p's circular list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void transfer(node_ptr p, node_ptr b, node_ptr e) + { + if (b != e) { + node_ptr prev_p(NodeTraits::get_previous(p)); + node_ptr prev_b(NodeTraits::get_previous(b)); + node_ptr prev_e(NodeTraits::get_previous(e)); + NodeTraits::set_next(prev_e, p); + NodeTraits::set_previous(p, prev_e); + NodeTraits::set_next(prev_b, e); + NodeTraits::set_previous(e, prev_b); + NodeTraits::set_next(prev_p, b); + NodeTraits::set_previous(b, prev_p); + } + } + + //! Requires: i must a node of a circular list + //! and p must be a node of a different circular list. + //! + //! Effects: Removes the node i from its circular list and inserts + //! it before p in p's circular list. + //! If p == i or p == NodeTraits::get_next(i), this function is a null operation. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void transfer(node_ptr p, node_ptr i) + { + node_ptr n(NodeTraits::get_next(i)); + if(n != p && i != p){ + node_ptr prev_p(NodeTraits::get_previous(p)); + node_ptr prev_i(NodeTraits::get_previous(i)); + NodeTraits::set_next(prev_p, i); + NodeTraits::set_previous(i, prev_p); + NodeTraits::set_next(i, p); + NodeTraits::set_previous(p, i); + NodeTraits::set_previous(n, prev_i); + NodeTraits::set_next(prev_i, n); + + } + } + + //! Effects: Reverses the order of elements in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time. + static void reverse(node_ptr p) + { + node_ptr f(NodeTraits::get_next(p)); + node_ptr i(NodeTraits::get_next(f)), e(p); + + while(i != e) { + node_ptr n = i; + i = NodeTraits::get_next(i); + transfer(f, n, i); + f = n; + } + } + + //! Effects: Moves the node p n positions towards the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of moved positions. + static void move_backwards(node_ptr p, std::size_t n) + { + //Null shift, nothing to do + if(!n) return; + node_ptr first = NodeTraits::get_next(p); + //size() == 0 or 1, nothing to do + if(first == NodeTraits::get_previous(p)) return; + unlink(p); + //Now get the new first node + while(n--){ + first = NodeTraits::get_next(first); + } + link_before(first, p); + } + + //! Effects: Moves the node p n positions towards the beginning of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of moved positions. + static void move_forward(node_ptr p, std::size_t n) + { + //Null shift, nothing to do + if(!n) return; + node_ptr last = NodeTraits::get_previous(p); + //size() == 0 or 1, nothing to do + if(last == NodeTraits::get_next(p)) return; + + unlink(p); + //Now get the new last node + while(n--){ + last = NodeTraits::get_previous(last); + } + link_after(last, p); + } +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_CIRCULAR_LIST_ALGORITHMS_HPP diff --git a/win32/include/boost/intrusive/circular_slist_algorithms.hpp b/win32/include/boost/intrusive/circular_slist_algorithms.hpp new file mode 100755 index 000000000..fc77bb17d --- /dev/null +++ b/win32/include/boost/intrusive/circular_slist_algorithms.hpp @@ -0,0 +1,405 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_CIRCULAR_SLIST_ALGORITHMS_HPP +#define BOOST_INTRUSIVE_CIRCULAR_SLIST_ALGORITHMS_HPP + +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +//! circular_slist_algorithms provides basic algorithms to manipulate nodes +//! forming a circular singly linked list. An empty circular list is formed by a node +//! whose pointer to the next node points to itself. +//! +//! circular_slist_algorithms is configured with a NodeTraits class, which encapsulates the +//! information about the node to be manipulated. NodeTraits must support the +//! following interface: +//! +//! Typedefs: +//! +//! node: The type of the node that forms the circular list +//! +//! node_ptr: A pointer to a node +//! +//! const_node_ptr: A pointer to a const node +//! +//! Static functions: +//! +//! static node_ptr get_next(const_node_ptr n); +//! +//! static void set_next(node_ptr n, node_ptr next); +template +class circular_slist_algorithms + /// @cond + : public detail::common_slist_algorithms + /// @endcond +{ + /// @cond + typedef detail::common_slist_algorithms base_t; + /// @endcond + public: + typedef typename NodeTraits::node node; + typedef typename NodeTraits::node_ptr node_ptr; + typedef typename NodeTraits::const_node_ptr const_node_ptr; + typedef NodeTraits node_traits; + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! Effects: Constructs an non-used list element, putting the next + //! pointer to null: + //! NodeTraits::get_next(this_node) == 0 + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void init(node_ptr this_node); + + //! Requires: this_node must be in a circular list or be an empty circular list. + //! + //! Effects: Returns true is "this_node" is the only node of a circular list: + //! or it's a not inserted node: + //! return !NodeTraits::get_next(this_node) || NodeTraits::get_next(this_node) == this_node + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static bool unique(const_node_ptr this_node); + + //! Effects: Returns true is "this_node" has the same state as + //! if it was inited using "init(node_ptr)" + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static bool inited(const_node_ptr this_node); + + //! Requires: prev_node must be in a circular list or be an empty circular list. + //! + //! Effects: Unlinks the next node of prev_node from the circular list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void unlink_after(node_ptr prev_node); + + //! Requires: prev_node and last_node must be in a circular list + //! or be an empty circular list. + //! + //! Effects: Unlinks the range (prev_node, last_node) from the circular list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void unlink_after(node_ptr prev_node, node_ptr last_node); + + //! Requires: prev_node must be a node of a circular list. + //! + //! Effects: Links this_node after prev_node in the circular list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void link_after(node_ptr prev_node, node_ptr this_node); + + //! Requires: b and e must be nodes of the same circular list or an empty range. + //! and p must be a node of a different circular list. + //! + //! Effects: Removes the nodes from (b, e] range from their circular list and inserts + //! them after p in p's circular list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void transfer_after(node_ptr p, node_ptr b, node_ptr e); + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! Effects: Constructs an empty list, making this_node the only + //! node of the circular list: + //! NodeTraits::get_next(this_node) == this_node. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void init_header(node_ptr this_node) + { NodeTraits::set_next(this_node, this_node); } + + //! Requires: this_node and prev_init_node must be in the same circular list. + //! + //! Effects: Returns the previous node of this_node in the circular list starting. + //! the search from prev_init_node. The first node checked for equality + //! is NodeTraits::get_next(prev_init_node). + //! + //! Complexity: Linear to the number of elements between prev_init_node and this_node. + //! + //! Throws: Nothing. + static node_ptr get_previous_node(node_ptr prev_init_node, node_ptr this_node) + { return base_t::get_previous_node(prev_init_node, this_node); } + + //! Requires: this_node must be in a circular list or be an empty circular list. + //! + //! Effects: Returns the previous node of this_node in the circular list. + //! + //! Complexity: Linear to the number of elements in the circular list. + //! + //! Throws: Nothing. + static node_ptr get_previous_node(node_ptr this_node) + { return base_t::get_previous_node(this_node, this_node); } + + //! Requires: this_node must be in a circular list or be an empty circular list. + //! + //! Effects: Returns the previous node of the previous node of this_node in the circular list. + //! + //! Complexity: Linear to the number of elements in the circular list. + //! + //! Throws: Nothing. + static node_ptr get_previous_previous_node(node_ptr this_node) + { return get_previous_previous_node(this_node, this_node); } + + //! Requires: this_node and prev_prev_init_node must be in the same circular list. + //! + //! Effects: Returns the previous node of the previous node of this_node in the + //! circular list starting. the search from prev_init_node. The first node checked + //! for equality is NodeTraits::get_next((NodeTraits::get_next(prev_prev_init_node)). + //! + //! Complexity: Linear to the number of elements in the circular list. + //! + //! Throws: Nothing. + static node_ptr get_previous_previous_node(node_ptr prev_prev_init_node, node_ptr this_node) + { + node_ptr p = prev_prev_init_node; + node_ptr p_next = NodeTraits::get_next(p); + node_ptr p_next_next = NodeTraits::get_next(p_next); + while (this_node != p_next_next){ + p = p_next; + p_next = p_next_next; + p_next_next = NodeTraits::get_next(p_next); + } + return p; + } + + //! Requires: this_node must be in a circular list or be an empty circular list. + //! + //! Effects: Returns the number of nodes in a circular list. If the circular list + //! is empty, returns 1. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static std::size_t count(const_node_ptr this_node) + { + std::size_t result = 0; + const_node_ptr p = this_node; + do{ + p = NodeTraits::get_next(p); + ++result; + } while (p != this_node); + return result; + } + + //! Requires: this_node must be in a circular list, be an empty circular list or be inited. + //! + //! Effects: Unlinks the node from the circular list. + //! + //! Complexity: Linear to the number of elements in the circular list + //! + //! Throws: Nothing. + static void unlink(node_ptr this_node) + { + if(NodeTraits::get_next(this_node)) + base_t::unlink_after(get_previous_node(this_node)); + } + + //! Requires: nxt_node must be a node of a circular list. + //! + //! Effects: Links this_node before nxt_node in the circular list. + //! + //! Complexity: Linear to the number of elements in the circular list. + //! + //! Throws: Nothing. + static void link_before (node_ptr nxt_node, node_ptr this_node) + { base_t::link_after(get_previous_node(nxt_node), this_node); } + + //! Requires: this_node and other_node must be nodes inserted + //! in circular lists or be empty circular lists. + //! + //! Effects: Swaps the position of the nodes: this_node is inserted in + //! other_nodes position in the second circular list and the other_node is inserted + //! in this_node's position in the first circular list. + //! + //! Complexity: Linear to number of elements of both lists + //! + //! Throws: Nothing. + static void swap_nodes(node_ptr this_node, node_ptr other_node) + { + if (other_node == this_node) + return; + bool this_inited = base_t::inited(this_node); + bool other_inited = base_t::inited(other_node); + if(this_inited){ + base_t::init_header(this_node); + } + if(other_inited){ + base_t::init_header(other_node); + } + + bool empty1 = base_t::unique(this_node); + bool empty2 = base_t::unique(other_node); + node_ptr prev_this (get_previous_node(this_node)); + node_ptr prev_other(get_previous_node(other_node)); + + node_ptr this_next (NodeTraits::get_next(this_node)); + node_ptr other_next(NodeTraits::get_next(other_node)); + NodeTraits::set_next(this_node, other_next); + NodeTraits::set_next(other_node, this_next); + NodeTraits::set_next(empty1 ? other_node : prev_this, other_node); + NodeTraits::set_next(empty2 ? this_node : prev_other, this_node); + + if(this_inited){ + base_t::init(other_node); + } + if(other_inited){ + base_t::init(this_node); + } + } + + //! Effects: Reverses the order of elements in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear to the contained elements. + static void reverse(node_ptr p) + { + node_ptr i = NodeTraits::get_next(p), e(p); + for (;;) { + node_ptr nxt(NodeTraits::get_next(i)); + if (nxt == e) + break; + base_t::transfer_after(e, i, nxt); + } + } + + //! Effects: Moves the node p n positions towards the end of the list. + //! + //! Returns: The previous node of p after the function if there has been any movement, + //! Null if n leads to no movement. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements plus the number moved positions. + static node_ptr move_backwards(node_ptr p, std::size_t n) + { + //Null shift, nothing to do + if(!n) return node_ptr(0); + node_ptr first = NodeTraits::get_next(p); + + //count() == 1 or 2, nothing to do + if(NodeTraits::get_next(first) == p) + return node_ptr(0); + + bool end_found = false; + node_ptr new_last(0); + + //Now find the new last node according to the shift count. + //If we find p before finding the new last node + //unlink p, shortcut the search now that we know the size of the list + //and continue. + for(std::size_t i = 1; i <= n; ++i){ + new_last = first; + first = NodeTraits::get_next(first); + if(first == p){ + //Shortcut the shift with the modulo of the size of the list + n %= i; + if(!n) + return node_ptr(0); + i = 0; + //Unlink p and continue the new first node search + first = NodeTraits::get_next(p); + base_t::unlink_after(new_last); + end_found = true; + } + } + + //If the p has not been found in the previous loop, find it + //starting in the new first node and unlink it + if(!end_found){ + base_t::unlink_after(base_t::get_previous_node(first, p)); + } + + //Now link p after the new last node + base_t::link_after(new_last, p); + return new_last; + } + + //! Effects: Moves the node p n positions towards the beginning of the list. + //! + //! Returns: The previous node of p after the function if there has been any movement, + //! Null if n leads equals to no movement. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements plus the number moved positions. + static node_ptr move_forward(node_ptr p, std::size_t n) + { + //Null shift, nothing to do + if(!n) return node_ptr(0); + node_ptr first = node_traits::get_next(p); + + //count() == 1 or 2, nothing to do + if(node_traits::get_next(first) == p) return node_ptr(0); + + //Iterate until p is found to know where the current last node is. + //If the shift count is less than the size of the list, we can also obtain + //the position of the new last node after the shift. + node_ptr old_last(first), next_to_it, new_last(p); + std::size_t distance = 1; + while(p != (next_to_it = node_traits::get_next(old_last))){ + if(++distance > n) + new_last = node_traits::get_next(new_last); + old_last = next_to_it; + } + //If the shift was bigger or equal than the size, obtain the equivalent + //forward shifts and find the new last node. + if(distance <= n){ + //Now find the equivalent forward shifts. + //Shortcut the shift with the modulo of the size of the list + std::size_t new_before_last_pos = (distance - (n % distance))% distance; + //If the shift is a multiple of the size there is nothing to do + if(!new_before_last_pos) return node_ptr(0); + + for( new_last = p + ; new_before_last_pos-- + ; new_last = node_traits::get_next(new_last)){ + //empty + } + } + + //Now unlink p and link it after the new last node + base_t::unlink_after(old_last); + base_t::link_after(new_last, p); + return new_last; + } +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_CIRCULAR_SLIST_ALGORITHMS_HPP diff --git a/win32/include/boost/intrusive/derivation_value_traits.hpp b/win32/include/boost/intrusive/derivation_value_traits.hpp new file mode 100755 index 000000000..31522a36d --- /dev/null +++ b/win32/include/boost/intrusive/derivation_value_traits.hpp @@ -0,0 +1,56 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP +#define BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP + +#include +#include + +namespace boost { +namespace intrusive { + +//!This value traits template is used to create value traits +//!from user defined node traits where value_traits::value_type will +//!derive from node_traits::node +template +struct derivation_value_traits +{ + public: + typedef NodeTraits node_traits; + typedef T value_type; + typedef typename node_traits::node node; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef typename boost::pointer_to_other::type pointer; + typedef typename boost::pointer_to_other::type const_pointer; + typedef typename std::iterator_traits::reference reference; + typedef typename std::iterator_traits::reference const_reference; + static const link_mode_type link_mode = LinkMode; + + static node_ptr to_node_ptr(reference value) + { return node_ptr(&value); } + + static const_node_ptr to_node_ptr(const_reference value) + { return node_ptr(&value); } + + static pointer to_value_ptr(node_ptr n) + { return pointer(static_cast(detail::get_pointer(n))); } + + static const_pointer to_value_ptr(const_node_ptr n) + { return const_pointer(static_cast(detail::get_pointer(n))); } +}; + +} //namespace intrusive +} //namespace boost + +#endif //BOOST_INTRUSIVE_DERIVATION_VALUE_TRAITS_HPP diff --git a/win32/include/boost/intrusive/detail/any_node_and_algorithms.hpp b/win32/include/boost/intrusive/detail/any_node_and_algorithms.hpp new file mode 100755 index 000000000..a96cbdb0d --- /dev/null +++ b/win32/include/boost/intrusive/detail/any_node_and_algorithms.hpp @@ -0,0 +1,301 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2008 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_ANY_NODE_HPP +#define BOOST_INTRUSIVE_ANY_NODE_HPP + +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +template +struct any_node +{ + typedef typename boost::pointer_to_other + ::type node_ptr; + node_ptr node_ptr_1; + node_ptr node_ptr_2; + node_ptr node_ptr_3; + std::size_t size_t_1; +}; + +template +struct any_list_node_traits +{ + typedef any_node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + + static node_ptr get_next(const_node_ptr n) + { return n->node_ptr_1; } + + static void set_next(node_ptr n, node_ptr next) + { n->node_ptr_1 = next; } + + static node_ptr get_previous(const_node_ptr n) + { return n->node_ptr_2; } + + static void set_previous(node_ptr n, node_ptr prev) + { n->node_ptr_2 = prev; } +}; + + +template +struct any_slist_node_traits +{ + typedef any_node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + + static node_ptr get_next(const_node_ptr n) + { return n->node_ptr_1; } + + static void set_next(node_ptr n, node_ptr next) + { n->node_ptr_1 = next; } +}; + + +template +struct any_unordered_node_traits + : public any_slist_node_traits +{ + typedef any_slist_node_traits reduced_slist_node_traits; + typedef typename reduced_slist_node_traits::node node; + typedef typename reduced_slist_node_traits::node_ptr node_ptr; + typedef typename reduced_slist_node_traits::const_node_ptr const_node_ptr; + + static const bool store_hash = true; + static const bool optimize_multikey = true; + + static node_ptr get_next(const_node_ptr n) + { return node_ptr(&static_cast(*n->node_ptr_1)); } + + static void set_next(node_ptr n, node_ptr next) + { n->node_ptr_1 = next; } + + static node_ptr get_prev_in_group(const_node_ptr n) + { return n->node_ptr_2; } + + static void set_prev_in_group(node_ptr n, node_ptr prev) + { n->node_ptr_2 = prev; } + + static std::size_t get_hash(const_node_ptr n) + { return n->size_t_1; } + + static void set_hash(node_ptr n, std::size_t h) + { n->size_t_1 = h; } +}; + + +template +struct any_rbtree_node_traits +{ + typedef any_node node; + + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + + typedef std::size_t color; + + static node_ptr get_parent(const_node_ptr n) + { return n->node_ptr_1; } + + static void set_parent(node_ptr n, node_ptr p) + { n->node_ptr_1 = p; } + + static node_ptr get_left(const_node_ptr n) + { return n->node_ptr_2; } + + static void set_left(node_ptr n, node_ptr l) + { n->node_ptr_2 = l; } + + static node_ptr get_right(const_node_ptr n) + { return n->node_ptr_3; } + + static void set_right(node_ptr n, node_ptr r) + { n->node_ptr_3 = r; } + + static color get_color(const_node_ptr n) + { return n->size_t_1; } + + static void set_color(node_ptr n, color c) + { n->size_t_1 = c; } + + static color black() + { return 0u; } + + static color red() + { return 1u; } +}; + + +template +struct any_avltree_node_traits +{ + typedef any_node node; + + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + typedef std::size_t balance; + + static node_ptr get_parent(const_node_ptr n) + { return n->node_ptr_1; } + + static void set_parent(node_ptr n, node_ptr p) + { n->node_ptr_1 = p; } + + static node_ptr get_left(const_node_ptr n) + { return n->node_ptr_2; } + + static void set_left(node_ptr n, node_ptr l) + { n->node_ptr_2 = l; } + + static node_ptr get_right(const_node_ptr n) + { return n->node_ptr_3; } + + static void set_right(node_ptr n, node_ptr r) + { n->node_ptr_3 = r; } + + static balance get_balance(const_node_ptr n) + { return n->size_t_1; } + + static void set_balance(node_ptr n, balance b) + { n->size_t_1 = b; } + + static balance negative() + { return 0u; } + + static balance zero() + { return 1u; } + + static balance positive() + { return 2u; } +}; + + +template +struct any_tree_node_traits +{ + typedef any_node node; + + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + + static node_ptr get_parent(const_node_ptr n) + { return n->node_ptr_1; } + + static void set_parent(node_ptr n, node_ptr p) + { n->node_ptr_1 = p; } + + static node_ptr get_left(const_node_ptr n) + { return n->node_ptr_2; } + + static void set_left(node_ptr n, node_ptr l) + { n->node_ptr_2 = l; } + + static node_ptr get_right(const_node_ptr n) + { return n->node_ptr_3; } + + static void set_right(node_ptr n, node_ptr r) + { n->node_ptr_3 = r; } +}; + +template +class any_node_traits +{ + public: + typedef any_node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; +}; + +template +class any_algorithms +{ + public: + typedef any_node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + typedef any_node_traits node_traits; + + //! Requires: node must not be part of any tree. + //! + //! Effects: After the function unique(node) == true. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Nodes: If node is inserted in a tree, this function corrupts the tree. + static void init(node_ptr node) + { node->node_ptr_1 = 0; }; + + //! Effects: Returns true if node is in the same state as if called init(node) + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static bool inited(const_node_ptr node) + { return !node->node_ptr_1; }; + + static bool unique(const_node_ptr node) + { return 0 == node->node_ptr_1; } + + +#if defined(__EDG__) && defined(__STD_STRICT_ANSI) + // For compilers checking the full source code at compile time, regardless + // of whether the code is instantiated or not, we turn the compile error + // below into a link error. + static void unlink(node_ptr); + static void swap_nodes(node_ptr l, node_ptr r); +#else + static void unlink(node_ptr) + { + //Auto-unlink hooks and unlink() call for safe hooks are not + //available for any hooks!!! + any_algorithms::unlink_not_available_for_any_hooks(); + } + + static void swap_nodes(node_ptr l, node_ptr r) + { + //Any nodes have no swap_nodes capability because they don't know + //what algorithm they must use from unlink them from the container + any_algorithms::swap_nodes_not_available_for_any_hooks(); + } +#endif +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_ANY_NODE_HPP diff --git a/win32/include/boost/intrusive/detail/assert.hpp b/win32/include/boost/intrusive/detail/assert.hpp new file mode 100755 index 000000000..2bb97d0b7 --- /dev/null +++ b/win32/include/boost/intrusive/detail/assert.hpp @@ -0,0 +1,35 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_DETAIL_ASSERT_HPP +#define BOOST_INTRUSIVE_DETAIL_ASSERT_HPP + +#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#pragma once +#endif + +#if !defined(BOOST_INTRUSIVE_INVARIANT_ASSERT) +#include +#define BOOST_INTRUSIVE_INVARIANT_ASSERT BOOST_ASSERT +#endif + +#if !defined(BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT) +#include +#define BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT BOOST_ASSERT +#endif + +#if !defined(BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT) +#include +#define BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT BOOST_ASSERT +#endif + +#endif //BOOST_INTRUSIVE_DETAIL_ASSERT_HPP diff --git a/win32/include/boost/intrusive/detail/avltree_node.hpp b/win32/include/boost/intrusive/detail/avltree_node.hpp new file mode 100755 index 000000000..c36759f3a --- /dev/null +++ b/win32/include/boost/intrusive/detail/avltree_node.hpp @@ -0,0 +1,179 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007. +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_AVLTREE_NODE_HPP +#define BOOST_INTRUSIVE_AVLTREE_NODE_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +///////////////////////////////////////////////////////////////////////////// +// // +// Generic node_traits for any pointer type // +// // +///////////////////////////////////////////////////////////////////////////// + +//This is the compact representation: 3 pointers +template +struct compact_avltree_node +{ + typedef typename pointer_to_other + >::type node_ptr; + enum balance { negative_t, zero_t, positive_t }; + node_ptr parent_, left_, right_; +}; + +//This is the normal representation: 3 pointers + enum +template +struct avltree_node +{ + typedef typename pointer_to_other + >::type node_ptr; + enum balance { negative_t, zero_t, positive_t }; + node_ptr parent_, left_, right_; + balance balance_; +}; + +//This is the default node traits implementation +//using a node with 3 generic pointers plus an enum +template +struct default_avltree_node_traits_impl +{ + typedef avltree_node node; + + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + typedef typename node::balance balance; + + static node_ptr get_parent(const_node_ptr n) + { return n->parent_; } + + static void set_parent(node_ptr n, node_ptr p) + { n->parent_ = p; } + + static node_ptr get_left(const_node_ptr n) + { return n->left_; } + + static void set_left(node_ptr n, node_ptr l) + { n->left_ = l; } + + static node_ptr get_right(const_node_ptr n) + { return n->right_; } + + static void set_right(node_ptr n, node_ptr r) + { n->right_ = r; } + + static balance get_balance(const_node_ptr n) + { return n->balance_; } + + static void set_balance(node_ptr n, balance b) + { n->balance_ = b; } + + static balance negative() + { return node::negative_t; } + + static balance zero() + { return node::zero_t; } + + static balance positive() + { return node::positive_t; } +}; + +//This is the compact node traits implementation +//using a node with 3 generic pointers +template +struct compact_avltree_node_traits_impl +{ + typedef compact_avltree_node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + typedef typename node::balance balance; + + typedef pointer_plus_bits ptr_bit; + + static node_ptr get_parent(const_node_ptr n) + { return ptr_bit::get_pointer(n->parent_); } + + static void set_parent(node_ptr n, node_ptr p) + { ptr_bit::set_pointer(n->parent_, p); } + + static node_ptr get_left(const_node_ptr n) + { return n->left_; } + + static void set_left(node_ptr n, node_ptr l) + { n->left_ = l; } + + static node_ptr get_right(const_node_ptr n) + { return n->right_; } + + static void set_right(node_ptr n, node_ptr r) + { n->right_ = r; } + + static balance get_balance(const_node_ptr n) + { return (balance)ptr_bit::get_bits(n->parent_); } + + static void set_balance(node_ptr n, balance b) + { ptr_bit::set_bits(n->parent_, (std::size_t)b); } + + static balance negative() + { return node::negative_t; } + + static balance zero() + { return node::zero_t; } + + static balance positive() + { return node::positive_t; } +}; + +//Dispatches the implementation based on the boolean +template +struct avltree_node_traits_dispatch + : public default_avltree_node_traits_impl +{}; + +template +struct avltree_node_traits_dispatch + : public compact_avltree_node_traits_impl +{}; + +//Inherit from the detail::link_dispatch depending on the embedding capabilities +template +struct avltree_node_traits + : public avltree_node_traits_dispatch + < VoidPointer + , OptimizeSize && + max_pointer_plus_bits + < VoidPointer + , detail::alignment_of >::value + >::value >= 2u + > +{}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_AVLTREE_NODE_HPP diff --git a/win32/include/boost/intrusive/detail/common_slist_algorithms.hpp b/win32/include/boost/intrusive/detail/common_slist_algorithms.hpp new file mode 100755 index 000000000..9bdcb2b9c --- /dev/null +++ b/win32/include/boost/intrusive/detail/common_slist_algorithms.hpp @@ -0,0 +1,96 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007-2008 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_COMMON_SLIST_ALGORITHMS_HPP +#define BOOST_INTRUSIVE_COMMON_SLIST_ALGORITHMS_HPP + +#include +#include +#include +#include + +namespace boost { +namespace intrusive { +namespace detail { + +template +class common_slist_algorithms +{ + public: + typedef typename NodeTraits::node node; + typedef typename NodeTraits::node_ptr node_ptr; + typedef typename NodeTraits::const_node_ptr const_node_ptr; + typedef NodeTraits node_traits; + + static node_ptr get_previous_node(node_ptr prev_init_node, node_ptr this_node) + { + node_ptr p = prev_init_node; + for( node_ptr p_next + ; this_node != (p_next = NodeTraits::get_next(p)) + ; p = p_next){ + //Logic error: possible use of linear lists with + //operations only permitted with lists + BOOST_INTRUSIVE_INVARIANT_ASSERT(p); + } + return p; + } + + static void init_header(node_ptr this_node) + { NodeTraits::set_next(this_node, this_node); } + + static void init(node_ptr this_node) + { NodeTraits::set_next(this_node, node_ptr(0)); } + + static bool unique(const_node_ptr this_node) + { + node_ptr next = NodeTraits::get_next(this_node); + return !next || next == this_node; + } + + static bool inited(const_node_ptr this_node) + { return !NodeTraits::get_next(this_node); } + + static void unlink_after(node_ptr prev_node) + { + node_ptr this_node(NodeTraits::get_next(prev_node)); + NodeTraits::set_next(prev_node, NodeTraits::get_next(this_node)); + } + + static void unlink_after(node_ptr prev_node, node_ptr last_node) + { NodeTraits::set_next(prev_node, last_node); } + + static void link_after(node_ptr prev_node, node_ptr this_node) + { + NodeTraits::set_next(this_node, NodeTraits::get_next(prev_node)); + NodeTraits::set_next(prev_node, this_node); + } + + static void transfer_after(node_ptr p, node_ptr b, node_ptr e) + { + if (p != b && p != e && b != e) { + node_ptr next_b = NodeTraits::get_next(b); + node_ptr next_e = NodeTraits::get_next(e); + node_ptr next_p = NodeTraits::get_next(p); + NodeTraits::set_next(b, next_e); + NodeTraits::set_next(e, next_p); + NodeTraits::set_next(p, next_b); + } + } +}; + +} //namespace detail +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_COMMON_SLIST_ALGORITHMS_HPP diff --git a/win32/include/boost/intrusive/detail/config_begin.hpp b/win32/include/boost/intrusive/detail/config_begin.hpp new file mode 100755 index 000000000..2205666bc --- /dev/null +++ b/win32/include/boost/intrusive/detail/config_begin.hpp @@ -0,0 +1,50 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_CONFIG_INCLUDED +#define BOOST_INTRUSIVE_CONFIG_INCLUDED +#include +#endif + +#ifdef BOOST_MSVC + + #pragma warning (push) + // + //'function' : resolved overload was found by argument-dependent lookup + //A function found by argument-dependent lookup (Koenig lookup) was eventually + //chosen by overload resolution. + // + //In Visual C++ .NET and earlier compilers, a different function would have + //been called. To pick the original function, use an explicitly qualified name. + // + + //warning C4275: non dll-interface class 'x' used as base for + //dll-interface class 'Y' + #pragma warning (disable : 4275) + //warning C4251: 'x' : class 'y' needs to have dll-interface to + //be used by clients of class 'z' + #pragma warning (disable : 4251) + #pragma warning (disable : 4675) + #pragma warning (disable : 4996) + #pragma warning (disable : 4503) + #pragma warning (disable : 4284) // odd return type for operator-> + #pragma warning (disable : 4244) // possible loss of data + #pragma warning (disable : 4521) ////Disable "multiple copy constructors specified" + #pragma warning (disable : 4522) + #pragma warning (disable : 4146) + #pragma warning (disable : 4267) //conversion from 'X' to 'Y', possible loss of data + #pragma warning (disable : 4127) //conditional expression is constant + #pragma warning (disable : 4706) //assignment within conditional expression +#endif + +//#define BOOST_INTRUSIVE_USE_ITERATOR_FACADE +//#define BOOST_INTRUSIVE_USE_ITERATOR_ENABLE_IF_CONVERTIBLE diff --git a/win32/include/boost/intrusive/detail/config_end.hpp b/win32/include/boost/intrusive/detail/config_end.hpp new file mode 100755 index 000000000..f21303adb --- /dev/null +++ b/win32/include/boost/intrusive/detail/config_end.hpp @@ -0,0 +1,15 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#if defined BOOST_MSVC + #pragma warning (pop) +#endif diff --git a/win32/include/boost/intrusive/detail/ebo_functor_holder.hpp b/win32/include/boost/intrusive/detail/ebo_functor_holder.hpp new file mode 100755 index 000000000..d73585592 --- /dev/null +++ b/win32/include/boost/intrusive/detail/ebo_functor_holder.hpp @@ -0,0 +1,92 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Joaquin M Lopez Munoz 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP +#define BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP + +#include + +namespace boost { +namespace intrusive { +namespace detail { + +template +class ebo_functor_holder_impl +{ + public: + ebo_functor_holder_impl() + {} + ebo_functor_holder_impl(const T& t) + : t(t) + {} + template + ebo_functor_holder_impl(const Arg1& arg1, const Arg2& arg2) + : t(arg1, arg2) + {} + + T& get(){return t;} + const T& get()const{return t;} + + private: + T t; +}; + +template +class ebo_functor_holder_impl + : public T +{ + public: + ebo_functor_holder_impl() + {} + ebo_functor_holder_impl(const T& t) + : T(t) + {} + template + ebo_functor_holder_impl(const Arg1& arg1, const Arg2& arg2) + : T(arg1, arg2) + {} + + T& get(){return *this;} + const T& get()const{return *this;} +}; + +template +class ebo_functor_holder + : public ebo_functor_holder_impl::value> +{ + private: + typedef ebo_functor_holder_impl::value> super; + + public: + ebo_functor_holder(){} + ebo_functor_holder(const T& t) + : super(t) + {} + + template + ebo_functor_holder(const Arg1& arg1, const Arg2& arg2) + : super(arg1, arg2) + {} + + ebo_functor_holder& operator=(const ebo_functor_holder& x) + { + this->get()=x.get(); + return *this; + } +}; + + +} //namespace detail { +} //namespace intrusive { +} //namespace boost { + +#endif //#ifndef BOOST_INTRUSIVE_DETAIL_EBO_HOLDER_HPP diff --git a/win32/include/boost/intrusive/detail/generic_hook.hpp b/win32/include/boost/intrusive/detail/generic_hook.hpp new file mode 100755 index 000000000..f6dad49e0 --- /dev/null +++ b/win32/include/boost/intrusive/detail/generic_hook.hpp @@ -0,0 +1,203 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_GENERIC_HOOK_HPP +#define BOOST_INTRUSIVE_GENERIC_HOOK_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { +namespace detail { + +/// @cond + +enum +{ NoBaseHook +, ListBaseHook +, SlistBaseHook +, SetBaseHook +, UsetBaseHook +, SplaySetBaseHook +, AvlSetBaseHook +, BsSetBaseHook +, AnyBaseHook +}; + +struct no_default_definer{}; + +template +struct default_definer; + +template +struct default_definer +{ typedef Hook default_list_hook; }; + +template +struct default_definer +{ typedef Hook default_slist_hook; }; + +template +struct default_definer +{ typedef Hook default_set_hook; }; + +template +struct default_definer +{ typedef Hook default_uset_hook; }; + +template +struct default_definer +{ typedef Hook default_splay_set_hook; }; + +template +struct default_definer +{ typedef Hook default_avl_set_hook; }; + +template +struct default_definer +{ typedef Hook default_bs_set_hook; }; + +template +struct default_definer +{ typedef Hook default_any_hook; }; + +template +struct make_default_definer +{ + typedef typename detail::if_c + < BaseHookType != 0 + , default_definer + , no_default_definer>::type type; +}; + +template + < class GetNodeAlgorithms + , class Tag + , link_mode_type LinkMode + , int HookType + > +struct make_node_holder +{ + typedef typename detail::if_c + ::value + , detail::node_holder + < typename GetNodeAlgorithms::type::node + , Tag + , LinkMode + , HookType> + , typename GetNodeAlgorithms::type::node + >::type type; +}; + +/// @endcond + +template + < class GetNodeAlgorithms + , class Tag + , link_mode_type LinkMode + , int HookType + > +class generic_hook + /// @cond + + //If the hook is a base hook, derive generic hook from detail::node_holder + //so that a unique base class is created to convert from the node + //to the type. This mechanism will be used by base_hook_traits. + // + //If the hook is a member hook, generic hook will directly derive + //from the hook. + : public make_default_definer + < generic_hook + , detail::is_same::value*HookType + >::type + , public make_node_holder::type + /// @endcond +{ + /// @cond + typedef typename GetNodeAlgorithms::type node_algorithms; + typedef typename node_algorithms::node node; + typedef typename node_algorithms::node_ptr node_ptr; + typedef typename node_algorithms::const_node_ptr const_node_ptr; + + public: + struct boost_intrusive_tags + { + static const int hook_type = HookType; + static const link_mode_type link_mode = LinkMode; + typedef Tag tag; + typedef typename GetNodeAlgorithms::type::node_traits node_traits; + static const bool is_base_hook = !detail::is_same::value; + static const bool safemode_or_autounlink = + (int)link_mode == (int)auto_unlink || (int)link_mode == (int)safe_link; + }; + + public: + /// @endcond + + generic_hook() + { + if(boost_intrusive_tags::safemode_or_autounlink){ + node_algorithms::init(static_cast(this)); + } + } + + generic_hook(const generic_hook& ) + { + if(boost_intrusive_tags::safemode_or_autounlink){ + node_algorithms::init(static_cast(this)); + } + } + + generic_hook& operator=(const generic_hook& ) + { return *this; } + + ~generic_hook() + { + destructor_impl + (*this, detail::link_dispatch()); + } + + void swap_nodes(generic_hook &other) + { + node_algorithms::swap_nodes + ( static_cast(this), static_cast(&other)); + } + + bool is_linked() const + { + //is_linked() can be only used in safe-mode or auto-unlink + BOOST_STATIC_ASSERT(( boost_intrusive_tags::safemode_or_autounlink )); + return !node_algorithms::unique + (static_cast(this)); + } + + void unlink() + { + BOOST_STATIC_ASSERT(( (int)boost_intrusive_tags::link_mode == (int)auto_unlink )); + node_algorithms::unlink(static_cast(this)); + node_algorithms::init(static_cast(this)); + } +}; + +} //namespace detail +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_GENERIC_HOOK_HPP diff --git a/win32/include/boost/intrusive/detail/hashtable_node.hpp b/win32/include/boost/intrusive/detail/hashtable_node.hpp new file mode 100755 index 000000000..cd341faf7 --- /dev/null +++ b/win32/include/boost/intrusive/detail/hashtable_node.hpp @@ -0,0 +1,200 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_HASHTABLE_NODE_HPP +#define BOOST_INTRUSIVE_HASHTABLE_NODE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include //remove-me +#include + +namespace boost { +namespace intrusive { +namespace detail { + +template +struct prime_list_holder +{ + static const std::size_t prime_list[]; + static const std::size_t prime_list_size; +}; + +template +const std::size_t prime_list_holder::prime_list[] = { + 53ul, 97ul, 193ul, 389ul, 769ul, + 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, + 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, + 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, + 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, + 1610612741ul, 3221225473ul, 4294967291ul }; + +template +const std::size_t prime_list_holder::prime_list_size + = sizeof(prime_list)/sizeof(std::size_t); + +template +struct bucket_impl : public Slist +{ + typedef Slist slist_type; + bucket_impl() + {} + + bucket_impl(const bucket_impl &) + {} + + ~bucket_impl() + { + //This bucket is still being used! + BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty()); + } + + bucket_impl &operator=(const bucket_impl&) + { + //This bucket is still in use! + BOOST_INTRUSIVE_INVARIANT_ASSERT(Slist::empty()); + //Slist::clear(); + return *this; + } +}; + +template +struct bucket_traits_impl +{ + /// @cond + typedef typename boost::pointer_to_other + < typename Slist::pointer, bucket_impl >::type bucket_ptr; + typedef typename Slist::size_type size_type; + /// @endcond + + bucket_traits_impl(bucket_ptr buckets, size_type len) + : buckets_(buckets), buckets_len_(len) + {} + + bucket_ptr bucket_begin() const + { return buckets_; } + + size_type bucket_count() const + { return buckets_len_; } + + private: + bucket_ptr buckets_; + size_type buckets_len_; +}; + +template +class hashtable_iterator + : public std::iterator + < std::forward_iterator_tag + , typename detail::add_const_if_c + ::type + > +{ + typedef typename Container::real_value_traits real_value_traits; + typedef typename Container::siterator siterator; + typedef typename Container::const_siterator const_siterator; + typedef typename Container::bucket_type bucket_type; + typedef typename boost::pointer_to_other + < typename Container::pointer, const Container>::type const_cont_ptr; + typedef typename Container::size_type size_type; + + static typename Container::node_ptr downcast_bucket(typename bucket_type::node_ptr p) + { return typename Container::node_ptr(&static_cast(*p)); } + + public: + typedef typename detail::add_const_if_c + ::type value_type; + + hashtable_iterator () + {} + + explicit hashtable_iterator(siterator ptr, const Container *cont) + : slist_it_ (ptr), cont_ (cont) + {} + + hashtable_iterator(const hashtable_iterator &other) + : slist_it_(other.slist_it()), cont_(other.get_container()) + {} + + const siterator &slist_it() const + { return slist_it_; } + + public: + hashtable_iterator& operator++() + { this->increment(); return *this; } + + hashtable_iterator operator++(int) + { + hashtable_iterator result (*this); + this->increment(); + return result; + } + + friend bool operator== (const hashtable_iterator& i, const hashtable_iterator& i2) + { return i.slist_it_ == i2.slist_it_; } + + friend bool operator!= (const hashtable_iterator& i, const hashtable_iterator& i2) + { return !(i == i2); } + + value_type& operator*() const + { return *this->operator ->(); } + + value_type* operator->() const + { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(downcast_bucket(slist_it_.pointed_node()))); } + + const Container *get_container() const + { return detail::get_pointer(cont_); } + + const real_value_traits *get_real_value_traits() const + { return &this->get_container()->get_real_value_traits(); } + + private: + void increment() + { + const Container *cont = detail::get_pointer(cont_); + bucket_type* buckets = detail::get_pointer(cont->bucket_pointer()); + size_type buckets_len = cont->bucket_count(); + + ++slist_it_; + if(buckets[0].cend().pointed_node() <= slist_it_.pointed_node() && + slist_it_.pointed_node()<= buckets[buckets_len].cend().pointed_node() ){ + //Now get the bucket_impl from the iterator + const bucket_type &b = static_cast + (bucket_type::slist_type::container_from_end_iterator(slist_it_)); + + //Now just calculate the index b has in the bucket array + size_type n_bucket = static_cast(&b - &buckets[0]); + do{ + if (++n_bucket == buckets_len){ + slist_it_ = (&buckets[0] + buckets_len)->end(); + break; + } + slist_it_ = buckets[n_bucket].begin(); + } + while (slist_it_ == buckets[n_bucket].end()); + } + } + + siterator slist_it_; + const_cont_ptr cont_; +}; + +} //namespace detail { +} //namespace intrusive { +} //namespace boost { + +#endif diff --git a/win32/include/boost/intrusive/detail/list_node.hpp b/win32/include/boost/intrusive/detail/list_node.hpp new file mode 100755 index 000000000..cce86c5c1 --- /dev/null +++ b/win32/include/boost/intrusive/detail/list_node.hpp @@ -0,0 +1,185 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_LIST_NODE_HPP +#define BOOST_INTRUSIVE_LIST_NODE_HPP + +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +// list_node_traits can be used with circular_list_algorithms and supplies +// a list_node holding the pointers needed for a double-linked list +// it is used by list_derived_node and list_member_node + +template +struct list_node +{ + typedef typename boost::pointer_to_other + ::type node_ptr; + node_ptr next_; + node_ptr prev_; +}; + +template +struct list_node_traits +{ + typedef list_node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + + static node_ptr get_previous(const_node_ptr n) + { return n->prev_; } + + static void set_previous(node_ptr n, node_ptr prev) + { n->prev_ = prev; } + + static node_ptr get_next(const_node_ptr n) + { return n->next_; } + + static void set_next(node_ptr n, node_ptr next) + { n->next_ = next; } +}; + +// list_iterator provides some basic functions for a +// node oriented bidirectional iterator: +template +class list_iterator + : public std::iterator + < std::bidirectional_iterator_tag + , typename detail::add_const_if_c + ::type + > +{ + protected: + typedef typename Container::real_value_traits real_value_traits; + typedef typename real_value_traits::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename node_traits::node_ptr node_ptr; + typedef typename boost::pointer_to_other + ::type void_pointer; + static const bool store_container_ptr = + detail::store_cont_ptr_on_it::value; + + public: + typedef typename detail::add_const_if_c + + ::type value_type; + typedef value_type & reference; + typedef value_type * pointer; + + list_iterator() + : members_ (node_ptr(0), 0) + {} + + explicit list_iterator(node_ptr node, const Container *cont_ptr) + : members_ (node, cont_ptr) + {} + + list_iterator(list_iterator const& other) + : members_(other.pointed_node(), other.get_container()) + {} + + const node_ptr &pointed_node() const + { return members_.nodeptr_; } + + list_iterator &operator=(const node_ptr &node) + { members_.nodeptr_ = node; return static_cast(*this); } + + public: + list_iterator& operator++() + { + members_.nodeptr_ = node_traits::get_next(members_.nodeptr_); + return static_cast (*this); + } + + list_iterator operator++(int) + { + list_iterator result (*this); + members_.nodeptr_ = node_traits::get_next(members_.nodeptr_); + return result; + } + + list_iterator& operator--() + { + members_.nodeptr_ = node_traits::get_previous(members_.nodeptr_); + return static_cast (*this); + } + + list_iterator operator--(int) + { + list_iterator result (*this); + members_.nodeptr_ = node_traits::get_previous(members_.nodeptr_); + return result; + } + + bool operator== (const list_iterator& i) const + { return members_.nodeptr_ == i.pointed_node(); } + + bool operator!= (const list_iterator& i) const + { return !operator== (i); } + + value_type& operator*() const + { return *operator->(); } + + pointer operator->() const + { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(members_.nodeptr_)); } + + const Container *get_container() const + { + if(store_container_ptr){ + const Container* c = static_cast(members_.get_ptr()); + BOOST_INTRUSIVE_INVARIANT_ASSERT(c != 0); + return c; + } + else{ + return 0; + } + } + + const real_value_traits *get_real_value_traits() const + { + if(store_container_ptr) + return &this->get_container()->get_real_value_traits(); + else + return 0; + } + + private: + struct members + : public detail::select_constptr + ::type + { + typedef typename detail::select_constptr + ::type Base; + + members(const node_ptr &n_ptr, const void *cont) + : Base(cont), nodeptr_(n_ptr) + {} + + node_ptr nodeptr_; + } members_; +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_LIST_NODE_HPP diff --git a/win32/include/boost/intrusive/detail/mpl.hpp b/win32/include/boost/intrusive/detail/mpl.hpp new file mode 100755 index 000000000..2bb1449ed --- /dev/null +++ b/win32/include/boost/intrusive/detail/mpl.hpp @@ -0,0 +1,317 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_DETAIL_MPL_HPP +#define BOOST_INTRUSIVE_DETAIL_MPL_HPP + +#include + +namespace boost { +namespace intrusive { +namespace detail { + +typedef char one; +struct two {one _[2];}; + +template< bool C_ > +struct bool_ +{ + static const bool value = C_; +}; + +typedef bool_ true_; +typedef bool_ false_; + +typedef true_ true_type; +typedef false_ false_type; + +typedef char yes_type; +struct no_type +{ + char padding[8]; +}; + +template +struct enable_if_c { + typedef T type; +}; + +template +struct enable_if_c {}; + +template +struct enable_if : public enable_if_c{}; + +template +class is_convertible +{ + typedef char true_t; + class false_t { char dummy[2]; }; + static true_t dispatch(U); + static false_t dispatch(...); + static T trigger(); + public: + static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t); +}; + +template< + bool C + , typename T1 + , typename T2 + > +struct if_c +{ + typedef T1 type; +}; + +template< + typename T1 + , typename T2 + > +struct if_c +{ + typedef T2 type; +}; + +template< + typename C + , typename T1 + , typename T2 + > +struct if_ +{ + typedef typename if_c<0 != C::value, T1, T2>::type type; +}; + +template< + bool C + , typename F1 + , typename F2 + > +struct eval_if_c + : if_c::type +{}; + +template< + typename C + , typename T1 + , typename T2 + > +struct eval_if + : if_::type +{}; + +// identity is an extension: it is not part of the standard. +template +struct identity +{ + typedef T type; +}; + +#if defined(BOOST_MSVC) || defined(__BORLANDC_) +#define BOOST_INTRUSIVE_TT_DECL __cdecl +#else +#define BOOST_INTRUSIVE_TT_DECL +#endif + +#if defined(_MSC_EXTENSIONS) && !defined(__BORLAND__) +#define BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS +#endif + +no_type BOOST_INTRUSIVE_TT_DECL is_function_ptr_tester(...); + +template +yes_type is_function_ptr_tester(R (*)()); + +template +yes_type is_function_ptr_tester(R (*)( ...)); + +#ifdef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)()); +template +yes_type is_function_ptr_tester(R (__stdcall*)( ...)); + +template +yes_type is_function_ptr_tester(R (__fastcall*)()); +template +yes_type is_function_ptr_tester(R (__fastcall*)( ...)); + +template +yes_type is_function_ptr_tester(R (__cdecl*)()); +template +yes_type is_function_ptr_tester(R (__cdecl*)( ...)); +#endif + +template +yes_type is_function_ptr_tester(R (*)( T0)); + +template +yes_type is_function_ptr_tester(R (*)( T0 ...)); + +#ifdef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0)); +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 ...)); + +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0)); +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 ...)); + +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0)); +#endif +template +yes_type is_function_ptr_tester(R (*)( T0 , T1)); + +#ifdef BOOST_INTRUSIVE_TT_TEST_MSC_FUNC_SIGS +template +yes_type is_function_ptr_tester(R (__stdcall*)( T0 , T1)); + +template +yes_type is_function_ptr_tester(R (__fastcall*)( T0 , T1)); + +template +yes_type is_function_ptr_tester(R (__cdecl*)( T0 , T1)); +#endif + +template +struct is_unary_or_binary_function_impl +{ + static T* t; + static const bool value = sizeof(is_function_ptr_tester(t)) == sizeof(yes_type); +}; + +template +struct is_unary_or_binary_function_impl +{ + static const bool value = false; +}; + +template +struct is_unary_or_binary_function +{ + static const bool value = is_unary_or_binary_function_impl::value; +}; + +//boost::alignment_of yields to 10K lines of preprocessed code, so we +//need an alternative +template struct alignment_of; + +template +struct alignment_of_hack +{ + char c; + T t; + alignment_of_hack(); +}; + +template +struct alignment_logic +{ + static const std::size_t value = A < S ? A : S; +}; + +template< typename T > +struct alignment_of +{ + static const std::size_t value = alignment_logic + < sizeof(alignment_of_hack) - sizeof(T) + , sizeof(T) + >::value; +}; + +template +struct is_same +{ + typedef char yes_type; + struct no_type + { + char padding[8]; + }; + + template + static yes_type is_same_tester(V*, V*); + static no_type is_same_tester(...); + + static T *t; + static U *u; + + static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u)); +}; + +template +struct add_const +{ typedef const T type; }; + +template +struct remove_const +{ typedef T type; }; + +template +struct remove_const +{ typedef T type; }; + +template +struct remove_reference +{ + typedef T type; +}; + +template +struct remove_reference +{ + typedef T type; +}; + +template +class is_empty_class +{ + template + struct empty_helper_t1 : public T + { + empty_helper_t1(); + int i[256]; + }; + + struct empty_helper_t2 + { int i[256]; }; + + public: + static const bool value = sizeof(empty_helper_t1) == sizeof(empty_helper_t2); +}; + +template +struct ls_zeros +{ + static const std::size_t value = (S & std::size_t(1)) ? 0 : (1 + ls_zeros<(S>>1u)>::value); +}; + +template<> +struct ls_zeros<0> +{ + static const std::size_t value = 0; +}; + +template<> +struct ls_zeros<1> +{ + static const std::size_t value = 0; +}; + +} //namespace detail +} //namespace intrusive +} //namespace boost + +#endif //BOOST_INTRUSIVE_DETAIL_MPL_HPP diff --git a/win32/include/boost/intrusive/detail/parent_from_member.hpp b/win32/include/boost/intrusive/detail/parent_from_member.hpp new file mode 100755 index 000000000..c272d7c36 --- /dev/null +++ b/win32/include/boost/intrusive/detail/parent_from_member.hpp @@ -0,0 +1,70 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP +#define BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP + +#include +#include + +#if defined(BOOST_MSVC) || (defined (BOOST_WINDOWS) && defined(BOOST_INTEL)) +#define BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER +#include +#endif + +namespace boost { +namespace intrusive { +namespace detail { + +template +inline std::ptrdiff_t offset_from_pointer_to_member(const Member Parent::* ptr_to_member) +{ + //The implementation of a pointer to member is compiler dependent. + #if defined(BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER) + //msvc compliant compilers use their the first 32 bits as offset (even in 64 bit mode) + return *(const boost::int32_t*)(void*)&ptr_to_member; + //This works with gcc, msvc, ac++, ibmcpp + #elif defined(__GNUC__) || defined(__HP_aCC) || defined(BOOST_INTEL) || \ + defined(__IBMCPP__) || defined(__DECCXX) + const Parent * const parent = 0; + const char *const member = reinterpret_cast(&(parent->*ptr_to_member)); + return std::ptrdiff_t(member - reinterpret_cast(parent)); + #else + //This is the traditional C-front approach: __MWERKS__, __DMC__, __SUNPRO_CC + return (*(const std::ptrdiff_t*)(void*)&ptr_to_member) - 1; + #endif +} + +template +inline Parent *parent_from_member(Member *member, const Member Parent::* ptr_to_member) +{ + return (Parent*)((char*)member - + offset_from_pointer_to_member(ptr_to_member)); +} + +template +inline const Parent *parent_from_member(const Member *member, const Member Parent::* ptr_to_member) +{ + return (const Parent*)((const char*)member - + offset_from_pointer_to_member(ptr_to_member)); +} + +} //namespace detail { +} //namespace intrusive { +} //namespace boost { + +#ifdef BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER +#undef BOOST_INTRUSIVE_MSVC_COMPLIANT_PTR_TO_MEMBER +#endif + +#include + +#endif //#ifndef BOOST_INTRUSIVE_PARENT_FROM_MEMBER_HPP diff --git a/win32/include/boost/intrusive/detail/pointer_to_other.hpp b/win32/include/boost/intrusive/detail/pointer_to_other.hpp new file mode 100755 index 000000000..4d4dfa348 --- /dev/null +++ b/win32/include/boost/intrusive/detail/pointer_to_other.hpp @@ -0,0 +1,65 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006. 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_POINTER_TO_OTHER_HPP +#define BOOST_INTRUSIVE_POINTER_TO_OTHER_HPP + +#include +#include + +#if (BOOST_VERSION < 103400) + +#ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED +#define BOOST_POINTER_TO_OTHER_HPP_INCLUDED + +namespace boost { + +template + struct pointer_to_other; + +template class Sp> + struct pointer_to_other< Sp, U > +{ + typedef Sp type; +}; + +template class Sp> + struct pointer_to_other< Sp, U > +{ + typedef Sp type; +}; + +template class Sp> +struct pointer_to_other< Sp, U > +{ + typedef Sp type; +}; + +template +struct pointer_to_other< T*, U > +{ + typedef U* type; +}; + +} // namespace boost + +#endif + +#else + +#include + +#endif //#ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED + +#include + +#endif //#ifndef BOOST_INTRUSIVE_POINTER_TO_OTHER_HPP diff --git a/win32/include/boost/intrusive/detail/rbtree_node.hpp b/win32/include/boost/intrusive/detail/rbtree_node.hpp new file mode 100755 index 000000000..309264f6c --- /dev/null +++ b/win32/include/boost/intrusive/detail/rbtree_node.hpp @@ -0,0 +1,177 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007. +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_RBTREE_NODE_HPP +#define BOOST_INTRUSIVE_RBTREE_NODE_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +///////////////////////////////////////////////////////////////////////////// +// // +// Generic node_traits for any pointer type // +// // +///////////////////////////////////////////////////////////////////////////// + +//This is the compact representation: 3 pointers +template +struct compact_rbtree_node +{ + typedef typename pointer_to_other + >::type node_ptr; + enum color { red_t, black_t }; + node_ptr parent_, left_, right_; +}; + +//This is the normal representation: 3 pointers + enum +template +struct rbtree_node +{ + typedef typename pointer_to_other + >::type node_ptr; + + enum color { red_t, black_t }; + node_ptr parent_, left_, right_; + color color_; +}; + +//This is the default node traits implementation +//using a node with 3 generic pointers plus an enum +template +struct default_rbtree_node_traits_impl +{ + typedef rbtree_node node; + + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + + typedef typename node::color color; + + static node_ptr get_parent(const_node_ptr n) + { return n->parent_; } + + static void set_parent(node_ptr n, node_ptr p) + { n->parent_ = p; } + + static node_ptr get_left(const_node_ptr n) + { return n->left_; } + + static void set_left(node_ptr n, node_ptr l) + { n->left_ = l; } + + static node_ptr get_right(const_node_ptr n) + { return n->right_; } + + static void set_right(node_ptr n, node_ptr r) + { n->right_ = r; } + + static color get_color(const_node_ptr n) + { return n->color_; } + + static void set_color(node_ptr n, color c) + { n->color_ = c; } + + static color black() + { return node::black_t; } + + static color red() + { return node::red_t; } +}; + +//This is the compact node traits implementation +//using a node with 3 generic pointers +template +struct compact_rbtree_node_traits_impl +{ + typedef compact_rbtree_node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + + typedef pointer_plus_bits ptr_bit; + + typedef typename node::color color; + + static node_ptr get_parent(const_node_ptr n) + { return ptr_bit::get_pointer(n->parent_); } + + static void set_parent(node_ptr n, node_ptr p) + { ptr_bit::set_pointer(n->parent_, p); } + + static node_ptr get_left(const_node_ptr n) + { return n->left_; } + + static void set_left(node_ptr n, node_ptr l) + { n->left_ = l; } + + static node_ptr get_right(const_node_ptr n) + { return n->right_; } + + static void set_right(node_ptr n, node_ptr r) + { n->right_ = r; } + + static color get_color(const_node_ptr n) + { return (color)ptr_bit::get_bits(n->parent_); } + + static void set_color(node_ptr n, color c) + { ptr_bit::set_bits(n->parent_, c != 0); } + + static color black() + { return node::black_t; } + + static color red() + { return node::red_t; } +}; + +//Dispatches the implementation based on the boolean +template +struct rbtree_node_traits_dispatch + : public default_rbtree_node_traits_impl +{}; + +template +struct rbtree_node_traits_dispatch + : public compact_rbtree_node_traits_impl +{}; + +//Inherit from the detail::link_dispatch depending on the embedding capabilities +template +struct rbtree_node_traits + : public rbtree_node_traits_dispatch + < VoidPointer + , OptimizeSize && + (max_pointer_plus_bits + < VoidPointer + , detail::alignment_of >::value + >::value >= 1) + > +{}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_RBTREE_NODE_HPP diff --git a/win32/include/boost/intrusive/detail/slist_node.hpp b/win32/include/boost/intrusive/detail/slist_node.hpp new file mode 100755 index 000000000..7cb6385a4 --- /dev/null +++ b/win32/include/boost/intrusive/detail/slist_node.hpp @@ -0,0 +1,160 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_SLIST_NODE_HPP +#define BOOST_INTRUSIVE_SLIST_NODE_HPP + +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +template +struct slist_node +{ + typedef typename boost::pointer_to_other + ::type node_ptr; + node_ptr next_; +}; + +// slist_node_traits can be used with circular_slist_algorithms and supplies +// a slist_node holding the pointers needed for a singly-linked list +// it is used by slist_base_hook and slist_member_hook +template +struct slist_node_traits +{ + typedef slist_node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + + static node_ptr get_next(const_node_ptr n) + { return n->next_; } + + static void set_next(node_ptr n, node_ptr next) + { n->next_ = next; } +}; + +// slist_iterator provides some basic functions for a +// node oriented bidirectional iterator: +template +class slist_iterator + : public std::iterator + < std::forward_iterator_tag + , typename detail::add_const_if_c + ::type + > +{ + protected: + typedef typename Container::real_value_traits real_value_traits; + typedef typename real_value_traits::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename node_traits::node_ptr node_ptr; + typedef typename boost::pointer_to_other + ::type void_pointer; + static const bool store_container_ptr = + detail::store_cont_ptr_on_it::value; + + public: + typedef typename detail::add_const_if_c + + ::type value_type; + typedef value_type & reference; + typedef value_type * pointer; + + slist_iterator() + : members_ (node_ptr(0), 0) + {} + + explicit slist_iterator(node_ptr node, const Container *cont_ptr) + : members_ (node, cont_ptr) + {} + + slist_iterator(slist_iterator const& other) + : members_(other.pointed_node(), other.get_container()) + {} + + const node_ptr &pointed_node() const + { return members_.nodeptr_; } + + slist_iterator &operator=(const node_ptr &node) + { members_.nodeptr_ = node; return static_cast(*this); } + + public: + slist_iterator& operator++() + { + members_.nodeptr_ = node_traits::get_next(members_.nodeptr_); + return static_cast (*this); + } + + slist_iterator operator++(int) + { + slist_iterator result (*this); + members_.nodeptr_ = node_traits::get_next(members_.nodeptr_); + return result; + } + + bool operator== (const slist_iterator& i) const + { return members_.nodeptr_ == i.pointed_node(); } + + bool operator!= (const slist_iterator& i) const + { return !operator== (i); } + + value_type& operator*() const + { return *operator->(); } + + pointer operator->() const + { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(members_.nodeptr_)); } + + const Container *get_container() const + { + if(store_container_ptr) + return static_cast(members_.get_ptr()); + else + return 0; + } + + const real_value_traits *get_real_value_traits() const + { + if(store_container_ptr) + return &this->get_container()->get_real_value_traits(); + else + return 0; + } + + private: + struct members + : public detail::select_constptr + ::type + { + typedef typename detail::select_constptr + ::type Base; + + members(const node_ptr &n_ptr, const void *cont) + : Base(cont), nodeptr_(n_ptr) + {} + + node_ptr nodeptr_; + } members_; +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_SLIST_NODE_HPP diff --git a/win32/include/boost/intrusive/detail/transform_iterator.hpp b/win32/include/boost/intrusive/detail/transform_iterator.hpp new file mode 100755 index 000000000..35ba419c7 --- /dev/null +++ b/win32/include/boost/intrusive/detail/transform_iterator.hpp @@ -0,0 +1,173 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_DETAIL_TRANSFORM_ITERATOR_HPP +#define BOOST_INTRUSIVE_DETAIL_TRANSFORM_ITERATOR_HPP + +#include +#include +#include + +namespace boost { +namespace intrusive { +namespace detail { + +template +struct operator_arrow_proxy +{ + operator_arrow_proxy(const PseudoReference &px) + : m_value(px) + {} + + PseudoReference* operator->() const { return &m_value; } + // This function is needed for MWCW and BCC, which won't call operator-> + // again automatically per 13.3.1.2 para 8 +// operator T*() const { return &m_value; } + mutable PseudoReference m_value; +}; + +template +struct operator_arrow_proxy +{ + operator_arrow_proxy(T &px) + : m_value(px) + {} + + T* operator->() const { return &m_value; } + // This function is needed for MWCW and BCC, which won't call operator-> + // again automatically per 13.3.1.2 para 8 +// operator T*() const { return &m_value; } + mutable T &m_value; +}; + +template +class transform_iterator + : public std::iterator + < typename Iterator::iterator_category + , typename detail::remove_reference::type + , typename Iterator::difference_type + , operator_arrow_proxy + , typename UnaryFunction::result_type> +{ + public: + explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction()) + : members_(it, f) + {} + + explicit transform_iterator() + : members_() + {} + + Iterator get_it() const + { return members_.m_it; } + + //Constructors + transform_iterator& operator++() + { increment(); return *this; } + + transform_iterator operator++(int) + { + transform_iterator result (*this); + increment(); + return result; + } + + friend bool operator== (const transform_iterator& i, const transform_iterator& i2) + { return i.equal(i2); } + + friend bool operator!= (const transform_iterator& i, const transform_iterator& i2) + { return !(i == i2); } + +/* + friend bool operator> (const transform_iterator& i, const transform_iterator& i2) + { return i2 < i; } + + friend bool operator<= (const transform_iterator& i, const transform_iterator& i2) + { return !(i > i2); } + + friend bool operator>= (const transform_iterator& i, const transform_iterator& i2) + { return !(i < i2); } +*/ + friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2) + { return i2.distance_to(i); } + + //Arithmetic + transform_iterator& operator+=(typename Iterator::difference_type off) + { this->advance(off); return *this; } + + transform_iterator operator+(typename Iterator::difference_type off) const + { + transform_iterator other(*this); + other.advance(off); + return other; + } + + friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right) + { return right + off; } + + transform_iterator& operator-=(typename Iterator::difference_type off) + { this->advance(-off); return *this; } + + transform_iterator operator-(typename Iterator::difference_type off) const + { return *this + (-off); } + + typename UnaryFunction::result_type operator*() const + { return dereference(); } + + operator_arrow_proxy + operator->() const + { return operator_arrow_proxy(dereference()); } + + private: + struct members + : UnaryFunction + { + members(const Iterator &it, const UnaryFunction &f) + : UnaryFunction(f), m_it(it) + {} + + members() + {} + + Iterator m_it; + } members_; + + + void increment() + { ++members_.m_it; } + + void decrement() + { --members_.m_it; } + + bool equal(const transform_iterator &other) const + { return members_.m_it == other.members_.m_it; } + + bool less(const transform_iterator &other) const + { return other.members_.m_it < members_.m_it; } + + typename UnaryFunction::result_type dereference() const + { return members_(*members_.m_it); } + + void advance(typename Iterator::difference_type n) + { std::advance(members_.m_it, n); } + + typename Iterator::difference_type distance_to(const transform_iterator &other)const + { return std::distance(other.members_.m_it, members_.m_it); } +}; + +} //namespace detail +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_DETAIL_TRANSFORM_ITERATOR_HPP diff --git a/win32/include/boost/intrusive/detail/tree_algorithms.hpp b/win32/include/boost/intrusive/detail/tree_algorithms.hpp new file mode 100755 index 000000000..a935bc65d --- /dev/null +++ b/win32/include/boost/intrusive/detail/tree_algorithms.hpp @@ -0,0 +1,1625 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007. +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_TREE_ALGORITHMS_HPP +#define BOOST_INTRUSIVE_TREE_ALGORITHMS_HPP + +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { +namespace detail { + +//! This is an implementation of a binary search tree. +//! A node in the search tree has references to its children and its parent. This +//! is to allow traversal of the whole tree from a given node making the +//! implementation of iterator a pointer to a node. +//! At the top of the tree a node is used specially. This node's parent pointer +//! is pointing to the root of the tree. Its left pointer points to the +//! leftmost node in the tree and the right pointer to the rightmost one. +//! This node is used to represent the end-iterator. +//! +//! +---------+ +//! header------------------------------>| | +//! | | +//! +----------(left)--------| |--------(right)---------+ +//! | +---------+ | +//! | | | +//! | | (parent) | +//! | | | +//! | | | +//! | +---------+ | +//! root of tree ..|......................> | | | +//! | | D | | +//! | | | | +//! | +-------+---------+-------+ | +//! | | | | +//! | | | | +//! | | | | +//! | | | | +//! | | | | +//! | +---------+ +---------+ | +//! | | | | | | +//! | | B | | F | | +//! | | | | | | +//! | +--+---------+--+ +--+---------+--+ | +//! | | | | | | +//! | | | | | | +//! | | | | | | +//! | +---+-----+ +-----+---+ +---+-----+ +-----+---+ | +//! +-->| | | | | | | |<--+ +//! | A | | C | | E | | G | +//! | | | | | | | | +//! +---------+ +---------+ +---------+ +---------+ +//! + +//! tree_algorithms is configured with a NodeTraits class, which encapsulates the +//! information about the node to be manipulated. NodeTraits must support the +//! following interface: +//! +//! Typedefs: +//! +//! node: The type of the node that forms the circular list +//! +//! node_ptr: A pointer to a node +//! +//! const_node_ptr: A pointer to a const node +//! +//! Static functions: +//! +//! static node_ptr get_parent(const_node_ptr n); +//! +//! static void set_parent(node_ptr n, node_ptr parent); +//! +//! static node_ptr get_left(const_node_ptr n); +//! +//! static void set_left(node_ptr n, node_ptr left); +//! +//! static node_ptr get_right(const_node_ptr n); +//! +//! static void set_right(node_ptr n, node_ptr right); +template +class tree_algorithms +{ + public: + typedef typename NodeTraits::node node; + typedef NodeTraits node_traits; + typedef typename NodeTraits::node_ptr node_ptr; + typedef typename NodeTraits::const_node_ptr const_node_ptr; + + //! This type is the information that will be filled by insert_unique_check + struct insert_commit_data + { + insert_commit_data() + : link_left(false) + , node(0) + {} + bool link_left; + node_ptr node; + }; + + struct nop_erase_fixup + { + void operator()(node_ptr, node_ptr){} + }; + + /// @cond + private: + template + struct dispose_subtree_disposer + { + dispose_subtree_disposer(Disposer &disp, node_ptr subtree) + : disposer_(&disp), subtree_(subtree) + {} + + void release() + { disposer_ = 0; } + + ~dispose_subtree_disposer() + { + if(disposer_){ + dispose_subtree(subtree_, *disposer_); + } + } + Disposer *disposer_; + node_ptr subtree_; + }; + + static node_ptr uncast(const_node_ptr ptr) + { + return node_ptr(const_cast(::boost::intrusive::detail::get_pointer(ptr))); + } + /// @endcond + + public: + static node_ptr begin_node(const_node_ptr header) + { return node_traits::get_left(header); } + + static node_ptr end_node(const_node_ptr header) + { return uncast(header); } + + //! Requires: node is a node of the tree or an node initialized + //! by init(...) or init_node. + //! + //! Effects: Returns true if the node is initialized by init() or init_node(). + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + static bool unique(const_node_ptr node) + { return NodeTraits::get_parent(node) == 0; } + + static node_ptr get_header(const_node_ptr node) + { + node_ptr h = uncast(node); + if(NodeTraits::get_parent(node)){ + h = NodeTraits::get_parent(node); + while(!is_header(h)) + h = NodeTraits::get_parent(h); + } + return h; + } + + //! Requires: node1 and node2 can't be header nodes + //! of two trees. + //! + //! Effects: Swaps two nodes. After the function node1 will be inserted + //! in the position node2 before the function. node2 will be inserted in the + //! position node1 had before the function. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! node1 and node2 are not equivalent according to the ordering rules. + //! + //!Experimental function + static void swap_nodes(node_ptr node1, node_ptr node2) + { + if(node1 == node2) + return; + + node_ptr header1(get_header(node1)), header2(get_header(node2)); + swap_nodes(node1, header1, node2, header2); + } + + //! Requires: node1 and node2 can't be header nodes + //! of two trees with header header1 and header2. + //! + //! Effects: Swaps two nodes. After the function node1 will be inserted + //! in the position node2 before the function. node2 will be inserted in the + //! position node1 had before the function. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! node1 and node2 are not equivalent according to the ordering rules. + //! + //!Experimental function + static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, node_ptr header2) + { + if(node1 == node2) + return; + + //node1 and node2 must not be header nodes + //BOOST_INTRUSIVE_INVARIANT_ASSERT((header1 != node1 && header2 != node2)); + if(header1 != header2){ + //Update header1 if necessary + if(node1 == NodeTraits::get_left(header1)){ + NodeTraits::set_left(header1, node2); + } + + if(node1 == NodeTraits::get_right(header1)){ + NodeTraits::set_right(header1, node2); + } + + if(node1 == NodeTraits::get_parent(header1)){ + NodeTraits::set_parent(header1, node2); + } + + //Update header2 if necessary + if(node2 == NodeTraits::get_left(header2)){ + NodeTraits::set_left(header2, node1); + } + + if(node2 == NodeTraits::get_right(header2)){ + NodeTraits::set_right(header2, node1); + } + + if(node2 == NodeTraits::get_parent(header2)){ + NodeTraits::set_parent(header2, node1); + } + } + else{ + //If both nodes are from the same tree + //Update header if necessary + if(node1 == NodeTraits::get_left(header1)){ + NodeTraits::set_left(header1, node2); + } + else if(node2 == NodeTraits::get_left(header2)){ + NodeTraits::set_left(header2, node1); + } + + if(node1 == NodeTraits::get_right(header1)){ + NodeTraits::set_right(header1, node2); + } + else if(node2 == NodeTraits::get_right(header2)){ + NodeTraits::set_right(header2, node1); + } + + if(node1 == NodeTraits::get_parent(header1)){ + NodeTraits::set_parent(header1, node2); + } + else if(node2 == NodeTraits::get_parent(header2)){ + NodeTraits::set_parent(header2, node1); + } + + //Adjust data in nodes to be swapped + //so that final link swap works as expected + if(node1 == NodeTraits::get_parent(node2)){ + NodeTraits::set_parent(node2, node2); + + if(node2 == NodeTraits::get_right(node1)){ + NodeTraits::set_right(node1, node1); + } + else{ + NodeTraits::set_left(node1, node1); + } + } + else if(node2 == NodeTraits::get_parent(node1)){ + NodeTraits::set_parent(node1, node1); + + if(node1 == NodeTraits::get_right(node2)){ + NodeTraits::set_right(node2, node2); + } + else{ + NodeTraits::set_left(node2, node2); + } + } + } + + //Now swap all the links + node_ptr temp; + //swap left link + temp = NodeTraits::get_left(node1); + NodeTraits::set_left(node1, NodeTraits::get_left(node2)); + NodeTraits::set_left(node2, temp); + //swap right link + temp = NodeTraits::get_right(node1); + NodeTraits::set_right(node1, NodeTraits::get_right(node2)); + NodeTraits::set_right(node2, temp); + //swap parent link + temp = NodeTraits::get_parent(node1); + NodeTraits::set_parent(node1, NodeTraits::get_parent(node2)); + NodeTraits::set_parent(node2, temp); + + //Now adjust adjacent nodes for newly inserted node 1 + if((temp = NodeTraits::get_left(node1))){ + NodeTraits::set_parent(temp, node1); + } + if((temp = NodeTraits::get_right(node1))){ + NodeTraits::set_parent(temp, node1); + } + if((temp = NodeTraits::get_parent(node1)) && + //The header has been already updated so avoid it + temp != header2){ + if(NodeTraits::get_left(temp) == node2){ + NodeTraits::set_left(temp, node1); + } + if(NodeTraits::get_right(temp) == node2){ + NodeTraits::set_right(temp, node1); + } + } + //Now adjust adjacent nodes for newly inserted node 2 + if((temp = NodeTraits::get_left(node2))){ + NodeTraits::set_parent(temp, node2); + } + if((temp = NodeTraits::get_right(node2))){ + NodeTraits::set_parent(temp, node2); + } + if((temp = NodeTraits::get_parent(node2)) && + //The header has been already updated so avoid it + temp != header1){ + if(NodeTraits::get_left(temp) == node1){ + NodeTraits::set_left(temp, node2); + } + if(NodeTraits::get_right(temp) == node1){ + NodeTraits::set_right(temp, node2); + } + } + } + + //! Requires: node_to_be_replaced must be inserted in a tree + //! and new_node must not be inserted in a tree. + //! + //! Effects: Replaces node_to_be_replaced in its position in the + //! tree with new_node. The tree does not need to be rebalanced + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! new_node is not equivalent to node_to_be_replaced according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing and comparison is needed. + //! + //!Experimental function + static void replace_node(node_ptr node_to_be_replaced, node_ptr new_node) + { + if(node_to_be_replaced == new_node) + return; + replace_node(node_to_be_replaced, get_header(node_to_be_replaced), new_node); + } + + //! Requires: node_to_be_replaced must be inserted in a tree + //! with header "header" and new_node must not be inserted in a tree. + //! + //! Effects: Replaces node_to_be_replaced in its position in the + //! tree with new_node. The tree does not need to be rebalanced + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! new_node is not equivalent to node_to_be_replaced according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + //! + //!Experimental function + static void replace_node(node_ptr node_to_be_replaced, node_ptr header, node_ptr new_node) + { + if(node_to_be_replaced == new_node) + return; + + //Update header if necessary + if(node_to_be_replaced == NodeTraits::get_left(header)){ + NodeTraits::set_left(header, new_node); + } + + if(node_to_be_replaced == NodeTraits::get_right(header)){ + NodeTraits::set_right(header, new_node); + } + + if(node_to_be_replaced == NodeTraits::get_parent(header)){ + NodeTraits::set_parent(header, new_node); + } + + //Now set data from the original node + node_ptr temp; + NodeTraits::set_left(new_node, NodeTraits::get_left(node_to_be_replaced)); + NodeTraits::set_right(new_node, NodeTraits::get_right(node_to_be_replaced)); + NodeTraits::set_parent(new_node, NodeTraits::get_parent(node_to_be_replaced)); + + //Now adjust adjacent nodes for newly inserted node + if((temp = NodeTraits::get_left(new_node))){ + NodeTraits::set_parent(temp, new_node); + } + if((temp = NodeTraits::get_right(new_node))){ + NodeTraits::set_parent(temp, new_node); + } + if((temp = NodeTraits::get_parent(new_node)) && + //The header has been already updated so avoid it + temp != header){ + if(NodeTraits::get_left(temp) == node_to_be_replaced){ + NodeTraits::set_left(temp, new_node); + } + if(NodeTraits::get_right(temp) == node_to_be_replaced){ + NodeTraits::set_right(temp, new_node); + } + } + } + + //! Requires: p is a node from the tree except the header. + //! + //! Effects: Returns the next node of the tree. + //! + //! Complexity: Average constant time. + //! + //! Throws: Nothing. + static node_ptr next_node(node_ptr p) + { + node_ptr p_right(NodeTraits::get_right(p)); + if(p_right){ + return minimum(p_right); + } + else { + node_ptr x = NodeTraits::get_parent(p); + while(p == NodeTraits::get_right(x)){ + p = x; + x = NodeTraits::get_parent(x); + } + return NodeTraits::get_right(p) != x ? x : uncast(p); + } + } + + //! Requires: p is a node from the tree except the leftmost node. + //! + //! Effects: Returns the previous node of the tree. + //! + //! Complexity: Average constant time. + //! + //! Throws: Nothing. + static node_ptr prev_node(node_ptr p) + { + if(is_header(p)){ + return maximum(NodeTraits::get_parent(p)); + } + else if(NodeTraits::get_left(p)){ + return maximum(NodeTraits::get_left(p)); + } + else { + node_ptr x = NodeTraits::get_parent(p); + while(p == NodeTraits::get_left(x)){ + p = x; + x = NodeTraits::get_parent(x); + } + return x; + } + } + + //! Requires: p is a node of a tree but not the header. + //! + //! Effects: Returns the minimum node of the subtree starting at p. + //! + //! Complexity: Logarithmic to the size of the subtree. + //! + //! Throws: Nothing. + static node_ptr minimum (node_ptr p) + { + for(node_ptr p_left = NodeTraits::get_left(p) + ;p_left + ;p_left = NodeTraits::get_left(p)){ + p = p_left; + } + return p; + } + + //! Requires: p is a node of a tree but not the header. + //! + //! Effects: Returns the maximum node of the subtree starting at p. + //! + //! Complexity: Logarithmic to the size of the subtree. + //! + //! Throws: Nothing. + static node_ptr maximum(node_ptr p) + { + for(node_ptr p_right = NodeTraits::get_right(p) + ;p_right + ;p_right = NodeTraits::get_right(p)){ + p = p_right; + } + return p; + } + + //! Requires: node must not be part of any tree. + //! + //! Effects: After the function unique(node) == true. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Nodes: If node is inserted in a tree, this function corrupts the tree. + static void init(node_ptr node) + { + NodeTraits::set_parent(node, node_ptr(0)); + NodeTraits::set_left(node, node_ptr(0)); + NodeTraits::set_right(node, node_ptr(0)); + }; + + //! Effects: Returns true if node is in the same state as if called init(node) + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static bool inited(const_node_ptr node) + { + return !NodeTraits::get_parent(node) && + !NodeTraits::get_left(node) && + !NodeTraits::get_right(node) ; + }; + + //! Requires: node must not be part of any tree. + //! + //! Effects: Initializes the header to represent an empty tree. + //! unique(header) == true. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Nodes: If node is inserted in a tree, this function corrupts the tree. + static void init_header(node_ptr header) + { + NodeTraits::set_parent(header, node_ptr(0)); + NodeTraits::set_left(header, header); + NodeTraits::set_right(header, header); + } + + //! Requires: "disposer" must be an object function + //! taking a node_ptr parameter and shouldn't throw. + //! + //! Effects: Empties the target tree calling + //! void disposer::operator()(node_ptr) for every node of the tree + //! except the header. + //! + //! Complexity: Linear to the number of element of the source tree plus the. + //! number of elements of tree target tree when calling this function. + //! + //! Throws: If cloner functor throws. If this happens target nodes are disposed. + template + static void clear_and_dispose(node_ptr header, Disposer disposer) + { + node_ptr source_root = NodeTraits::get_parent(header); + if(!source_root) + return; + dispose_subtree(source_root, disposer); + init_header(header); + } + + //! Requires: header is the header of a tree. + //! + //! Effects: Unlinks the leftmost node from the tree, and + //! updates the header link to the new leftmost node. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + static node_ptr unlink_leftmost_without_rebalance(node_ptr header) + { + node_ptr leftmost = NodeTraits::get_left(header); + if (leftmost == header) + return node_ptr(0); + node_ptr leftmost_parent(NodeTraits::get_parent(leftmost)); + node_ptr leftmost_right (NodeTraits::get_right(leftmost)); + bool is_root = leftmost_parent == header; + + if (leftmost_right){ + NodeTraits::set_parent(leftmost_right, leftmost_parent); + NodeTraits::set_left(header, tree_algorithms::minimum(leftmost_right)); + + if (is_root) + NodeTraits::set_parent(header, leftmost_right); + else + NodeTraits::set_left(NodeTraits::get_parent(header), leftmost_right); + } + else if (is_root){ + NodeTraits::set_parent(header, node_ptr(0)); + NodeTraits::set_left(header, header); + NodeTraits::set_right(header, header); + } + else{ + NodeTraits::set_left(leftmost_parent, node_ptr(0)); + NodeTraits::set_left(header, leftmost_parent); + } + return leftmost; + } + + //! Requires: node is a node of the tree but it's not the header. + //! + //! Effects: Returns the number of nodes of the subtree. + //! + //! Complexity: Linear time. + //! + //! Throws: Nothing. + static std::size_t count(const_node_ptr subtree) + { + if(!subtree) return 0; + std::size_t count = 0; + node_ptr p = minimum(uncast(subtree)); + bool continue_looping = true; + while(continue_looping){ + ++count; + node_ptr p_right(NodeTraits::get_right(p)); + if(p_right){ + p = minimum(p_right); + } + else { + for(;;){ + node_ptr q; + if (p == subtree){ + continue_looping = false; + break; + } + q = p; + p = NodeTraits::get_parent(p); + if (NodeTraits::get_left(p) == q) + break; + } + } + } + return count; + } + + //! Requires: node is a node of the tree but it's not the header. + //! + //! Effects: Returns the number of nodes of the subtree. + //! + //! Complexity: Linear time. + //! + //! Throws: Nothing. + static std::size_t size(const_node_ptr header) + { + node_ptr beg(begin_node(header)); + node_ptr end(end_node(header)); + std::size_t i = 0; + for(;beg != end; beg = next_node(beg)) ++i; + return i; + } + + //! Requires: header1 and header2 must be the header nodes + //! of two trees. + //! + //! Effects: Swaps two trees. After the function header1 will contain + //! links to the second tree and header2 will have links to the first tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static void swap_tree(node_ptr header1, node_ptr header2) + { + if(header1 == header2) + return; + + node_ptr tmp; + + //Parent swap + tmp = NodeTraits::get_parent(header1); + NodeTraits::set_parent(header1, NodeTraits::get_parent(header2)); + NodeTraits::set_parent(header2, tmp); + //Left swap + tmp = NodeTraits::get_left(header1); + NodeTraits::set_left(header1, NodeTraits::get_left(header2)); + NodeTraits::set_left(header2, tmp); + //Right swap + tmp = NodeTraits::get_right(header1); + NodeTraits::set_right(header1, NodeTraits::get_right(header2)); + NodeTraits::set_right(header2, tmp); + + //Now test parent + node_ptr h1_parent(NodeTraits::get_parent(header1)); + if(h1_parent){ + NodeTraits::set_parent(h1_parent, header1); + } + else{ + NodeTraits::set_left(header1, header1); + NodeTraits::set_right(header1, header1); + } + + node_ptr h2_parent(NodeTraits::get_parent(header2)); + if(h2_parent){ + NodeTraits::set_parent(h2_parent, header2); + } + else{ + NodeTraits::set_left(header2, header2); + NodeTraits::set_right(header2, header2); + } + } + + static bool is_header(const_node_ptr p) + { +/* + node_ptr p_parent = NodeTraits::get_parent(p); + if(!p_parent) + return true; + if(!NodeTraits::get_parent(p_parent) != p) + return false; + if(NodeTraits::get_left(p) != 0){ + if(NodeTraits::get_parent(NodeTraits::get_left(p)) != p){ + is_header = true; + } + if(NodeTraits::get_parent(p) == NodeTraits::get_left(p)){ + is_header = true; + } + } +*/ + + bool is_header = false; + if(NodeTraits::get_parent(p) == p){ + is_header = true; + } + else if(NodeTraits::get_parent(NodeTraits::get_parent(p)) == p){ + if(NodeTraits::get_left(p) != 0){ + if(NodeTraits::get_parent(NodeTraits::get_left(p)) != p){ + is_header = true; + } + if(NodeTraits::get_parent(p) == NodeTraits::get_left(p)){ + is_header = true; + } + } + } + return is_header; + } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the element that is equivalent to + //! "key" according to "comp" or "header" if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr find + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { + node_ptr end = uncast(header); + node_ptr y = lower_bound(header, key, comp); + return (y == end || comp(key, y)) ? end : y; + } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an a pair of node_ptr delimiting a range containing + //! all elements that are equivalent to "key" according to "comp" or an + //! empty range that indicates the position where those elements would be + //! if they there are no equivalent elements. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static std::pair equal_range + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { + node_ptr y = uncast(header); + node_ptr x = NodeTraits::get_parent(header); + + while(x){ + if(comp(x, key)){ + x = NodeTraits::get_right(x); + } + else if(comp(key, x)){ + y = x; + x = NodeTraits::get_left(x); + } + else{ + node_ptr xu(x), yu(y); + y = x, x = NodeTraits::get_left(x); + xu = NodeTraits::get_right(xu); + + while(x){ + if(comp(x, key)){ + x = NodeTraits::get_right(x); + } + else { + y = x; + x = NodeTraits::get_left(x); + } + } + + while(xu){ + if(comp(key, xu)){ + yu = xu; + xu = NodeTraits::get_left(xu); + } + else { + xu = NodeTraits::get_right(xu); + } + } + return std::pair (y, yu); + } + } + return std::pair (y, y); + } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the first element that is + //! not less than "key" according to "comp" or "header" if that element does + //! not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr lower_bound + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { + node_ptr y = uncast(header); + node_ptr x = NodeTraits::get_parent(header); + while(x){ + if(comp(x, key)){ + x = NodeTraits::get_right(x); + } + else { + y = x; + x = NodeTraits::get_left(x); + } + } + return y; + } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the first element that is greater + //! than "key" according to "comp" or "header" if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr upper_bound + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { + node_ptr y = uncast(header); + node_ptr x = NodeTraits::get_parent(header); + while(x){ + if(comp(key, x)){ + y = x; + x = NodeTraits::get_left(x); + } + else { + x = NodeTraits::get_right(x); + } + } + return y; + } + + //! Requires: "header" must be the header node of a tree. + //! "commit_data" must have been obtained from a previous call to + //! "insert_unique_check". No objects should have been inserted or erased + //! from the set between the "insert_unique_check" that filled "commit_data" + //! and the call to "insert_commit". + //! + //! + //! Effects: Inserts new_node in the set using the information obtained + //! from the "commit_data" that a previous "insert_check" filled. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function has only sense if a "insert_unique_check" has been + //! previously executed to fill "commit_data". No value should be inserted or + //! erased between the "insert_check" and "insert_commit" calls. + static void insert_unique_commit + (node_ptr header, node_ptr new_value, const insert_commit_data &commit_data) + { + //Check if commit_data has not been initialized by a insert_unique_check call. + BOOST_INTRUSIVE_INVARIANT_ASSERT(commit_data.node != 0); + link(header, new_value, commit_data.node, commit_data.link_left); + } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares KeyType with a node_ptr. + //! + //! Effects: Checks if there is an equivalent node to "key" in the + //! tree according to "comp" and obtains the needed information to realize + //! a constant-time node insertion if there is no equivalent node. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing a node_ptr to the already present node + //! and false. If there is not equivalent key can be inserted returns true + //! in the returned pair's boolean and fills "commit_data" that is meant to + //! be used with the "insert_commit" function to achieve a constant-time + //! insertion function. + //! + //! Complexity: Average complexity is at most logarithmic. + //! + //! Throws: If "comp" throws. + //! + //! Notes: This function is used to improve performance when constructing + //! a node is expensive and the user does not want to have two equivalent nodes + //! in the tree: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the order is much cheaper to construct + //! than the node and this function offers the possibility to use that part + //! to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the node and use + //! "insert_commit" to insert the node in constant-time. This gives a total + //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_unique_commit" only + //! if no more objects are inserted or erased from the set. + template + static std::pair insert_unique_check + (const_node_ptr header, const KeyType &key + ,KeyNodePtrCompare comp, insert_commit_data &commit_data, std::size_t *pdepth = 0) + { + std::size_t depth = 0; + node_ptr h(uncast(header)); + node_ptr y(h); + node_ptr x(NodeTraits::get_parent(y)); + node_ptr prev(0); + + //Find the upper bound, cache the previous value and if we should + //store it in the left or right node + bool left_child = true; + while(x){ + ++depth; + y = x; + x = (left_child = comp(key, x)) ? + NodeTraits::get_left(x) : (prev = y, NodeTraits::get_right(x)); + } + + if(pdepth) *pdepth = depth; + + //Since we've found the upper bound there is no other value with the same key if: + // - There is no previous node + // - The previous node is less than the key + if(!prev || comp(prev, key)){ + commit_data.link_left = left_child; + commit_data.node = y; + return std::pair(node_ptr(), true); + } + //If the previous value was not less than key, it means that it's equal + //(because we've checked the upper bound) + else{ + return std::pair(prev, false); + } + } + + template + static std::pair insert_unique_check + (const_node_ptr header, node_ptr hint, const KeyType &key + ,KeyNodePtrCompare comp, insert_commit_data &commit_data, std::size_t *pdepth = 0) + { + //hint must be bigger than the key + if(hint == header || comp(key, hint)){ + node_ptr prev = hint; + //The previous value should be less than the key + if(prev == NodeTraits::get_left(header) || comp((prev = prev_node(hint)), key)){ + commit_data.link_left = unique(header) || !NodeTraits::get_left(hint); + commit_data.node = commit_data.link_left ? hint : prev; + if(pdepth){ + *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1; + } + return std::pair(node_ptr(), true); + } + else{ + return insert_unique_check(header, key, comp, commit_data, pdepth); + } + } + //The hint was wrong, use hintless insert + else{ + return insert_unique_check(header, key, comp, commit_data, pdepth); + } + } + + //! Requires: "header" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from + //! the "header"'s tree. + //! + //! Effects: Inserts new_node into the tree, using "hint" as a hint to + //! where it will be inserted. If "hint" is the upper_bound + //! the insertion takes constant time (two comparisons in the worst case). + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time if new_node is inserted immediately before "hint". + //! + //! Throws: If "comp" throws. + template + static node_ptr insert_equal + (node_ptr header, node_ptr hint, node_ptr new_node, NodePtrCompare comp, std::size_t *pdepth = 0) + { + if(hint == header || !comp(hint, new_node)){ + node_ptr prev(hint); + if(hint == NodeTraits::get_left(header) || + !comp(new_node, (prev = prev_node(hint)))){ + bool link_left = unique(header) || !NodeTraits::get_left(hint); + link(header, new_node, link_left ? hint : prev, link_left); + if(pdepth) *pdepth = depth(new_node) + 1; + return new_node; + } + else{ + return insert_equal_upper_bound(header, new_node, comp, pdepth); + } + } + else{ + return insert_equal_lower_bound(header, new_node, comp, pdepth); + } + } + + //! Requires: p can't be a header node. + //! + //! Effects: Calculates the depth of a node: the depth of a + //! node is the length (number of edges) of the path from the root + //! to that node. (The root node is at depth 0.) + //! + //! Complexity: Logarithmic to the number of nodes in the tree. + //! + //! Throws: Nothing. + static std::size_t depth(const_node_ptr p) + { + std::size_t depth = 0; + node_ptr p_parent; + while(p != NodeTraits::get_parent(p_parent = NodeTraits::get_parent(p))){ + ++depth; + p = p_parent; + } + return depth; + } + + template + static node_ptr insert_equal_upper_bound + (node_ptr h, node_ptr new_node, NodePtrCompare comp, std::size_t *pdepth = 0) + { + std::size_t depth = 0; + node_ptr y(h); + node_ptr x(NodeTraits::get_parent(y)); + + while(x){ + ++depth; + y = x; + x = comp(new_node, x) ? + NodeTraits::get_left(x) : NodeTraits::get_right(x); + } + + bool link_left = (y == h) || comp(new_node, y); + link(h, new_node, y, link_left); + if(pdepth) *pdepth = depth; + return new_node; + } + + template + static node_ptr insert_equal_lower_bound + (node_ptr h, node_ptr new_node, NodePtrCompare comp, std::size_t *pdepth = 0) + { + std::size_t depth = 0; + node_ptr y(h); + node_ptr x(NodeTraits::get_parent(y)); + + while(x){ + ++depth; + y = x; + x = !comp(x, new_node) ? + NodeTraits::get_left(x) : NodeTraits::get_right(x); + } + + bool link_left = (y == h) || !comp(y, new_node); + link(h, new_node, y, link_left); + if(pdepth) *pdepth = depth; + return new_node; + } + + //! Requires: "cloner" must be a function + //! object taking a node_ptr and returning a new cloned node of it. "disposer" must + //! take a node_ptr and shouldn't throw. + //! + //! Effects: First empties target tree calling + //! void disposer::operator()(node_ptr) for every node of the tree + //! except the header. + //! + //! Then, duplicates the entire tree pointed by "source_header" cloning each + //! source node with node_ptr Cloner::operator()(node_ptr) to obtain + //! the nodes of the target tree. If "cloner" throws, the cloned target nodes + //! are disposed using void disposer(node_ptr). + //! + //! Complexity: Linear to the number of element of the source tree plus the. + //! number of elements of tree target tree when calling this function. + //! + //! Throws: If cloner functor throws. If this happens target nodes are disposed. + template + static void clone + (const_node_ptr source_header, node_ptr target_header, Cloner cloner, Disposer disposer) + { + if(!unique(target_header)){ + clear_and_dispose(target_header, disposer); + } + + node_ptr leftmost, rightmost; + node_ptr new_root = clone_subtree + (source_header, target_header, cloner, disposer, leftmost, rightmost); + + //Now update header node + NodeTraits::set_parent(target_header, new_root); + NodeTraits::set_left (target_header, leftmost); + NodeTraits::set_right (target_header, rightmost); + } + + template + static node_ptr clone_subtree + ( const_node_ptr source_parent, node_ptr target_parent + , Cloner cloner, Disposer disposer + , node_ptr &leftmost_out, node_ptr &rightmost_out + ) + { + node_ptr target_sub_root = target_parent; + node_ptr source_root = NodeTraits::get_parent(source_parent); + if(!source_root){ + leftmost_out = rightmost_out = source_root; + } + else{ + //We'll calculate leftmost and rightmost nodes while iterating + node_ptr current = source_root; + node_ptr insertion_point = target_sub_root = cloner(current); + + //We'll calculate leftmost and rightmost nodes while iterating + node_ptr leftmost = target_sub_root; + node_ptr rightmost = target_sub_root; + + //First set the subroot + NodeTraits::set_left(target_sub_root, node_ptr(0)); + NodeTraits::set_right(target_sub_root, node_ptr(0)); + NodeTraits::set_parent(target_sub_root, target_parent); + + dispose_subtree_disposer rollback(disposer, target_sub_root); + while(true) { + //First clone left nodes + if( NodeTraits::get_left(current) && + !NodeTraits::get_left(insertion_point)) { + current = NodeTraits::get_left(current); + node_ptr temp = insertion_point; + //Clone and mark as leaf + insertion_point = cloner(current); + NodeTraits::set_left (insertion_point, node_ptr(0)); + NodeTraits::set_right (insertion_point, node_ptr(0)); + //Insert left + NodeTraits::set_parent(insertion_point, temp); + NodeTraits::set_left (temp, insertion_point); + //Update leftmost + if(rightmost == target_sub_root) + leftmost = insertion_point; + } + //Then clone right nodes + else if( NodeTraits::get_right(current) && + !NodeTraits::get_right(insertion_point)){ + current = NodeTraits::get_right(current); + node_ptr temp = insertion_point; + //Clone and mark as leaf + insertion_point = cloner(current); + NodeTraits::set_left (insertion_point, node_ptr(0)); + NodeTraits::set_right (insertion_point, node_ptr(0)); + //Insert right + NodeTraits::set_parent(insertion_point, temp); + NodeTraits::set_right (temp, insertion_point); + //Update rightmost + rightmost = insertion_point; + } + //If not, go up + else if(current == source_root){ + break; + } + else{ + //Branch completed, go up searching more nodes to clone + current = NodeTraits::get_parent(current); + insertion_point = NodeTraits::get_parent(insertion_point); + } + } + rollback.release(); + leftmost_out = leftmost; + rightmost_out = rightmost; + } + return target_sub_root; + } + + template + static void dispose_subtree(node_ptr x, Disposer disposer) + { + node_ptr save; + while (x){ + save = NodeTraits::get_left(x); + if (save) { + // Right rotation + NodeTraits::set_left(x, NodeTraits::get_right(save)); + NodeTraits::set_right(save, x); + } + else { + save = NodeTraits::get_right(x); + init(x); + disposer(x); + } + x = save; + } + } + + //! Requires: p is a node of a tree. + //! + //! Effects: Returns true if p is a left child. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static bool is_left_child(node_ptr p) + { return NodeTraits::get_left(NodeTraits::get_parent(p)) == p; } + + //! Requires: p is a node of a tree. + //! + //! Effects: Returns true if p is a right child. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static bool is_right_child (node_ptr p) + { return NodeTraits::get_right(NodeTraits::get_parent(p)) == p; } + + static void replace_own (node_ptr own, node_ptr x, node_ptr header) + { + if(NodeTraits::get_parent(header) == own) + NodeTraits::set_parent(header, x); + else if(is_left_child(own)) + NodeTraits::set_left(NodeTraits::get_parent(own), x); + else + NodeTraits::set_right(NodeTraits::get_parent(own), x); + } + + static void rotate_left(node_ptr p, node_ptr header) + { + node_ptr x = NodeTraits::get_right(p); + NodeTraits::set_right(p, NodeTraits::get_left(x)); + if(NodeTraits::get_left(x) != 0) + NodeTraits::set_parent(NodeTraits::get_left(x), p); + NodeTraits::set_parent(x, NodeTraits::get_parent(p)); + replace_own (p, x, header); + NodeTraits::set_left(x, p); + NodeTraits::set_parent(p, x); + } + + static void rotate_right(node_ptr p, node_ptr header) + { + node_ptr x(NodeTraits::get_left(p)); + node_ptr x_right(NodeTraits::get_right(x)); + NodeTraits::set_left(p, x_right); + if(x_right) + NodeTraits::set_parent(x_right, p); + NodeTraits::set_parent(x, NodeTraits::get_parent(p)); + replace_own (p, x, header); + NodeTraits::set_right(x, p); + NodeTraits::set_parent(p, x); + } + + // rotate node t with left child | complexity : constant | exception : nothrow + static node_ptr rotate_left(node_ptr t) + { + node_ptr x = NodeTraits::get_right(t); + NodeTraits::set_right(t, NodeTraits::get_left(x)); + + if( NodeTraits::get_right(t) != 0 ){ + NodeTraits::set_parent(NodeTraits::get_right(t), t ); + } + NodeTraits::set_left(x, t); + NodeTraits::set_parent(t, x); + return x; + } + + // rotate node t with right child | complexity : constant | exception : nothrow + static node_ptr rotate_right(node_ptr t) + { + node_ptr x = NodeTraits::get_left(t); + NodeTraits::set_left(t, NodeTraits::get_right(x)); + if( NodeTraits::get_left(t) != 0 ){ + NodeTraits::set_parent(NodeTraits::get_left(t), t); + } + NodeTraits::set_right(x, t); + NodeTraits::set_parent(t, x); + return x; + } + + static void link(node_ptr header, node_ptr z, node_ptr par, bool left) + { + if(par == header){ + NodeTraits::set_parent(header, z); + NodeTraits::set_right(header, z); + NodeTraits::set_left(header, z); + } + else if(left){ + NodeTraits::set_left(par, z); + if(par == NodeTraits::get_left(header)) + NodeTraits::set_left(header, z); + } + else{ + NodeTraits::set_right(par, z); + if(par == NodeTraits::get_right(header)) + NodeTraits::set_right(header, z); + } + NodeTraits::set_parent(z, par); + NodeTraits::set_right(z, node_ptr(0)); + NodeTraits::set_left(z, node_ptr(0)); + } + + static void erase(node_ptr header, node_ptr z) + { + data_for_rebalance ignored; + erase(header, z, nop_erase_fixup(), ignored); + } + + struct data_for_rebalance + { + node_ptr x; + node_ptr x_parent; + node_ptr y; + }; + + template + static void erase(node_ptr header, node_ptr z, F z_and_successor_fixup, data_for_rebalance &info) + { + erase_impl(header, z, info); + if(info.y != z){ + z_and_successor_fixup(z, info.y); + } + } + + static void unlink(node_ptr node) + { + node_ptr x = NodeTraits::get_parent(node); + if(x){ + while(!is_header(x)) + x = NodeTraits::get_parent(x); + erase(x, node); + } + } + + static void tree_to_vine(node_ptr header) + { subtree_to_vine(NodeTraits::get_parent(header)); } + + static void vine_to_tree(node_ptr header, std::size_t count) + { vine_to_subtree(NodeTraits::get_parent(header), count); } + + static void rebalance(node_ptr header) + { + //Taken from: + //"Tree rebalancing in optimal time and space" + //Quentin F. Stout and Bette L. Warren + std::size_t len; + subtree_to_vine(NodeTraits::get_parent(header), &len); + vine_to_subtree(NodeTraits::get_parent(header), len); + } + + static node_ptr rebalance_subtree(node_ptr old_root) + { + std::size_t len; + node_ptr new_root = subtree_to_vine(old_root, &len); + return vine_to_subtree(new_root, len); + } + + static node_ptr subtree_to_vine(node_ptr old_root, std::size_t *plen = 0) + { + std::size_t len; + len = 0; + if(!old_root) return node_ptr(0); + + //To avoid irregularities in the algorithm (old_root can be a + //left or right child or even the root of the tree) just put the + //root as the right child of its parent. Before doing this backup + //information to restore the original relationship after + //the algorithm is applied. + node_ptr super_root = NodeTraits::get_parent(old_root); + BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root); + + //Get info + node_ptr super_root_right_backup = NodeTraits::get_right(super_root); + bool super_root_is_header = is_header(super_root); + bool old_root_is_right = is_right_child(old_root); + + node_ptr x(old_root); + node_ptr new_root(x); + node_ptr save; + bool moved_to_right = false; + for( ; x; x = save){ + save = NodeTraits::get_left(x); + if(save){ + // Right rotation + node_ptr save_right = NodeTraits::get_right(save); + node_ptr x_parent = NodeTraits::get_parent(x); + NodeTraits::set_parent(save, x_parent); + NodeTraits::set_right (x_parent, save); + NodeTraits::set_parent(x, save); + NodeTraits::set_right (save, x); + NodeTraits::set_left(x, save_right); + if(save_right) + NodeTraits::set_parent(save_right, x); + if(!moved_to_right) + new_root = save; + } + else{ + moved_to_right = true; + save = NodeTraits::get_right(x); + ++len; + } + } + + if(super_root_is_header){ + NodeTraits::set_right(super_root, super_root_right_backup); + NodeTraits::set_parent(super_root, new_root); + } + else if(old_root_is_right){ + NodeTraits::set_right(super_root, new_root); + } + else{ + NodeTraits::set_right(super_root, super_root_right_backup); + NodeTraits::set_left(super_root, new_root); + } + if(plen) *plen = len; + return new_root; + } + + static node_ptr vine_to_subtree(node_ptr old_root, std::size_t count) + { + std::size_t leaf_nodes = count + 1 - ((size_t) 1 << floor_log2 (count + 1)); + std::size_t vine_nodes = count - leaf_nodes; + + node_ptr new_root = compress_subtree(old_root, leaf_nodes); + while(vine_nodes > 1){ + vine_nodes /= 2; + new_root = compress_subtree(new_root, vine_nodes); + } + return new_root; + } + + static node_ptr compress_subtree(node_ptr old_root, std::size_t count) + { + if(!old_root) return old_root; + + //To avoid irregularities in the algorithm (old_root can be + //left or right child or even the root of the tree) just put the + //root as the right child of its parent. First obtain + //information to restore the original relationship after + //the algorithm is applied. + node_ptr super_root = NodeTraits::get_parent(old_root); + BOOST_INTRUSIVE_INVARIANT_ASSERT(super_root); + + //Get info + node_ptr super_root_right_backup = NodeTraits::get_right(super_root); + bool super_root_is_header = is_header(super_root); + bool old_root_is_right = is_right_child(old_root); + + //Put old_root as right child + NodeTraits::set_right(super_root, old_root); + + //Start the compression algorithm + node_ptr even_parent = super_root; + node_ptr new_root = old_root; + + while(count--){ + node_ptr even = NodeTraits::get_right(even_parent); + node_ptr odd = NodeTraits::get_right(even); + + if(new_root == old_root) + new_root = odd; + + node_ptr even_right = NodeTraits::get_left(odd); + NodeTraits::set_right(even, even_right); + if (even_right) + NodeTraits::set_parent(even_right, even); + + NodeTraits::set_right(even_parent, odd); + NodeTraits::set_parent(odd, even_parent); + NodeTraits::set_left(odd, even); + NodeTraits::set_parent(even, odd); + even_parent = odd; + } + + if(super_root_is_header){ + NodeTraits::set_parent(super_root, new_root); + NodeTraits::set_right(super_root, super_root_right_backup); + } + else if(old_root_is_right){ + NodeTraits::set_right(super_root, new_root); + } + else{ + NodeTraits::set_left(super_root, new_root); + NodeTraits::set_right(super_root, super_root_right_backup); + } + return new_root; + } + + //! Requires: "n" must be a node inserted in a tree. + //! + //! Effects: Returns a pointer to the header node of the tree. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + static node_ptr get_root(node_ptr node) + { + BOOST_INTRUSIVE_INVARIANT_ASSERT((!inited(node))); + node_ptr x = NodeTraits::get_parent(node); + if(x){ + while(!is_header(x)){ + x = NodeTraits::get_parent(x); + } + return x; + } + else{ + return node; + } + } + + private: + static void erase_impl(node_ptr header, node_ptr z, data_for_rebalance &info) + { + node_ptr y(z); + node_ptr x; + node_ptr x_parent(0); + node_ptr z_left(NodeTraits::get_left(z)); + node_ptr z_right(NodeTraits::get_right(z)); + if(!z_left){ + x = z_right; // x might be null. + } + else if(!z_right){ // z has exactly one non-null child. y == z. + x = z_left; // x is not null. + } + else{ + // find z's successor + y = tree_algorithms::minimum (z_right); + x = NodeTraits::get_right(y); // x might be null. + } + + if(y != z){ + // relink y in place of z. y is z's successor + NodeTraits::set_parent(NodeTraits::get_left(z), y); + NodeTraits::set_left(y, NodeTraits::get_left(z)); + if(y != NodeTraits::get_right(z)){ + x_parent = NodeTraits::get_parent(y); + if(x) + NodeTraits::set_parent(x, x_parent); + NodeTraits::set_left(x_parent, x); // y must be a child of left_ + NodeTraits::set_right(y, NodeTraits::get_right(z)); + NodeTraits::set_parent(NodeTraits::get_right(z), y); + } + else + x_parent = y; + tree_algorithms::replace_own (z, y, header); + NodeTraits::set_parent(y, NodeTraits::get_parent(z)); + } + else { // y == z --> z has only one child, or none + x_parent = NodeTraits::get_parent(z); + if(x) + NodeTraits::set_parent(x, x_parent); + tree_algorithms::replace_own (z, x, header); + if(NodeTraits::get_left(header) == z){ + NodeTraits::set_left(header, NodeTraits::get_right(z) == 0 ? // z->get_left() must be null also + NodeTraits::get_parent(z) : // makes leftmost == header if z == root + tree_algorithms::minimum (x)); + } + if(NodeTraits::get_right(header) == z){ + NodeTraits::set_right(header, NodeTraits::get_left(z) == 0 ? // z->get_right() must be null also + NodeTraits::get_parent(z) : // makes rightmost == header if z == root + tree_algorithms::maximum(x)); + } + } + + info.x = x; + info.x_parent = x_parent; + info.y = y; + } +}; + +} //namespace detail { +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_TREE_ALGORITHMS_HPP diff --git a/win32/include/boost/intrusive/detail/tree_node.hpp b/win32/include/boost/intrusive/detail/tree_node.hpp new file mode 100755 index 000000000..a36d54024 --- /dev/null +++ b/win32/include/boost/intrusive/detail/tree_node.hpp @@ -0,0 +1,197 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007. +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_TREE_NODE_HPP +#define BOOST_INTRUSIVE_TREE_NODE_HPP + +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +template +struct tree_node +{ + typedef typename pointer_to_other + >::type node_ptr; + + node_ptr parent_, left_, right_; +}; + +template +struct tree_node_traits +{ + typedef tree_node node; + + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + + static node_ptr get_parent(const_node_ptr n) + { return n->parent_; } + + static void set_parent(node_ptr n, node_ptr p) + { n->parent_ = p; } + + static node_ptr get_left(const_node_ptr n) + { return n->left_; } + + static void set_left(node_ptr n, node_ptr l) + { n->left_ = l; } + + static node_ptr get_right(const_node_ptr n) + { return n->right_; } + + static void set_right(node_ptr n, node_ptr r) + { n->right_ = r; } +}; + +///////////////////////////////////////////////////////////////////////////// +// // +// Implementation of the tree iterator // +// // +///////////////////////////////////////////////////////////////////////////// + +// tree_iterator provides some basic functions for a +// node oriented bidirectional iterator: +template +class tree_iterator + : public std::iterator + < std::bidirectional_iterator_tag + , typename detail::add_const_if_c + ::type + > +{ + protected: + typedef typename Container::real_value_traits real_value_traits; + typedef typename Container::node_algorithms node_algorithms; + typedef typename real_value_traits::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename node_traits::node_ptr node_ptr; + typedef typename boost::pointer_to_other + ::type void_pointer; + static const bool store_container_ptr = + detail::store_cont_ptr_on_it::value; + + public: + public: + typedef typename detail::add_const_if_c + + ::type value_type; + typedef value_type & reference; + typedef value_type * pointer; + + tree_iterator() + : members_ (0, 0) + {} + + explicit tree_iterator(node_ptr node, const Container *cont_ptr) + : members_ (node, cont_ptr) + {} + + tree_iterator(tree_iterator const& other) + : members_(other.pointed_node(), other.get_container()) + {} + + const node_ptr &pointed_node() const + { return members_.nodeptr_; } + + tree_iterator &operator=(const node_ptr &node) + { members_.nodeptr_ = node; return static_cast(*this); } + + public: + tree_iterator& operator++() + { + members_.nodeptr_ = node_algorithms::next_node(members_.nodeptr_); + return static_cast (*this); + } + + tree_iterator operator++(int) + { + tree_iterator result (*this); + members_.nodeptr_ = node_algorithms::next_node(members_.nodeptr_); + return result; + } + + tree_iterator& operator--() + { + members_.nodeptr_ = node_algorithms::prev_node(members_.nodeptr_); + return static_cast (*this); + } + + tree_iterator operator--(int) + { + tree_iterator result (*this); + members_.nodeptr_ = node_algorithms::prev_node(members_.nodeptr_); + return result; + } + + bool operator== (const tree_iterator& i) const + { return members_.nodeptr_ == i.pointed_node(); } + + bool operator!= (const tree_iterator& i) const + { return !operator== (i); } + + value_type& operator*() const + { return *operator->(); } + + pointer operator->() const + { return detail::get_pointer(this->get_real_value_traits()->to_value_ptr(members_.nodeptr_)); } + + const Container *get_container() const + { + if(store_container_ptr) + return static_cast(members_.get_ptr()); + else + return 0; + } + + const real_value_traits *get_real_value_traits() const + { + if(store_container_ptr) + return &this->get_container()->get_real_value_traits(); + else + return 0; + } + + tree_iterator end_iterator_from_it() const + { + return tree_iterator(node_algorithms::get_header(this->pointed_node()), this->get_container()); + } + + private: + struct members + : public detail::select_constptr + ::type + { + typedef typename detail::select_constptr + ::type Base; + + members(const node_ptr &n_ptr, const void *cont) + : Base(cont), nodeptr_(n_ptr) + {} + + node_ptr nodeptr_; + } members_; +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_TREE_NODE_HPP diff --git a/win32/include/boost/intrusive/detail/utilities.hpp b/win32/include/boost/intrusive/detail/utilities.hpp new file mode 100755 index 000000000..a9392566e --- /dev/null +++ b/win32/include/boost/intrusive/detail/utilities.hpp @@ -0,0 +1,629 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_DETAIL_UTILITIES_HPP +#define BOOST_INTRUSIVE_DETAIL_UTILITIES_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { +namespace detail { + +template +struct internal_member_value_traits +{ + template static detail::one test(...); + template static detail::two test(typename U::member_value_traits* = 0); + static const bool value = sizeof(test(0)) == sizeof(detail::two); +}; + +template +struct internal_base_hook_bool +{ + template + struct two_or_three {one _[2 + Add];}; + template static one test(...); + template static two_or_three + test (detail::bool_* = 0); + static const std::size_t value = sizeof(test(0)); +}; + +template +struct internal_base_hook_bool_is_true +{ + static const bool value = internal_base_hook_bool::value > sizeof(one)*2; +}; + +template +struct internal_any_hook_bool +{ + template + struct two_or_three {one _[2 + Add];}; + template static one test(...); + template static two_or_three + test (detail::bool_* = 0); + static const std::size_t value = sizeof(test(0)); +}; + +template +struct internal_any_hook_bool_is_true +{ + static const bool value = internal_any_hook_bool::value > sizeof(one)*2; +}; + + +template +struct external_value_traits_bool +{ + template + struct two_or_three {one _[2 + Add];}; + template static one test(...); + template static two_or_three + test (detail::bool_* = 0); + static const std::size_t value = sizeof(test(0)); +}; + +template +struct external_bucket_traits_bool +{ + template + struct two_or_three {one _[2 + Add];}; + template static one test(...); + template static two_or_three + test (detail::bool_* = 0); + static const std::size_t value = sizeof(test(0)); +}; + +template +struct external_value_traits_is_true +{ + static const bool value = external_value_traits_bool::value > sizeof(one)*2; +}; + +template +struct node_holder + : public Node +{}; + +template +struct smart_ptr_type +{ + typedef typename SmartPtr::value_type value_type; + typedef value_type *pointer; + static pointer get (const SmartPtr &smartptr) + { return smartptr.get();} +}; + +template +struct smart_ptr_type +{ + typedef T value_type; + typedef value_type *pointer; + static pointer get (pointer ptr) + { return ptr;} +}; + +//!Overload for smart pointers to avoid ADL problems with get_pointer +template +inline typename smart_ptr_type::pointer +get_pointer(const Ptr &ptr) +{ return smart_ptr_type::get(ptr); } + +//This functor compares a stored value +//and the one passed as an argument +template +class equal_to_value +{ + ConstReference t_; + + public: + equal_to_value(ConstReference t) + : t_(t) + {} + + bool operator()(ConstReference t)const + { return t_ == t; } +}; + +class null_disposer +{ + public: + template + void operator()(Pointer) + {} +}; + +template +class init_disposer +{ + typedef typename NodeAlgorithms::node_ptr node_ptr; + + public: + void operator()(node_ptr p) + { NodeAlgorithms::init(p); } +}; + +template +struct size_holder +{ + static const bool constant_time_size = ConstantSize; + typedef SizeType size_type; + + SizeType get_size() const + { return size_; } + + void set_size(SizeType size) + { size_ = size; } + + void decrement() + { --size_; } + + void increment() + { ++size_; } + + SizeType size_; +}; + +template +struct size_holder +{ + static const bool constant_time_size = false; + typedef SizeType size_type; + + size_type get_size() const + { return 0; } + + void set_size(size_type) + {} + + void decrement() + {} + + void increment() + {} +}; + +template +struct key_nodeptr_comp + : private detail::ebo_functor_holder +{ + typedef typename Container::real_value_traits real_value_traits; + typedef typename real_value_traits::node_ptr node_ptr; + typedef detail::ebo_functor_holder base_t; + key_nodeptr_comp(KeyValueCompare kcomp, const Container *cont) + : base_t(kcomp), cont_(cont) + {} + + template + bool operator()(node_ptr node, const KeyType &key) const + { return base_t::get()(*cont_->get_real_value_traits().to_value_ptr(node), key); } + + template + bool operator()(const KeyType &key, node_ptr node) const + { return base_t::get()(key, *cont_->get_real_value_traits().to_value_ptr(node)); } + + bool operator()(node_ptr node1, node_ptr node2) const + { + return base_t::get() + ( *cont_->get_real_value_traits().to_value_ptr(node1) + , *cont_->get_real_value_traits().to_value_ptr(node2) + ); + } + + const Container *cont_; +}; + +template +struct node_cloner + : private detail::ebo_functor_holder +{ + typedef typename Container::real_value_traits real_value_traits; + typedef typename Container::node_algorithms node_algorithms; + typedef typename real_value_traits::value_type value_type; + typedef typename real_value_traits::pointer pointer; + typedef typename real_value_traits::node_traits::node node; + typedef typename real_value_traits::node_ptr node_ptr; + typedef typename real_value_traits::const_node_ptr const_node_ptr; + typedef detail::ebo_functor_holder base_t; + enum { safemode_or_autounlink = + (int)real_value_traits::link_mode == (int)auto_unlink || + (int)real_value_traits::link_mode == (int)safe_link }; + + node_cloner(F f, const Container *cont) + : base_t(f), cont_(cont) + {} + + node_ptr operator()(node_ptr p) + { return this->operator()(*p); } + + node_ptr operator()(const node &to_clone) + { + const value_type &v = + *cont_->get_real_value_traits().to_value_ptr(const_node_ptr(&to_clone)); + node_ptr n = cont_->get_real_value_traits().to_node_ptr(*base_t::get()(v)); + //Cloned node must be in default mode if the linking mode requires it + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n)); + return n; + } + + const Container *cont_; +}; + +template +struct node_disposer + : private detail::ebo_functor_holder +{ + typedef typename Container::real_value_traits real_value_traits; + typedef typename real_value_traits::node_ptr node_ptr; + typedef detail::ebo_functor_holder base_t; + typedef typename Container::node_algorithms node_algorithms; + enum { safemode_or_autounlink = + (int)real_value_traits::link_mode == (int)auto_unlink || + (int)real_value_traits::link_mode == (int)safe_link }; + + node_disposer(F f, const Container *cont) + : base_t(f), cont_(cont) + {} + + void operator()(node_ptr p) + { + if(safemode_or_autounlink) + node_algorithms::init(p); + base_t::get()(cont_->get_real_value_traits().to_value_ptr(p)); + } + const Container *cont_; +}; + +struct dummy_constptr +{ + dummy_constptr(const void *) + {} + + const void *get_ptr() const + { return 0; } +}; + +template +struct constptr +{ + typedef typename boost::pointer_to_other + ::type ConstVoidPtr; + + constptr(const void *ptr) + : const_void_ptr_(ptr) + {} + + const void *get_ptr() const + { return detail::get_pointer(const_void_ptr_); } + + ConstVoidPtr const_void_ptr_; +}; + +template +struct select_constptr +{ + typedef typename detail::if_c + < store_ptr + , constptr + , dummy_constptr + >::type type; +}; + +template +struct store_cont_ptr_on_it +{ + typedef typename Container::value_traits value_traits; + static const bool value = + !detail::is_empty_class::value + || detail::external_value_traits_is_true::value + ; +}; + +template +struct add_const_if_c +{ + typedef typename detail::if_c + < Add + , typename detail::add_const::type + , T + >::type type; +}; + +template +struct node_to_value + : public detail::select_constptr + < typename boost::pointer_to_other + ::type + , detail::store_cont_ptr_on_it::value + >::type +{ + static const bool store_container_ptr = + detail::store_cont_ptr_on_it::value; + + typedef typename Container::real_value_traits real_value_traits; + typedef typename real_value_traits::value_type value_type; + typedef typename detail::select_constptr + < typename boost::pointer_to_other + ::type + , store_container_ptr >::type Base; + typedef typename real_value_traits::node_traits::node node; + typedef typename detail::add_const_if_c + ::type vtype; + typedef typename detail::add_const_if_c + ::type ntype; + typedef typename boost::pointer_to_other + ::type npointer; + + node_to_value(const Container *cont) + : Base(cont) + {} + + typedef vtype & result_type; + typedef ntype & first_argument_type; + + const Container *get_container() const + { + if(store_container_ptr) + return static_cast(Base::get_ptr()); + else + return 0; + } + + const real_value_traits *get_real_value_traits() const + { + if(store_container_ptr) + return &this->get_container()->get_real_value_traits(); + else + return 0; + } + + result_type operator()(first_argument_type arg) const + { return *(this->get_real_value_traits()->to_value_ptr(npointer(&arg))); } +}; + +template +struct link_dispatch +{}; + +template +void destructor_impl(Hook &hook, detail::link_dispatch) +{ //If this assertion raises, you might have destroyed an object + //while it was still inserted in a container that is alive. + //If so, remove the object from the container before destroying it. + (void)hook; BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT(!hook.is_linked()); +} + +template +void destructor_impl(Hook &hook, detail::link_dispatch) +{ hook.unlink(); } + +template +void destructor_impl(Hook &, detail::link_dispatch) +{} + +template +struct base_hook_traits +{ + public: + typedef detail::node_holder + node_holder; + typedef NodeTraits node_traits; + typedef T value_type; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef typename boost::pointer_to_other::type pointer; + typedef typename boost::pointer_to_other::type const_pointer; + typedef typename std::iterator_traits::reference reference; + typedef typename std::iterator_traits::reference const_reference; + static const link_mode_type link_mode = LinkMode; + + static node_ptr to_node_ptr(reference value) + { return static_cast(&value); } + + static const_node_ptr to_node_ptr(const_reference value) + { return static_cast(&value); } + + static pointer to_value_ptr(node_ptr n) + { return static_cast(static_cast(&*n)); } + + static const_pointer to_value_ptr(const_node_ptr n) + { return static_cast(static_cast(&*n)); } +}; + +template +struct member_hook_traits +{ + public: + typedef Hook hook_type; + typedef typename hook_type::boost_intrusive_tags::node_traits node_traits; + typedef typename node_traits::node node; + typedef T value_type; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef typename boost::pointer_to_other::type pointer; + typedef typename boost::pointer_to_other::type const_pointer; + typedef typename std::iterator_traits::reference reference; + typedef typename std::iterator_traits::reference const_reference; + static const link_mode_type link_mode = Hook::boost_intrusive_tags::link_mode; + + static node_ptr to_node_ptr(reference value) + { + return reinterpret_cast(&(value.*P)); + } + + static const_node_ptr to_node_ptr(const_reference value) + { + return static_cast(&(value.*P)); + } + + static pointer to_value_ptr(node_ptr n) + { + return detail::parent_from_member + (static_cast(detail::get_pointer(n)), P); + } + + static const_pointer to_value_ptr(const_node_ptr n) + { + return detail::parent_from_member + (static_cast(detail::get_pointer(n)), P); + } +}; + +//This function uses binary search to discover the +//highest set bit of the integer +inline std::size_t floor_log2 (std::size_t x) +{ + const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT; + const bool Size_t_Bits_Power_2= !(Bits & (Bits-1)); + BOOST_STATIC_ASSERT(Size_t_Bits_Power_2); + + std::size_t n = x; + std::size_t log2 = 0; + + for(std::size_t shift = Bits >> 1; shift; shift >>= 1){ + std::size_t tmp = n >> shift; + if (tmp) + log2 += shift, n = tmp; + } + + return log2; +} + +inline float fast_log2 (float val) +{ + boost::uint32_t * exp_ptr = + static_cast(static_cast(&val)); + boost::uint32_t x = *exp_ptr; + const int log_2 = (int)(((x >> 23) & 255) - 128); + x &= ~(255 << 23); + x += 127 << 23; + *exp_ptr = x; + + val = ((-1.0f/3) * val + 2) * val - 2.0f/3; + + return (val + log_2); +} + +inline std::size_t ceil_log2 (std::size_t x) +{ + return ((x & (x-1))!= 0) + floor_log2(x); +} + +template +struct numbits_eq +{ + static const bool value = sizeof(SizeType)*CHAR_BIT == N; +}; + +template +struct sqrt2_pow_max; + +template +struct sqrt2_pow_max >::type> +{ + static const boost::uint32_t value = 0xb504f334; + static const std::size_t pow = 31; +}; + +template +struct sqrt2_pow_max >::type> +{ + static const boost::uint64_t value = 0xb504f333f9de6484ull; + static const std::size_t pow = 63; +}; + +// Returns floor(pow(sqrt(2), x * 2 + 1)). +// Defined for X from 0 up to the number of bits in size_t minus 1. +inline std::size_t sqrt2_pow_2xplus1 (std::size_t x) +{ + const std::size_t value = (std::size_t)sqrt2_pow_max::value; + const std::size_t pow = (std::size_t)sqrt2_pow_max::pow; + return (value >> (pow - x)) + 1; +} + +template +class exception_disposer +{ + Container *cont_; + Disposer &disp_; + + exception_disposer(const exception_disposer&); + exception_disposer &operator=(const exception_disposer&); + + public: + exception_disposer(Container &cont, Disposer &disp) + : cont_(&cont), disp_(disp) + {} + + void release() + { cont_ = 0; } + + ~exception_disposer() + { + if(cont_){ + cont_->clear_and_dispose(disp_); + } + } +}; + +template +class exception_array_disposer +{ + Container *cont_; + Disposer &disp_; + typename Container::size_type &constructed_; + + exception_array_disposer(const exception_array_disposer&); + exception_array_disposer &operator=(const exception_array_disposer&); + + public: + typedef typename Container::size_type size_type; + exception_array_disposer + (Container &cont, Disposer &disp, size_type &constructed) + : cont_(&cont), disp_(disp), constructed_(constructed) + {} + + void release() + { cont_ = 0; } + + ~exception_array_disposer() + { + size_type n = constructed_; + if(cont_){ + while(n--){ + cont_[n].clear_and_dispose(disp_); + } + } + } +}; + +} //namespace detail +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_DETAIL_UTILITIES_HPP diff --git a/win32/include/boost/intrusive/hashtable.hpp b/win32/include/boost/intrusive/hashtable.hpp new file mode 100755 index 000000000..2d3a2d0c7 --- /dev/null +++ b/win32/include/boost/intrusive/hashtable.hpp @@ -0,0 +1,2678 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_HASHTABLE_HPP +#define BOOST_INTRUSIVE_HASHTABLE_HPP + +#include +//std C++ +#include //std::equal_to +#include //std::pair +#include //std::swap, std::lower_bound, std::upper_bound +#include //std::size_t +#include //std::iterator_traits +//boost +#include +#include +#include +//General intrusive utilities +#include +#include +#include +#include +#include +#include +//Implementation utilities +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond + +namespace detail { + +template +struct hash_reduced_slist_node_traits +{ + template static detail::one test(...); + template static detail::two test(typename U::reduced_slist_node_traits* = 0); + static const bool value = sizeof(test(0)) == sizeof(detail::two); +}; + +template +struct apply_reduced_slist_node_traits +{ + typedef typename NodeTraits::reduced_slist_node_traits type; +}; + +template +struct reduced_slist_node_traits +{ + typedef typename detail::eval_if_c + < hash_reduced_slist_node_traits::value + , apply_reduced_slist_node_traits + , detail::identity + >::type type; +}; + +template +struct get_slist_impl +{ + typedef trivial_value_traits trivial_traits; + + //Reducing symbol length + struct type : make_slist + < typename NodeTraits::node + , boost::intrusive::value_traits + , boost::intrusive::constant_time_size + , boost::intrusive::size_type + >::type + {}; +}; + +template +struct real_from_supposed_value_traits +{ + typedef typename detail::eval_if_c + < detail::external_value_traits_is_true + ::value + , detail::eval_value_traits + + , detail::identity + + >::type type; +}; + +template +struct get_slist_impl_from_supposed_value_traits +{ + typedef typename + real_from_supposed_value_traits + < SupposedValueTraits>::type real_value_traits; + typedef typename detail::get_node_traits + ::type node_traits; + typedef typename get_slist_impl + ::type + >::type type; +}; + + +template +struct unordered_bucket_impl +{ + /// @cond + typedef typename + get_slist_impl_from_supposed_value_traits + ::type slist_impl; + typedef detail::bucket_impl implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +template +struct unordered_bucket_ptr_impl +{ + /// @cond + typedef typename detail::get_node_traits + ::type::node_ptr node_ptr; + typedef typename unordered_bucket_impl + ::type bucket_type; + typedef typename boost::pointer_to_other + ::type implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +template +struct store_hash_bool +{ + template + struct two_or_three {one _[2 + Add];}; + template static one test(...); + template static two_or_three + test (detail::bool_* = 0); + static const std::size_t value = sizeof(test(0)); +}; + +template +struct store_hash_is_true +{ + static const bool value = store_hash_bool::value > sizeof(one)*2; +}; + +template +struct optimize_multikey_bool +{ + template + struct two_or_three {one _[2 + Add];}; + template static one test(...); + template static two_or_three + test (detail::bool_* = 0); + static const std::size_t value = sizeof(test(0)); +}; + +template +struct optimize_multikey_is_true +{ + static const bool value = optimize_multikey_bool::value > sizeof(one)*2; +}; + +template +struct bucket_plus_size + : public detail::size_holder + < Config::constant_time_size + , typename Config::size_type> +{ + typedef detail::size_holder + < Config::constant_time_size + , typename Config::size_type> size_traits; + typedef typename Config::bucket_traits bucket_traits; + + bucket_plus_size(const bucket_traits &b_traits) + : bucket_traits_(b_traits) + {} + bucket_traits bucket_traits_; +}; + +template +struct bucket_hash_t : public detail::ebo_functor_holder +{ + typedef typename Config::hash hasher; + typedef detail::size_holder + < Config::constant_time_size + , typename Config::size_type> size_traits; + typedef typename Config::bucket_traits bucket_traits; + + bucket_hash_t(const bucket_traits &b_traits, const hasher & h) + : detail::ebo_functor_holder(h), bucket_plus_size_(b_traits) + {} + + bucket_plus_size bucket_plus_size_; +}; + +template +struct bucket_hash_equal_t : public detail::ebo_functor_holder +{ + typedef typename Config::equal equal; + typedef typename Config::hash hasher; + typedef typename Config::bucket_traits bucket_traits; + + bucket_hash_equal_t(const bucket_traits &b_traits, const hasher & h, const equal &e) + : detail::ebo_functor_holder(e), bucket_hash(b_traits, h) + {} + bucket_hash_t bucket_hash; +}; + +template //cache_begin == true version +struct bucket_hash_equal_t + : public detail::ebo_functor_holder +{ + typedef typename Config::equal equal; + typedef typename Config::hash hasher; + typedef typename Config::bucket_traits bucket_traits; + typedef typename unordered_bucket_ptr_impl + ::type bucket_ptr; + + bucket_hash_equal_t(const bucket_traits &b_traits, const hasher & h, const equal &e) + : detail::ebo_functor_holder(e), bucket_hash(b_traits, h) + {} + bucket_hash_t bucket_hash; + bucket_ptr cached_begin_; +}; + +template +struct hashtable_data_t : public Config::value_traits +{ + typedef typename Config::value_traits value_traits; + typedef typename Config::equal equal; + typedef typename Config::hash hasher; + typedef typename Config::bucket_traits bucket_traits; + + hashtable_data_t( const bucket_traits &b_traits, const hasher & h + , const equal &e, const value_traits &val_traits) + : Config::value_traits(val_traits), bucket_hash_equal_(b_traits, h, e) + {} + bucket_hash_equal_t bucket_hash_equal_; +}; + +struct insert_commit_data_impl +{ + std::size_t hash; +}; + +template +struct internal_default_uset_hook +{ + template static detail::one test(...); + template static detail::two test(typename U::default_uset_hook* = 0); + static const bool value = sizeof(test(0)) == sizeof(detail::two); +}; + +} //namespace detail { + +//!This metafunction will obtain the type of a bucket +//!from the value_traits or hook option to be used with +//!a hash container. +template +struct unordered_bucket + : public detail::unordered_bucket_impl + ::value_traits + > +{}; + +//!This metafunction will obtain the type of a bucket pointer +//!from the value_traits or hook option to be used with +//!a hash container. +template +struct unordered_bucket_ptr + : public detail::unordered_bucket_ptr_impl + ::value_traits + > +{}; + +//!This metafunction will obtain the type of the default bucket traits +//!(when the user does not specify the bucket_traits<> option) from the +//!value_traits or hook option to be used with +//!a hash container. +template +struct unordered_default_bucket_traits +{ + /// @cond + typedef typename ValueTraitsOrHookOption:: + template pack::value_traits supposed_value_traits; + typedef typename detail:: + get_slist_impl_from_supposed_value_traits + ::type slist_impl; + typedef detail::bucket_traits_impl + implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +template +struct get_default_uset_hook +{ + typedef typename T::default_uset_hook type; +}; + +template < class ValueTraits + , bool UniqueKeys + , class Hash + , class Equal + , class SizeType + , bool ConstantTimeSize + , class BucketTraits + , bool Power2Buckets + , bool CacheBegin + , bool CompareHash + > +struct usetopt +{ + typedef ValueTraits value_traits; + typedef Hash hash; + typedef Equal equal; + typedef SizeType size_type; + typedef BucketTraits bucket_traits; + static const bool constant_time_size = ConstantTimeSize; + static const bool power_2_buckets = Power2Buckets; + static const bool unique_keys = UniqueKeys; + static const bool cache_begin = CacheBegin; + static const bool compare_hash = CompareHash; +}; + +struct default_bucket_traits; + +template +struct uset_defaults + : pack_options + < none + , base_hook + < typename detail::eval_if_c + < detail::internal_default_uset_hook::value + , get_default_uset_hook + , detail::identity + >::type + > + , constant_time_size + , size_type + , equal > + , hash > + , bucket_traits + , power_2_buckets + , cache_begin + , compare_hash + >::type +{}; + +/// @endcond + +//! The class template hashtable is an intrusive hash table container, that +//! is used to construct intrusive unordered_set and unordered_multiset containers. The +//! no-throw guarantee holds only, if the Equal object and Hasher don't throw. +//! +//! hashtable is a semi-intrusive container: each object to be stored in the +//! container must contain a proper hook, but the container also needs +//! additional auxiliary memory to work: hashtable needs a pointer to an array +//! of type `bucket_type` to be passed in the constructor. This bucket array must +//! have at least the same lifetime as the container. This makes the use of +//! hashtable more complicated than purely intrusive containers. +//! `bucket_type` is default-constructible, copyable and assignable +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<> +//! \c bucket_traits<>, power_2_buckets<> and cache_begin<>. +//! +//! hashtable only provides forward iterators but it provides 4 iterator types: +//! iterator and const_iterator to navigate through the whole container and +//! local_iterator and const_local_iterator to navigate through the values +//! stored in a single bucket. Local iterators are faster and smaller. +//! +//! It's not recommended to use non constant-time size hashtables because several +//! key functions, like "empty()", become non-constant time functions. Non +//! constant_time size hashtables are mainly provided to support auto-unlink hooks. +//! +//! hashtables, does not make automatic rehashings nor +//! offers functions related to a load factor. Rehashing can be explicitly requested +//! and the user must provide a new bucket array that will be used from that moment. +//! +//! Since no automatic rehashing is done, iterators are never invalidated when +//! inserting or erasing elements. Iterators are only invalidated when rehashing. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class hashtable_impl + : private detail::hashtable_data_t +{ + public: + typedef typename Config::value_traits value_traits; + + /// @cond + static const bool external_value_traits = + detail::external_value_traits_is_true::value; + typedef typename detail::eval_if_c + < external_value_traits + , detail::eval_value_traits + , detail::identity + >::type real_value_traits; + typedef typename Config::bucket_traits bucket_traits; + static const bool external_bucket_traits = + detail::external_bucket_traits_is_true::value; + typedef typename detail::eval_if_c + < external_bucket_traits + , detail::eval_bucket_traits + , detail::identity + >::type real_bucket_traits; + typedef typename detail::get_slist_impl + ::type + >::type slist_impl; + /// @endcond + + typedef typename real_value_traits::pointer pointer; + typedef typename real_value_traits::const_pointer const_pointer; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::reference reference; + typedef typename std::iterator_traits::reference const_reference; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename Config::size_type size_type; + typedef value_type key_type; + typedef typename Config::equal key_equal; + typedef typename Config::hash hasher; + typedef detail::bucket_impl bucket_type; + typedef typename boost::pointer_to_other + ::type bucket_ptr; + typedef typename slist_impl::iterator siterator; + typedef typename slist_impl::const_iterator const_siterator; + typedef detail::hashtable_iterator iterator; + typedef detail::hashtable_iterator const_iterator; + typedef typename real_value_traits::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + typedef typename slist_impl::node_algorithms node_algorithms; + + static const bool constant_time_size = Config::constant_time_size; + static const bool stateful_value_traits = detail::store_cont_ptr_on_it::value; + static const bool store_hash = detail::store_hash_is_true::value; + static const bool unique_keys = Config::unique_keys; + static const bool optimize_multikey + = detail::optimize_multikey_is_true::value && !unique_keys; + static const bool power_2_buckets = Config::power_2_buckets; + static const bool cache_begin = Config::cache_begin; + static const bool compare_hash = Config::compare_hash; + + /// @cond + private: + //Configuration error: compare_hash<> can't be specified without store_hash<> + //See documentation for more explanations + BOOST_STATIC_ASSERT((!compare_hash || store_hash)); + + typedef typename slist_impl::node_ptr slist_node_ptr; + typedef typename boost::pointer_to_other + ::type void_pointer; + //We'll define group traits, but these won't be instantiated if + //optimize_multikey is not true + typedef unordered_group_adapter group_traits; + typedef circular_slist_algorithms group_algorithms; + typedef detail::bool_ store_hash_t; + typedef detail::bool_ optimize_multikey_t; + typedef detail::bool_ cache_begin_t; + typedef detail::bool_ power_2_buckets_t; + typedef detail::size_holder size_traits; + typedef detail::hashtable_data_t base_type; + + template + struct downcast_node_to_value + : public detail::node_to_value + { + typedef detail::node_to_value base_t; + typedef typename base_t::result_type result_type; + typedef typename detail::add_const_if_c + ::type &first_argument_type; + typedef typename detail::add_const_if_c + ::type &intermediate_argument_type; + + downcast_node_to_value(const hashtable_impl *cont) + : base_t(cont) + {} + + result_type operator()(first_argument_type arg) const + { return this->base_t::operator()(static_cast(arg)); } + }; + + template + struct node_cast_adaptor + : private detail::ebo_functor_holder + { + typedef detail::ebo_functor_holder base_t; + + template + node_cast_adaptor(const ConvertibleToF &c2f, const hashtable_impl *cont) + : base_t(base_t(c2f, cont)) + {} + + typename base_t::node_ptr operator()(const typename slist_impl::node &to_clone) + { return base_t::operator()(static_cast(to_clone)); } + + void operator()(typename slist_impl::node_ptr to_clone) + { base_t::operator()(node_ptr(&static_cast(*to_clone))); } + }; + + private: + //noncopyable + hashtable_impl (const hashtable_impl&); + hashtable_impl operator =(const hashtable_impl&); + + enum { safemode_or_autounlink = + (int)real_value_traits::link_mode == (int)auto_unlink || + (int)real_value_traits::link_mode == (int)safe_link }; + + //Constant-time size is incompatible with auto-unlink hooks! + BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); + + template + node_cast_adaptor > + make_node_disposer(const Disposer &disposer) const + { return node_cast_adaptor >(disposer, this); } + + /// @endcond + + public: + typedef detail::insert_commit_data_impl insert_commit_data; + + typedef detail::transform_iterator + < typename slist_impl::iterator + , downcast_node_to_value > local_iterator; + + typedef detail::transform_iterator + < typename slist_impl::iterator + , downcast_node_to_value > const_local_iterator; + + /// @cond + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return *this; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return base_type::get_value_traits(*this); } + + real_value_traits &get_real_value_traits(detail::bool_) + { return *this; } + + real_value_traits &get_real_value_traits(detail::bool_) + { return base_type::get_value_traits(*this); } + + /// @endcond + + public: + + const real_value_traits &get_real_value_traits() const + { return this->get_real_value_traits(detail::bool_()); } + + real_value_traits &get_real_value_traits() + { return this->get_real_value_traits(detail::bool_()); } + + //! Requires: buckets must not be being used by any other resource. + //! + //! Effects: Constructs an empty unordered_set, storing a reference + //! to the bucket array and copies of the key_hasher and equal_func functors. + //! + //! Complexity: Constant. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor or invocation of hash_func or equal_func throws. + //! + //! Notes: buckets array must be disposed only after + //! *this is disposed. + hashtable_impl ( const bucket_traits &b_traits + , const hasher & hash_func = hasher() + , const key_equal &equal_func = key_equal() + , const value_traits &v_traits = value_traits()) + : base_type(b_traits, hash_func, equal_func, v_traits) + { + priv_initialize_buckets(); + this->priv_size_traits().set_size(size_type(0)); + BOOST_INTRUSIVE_INVARIANT_ASSERT(this->priv_buckets_len() != 0); + //Check power of two bucket array if the option is activated + BOOST_INTRUSIVE_INVARIANT_ASSERT + (!power_2_buckets || (0 == (this->priv_buckets_len() & (this->priv_buckets_len()-1)))); + } + + //! Effects: Detaches all elements from this. The objects in the unordered_set + //! are not deleted (i.e. no destructors are called). + //! + //! Complexity: Linear to the number of elements in the unordered_set, if + //! it's a safe-mode or auto-unlink value. Otherwise constant. + //! + //! Throws: Nothing. + ~hashtable_impl() + { this->clear(); } + + //! Effects: Returns an iterator pointing to the beginning of the unordered_set. + //! + //! Complexity: Amortized constant time. + //! Worst case (empty unordered_set): O(this->bucket_count()) + //! + //! Throws: Nothing. + iterator begin() + { + size_type bucket_num; + return iterator(this->priv_begin(bucket_num), this); + } + + //! Effects: Returns a const_iterator pointing to the beginning + //! of the unordered_set. + //! + //! Complexity: Amortized constant time. + //! Worst case (empty unordered_set): O(this->bucket_count()) + //! + //! Throws: Nothing. + const_iterator begin() const + { return this->cbegin(); } + + //! Effects: Returns a const_iterator pointing to the beginning + //! of the unordered_set. + //! + //! Complexity: Amortized constant time. + //! Worst case (empty unordered_set): O(this->bucket_count()) + //! + //! Throws: Nothing. + const_iterator cbegin() const + { + size_type bucket_num; + return const_iterator(this->priv_begin(bucket_num), this); + } + + //! Effects: Returns an iterator pointing to the end of the unordered_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return iterator(priv_invalid_local_it(), 0); } + + //! Effects: Returns a const_iterator pointing to the end of the unordered_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return this->cend(); } + + //! Effects: Returns a const_iterator pointing to the end of the unordered_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return const_iterator(priv_invalid_local_it(), 0); } + + //! Effects: Returns the hasher object used by the unordered_set. + //! + //! Complexity: Constant. + //! + //! Throws: If hasher copy-constructor throws. + hasher hash_function() const + { return this->priv_hasher(); } + + //! Effects: Returns the key_equal object used by the unordered_set. + //! + //! Complexity: Constant. + //! + //! Throws: If key_equal copy-constructor throws. + key_equal key_eq() const + { return this->priv_equal(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: if constant-time size and cache_last options are disabled, + //! average constant time (worst case, with empty() == true: O(this->bucket_count()). + //! Otherwise constant. + //! + //! Throws: Nothing. + bool empty() const + { + if(constant_time_size){ + return !this->size(); + } + else if(cache_begin){ + return this->begin() == this->end(); + } + else{ + size_type buckets_len = this->priv_buckets_len(); + const bucket_type *b = detail::get_pointer(this->priv_buckets()); + for (size_type n = 0; n < buckets_len; ++n, ++b){ + if(!b->empty()){ + return false; + } + } + return true; + } + } + + //! Effects: Returns the number of elements stored in the unordered_set. + //! + //! Complexity: Linear to elements contained in *this if + //! constant_time_size is false. Constant-time otherwise. + //! + //! Throws: Nothing. + size_type size() const + { + if(constant_time_size) + return this->priv_size_traits().get_size(); + else{ + size_type len = 0; + size_type buckets_len = this->priv_buckets_len(); + const bucket_type *b = detail::get_pointer(this->priv_buckets()); + for (size_type n = 0; n < buckets_len; ++n, ++b){ + len += b->size(); + } + return len; + } + } + + //! Requires: the hasher and the equality function unqualified swap + //! call should not throw. + //! + //! Effects: Swaps the contents of two unordered_sets. + //! Swaps also the contained bucket array and equality and hasher functors. + //! + //! Complexity: Constant. + //! + //! Throws: If the swap() call for the comparison or hash functors + //! found using ADL throw. Basic guarantee. + void swap(hashtable_impl& other) + { + using std::swap; + //These can throw + swap(this->priv_equal(), other.priv_equal()); + swap(this->priv_hasher(), other.priv_hasher()); + //These can't throw + swap(this->priv_real_bucket_traits(), other.priv_real_bucket_traits()); + priv_swap_cache(cache_begin_t(), other); + if(constant_time_size){ + size_type backup = this->priv_size_traits().get_size(); + this->priv_size_traits().set_size(other.priv_size_traits().get_size()); + other.priv_size_traits().set_size(backup); + } + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. Basic guarantee. + template + void clone_from(const hashtable_impl &src, Cloner cloner, Disposer disposer) + { + this->clear_and_dispose(disposer); + if(!constant_time_size || !src.empty()){ + const size_type src_bucket_count = src.bucket_count(); + const size_type dst_bucket_count = this->bucket_count(); + //Check power of two bucket array if the option is activated + BOOST_INTRUSIVE_INVARIANT_ASSERT + (!power_2_buckets || (0 == (src_bucket_count & (src_bucket_count-1)))); + BOOST_INTRUSIVE_INVARIANT_ASSERT + (!power_2_buckets || (0 == (dst_bucket_count & (dst_bucket_count-1)))); + + //If src bucket count is bigger or equal, structural copy is possible + if(src_bucket_count >= dst_bucket_count){ + //First clone the first ones + const bucket_ptr src_buckets = src.priv_buckets(); + const bucket_ptr dst_buckets = this->priv_buckets(); + size_type constructed; + typedef node_cast_adaptor > NodeDisposer; + typedef node_cast_adaptor > NodeCloner; + NodeDisposer node_disp(disposer, this); + + detail::exception_array_disposer + rollback(dst_buckets[0], node_disp, constructed); + for( constructed = 0 + ; constructed < dst_bucket_count + ; ++constructed){ + dst_buckets[constructed].clone_from + ( src_buckets[constructed] + , NodeCloner(cloner, this), node_disp); + } + if(src_bucket_count != dst_bucket_count){ + //Now insert the remaining ones using the modulo trick + for(//"constructed" comes from the previous loop + ; constructed < src_bucket_count + ; ++constructed){ + bucket_type &dst_b = + dst_buckets[priv_hash_to_bucket(constructed, dst_bucket_count)]; + bucket_type &src_b = src_buckets[constructed]; + for( siterator b(src_b.begin()), e(src_b.end()) + ; b != e + ; ++b){ + dst_b.push_front(*(NodeCloner(cloner, this)(*b.pointed_node()))); + } + } + } + rollback.release(); + this->priv_size_traits().set_size(src.priv_size_traits().get_size()); + priv_insertion_update_cache(0u); + priv_erasure_update_cache(); + } + else{ + //Unlike previous cloning algorithm, this can throw + //if cloner, the hasher or comparison functor throw + const_iterator b(src.begin()), e(src.end()); + detail::exception_disposer + rollback(*this, disposer); + for(; b != e; ++b){ + this->insert_equal(*cloner(*b)); + } + rollback.release(); + } + } + } + + iterator insert_equal(reference value) + { + size_type bucket_num; + std::size_t hash_value; + siterator prev; + siterator it = this->priv_find + (value, this->priv_hasher(), this->priv_equal(), bucket_num, hash_value, prev); + bucket_type &b = this->priv_buckets()[bucket_num]; + bool found_equal = it != priv_invalid_local_it(); + node_ptr n = node_ptr(&priv_value_to_node(value)); + this->priv_store_hash(n, hash_value, store_hash_t()); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n)); + if(!found_equal){ + it = b.before_begin(); + } + if(optimize_multikey){ + node_ptr first_in_group = found_equal ? + dcast_bucket_ptr(it.pointed_node()) : node_ptr(0); + this->priv_insert_in_group(first_in_group, n, optimize_multikey_t()); + } + priv_insertion_update_cache(bucket_num); + this->priv_size_traits().increment(); + return iterator(b.insert_after(it, *n), this); + } + + template + void insert_equal(Iterator b, Iterator e) + { + for (; b != e; ++b) + this->insert_equal(*b); + } + + //! Requires: value must be an lvalue + //! + //! Effects: Tries to inserts value into the unordered_set. + //! + //! Returns: If the value + //! is not already present inserts it and returns a pair containing the + //! iterator to the new value and true. If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + std::pair insert_unique(reference value) + { + insert_commit_data commit_data; + std::pair ret = this->insert_unique_check + (value, this->priv_hasher(), this->priv_equal(), commit_data); + if(!ret.second) + return ret; + return std::pair + (this->insert_unique_commit(value, commit_data), true); + } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Equivalent to this->insert(t) for each element in [b, e). + //! + //! Complexity: Average case O(N), where N is std::distance(b, e). + //! Worst case O(N*this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert_unique(Iterator b, Iterator e) + { + for (; b != e; ++b) + this->insert_unique(*b); + } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "equal_func" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "equal_func" compares an arbitrary key with the contained values. + //! + //! Effects: Checks if a value can be inserted in the unordered_set, using + //! a user provided key instead of the value itself. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. If the value can be inserted returns true in the returned + //! pair boolean and fills "commit_data" that is meant to be used with + //! the "insert_commit" function. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If hash_func or equal_func throw. Strong guarantee. + //! + //! Notes: This function is used to improve performance when constructing + //! a value_type is expensive: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the hash or the equality is much cheaper to + //! construct than the value_type and this function offers the possibility to + //! use that the part to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the value_type and use + //! "insert_commit" to insert the object in constant-time. + //! + //! "commit_data" remains valid for a subsequent "insert_commit" only if no more + //! objects are inserted or erased from the unordered_set. + //! + //! After a successful rehashing insert_commit_data remains valid. + template + std::pair insert_unique_check + ( const KeyType &key + , KeyHasher hash_func + , KeyValueEqual equal_func + , insert_commit_data &commit_data) + { + size_type bucket_num; + siterator prev; + siterator prev_pos = + this->priv_find(key, hash_func, equal_func, bucket_num, commit_data.hash, prev); + bool success = prev_pos == priv_invalid_local_it(); + if(success){ + prev_pos = this->priv_buckets()[bucket_num].before_begin(); + } + return std::pair(iterator(prev_pos, this),success); + } + + //! Requires: value must be an lvalue of type value_type. commit_data + //! must have been obtained from a previous call to "insert_check". + //! No objects should have been inserted or erased from the unordered_set between + //! the "insert_check" that filled "commit_data" and the call to "insert_commit". + //! + //! Effects: Inserts the value in the unordered_set using the information obtained + //! from the "commit_data" that a previous "insert_check" filled. + //! + //! Returns: An iterator to the newly inserted object. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function has only sense if a "insert_check" has been + //! previously executed to fill "commit_data". No value should be inserted or + //! erased between the "insert_check" and "insert_commit" calls. + //! + //! After a successful rehashing insert_commit_data remains valid. + iterator insert_unique_commit(reference value, const insert_commit_data &commit_data) + { + size_type bucket_num = priv_hash_to_bucket(commit_data.hash); + bucket_type &b = this->priv_buckets()[bucket_num]; + this->priv_size_traits().increment(); + node_ptr n = node_ptr(&priv_value_to_node(value)); + this->priv_store_hash(n, commit_data.hash, store_hash_t()); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(n)); + priv_insertion_update_cache(bucket_num); + this->priv_insert_in_group(node_ptr(0), n, optimize_multikey_t()); + return iterator(b.insert_after(b.before_begin(), *n), this); + } + + //! Effects: Erases the element pointed to by i. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased element. No destructors are called. + void erase(const_iterator i) + { this->erase_and_dispose(i, detail::null_disposer()); } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Complexity: Average case O(std::distance(b, e)), + //! worst case O(this->size()). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void erase(const_iterator b, const_iterator e) + { this->erase_and_dispose(b, e, detail::null_disposer()); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Average case O(this->count(value)). + //! Worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + //! Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return this->erase(value, this->priv_hasher(), this->priv_equal()); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "equal_func" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "equal_func" compares an arbitrary key with the contained values. + //! + //! Effects: Erases all the elements that have the same hash and + //! compare equal with the given key. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Average case O(this->count(value)). + //! Worst case O(this->size()). + //! + //! Throws: If hash_func or equal_func throw. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) + { return this->erase_and_dispose(key, hash_func, equal_func, detail::null_disposer()); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element pointed to by i. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + void erase_and_dispose(const_iterator i, Disposer disposer) + { + priv_erase(i, disposer, optimize_multikey_t()); + this->priv_size_traits().decrement(); + priv_erasure_update_cache(); + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average case O(std::distance(b, e)), + //! worst case O(this->size()). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) + { + if(b == e) return; + + //Get the bucket number and local iterator for both iterators + siterator first_local_it(b.slist_it()); + size_type first_bucket_num = this->priv_get_bucket_num(first_local_it); + + siterator before_first_local_it + = priv_get_previous(priv_buckets()[first_bucket_num], first_local_it); + size_type last_bucket_num; + siterator last_local_it; + + //For the end iterator, we will assign the end iterator + //of the last bucket + if(e == this->end()){ + last_bucket_num = this->bucket_count() - 1; + last_local_it = priv_buckets()[last_bucket_num].end(); + } + else{ + last_local_it = e.slist_it(); + last_bucket_num = this->priv_get_bucket_num(last_local_it); + } + priv_erase_range(before_first_local_it, first_bucket_num, last_local_it, last_bucket_num, disposer); + priv_erasure_update_cache(first_bucket_num, last_bucket_num); + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Average case O(this->count(value)). + //! Worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + //! Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { return this->erase_and_dispose(value, priv_hasher(), priv_equal(), disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "equal_func". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Average case O(this->count(value)). + //! Worst case O(this->size()). + //! + //! Throws: If hash_func or equal_func throw. Basic guarantee. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func + ,KeyValueEqual equal_func, Disposer disposer) + { + size_type bucket_num; + std::size_t h; + siterator prev; + siterator it = + this->priv_find(key, hash_func, equal_func, bucket_num, h, prev); + bool success = it != priv_invalid_local_it(); + size_type count(0); + if(!success){ + return 0; + } + else if(optimize_multikey){ + siterator last = bucket_type::s_iterator_to + (*node_traits::get_next(priv_get_last_in_group + (dcast_bucket_ptr(it.pointed_node())))); + this->priv_erase_range_impl(bucket_num, prev, last, disposer, count); + } + else{ + //If found erase all equal values + bucket_type &b = this->priv_buckets()[bucket_num]; + for(siterator end = b.end(); it != end; ++count, ++it){ + slist_node_ptr n(it.pointed_node()); + const value_type &v = priv_value_from_slist_node(n); + if(compare_hash){ + std::size_t vh = this->priv_stored_hash(v, store_hash_t()); + if(h != vh || !equal_func(key, v)){ + break; + } + } + else if(!equal_func(key, v)){ + break; + } + this->priv_size_traits().decrement(); + } + b.erase_after_and_dispose(prev, it, make_node_disposer(disposer)); + } + priv_erasure_update_cache(); + return count; + } + + //! Effects: Erases all of the elements. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { + priv_clear_buckets(); + this->priv_size_traits().set_size(size_type(0)); + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all of the elements. + //! + //! Complexity: Linear to the number of elements on the container. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + void clear_and_dispose(Disposer disposer) + { + if(!constant_time_size || !this->empty()){ + size_type num_buckets = this->bucket_count(); + bucket_ptr b = this->priv_buckets(); + for(; num_buckets--; ++b){ + b->clear_and_dispose(make_node_disposer(disposer)); + } + this->priv_size_traits().set_size(size_type(0)); + } + priv_initialize_cache(); + } + + //! Effects: Returns the number of contained elements with the given value + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + size_type count(const_reference value) const + { return this->count(value, this->priv_hasher(), this->priv_equal()); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "equal_func" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "equal_func" compares an arbitrary key with the contained values. + //! + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If hash_func or equal throw. + template + size_type count(const KeyType &key, const KeyHasher &hash_func, const KeyValueEqual &equal_func) const + { + size_type bucket_n1, bucket_n2, count; + this->priv_equal_range(key, hash_func, equal_func, bucket_n1, bucket_n2, count); + return count; + } + + //! Effects: Finds an iterator to the first element is equal to + //! "value" or end() if that element does not exist. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + iterator find(const_reference value) + { return this->find(value, this->priv_hasher(), this->priv_equal()); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "equal_func" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "equal_func" compares an arbitrary key with the contained values. + //! + //! Effects: Finds an iterator to the first element whose key is + //! "key" according to the given hash and equality functor or end() if + //! that element does not exist. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If hash_func or equal_func throw. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator find(const KeyType &key, KeyHasher hash_func, KeyValueEqual equal_func) + { + size_type bucket_n; + std::size_t hash; + siterator prev; + siterator local_it = this->priv_find(key, hash_func, equal_func, bucket_n, hash, prev); + return iterator(local_it, this); + } + + //! Effects: Finds a const_iterator to the first element whose key is + //! "key" or end() if that element does not exist. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + const_iterator find(const_reference value) const + { return this->find(value, this->priv_hasher(), this->priv_equal()); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "equal_func" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "equal_func" compares an arbitrary key with the contained values. + //! + //! Effects: Finds an iterator to the first element whose key is + //! "key" according to the given hasher and equality functor or end() if + //! that element does not exist. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If hash_func or equal_func throw. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator find + (const KeyType &key, KeyHasher hash_func, KeyValueEqual equal_func) const + { + size_type bucket_n; + std::size_t hash_value; + siterator prev; + siterator sit = this->priv_find(key, hash_func, equal_func, bucket_n, hash_value, prev); + return const_iterator(sit, this); + } + + //! Effects: Returns a range containing all elements with values equivalent + //! to value. Returns std::make_pair(this->end(), this->end()) if no such + //! elements exist. + //! + //! Complexity: Average case O(this->count(value)). Worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + std::pair equal_range(const_reference value) + { return this->equal_range(value, this->priv_hasher(), this->priv_equal()); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "equal_func" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "equal_func" compares an arbitrary key with the contained values. + //! + //! Effects: Returns a range containing all elements with equivalent + //! keys. Returns std::make_pair(this->end(), this->end()) if no such + //! elements exist. + //! + //! Complexity: Average case O(this->count(key, hash_func, equal_func)). + //! Worst case O(this->size()). + //! + //! Throws: If hash_func or the equal_func throw. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair equal_range + (const KeyType &key, KeyHasher hash_func, KeyValueEqual equal_func) + { + size_type bucket_n1, bucket_n2, count; + std::pair ret = this->priv_equal_range + (key, hash_func, equal_func, bucket_n1, bucket_n2, count); + return std::pair + (iterator(ret.first, this), iterator(ret.second, this)); + } + + //! Effects: Returns a range containing all elements with values equivalent + //! to value. Returns std::make_pair(this->end(), this->end()) if no such + //! elements exist. + //! + //! Complexity: Average case O(this->count(value)). Worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + std::pair + equal_range(const_reference value) const + { return this->equal_range(value, this->priv_hasher(), this->priv_equal()); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "equal_func" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "equal_func" compares an arbitrary key with the contained values. + //! + //! Effects: Returns a range containing all elements with equivalent + //! keys. Returns std::make_pair(this->end(), this->end()) if no such + //! elements exist. + //! + //! Complexity: Average case O(this->count(key, hash_func, equal_func)). + //! Worst case O(this->size()). + //! + //! Throws: If the hasher or equal_func throw. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair equal_range + (const KeyType &key, KeyHasher hash_func, KeyValueEqual equal_func) const + { + size_type bucket_n1, bucket_n2, count; + std::pair ret = + this->priv_equal_range(key, hash_func, equal_func, bucket_n1, bucket_n2, count); + return std::pair + (const_iterator(ret.first, this), const_iterator(ret.second, this)); + } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator belonging to the unordered_set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: If the internal hash function throws. + iterator iterator_to(reference value) + { + return iterator(bucket_type::s_iterator_to(priv_value_to_node(value)), this); + } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator belonging to the + //! unordered_set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: If the internal hash function throws. + const_iterator iterator_to(const_reference value) const + { + return const_iterator(bucket_type::s_iterator_to(priv_value_to_node(const_cast(value))), this); + } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid local_iterator belonging to the unordered_set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static local_iterator s_local_iterator_to(reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + siterator sit = bucket_type::s_iterator_to(((hashtable_impl*)0)->priv_value_to_node(value)); + return local_iterator(sit, (hashtable_impl*)0); + } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_local_iterator belonging to + //! the unordered_set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_local_iterator s_local_iterator_to(const_reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + siterator sit = bucket_type::s_iterator_to(((hashtable_impl*)0)->priv_value_to_node(const_cast(value))); + return const_local_iterator(sit, (hashtable_impl*)0); + } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid local_iterator belonging to the unordered_set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + local_iterator local_iterator_to(reference value) + { + siterator sit = bucket_type::s_iterator_to(this->priv_value_to_node(value)); + return local_iterator(sit, this); + } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_local_iterator belonging to + //! the unordered_set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_local_iterator local_iterator_to(const_reference value) const + { + siterator sit = bucket_type::s_iterator_to + (const_cast(this->priv_value_to_node(value))); + return const_local_iterator(sit, this); + } + + //! Effects: Returns the number of buckets passed in the constructor + //! or the last rehash function. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + size_type bucket_count() const + { return this->priv_buckets_len(); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns the number of elements in the nth bucket. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + size_type bucket_size(size_type n) const + { return this->priv_buckets()[n].size(); } + + //! Effects: Returns the index of the bucket in which elements + //! with keys equivalent to k would be found, if any such element existed. + //! + //! Complexity: Constant. + //! + //! Throws: If the hash functor throws. + //! + //! Note: the return value is in the range [0, this->bucket_count()). + size_type bucket(const key_type& k) const + { return this->bucket(k, this->priv_hasher()); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! Effects: Returns the index of the bucket in which elements + //! with keys equivalent to k would be found, if any such element existed. + //! + //! Complexity: Constant. + //! + //! Throws: If hash_func throws. + //! + //! Note: the return value is in the range [0, this->bucket_count()). + template + size_type bucket(const KeyType& k, const KeyHasher &hash_func) const + { return priv_hash_to_bucket(hash_func(k)); } + + //! Effects: Returns the bucket array pointer passed in the constructor + //! or the last rehash function. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bucket_ptr bucket_pointer() const + { return this->priv_buckets(); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a local_iterator pointing to the beginning + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + local_iterator begin(size_type n) + { return local_iterator(this->priv_buckets()[n].begin(), this); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a const_local_iterator pointing to the beginning + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + const_local_iterator begin(size_type n) const + { return this->cbegin(n); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a const_local_iterator pointing to the beginning + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + const_local_iterator cbegin(size_type n) const + { + siterator sit = const_cast(this->priv_buckets()[n]).begin(); + return const_local_iterator(sit, this); + } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a local_iterator pointing to the end + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + local_iterator end(size_type n) + { return local_iterator(this->priv_buckets()[n].end(), this); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a const_local_iterator pointing to the end + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + const_local_iterator end(size_type n) const + { return this->cend(n); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a const_local_iterator pointing to the end + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + const_local_iterator cend(size_type n) const + { return const_local_iterator(const_cast(this->priv_buckets()[n]).end(), this); } + + //! Requires: new_buckets must be a pointer to a new bucket array + //! or the same as the old bucket array. new_size is the length of the + //! the array pointed by new_buckets. If new_buckets == this->bucket_pointer() + //! n can be bigger or smaller than this->bucket_count(). + //! + //! Effects: Updates the internal reference with the new bucket erases + //! the values from the old bucket and inserts then in the new one. + //! + //! Complexity: Average case linear in this->size(), worst case quadratic. + //! + //! Throws: If the hasher functor throws. Basic guarantee. + void rehash(const bucket_traits &new_bucket_traits) + { + bucket_ptr new_buckets = new_bucket_traits.bucket_begin(); + size_type new_buckets_len = new_bucket_traits.bucket_count(); + bucket_ptr old_buckets = this->priv_buckets(); + size_type old_buckets_len = this->priv_buckets_len(); + + //Check power of two bucket array if the option is activated + BOOST_INTRUSIVE_INVARIANT_ASSERT + (!power_2_buckets || (0 == (new_buckets_len & (new_buckets_len-1u)))); + + size_type n = priv_get_cache_bucket_num(); + const bool same_buffer = old_buckets == new_buckets; + //If the new bucket length is a common factor + //of the old one we can avoid hash calculations. + const bool fast_shrink = (old_buckets_len > new_buckets_len) && + (power_2_buckets ||(old_buckets_len % new_buckets_len) == 0); + //If we are shrinking the same bucket array and it's + //is a fast shrink, just rehash the last nodes + size_type new_first_bucket_num = new_buckets_len; + if(same_buffer && fast_shrink && (n < new_buckets_len)){ + n = new_buckets_len; + new_first_bucket_num = priv_get_cache_bucket_num(); + } + + //Anti-exception stuff: they destroy the elements if something goes wrong + typedef detail::init_disposer NodeDisposer; + NodeDisposer node_disp; + detail::exception_array_disposer + rollback1(new_buckets[0], node_disp, new_buckets_len); + detail::exception_array_disposer + rollback2(old_buckets[0], node_disp, old_buckets_len); + + //Put size in a safe value for rollback exception + size_type size_backup = this->priv_size_traits().get_size(); + this->priv_size_traits().set_size(0); + //Put cache to safe position + priv_initialize_cache(); + priv_insertion_update_cache(size_type(0u)); + + //Iterate through nodes + for(; n < old_buckets_len; ++n){ + bucket_type &old_bucket = old_buckets[n]; + + if(!fast_shrink){ + siterator before_i(old_bucket.before_begin()); + siterator end(old_bucket.end()); + siterator i(old_bucket.begin()); + for(;i != end; ++i){ + const value_type &v = priv_value_from_slist_node(i.pointed_node()); + const std::size_t hash_value = this->priv_stored_hash(v, store_hash_t()); + const size_type new_n = priv_hash_to_bucket(hash_value, new_buckets_len); + if(cache_begin && new_n < new_first_bucket_num) + new_first_bucket_num = new_n; + siterator last = bucket_type::s_iterator_to + (*priv_get_last_in_group(dcast_bucket_ptr(i.pointed_node()))); + if(same_buffer && new_n == n){ + before_i = last; + } + else{ + bucket_type &new_b = new_buckets[new_n]; + new_b.splice_after(new_b.before_begin(), old_bucket, before_i, last); + } + i = before_i; + } + } + else{ + const size_type new_n = priv_hash_to_bucket(n, new_buckets_len); + if(cache_begin && new_n < new_first_bucket_num) + new_first_bucket_num = new_n; + bucket_type &new_b = new_buckets[new_n]; + if(!old_bucket.empty()){ + new_b.splice_after( new_b.before_begin() + , old_bucket + , old_bucket.before_begin() + , priv_get_last(old_bucket)); + } + } + } + + this->priv_size_traits().set_size(size_backup); + this->priv_real_bucket_traits() = new_bucket_traits; + priv_initialize_cache(); + priv_insertion_update_cache(new_first_bucket_num); + //priv_erasure_update_cache(); + rollback1.release(); + rollback2.release(); + } + + //! Effects: Returns the nearest new bucket count optimized for + //! the container that is bigger than n. This suggestion can be used + //! to create bucket arrays with a size that will usually improve + //! container's performance. If such value does not exist, the + //! higher possible value is returned. + //! + //! Complexity: Amortized constant time. + //! + //! Throws: Nothing. + static size_type suggested_upper_bucket_count(size_type n) + { + const std::size_t *primes = &detail::prime_list_holder<0>::prime_list[0]; + const std::size_t *primes_end = primes + detail::prime_list_holder<0>::prime_list_size; + size_type const* bound = std::lower_bound(primes, primes_end, n); + if(bound == primes_end) + bound--; + return size_type(*bound); + } + + //! Effects: Returns the nearest new bucket count optimized for + //! the container that is smaller than n. This suggestion can be used + //! to create bucket arrays with a size that will usually improve + //! container's performance. If such value does not exist, the + //! lower possible value is returned. + //! + //! Complexity: Amortized constant time. + //! + //! Throws: Nothing. + static size_type suggested_lower_bucket_count(size_type n) + { + const std::size_t *primes = &detail::prime_list_holder<0>::prime_list[0]; + const std::size_t *primes_end = primes + detail::prime_list_holder<0>::prime_list_size; + size_type const* bound = std::upper_bound(primes, primes_end, n); + if(bound != primes_end) + bound--; + return size_type(*bound); + } + + /// @cond + private: + std::size_t priv_hash_to_bucket(std::size_t hash_value) const + { return priv_hash_to_bucket(hash_value, power_2_buckets_t()); } + + std::size_t priv_hash_to_bucket(std::size_t hash_value, detail::bool_) const + { return hash_value % this->priv_real_bucket_traits().bucket_count(); } + + std::size_t priv_hash_to_bucket(std::size_t hash_value, detail::bool_) const + { return hash_value & (this->priv_real_bucket_traits().bucket_count() - 1); } + + std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_len) const + { return priv_hash_to_bucket(hash_value, bucket_len, power_2_buckets_t()); } + + std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_len, detail::bool_) const + { return hash_value % bucket_len; } + + std::size_t priv_hash_to_bucket(std::size_t hash_value, std::size_t bucket_len, detail::bool_) const + { return hash_value & (bucket_len - 1); } + + const key_equal &priv_equal() const + { return static_cast(this->bucket_hash_equal_.get()); } + + key_equal &priv_equal() + { return static_cast(this->bucket_hash_equal_.get()); } + + value_type &priv_value_from_slist_node(slist_node_ptr n) + { return *this->get_real_value_traits().to_value_ptr(dcast_bucket_ptr(n)); } + + const value_type &priv_value_from_slist_node(slist_node_ptr n) const + { return *this->get_real_value_traits().to_value_ptr(dcast_bucket_ptr(n)); } + + const real_bucket_traits &priv_real_bucket_traits(detail::bool_) const + { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; } + + const real_bucket_traits &priv_real_bucket_traits(detail::bool_) const + { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); } + + real_bucket_traits &priv_real_bucket_traits(detail::bool_) + { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_; } + + real_bucket_traits &priv_real_bucket_traits(detail::bool_) + { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_.bucket_traits_.get_bucket_traits(*this); } + + const real_bucket_traits &priv_real_bucket_traits() const + { return this->priv_real_bucket_traits(detail::bool_()); } + + real_bucket_traits &priv_real_bucket_traits() + { return this->priv_real_bucket_traits(detail::bool_()); } + + const hasher &priv_hasher() const + { return static_cast(this->bucket_hash_equal_.bucket_hash.get()); } + + hasher &priv_hasher() + { return static_cast(this->bucket_hash_equal_.bucket_hash.get()); } + + bucket_ptr priv_buckets() const + { return this->priv_real_bucket_traits().bucket_begin(); } + + size_type priv_buckets_len() const + { return this->priv_real_bucket_traits().bucket_count(); } + + static node_ptr uncast(const_node_ptr ptr) + { return node_ptr(const_cast(detail::get_pointer(ptr))); } + + node &priv_value_to_node(value_type &v) + { return *this->get_real_value_traits().to_node_ptr(v); } + + const node &priv_value_to_node(const value_type &v) const + { return *this->get_real_value_traits().to_node_ptr(v); } + + size_traits &priv_size_traits() + { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_; } + + const size_traits &priv_size_traits() const + { return this->bucket_hash_equal_.bucket_hash.bucket_plus_size_; } + + template + void priv_erase_range_impl + (size_type bucket_num, siterator before_first_it, siterator end, Disposer disposer, size_type &num_erased) + { + const bucket_ptr buckets = priv_buckets(); + bucket_type &b = buckets[bucket_num]; + + if(before_first_it == b.before_begin() && end == b.end()){ + priv_erase_range_impl(bucket_num, 1, disposer, num_erased); + } + else{ + num_erased = 0; + siterator to_erase(before_first_it); + ++to_erase; + slist_node_ptr end_ptr = end.pointed_node(); + while(to_erase != end){ + priv_erase_from_group(end_ptr, dcast_bucket_ptr(to_erase.pointed_node()), optimize_multikey_t()); + to_erase = b.erase_after_and_dispose(before_first_it, make_node_disposer(disposer)); + ++num_erased; + } + this->priv_size_traits().set_size(this->priv_size_traits().get_size()-num_erased); + } + } + + template + void priv_erase_range_impl + (size_type first_bucket_num, size_type num_buckets, Disposer disposer, size_type &num_erased) + { + //Now fully clear the intermediate buckets + const bucket_ptr buckets = priv_buckets(); + num_erased = 0; + for(size_type i = first_bucket_num; i < (num_buckets + first_bucket_num); ++i){ + bucket_type &b = buckets[i]; + siterator b_begin(b.before_begin()); + siterator nxt(b_begin); + ++nxt; + siterator end(b.end()); + while(nxt != end){ + priv_init_group(nxt.pointed_node(), optimize_multikey_t()); + nxt = b.erase_after_and_dispose + (b_begin, make_node_disposer(disposer)); + this->priv_size_traits().decrement(); + ++num_erased; + } + } + } + + template + void priv_erase_range( siterator before_first_it, size_type first_bucket + , siterator last_it, size_type last_bucket + , Disposer disposer) + { + size_type num_erased; + if (first_bucket == last_bucket){ + priv_erase_range_impl(first_bucket, before_first_it, last_it, disposer, num_erased); + } + else { + bucket_type *b = (&this->priv_buckets()[0]); + priv_erase_range_impl(first_bucket, before_first_it, b[first_bucket].end(), disposer, num_erased); + if(size_type n = (last_bucket - first_bucket - 1)) + priv_erase_range_impl(first_bucket + 1, n, disposer, num_erased); + priv_erase_range_impl(last_bucket, b[last_bucket].before_begin(), last_it, disposer, num_erased); + } + } + + static node_ptr dcast_bucket_ptr(typename slist_impl::node_ptr p) + { return node_ptr(&static_cast(*p)); } + + std::size_t priv_stored_hash(const value_type &v, detail::true_) const + { return node_traits::get_hash(this->get_real_value_traits().to_node_ptr(v)); } + + std::size_t priv_stored_hash(const value_type &v, detail::false_) const + { return priv_hasher()(v); } + + std::size_t priv_stored_hash(slist_node_ptr n, detail::true_) const + { return node_traits::get_hash(dcast_bucket_ptr(n)); } + + std::size_t priv_stored_hash(slist_node_ptr, detail::false_) const + { + //This code should never be reached! + BOOST_INTRUSIVE_INVARIANT_ASSERT(0); + return 0; + } + + static void priv_store_hash(node_ptr p, std::size_t h, detail::true_) + { return node_traits::set_hash(p, h); } + + static void priv_store_hash(node_ptr, std::size_t, detail::false_) + {} + + static void priv_clear_group_nodes(bucket_type &b, detail::true_) + { + siterator it(b.begin()), itend(b.end()); + while(it != itend){ + node_ptr to_erase(dcast_bucket_ptr(it.pointed_node())); + ++it; + group_algorithms::init(to_erase); + } + } + + static void priv_clear_group_nodes(bucket_type &, detail::false_) + {} + + std::size_t priv_get_bucket_num(siterator it) + { return priv_get_bucket_num_hash_dispatch(it, store_hash_t()); } + + std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::true_) + { + return this->priv_hash_to_bucket + (this->priv_stored_hash(it.pointed_node(), store_hash_t())); + } + + std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::false_) + { return priv_get_bucket_num_no_hash_store(it, optimize_multikey_t()); } + + std::size_t priv_get_bucket_num_no_hash_store( siterator it, detail::true_) + { + bucket_ptr f(priv_buckets()), l(f + priv_buckets_len() - 1); + slist_node_ptr bb = priv_get_bucket_before_begin + ( f->end().pointed_node() + , l->end().pointed_node() + , dcast_bucket_ptr(it.pointed_node())); + //Now get the bucket_impl from the iterator + const bucket_type &b = static_cast + (bucket_type::slist_type::container_from_end_iterator(bucket_type::s_iterator_to(*bb))); + //Now just calculate the index b has in the bucket array + return static_cast(&b - &*f); + } + + std::size_t priv_get_bucket_num_no_hash_store( siterator it, detail::false_) + { + bucket_ptr f(priv_buckets()), l(f + priv_buckets_len() - 1); + slist_node_ptr first_ptr(f->cend().pointed_node()) + , last_ptr(l->cend().pointed_node()); + + //The end node is embedded in the singly linked list: + //iterate until we reach it. + while(!(first_ptr <= it.pointed_node() && it.pointed_node() <= last_ptr)){ + ++it; + } + //Now get the bucket_impl from the iterator + const bucket_type &b = static_cast + (bucket_type::container_from_end_iterator(it)); + + //Now just calculate the index b has in the bucket array + return static_cast(&b - &*f); + } + + void priv_erase_from_group(slist_node_ptr end_ptr, node_ptr to_erase_ptr, detail::true_) + { + node_ptr nxt_ptr(node_traits::get_next(to_erase_ptr)); + node_ptr prev_in_group_ptr(group_traits::get_next(to_erase_ptr)); + bool last_in_group = (end_ptr == nxt_ptr) || + (group_traits::get_next(nxt_ptr) != to_erase_ptr); + bool first_in_group = node_traits::get_next(prev_in_group_ptr) != to_erase_ptr; + + if(first_in_group && last_in_group){ + group_algorithms::init(to_erase_ptr); + } + else if(first_in_group){ + group_algorithms::unlink_after(nxt_ptr); + } + else if(last_in_group){ + node_ptr first_in_group = //possible_first_in_group ? possible_first_in_group : + priv_get_first_in_group_of_last_in_group(to_erase_ptr); + group_algorithms::unlink_after(first_in_group); + //possible_first_in_group = 0; + } + else{ + group_algorithms::unlink_after(nxt_ptr); + } + } + + void priv_erase_from_group(slist_node_ptr, node_ptr, detail::false_) + {} + + void priv_init_group(slist_node_ptr n, detail::true_) + { group_algorithms::init(dcast_bucket_ptr(n)); } + + void priv_init_group(slist_node_ptr, detail::false_) + {} + + void priv_insert_in_group(node_ptr first_in_group, node_ptr n, detail::true_) + { + if(first_in_group){ + if(group_algorithms::unique(first_in_group)) + group_algorithms::link_after(first_in_group, n); + else{ + group_algorithms::link_after(node_traits::get_next(first_in_group), n); + } + } + else{ + group_algorithms::init_header(n); + } + } + + static slist_node_ptr priv_get_bucket_before_begin + (slist_node_ptr bucket_beg, slist_node_ptr bucket_end, node_ptr p) + { + //First find the last node of p's group. + //This requires checking the first node of the next group or + //the bucket node. + node_ptr prev_node = p; + node_ptr nxt(node_traits::get_next(p)); + while(!(bucket_beg <= nxt && nxt <= bucket_end) && + (group_traits::get_next(nxt) == prev_node)){ + prev_node = nxt; + nxt = node_traits::get_next(nxt); + } + + //If we've reached the bucket node just return it. + if(bucket_beg <= nxt && nxt <= bucket_end){ + return nxt; + } + + //Otherwise, iterate using group links until the bucket node + node_ptr first_node_of_group = nxt; + node_ptr last_node_group = group_traits::get_next(first_node_of_group); + slist_node_ptr possible_end = node_traits::get_next(last_node_group); + + while(!(bucket_beg <= possible_end && possible_end <= bucket_end)){ + first_node_of_group = dcast_bucket_ptr(possible_end); + last_node_group = group_traits::get_next(first_node_of_group); + possible_end = node_traits::get_next(last_node_group); + } + return possible_end; + } + + static node_ptr priv_get_prev_to_first_in_group(slist_node_ptr bucket_node, node_ptr first_in_group) + { + //Just iterate using group links and obtain the node + //before "first_in_group)" + node_ptr prev_node = dcast_bucket_ptr(bucket_node); + node_ptr nxt(node_traits::get_next(prev_node)); + while(nxt != first_in_group){ + prev_node = group_traits::get_next(nxt); + nxt = node_traits::get_next(prev_node); + } + return prev_node; + } + + static node_ptr priv_get_first_in_group_of_last_in_group(node_ptr last_in_group) + { + //Just iterate using group links and obtain the node + //before "last_in_group" + node_ptr possible_first = group_traits::get_next(last_in_group); + node_ptr possible_first_prev = group_traits::get_next(possible_first); + // The deleted node is at the end of the group, so the + // node in the group pointing to it is at the beginning + // of the group. Find that to change its pointer. + while(possible_first_prev != last_in_group){ + possible_first = possible_first_prev; + possible_first_prev = group_traits::get_next(possible_first); + } + return possible_first; + } + + void priv_insert_in_group(node_ptr, node_ptr, detail::false_) + {} + + static node_ptr priv_get_last_in_group(node_ptr first_in_group) + { return priv_get_last_in_group(first_in_group, optimize_multikey_t()); } + + static node_ptr priv_get_last_in_group(node_ptr first_in_group, detail::true_) + { return group_traits::get_next(first_in_group); } + + static node_ptr priv_get_last_in_group(node_ptr n, detail::false_) + { return n; } + + siterator priv_get_previous + (bucket_type &b, siterator i) + { return priv_get_previous(b, i, optimize_multikey_t()); } + + siterator priv_get_previous + (bucket_type &b, siterator i, detail::true_) + { + node_ptr elem(dcast_bucket_ptr(i.pointed_node())); + node_ptr prev_in_group(group_traits::get_next(elem)); + bool first_in_group = node_traits::get_next(prev_in_group) != elem; + + typename bucket_type::node &n = first_in_group + ? *priv_get_prev_to_first_in_group(b.end().pointed_node(), elem) + : *group_traits::get_next(elem) + ; + return bucket_type::s_iterator_to(n); + } + + siterator priv_get_previous + (bucket_type &b, siterator i, detail::false_) + { return b.previous(i); } + + static siterator priv_get_last(bucket_type &b) + { return priv_get_last(b, optimize_multikey_t()); } + + static siterator priv_get_last(bucket_type &b, detail::true_) + { + //First find the last node of p's group. + //This requires checking the first node of the next group or + //the bucket node. + slist_node_ptr end_ptr(b.end().pointed_node()); + node_ptr possible_end(node_traits::get_next( dcast_bucket_ptr(end_ptr))); + node_ptr last_node_group(possible_end); + + while(end_ptr != possible_end){ + last_node_group = group_traits::get_next(dcast_bucket_ptr(possible_end)); + possible_end = node_traits::get_next(last_node_group); + } + return bucket_type::s_iterator_to(*last_node_group); + } + + static siterator priv_get_last(bucket_type &b, detail::false_) + { return b.previous(b.end()); } + + siterator priv_get_previous_and_next_in_group + (siterator i, node_ptr &nxt_in_group) + { + siterator prev; + node_ptr elem(dcast_bucket_ptr(i.pointed_node())); + bucket_ptr f(priv_buckets()), l(f + priv_buckets_len() - 1); + + slist_node_ptr first_end_ptr(f->cend().pointed_node()); + slist_node_ptr last_end_ptr (l->cend().pointed_node()); + + node_ptr nxt(node_traits::get_next(elem)); + node_ptr prev_in_group(group_traits::get_next(elem)); + bool last_in_group = (first_end_ptr <= nxt && nxt <= last_end_ptr) || + (group_traits::get_next(nxt) != elem); + bool first_in_group = node_traits::get_next(prev_in_group) != elem; + + if(first_in_group){ + node_ptr start_pos; + if(last_in_group){ + start_pos = elem; + nxt_in_group = 0; + } + else{ + start_pos = prev_in_group; + nxt_in_group = node_traits::get_next(elem); + } + slist_node_ptr bucket_node; + if(store_hash){ + bucket_node = this->priv_buckets() + [this->priv_hash_to_bucket + (this->priv_stored_hash(elem, store_hash_t())) + ].before_begin().pointed_node(); + } + else{ + bucket_node = priv_get_bucket_before_begin + (first_end_ptr, last_end_ptr, start_pos); + } + prev = bucket_type::s_iterator_to + (*priv_get_prev_to_first_in_group(bucket_node, elem)); + } + else{ + if(last_in_group){ + nxt_in_group = priv_get_first_in_group_of_last_in_group(elem); + } + else{ + nxt_in_group = node_traits::get_next(elem); + } + prev = bucket_type::s_iterator_to(*group_traits::get_next(elem)); + } + return prev; + } + + template + void priv_erase(const_iterator i, Disposer disposer, detail::true_) + { + siterator elem(i.slist_it()); + node_ptr nxt_in_group; + siterator prev = priv_get_previous_and_next_in_group(elem, nxt_in_group); + bucket_type::s_erase_after_and_dispose(prev, make_node_disposer(disposer)); + if(nxt_in_group) + group_algorithms::unlink_after(nxt_in_group); + if(safemode_or_autounlink) + group_algorithms::init(dcast_bucket_ptr(elem.pointed_node())); + } + + template + void priv_erase(const_iterator i, Disposer disposer, detail::false_) + { + siterator to_erase(i.slist_it()); + bucket_type &b = this->priv_buckets()[this->priv_get_bucket_num(to_erase)]; + siterator prev(priv_get_previous(b, to_erase)); + b.erase_after_and_dispose(prev, make_node_disposer(disposer)); + } + + bucket_ptr priv_invalid_bucket() const + { + const real_bucket_traits &rbt = this->priv_real_bucket_traits(); + return rbt.bucket_begin() + rbt.bucket_count(); + } + + siterator priv_invalid_local_it() const + { return priv_invalid_bucket()->end(); } + + siterator priv_begin(size_type &bucket_num) const + { return priv_begin(bucket_num, cache_begin_t()); } + + siterator priv_begin(size_type &bucket_num, detail::bool_) const + { + size_type n = 0; + size_type buckets_len = this->priv_buckets_len(); + for (n = 0; n < buckets_len; ++n){ + bucket_type &b = this->priv_buckets()[n]; + if(!b.empty()){ + bucket_num = n; + return b.begin(); + } + } + bucket_num = n; + return priv_invalid_local_it(); + } + + siterator priv_begin(size_type &bucket_num, detail::bool_) const + { + bucket_num = this->bucket_hash_equal_.cached_begin_ - this->priv_buckets(); + if(this->bucket_hash_equal_.cached_begin_ == priv_invalid_bucket()){ + return priv_invalid_local_it(); + } + else{ + return this->bucket_hash_equal_.cached_begin_->begin(); + } + } + + void priv_initialize_cache() + { priv_initialize_cache(cache_begin_t()); } + + void priv_initialize_cache(detail::bool_) + { this->bucket_hash_equal_.cached_begin_ = priv_invalid_bucket(); } + + void priv_initialize_cache(detail::bool_) + {} + + void priv_insertion_update_cache(size_type insertion_bucket) + { priv_insertion_update_cache(insertion_bucket, cache_begin_t()); } + + void priv_insertion_update_cache(size_type insertion_bucket, detail::bool_) + { + bucket_ptr p = priv_buckets() + insertion_bucket; + if(p < this->bucket_hash_equal_.cached_begin_){ + this->bucket_hash_equal_.cached_begin_ = p; + } + } + + void priv_insertion_update_cache(size_type, detail::bool_) + {} + + void priv_erasure_update_cache(size_type first_bucket, size_type last_bucket) + { priv_erasure_update_cache(first_bucket, last_bucket, cache_begin_t()); } + + void priv_erasure_update_cache(size_type first_bucket_num, size_type last_bucket_num, detail::bool_) + { + //If the last bucket is the end, the cache must be updated + //to the last position if all + if(priv_get_cache_bucket_num() == first_bucket_num && + priv_buckets()[first_bucket_num].empty() ){ + priv_set_cache(priv_buckets() + last_bucket_num); + priv_erasure_update_cache(); + } + } + + void priv_erasure_update_cache(size_type, size_type, detail::bool_) + {} + + void priv_erasure_update_cache() + { priv_erasure_update_cache(cache_begin_t()); } + + void priv_erasure_update_cache(detail::bool_) + { + if(constant_time_size && !size()){ + priv_initialize_cache(); + } + else{ + size_type current_n = this->bucket_hash_equal_.cached_begin_ - priv_buckets(); + for( const size_type num_buckets = this->priv_buckets_len() + ; current_n < num_buckets + ; ++current_n, ++this->bucket_hash_equal_.cached_begin_){ + if(!this->bucket_hash_equal_.cached_begin_->empty()){ + return; + } + } + priv_initialize_cache(); + } + } + + void priv_erasure_update_cache(detail::bool_) + {} + + void priv_swap_cache(detail::bool_, hashtable_impl &other) + { + std::swap( this->bucket_hash_equal_.cached_begin_ + , other.bucket_hash_equal_.cached_begin_); + } + + void priv_swap_cache(detail::bool_, hashtable_impl &) + {} + + bucket_ptr priv_get_cache() + { return priv_get_cache(cache_begin_t()); } + + bucket_ptr priv_get_cache(detail::bool_) + { return this->bucket_hash_equal_.cached_begin_; } + + bucket_ptr priv_get_cache(detail::bool_) + { return this->priv_buckets(); } + + void priv_set_cache(bucket_ptr p) + { priv_set_cache(p, cache_begin_t()); } + + void priv_set_cache(bucket_ptr p, detail::bool_) + { this->bucket_hash_equal_.cached_begin_ = p; } + + void priv_set_cache(bucket_ptr, detail::bool_) + {} + + size_type priv_get_cache_bucket_num() + { return priv_get_cache_bucket_num(cache_begin_t()); } + + size_type priv_get_cache_bucket_num(detail::bool_) + { return this->bucket_hash_equal_.cached_begin_ - this->priv_buckets(); } + + size_type priv_get_cache_bucket_num(detail::bool_) + { return 0u; } + + void priv_clear_buckets() + { + this->priv_clear_buckets + ( priv_get_cache() + , this->priv_buckets_len() - (priv_get_cache() - priv_buckets())); + } + + void priv_initialize_buckets() + { + this->priv_clear_buckets + ( priv_buckets(), this->priv_buckets_len()); + } + + void priv_clear_buckets(bucket_ptr buckets_ptr, size_type buckets_len) + { + for(; buckets_len--; ++buckets_ptr){ + if(safemode_or_autounlink){ + priv_clear_group_nodes(*buckets_ptr, optimize_multikey_t()); + buckets_ptr->clear_and_dispose(detail::init_disposer()); + } + else{ + buckets_ptr->clear(); + } + } + priv_initialize_cache(); + } + + template + siterator priv_find + ( const KeyType &key, KeyHasher hash_func + , KeyValueEqual equal_func, size_type &bucket_number, std::size_t &h, siterator &previt) const + { + bucket_number = priv_hash_to_bucket((h = hash_func(key))); + + if(constant_time_size && this->empty()){ + return priv_invalid_local_it(); + } + + bucket_type &b = this->priv_buckets()[bucket_number]; + previt = b.before_begin(); + siterator it = previt; + ++it; + + while(it != b.end()){ + const value_type &v = priv_value_from_slist_node(it.pointed_node()); + if(compare_hash){ + std::size_t vh = this->priv_stored_hash(v, store_hash_t()); + if(h == vh && equal_func(key, v)){ + return it; + } + } + else if(equal_func(key, v)){ + return it; + } + if(optimize_multikey){ + previt = bucket_type::s_iterator_to + (*priv_get_last_in_group(dcast_bucket_ptr(it.pointed_node()))); + it = previt; + } + else{ + previt = it; + } + ++it; + } + + return priv_invalid_local_it(); + } + + template + std::pair priv_equal_range + ( const KeyType &key + , KeyHasher hash_func + , KeyValueEqual equal_func + , size_type &bucket_number_first + , size_type &bucket_number_second + , size_type &count) const + { + std::size_t h; + count = 0; + siterator prev; + //Let's see if the element is present + std::pair to_return + ( priv_find(key, hash_func, equal_func, bucket_number_first, h, prev) + , priv_invalid_local_it()); + if(to_return.first == to_return.second){ + bucket_number_second = bucket_number_first; + return to_return; + } + //If it's present, find the first that it's not equal in + //the same bucket + bucket_type &b = this->priv_buckets()[bucket_number_first]; + siterator it = to_return.first; + if(optimize_multikey){ + to_return.second = bucket_type::s_iterator_to + (*node_traits::get_next(priv_get_last_in_group + (dcast_bucket_ptr(it.pointed_node())))); + count = std::distance(it, to_return.second); + if(to_return.second != b.end()){ + bucket_number_second = bucket_number_first; + return to_return; + } + } + else{ + ++count; + ++it; + while(it != b.end()){ + const value_type &v = priv_value_from_slist_node(it.pointed_node()); + if(compare_hash){ + std::size_t hv = this->priv_stored_hash(v, store_hash_t()); + if(hv != h || !equal_func(key, v)){ + to_return.second = it; + bucket_number_second = bucket_number_first; + return to_return; + } + } + else if(!equal_func(key, v)){ + to_return.second = it; + bucket_number_second = bucket_number_first; + return to_return; + } + ++it; + ++count; + } + } + + //If we reached the end, find the first, non-empty bucket + for(bucket_number_second = bucket_number_first+1 + ; bucket_number_second != this->priv_buckets_len() + ; ++bucket_number_second){ + bucket_type &b = this->priv_buckets()[bucket_number_second]; + if(!b.empty()){ + to_return.second = b.begin(); + return to_return; + } + } + + //Otherwise, return the end node + to_return.second = priv_invalid_local_it(); + return to_return; + } + /// @endcond +}; + +/// @cond +template < class T + , bool UniqueKeys + , class O1 = none, class O2 = none + , class O3 = none, class O4 = none + , class O5 = none, class O6 = none + , class O7 = none, class O8 = none + , class O9 = none + > +struct make_hashtable_opt +{ + typedef typename pack_options + < uset_defaults, O1, O2, O3, O4, O5, O6, O7, O8, O9>::type packed_options; + + //Real value traits must be calculated from options + typedef typename detail::get_value_traits + ::type value_traits; + /// @cond + static const bool external_value_traits = + detail::external_value_traits_is_true::value; + typedef typename detail::eval_if_c + < external_value_traits + , detail::eval_value_traits + , detail::identity + >::type real_value_traits; + typedef typename packed_options::bucket_traits specified_bucket_traits; + /// @endcond + + //Real bucket traits must be calculated from options and calculated value_traits + typedef typename detail::get_slist_impl + ::type + >::type slist_impl; + + typedef typename + detail::if_c< detail::is_same + < specified_bucket_traits + , default_bucket_traits + >::value + , detail::bucket_traits_impl + , specified_bucket_traits + >::type real_bucket_traits; + + typedef usetopt + < value_traits + , UniqueKeys + , typename packed_options::hash + , typename packed_options::equal + , typename packed_options::size_type + , packed_options::constant_time_size + , real_bucket_traits + , packed_options::power_2_buckets + , packed_options::cache_begin + , packed_options::compare_hash + > type; +}; +/// @endcond + +//! Helper metafunction to define a \c hashtable that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_hashtable +{ + /// @cond + typedef hashtable_impl + < typename make_hashtable_opt + ::type + > implementation_defined; + + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class hashtable + : public make_hashtable::type +{ + typedef typename make_hashtable + ::type Base; + + public: + typedef typename Base::value_traits value_traits; + typedef typename Base::real_value_traits real_value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + typedef typename Base::bucket_ptr bucket_ptr; + typedef typename Base::size_type size_type; + typedef typename Base::hasher hasher; + typedef typename Base::bucket_traits bucket_traits; + typedef typename Base::key_equal key_equal; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + hashtable ( const bucket_traits &b_traits + , const hasher & hash_func = hasher() + , const key_equal &equal_func = key_equal() + , const value_traits &v_traits = value_traits()) + : Base(b_traits, hash_func, equal_func, v_traits) + {} +}; + +#endif + + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_HASHTABLE_HPP diff --git a/win32/include/boost/intrusive/intrusive_fwd.hpp b/win32/include/boost/intrusive/intrusive_fwd.hpp new file mode 100755 index 000000000..1db71c1dc --- /dev/null +++ b/win32/include/boost/intrusive/intrusive_fwd.hpp @@ -0,0 +1,364 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_FWD_HPP +#define BOOST_INTRUSIVE_FWD_HPP + +#include +#include + +/// @cond + +//std predeclarations +namespace std{ + +template +struct equal_to; + +template +struct less; + +} //namespace std{ + +namespace boost { + +//Hash predeclaration +template +struct hash; + +namespace intrusive { + +struct none; + +} //namespace intrusive{ +} //namespace boost{ + +namespace boost { +namespace intrusive { + +//////////////////////////// +// Node algorithms +//////////////////////////// + +//Algorithms predeclarations +template +class circular_list_algorithms; + +template +class circular_slist_algorithms; + +template +class rbtree_algorithms; + +//////////////////////////// +// Containers +//////////////////////////// + +//slist +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + , class O5 = none + > +class slist; + +template + < class O1 = none + , class O2 = none + , class O3 = none + > +class slist_base_hook; + +template + < class O1 = none + , class O2 = none + , class O3 = none + > +class slist_member_hook; + +//list +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + > +class list; + +template + < class O1 = none + , class O2 = none + , class O3 = none + > +class list_base_hook; + +template + < class O1 = none + , class O2 = none + , class O3 = none + > +class list_member_hook; + +//rbtree/set/multiset +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class rbtree; + +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class set; + +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class multiset; + +template + < class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class set_base_hook; + +template + < class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class set_member_hook; + +//splaytree/splay_set/splay_multiset +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class splaytree; + +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class splay_set; + +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class splay_multiset; + +template + < class O1 = none + , class O2 = none + , class O3 = none + > +class splay_set_base_hook; + +template + < class O1 = none + , class O2 = none + , class O3 = none + > +class splay_set_member_hook; + +//avltree/avl_set/avl_multiset +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class avltree; + +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class avl_set; + +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class avl_multiset; + +template + < class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class avl_set_base_hook; + +template + < class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class avl_set_member_hook; + +//sgtree/sg_set/sg_multiset +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class sgtree; + +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class sg_set; + +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class sg_multiset; + +template + < class O1 = none + , class O2 = none + , class O3 = none + > +class bs_set_base_hook; + +template + < class O1 = none + , class O2 = none + , class O3 = none + > +class bs_set_member_hook; + +//hashtable/unordered_set/unordered_multiset +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + , class O5 = none + , class O6 = none + , class O7 = none + , class O8 = none + , class O9 = none + > +class hashtable; + +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + , class O5 = none + , class O6 = none + , class O7 = none + , class O8 = none + , class O9 = none + > +class unordered_set; + +template + < class T + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + , class O5 = none + , class O6 = none + , class O7 = none + , class O8 = none + , class O9 = none + > +class unordered_multiset; + +template + < class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class unordered_set_base_hook; + +template + < class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + > +class unordered_set_member_hook; + +template + < class O1 = none + , class O2 = none + , class O3 = none + > +class any_base_hook; + +template + < class O1 = none + , class O2 = none + , class O3 = none + > +class any_member_hook; + +} //namespace intrusive { +} //namespace boost { + +/// @endcond + +#endif //#ifndef BOOST_INTRUSIVE_FWD_HPP diff --git a/win32/include/boost/intrusive/linear_slist_algorithms.hpp b/win32/include/boost/intrusive/linear_slist_algorithms.hpp new file mode 100755 index 000000000..0bdadb3dd --- /dev/null +++ b/win32/include/boost/intrusive/linear_slist_algorithms.hpp @@ -0,0 +1,327 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_LINEAR_SLIST_ALGORITHMS_HPP +#define BOOST_INTRUSIVE_LINEAR_SLIST_ALGORITHMS_HPP + +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +//! linear_slist_algorithms provides basic algorithms to manipulate nodes +//! forming a linear singly linked list. +//! +//! linear_slist_algorithms is configured with a NodeTraits class, which encapsulates the +//! information about the node to be manipulated. NodeTraits must support the +//! following interface: +//! +//! Typedefs: +//! +//! node: The type of the node that forms the linear list +//! +//! node_ptr: A pointer to a node +//! +//! const_node_ptr: A pointer to a const node +//! +//! Static functions: +//! +//! static node_ptr get_next(const_node_ptr n); +//! +//! static void set_next(node_ptr n, node_ptr next); +template +class linear_slist_algorithms + /// @cond + : public detail::common_slist_algorithms + /// @endcond +{ + /// @cond + typedef detail::common_slist_algorithms base_t; + /// @endcond + public: + typedef typename NodeTraits::node node; + typedef typename NodeTraits::node_ptr node_ptr; + typedef typename NodeTraits::const_node_ptr const_node_ptr; + typedef NodeTraits node_traits; + + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! Effects: Constructs an non-used list element, putting the next + //! pointer to null: + //! NodeTraits::get_next(this_node) == 0 + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void init(node_ptr this_node); + + //! Requires: this_node must be in a circular list or be an empty circular list. + //! + //! Effects: Returns true is "this_node" is the only node of a circular list: + //! or it's a not inserted node: + //! return !NodeTraits::get_next(this_node) || NodeTraits::get_next(this_node) == this_node + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static bool unique(const_node_ptr this_node); + + //! Effects: Returns true is "this_node" has the same state as if + //! it was inited using "init(node_ptr)" + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static bool inited(const_node_ptr this_node); + + //! Requires: prev_node must be in a circular list or be an empty circular list. + //! + //! Effects: Unlinks the next node of prev_node from the circular list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void unlink_after(node_ptr prev_node); + + //! Requires: prev_node and last_node must be in a circular list + //! or be an empty circular list. + //! + //! Effects: Unlinks the range (prev_node, last_node) from the linear list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void unlink_after(node_ptr prev_node, node_ptr last_node); + + //! Requires: prev_node must be a node of a linear list. + //! + //! Effects: Links this_node after prev_node in the linear list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void link_after(node_ptr prev_node, node_ptr this_node); + + //! Requires: b and e must be nodes of the same linear list or an empty range. + //! and p must be a node of a different linear list. + //! + //! Effects: Removes the nodes from (b, e] range from their linear list and inserts + //! them after p in p's linear list. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void transfer_after(node_ptr p, node_ptr b, node_ptr e); + + #endif //#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + + //! Effects: Constructs an empty list, making this_node the only + //! node of the circular list: + //! NodeTraits::get_next(this_node) == this_node. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void init_header(node_ptr this_node) + { NodeTraits::set_next(this_node, node_ptr(0)); } + + //! Requires: this_node and prev_init_node must be in the same linear list. + //! + //! Effects: Returns the previous node of this_node in the linear list starting. + //! the search from prev_init_node. The first node checked for equality + //! is NodeTraits::get_next(prev_init_node). + //! + //! Complexity: Linear to the number of elements between prev_init_node and this_node. + //! + //! Throws: Nothing. + static node_ptr get_previous_node(node_ptr prev_init_node, node_ptr this_node) + { return base_t::get_previous_node(prev_init_node, this_node); } + + //! Requires: this_node must be in a linear list or be an empty linear list. + //! + //! Effects: Returns the number of nodes in a linear list. If the linear list + //! is empty, returns 1. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static std::size_t count(const_node_ptr this_node) + { + std::size_t result = 0; + const_node_ptr p = this_node; + do{ + p = NodeTraits::get_next(p); + ++result; + } while (p); + return result; + } + + //! Requires: this_node and other_node must be nodes inserted + //! in linear lists or be empty linear lists. + //! + //! Effects: Moves all the nodes previously chained after this_node after other_node + //! and vice-versa. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + static void swap_trailing_nodes(node_ptr this_node, node_ptr other_node) + { + node_ptr this_nxt = NodeTraits::get_next(this_node); + node_ptr other_nxt = NodeTraits::get_next(other_node); + NodeTraits::set_next(this_node, other_nxt); + NodeTraits::set_next(other_node, this_nxt); + } + + //! Effects: Reverses the order of elements in the list. + //! + //! Returns: The new first node of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear to the contained elements. + static node_ptr reverse(node_ptr p) + { + if(!p) return node_ptr(0); + node_ptr i = NodeTraits::get_next(p); + node_ptr first(p); + while(i){ + node_ptr nxti(NodeTraits::get_next(i)); + base_t::unlink_after(p); + NodeTraits::set_next(i, first); + first = i; + i = nxti; + } + return first; + } + + //! Effects: Moves the first n nodes starting at p to the end of the list. + //! + //! Returns: A pair containing the new first and last node of the list or + //! if there has been any movement, a null pair if n leads to no movement. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements plus the number moved positions. + static std::pair move_first_n_backwards(node_ptr p, std::size_t n) + { + std::pair ret(node_ptr(0), node_ptr(0)); + //Null shift, or count() == 0 or 1, nothing to do + if(!n || !p || !NodeTraits::get_next(p)){ + return ret; + } + + node_ptr first = p; + bool end_found = false; + node_ptr new_last(0); + node_ptr old_last(0); + + //Now find the new last node according to the shift count. + //If we find 0 before finding the new last node + //unlink p, shortcut the search now that we know the size of the list + //and continue. + for(std::size_t i = 1; i <= n; ++i){ + new_last = first; + first = NodeTraits::get_next(first); + if(first == 0){ + //Shortcut the shift with the modulo of the size of the list + n %= i; + if(!n) return ret; + old_last = new_last; + i = 0; + //Unlink p and continue the new first node search + first = p; + //unlink_after(new_last); + end_found = true; + } + } + + //If the p has not been found in the previous loop, find it + //starting in the new first node and unlink it + if(!end_found){ + old_last = base_t::get_previous_node(first, node_ptr(0)); + } + + //Now link p after the new last node + NodeTraits::set_next(old_last, p); + NodeTraits::set_next(new_last, node_ptr(0)); + ret.first = first; + ret.second = new_last; + return ret; + } + + //! Effects: Moves the first n nodes starting at p to the beginning of the list. + //! + //! Returns: A pair containing the new first and last node of the list or + //! if there has been any movement, a null pair if n leads to no movement. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements plus the number moved positions. + static std::pair move_first_n_forward(node_ptr p, std::size_t n) + { + std::pair ret(node_ptr(0), node_ptr(0)); + //Null shift, or count() == 0 or 1, nothing to do + if(!n || !p || !NodeTraits::get_next(p)) + return ret; + + node_ptr first = p; + + //Iterate until p is found to know where the current last node is. + //If the shift count is less than the size of the list, we can also obtain + //the position of the new last node after the shift. + node_ptr old_last(first), next_to_it, new_last(p); + std::size_t distance = 1; + while(!!(next_to_it = node_traits::get_next(old_last))){ + if(distance++ > n) + new_last = node_traits::get_next(new_last); + old_last = next_to_it; + } + //If the shift was bigger or equal than the size, obtain the equivalent + //forward shifts and find the new last node. + if(distance <= n){ + //Now find the equivalent forward shifts. + //Shortcut the shift with the modulo of the size of the list + std::size_t new_before_last_pos = (distance - (n % distance))% distance; + //If the shift is a multiple of the size there is nothing to do + if(!new_before_last_pos) + return ret; + + for( new_last = p + ; --new_before_last_pos + ; new_last = node_traits::get_next(new_last)){ + //empty + } + } + + //Get the first new node + node_ptr new_first(node_traits::get_next(new_last)); + //Now put the old beginning after the old end + NodeTraits::set_next(old_last, p); + NodeTraits::set_next(new_last, node_ptr(0)); + ret.first = new_first; + ret.second = new_last; + return ret; + } +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_LINEAR_SLIST_ALGORITHMS_HPP diff --git a/win32/include/boost/intrusive/link_mode.hpp b/win32/include/boost/intrusive/link_mode.hpp new file mode 100755 index 000000000..80ff7de47 --- /dev/null +++ b/win32/include/boost/intrusive/link_mode.hpp @@ -0,0 +1,46 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_VALUE_LINK_TYPE_HPP +#define BOOST_INTRUSIVE_VALUE_LINK_TYPE_HPP + +namespace boost { +namespace intrusive { + +//!This enumeration defines the type of value_traits that can be defined +//!for Boost.Intrusive containers +enum link_mode_type{ + //!If this linking policy is specified in a value_traits class + //!as the link_mode, containers + //!configured with such value_traits won't set the hooks + //!of the erased values to a default state. Containers also won't + //!check that the hooks of the new values are default initialized. + normal_link, + + //!If this linking policy is specified in a value_traits class + //!as the link_mode, containers + //!configured with such value_traits will set the hooks + //!of the erased values to a default state. Containers also will + //!check that the hooks of the new values are default initialized. + safe_link, + + //!Same as "safe_link" but the user type is an auto-unlink + //!type, so the containers with constant-time size features won't be + //!compatible with value_traits configured with this policy. + //!Containers also know that the a value can be silently erased from + //!the container without using any function provided by the containers. + auto_unlink +}; +} //namespace intrusive +} //namespace boost + +#endif //BOOST_INTRUSIVE_VALUE_LINK_TYPE_HPP diff --git a/win32/include/boost/intrusive/list.hpp b/win32/include/boost/intrusive/list.hpp new file mode 100755 index 000000000..5722f5d61 --- /dev/null +++ b/win32/include/boost/intrusive/list.hpp @@ -0,0 +1,1470 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_LIST_HPP +#define BOOST_INTRUSIVE_LIST_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond + +template +struct internal_default_list_hook +{ + template static detail::one test(...); + template static detail::two test(typename U::default_list_hook* = 0); + static const bool value = sizeof(test(0)) == sizeof(detail::two); +}; + +template +struct get_default_list_hook +{ + typedef typename T::default_list_hook type; +}; + +template +struct listopt +{ + typedef ValueTraits value_traits; + typedef SizeType size_type; + static const bool constant_time_size = ConstantTimeSize; +}; + +template +struct list_defaults + : pack_options + < none + , base_hook + < typename detail::eval_if_c + < internal_default_list_hook::value + , get_default_list_hook + , detail::identity + >::type + > + , constant_time_size + , size_type + >::type +{}; + +/// @endcond + +//! The class template list is an intrusive container that mimics most of the +//! interface of std::list as described in the C++ standard. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<> and \c size_type<>. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class list_impl +{ + //Public typedefs + public: + typedef typename Config::value_traits value_traits; + /// @cond + static const bool external_value_traits = + detail::external_value_traits_is_true::value; + typedef typename detail::eval_if_c + < external_value_traits + , detail::eval_value_traits + , detail::identity + >::type real_value_traits; + /// @endcond + typedef typename real_value_traits::pointer pointer; + typedef typename real_value_traits::const_pointer const_pointer; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::reference reference; + typedef typename std::iterator_traits::reference const_reference; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename Config::size_type size_type; + typedef list_iterator iterator; + typedef list_iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef typename real_value_traits::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef circular_list_algorithms node_algorithms; + + static const bool constant_time_size = Config::constant_time_size; + static const bool stateful_value_traits = detail::store_cont_ptr_on_it::value; + + /// @cond + + private: + typedef detail::size_holder size_traits; + + //Non-copyable and non-moveable + list_impl (const list_impl&); + list_impl &operator =(const list_impl&); + + enum { safemode_or_autounlink = + (int)real_value_traits::link_mode == (int)auto_unlink || + (int)real_value_traits::link_mode == (int)safe_link }; + + //Constant-time size is incompatible with auto-unlink hooks! + BOOST_STATIC_ASSERT(!(constant_time_size && + ((int)real_value_traits::link_mode == (int)auto_unlink) + )); + + //Const cast emulation for smart pointers + static node_ptr uncast(const_node_ptr ptr) + { + //return node_ptr(detail::get_pointer(ptr))); + return const_cast(detail::get_pointer(ptr)); + } + + node_ptr get_root_node() + { return node_ptr(&data_.root_plus_size_.root_); } + + const_node_ptr get_root_node() const + { return const_node_ptr(&data_.root_plus_size_.root_); } + + struct root_plus_size : public size_traits + { + node root_; + }; + + struct data_t : public value_traits + { + typedef typename list_impl::value_traits value_traits; + data_t(const value_traits &val_traits) + : value_traits(val_traits) + {} + + root_plus_size root_plus_size_; + } data_; + + size_traits &priv_size_traits() + { return data_.root_plus_size_; } + + const size_traits &priv_size_traits() const + { return data_.root_plus_size_; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return data_; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return data_.get_value_traits(*this); } + + real_value_traits &get_real_value_traits(detail::bool_) + { return data_; } + + real_value_traits &get_real_value_traits(detail::bool_) + { return data_.get_value_traits(*this); } + + /// @endcond + + public: + + const real_value_traits &get_real_value_traits() const + { return this->get_real_value_traits(detail::bool_()); } + + real_value_traits &get_real_value_traits() + { return this->get_real_value_traits(detail::bool_()); } + + //! Effects: constructs an empty list. + //! + //! Complexity: Constant + //! + //! Throws: If real_value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks). + list_impl(const value_traits &v_traits = value_traits()) + : data_(v_traits) + { + this->priv_size_traits().set_size(size_type(0)); + node_algorithms::init_header(this->get_root_node()); + } + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! + //! Effects: Constructs a list equal to the range [first,last). + //! + //! Complexity: Linear in std::distance(b, e). No copy constructors are called. + //! + //! Throws: If real_value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks). + template + list_impl(Iterator b, Iterator e, const value_traits &v_traits = value_traits()) + : data_(v_traits) + { + this->priv_size_traits().set_size(size_type(0)); + node_algorithms::init_header(this->get_root_node()); + this->insert(this->end(), b, e); + } + + //! Effects: If it's not a safe-mode or an auto-unlink value_type + //! the destructor does nothing + //! (ie. no code is generated). Otherwise it detaches all elements from this. + //! In this case the objects in the list are not deleted (i.e. no destructors + //! are called), but the hooks according to the ValueTraits template parameter + //! are set to their default value. + //! + //! Complexity: Linear to the number of elements in the list, if + //! it's a safe-mode or auto-unlink value . Otherwise constant. + ~list_impl() + { + if(safemode_or_autounlink){ + this->clear(); + } + } + + //! Requires: value must be an lvalue. + //! + //! Effects: Inserts the value in the back of the list. + //! No copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Does not affect the validity of iterators and references. + void push_back(reference value) + { + node_ptr to_insert = get_real_value_traits().to_node_ptr(value); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); + node_algorithms::link_before(this->get_root_node(), to_insert); + this->priv_size_traits().increment(); + } + + //! Requires: value must be an lvalue. + //! + //! Effects: Inserts the value in the front of the list. + //! No copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Does not affect the validity of iterators and references. + void push_front(reference value) + { + node_ptr to_insert = get_real_value_traits().to_node_ptr(value); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); + node_algorithms::link_before(node_traits::get_next(this->get_root_node()), to_insert); + this->priv_size_traits().increment(); + } + + //! Effects: Erases the last element of the list. + //! No destructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Invalidates the iterators (but not the references) to the erased element. + void pop_back() + { return this->pop_back_and_dispose(detail::null_disposer()); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the last element of the list. + //! No destructors are called. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Invalidates the iterators to the erased element. + template + void pop_back_and_dispose(Disposer disposer) + { + node_ptr to_erase = node_traits::get_previous(this->get_root_node()); + node_algorithms::unlink(to_erase); + this->priv_size_traits().decrement(); + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + disposer(get_real_value_traits().to_value_ptr(to_erase)); + } + + //! Effects: Erases the first element of the list. + //! No destructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Invalidates the iterators (but not the references) to the erased element. + void pop_front() + { return this->pop_front_and_dispose(detail::null_disposer()); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the first element of the list. + //! No destructors are called. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Invalidates the iterators to the erased element. + template + void pop_front_and_dispose(Disposer disposer) + { + node_ptr to_erase = node_traits::get_next(this->get_root_node()); + node_algorithms::unlink(to_erase); + this->priv_size_traits().decrement(); + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + disposer(get_real_value_traits().to_value_ptr(to_erase)); + } + + //! Effects: Returns a reference to the first element of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference front() + { return *get_real_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); } + + //! Effects: Returns a const_reference to the first element of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference front() const + { return *get_real_value_traits().to_value_ptr(uncast(node_traits::get_next(this->get_root_node()))); } + + //! Effects: Returns a reference to the last element of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference back() + { return *get_real_value_traits().to_value_ptr(node_traits::get_previous(this->get_root_node())); } + + //! Effects: Returns a const_reference to the last element of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference back() const + { return *get_real_value_traits().to_value_ptr(uncast(node_traits::get_previous(this->get_root_node()))); } + + //! Effects: Returns an iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return iterator(node_traits::get_next(this->get_root_node()), this); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return this->cbegin(); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return const_iterator(node_traits::get_next(this->get_root_node()), this); } + + //! Effects: Returns an iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return iterator(this->get_root_node(), this); } + + //! Effects: Returns a const_iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return this->cend(); } + + //! Effects: Returns a constant iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return const_iterator(uncast(this->get_root_node()), this); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rbegin() + { return reverse_iterator(this->end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rbegin() const + { return this->crbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crbegin() const + { return const_reverse_iterator(end()); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reverse_iterator rend() + { return reverse_iterator(begin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator rend() const + { return this->crend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reverse_iterator crend() const + { return const_reverse_iterator(this->begin()); } + + //! Precondition: end_iterator must be a valid end iterator + //! of list. + //! + //! Effects: Returns a const reference to the list associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static list_impl &container_from_end_iterator(iterator end_iterator) + { return list_impl::priv_container_from_end_iterator(end_iterator); } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of list. + //! + //! Effects: Returns a const reference to the list associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const list_impl &container_from_end_iterator(const_iterator end_iterator) + { return list_impl::priv_container_from_end_iterator(end_iterator); } + + //! Effects: Returns the number of the elements contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements contained in the list. + //! if constant-time size option is disabled. Constant time otherwise. + //! + //! Note: Does not affect the validity of iterators and references. + size_type size() const + { + if(constant_time_size) + return this->priv_size_traits().get_size(); + else + return node_algorithms::count(this->get_root_node()) - 1; + } + + //! Effects: Returns true if the list contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Does not affect the validity of iterators and references. + bool empty() const + { return node_algorithms::unique(this->get_root_node()); } + + //! Effects: Swaps the elements of x and *this. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Does not affect the validity of iterators and references. + void swap(list_impl& other) + { + node_algorithms::swap_nodes(this->get_root_node(), other.get_root_node()); + if(constant_time_size){ + size_type backup = this->priv_size_traits().get_size(); + this->priv_size_traits().set_size(other.priv_size_traits().get_size()); + other.priv_size_traits().set_size(backup); + } + } + + //! Effects: Moves backwards all the elements, so that the first + //! element becomes the second, the second becomes the third... + //! the last element becomes the first one. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of shifts. + //! + //! Note: Does not affect the validity of iterators and references. + void shift_backwards(size_type n = 1) + { node_algorithms::move_forward(this->get_root_node(), n); } + + //! Effects: Moves forward all the elements, so that the second + //! element becomes the first, the third becomes the second... + //! the first element becomes the last one. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of shifts. + //! + //! Note: Does not affect the validity of iterators and references. + void shift_forward(size_type n = 1) + { node_algorithms::move_backwards(this->get_root_node(), n); } + + //! Effects: Erases the element pointed by i of the list. + //! No destructors are called. + //! + //! Returns: the first element remaining beyond the removed element, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Invalidates the iterators (but not the references) to the + //! erased element. + iterator erase(iterator i) + { return this->erase_and_dispose(i, detail::null_disposer()); } + + //! Requires: b and e must be valid iterators to elements in *this. + //! + //! Effects: Erases the element range pointed by b and e + //! No destructors are called. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of erased elements if it's a safe-mode + //! or auto-unlink value, or constant-time size is enabled. Constant-time otherwise. + //! + //! Note: Invalidates the iterators (but not the references) to the + //! erased elements. + iterator erase(iterator b, iterator e) + { + if(safemode_or_autounlink || constant_time_size){ + return this->erase_and_dispose(b, e, detail::null_disposer()); + } + else{ + node_algorithms::unlink(b.pointed_node(), e.pointed_node()); + return e; + } + } + + //! Requires: b and e must be valid iterators to elements in *this. + //! n must be std::distance(b, e). + //! + //! Effects: Erases the element range pointed by b and e + //! No destructors are called. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of erased elements if it's a safe-mode + //! or auto-unlink value is enabled. Constant-time otherwise. + //! + //! Note: Invalidates the iterators (but not the references) to the + //! erased elements. + iterator erase(iterator b, iterator e, difference_type n) + { + BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(b, e) == difference_type(n)); + if(safemode_or_autounlink || constant_time_size){ + return this->erase_and_dispose(b, e, detail::null_disposer()); + } + else{ + if(constant_time_size){ + this->priv_size_traits().set_size(this->priv_size_traits().get_size() - n); + } + node_algorithms::unlink(b.pointed_node(), e.pointed_node()); + return e; + } + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element pointed by i of the list. + //! No destructors are called. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Returns: the first element remaining beyond the removed element, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Invalidates the iterators to the erased element. + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { + node_ptr to_erase(i.pointed_node()); + ++i; + node_algorithms::unlink(to_erase); + this->priv_size_traits().decrement(); + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + disposer(this->get_real_value_traits().to_value_ptr(to_erase)); + return i; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element range pointed by b and e + //! No destructors are called. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements erased. + //! + //! Note: Invalidates the iterators to the erased elements. + template + iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) + { + node_ptr bp(b.pointed_node()), ep(e.pointed_node()); + node_algorithms::unlink(bp, ep); + while(bp != ep){ + node_ptr to_erase(bp); + bp = node_traits::get_next(bp); + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + disposer(get_real_value_traits().to_value_ptr(to_erase)); + this->priv_size_traits().decrement(); + } + return e; + } + + //! Effects: Erases all the elements of the container. + //! No destructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements of the list. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Note: Invalidates the iterators (but not the references) to the erased elements. + void clear() + { + if(safemode_or_autounlink){ + this->clear_and_dispose(detail::null_disposer()); + } + else{ + node_algorithms::init_header(this->get_root_node()); + this->priv_size_traits().set_size(size_type(0)); + } + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements of the container. + //! No destructors are called. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements of the list. + //! + //! Note: Invalidates the iterators to the erased elements. + template + void clear_and_dispose(Disposer disposer) + { + iterator it(this->begin()), itend(this->end()); + while(it != itend){ + node_ptr to_erase(it.pointed_node()); + ++it; + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + disposer(get_real_value_traits().to_value_ptr(to_erase)); + } + node_algorithms::init_header(this->get_root_node()); + this->priv_size_traits().set_size(0); + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. Basic guarantee. + template + void clone_from(const list_impl &src, Cloner cloner, Disposer disposer) + { + this->clear_and_dispose(disposer); + detail::exception_disposer + rollback(*this, disposer); + const_iterator b(src.begin()), e(src.end()); + for(; b != e; ++b){ + this->push_back(*cloner(*b)); + } + rollback.release(); + } + + //! Requires: value must be an lvalue and p must be a valid iterator of *this. + //! + //! Effects: Inserts the value before the position pointed by p. + //! + //! Returns: An iterator to the inserted element. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. No copy constructors are called. + //! + //! Note: Does not affect the validity of iterators and references. + iterator insert(iterator p, reference value) + { + node_ptr to_insert = this->get_real_value_traits().to_node_ptr(value); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); + node_algorithms::link_before(p.pointed_node(), to_insert); + this->priv_size_traits().increment(); + return iterator(to_insert, this); + } + + //! Requires: Dereferencing iterator must yield + //! an lvalue of type value_type and p must be a valid iterator of *this. + //! + //! Effects: Inserts the range pointed by b and e before the position p. + //! No copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements inserted. + //! + //! Note: Does not affect the validity of iterators and references. + template + void insert(iterator p, Iterator b, Iterator e) + { + for (; b != e; ++b) + this->insert(p, *b); + } + + //! Requires: Dereferencing iterator must yield + //! an lvalue of type value_type. + //! + //! Effects: Clears the list and inserts the range pointed by b and e. + //! No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements inserted plus + //! linear to the elements contained in the list if it's a safe-mode + //! or auto-unlink value. + //! Linear to the number of elements inserted in the list otherwise. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. + template + void assign(Iterator b, Iterator e) + { + this->clear(); + this->insert(this->end(), b, e); + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Requires: Dereferencing iterator must yield + //! an lvalue of type value_type. + //! + //! Effects: Clears the list and inserts the range pointed by b and e. + //! No destructors or copy constructors are called. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements inserted plus + //! linear to the elements contained in the list. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. + template + void dispose_and_assign(Disposer disposer, Iterator b, Iterator e) + { + this->clear_and_dispose(disposer); + this->insert(this->end(), b, e); + } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Transfers all the elements of list x to this list, before the + //! the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of + //! this list. Iterators of this list and all the references are not invalidated. + void splice(iterator p, list_impl& x) + { + if(!x.empty()){ + size_traits &thist = this->priv_size_traits(); + size_traits &xt = x.priv_size_traits(); + node_algorithms::transfer + (p.pointed_node(), x.begin().pointed_node(), x.end().pointed_node()); + thist.set_size(thist.get_size() + xt.get_size()); + xt.set_size(size_type(0)); + } + } + + //! Requires: p must be a valid iterator of *this. + //! new_ele must point to an element contained in list x. + //! + //! Effects: Transfers the value pointed by new_ele, from list x to this list, + //! before the the element pointed by p. No destructors or copy constructors are called. + //! If p == new_ele or p == ++new_ele, this function is a null operation. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(iterator p, list_impl&x, iterator new_ele) + { + node_algorithms::transfer(p.pointed_node(), new_ele.pointed_node()); + x.priv_size_traits().decrement(); + this->priv_size_traits().increment(); + } + + //! Requires: p must be a valid iterator of *this. + //! start and end must point to elements contained in list x. + //! + //! Effects: Transfers the range pointed by start and end from list x to this list, + //! before the the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements transferred + //! if constant-time size option is enabled. Constant-time otherwise. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(iterator p, list_impl&x, iterator start, iterator end) + { + if(constant_time_size) + this->splice(p, x, start, end, std::distance(start, end)); + else + this->splice(p, x, start, end, 1);//distance is a dummy value + } + + //! Requires: p must be a valid iterator of *this. + //! start and end must point to elements contained in list x. + //! n == std::distance(start, end) + //! + //! Effects: Transfers the range pointed by start and end from list x to this list, + //! before the the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(iterator p, list_impl&x, iterator start, iterator end, difference_type n) + { + if(n){ + if(constant_time_size){ + size_traits &thist = this->priv_size_traits(); + size_traits &xt = x.priv_size_traits(); + BOOST_INTRUSIVE_INVARIANT_ASSERT(n == std::distance(start, end)); + node_algorithms::transfer(p.pointed_node(), start.pointed_node(), end.pointed_node()); + thist.set_size(thist.get_size() + n); + xt.set_size(xt.get_size() - n); + } + else{ + node_algorithms::transfer(p.pointed_node(), start.pointed_node(), end.pointed_node()); + } + } + } + + //! Effects: This function sorts the list *this according to std::less. + //! The sort is stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: If real_value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or std::less throws. Basic guarantee. + //! + //! Notes: Iterators and references are not invalidated. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + void sort() + { this->sort(std::less()); } + + //! Requires: p must be a comparison function that induces a strict weak ordering + //! + //! Effects: This function sorts the list *this according to p. The sort is + //! stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: If real_value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the predicate throws. Basic guarantee. + //! + //! Notes: This won't throw if list_base_hook<> or + //! list_member_hook are used. + //! Iterators and references are not invalidated. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + template + void sort(Predicate p) + { + if(node_traits::get_next(this->get_root_node()) + != node_traits::get_previous(this->get_root_node())){ + list_impl carry; + list_impl counter[64]; + int fill = 0; + while(!this->empty()){ + carry.splice(carry.begin(), *this, this->begin()); + int i = 0; + while(i < fill && !counter[i].empty()) { + carry.merge(counter[i++], p); + } + carry.swap(counter[i]); + if(i == fill) + ++fill; + } + for (int i = 1; i < fill; ++i) + counter[i].merge(counter[i-1], p); + this->swap(counter[fill-1]); + } + } + + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this according to std::less. The merge is stable; + //! that is, if an element from *this is equivalent to one from x, then the element + //! from *this will precede the one from x. + //! + //! Throws: If std::less throws. Basic guarantee. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references are not invalidated + void merge(list_impl& x) + { this->merge(x, std::less()); } + + //! Requires: p must be a comparison function that induces a strict weak + //! ordering and both *this and x must be sorted according to that ordering + //! The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this. The merge is stable; that is, if an element from *this is + //! equivalent to one from x, then the element from *this will precede the one from x. + //! + //! Throws: If the predicate throws. Basic guarantee. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references are not invalidated. + template + void merge(list_impl& x, Predicate p) + { + iterator e(this->end()); + iterator bx(x.begin()); + iterator ex(x.end()); + + for (iterator b = this->begin(); b != e; ++b) { + size_type n(0); + iterator ix(bx); + while(ix != ex && p(*ix, *b)){ + ++ix; ++n; + } + this->splice(b, x, bx, ix, n); + bx = ix; + } + //Now transfer the rest at the end of the container + this->splice(e, x); + } + + //! Effects: Reverses the order of elements in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time. + //! + //! Note: Iterators and references are not invalidated + void reverse() + { node_algorithms::reverse(this->get_root_node()); } + + //! Effects: Removes all the elements that compare equal to value. + //! No destructors are called. + //! + //! Throws: If std::equal_to throws. Basic guarantee. + //! + //! Complexity: Linear time. It performs exactly size() comparisons for equality. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + void remove(const_reference value) + { this->remove_if(detail::equal_to_value(value)); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Removes all the elements that compare equal to value. + //! Disposer::operator()(pointer) is called for every removed element. + //! + //! Throws: If std::equal_to throws. Basic guarantee. + //! + //! Complexity: Linear time. It performs exactly size() comparisons for equality. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void remove_and_dispose(const_reference value, Disposer disposer) + { this->remove_and_dispose_if(detail::equal_to_value(value), disposer); } + + //! Effects: Removes all the elements for which a specified + //! predicate is satisfied. No destructors are called. + //! + //! Throws: If pred throws. Basic guarantee. + //! + //! Complexity: Linear time. It performs exactly size() calls to the predicate. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void remove_if(Pred pred) + { this->remove_and_dispose_if(pred, detail::null_disposer()); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Removes all the elements for which a specified + //! predicate is satisfied. + //! Disposer::operator()(pointer) is called for every removed element. + //! + //! Throws: If pred throws. Basic guarantee. + //! + //! Complexity: Linear time. It performs exactly size() comparisons for equality. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void remove_and_dispose_if(Pred pred, Disposer disposer) + { + iterator cur(this->begin()); + iterator last(this->end()); + while(cur != last) { + if(pred(*cur)){ + cur = this->erase_and_dispose(cur, disposer); + } + else{ + ++cur; + } + } + } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that are equal from the list. No destructors are called. + //! + //! Throws: If std::equal_toComplexity: Linear time (size()-1 comparisons calls to pred()). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + void unique() + { this->unique_and_dispose(std::equal_to(), detail::null_disposer()); } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that satisfy some binary predicate from the list. + //! No destructors are called. + //! + //! Throws: If pred throws. Basic guarantee. + //! + //! Complexity: Linear time (size()-1 comparisons equality comparisons). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void unique(BinaryPredicate pred) + { this->unique_and_dispose(pred, detail::null_disposer()); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that are equal from the list. + //! Disposer::operator()(pointer) is called for every removed element. + //! + //! Throws: If std::equal_toComplexity: Linear time (size()-1) comparisons equality comparisons. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void unique_and_dispose(Disposer disposer) + { this->unique_and_dispose(std::equal_to(), disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that satisfy some binary predicate from the list. + //! Disposer::operator()(pointer) is called for every removed element. + //! + //! Throws: If pred throws. Basic guarantee. + //! + //! Complexity: Linear time (size()-1) comparisons equality comparisons. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void unique_and_dispose(BinaryPredicate pred, Disposer disposer) + { + iterator itend(this->end()); + iterator cur(this->begin()); + + if(cur != itend){ + iterator after(cur); + ++after; + while(after != itend){ + if(pred(*cur, *after)){ + after = this->erase_and_dispose(after, disposer); + } + else{ + cur = after; + ++after; + } + } + } + } + + //! Requires: value must be a reference to a value inserted in a list. + //! + //! Effects: This function returns a const_iterator pointing to the element + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: Iterators and references are not invalidated. + //! This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(value))); + return iterator(real_value_traits::to_node_ptr(value), 0); + } + + //! Requires: value must be a const reference to a value inserted in a list. + //! + //! Effects: This function returns an iterator pointing to the element. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: Iterators and references are not invalidated. + //! This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(const_cast (value)))); + return const_iterator(real_value_traits::to_node_ptr(const_cast (value)), 0); + } + + //! Requires: value must be a reference to a value inserted in a list. + //! + //! Effects: This function returns a const_iterator pointing to the element + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: Iterators and references are not invalidated. + iterator iterator_to(reference value) + { + BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(value))); + return iterator(real_value_traits::to_node_ptr(value), this); + } + + //! Requires: value must be a const reference to a value inserted in a list. + //! + //! Effects: This function returns an iterator pointing to the element. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: Iterators and references are not invalidated. + const_iterator iterator_to(const_reference value) const + { + BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(real_value_traits::to_node_ptr(const_cast (value)))); + return const_iterator(real_value_traits::to_node_ptr(const_cast (value)), this); + } + + /// @cond + + private: + static list_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) + { + root_plus_size *r = detail::parent_from_member + ( detail::get_pointer(end_iterator.pointed_node()), &root_plus_size::root_); + data_t *d = detail::parent_from_member + ( r, &data_t::root_plus_size_); + list_impl *s = detail::parent_from_member(d, &list_impl::data_); + return *s; + } + /// @endcond +}; + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator< +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const list_impl &x, const list_impl &y) +#else +(const list_impl &x, const list_impl &y) +#endif +{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +bool operator== +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const list_impl &x, const list_impl &y) +#else +(const list_impl &x, const list_impl &y) +#endif +{ + typedef list_impl list_type; + typedef typename list_type::const_iterator const_iterator; + const bool C = list_type::constant_time_size; + if(C && x.size() != y.size()){ + return false; + } + const_iterator end1 = x.end(); + + const_iterator i1 = x.begin(); + const_iterator i2 = y.begin(); + if(C){ + while (i1 != end1 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1; + } + else{ + const_iterator end2 = y.end(); + while (i1 != end1 && i2 != end2 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1 && i2 == end2; + } +} + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator!= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const list_impl &x, const list_impl &y) +#else +(const list_impl &x, const list_impl &y) +#endif +{ return !(x == y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator> +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const list_impl &x, const list_impl &y) +#else +(const list_impl &x, const list_impl &y) +#endif +{ return y < x; } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator<= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const list_impl &x, const list_impl &y) +#else +(const list_impl &x, const list_impl &y) +#endif +{ return !(y < x); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator>= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const list_impl &x, const list_impl &y) +#else +(const list_impl &x, const list_impl &y) +#endif +{ return !(x < y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline void swap +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(list_impl &x, list_impl &y) +#else +(list_impl &x, list_impl &y) +#endif +{ x.swap(y); } + +//! Helper metafunction to define a \c list that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_list +{ + /// @cond + typedef typename pack_options + < list_defaults, O1, O2, O3>::type packed_options; + typedef typename detail::get_value_traits + ::type value_traits; + + typedef list_impl + < + listopt + < value_traits + , typename packed_options::size_type + , packed_options::constant_time_size + > + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class list + : public make_list::type +{ + typedef typename make_list + ::type Base; + typedef typename Base::real_value_traits real_value_traits; + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + public: + typedef typename Base::value_traits value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + list(const value_traits &v_traits = value_traits()) + : Base(v_traits) + {} + + template + list(Iterator b, Iterator e, const value_traits &v_traits = value_traits()) + : Base(b, e, v_traits) + {} + + static list &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const list &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } +}; + +#endif + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_LIST_HPP diff --git a/win32/include/boost/intrusive/list_hook.hpp b/win32/include/boost/intrusive/list_hook.hpp new file mode 100755 index 000000000..e43aa6fdd --- /dev/null +++ b/win32/include/boost/intrusive/list_hook.hpp @@ -0,0 +1,264 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_LIST_HOOK_HPP +#define BOOST_INTRUSIVE_LIST_HOOK_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond +template +struct get_list_node_algo +{ + typedef circular_list_algorithms > type; +}; +/// @endcond + +//! Helper metafunction to define a \c \c list_base_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_list_base_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3>::type packed_options; + + typedef detail::generic_hook + < get_list_node_algo + , typename packed_options::tag + , packed_options::link_mode + , detail::ListBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Derive a class from this hook in order to store objects of that class +//! in an list. +//! +//! The hook admits the following options: \c tag<>, \c void_pointer<> and +//! \c link_mode<>. +//! +//! \c tag<> defines a tag to identify the node. +//! The same tag value can be used in different classes, but if a class is +//! derived from more than one \c list_base_hook, then each \c list_base_hook needs its +//! unique tag. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, +//! \c auto_unlink or \c safe_link). +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class list_base_hook + : public make_list_base_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + list_base_hook(); + + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + list_base_hook(const list_base_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + list_base_hook& operator=(const list_base_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in an list an assertion is raised. If link_mode is + //! \c auto_unlink and \c is_linked() is true, the node is unlinked. + //! + //! Throws: Nothing. + ~list_base_hook(); + + //! Effects: Swapping two nodes swaps the position of the elements + //! related to those nodes in one or two containers. That is, if the node + //! this is part of the element e1, the node x is part of the element e2 + //! and both elements are included in the containers s1 and s2, then after + //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 + //! at the position of e1. If one element is not in a container, then + //! after the swap-operation the other element is not in a container. + //! Iterators to e1 and e2 related to those nodes are invalidated. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + void swap_nodes(list_base_hook &other); + + //! Precondition: link_mode must be \c safe_link or \c auto_unlink. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c list::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + + //! Effects: Removes the node if it's inserted in a container. + //! This function is only allowed if link_mode is \c auto_unlink. + //! + //! Throws: Nothing. + void unlink(); + #endif +}; + +//! Helper metafunction to define a \c \c list_member_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_list_member_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3>::type packed_options; + + typedef detail::generic_hook + < get_list_node_algo + , member_tag + , packed_options::link_mode + , detail::NoBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Store this hook in a class to be inserted +//! in an list. +//! +//! The hook admits the following options: \c void_pointer<> and +//! \c link_mode<>. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, +//! \c auto_unlink or \c safe_link). +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class list_member_hook + : public make_list_member_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + list_member_hook(); + + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + list_member_hook(const list_member_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + list_member_hook& operator=(const list_member_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in an list an assertion is raised. If link_mode is + //! \c auto_unlink and \c is_linked() is true, the node is unlinked. + //! + //! Throws: Nothing. + ~list_member_hook(); + + //! Effects: Swapping two nodes swaps the position of the elements + //! related to those nodes in one or two containers. That is, if the node + //! this is part of the element e1, the node x is part of the element e2 + //! and both elements are included in the containers s1 and s2, then after + //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 + //! at the position of e1. If one element is not in a container, then + //! after the swap-operation the other element is not in a container. + //! Iterators to e1 and e2 related to those nodes are invalidated. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + void swap_nodes(list_member_hook &other); + + //! Precondition: link_mode must be \c safe_link or \c auto_unlink. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c list::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + + //! Effects: Removes the node if it's inserted in a container. + //! This function is only allowed if link_mode is \c auto_unlink. + //! + //! Throws: Nothing. + void unlink(); + #endif +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_LIST_HOOK_HPP diff --git a/win32/include/boost/intrusive/member_value_traits.hpp b/win32/include/boost/intrusive/member_value_traits.hpp new file mode 100755 index 000000000..8d90b67a1 --- /dev/null +++ b/win32/include/boost/intrusive/member_value_traits.hpp @@ -0,0 +1,65 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_MEMBER_VALUE_TRAITS_HPP +#define BOOST_INTRUSIVE_MEMBER_VALUE_TRAITS_HPP + +#include +#include +#include + +namespace boost { +namespace intrusive { + +//!This value traits template is used to create value traits +//!from user defined node traits where value_traits::value_type will +//!store a node_traits::node +template< class T, class NodeTraits + , typename NodeTraits::node T::* PtrToMember + , link_mode_type LinkMode = safe_link> +struct member_value_traits +{ + public: + typedef NodeTraits node_traits; + typedef T value_type; + typedef typename node_traits::node node; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef typename boost::pointer_to_other::type pointer; + typedef typename boost::pointer_to_other::type const_pointer; + typedef typename std::iterator_traits::reference reference; + typedef typename std::iterator_traits::reference const_reference; + static const link_mode_type link_mode = LinkMode; + + static node_ptr to_node_ptr(reference value) + { return node_ptr(&(value.*PtrToMember)); } + + static const_node_ptr to_node_ptr(const_reference value) + { return node_ptr(&(value.*PtrToMember)); } + + static pointer to_value_ptr(node_ptr n) + { + return pointer(detail::parent_from_member + (detail::get_pointer(n), PtrToMember)); + } + + static const_pointer to_value_ptr(const_node_ptr n) + { + return pointer(detail::parent_from_member + (detail::get_pointer(n), PtrToMember)); + } +}; + +} //namespace intrusive +} //namespace boost + +#endif //BOOST_INTRUSIVE_MEMBER_VALUE_TRAITS_HPP diff --git a/win32/include/boost/intrusive/options.hpp b/win32/include/boost/intrusive/options.hpp new file mode 100755 index 000000000..f143f0a8f --- /dev/null +++ b/win32/include/boost/intrusive/options.hpp @@ -0,0 +1,600 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_OPTIONS_HPP +#define BOOST_INTRUSIVE_OPTIONS_HPP + +#include +#include +#include +#include +#include +#include + + +namespace boost { +namespace intrusive { + +/// @cond + +struct default_tag; +struct member_tag; + +namespace detail{ + +template +struct eval_value_traits +{ + typedef typename ValueTraits::value_traits type; +}; + +template +struct external_bucket_traits_is_true +{ + static const bool value = external_bucket_traits_bool::value == 3; +}; + +template +struct eval_bucket_traits +{ + typedef typename BucketTraits::bucket_traits type; +}; + +template +struct concrete_hook_base_value_traits +{ + typedef typename BaseHook::boost_intrusive_tags tags; + typedef detail::base_hook_traits + < T + , typename tags::node_traits + , tags::link_mode + , typename tags::tag + , tags::hook_type> type; +}; + +template +struct concrete_hook_base_node_traits +{ typedef typename BaseHook::boost_intrusive_tags::node_traits type; }; + +template +struct any_hook_base_value_traits +{ + typedef typename BaseHook::boost_intrusive_tags tags; + typedef detail::base_hook_traits + < T + , typename BaseHook::node_traits + , tags::link_mode + , typename tags::tag + , tags::hook_type> type; +}; + +template +struct any_hook_base_node_traits +{ typedef typename BaseHook::node_traits type; }; + +template +struct get_base_value_traits +{ + typedef typename detail::eval_if_c + < internal_any_hook_bool_is_true::value + , any_hook_base_value_traits + , concrete_hook_base_value_traits + >::type type; +}; + +template +struct get_base_node_traits +{ + typedef typename detail::eval_if_c + < internal_any_hook_bool_is_true::value + , any_hook_base_node_traits + , concrete_hook_base_node_traits + >::type type; +}; + +template +struct get_member_value_traits +{ + typedef typename MemberHook::member_value_traits type; +}; + +template +struct get_member_node_traits +{ + typedef typename MemberHook::member_value_traits::node_traits type; +}; + +template +struct get_value_traits +{ + typedef SupposedValueTraits supposed_value_traits; + //...if it's a base hook + typedef typename detail::eval_if_c + < internal_base_hook_bool_is_true::value + //...get it's internal value traits using + //the provided T value type. + , get_base_value_traits + //...else use it's internal value traits tag + //(member hooks and custom value traits are in this group) + , detail::eval_if_c + < internal_member_value_traits::value + , get_member_value_traits + , detail::identity + > + >::type type; +}; + +template +struct get_explicit_node_traits +{ + typedef typename ValueTraits::node_traits type; +}; + +template +struct get_node_traits +{ + typedef SupposedValueTraits supposed_value_traits; + //...if it's a base hook + typedef typename detail::eval_if_c + < internal_base_hook_bool_is_true::value + //...get it's internal value traits using + //the provided T value type. + , get_base_node_traits + //...else use it's internal value traits tag + //(member hooks and custom value traits are in this group) + , detail::eval_if_c + < internal_member_value_traits::value + , get_member_node_traits + , get_explicit_node_traits + > + >::type type; +}; + +} //namespace detail{ + + +//!This type indicates that no option is being used +//!and that the default options should be used +struct none +{ + template + struct pack : Base + { }; +}; + +/// @endcond + +//!This option setter specifies if the intrusive +//!container stores its size as a member to +//!obtain constant-time size() member. +template +struct constant_time_size +{ +/// @cond + template + struct pack : Base + { + static const bool constant_time_size = Enabled; + }; +/// @endcond +}; + +//!This option setter specifies the type that +//!the container will use to store its size. +template +struct size_type +{ +/// @cond + template + struct pack : Base + { + typedef SizeType size_type; + }; +/// @endcond +}; + +//!This option setter specifies the strict weak ordering +//!comparison functor for the value type +template +struct compare +{ +/// @cond + template + struct pack : Base + { + typedef Compare compare; + }; +/// @endcond +}; + +//!This option setter for scapegoat containers specifies if +//!the intrusive scapegoat container should use a non-variable +//!alpha value that does not need floating-point operations. +//! +//!If activated, the fixed alpha value is 1/sqrt(2). This +//!option also saves some space in the container since +//!the alpha value and some additional data does not need +//!to be stored in the container. +//! +//!If the user only needs an alpha value near 1/sqrt(2), this +//!option also improves performance since avoids logarithm +//!and division operations when rebalancing the tree. +template +struct floating_point +{ +/// @cond + template + struct pack : Base + { + static const bool floating_point = Enabled; + }; +/// @endcond +}; + +//!This option setter specifies the equality +//!functor for the value type +template +struct equal +{ +/// @cond + template + struct pack : Base + { + typedef Equal equal; + }; +/// @endcond +}; + +//!This option setter specifies the hash +//!functor for the value type +template +struct hash +{ +/// @cond + template + struct pack : Base + { + typedef Hash hash; + }; +/// @endcond +}; + +//!This option setter specifies the relationship between the type +//!to be managed by the container (the value type) and the node to be +//!used in the node algorithms. It also specifies the linking policy. +template +struct value_traits +{ +/// @cond + template + struct pack : Base + { + typedef ValueTraits value_traits; + }; +/// @endcond +}; + +//!This option setter specifies the member hook the +//!container must use. +template< typename Parent + , typename MemberHook + , MemberHook Parent::* PtrToMember> +struct member_hook +{ +/// @cond + typedef detail::member_hook_traits + < Parent + , MemberHook + , PtrToMember + > member_value_traits; + template + struct pack : Base + { + typedef member_value_traits value_traits; + }; +/// @endcond +}; + + +//!This option setter specifies that the container +//!must use the specified base hook +template +struct base_hook +{ +/// @cond + template + struct pack : Base + { + typedef BaseHook value_traits; + }; +/// @endcond +}; + +//!This option setter specifies the type of +//!a void pointer. This will instruct the hook +//!to use this type of pointer instead of the +//!default one +template +struct void_pointer +{ +/// @cond + template + struct pack : Base + { + typedef VoidPointer void_pointer; + }; +/// @endcond +}; + +//!This option setter specifies the type of +//!the tag of a base hook. A type can not have two +//!base hooks of the same type, so a tag can be used +//!to differentiate two base hooks with otherwise same type +template +struct tag +{ +/// @cond + template + struct pack : Base + { + typedef Tag tag; + }; +/// @endcond +}; + +//!This option setter specifies the link mode +//!(normal_link, safe_link or auto_unlink) +template +struct link_mode +{ +/// @cond + template + struct pack : Base + { + static const link_mode_type link_mode = LinkType; + }; +/// @endcond +}; + +//!This option setter specifies if the hook +//!should be optimized for size instead of for speed. +template +struct optimize_size +{ +/// @cond + template + struct pack : Base + { + static const bool optimize_size = Enabled; + }; +/// @endcond +}; + +//!This option setter specifies if the list container should +//!use a linear implementation instead of a circular one. +template +struct linear +{ +/// @cond + template + struct pack : Base + { + static const bool linear = Enabled; + }; +/// @endcond +}; + +//!This option setter specifies if the list container should +//!use a linear implementation instead of a circular one. +template +struct cache_last +{ +/// @cond + template + struct pack : Base + { + static const bool cache_last = Enabled; + }; +/// @endcond +}; + +//!This option setter specifies the bucket traits +//!class for unordered associative containers. When this option is specified, +//!instead of using the default bucket traits, a user defined holder will be defined +template +struct bucket_traits +{ +/// @cond + template + struct pack : Base + { + typedef BucketTraits bucket_traits; + }; +/// @endcond +}; + +//!This option setter specifies if the unordered hook +//!should offer room to store the hash value. +//!Storing the hash in the hook will speed up rehashing +//!processes in applications where rehashing is frequent, +//!rehashing might throw or the value is heavy to hash. +template +struct store_hash +{ +/// @cond + template + struct pack : Base + { + static const bool store_hash = Enabled; + }; +/// @endcond +}; + +//!This option setter specifies if the unordered hook +//!should offer room to store another link to another node +//!with the same key. +//!Storing this link will speed up lookups and insertions on +//!unordered_multiset containers with a great number of elements +//!with the same key. +template +struct optimize_multikey +{ +/// @cond + template + struct pack : Base + { + static const bool optimize_multikey = Enabled; + }; +/// @endcond +}; + +//!This option setter specifies if the bucket array will be always power of two. +//!This allows using masks instead of the default modulo operation to determine +//!the bucket number from the hash value, leading to better performance. +//!In debug mode, if power of two buckets mode is activated, the bucket length +//!will be checked to through assertions to assure the bucket length is power of two. +template +struct power_2_buckets +{ +/// @cond + template + struct pack : Base + { + static const bool power_2_buckets = Enabled; + }; +/// @endcond +}; + +//!This option setter specifies if the container will cache a pointer to the first +//!non-empty bucket so that begin() is always constant-time. +//!This is specially helpful when we can have containers with a few elements +//!but with big bucket arrays (that is, hashtables with low load factors). +template +struct cache_begin +{ +/// @cond + template + struct pack : Base + { + static const bool cache_begin = Enabled; + }; +/// @endcond +}; + + +//!This option setter specifies if the container will compare the hash value +//!before comparing objects. This option can't be specified if store_hash<> +//!is not true. +//!This is specially helpful when we have containers with a high load factor. +//!and the comparison function is much more expensive that comparing already +//!stored hash values. +template +struct compare_hash +{ +/// @cond + template + struct pack : Base + { + static const bool compare_hash = Enabled; + }; +/// @endcond +}; + +/// @cond + +template +struct do_pack +{ + //Use "pack" member template to pack options + typedef typename Next::template pack type; +}; + +template +struct do_pack +{ + //Avoid packing "none" to shorten template names + typedef Prev type; +}; + + +template + < class DefaultOptions + , class O1 = none + , class O2 = none + , class O3 = none + , class O4 = none + , class O5 = none + , class O6 = none + , class O7 = none + , class O8 = none + , class O9 = none + , class Option10 = none + > +struct pack_options +{ + // join options + typedef + typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < typename do_pack + < DefaultOptions + , O1 + >::type + , O2 + >::type + , O3 + >::type + , O4 + >::type + , O5 + >::type + , O6 + >::type + , O7 + >::type + , O8 + >::type + , O9 + >::type + , Option10 + >::type + type; +}; + +struct hook_defaults + : public pack_options + < none + , void_pointer + , link_mode + , tag + , optimize_size + , store_hash + , linear + , optimize_multikey + >::type +{}; + +/// @endcond + +} //namespace intrusive { +} //namespace boost { + +#include + +#endif //#ifndef BOOST_INTRUSIVE_OPTIONS_HPP diff --git a/win32/include/boost/intrusive/pointer_plus_bits.hpp b/win32/include/boost/intrusive/pointer_plus_bits.hpp new file mode 100755 index 000000000..e50d52bd2 --- /dev/null +++ b/win32/include/boost/intrusive/pointer_plus_bits.hpp @@ -0,0 +1,81 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP +#define BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP + +#include //ls_zeros + +namespace boost { +namespace intrusive { + +//!This trait class is used to know if a pointer +//!can embed extra bits of information if +//!it's going to be used to point to objects +//!with an alignment of "Alignment" bytes. +template +struct max_pointer_plus_bits +{ + static const std::size_t value = 0; +}; + +//!This is an specialization for raw pointers. +//!Raw pointers can embed extra bits in the lower bits +//!if the alignment is multiple of 2pow(NumBits). +template +struct max_pointer_plus_bits +{ + static const std::size_t value = detail::ls_zeros::value; +}; + +//!This is class that is supposed to have static methods +//!to embed extra bits of information in a pointer. +//!This is a declaration and there is no default implementation, +//!because operations to embed the bits change with every pointer type. +//! +//!An implementation that detects that a pointer type whose +//!has_pointer_plus_bits<>::value is non-zero can make use of these +//!operations to embed the bits in the pointer. +template +struct pointer_plus_bits; + +//!This is the specialization to embed extra bits of information +//!in a raw pointer. The extra bits are stored in the lower bit of the pointer. +template +struct pointer_plus_bits +{ + static const std::size_t Mask = ((std::size_t(1u) << NumBits) - 1); + typedef T* pointer; + + static pointer get_pointer(pointer n) + { return pointer(std::size_t(n) & ~Mask); } + + static void set_pointer(pointer &n, pointer p) + { + assert(0 == (std::size_t(p) & Mask)); + n = pointer(std::size_t(p) | (std::size_t(n) & Mask)); + } + + static std::size_t get_bits(pointer n) + { return (std::size_t(n) & Mask); } + + static void set_bits(pointer &n, std::size_t c) + { + assert(c <= Mask); + n = pointer(std::size_t(get_pointer(n)) | c); + } +}; + +} //namespace intrusive +} //namespace boost + +#endif //BOOST_INTRUSIVE_POINTER_PLUS_BITS_HPP diff --git a/win32/include/boost/intrusive/rbtree.hpp b/win32/include/boost/intrusive/rbtree.hpp new file mode 100755 index 000000000..abd747b72 --- /dev/null +++ b/win32/include/boost/intrusive/rbtree.hpp @@ -0,0 +1,1463 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_RBTREE_HPP +#define BOOST_INTRUSIVE_RBTREE_HPP + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond + +template +struct internal_default_set_hook +{ + template static detail::one test(...); + template static detail::two test(typename U::default_set_hook* = 0); + static const bool value = sizeof(test(0)) == sizeof(detail::two); +}; + +template +struct get_default_set_hook +{ + typedef typename T::default_set_hook type; +}; + +template +struct setopt +{ + typedef ValueTraits value_traits; + typedef Compare compare; + typedef SizeType size_type; + static const bool constant_time_size = ConstantTimeSize; +}; + +template +struct set_defaults + : pack_options + < none + , base_hook + < typename detail::eval_if_c + < internal_default_set_hook::value + , get_default_set_hook + , detail::identity + >::type + > + , constant_time_size + , size_type + , compare > + >::type +{}; + +/// @endcond + +//! The class template rbtree is an intrusive red-black tree container, that +//! is used to construct intrusive set and multiset containers. The no-throw +//! guarantee holds only, if the value_compare object +//! doesn't throw. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<> and +//! \c compare<>. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class rbtree_impl +{ + public: + typedef typename Config::value_traits value_traits; + /// @cond + static const bool external_value_traits = + detail::external_value_traits_is_true::value; + typedef typename detail::eval_if_c + < external_value_traits + , detail::eval_value_traits + , detail::identity + >::type real_value_traits; + /// @endcond + typedef typename real_value_traits::pointer pointer; + typedef typename real_value_traits::const_pointer const_pointer; + typedef typename std::iterator_traits::value_type value_type; + typedef value_type key_type; + typedef typename std::iterator_traits::reference reference; + typedef typename std::iterator_traits::reference const_reference; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename Config::size_type size_type; + typedef typename Config::compare value_compare; + typedef value_compare key_compare; + typedef tree_iterator iterator; + typedef tree_iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef typename real_value_traits::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + typedef rbtree_algorithms node_algorithms; + + static const bool constant_time_size = Config::constant_time_size; + static const bool stateful_value_traits = detail::store_cont_ptr_on_it::value; + + /// @cond + private: + typedef detail::size_holder size_traits; + + //noncopyable + rbtree_impl (const rbtree_impl&); + rbtree_impl operator =(const rbtree_impl&); + + enum { safemode_or_autounlink = + (int)real_value_traits::link_mode == (int)auto_unlink || + (int)real_value_traits::link_mode == (int)safe_link }; + + //Constant-time size is incompatible with auto-unlink hooks! + BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); + + struct header_plus_size : public size_traits + { node header_; }; + + struct node_plus_pred_t : public detail::ebo_functor_holder + { + node_plus_pred_t(const value_compare &comp) + : detail::ebo_functor_holder(comp) + {} + header_plus_size header_plus_size_; + }; + + struct data_t : public rbtree_impl::value_traits + { + typedef typename rbtree_impl::value_traits value_traits; + data_t(const value_compare & comp, const value_traits &val_traits) + : value_traits(val_traits), node_plus_pred_(comp) + {} + node_plus_pred_t node_plus_pred_; + } data_; + + const value_compare &priv_comp() const + { return data_.node_plus_pred_.get(); } + + value_compare &priv_comp() + { return data_.node_plus_pred_.get(); } + + const node &priv_header() const + { return data_.node_plus_pred_.header_plus_size_.header_; } + + node &priv_header() + { return data_.node_plus_pred_.header_plus_size_.header_; } + + static node_ptr uncast(const_node_ptr ptr) + { + return node_ptr(const_cast(detail::get_pointer(ptr))); + } + + size_traits &priv_size_traits() + { return data_.node_plus_pred_.header_plus_size_; } + + const size_traits &priv_size_traits() const + { return data_.node_plus_pred_.header_plus_size_; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return data_; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return data_.get_value_traits(*this); } + + real_value_traits &get_real_value_traits(detail::bool_) + { return data_; } + + real_value_traits &get_real_value_traits(detail::bool_) + { return data_.get_value_traits(*this); } + + /// @endcond + + public: + + const real_value_traits &get_real_value_traits() const + { return this->get_real_value_traits(detail::bool_()); } + + real_value_traits &get_real_value_traits() + { return this->get_real_value_traits(detail::bool_()); } + + typedef typename node_algorithms::insert_commit_data insert_commit_data; + + //! Effects: Constructs an empty tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing unless the copy constructor of the value_compare object throws. + rbtree_impl( value_compare cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : data_(cmp, v_traits) + { + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(size_type(0)); + } + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! cmp must be a comparison function that induces a strict weak ordering. + //! + //! Effects: Constructs an empty tree and inserts elements from + //! [b, e). + //! + //! Complexity: Linear in N if [b, e) is already sorted using + //! comp and otherwise N * log N, where N is the distance between first and last. + //! + //! Throws: Nothing unless the copy constructor of the value_compare object throws. + template + rbtree_impl( bool unique, Iterator b, Iterator e + , value_compare cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : data_(cmp, v_traits) + { + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(size_type(0)); + if(unique) + this->insert_unique(b, e); + else + this->insert_equal(b, e); + } + + //! Effects: Detaches all elements from this. The objects in the set + //! are not deleted (i.e. no destructors are called), but the nodes according to + //! the value_traits template parameter are reinitialized and thus can be reused. + //! + //! Complexity: Linear to elements contained in *this. + //! + //! Throws: Nothing. + ~rbtree_impl() + { this->clear(); } + + //! Effects: Returns an iterator pointing to the beginning of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator begin() + { return iterator (node_traits::get_left(node_ptr(&priv_header())), this); } + + //! Effects: Returns a const_iterator pointing to the beginning of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator begin() const + { return cbegin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cbegin() const + { return const_iterator (node_traits::get_left(const_node_ptr(&priv_header())), this); } + + //! Effects: Returns an iterator pointing to the end of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return iterator (node_ptr(&priv_header()), this); } + + //! Effects: Returns a const_iterator pointing to the end of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return cend(); } + + //! Effects: Returns a const_iterator pointing to the end of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return const_iterator (uncast(const_node_ptr(&priv_header())), this); } + + //! Effects: Returns a reverse_iterator pointing to the beginning of the + //! reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rbegin() + { return reverse_iterator(end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rbegin() const + { return const_reverse_iterator(end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crbegin() const + { return const_reverse_iterator(end()); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rend() + { return reverse_iterator(begin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rend() const + { return const_reverse_iterator(begin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crend() const + { return const_reverse_iterator(begin()); } + + //! Precondition: end_iterator must be a valid end iterator + //! of rbtree. + //! + //! Effects: Returns a const reference to the rbtree associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static rbtree_impl &container_from_end_iterator(iterator end_iterator) + { return priv_container_from_end_iterator(end_iterator); } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of rbtree. + //! + //! Effects: Returns a const reference to the rbtree associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const rbtree_impl &container_from_end_iterator(const_iterator end_iterator) + { return priv_container_from_end_iterator(end_iterator); } + + //! Precondition: it must be a valid iterator + //! of rbtree. + //! + //! Effects: Returns a const reference to the tree associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static rbtree_impl &container_from_iterator(iterator it) + { return priv_container_from_iterator(it); } + + //! Precondition: it must be a valid end const_iterator + //! of rbtree. + //! + //! Effects: Returns a const reference to the tree associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static const rbtree_impl &container_from_iterator(const_iterator it) + { return priv_container_from_iterator(it); } + + //! Effects: Returns the value_compare object used by the tree. + //! + //! Complexity: Constant. + //! + //! Throws: If value_compare copy-constructor throws. + value_compare value_comp() const + { return priv_comp(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bool empty() const + { return node_algorithms::unique(const_node_ptr(&priv_header())); } + + //! Effects: Returns the number of elements stored in the tree. + //! + //! Complexity: Linear to elements contained in *this. + //! + //! Throws: Nothing. + size_type size() const + { + if(constant_time_size) + return this->priv_size_traits().get_size(); + else{ + return (size_type)node_algorithms::size(const_node_ptr(&priv_header())); + } + } + + //! Effects: Swaps the contents of two multisets. + //! + //! Complexity: Constant. + //! + //! Throws: If the comparison functor's swap call throws. + void swap(rbtree_impl& other) + { + //This can throw + using std::swap; + swap(priv_comp(), priv_comp()); + //These can't throw + node_algorithms::swap_tree(node_ptr(&priv_header()), node_ptr(&other.priv_header())); + if(constant_time_size){ + size_type backup = this->priv_size_traits().get_size(); + this->priv_size_traits().set_size(other.priv_size_traits().get_size()); + other.priv_size_traits().set_size(backup); + } + } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the tree before the upper bound. + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_equal(reference value) + { + detail::key_nodeptr_comp + key_node_comp(priv_comp(), this); + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + return iterator(node_algorithms::insert_equal_upper_bound + (node_ptr(&priv_header()), to_insert, key_node_comp), this); + } + + //! Requires: value must be an lvalue, and "hint" must be + //! a valid iterator. + //! + //! Effects: Inserts x into the tree, using "hint" as a hint to + //! where it will be inserted. If "hint" is the upper_bound + //! the insertion takes constant time (two comparisons in the worst case) + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_equal(const_iterator hint, reference value) + { + detail::key_nodeptr_comp + key_node_comp(priv_comp(), this); + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + return iterator(node_algorithms::insert_equal + (node_ptr(&priv_header()), hint.pointed_node(), to_insert, key_node_comp), this); + } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Inserts a each element of a range into the tree + //! before the upper bound of the key of each element. + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert_equal(Iterator b, Iterator e) + { + iterator end(this->end()); + for (; b != e; ++b) + this->insert_equal(end, *b); + } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the tree if the value + //! is not already present. + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + std::pair insert_unique(reference value) + { + insert_commit_data commit_data; + std::pair ret = insert_unique_check(value, commit_data); + if(!ret.second) + return ret; + return std::pair (insert_unique_commit(value, commit_data), true); + } + + //! Requires: value must be an lvalue, and "hint" must be + //! a valid iterator + //! + //! Effects: Tries to insert x into the tree, using "hint" as a hint + //! to where it will be inserted. + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time (two comparisons in the worst case) + //! if t is inserted immediately before hint. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_unique(const_iterator hint, reference value) + { + insert_commit_data commit_data; + std::pair ret = insert_unique_check(hint, value, commit_data); + if(!ret.second) + return ret.first; + return insert_unique_commit(value, commit_data); + } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Tries to insert each element of a range into the tree. + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert_unique(Iterator b, Iterator e) + { + if(this->empty()){ + iterator end(this->end()); + for (; b != e; ++b) + this->insert_unique(end, *b); + } + else{ + for (; b != e; ++b) + this->insert_unique(*b); + } + } + + std::pair insert_unique_check + (const_reference value, insert_commit_data &commit_data) + { return insert_unique_check(value, priv_comp(), commit_data); } + + template + std::pair insert_unique_check + (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { + detail::key_nodeptr_comp + comp(key_value_comp, this); + std::pair ret = + (node_algorithms::insert_unique_check + (node_ptr(&priv_header()), key, comp, commit_data)); + return std::pair(iterator(ret.first, this), ret.second); + } + + std::pair insert_unique_check + (const_iterator hint, const_reference value, insert_commit_data &commit_data) + { return insert_unique_check(hint, value, priv_comp(), commit_data); } + + template + std::pair insert_unique_check + (const_iterator hint, const KeyType &key + ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { + detail::key_nodeptr_comp + comp(key_value_comp, this); + std::pair ret = + (node_algorithms::insert_unique_check + (node_ptr(&priv_header()), hint.pointed_node(), key, comp, commit_data)); + return std::pair(iterator(ret.first, this), ret.second); + } + + iterator insert_unique_commit(reference value, const insert_commit_data &commit_data) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + node_algorithms::insert_unique_commit + (node_ptr(&priv_header()), to_insert, commit_data); + return iterator(to_insert, this); + } + + //! Effects: Erases the element pointed to by pos. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator i) + { + iterator ret(i); + ++ret; + node_ptr to_erase(i.pointed_node()); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase)); + node_algorithms::erase(&priv_header(), to_erase); + this->priv_size_traits().decrement(); + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + return ret; + } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator b, iterator e) + { size_type n; return private_erase(b, e, n); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return this->erase(value, priv_comp()); } + + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyValueCompare comp) + { + std::pair p = this->equal_range(key, comp); + size_type n; + private_erase(p.first, p.second, n); + return n; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element pointed to by pos. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { + node_ptr to_erase(i.pointed_node()); + iterator ret(this->erase(i)); + disposer(get_real_value_traits().to_value_ptr(to_erase)); + return ret; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) + { size_type n; return private_erase(b, e, n, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { + std::pair p = this->equal_range(value); + size_type n; + private_erase(p.first, p.second, n, disposer); + return n; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) + { + std::pair p = this->equal_range(key, comp); + size_type n; + private_erase(p.first, p.second, n, disposer); + return n; + } + + //! Effects: Erases all of the elements. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { + if(safemode_or_autounlink){ + this->clear_and_dispose(detail::null_disposer()); + } + else{ + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(0); + } + } + + //! Effects: Erases all of the elements calling disposer(p) for + //! each node to be erased. + //! Complexity: Average complexity for is at most O(log(size() + N)), + //! where N is the number of elements in the container. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. Calls N times to disposer functor. + template + void clear_and_dispose(Disposer disposer) + { + node_algorithms::clear_and_dispose(node_ptr(&priv_header()) + , detail::node_disposer(disposer, this)); + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(0); + } + + //! Effects: Returns the number of contained elements with the given value + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given value. + //! + //! Throws: Nothing. + size_type count(const_reference value) const + { return this->count(value, priv_comp()); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: Nothing. + template + size_type count(const KeyType &key, KeyValueCompare comp) const + { + std::pair ret = this->equal_range(key, comp); + return std::distance(ret.first, ret.second); + } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + iterator lower_bound(const_reference value) + { return this->lower_bound(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator lower_bound(const_reference value) const + { return this->lower_bound(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + iterator lower_bound(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return iterator(node_algorithms::lower_bound + (const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Returns a const iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return const_iterator(node_algorithms::lower_bound + (const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + iterator upper_bound(const_reference value) + { return this->upper_bound(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k according to comp or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + iterator upper_bound(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return iterator(node_algorithms::upper_bound + (const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator upper_bound(const_reference value) const + { return this->upper_bound(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k according to comp or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return const_iterator(node_algorithms::upper_bound + (const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Finds an iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + iterator find(const_reference value) + { return this->find(value, priv_comp()); } + + //! Effects: Finds an iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + iterator find(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return iterator + (node_algorithms::find(const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Finds a const_iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator find(const_reference value) const + { return this->find(value, priv_comp()); } + + //! Effects: Finds a const_iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator find(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return const_iterator + (node_algorithms::find(const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + std::pair equal_range(const_reference value) + { return this->equal_range(value, priv_comp()); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + std::pair equal_range(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + std::pair ret + (node_algorithms::equal_range(const_node_ptr(&priv_header()), key, key_node_comp)); + return std::pair(iterator(ret.first, this), iterator(ret.second, this)); + } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + std::pair + equal_range(const_reference value) const + { return this->equal_range(value, priv_comp()); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + std::pair + equal_range(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + std::pair ret + (node_algorithms::equal_range(const_node_ptr(&priv_header()), key, key_node_comp)); + return std::pair(const_iterator(ret.first, this), const_iterator(ret.second, this)); + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. + template + void clone_from(const rbtree_impl &src, Cloner cloner, Disposer disposer) + { + this->clear_and_dispose(disposer); + if(!src.empty()){ + node_algorithms::clone + (const_node_ptr(&src.priv_header()) + ,node_ptr(&this->priv_header()) + ,detail::node_cloner(cloner, this) + ,detail::node_disposer(disposer, this)); + this->priv_size_traits().set_size(src.priv_size_traits().get_size()); + } + } + + //! Effects: Unlinks the leftmost node from the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + pointer unlink_leftmost_without_rebalance() + { + node_ptr to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance + (node_ptr(&priv_header()))); + if(!to_be_disposed) + return 0; + this->priv_size_traits().decrement(); + if(safemode_or_autounlink)//If this is commented does not work with normal_link + node_algorithms::init(to_be_disposed); + return get_real_value_traits().to_value_ptr(to_be_disposed); + } + + //! Requires: replace_this must be a valid iterator of *this + //! and with_this must not be inserted in any tree. + //! + //! Effects: Replaces replace_this in its position in the + //! tree with with_this. The tree does not need to be rebalanced. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! with_this is not equivalent to *replace_this according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + void replace_node(iterator replace_this, reference with_this) + { + node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this) + , node_ptr(&priv_header()) + , get_real_value_traits().to_node_ptr(with_this)); + } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + return iterator (value_traits::to_node_ptr(value), 0); + } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), 0); + } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator iterator_to(reference value) + { return iterator (value_traits::to_node_ptr(value), this); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator iterator_to(const_reference value) const + { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this); } + + //! Requires: value shall not be in a tree. + //! + //! Effects: init_node puts the hook of a value in a well-known default + //! state. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This function puts the hook in the well-known default state + //! used by auto_unlink and safe hooks. + static void init_node(reference value) + { node_algorithms::init(value_traits::to_node_ptr(value)); } + + //! Effects: removes "value" from the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic time. + //! + //! Note: This static function is only usable with non-constant + //! time size containers that have stateless comparison functors. + //! + //! If the user calls + //! this function with a constant time size container or stateful comparison + //! functor a compilation error will be issued. + static void remove_node(reference value) + { + BOOST_STATIC_ASSERT((!constant_time_size)); + node_ptr to_remove(value_traits::to_node_ptr(value)); + node_algorithms::unlink(to_remove); + if(safemode_or_autounlink) + node_algorithms::init(to_remove); + } + + /// @cond + private: + template + iterator private_erase(iterator b, iterator e, size_type &n, Disposer disposer) + { + for(n = 0; b != e; ++n) + this->erase_and_dispose(b++, disposer); + return b; + } + + iterator private_erase(iterator b, iterator e, size_type &n) + { + for(n = 0; b != e; ++n) + this->erase(b++); + return b; + } + /// @endcond + + private: + static rbtree_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) + { + header_plus_size *r = detail::parent_from_member + ( detail::get_pointer(end_iterator.pointed_node()), &header_plus_size::header_); + node_plus_pred_t *n = detail::parent_from_member + (r, &node_plus_pred_t::header_plus_size_); + data_t *d = detail::parent_from_member(n, &data_t::node_plus_pred_); + rbtree_impl *rb = detail::parent_from_member(d, &rbtree_impl::data_); + return *rb; + } + + static rbtree_impl &priv_container_from_iterator(const const_iterator &it) + { return priv_container_from_end_iterator(it.end_iterator_from_it()); } +}; + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator< +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const rbtree_impl &x, const rbtree_impl &y) +#else +(const rbtree_impl &x, const rbtree_impl &y) +#endif +{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +bool operator== +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const rbtree_impl &x, const rbtree_impl &y) +#else +(const rbtree_impl &x, const rbtree_impl &y) +#endif +{ + typedef rbtree_impl tree_type; + typedef typename tree_type::const_iterator const_iterator; + + if(tree_type::constant_time_size && x.size() != y.size()){ + return false; + } + const_iterator end1 = x.end(); + const_iterator i1 = x.begin(); + const_iterator i2 = y.begin(); + if(tree_type::constant_time_size){ + while (i1 != end1 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1; + } + else{ + const_iterator end2 = y.end(); + while (i1 != end1 && i2 != end2 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1 && i2 == end2; + } +} + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator!= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const rbtree_impl &x, const rbtree_impl &y) +#else +(const rbtree_impl &x, const rbtree_impl &y) +#endif +{ return !(x == y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator> +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const rbtree_impl &x, const rbtree_impl &y) +#else +(const rbtree_impl &x, const rbtree_impl &y) +#endif +{ return y < x; } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator<= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const rbtree_impl &x, const rbtree_impl &y) +#else +(const rbtree_impl &x, const rbtree_impl &y) +#endif +{ return !(y < x); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator>= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const rbtree_impl &x, const rbtree_impl &y) +#else +(const rbtree_impl &x, const rbtree_impl &y) +#endif +{ return !(x < y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline void swap +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(rbtree_impl &x, rbtree_impl &y) +#else +(rbtree_impl &x, rbtree_impl &y) +#endif +{ x.swap(y); } + +/// @cond +template +struct make_rbtree_opt +{ + typedef typename pack_options + < set_defaults, O1, O2, O3, O4>::type packed_options; + typedef typename detail::get_value_traits + ::type value_traits; + + typedef setopt + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + > type; +}; +/// @endcond + +//! Helper metafunction to define a \c rbtree that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_rbtree +{ + /// @cond + typedef rbtree_impl + < typename make_rbtree_opt::type + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class rbtree + : public make_rbtree::type +{ + typedef typename make_rbtree + ::type Base; + + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::real_value_traits real_value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + rbtree( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + rbtree( bool unique, Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(unique, b, e, cmp, v_traits) + {} + + static rbtree &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const rbtree &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static rbtree &container_from_it(iterator it) + { return static_cast(Base::container_from_iterator(it)); } + + static const rbtree &container_from_it(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } +}; + +#endif + + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_RBTREE_HPP diff --git a/win32/include/boost/intrusive/rbtree_algorithms.hpp b/win32/include/boost/intrusive/rbtree_algorithms.hpp new file mode 100755 index 000000000..600bfff14 --- /dev/null +++ b/win32/include/boost/intrusive/rbtree_algorithms.hpp @@ -0,0 +1,850 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007. +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +// The internal implementation of red-black trees is based on that of SGI STL +// stl_tree.h file: +// +// Copyright (c) 1996,1997 +// Silicon Graphics Computer Systems, Inc. +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. Silicon Graphics makes no +// representations about the suitability of this software for any +// purpose. It is provided "as is" without express or implied warranty. +// +// +// Copyright (c) 1994 +// Hewlett-Packard Company +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appear in all copies and +// that both that copyright notice and this permission notice appear +// in supporting documentation. Hewlett-Packard Company makes no +// representations about the suitability of this software for any +// purpose. It is provided "as is" without express or implied warranty. +// +// The tree destruction algorithm is based on Julienne Walker and The EC Team code: +// +// This code is in the public domain. Anyone may use it or change it in any way that +// they see fit. The author assumes no responsibility for damages incurred through +// use of the original code or any variations thereof. +// +// It is requested, but not required, that due credit is given to the original author +// and anyone who has modified the code through a header comment, such as this one. + +#ifndef BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP +#define BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP + +#include + +#include +#include + +#include +#include +#include + + +namespace boost { +namespace intrusive { + +//! rbtree_algorithms provides basic algorithms to manipulate +//! nodes forming a red-black tree. The insertion and deletion algorithms are +//! based on those in Cormen, Leiserson, and Rivest, Introduction to Algorithms +//! (MIT Press, 1990), except that +//! +//! (1) the header node is maintained with links not only to the root +//! but also to the leftmost node of the tree, to enable constant time +//! begin(), and to the rightmost node of the tree, to enable linear time +//! performance when used with the generic set algorithms (set_union, +//! etc.); +//! +//! (2) when a node being deleted has two children its successor node is +//! relinked into its place, rather than copied, so that the only +//! pointers invalidated are those referring to the deleted node. +//! +//! rbtree_algorithms is configured with a NodeTraits class, which encapsulates the +//! information about the node to be manipulated. NodeTraits must support the +//! following interface: +//! +//! Typedefs: +//! +//! node: The type of the node that forms the circular list +//! +//! node_ptr: A pointer to a node +//! +//! const_node_ptr: A pointer to a const node +//! +//! color: The type that can store the color of a node +//! +//! Static functions: +//! +//! static node_ptr get_parent(const_node_ptr n); +//! +//! static void set_parent(node_ptr n, node_ptr parent); +//! +//! static node_ptr get_left(const_node_ptr n); +//! +//! static void set_left(node_ptr n, node_ptr left); +//! +//! static node_ptr get_right(const_node_ptr n); +//! +//! static void set_right(node_ptr n, node_ptr right); +//! +//! static color get_color(const_node_ptr n); +//! +//! static void set_color(node_ptr n, color c); +//! +//! static color black(); +//! +//! static color red(); +template +class rbtree_algorithms +{ + public: + typedef NodeTraits node_traits; + typedef typename NodeTraits::node node; + typedef typename NodeTraits::node_ptr node_ptr; + typedef typename NodeTraits::const_node_ptr const_node_ptr; + typedef typename NodeTraits::color color; + + /// @cond + private: + + typedef detail::tree_algorithms tree_algorithms; + + template + struct rbtree_node_cloner + : private detail::ebo_functor_holder + { + typedef detail::ebo_functor_holder base_t; + + rbtree_node_cloner(F f) + : base_t(f) + {} + + node_ptr operator()(node_ptr p) + { + node_ptr n = base_t::get()(p); + NodeTraits::set_color(n, NodeTraits::get_color(p)); + return n; + } + }; + + struct rbtree_erase_fixup + { + void operator()(node_ptr to_erase, node_ptr successor) + { + //Swap color of y and z + color tmp(NodeTraits::get_color(successor)); + NodeTraits::set_color(successor, NodeTraits::get_color(to_erase)); + NodeTraits::set_color(to_erase, tmp); + } + }; + + static node_ptr uncast(const_node_ptr ptr) + { + return node_ptr(const_cast(::boost::intrusive::detail::get_pointer(ptr))); + } + /// @endcond + + public: + static node_ptr begin_node(const_node_ptr header) + { return tree_algorithms::begin_node(header); } + + static node_ptr end_node(const_node_ptr header) + { return tree_algorithms::end_node(header); } + + //! This type is the information that will be + //! filled by insert_unique_check + typedef typename tree_algorithms::insert_commit_data insert_commit_data; + + //! Requires: header1 and header2 must be the header nodes + //! of two trees. + //! + //! Effects: Swaps two trees. After the function header1 will contain + //! links to the second tree and header2 will have links to the first tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static void swap_tree(node_ptr header1, node_ptr header2) + { return tree_algorithms::swap_tree(header1, header2); } + + //! Requires: node1 and node2 can't be header nodes + //! of two trees. + //! + //! Effects: Swaps two nodes. After the function node1 will be inserted + //! in the position node2 before the function. node2 will be inserted in the + //! position node1 had before the function. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! node1 and node2 are not equivalent according to the ordering rules. + //! + //!Experimental function + static void swap_nodes(node_ptr node1, node_ptr node2) + { + if(node1 == node2) + return; + + node_ptr header1(tree_algorithms::get_header(node1)), header2(tree_algorithms::get_header(node2)); + swap_nodes(node1, header1, node2, header2); + } + + //! Requires: node1 and node2 can't be header nodes + //! of two trees with header header1 and header2. + //! + //! Effects: Swaps two nodes. After the function node1 will be inserted + //! in the position node2 before the function. node2 will be inserted in the + //! position node1 had before the function. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! node1 and node2 are not equivalent according to the ordering rules. + //! + //!Experimental function + static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, node_ptr header2) + { + if(node1 == node2) return; + + tree_algorithms::swap_nodes(node1, header1, node2, header2); + //Swap color + color c = NodeTraits::get_color(node1); + NodeTraits::set_color(node1, NodeTraits::get_color(node2)); + NodeTraits::set_color(node2, c); + } + + //! Requires: node_to_be_replaced must be inserted in a tree + //! and new_node must not be inserted in a tree. + //! + //! Effects: Replaces node_to_be_replaced in its position in the + //! tree with new_node. The tree does not need to be rebalanced + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! new_node is not equivalent to node_to_be_replaced according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing and comparison is needed. + //! + //!Experimental function + static void replace_node(node_ptr node_to_be_replaced, node_ptr new_node) + { + if(node_to_be_replaced == new_node) + return; + replace_node(node_to_be_replaced, tree_algorithms::get_header(node_to_be_replaced), new_node); + } + + //! Requires: node_to_be_replaced must be inserted in a tree + //! with header "header" and new_node must not be inserted in a tree. + //! + //! Effects: Replaces node_to_be_replaced in its position in the + //! tree with new_node. The tree does not need to be rebalanced + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! new_node is not equivalent to node_to_be_replaced according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + //! + //!Experimental function + static void replace_node(node_ptr node_to_be_replaced, node_ptr header, node_ptr new_node) + { + tree_algorithms::replace_node(node_to_be_replaced, header, new_node); + NodeTraits::set_color(new_node, NodeTraits::get_color(node_to_be_replaced)); + } + + //! Requires: node is a tree node but not the header. + //! + //! Effects: Unlinks the node and rebalances the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + static void unlink(node_ptr node) + { + node_ptr x = NodeTraits::get_parent(node); + if(x){ + while(!is_header(x)) + x = NodeTraits::get_parent(x); + erase(x, node); + } + } + + //! Requires: header is the header of a tree. + //! + //! Effects: Unlinks the leftmost node from the tree, and + //! updates the header link to the new leftmost node. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + static node_ptr unlink_leftmost_without_rebalance(node_ptr header) + { return tree_algorithms::unlink_leftmost_without_rebalance(header); } + + //! Requires: node is a node of the tree or an node initialized + //! by init(...). + //! + //! Effects: Returns true if the node is initialized by init(). + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + static bool unique(const_node_ptr node) + { return tree_algorithms::unique(node); } + + //! Requires: node is a node of the tree but it's not the header. + //! + //! Effects: Returns the number of nodes of the subtree. + //! + //! Complexity: Linear time. + //! + //! Throws: Nothing. + static std::size_t count(const_node_ptr node) + { return tree_algorithms::count(node); } + + //! Requires: header is the header node of the tree. + //! + //! Effects: Returns the number of nodes above the header. + //! + //! Complexity: Linear time. + //! + //! Throws: Nothing. + static std::size_t size(const_node_ptr header) + { return tree_algorithms::size(header); } + + //! Requires: p is a node from the tree except the header. + //! + //! Effects: Returns the next node of the tree. + //! + //! Complexity: Average constant time. + //! + //! Throws: Nothing. + static node_ptr next_node(node_ptr p) + { return tree_algorithms::next_node(p); } + + //! Requires: p is a node from the tree except the leftmost node. + //! + //! Effects: Returns the previous node of the tree. + //! + //! Complexity: Average constant time. + //! + //! Throws: Nothing. + static node_ptr prev_node(node_ptr p) + { return tree_algorithms::prev_node(p); } + + //! Requires: node must not be part of any tree. + //! + //! Effects: After the function unique(node) == true. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Nodes: If node is inserted in a tree, this function corrupts the tree. + static void init(node_ptr node) + { tree_algorithms::init(node); } + + //! Requires: node must not be part of any tree. + //! + //! Effects: Initializes the header to represent an empty tree. + //! unique(header) == true. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Nodes: If node is inserted in a tree, this function corrupts the tree. + static void init_header(node_ptr header) + { + tree_algorithms::init_header(header); + NodeTraits::set_color(header, NodeTraits::red()); + } + + //! Requires: header must be the header of a tree, z a node + //! of that tree and z != header. + //! + //! Effects: Erases node "z" from the tree with header "header". + //! + //! Complexity: Amortized constant time. + //! + //! Throws: Nothing. + static node_ptr erase(node_ptr header, node_ptr z) + { + typename tree_algorithms::data_for_rebalance info; + tree_algorithms::erase(header, z, rbtree_erase_fixup(), info); + node_ptr x = info.x; + node_ptr x_parent = info.x_parent; + + //Rebalance rbtree + if(NodeTraits::get_color(z) != NodeTraits::red()){ + rebalance_after_erasure(header, x, x_parent); + } + return z; + } + + //! Requires: "cloner" must be a function + //! object taking a node_ptr and returning a new cloned node of it. "disposer" must + //! take a node_ptr and shouldn't throw. + //! + //! Effects: First empties target tree calling + //! void disposer::operator()(node_ptr) for every node of the tree + //! except the header. + //! + //! Then, duplicates the entire tree pointed by "source_header" cloning each + //! source node with node_ptr Cloner::operator()(node_ptr) to obtain + //! the nodes of the target tree. If "cloner" throws, the cloned target nodes + //! are disposed using void disposer(node_ptr). + //! + //! Complexity: Linear to the number of element of the source tree plus the. + //! number of elements of tree target tree when calling this function. + //! + //! Throws: If cloner functor throws. If this happens target nodes are disposed. + template + static void clone + (const_node_ptr source_header, node_ptr target_header, Cloner cloner, Disposer disposer) + { + rbtree_node_cloner new_cloner(cloner); + tree_algorithms::clone(source_header, target_header, new_cloner, disposer); + } + + //! Requires: "disposer" must be an object function + //! taking a node_ptr parameter and shouldn't throw. + //! + //! Effects: Empties the target tree calling + //! void disposer::operator()(node_ptr) for every node of the tree + //! except the header. + //! + //! Complexity: Linear to the number of element of the source tree plus the. + //! number of elements of tree target tree when calling this function. + //! + //! Throws: If cloner functor throws. If this happens target nodes are disposed. + template + static void clear_and_dispose(node_ptr header, Disposer disposer) + { tree_algorithms::clear_and_dispose(header, disposer); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the first element that is + //! not less than "key" according to "comp" or "header" if that element does + //! not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr lower_bound + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { return tree_algorithms::lower_bound(header, key, comp); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the first element that is greater + //! than "key" according to "comp" or "header" if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr upper_bound + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { return tree_algorithms::upper_bound(header, key, comp); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the element that is equivalent to + //! "key" according to "comp" or "header" if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr find + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { return tree_algorithms::find(header, key, comp); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an a pair of node_ptr delimiting a range containing + //! all elements that are equivalent to "key" according to "comp" or an + //! empty range that indicates the position where those elements would be + //! if they there are no equivalent elements. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static std::pair equal_range + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { return tree_algorithms::equal_range(header, key, comp); } + + //! Requires: "h" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. + //! + //! Effects: Inserts new_node into the tree before the upper bound + //! according to "comp". + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr insert_equal_upper_bound + (node_ptr h, node_ptr new_node, NodePtrCompare comp) + { + tree_algorithms::insert_equal_upper_bound(h, new_node, comp); + rebalance_after_insertion(h, new_node); + return new_node; + } + + //! Requires: "h" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. + //! + //! Effects: Inserts new_node into the tree before the lower bound + //! according to "comp". + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr insert_equal_lower_bound + (node_ptr h, node_ptr new_node, NodePtrCompare comp) + { + tree_algorithms::insert_equal_lower_bound(h, new_node, comp); + rebalance_after_insertion(h, new_node); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from + //! the "header"'s tree. + //! + //! Effects: Inserts new_node into the tree, using "hint" as a hint to + //! where it will be inserted. If "hint" is the upper_bound + //! the insertion takes constant time (two comparisons in the worst case). + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time if new_node is inserted immediately before "hint". + //! + //! Throws: If "comp" throws. + template + static node_ptr insert_equal + (node_ptr header, node_ptr hint, node_ptr new_node, NodePtrCompare comp) + { + tree_algorithms::insert_equal(header, hint, new_node, comp); + rebalance_after_insertion(header, new_node); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares KeyType with a node_ptr. + //! + //! Effects: Checks if there is an equivalent node to "key" in the + //! tree according to "comp" and obtains the needed information to realize + //! a constant-time node insertion if there is no equivalent node. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing a node_ptr to the already present node + //! and false. If there is not equivalent key can be inserted returns true + //! in the returned pair's boolean and fills "commit_data" that is meant to + //! be used with the "insert_commit" function to achieve a constant-time + //! insertion function. + //! + //! Complexity: Average complexity is at most logarithmic. + //! + //! Throws: If "comp" throws. + //! + //! Notes: This function is used to improve performance when constructing + //! a node is expensive and the user does not want to have two equivalent nodes + //! in the tree: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the order is much cheaper to construct + //! than the node and this function offers the possibility to use that part + //! to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the node and use + //! "insert_commit" to insert the node in constant-time. This gives a total + //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_unique_commit" only + //! if no more objects are inserted or erased from the set. + template + static std::pair insert_unique_check + (const_node_ptr header, const KeyType &key + ,KeyNodePtrCompare comp, insert_commit_data &commit_data) + { return tree_algorithms::insert_unique_check(header, key, comp, commit_data); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares KeyType with a node_ptr. + //! "hint" is node from the "header"'s tree. + //! + //! Effects: Checks if there is an equivalent node to "key" in the + //! tree according to "comp" using "hint" as a hint to where it should be + //! inserted and obtains the needed information to realize + //! a constant-time node insertion if there is no equivalent node. + //! If "hint" is the upper_bound the function has constant time + //! complexity (two comparisons in the worst case). + //! + //! Returns: If there is an equivalent value + //! returns a pair containing a node_ptr to the already present node + //! and false. If there is not equivalent key can be inserted returns true + //! in the returned pair's boolean and fills "commit_data" that is meant to + //! be used with the "insert_commit" function to achieve a constant-time + //! insertion function. + //! + //! Complexity: Average complexity is at most logarithmic, but it is + //! amortized constant time if new_node should be inserted immediately before "hint". + //! + //! Throws: If "comp" throws. + //! + //! Notes: This function is used to improve performance when constructing + //! a node is expensive and the user does not want to have two equivalent nodes + //! in the tree: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the order is much cheaper to construct + //! than the node and this function offers the possibility to use that part + //! to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the node and use + //! "insert_commit" to insert the node in constant-time. This gives a total + //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_unique_commit" only + //! if no more objects are inserted or erased from the set. + template + static std::pair insert_unique_check + (const_node_ptr header, node_ptr hint, const KeyType &key + ,KeyNodePtrCompare comp, insert_commit_data &commit_data) + { return tree_algorithms::insert_unique_check(header, hint, key, comp, commit_data); } + + //! Requires: "header" must be the header node of a tree. + //! "commit_data" must have been obtained from a previous call to + //! "insert_unique_check". No objects should have been inserted or erased + //! from the set between the "insert_unique_check" that filled "commit_data" + //! and the call to "insert_commit". + //! + //! + //! Effects: Inserts new_node in the set using the information obtained + //! from the "commit_data" that a previous "insert_check" filled. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function has only sense if a "insert_unique_check" has been + //! previously executed to fill "commit_data". No value should be inserted or + //! erased between the "insert_check" and "insert_commit" calls. + static void insert_unique_commit + (node_ptr header, node_ptr new_value, const insert_commit_data &commit_data) + { + tree_algorithms::insert_unique_commit(header, new_value, commit_data); + rebalance_after_insertion(header, new_value); + } + + //! Requires: "n" must be a node inserted in a tree. + //! + //! Effects: Returns a pointer to the header node of the tree. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + static node_ptr get_header(node_ptr n) + { return tree_algorithms::get_header(n); } + + /// @cond + private: + + //! Requires: p is a node of a tree. + //! + //! Effects: Returns true if p is the header of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static bool is_header(const_node_ptr p) + { + return NodeTraits::get_color(p) == NodeTraits::red() && + tree_algorithms::is_header(p); + //return NodeTraits::get_color(p) == NodeTraits::red() && + // NodeTraits::get_parent(NodeTraits::get_parent(p)) == p; + } + + static void rebalance_after_erasure(node_ptr header, node_ptr x, node_ptr x_parent) + { + while(x != NodeTraits::get_parent(header) && (x == 0 || NodeTraits::get_color(x) == NodeTraits::black())){ + if(x == NodeTraits::get_left(x_parent)){ + node_ptr w = NodeTraits::get_right(x_parent); + if(NodeTraits::get_color(w) == NodeTraits::red()){ + NodeTraits::set_color(w, NodeTraits::black()); + NodeTraits::set_color(x_parent, NodeTraits::red()); + tree_algorithms::rotate_left(x_parent, header); + w = NodeTraits::get_right(x_parent); + } + if((NodeTraits::get_left(w) == 0 || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black()) && + (NodeTraits::get_right(w) == 0 || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black())){ + NodeTraits::set_color(w, NodeTraits::red()); + x = x_parent; + x_parent = NodeTraits::get_parent(x_parent); + } + else { + if(NodeTraits::get_right(w) == 0 || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black()){ + NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black()); + NodeTraits::set_color(w, NodeTraits::red()); + tree_algorithms::rotate_right(w, header); + w = NodeTraits::get_right(x_parent); + } + NodeTraits::set_color(w, NodeTraits::get_color(x_parent)); + NodeTraits::set_color(x_parent, NodeTraits::black()); + if(NodeTraits::get_right(w)) + NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black()); + tree_algorithms::rotate_left(x_parent, header); + break; + } + } + else { + // same as above, with right_ <-> left_. + node_ptr w = NodeTraits::get_left(x_parent); + if(NodeTraits::get_color(w) == NodeTraits::red()){ + NodeTraits::set_color(w, NodeTraits::black()); + NodeTraits::set_color(x_parent, NodeTraits::red()); + tree_algorithms::rotate_right(x_parent, header); + w = NodeTraits::get_left(x_parent); + } + if((NodeTraits::get_right(w) == 0 || NodeTraits::get_color(NodeTraits::get_right(w)) == NodeTraits::black()) && + (NodeTraits::get_left(w) == 0 || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black())){ + NodeTraits::set_color(w, NodeTraits::red()); + x = x_parent; + x_parent = NodeTraits::get_parent(x_parent); + } + else { + if(NodeTraits::get_left(w) == 0 || NodeTraits::get_color(NodeTraits::get_left(w)) == NodeTraits::black()){ + NodeTraits::set_color(NodeTraits::get_right(w), NodeTraits::black()); + NodeTraits::set_color(w, NodeTraits::red()); + tree_algorithms::rotate_left(w, header); + w = NodeTraits::get_left(x_parent); + } + NodeTraits::set_color(w, NodeTraits::get_color(x_parent)); + NodeTraits::set_color(x_parent, NodeTraits::black()); + if(NodeTraits::get_left(w)) + NodeTraits::set_color(NodeTraits::get_left(w), NodeTraits::black()); + tree_algorithms::rotate_right(x_parent, header); + break; + } + } + } + if(x) + NodeTraits::set_color(x, NodeTraits::black()); + } + + + static void rebalance_after_insertion(node_ptr header, node_ptr p) + { + NodeTraits::set_color(p, NodeTraits::red()); + while(p != NodeTraits::get_parent(header) && NodeTraits::get_color(NodeTraits::get_parent(p)) == NodeTraits::red()){ + node_ptr p_parent(NodeTraits::get_parent(p)); + node_ptr p_parent_parent(NodeTraits::get_parent(p_parent)); + if(tree_algorithms::is_left_child(p_parent)){ + node_ptr x = NodeTraits::get_right(p_parent_parent); + if(x && NodeTraits::get_color(x) == NodeTraits::red()){ + NodeTraits::set_color(p_parent, NodeTraits::black()); + NodeTraits::set_color(p_parent_parent, NodeTraits::red()); + NodeTraits::set_color(x, NodeTraits::black()); + p = p_parent_parent; + } + else { + if(!tree_algorithms::is_left_child(p)){ + p = p_parent; + tree_algorithms::rotate_left(p, header); + } + node_ptr new_p_parent(NodeTraits::get_parent(p)); + node_ptr new_p_parent_parent(NodeTraits::get_parent(new_p_parent)); + NodeTraits::set_color(new_p_parent, NodeTraits::black()); + NodeTraits::set_color(new_p_parent_parent, NodeTraits::red()); + tree_algorithms::rotate_right(new_p_parent_parent, header); + } + } + else{ + node_ptr x = NodeTraits::get_left(p_parent_parent); + if(x && NodeTraits::get_color(x) == NodeTraits::red()){ + NodeTraits::set_color(p_parent, NodeTraits::black()); + NodeTraits::set_color(p_parent_parent, NodeTraits::red()); + NodeTraits::set_color(x, NodeTraits::black()); + p = p_parent_parent; + } + else{ + if(tree_algorithms::is_left_child(p)){ + p = p_parent; + tree_algorithms::rotate_right(p, header); + } + node_ptr new_p_parent(NodeTraits::get_parent(p)); + node_ptr new_p_parent_parent(NodeTraits::get_parent(new_p_parent)); + NodeTraits::set_color(new_p_parent, NodeTraits::black()); + NodeTraits::set_color(new_p_parent_parent, NodeTraits::red()); + tree_algorithms::rotate_left(new_p_parent_parent, header); + } + } + } + NodeTraits::set_color(NodeTraits::get_parent(header), NodeTraits::black()); + } + /// @endcond +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_RBTREE_ALGORITHMS_HPP diff --git a/win32/include/boost/intrusive/set.hpp b/win32/include/boost/intrusive/set.hpp new file mode 100755 index 000000000..cffb96271 --- /dev/null +++ b/win32/include/boost/intrusive/set.hpp @@ -0,0 +1,2153 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_SET_HPP +#define BOOST_INTRUSIVE_SET_HPP + +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +//! The class template set is an intrusive container, that mimics most of +//! the interface of std::set as described in the C++ standard. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<> and +//! \c compare<>. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class set_impl +{ + /// @cond + typedef rbtree_impl tree_type; + //! This class is + //! non-copyable + set_impl (const set_impl&); + + //! This class is + //! non-assignable + set_impl &operator =(const set_impl&); + + typedef tree_type implementation_defined; + /// @endcond + + public: + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::value_traits value_traits; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::insert_commit_data insert_commit_data; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; + + /// @cond + private: + tree_type tree_; + /// @endcond + + public: + //! Effects: Constructs an empty set. + //! + //! Complexity: Constant. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor of the value_compare object throws. + set_impl( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(cmp, v_traits) + {} + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! cmp must be a comparison function that induces a strict weak ordering. + //! + //! Effects: Constructs an empty set and inserts elements from + //! [b, e). + //! + //! Complexity: Linear in N if [b, e) is already sorted using + //! comp and otherwise N * log N, where N is std::distance(last, first). + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor/operator() of the value_compare object throws. + template + set_impl( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(true, b, e, cmp, v_traits) + {} + + //! Effects: Detaches all elements from this. The objects in the set + //! are not deleted (i.e. no destructors are called). + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + ~set_impl() + {} + + //! Effects: Returns an iterator pointing to the beginning of the set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator begin() + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator begin() const + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cbegin() const + { return tree_.cbegin(); } + + //! Effects: Returns an iterator pointing to the end of the set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return tree_.cend(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning of the + //! reversed set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rbegin() + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rbegin() const + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crbegin() const + { return tree_.crbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rend() + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rend() const + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crend() const + { return tree_.crend(); } + + //! Precondition: end_iterator must be a valid end iterator + //! of set. + //! + //! Effects: Returns a reference to the set associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static set_impl &container_from_end_iterator(iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &set_impl::tree_); + } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of set. + //! + //! Effects: Returns a const reference to the set associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const set_impl &container_from_end_iterator(const_iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &set_impl::tree_); + } + + //! Precondition: it must be a valid iterator of set. + //! + //! Effects: Returns a reference to the set associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static set_impl &container_from_iterator(iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &set_impl::tree_); + } + + //! Precondition: it must be a valid const_iterator of set. + //! + //! Effects: Returns a const reference to the set associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static const set_impl &container_from_iterator(const_iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &set_impl::tree_); + } + + //! Effects: Returns the key_compare object used by the set. + //! + //! Complexity: Constant. + //! + //! Throws: If key_compare copy-constructor throws. + key_compare key_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns the value_compare object used by the set. + //! + //! Complexity: Constant. + //! + //! Throws: If value_compare copy-constructor throws. + value_compare value_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bool empty() const + { return tree_.empty(); } + + //! Effects: Returns the number of elements stored in the set. + //! + //! Complexity: Linear to elements contained in *this if, + //! constant-time size option is enabled. Constant-time otherwise. + //! + //! Throws: Nothing. + size_type size() const + { return tree_.size(); } + + //! Effects: Swaps the contents of two sets. + //! + //! Complexity: Constant. + //! + //! Throws: If the swap() call for the comparison functor + //! found using ADL throws. Strong guarantee. + void swap(set_impl& other) + { tree_.swap(other.tree_); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. + template + void clone_from(const set_impl &src, Cloner cloner, Disposer disposer) + { tree_.clone_from(src.tree_, cloner, disposer); } + + //! Requires: value must be an lvalue + //! + //! Effects: Tries to inserts value into the set. + //! + //! Returns: If the value + //! is not already present inserts it and returns a pair containing the + //! iterator to the new value and true. If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + std::pair insert(reference value) + { return tree_.insert_unique(value); } + + //! Requires: value must be an lvalue + //! + //! Effects: Tries to to insert x into the set, using "hint" + //! as a hint to where it will be inserted. + //! + //! Returns: An iterator that points to the position where the + //! new element was inserted into the set. + //! + //! Complexity: Logarithmic in general, but it's amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert(const_iterator hint, reference value) + { return tree_.insert_unique(hint, value); } + + //! Requires: key_value_comp must be a comparison function that induces + //! the same strict weak ordering as value_compare. The difference is that + //! key_value_comp compares an arbitrary key with the contained values. + //! + //! Effects: Checks if a value can be inserted in the set, using + //! a user provided key instead of the value itself. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. If the value can be inserted returns true in the returned + //! pair boolean and fills "commit_data" that is meant to be used with + //! the "insert_commit" function. + //! + //! Complexity: Average complexity is at most logarithmic. + //! + //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! + //! Notes: This function is used to improve performance when constructing + //! a value_type is expensive: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the order is much cheaper to construct + //! than the value_type and this function offers the possibility to use that + //! part to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the value_type and use + //! "insert_commit" to insert the object in constant-time. This gives a total + //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_commit" only if no more + //! objects are inserted or erased from the set. + template + std::pair insert_check + (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { return tree_.insert_unique_check(key, key_value_comp, commit_data); } + + //! Requires: key_value_comp must be a comparison function that induces + //! the same strict weak ordering as value_compare. The difference is that + //! key_value_comp compares an arbitrary key with the contained values. + //! + //! Effects: Checks if a value can be inserted in the set, using + //! a user provided key instead of the value itself, using "hint" + //! as a hint to where it will be inserted. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. If the value can be inserted returns true in the returned + //! pair boolean and fills "commit_data" that is meant to be used with + //! the "insert_commit" function. + //! + //! Complexity: Logarithmic in general, but it's amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! + //! Notes: This function is used to improve performance when constructing + //! a value_type is expensive: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! constructing that is used to impose the order is much cheaper to construct + //! than the value_type and this function offers the possibility to use that key + //! to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the value_type and use + //! "insert_commit" to insert the object in constant-time. This can give a total + //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_commit" only if no more + //! objects are inserted or erased from the set. + template + std::pair insert_check + (const_iterator hint, const KeyType &key + ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { return tree_.insert_unique_check(hint, key, key_value_comp, commit_data); } + + //! Requires: value must be an lvalue of type value_type. commit_data + //! must have been obtained from a previous call to "insert_check". + //! No objects should have been inserted or erased from the set between + //! the "insert_check" that filled "commit_data" and the call to "insert_commit". + //! + //! Effects: Inserts the value in the set using the information obtained + //! from the "commit_data" that a previous "insert_check" filled. + //! + //! Returns: An iterator to the newly inserted object. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function has only sense if a "insert_check" has been + //! previously executed to fill "commit_data". No value should be inserted or + //! erased between the "insert_check" and "insert_commit" calls. + iterator insert_commit(reference value, const insert_commit_data &commit_data) + { return tree_.insert_unique_commit(value, commit_data); } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Inserts a range into the set. + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert(Iterator b, Iterator e) + { tree_.insert_unique(b, e); } + + //! Effects: Erases the element pointed to by pos. + //! + //! Complexity: Average complexity is constant time. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator i) + { return tree_.erase(i); } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator b, iterator e) + { return tree_.erase(b, e); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size()) + this->count(value)). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return tree_.erase(value); } + + //! Effects: Erases all the elements that compare equal with + //! the given key and the given comparison functor. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(key, comp)). + //! + //! Throws: If the comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyValueCompare comp) + { return tree_.erase(key, comp); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element pointed to by pos. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { return tree_.erase_and_dispose(i, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) + { return tree_.erase_and_dispose(b, e, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: If the internal value_compare ordering function throws. + //! + //! Complexity: O(log(size() + this->count(value)). Basic guarantee. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { return tree_.erase_and_dispose(value, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(key, comp)). + //! + //! Throws: If comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) + { return tree_.erase_and_dispose(key, comp, disposer); } + + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { return tree_.clear(); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + void clear_and_dispose(Disposer disposer) + { return tree_.clear_and_dispose(disposer); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If the internal value_compare ordering function throws. + size_type count(const_reference value) const + { return tree_.find(value) != end(); } + + //! Effects: Returns the number of contained elements with the same key + //! compared with the given comparison functor. + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If comp ordering function throws. + template + size_type count(const KeyType& key, KeyValueCompare comp) const + { return tree_.find(key, comp) != end(); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator lower_bound(const_reference value) + { return tree_.lower_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator lower_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.lower_bound(key, comp); } + + //! Effects: Returns a const iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator lower_bound(const_reference value) const + { return tree_.lower_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const + { return tree_.lower_bound(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator upper_bound(const_reference value) + { return tree_.upper_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator upper_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.upper_bound(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator upper_bound(const_reference value) const + { return tree_.upper_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const + { return tree_.upper_bound(key, comp); } + + //! Effects: Finds an iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator find(const_reference value) + { return tree_.find(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds an iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator find(const KeyType& key, KeyValueCompare comp) + { return tree_.find(key, comp); } + + //! Effects: Finds a const_iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator find(const_reference value) const + { return tree_.find(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a const_iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator find(const KeyType& key, KeyValueCompare comp) const + { return tree_.find(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair equal_range(const_reference value) + { return tree_.equal_range(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return tree_.equal_range(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair + equal_range(const_reference value) const + { return tree_.equal_range(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair + equal_range(const KeyType& key, KeyValueCompare comp) const + { return tree_.equal_range(key, comp); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator iterator_to(reference value) + { return tree_.iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator iterator_to(const_reference value) const + { return tree_.iterator_to(value); } + + //! Requires: value shall not be in a set/multiset. + //! + //! Effects: init_node puts the hook of a value in a well-known default + //! state. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This function puts the hook in the well-known default state + //! used by auto_unlink and safe hooks. + static void init_node(reference value) + { tree_type::init_node(value); } + + //! Effects: Unlinks the leftmost node from the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + pointer unlink_leftmost_without_rebalance() + { return tree_.unlink_leftmost_without_rebalance(); } + + //! Requires: replace_this must be a valid iterator of *this + //! and with_this must not be inserted in any tree. + //! + //! Effects: Replaces replace_this in its position in the + //! tree with with_this. The tree does not need to be rebalanced. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! with_this is not equivalent to *replace_this according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + void replace_node(iterator replace_this, reference with_this) + { tree_.replace_node(replace_this, with_this); } + + /// @cond + friend bool operator==(const set_impl &x, const set_impl &y) + { return x.tree_ == y.tree_; } + + friend bool operator<(const set_impl &x, const set_impl &y) + { return x.tree_ < y.tree_; } + /// @endcond +}; + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator!= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const set_impl &x, const set_impl &y) +#else +(const set_impl &x, const set_impl &y) +#endif +{ return !(x == y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator> +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const set_impl &x, const set_impl &y) +#else +(const set_impl &x, const set_impl &y) +#endif +{ return y < x; } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator<= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const set_impl &x, const set_impl &y) +#else +(const set_impl &x, const set_impl &y) +#endif +{ return !(y < x); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator>= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const set_impl &x, const set_impl &y) +#else +(const set_impl &x, const set_impl &y) +#endif +{ return !(x < y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline void swap +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(set_impl &x, set_impl &y) +#else +(set_impl &x, set_impl &y) +#endif +{ x.swap(y); } + +//! Helper metafunction to define a \c set that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_set +{ + /// @cond + typedef set_impl + < typename make_rbtree_opt::type + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class set + : public make_set::type +{ + typedef typename make_set + ::type Base; + + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + set( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + set( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(b, e, cmp, v_traits) + {} + + static set &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const set &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static set &container_from_iterator(iterator it) + { return static_cast(Base::container_from_iterator(it)); } + + static const set &container_from_iterator(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } +}; + +#endif + +//! The class template multiset is an intrusive container, that mimics most of +//! the interface of std::multiset as described in the C++ standard. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<> and +//! \c compare<>. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class multiset_impl +{ + /// @cond + typedef rbtree_impl tree_type; + + //Non-copyable and non-assignable + multiset_impl (const multiset_impl&); + multiset_impl &operator =(const multiset_impl&); + typedef tree_type implementation_defined; + /// @endcond + + public: + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::value_traits value_traits; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::insert_commit_data insert_commit_data; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; + + /// @cond + private: + tree_type tree_; + /// @endcond + + public: + //! Effects: Constructs an empty multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor/operator() of the value_compare object throws. + multiset_impl( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(cmp, v_traits) + {} + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! cmp must be a comparison function that induces a strict weak ordering. + //! + //! Effects: Constructs an empty multiset and inserts elements from + //! [b, e). + //! + //! Complexity: Linear in N if [b, e) is already sorted using + //! comp and otherwise N * log N, where N is the distance between first and last + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor/operator() of the value_compare object throws. + template + multiset_impl( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(false, b, e, cmp, v_traits) + {} + + //! Effects: Detaches all elements from this. The objects in the set + //! are not deleted (i.e. no destructors are called). + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + ~multiset_impl() + {} + + //! Effects: Returns an iterator pointing to the beginning of the multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator begin() + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator begin() const + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cbegin() const + { return tree_.cbegin(); } + + //! Effects: Returns an iterator pointing to the end of the multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return tree_.cend(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning of the + //! reversed multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rbegin() + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rbegin() const + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crbegin() const + { return tree_.crbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rend() + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rend() const + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crend() const + { return tree_.crend(); } + + //! Precondition: end_iterator must be a valid end iterator + //! of multiset. + //! + //! Effects: Returns a const reference to the multiset associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static multiset_impl &container_from_end_iterator(iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &multiset_impl::tree_); + } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of multiset. + //! + //! Effects: Returns a const reference to the multiset associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const multiset_impl &container_from_end_iterator(const_iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &multiset_impl::tree_); + } + + //! Precondition: it must be a valid iterator of multiset. + //! + //! Effects: Returns a const reference to the multiset associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static multiset_impl &container_from_iterator(iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &multiset_impl::tree_); + } + + //! Precondition: it must be a valid const_iterator of multiset. + //! + //! Effects: Returns a const reference to the multiset associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const multiset_impl &container_from_iterator(const_iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &multiset_impl::tree_); + } + + //! Effects: Returns the key_compare object used by the multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If key_compare copy-constructor throws. + key_compare key_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns the value_compare object used by the multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If value_compare copy-constructor throws. + value_compare value_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bool empty() const + { return tree_.empty(); } + + //! Effects: Returns the number of elements stored in the multiset. + //! + //! Complexity: Linear to elements contained in *this if, + //! constant-time size option is enabled. Constant-time otherwise. + //! + //! Throws: Nothing. + size_type size() const + { return tree_.size(); } + + //! Effects: Swaps the contents of two multisets. + //! + //! Complexity: Constant. + //! + //! Throws: If the swap() call for the comparison functor + //! found using ADL throws. Strong guarantee. + void swap(multiset_impl& other) + { tree_.swap(other.tree_); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. Basic guarantee. + template + void clone_from(const multiset_impl &src, Cloner cloner, Disposer disposer) + { tree_.clone_from(src.tree_, cloner, disposer); } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the multiset. + //! + //! Returns: An iterator that points to the position where the new + //! element was inserted. + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert(reference value) + { return tree_.insert_equal(value); } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts x into the multiset, using pos as a hint to + //! where it will be inserted. + //! + //! Returns: An iterator that points to the position where the new + //! element was inserted. + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert(const_iterator hint, reference value) + { return tree_.insert_equal(hint, value); } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Inserts a range into the multiset. + //! + //! Returns: An iterator that points to the position where the new + //! element was inserted. + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert(Iterator b, Iterator e) + { tree_.insert_equal(b, e); } + + //! Effects: Erases the element pointed to by pos. + //! + //! Complexity: Average complexity is constant time. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator i) + { return tree_.erase(i); } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator b, iterator e) + { return tree_.erase(b, e); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(value)). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return tree_.erase(value); } + + //! Effects: Erases all the elements that compare equal with + //! the given key and the given comparison functor. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(key, comp)). + //! + //! Throws: If comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyValueCompare comp) + { return tree_.erase(key, comp); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Effects: Erases the element pointed to by pos. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { return tree_.erase_and_dispose(i, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) + { return tree_.erase_and_dispose(b, e, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(value)). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { return tree_.erase_and_dispose(value, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(key, comp)). + //! + //! Throws: If comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) + { return tree_.erase_and_dispose(key, comp, disposer); } + + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { return tree_.clear(); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + void clear_and_dispose(Disposer disposer) + { return tree_.clear_and_dispose(disposer); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If the internal value_compare ordering function throws. + size_type count(const_reference value) const + { return tree_.count(value); } + + //! Effects: Returns the number of contained elements with the same key + //! compared with the given comparison functor. + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If comp ordering function throws. + template + size_type count(const KeyType& key, KeyValueCompare comp) const + { return tree_.count(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator lower_bound(const_reference value) + { return tree_.lower_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator lower_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.lower_bound(key, comp); } + + //! Effects: Returns a const iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator lower_bound(const_reference value) const + { return tree_.lower_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const + { return tree_.lower_bound(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator upper_bound(const_reference value) + { return tree_.upper_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator upper_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.upper_bound(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator upper_bound(const_reference value) const + { return tree_.upper_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const + { return tree_.upper_bound(key, comp); } + + //! Effects: Finds an iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator find(const_reference value) + { return tree_.find(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds an iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator find(const KeyType& key, KeyValueCompare comp) + { return tree_.find(key, comp); } + + //! Effects: Finds a const_iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator find(const_reference value) const + { return tree_.find(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a const_iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator find(const KeyType& key, KeyValueCompare comp) const + { return tree_.find(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair equal_range(const_reference value) + { return tree_.equal_range(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return tree_.equal_range(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair + equal_range(const_reference value) const + { return tree_.equal_range(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair + equal_range(const KeyType& key, KeyValueCompare comp) const + { return tree_.equal_range(key, comp); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator iterator_to(reference value) + { return tree_.iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator iterator_to(const_reference value) const + { return tree_.iterator_to(value); } + + //! Requires: value shall not be in a set/multiset. + //! + //! Effects: init_node puts the hook of a value in a well-known default + //! state. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This function puts the hook in the well-known default state + //! used by auto_unlink and safe hooks. + static void init_node(reference value) + { tree_type::init_node(value); } + + //! Effects: Unlinks the leftmost node from the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + pointer unlink_leftmost_without_rebalance() + { return tree_.unlink_leftmost_without_rebalance(); } + + //! Requires: replace_this must be a valid iterator of *this + //! and with_this must not be inserted in any tree. + //! + //! Effects: Replaces replace_this in its position in the + //! tree with with_this. The tree does not need to be rebalanced. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! with_this is not equivalent to *replace_this according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + void replace_node(iterator replace_this, reference with_this) + { tree_.replace_node(replace_this, with_this); } + + //! Effects: removes "value" from the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic time. + //! + //! Note: This static function is only usable with non-constant + //! time size containers that have stateless comparison functors. + //! + //! If the user calls + //! this function with a constant time size container or stateful comparison + //! functor a compilation error will be issued. + static void remove_node(reference value) + { tree_type::remove_node(value); } + + /// @cond + friend bool operator==(const multiset_impl &x, const multiset_impl &y) + { return x.tree_ == y.tree_; } + + friend bool operator<(const multiset_impl &x, const multiset_impl &y) + { return x.tree_ < y.tree_; } + /// @endcond +}; + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator!= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const multiset_impl &x, const multiset_impl &y) +#else +(const multiset_impl &x, const multiset_impl &y) +#endif +{ return !(x == y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator> +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const multiset_impl &x, const multiset_impl &y) +#else +(const multiset_impl &x, const multiset_impl &y) +#endif +{ return y < x; } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator<= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const multiset_impl &x, const multiset_impl &y) +#else +(const multiset_impl &x, const multiset_impl &y) +#endif +{ return !(y < x); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator>= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const multiset_impl &x, const multiset_impl &y) +#else +(const multiset_impl &x, const multiset_impl &y) +#endif +{ return !(x < y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline void swap +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(multiset_impl &x, multiset_impl &y) +#else +(multiset_impl &x, multiset_impl &y) +#endif +{ x.swap(y); } + +//! Helper metafunction to define a \c multiset that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_multiset +{ + /// @cond + typedef multiset_impl + < typename make_rbtree_opt::type + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class multiset + : public make_multiset::type +{ + typedef typename make_multiset + ::type Base; + + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + multiset( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + multiset( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(b, e, cmp, v_traits) + {} + + static multiset &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const multiset &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static multiset &container_from_iterator(iterator it) + { return static_cast(Base::container_from_iterator(it)); } + + static const multiset &container_from_iterator(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } +}; + +#endif + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_SET_HPP diff --git a/win32/include/boost/intrusive/set_hook.hpp b/win32/include/boost/intrusive/set_hook.hpp new file mode 100755 index 000000000..83103646a --- /dev/null +++ b/win32/include/boost/intrusive/set_hook.hpp @@ -0,0 +1,274 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_SET_HOOK_HPP +#define BOOST_INTRUSIVE_SET_HOOK_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond +template +struct get_set_node_algo +{ + typedef rbtree_algorithms > type; +}; +/// @endcond + +//! Helper metafunction to define a \c set_base_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_set_base_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3, O4>::type packed_options; + + typedef detail::generic_hook + < get_set_node_algo + , typename packed_options::tag + , packed_options::link_mode + , detail::SetBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Derive a class from set_base_hook in order to store objects in +//! in a set/multiset. set_base_hook holds the data necessary to maintain +//! the set/multiset and provides an appropriate value_traits class for set/multiset. +//! +//! The hook admits the following options: \c tag<>, \c void_pointer<>, +//! \c link_mode<> and \c optimize_size<>. +//! +//! \c tag<> defines a tag to identify the node. +//! The same tag value can be used in different classes, but if a class is +//! derived from more than one \c list_base_hook, then each \c list_base_hook needs its +//! unique tag. +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, +//! \c auto_unlink or \c safe_link). +//! +//! \c optimize_size<> will tell the hook to optimize the hook for size instead +//! of speed. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class set_base_hook + : public make_set_base_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + set_base_hook(); + + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + set_base_hook(const set_base_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + set_base_hook& operator=(const set_base_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in a set an assertion is raised. If link_mode is + //! \c auto_unlink and \c is_linked() is true, the node is unlinked. + //! + //! Throws: Nothing. + ~set_base_hook(); + + //! Effects: Swapping two nodes swaps the position of the elements + //! related to those nodes in one or two containers. That is, if the node + //! this is part of the element e1, the node x is part of the element e2 + //! and both elements are included in the containers s1 and s2, then after + //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 + //! at the position of e1. If one element is not in a container, then + //! after the swap-operation the other element is not in a container. + //! Iterators to e1 and e2 related to those nodes are invalidated. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + void swap_nodes(set_base_hook &other); + + //! Precondition: link_mode must be \c safe_link or \c auto_unlink. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c set::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + + //! Effects: Removes the node if it's inserted in a container. + //! This function is only allowed if link_mode is \c auto_unlink. + //! + //! Throws: Nothing. + void unlink(); + #endif +}; + +//! Helper metafunction to define a \c set_member_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_set_member_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3, O4>::type packed_options; + + typedef detail::generic_hook + < get_set_node_algo + , member_tag + , packed_options::link_mode + , detail::NoBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Put a public data member set_member_hook in order to store objects of this class in +//! a set/multiset. set_member_hook holds the data necessary for maintaining the +//! set/multiset and provides an appropriate value_traits class for set/multiset. +//! +//! The hook admits the following options: \c void_pointer<>, +//! \c link_mode<> and \c optimize_size<>. +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, +//! \c auto_unlink or \c safe_link). +//! +//! \c optimize_size<> will tell the hook to optimize the hook for size instead +//! of speed. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class set_member_hook + : public make_set_member_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + set_member_hook(); + + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + set_member_hook(const set_member_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + set_member_hook& operator=(const set_member_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in a set an assertion is raised. If link_mode is + //! \c auto_unlink and \c is_linked() is true, the node is unlinked. + //! + //! Throws: Nothing. + ~set_member_hook(); + + //! Effects: Swapping two nodes swaps the position of the elements + //! related to those nodes in one or two containers. That is, if the node + //! this is part of the element e1, the node x is part of the element e2 + //! and both elements are included in the containers s1 and s2, then after + //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 + //! at the position of e1. If one element is not in a container, then + //! after the swap-operation the other element is not in a container. + //! Iterators to e1 and e2 related to those nodes are invalidated. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + void swap_nodes(set_member_hook &other); + + //! Precondition: link_mode must be \c safe_link or \c auto_unlink. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c set::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + + //! Effects: Removes the node if it's inserted in a container. + //! This function is only allowed if link_mode is \c auto_unlink. + //! + //! Throws: Nothing. + void unlink(); + #endif +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_SET_HOOK_HPP diff --git a/win32/include/boost/intrusive/sg_set.hpp b/win32/include/boost/intrusive/sg_set.hpp new file mode 100755 index 000000000..b1fbfb3cc --- /dev/null +++ b/win32/include/boost/intrusive/sg_set.hpp @@ -0,0 +1,2215 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_SG_SET_HPP +#define BOOST_INTRUSIVE_SG_SET_HPP + +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +//! The class template sg_set is an intrusive container, that mimics most of +//! the interface of std::set as described in the C++ standard. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<> and +//! \c compare<>. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class sg_set_impl +{ + /// @cond + typedef sgtree_impl tree_type; + //! This class is + //! non-copyable + sg_set_impl (const sg_set_impl&); + + //! This class is + //! non-assignable + sg_set_impl &operator =(const sg_set_impl&); + + typedef tree_type implementation_defined; + /// @endcond + + public: + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::value_traits value_traits; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::insert_commit_data insert_commit_data; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; + + /// @cond + private: + tree_type tree_; + /// @endcond + + public: + //! Effects: Constructs an empty sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor of the value_compare object throws. + sg_set_impl( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(cmp, v_traits) + {} + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! cmp must be a comparison function that induces a strict weak ordering. + //! + //! Effects: Constructs an empty sg_set and inserts elements from + //! [b, e). + //! + //! Complexity: Linear in N if [b, e) is already sorted using + //! comp and otherwise N * log N, where N is std::distance(last, first). + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor/operator() of the value_compare object throws. + template + sg_set_impl( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(true, b, e, cmp, v_traits) + {} + + //! Effects: Detaches all elements from this. The objects in the sg_set + //! are not deleted (i.e. no destructors are called). + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + ~sg_set_impl() + {} + + //! Effects: Returns an iterator pointing to the beginning of the sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator begin() + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator begin() const + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cbegin() const + { return tree_.cbegin(); } + + //! Effects: Returns an iterator pointing to the end of the sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return tree_.cend(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning of the + //! reversed sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rbegin() + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rbegin() const + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crbegin() const + { return tree_.crbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rend() + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rend() const + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crend() const + { return tree_.crend(); } + + //! Precondition: end_iterator must be a valid end iterator + //! of sg_set. + //! + //! Effects: Returns a const reference to the sg_set associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static sg_set_impl &container_from_end_iterator(iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &sg_set_impl::tree_); + } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of sg_set. + //! + //! Effects: Returns a const reference to the sg_set associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const sg_set_impl &container_from_end_iterator(const_iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &sg_set_impl::tree_); + } + + //! Precondition: it must be a valid iterator of set. + //! + //! Effects: Returns a reference to the set associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static sg_set_impl &container_from_iterator(iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &sg_set_impl::tree_); + } + + //! Precondition: it must be a valid const_iterator of set. + //! + //! Effects: Returns a const reference to the set associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static const sg_set_impl &container_from_iterator(const_iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &sg_set_impl::tree_); + } + + //! Effects: Returns the key_compare object used by the sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: If key_compare copy-constructor throws. + key_compare key_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns the value_compare object used by the sg_set. + //! + //! Complexity: Constant. + //! + //! Throws: If value_compare copy-constructor throws. + value_compare value_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bool empty() const + { return tree_.empty(); } + + //! Effects: Returns the number of elements stored in the sg_set. + //! + //! Complexity: Linear to elements contained in *this if, + //! constant-time size option is enabled. Constant-time otherwise. + //! + //! Throws: Nothing. + size_type size() const + { return tree_.size(); } + + //! Effects: Swaps the contents of two sets. + //! + //! Complexity: Constant. + //! + //! Throws: If the swap() call for the comparison functor + //! found using ADL throws. Strong guarantee. + void swap(sg_set_impl& other) + { tree_.swap(other.tree_); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. + template + void clone_from(const sg_set_impl &src, Cloner cloner, Disposer disposer) + { tree_.clone_from(src.tree_, cloner, disposer); } + + //! Requires: value must be an lvalue + //! + //! Effects: Tries to inserts value into the sg_set. + //! + //! Returns: If the value + //! is not already present inserts it and returns a pair containing the + //! iterator to the new value and true. If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + std::pair insert(reference value) + { return tree_.insert_unique(value); } + + //! Requires: value must be an lvalue + //! + //! Effects: Tries to to insert x into the sg_set, using "hint" + //! as a hint to where it will be inserted. + //! + //! Returns: An iterator that points to the position where the + //! new element was inserted into the sg_set. + //! + //! Complexity: Logarithmic in general, but it's amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert(const_iterator hint, reference value) + { return tree_.insert_unique(hint, value); } + + //! Requires: key_value_comp must be a comparison function that induces + //! the same strict weak ordering as value_compare. The difference is that + //! key_value_comp compares an ascapegoatitrary key with the contained values. + //! + //! Effects: Checks if a value can be inserted in the sg_set, using + //! a user provided key instead of the value itself. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. If the value can be inserted returns true in the returned + //! pair boolean and fills "commit_data" that is meant to be used with + //! the "insert_commit" function. + //! + //! Complexity: Average complexity is at most logarithmic. + //! + //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! + //! Notes: This function is used to improve performance when constructing + //! a value_type is expensive: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the order is much cheaper to construct + //! than the value_type and this function offers the possibility to use that + //! part to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the value_type and use + //! "insert_commit" to insert the object in constant-time. This gives a total + //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_commit" only if no more + //! objects are inserted or erased from the sg_set. + template + std::pair insert_check + (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { return tree_.insert_unique_check(key, key_value_comp, commit_data); } + + //! Requires: key_value_comp must be a comparison function that induces + //! the same strict weak ordering as value_compare. The difference is that + //! key_value_comp compares an ascapegoatitrary key with the contained values. + //! + //! Effects: Checks if a value can be inserted in the sg_set, using + //! a user provided key instead of the value itself, using "hint" + //! as a hint to where it will be inserted. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. If the value can be inserted returns true in the returned + //! pair boolean and fills "commit_data" that is meant to be used with + //! the "insert_commit" function. + //! + //! Complexity: Logarithmic in general, but it's amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! + //! Notes: This function is used to improve performance when constructing + //! a value_type is expensive: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! constructing that is used to impose the order is much cheaper to construct + //! than the value_type and this function offers the possibility to use that key + //! to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the value_type and use + //! "insert_commit" to insert the object in constant-time. This can give a total + //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_commit" only if no more + //! objects are inserted or erased from the sg_set. + template + std::pair insert_check + (const_iterator hint, const KeyType &key + ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { return tree_.insert_unique_check(hint, key, key_value_comp, commit_data); } + + //! Requires: value must be an lvalue of type value_type. commit_data + //! must have been obtained from a previous call to "insert_check". + //! No objects should have been inserted or erased from the sg_set between + //! the "insert_check" that filled "commit_data" and the call to "insert_commit". + //! + //! Effects: Inserts the value in the sg_set using the information obtained + //! from the "commit_data" that a previous "insert_check" filled. + //! + //! Returns: An iterator to the newly inserted object. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function has only sense if a "insert_check" has been + //! previously executed to fill "commit_data". No value should be inserted or + //! erased between the "insert_check" and "insert_commit" calls. + iterator insert_commit(reference value, const insert_commit_data &commit_data) + { return tree_.insert_unique_commit(value, commit_data); } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Inserts a range into the sg_set. + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert(Iterator b, Iterator e) + { tree_.insert_unique(b, e); } + + //! Effects: Erases the element pointed to by pos. + //! + //! Complexity: Average complexity is constant time. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator i) + { return tree_.erase(i); } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator b, iterator e) + { return tree_.erase(b, e); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size()) + this->count(value)). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return tree_.erase(value); } + + //! Effects: Erases all the elements that compare equal with + //! the given key and the given comparison functor. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(key, comp)). + //! + //! Throws: If the comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyValueCompare comp) + { return tree_.erase(key, comp); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element pointed to by pos. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { return tree_.erase_and_dispose(i, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) + { return tree_.erase_and_dispose(b, e, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: If the internal value_compare ordering function throws. + //! + //! Complexity: O(log(size() + this->count(value)). Basic guarantee. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { return tree_.erase_and_dispose(value, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(key, comp)). + //! + //! Throws: If comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) + { return tree_.erase_and_dispose(key, comp, disposer); } + + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { return tree_.clear(); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + void clear_and_dispose(Disposer disposer) + { return tree_.clear_and_dispose(disposer); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If the internal value_compare ordering function throws. + size_type count(const_reference value) const + { return tree_.find(value) != end(); } + + //! Effects: Returns the number of contained elements with the same key + //! compared with the given comparison functor. + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If comp ordering function throws. + template + size_type count(const KeyType& key, KeyValueCompare comp) const + { return tree_.find(key, comp) != end(); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator lower_bound(const_reference value) + { return tree_.lower_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator lower_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.lower_bound(key, comp); } + + //! Effects: Returns a const iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator lower_bound(const_reference value) const + { return tree_.lower_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const + { return tree_.lower_bound(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator upper_bound(const_reference value) + { return tree_.upper_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator upper_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.upper_bound(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator upper_bound(const_reference value) const + { return tree_.upper_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const + { return tree_.upper_bound(key, comp); } + + //! Effects: Finds an iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator find(const_reference value) + { return tree_.find(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds an iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator find(const KeyType& key, KeyValueCompare comp) + { return tree_.find(key, comp); } + + //! Effects: Finds a const_iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator find(const_reference value) const + { return tree_.find(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a const_iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator find(const KeyType& key, KeyValueCompare comp) const + { return tree_.find(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair equal_range(const_reference value) + { return tree_.equal_range(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return tree_.equal_range(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair + equal_range(const_reference value) const + { return tree_.equal_range(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair + equal_range(const KeyType& key, KeyValueCompare comp) const + { return tree_.equal_range(key, comp); } + + //! Requires: value must be an lvalue and shall be in a sg_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the sg_set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a sg_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! sg_set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a sg_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the sg_set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator iterator_to(reference value) + { return tree_.iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a sg_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! sg_set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator iterator_to(const_reference value) const + { return tree_.iterator_to(value); } + + //! Requires: value shall not be in a sg_set/sg_multiset. + //! + //! Effects: init_node puts the hook of a value in a well-known default + //! state. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This function puts the hook in the well-known default state + //! used by auto_unlink and safe hooks. + static void init_node(reference value) + { tree_type::init_node(value); } + + //! Effects: Unlinks the leftmost node from the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + pointer unlink_leftmost_without_rebalance() + { return tree_.unlink_leftmost_without_rebalance(); } + + //! Requires: replace_this must be a valid iterator of *this + //! and with_this must not be inserted in any tree. + //! + //! Effects: Replaces replace_this in its position in the + //! tree with with_this. The tree does not need to be rebalanced. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! with_this is not equivalent to *replace_this according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + void replace_node(iterator replace_this, reference with_this) + { tree_.replace_node(replace_this, with_this); } + + //! Effects: Rebalances the tree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear. + void rebalance() + { tree_.rebalance(); } + + //! Requires: old_root is a node of a tree. + //! + //! Effects: Rebalances the subtree rooted at old_root. + //! + //! Returns: The new root of the subtree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements in the subtree. + iterator rebalance_subtree(iterator root) + { return tree_.rebalance_subtree(root); } + + //! Returns: The balance factor (alpha) used in this tree + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + float balance_factor() const + { return tree_.balance_factor(); } + + //! Requires: new_alpha must be a value between 0.5 and 1.0 + //! + //! Effects: Establishes a new balance factor (alpha) and rebalances + //! the tree if the new balance factor is stricter (less) than the old factor. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements in the subtree. + void balance_factor(float new_alpha) + { tree_.balance_factor(new_alpha); } + + /// @cond + friend bool operator==(const sg_set_impl &x, const sg_set_impl &y) + { return x.tree_ == y.tree_; } + + friend bool operator<(const sg_set_impl &x, const sg_set_impl &y) + { return x.tree_ < y.tree_; } + /// @endcond +}; + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator!= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const sg_set_impl &x, const sg_set_impl &y) +#else +(const sg_set_impl &x, const sg_set_impl &y) +#endif +{ return !(x == y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator> +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const sg_set_impl &x, const sg_set_impl &y) +#else +(const sg_set_impl &x, const sg_set_impl &y) +#endif +{ return y < x; } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator<= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const sg_set_impl &x, const sg_set_impl &y) +#else +(const sg_set_impl &x, const sg_set_impl &y) +#endif +{ return !(y < x); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator>= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const sg_set_impl &x, const sg_set_impl &y) +#else +(const sg_set_impl &x, const sg_set_impl &y) +#endif +{ return !(x < y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline void swap +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(sg_set_impl &x, sg_set_impl &y) +#else +(sg_set_impl &x, sg_set_impl &y) +#endif +{ x.swap(y); } + +//! Helper metafunction to define a \c sg_set that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_sg_set +{ + /// @cond + typedef sg_set_impl + < typename make_sgtree_opt::type + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class sg_set + : public make_sg_set::type +{ + typedef typename make_sg_set + ::type Base; + + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + sg_set( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + sg_set( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(b, e, cmp, v_traits) + {} + + static sg_set &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const sg_set &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static sg_set &container_from_iterator(iterator it) + { return static_cast(Base::container_from_iterator(it)); } + + static const sg_set &container_from_iterator(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } +}; + +#endif + +//! The class template sg_multiset is an intrusive container, that mimics most of +//! the interface of std::sg_multiset as described in the C++ standard. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<> and +//! \c compare<>. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class sg_multiset_impl +{ + /// @cond + typedef sgtree_impl tree_type; + + //Non-copyable and non-assignable + sg_multiset_impl (const sg_multiset_impl&); + sg_multiset_impl &operator =(const sg_multiset_impl&); + typedef tree_type implementation_defined; + /// @endcond + + public: + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::value_traits value_traits; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::insert_commit_data insert_commit_data; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; + + /// @cond + private: + tree_type tree_; + /// @endcond + + public: + //! Effects: Constructs an empty sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor/operator() of the value_compare object throws. + sg_multiset_impl( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(cmp, v_traits) + {} + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! cmp must be a comparison function that induces a strict weak ordering. + //! + //! Effects: Constructs an empty sg_multiset and inserts elements from + //! [b, e). + //! + //! Complexity: Linear in N if [b, e) is already sorted using + //! comp and otherwise N * log N, where N is the distance between first and last + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor/operator() of the value_compare object throws. + template + sg_multiset_impl( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(false, b, e, cmp, v_traits) + {} + + //! Effects: Detaches all elements from this. The objects in the sg_multiset + //! are not deleted (i.e. no destructors are called). + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + ~sg_multiset_impl() + {} + + //! Effects: Returns an iterator pointing to the beginning of the sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator begin() + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator begin() const + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cbegin() const + { return tree_.cbegin(); } + + //! Effects: Returns an iterator pointing to the end of the sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return tree_.cend(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning of the + //! reversed sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rbegin() + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rbegin() const + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crbegin() const + { return tree_.crbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rend() + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rend() const + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crend() const + { return tree_.crend(); } + + //! Precondition: end_iterator must be a valid end iterator + //! of sg_multiset. + //! + //! Effects: Returns a const reference to the sg_multiset associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static sg_multiset_impl &container_from_end_iterator(iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &sg_multiset_impl::tree_); + } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of sg_multiset. + //! + //! Effects: Returns a const reference to the sg_multiset associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const sg_multiset_impl &container_from_end_iterator(const_iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &sg_multiset_impl::tree_); + } + + //! Precondition: it must be a valid iterator of multiset. + //! + //! Effects: Returns a const reference to the multiset associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static sg_multiset_impl &container_from_iterator(iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &sg_multiset_impl::tree_); + } + + //! Precondition: it must be a valid const_iterator of multiset. + //! + //! Effects: Returns a const reference to the multiset associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const sg_multiset_impl &container_from_iterator(const_iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &sg_multiset_impl::tree_); + } + + //! Effects: Returns the key_compare object used by the sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If key_compare copy-constructor throws. + key_compare key_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns the value_compare object used by the sg_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If value_compare copy-constructor throws. + value_compare value_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bool empty() const + { return tree_.empty(); } + + //! Effects: Returns the number of elements stored in the sg_multiset. + //! + //! Complexity: Linear to elements contained in *this if, + //! constant-time size option is enabled. Constant-time otherwise. + //! + //! Throws: Nothing. + size_type size() const + { return tree_.size(); } + + //! Effects: Swaps the contents of two sg_multisets. + //! + //! Complexity: Constant. + //! + //! Throws: If the swap() call for the comparison functor + //! found using ADL throws. Strong guarantee. + void swap(sg_multiset_impl& other) + { tree_.swap(other.tree_); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. Basic guarantee. + template + void clone_from(const sg_multiset_impl &src, Cloner cloner, Disposer disposer) + { tree_.clone_from(src.tree_, cloner, disposer); } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the sg_multiset. + //! + //! Returns: An iterator that points to the position where the new + //! element was inserted. + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert(reference value) + { return tree_.insert_equal(value); } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts x into the sg_multiset, using pos as a hint to + //! where it will be inserted. + //! + //! Returns: An iterator that points to the position where the new + //! element was inserted. + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert(const_iterator hint, reference value) + { return tree_.insert_equal(hint, value); } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Inserts a range into the sg_multiset. + //! + //! Returns: An iterator that points to the position where the new + //! element was inserted. + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert(Iterator b, Iterator e) + { tree_.insert_equal(b, e); } + + //! Effects: Erases the element pointed to by pos. + //! + //! Complexity: Average complexity is constant time. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator i) + { return tree_.erase(i); } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator b, iterator e) + { return tree_.erase(b, e); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(value)). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return tree_.erase(value); } + + //! Effects: Erases all the elements that compare equal with + //! the given key and the given comparison functor. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(key, comp)). + //! + //! Throws: If comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyValueCompare comp) + { return tree_.erase(key, comp); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Effects: Erases the element pointed to by pos. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { return tree_.erase_and_dispose(i, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) + { return tree_.erase_and_dispose(b, e, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(value)). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { return tree_.erase_and_dispose(value, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + this->count(key, comp)). + //! + //! Throws: If comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) + { return tree_.erase_and_dispose(key, comp, disposer); } + + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { return tree_.clear(); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + void clear_and_dispose(Disposer disposer) + { return tree_.clear_and_dispose(disposer); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If the internal value_compare ordering function throws. + size_type count(const_reference value) const + { return tree_.count(value); } + + //! Effects: Returns the number of contained elements with the same key + //! compared with the given comparison functor. + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If comp ordering function throws. + template + size_type count(const KeyType& key, KeyValueCompare comp) const + { return tree_.count(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator lower_bound(const_reference value) + { return tree_.lower_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator lower_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.lower_bound(key, comp); } + + //! Effects: Returns a const iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator lower_bound(const_reference value) const + { return tree_.lower_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator lower_bound(const KeyType& key, KeyValueCompare comp) const + { return tree_.lower_bound(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator upper_bound(const_reference value) + { return tree_.upper_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator upper_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.upper_bound(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator upper_bound(const_reference value) const + { return tree_.upper_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator upper_bound(const KeyType& key, KeyValueCompare comp) const + { return tree_.upper_bound(key, comp); } + + //! Effects: Finds an iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator find(const_reference value) + { return tree_.find(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds an iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator find(const KeyType& key, KeyValueCompare comp) + { return tree_.find(key, comp); } + + //! Effects: Finds a const_iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator find(const_reference value) const + { return tree_.find(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a const_iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator find(const KeyType& key, KeyValueCompare comp) const + { return tree_.find(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair equal_range(const_reference value) + { return tree_.equal_range(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return tree_.equal_range(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair + equal_range(const_reference value) const + { return tree_.equal_range(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair + equal_range(const KeyType& key, KeyValueCompare comp) const + { return tree_.equal_range(key, comp); } + + //! Requires: value must be an lvalue and shall be in a sg_multiset of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the sg_multiset + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a sg_multiset of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! sg_multiset that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a sg_multiset of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the sg_multiset + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator iterator_to(reference value) + { return tree_.iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a sg_multiset of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! sg_multiset that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator iterator_to(const_reference value) const + { return tree_.iterator_to(value); } + + //! Requires: value shall not be in a sg_multiset/sg_multiset. + //! + //! Effects: init_node puts the hook of a value in a well-known default + //! state. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This function puts the hook in the well-known default state + //! used by auto_unlink and safe hooks. + static void init_node(reference value) + { tree_type::init_node(value); } + + //! Effects: Unlinks the leftmost node from the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + pointer unlink_leftmost_without_rebalance() + { return tree_.unlink_leftmost_without_rebalance(); } + + //! Requires: replace_this must be a valid iterator of *this + //! and with_this must not be inserted in any tree. + //! + //! Effects: Replaces replace_this in its position in the + //! tree with with_this. The tree does not need to be rebalanced. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! with_this is not equivalent to *replace_this according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + void replace_node(iterator replace_this, reference with_this) + { tree_.replace_node(replace_this, with_this); } + + //! Effects: Rebalances the tree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear. + void rebalance() + { tree_.rebalance(); } + + //! Requires: old_root is a node of a tree. + //! + //! Effects: Rebalances the subtree rooted at old_root. + //! + //! Returns: The new root of the subtree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements in the subtree. + iterator rebalance_subtree(iterator root) + { return tree_.rebalance_subtree(root); } + + //! Returns: The balance factor (alpha) used in this tree + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + float balance_factor() const + { return tree_.balance_factor(); } + + //! Requires: new_alpha must be a value between 0.5 and 1.0 + //! + //! Effects: Establishes a new balance factor (alpha) and rebalances + //! the tree if the new balance factor is stricter (less) than the old factor. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements in the subtree. + void balance_factor(float new_alpha) + { tree_.balance_factor(new_alpha); } + + /// @cond + friend bool operator==(const sg_multiset_impl &x, const sg_multiset_impl &y) + { return x.tree_ == y.tree_; } + + friend bool operator<(const sg_multiset_impl &x, const sg_multiset_impl &y) + { return x.tree_ < y.tree_; } + /// @endcond +}; + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator!= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const sg_multiset_impl &x, const sg_multiset_impl &y) +#else +(const sg_multiset_impl &x, const sg_multiset_impl &y) +#endif +{ return !(x == y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator> +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const sg_multiset_impl &x, const sg_multiset_impl &y) +#else +(const sg_multiset_impl &x, const sg_multiset_impl &y) +#endif +{ return y < x; } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator<= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const sg_multiset_impl &x, const sg_multiset_impl &y) +#else +(const sg_multiset_impl &x, const sg_multiset_impl &y) +#endif +{ return !(y < x); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator>= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const sg_multiset_impl &x, const sg_multiset_impl &y) +#else +(const sg_multiset_impl &x, const sg_multiset_impl &y) +#endif +{ return !(x < y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline void swap +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(sg_multiset_impl &x, sg_multiset_impl &y) +#else +(sg_multiset_impl &x, sg_multiset_impl &y) +#endif +{ x.swap(y); } + +//! Helper metafunction to define a \c sg_multiset that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_sg_multiset +{ + /// @cond + typedef sg_multiset_impl + < typename make_sgtree_opt::type + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class sg_multiset + : public make_sg_multiset::type +{ + typedef typename make_sg_multiset + ::type Base; + + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + sg_multiset( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + sg_multiset( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(b, e, cmp, v_traits) + {} + + static sg_multiset &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const sg_multiset &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static sg_multiset &container_from_iterator(iterator it) + { return static_cast(Base::container_from_iterator(it)); } + + static const sg_multiset &container_from_iterator(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } +}; + +#endif + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_SG_SET_HPP diff --git a/win32/include/boost/intrusive/sgtree.hpp b/win32/include/boost/intrusive/sgtree.hpp new file mode 100755 index 000000000..123944746 --- /dev/null +++ b/win32/include/boost/intrusive/sgtree.hpp @@ -0,0 +1,1673 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +// +// The option that yields to non-floating point 1/sqrt(2) alpha is taken +// from the scapegoat tree implementation of the PSPP library. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_SGTREE_HPP +#define BOOST_INTRUSIVE_SGTREE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond + +namespace detail{ + +//! Returns floor(log(n)/log(sqrt(2))) -> floor(2*log2(n)) +//! Undefined if N is 0. +//! +//! This function does not use float point operations. +inline std::size_t calculate_h_sqrt2 (std::size_t n) +{ + std::size_t f_log2 = detail::floor_log2(n); + return (2*f_log2) + (n >= detail::sqrt2_pow_2xplus1 (f_log2)); +} + +struct h_alpha_sqrt2_t +{ + h_alpha_sqrt2_t(void){} + std::size_t operator()(std::size_t n) const + { return calculate_h_sqrt2(n); } +}; + +struct alpha_0_75_by_max_size_t +{ + alpha_0_75_by_max_size_t(void){} + std::size_t operator()(std::size_t max_tree_size) const + { + const std::size_t max_tree_size_limit = ((~std::size_t(0))/std::size_t(3)); + return max_tree_size > max_tree_size_limit ? max_tree_size/4*3 : max_tree_size*3/4; + } +}; + +struct h_alpha_t +{ + h_alpha_t(float inv_minus_logalpha) + : inv_minus_logalpha_(inv_minus_logalpha) + {} + + std::size_t operator()(std::size_t n) const + { + //Returns floor(log1/alpha(n)) -> + // floor(log(n)/log(1/alpha)) -> + // floor(log(n)/(-log(alpha))) + //return static_cast(std::log(float(n))*inv_minus_logalpha_); + return static_cast(detail::fast_log2(float(n))*inv_minus_logalpha_); + } + + private: + //Since the function will be repeatedly called + //precalculate constant data to avoid repeated + //calls to log and division. + //This will store 1/(-std::log(alpha_)) + float inv_minus_logalpha_; +}; + +struct alpha_by_max_size_t +{ + alpha_by_max_size_t(float alpha) + : alpha_(alpha) + {} + + float operator()(std::size_t max_tree_size) const + { return float(max_tree_size)*alpha_; } + + private: + float alpha_; + float inv_minus_logalpha_; +}; + +template +struct alpha_holder +{ + typedef boost::intrusive::detail::h_alpha_t h_alpha_t; + typedef boost::intrusive::detail::alpha_by_max_size_t multiply_by_alpha_t; + + alpha_holder() + { set_alpha(0.7f); } + + float get_alpha() const + { return alpha_; } + + void set_alpha(float alpha) + { + alpha_ = alpha; + inv_minus_logalpha_ = 1/(-detail::fast_log2(alpha)); + } + + h_alpha_t get_h_alpha_t() const + { return h_alpha_t(inv_minus_logalpha_); } + + multiply_by_alpha_t get_multiply_by_alpha_t() const + { return multiply_by_alpha_t(alpha_); } + + private: + float alpha_; + float inv_minus_logalpha_; +}; + +template<> +struct alpha_holder +{ + //This specialization uses alpha = 1/sqrt(2) + //without using floating point operations + //Downside: alpha CAN't be changed. + typedef boost::intrusive::detail::h_alpha_sqrt2_t h_alpha_t; + typedef boost::intrusive::detail::alpha_0_75_by_max_size_t multiply_by_alpha_t; + + float get_alpha() const + { return 0.70710677f; } + + void set_alpha(float) + { //alpha CAN't be changed. + assert(0); + } + + h_alpha_t get_h_alpha_t() const + { return h_alpha_t(); } + + multiply_by_alpha_t get_multiply_by_alpha_t() const + { return multiply_by_alpha_t(); } +}; + +} //namespace detail{ + +template +struct sg_setopt +{ + typedef ValueTraits value_traits; + typedef Compare compare; + typedef SizeType size_type; + static const bool floating_point = FloatingPoint; +}; + +template +struct sg_set_defaults + : pack_options + < none + , base_hook + < typename detail::eval_if_c + < internal_default_bs_set_hook::value + , get_default_bs_set_hook + , detail::identity + >::type + > + , floating_point + , size_type + , compare > + >::type +{}; + +/// @endcond + +//! The class template sgtree is an intrusive scapegoat tree container, that +//! is used to construct intrusive sg_set and sg_multiset containers. +//! The no-throw guarantee holds only, if the value_compare object +//! doesn't throw. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c floating_point<>, \c size_type<> and +//! \c compare<>. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class sgtree_impl +{ + public: + typedef typename Config::value_traits value_traits; + /// @cond + static const bool external_value_traits = + detail::external_value_traits_is_true::value; + typedef typename detail::eval_if_c + < external_value_traits + , detail::eval_value_traits + , detail::identity + >::type real_value_traits; + /// @endcond + typedef typename real_value_traits::pointer pointer; + typedef typename real_value_traits::const_pointer const_pointer; + typedef typename std::iterator_traits::value_type value_type; + typedef value_type key_type; + typedef typename std::iterator_traits::reference reference; + typedef typename std::iterator_traits::reference const_reference; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename Config::size_type size_type; + typedef typename Config::compare value_compare; + typedef value_compare key_compare; + typedef tree_iterator iterator; + typedef tree_iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef typename real_value_traits::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + typedef sgtree_algorithms node_algorithms; + + static const bool floating_point = Config::floating_point; + static const bool constant_time_size = true; + static const bool stateful_value_traits = detail::store_cont_ptr_on_it::value; + + /// @cond + private: + typedef detail::size_holder size_traits; + typedef detail::alpha_holder alpha_traits; + typedef typename alpha_traits::h_alpha_t h_alpha_t; + typedef typename alpha_traits::multiply_by_alpha_t multiply_by_alpha_t; + + //noncopyable + sgtree_impl (const sgtree_impl&); + sgtree_impl operator =(const sgtree_impl&); + + enum { safemode_or_autounlink = + (int)real_value_traits::link_mode == (int)auto_unlink || + (int)real_value_traits::link_mode == (int)safe_link }; + + BOOST_STATIC_ASSERT(((int)real_value_traits::link_mode != (int)auto_unlink)); + + //BOOST_STATIC_ASSERT(( + // (int)real_value_traits::link_mode != (int)auto_unlink || + // !floating_point + // )); + + struct header_plus_alpha : public alpha_traits + { node header_; }; + + struct node_plus_pred_t : public detail::ebo_functor_holder + { + node_plus_pred_t(const value_compare &comp) + : detail::ebo_functor_holder(comp) + {} + header_plus_alpha header_plus_alpha_; + size_traits size_traits_; + }; + + struct data_t : public sgtree_impl::value_traits + { + typedef typename sgtree_impl::value_traits value_traits; + data_t(const value_compare & comp, const value_traits &val_traits) + : value_traits(val_traits), node_plus_pred_(comp) + , max_tree_size_(0) + {} + node_plus_pred_t node_plus_pred_; + size_type max_tree_size_; + } data_; + + float priv_alpha() const + { return this->priv_alpha_traits().get_alpha(); } + + void priv_alpha(float alpha) + { return this->priv_alpha_traits().set_alpha(alpha); } + + const value_compare &priv_comp() const + { return data_.node_plus_pred_.get(); } + + value_compare &priv_comp() + { return data_.node_plus_pred_.get(); } + + const node &priv_header() const + { return data_.node_plus_pred_.header_plus_alpha_.header_; } + + node &priv_header() + { return data_.node_plus_pred_.header_plus_alpha_.header_; } + + static node_ptr uncast(const_node_ptr ptr) + { return node_ptr(const_cast(detail::get_pointer(ptr))); } + + size_traits &priv_size_traits() + { return data_.node_plus_pred_.size_traits_; } + + const size_traits &priv_size_traits() const + { return data_.node_plus_pred_.size_traits_; } + + alpha_traits &priv_alpha_traits() + { return data_.node_plus_pred_.header_plus_alpha_; } + + const alpha_traits &priv_alpha_traits() const + { return data_.node_plus_pred_.header_plus_alpha_; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return data_; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return data_.get_value_traits(*this); } + + real_value_traits &get_real_value_traits(detail::bool_) + { return data_; } + + real_value_traits &get_real_value_traits(detail::bool_) + { return data_.get_value_traits(*this); } + + h_alpha_t get_h_alpha_func() const + { return priv_alpha_traits().get_h_alpha_t(); } + + multiply_by_alpha_t get_alpha_by_max_size_func() const + { return priv_alpha_traits().get_multiply_by_alpha_t(); } + + /// @endcond + + public: + + const real_value_traits &get_real_value_traits() const + { return this->get_real_value_traits(detail::bool_()); } + + real_value_traits &get_real_value_traits() + { return this->get_real_value_traits(detail::bool_()); } + + typedef typename node_algorithms::insert_commit_data insert_commit_data; + + //! Effects: Constructs an empty tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing unless the copy constructor of the value_compare object throws. + sgtree_impl( value_compare cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : data_(cmp, v_traits) + { + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(size_type(0)); + } + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! cmp must be a comparison function that induces a strict weak ordering. + //! + //! Effects: Constructs an empty tree and inserts elements from + //! [b, e). + //! + //! Complexity: Linear in N if [b, e) is already sorted using + //! comp and otherwise N * log N, where N is the distance between first and last. + //! + //! Throws: Nothing unless the copy constructor of the value_compare object throws. + template + sgtree_impl( bool unique, Iterator b, Iterator e + , value_compare cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : data_(cmp, v_traits) + { + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(size_type(0)); + if(unique) + this->insert_unique(b, e); + else + this->insert_equal(b, e); + } + + //! Effects: Detaches all elements from this. The objects in the set + //! are not deleted (i.e. no destructors are called), but the nodes according to + //! the value_traits template parameter are reinitialized and thus can be reused. + //! + //! Complexity: Linear to elements contained in *this. + //! + //! Throws: Nothing. + ~sgtree_impl() + { this->clear(); } + + //! Effects: Returns an iterator pointing to the beginning of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator begin() + { return iterator (node_traits::get_left(node_ptr(&priv_header())), this); } + + //! Effects: Returns a const_iterator pointing to the beginning of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator begin() const + { return cbegin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cbegin() const + { return const_iterator (node_traits::get_left(const_node_ptr(&priv_header())), this); } + + //! Effects: Returns an iterator pointing to the end of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return iterator (node_ptr(&priv_header()), this); } + + //! Effects: Returns a const_iterator pointing to the end of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return cend(); } + + //! Effects: Returns a const_iterator pointing to the end of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return const_iterator (uncast(const_node_ptr(&priv_header())), this); } + + //! Effects: Returns a reverse_iterator pointing to the beginning of the + //! reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rbegin() + { return reverse_iterator(end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rbegin() const + { return const_reverse_iterator(end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crbegin() const + { return const_reverse_iterator(end()); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rend() + { return reverse_iterator(begin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rend() const + { return const_reverse_iterator(begin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crend() const + { return const_reverse_iterator(begin()); } + + //! Precondition: end_iterator must be a valid end iterator + //! of sgtree. + //! + //! Effects: Returns a const reference to the sgtree associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static sgtree_impl &container_from_end_iterator(iterator end_iterator) + { return priv_container_from_end_iterator(end_iterator); } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of sgtree. + //! + //! Effects: Returns a const reference to the sgtree associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const sgtree_impl &container_from_end_iterator(const_iterator end_iterator) + { return priv_container_from_end_iterator(end_iterator); } + + //! Precondition: it must be a valid iterator + //! of rbtree. + //! + //! Effects: Returns a const reference to the tree associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static sgtree_impl &container_from_iterator(iterator it) + { return priv_container_from_iterator(it); } + + //! Precondition: it must be a valid end const_iterator + //! of rbtree. + //! + //! Effects: Returns a const reference to the tree associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static const sgtree_impl &container_from_iterator(const_iterator it) + { return priv_container_from_iterator(it); } + + //! Effects: Returns the value_compare object used by the tree. + //! + //! Complexity: Constant. + //! + //! Throws: If value_compare copy-constructor throws. + value_compare value_comp() const + { return priv_comp(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bool empty() const + { return node_algorithms::unique(const_node_ptr(&priv_header())); } + + //! Effects: Returns the number of elements stored in the tree. + //! + //! Complexity: Linear to elements contained in *this. + //! + //! Throws: Nothing. + size_type size() const + { + if(constant_time_size) + return this->priv_size_traits().get_size(); + else{ + return (size_type)node_algorithms::size(const_node_ptr(&priv_header())); + } + } + + //! Effects: Swaps the contents of two multisets. + //! + //! Complexity: Constant. + //! + //! Throws: If the comparison functor's swap call throws. + void swap(sgtree_impl& other) + { + //This can throw + using std::swap; + swap(priv_comp(), priv_comp()); + swap(priv_alpha_traits(), priv_alpha_traits()); + swap(data_.max_tree_size_, other.data_.max_tree_size_); + //These can't throw + node_algorithms::swap_tree(node_ptr(&priv_header()), node_ptr(&other.priv_header())); + if(constant_time_size){ + size_type backup = this->priv_size_traits().get_size(); + this->priv_size_traits().set_size(other.priv_size_traits().get_size()); + other.priv_size_traits().set_size(backup); + } + } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the tree before the upper bound. + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_equal(reference value) + { + detail::key_nodeptr_comp + key_node_comp(priv_comp(), this); + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + std::size_t max_tree_size = (std::size_t)data_.max_tree_size_; + node_ptr p = node_algorithms::insert_equal_upper_bound + (node_ptr(&priv_header()), to_insert, key_node_comp + , (size_type)this->size(), this->get_h_alpha_func(), max_tree_size); + data_.max_tree_size_ = (size_type)max_tree_size; + return iterator(p, this); + } + + //! Requires: value must be an lvalue, and "hint" must be + //! a valid iterator. + //! + //! Effects: Inserts x into the tree, using "hint" as a hint to + //! where it will be inserted. If "hint" is the upper_bound + //! the insertion takes constant time (two comparisons in the worst case) + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_equal(const_iterator hint, reference value) + { + detail::key_nodeptr_comp + key_node_comp(priv_comp(), this); + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + std::size_t max_tree_size = (std::size_t)data_.max_tree_size_; + node_ptr p = node_algorithms::insert_equal + (node_ptr(&priv_header()), hint.pointed_node(), to_insert, key_node_comp + , (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size); + data_.max_tree_size_ = (size_type)max_tree_size; + return iterator(p, this); + } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Inserts a each element of a range into the tree + //! before the upper bound of the key of each element. + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert_equal(Iterator b, Iterator e) + { + iterator end(this->end()); + for (; b != e; ++b) + this->insert_equal(end, *b); + } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the tree if the value + //! is not already present. + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + std::pair insert_unique(reference value) + { + insert_commit_data commit_data; + std::pair ret = insert_unique_check(value, commit_data); + if(!ret.second) + return ret; + return std::pair (insert_unique_commit(value, commit_data), true); + } + + //! Requires: value must be an lvalue, and "hint" must be + //! a valid iterator + //! + //! Effects: Tries to insert x into the tree, using "hint" as a hint + //! to where it will be inserted. + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time (two comparisons in the worst case) + //! if t is inserted immediately before hint. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_unique(const_iterator hint, reference value) + { + insert_commit_data commit_data; + std::pair ret = insert_unique_check(hint, value, commit_data); + if(!ret.second) + return ret.first; + return insert_unique_commit(value, commit_data); + } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Tries to insert each element of a range into the tree. + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert_unique(Iterator b, Iterator e) + { + if(this->empty()){ + iterator end(this->end()); + for (; b != e; ++b) + this->insert_unique(end, *b); + } + else{ + for (; b != e; ++b) + this->insert_unique(*b); + } + } + + std::pair insert_unique_check + (const_reference value, insert_commit_data &commit_data) + { return insert_unique_check(value, priv_comp(), commit_data); } + + template + std::pair insert_unique_check + (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { + detail::key_nodeptr_comp + comp(key_value_comp, this); + std::pair ret = + (node_algorithms::insert_unique_check + (node_ptr(&priv_header()), key, comp, commit_data)); + return std::pair(iterator(ret.first, this), ret.second); + } + + std::pair insert_unique_check + (const_iterator hint, const_reference value, insert_commit_data &commit_data) + { return insert_unique_check(hint, value, priv_comp(), commit_data); } + + template + std::pair insert_unique_check + (const_iterator hint, const KeyType &key + ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { + detail::key_nodeptr_comp + comp(key_value_comp, this); + std::pair ret = + (node_algorithms::insert_unique_check + (node_ptr(&priv_header()), hint.pointed_node(), key, comp, commit_data)); + return std::pair(iterator(ret.first, this), ret.second); + } + + iterator insert_unique_commit(reference value, const insert_commit_data &commit_data) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + std::size_t max_tree_size = (std::size_t)data_.max_tree_size_; + node_algorithms::insert_unique_commit + ( node_ptr(&priv_header()), to_insert, commit_data + , (std::size_t)this->size(), this->get_h_alpha_func(), max_tree_size); + data_.max_tree_size_ = (size_type)max_tree_size; + return iterator(to_insert, this); + } + + //! Effects: Erases the element pointed to by pos. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator i) + { + iterator ret(i); + ++ret; + node_ptr to_erase(i.pointed_node()); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase)); + std::size_t max_tree_size = data_.max_tree_size_; + node_algorithms::erase + ( &priv_header(), to_erase, (std::size_t)this->size() + , max_tree_size, this->get_alpha_by_max_size_func()); + data_.max_tree_size_ = (size_type)max_tree_size; + this->priv_size_traits().decrement(); + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + return ret; + } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator b, iterator e) + { size_type n; return private_erase(b, e, n); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return this->erase(value, priv_comp()); } + + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyValueCompare comp) + { + std::pair p = this->equal_range(key, comp); + size_type n; + private_erase(p.first, p.second, n); + return n; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element pointed to by pos. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { + node_ptr to_erase(i.pointed_node()); + iterator ret(this->erase(i)); + disposer(get_real_value_traits().to_value_ptr(to_erase)); + return ret; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) + { size_type n; return private_erase(b, e, n, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { + std::pair p = this->equal_range(value); + size_type n; + private_erase(p.first, p.second, n, disposer); + return n; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) + { + std::pair p = this->equal_range(key, comp); + size_type n; + private_erase(p.first, p.second, n, disposer); + return n; + } + + //! Effects: Erases all of the elements. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { + if(safemode_or_autounlink){ + this->clear_and_dispose(detail::null_disposer()); + } + else{ + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(0); + } + } + + //! Effects: Erases all of the elements calling disposer(p) for + //! each node to be erased. + //! Complexity: Average complexity for is at most O(log(size() + N)), + //! where N is the number of elements in the container. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. Calls N times to disposer functor. + template + void clear_and_dispose(Disposer disposer) + { + node_algorithms::clear_and_dispose(node_ptr(&priv_header()) + , detail::node_disposer(disposer, this)); + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(0); + } + + //! Effects: Returns the number of contained elements with the given value + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given value. + //! + //! Throws: Nothing. + size_type count(const_reference value) const + { return this->count(value, priv_comp()); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: Nothing. + template + size_type count(const KeyType &key, KeyValueCompare comp) const + { + std::pair ret = this->equal_range(key, comp); + return std::distance(ret.first, ret.second); + } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + iterator lower_bound(const_reference value) + { return this->lower_bound(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator lower_bound(const_reference value) const + { return this->lower_bound(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + iterator lower_bound(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return iterator(node_algorithms::lower_bound + (const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Returns a const iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator lower_bound(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return const_iterator(node_algorithms::lower_bound + (const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + iterator upper_bound(const_reference value) + { return this->upper_bound(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k according to comp or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + iterator upper_bound(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return iterator(node_algorithms::upper_bound + (const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator upper_bound(const_reference value) const + { return this->upper_bound(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k according to comp or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator upper_bound(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return const_iterator(node_algorithms::upper_bound + (const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Finds an iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + iterator find(const_reference value) + { return this->find(value, priv_comp()); } + + //! Effects: Finds an iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + iterator find(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return iterator + (node_algorithms::find(const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Finds a const_iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator find(const_reference value) const + { return this->find(value, priv_comp()); } + + //! Effects: Finds a const_iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator find(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return const_iterator + (node_algorithms::find(const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + std::pair equal_range(const_reference value) + { return this->equal_range(value, priv_comp()); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + std::pair equal_range(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + std::pair ret + (node_algorithms::equal_range(const_node_ptr(&priv_header()), key, key_node_comp)); + return std::pair(iterator(ret.first, this), iterator(ret.second, this)); + } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + std::pair + equal_range(const_reference value) const + { return this->equal_range(value, priv_comp()); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + std::pair + equal_range(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + std::pair ret + (node_algorithms::equal_range(const_node_ptr(&priv_header()), key, key_node_comp)); + return std::pair(const_iterator(ret.first, this), const_iterator(ret.second, this)); + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. + template + void clone_from(const sgtree_impl &src, Cloner cloner, Disposer disposer) + { + this->clear_and_dispose(disposer); + if(!src.empty()){ + node_algorithms::clone + (const_node_ptr(&src.priv_header()) + ,node_ptr(&this->priv_header()) + ,detail::node_cloner(cloner, this) + ,detail::node_disposer(disposer, this)); + this->priv_size_traits().set_size(src.priv_size_traits().get_size()); + } + } + + //! Effects: Unlinks the leftmost node from the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + pointer unlink_leftmost_without_rebalance() + { + node_ptr to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance + (node_ptr(&priv_header()))); + if(!to_be_disposed) + return 0; + this->priv_size_traits().decrement(); + if(safemode_or_autounlink)//If this is commented does not work with normal_link + node_algorithms::init(to_be_disposed); + return get_real_value_traits().to_value_ptr(to_be_disposed); + } + + //! Requires: replace_this must be a valid iterator of *this + //! and with_this must not be inserted in any tree. + //! + //! Effects: Replaces replace_this in its position in the + //! tree with with_this. The tree does not need to be rebalanced. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! with_this is not equivalent to *replace_this according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + void replace_node(iterator replace_this, reference with_this) + { + node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this) + , node_ptr(&priv_header()) + , get_real_value_traits().to_node_ptr(with_this)); + } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + return iterator (value_traits::to_node_ptr(value), 0); + } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), 0); + } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator iterator_to(reference value) + { return iterator (value_traits::to_node_ptr(value), this); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator iterator_to(const_reference value) const + { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this); } + + //! Requires: value shall not be in a tree. + //! + //! Effects: init_node puts the hook of a value in a well-known default + //! state. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This function puts the hook in the well-known default state + //! used by auto_unlink and safe hooks. + static void init_node(reference value) + { node_algorithms::init(value_traits::to_node_ptr(value)); } + + //! Effects: Rebalances the tree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear. + void rebalance() + { node_algorithms::rebalance(node_ptr(&priv_header())); } + + //! Requires: old_root is a node of a tree. + //! + //! Effects: Rebalances the subtree rooted at old_root. + //! + //! Returns: The new root of the subtree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements in the subtree. + iterator rebalance_subtree(iterator root) + { return iterator(node_algorithms::rebalance_subtree(root.pointed_node()), this); } + + //! Returns: The balance factor (alpha) used in this tree + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + float balance_factor() const + { return this->priv_alpha(); } + + //! Requires: new_alpha must be a value between 0.5 and 1.0 + //! + //! Effects: Establishes a new balance factor (alpha) and rebalances + //! the tree if the new balance factor is stricter (less) than the old factor. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements in the subtree. + void balance_factor(float new_alpha) + { + BOOST_INTRUSIVE_INVARIANT_ASSERT((new_alpha > 0.5f && new_alpha < 1.0f)); + if(new_alpha < 0.5f && new_alpha >= 1.0f) return; + + //The alpha factor CAN't be changed if the fixed, floating operation-less + //1/sqrt(2) alpha factor option is activated + BOOST_STATIC_ASSERT((floating_point)); + float old_alpha = this->priv_alpha(); + this->priv_alpha(new_alpha); + + if(new_alpha < old_alpha){ + data_.max_tree_size_ = this->size(); + this->rebalance(); + } + } +/* + //! Effects: removes x from a tree of the appropriate type. It has no effect, + //! if x is not in such a tree. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This static function is only usable with the "safe mode" + //! hook and non-constant time size lists. Otherwise, the user must use + //! the non-static "erase(reference )" member. If the user calls + //! this function with a non "safe mode" or constant time size list + //! a compilation error will be issued. + template + static void remove_node(T& value) + { + //This function is only usable for safe mode hooks and non-constant + //time lists. + //BOOST_STATIC_ASSERT((!(safemode_or_autounlink && constant_time_size))); + BOOST_STATIC_ASSERT((!constant_time_size)); + BOOST_STATIC_ASSERT((boost::is_convertible::value)); + node_ptr to_remove(value_traits::to_node_ptr(value)); + node_algorithms::unlink_and_rebalance(to_remove); + if(safemode_or_autounlink) + node_algorithms::init(to_remove); + } +*/ + + /// @cond + private: + template + iterator private_erase(iterator b, iterator e, size_type &n, Disposer disposer) + { + for(n = 0; b != e; ++n) + this->erase_and_dispose(b++, disposer); + return b; + } + + iterator private_erase(iterator b, iterator e, size_type &n) + { + for(n = 0; b != e; ++n) + this->erase(b++); + return b; + } + /// @endcond + + private: + static sgtree_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) + { + header_plus_alpha *r = detail::parent_from_member + ( detail::get_pointer(end_iterator.pointed_node()), &header_plus_alpha::header_); + node_plus_pred_t *n = detail::parent_from_member + (r, &node_plus_pred_t::header_plus_alpha_); + data_t *d = detail::parent_from_member(n, &data_t::node_plus_pred_); + sgtree_impl *scapegoat = detail::parent_from_member(d, &sgtree_impl::data_); + return *scapegoat; + } + + static sgtree_impl &priv_container_from_iterator(const const_iterator &it) + { return priv_container_from_end_iterator(it.end_iterator_from_it()); } +}; + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator< +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const sgtree_impl &x, const sgtree_impl &y) +#else +(const sgtree_impl &x, const sgtree_impl &y) +#endif +{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +bool operator== +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const sgtree_impl &x, const sgtree_impl &y) +#else +(const sgtree_impl &x, const sgtree_impl &y) +#endif +{ + typedef sgtree_impl tree_type; + typedef typename tree_type::const_iterator const_iterator; + + if(tree_type::constant_time_size && x.size() != y.size()){ + return false; + } + const_iterator end1 = x.end(); + const_iterator i1 = x.begin(); + const_iterator i2 = y.begin(); + if(tree_type::constant_time_size){ + while (i1 != end1 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1; + } + else{ + const_iterator end2 = y.end(); + while (i1 != end1 && i2 != end2 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1 && i2 == end2; + } +} + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator!= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const sgtree_impl &x, const sgtree_impl &y) +#else +(const sgtree_impl &x, const sgtree_impl &y) +#endif +{ return !(x == y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator> +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const sgtree_impl &x, const sgtree_impl &y) +#else +(const sgtree_impl &x, const sgtree_impl &y) +#endif +{ return y < x; } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator<= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const sgtree_impl &x, const sgtree_impl &y) +#else +(const sgtree_impl &x, const sgtree_impl &y) +#endif +{ return !(y < x); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator>= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const sgtree_impl &x, const sgtree_impl &y) +#else +(const sgtree_impl &x, const sgtree_impl &y) +#endif +{ return !(x < y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline void swap +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(sgtree_impl &x, sgtree_impl &y) +#else +(sgtree_impl &x, sgtree_impl &y) +#endif +{ x.swap(y); } + +/// @cond +template +struct make_sgtree_opt +{ + typedef typename pack_options + < sg_set_defaults, O1, O2, O3, O4>::type packed_options; + typedef typename detail::get_value_traits + ::type value_traits; + + typedef sg_setopt + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::floating_point + > type; +}; +/// @endcond + +//! Helper metafunction to define a \c sgtree that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_sgtree +{ + /// @cond + typedef sgtree_impl + < typename make_sgtree_opt::type + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class sgtree + : public make_sgtree::type +{ + typedef typename make_sgtree + ::type Base; + + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::real_value_traits real_value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + sgtree( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + sgtree( bool unique, Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(unique, b, e, cmp, v_traits) + {} + + static sgtree &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const sgtree &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } +}; + +#endif + + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_SGTREE_HPP diff --git a/win32/include/boost/intrusive/sgtree_algorithms.hpp b/win32/include/boost/intrusive/sgtree_algorithms.hpp new file mode 100755 index 000000000..56659c811 --- /dev/null +++ b/win32/include/boost/intrusive/sgtree_algorithms.hpp @@ -0,0 +1,713 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007. +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +// +// Scapegoat tree algorithms are taken from the paper titled: +// "Scapegoat Trees" by Igal Galperin Ronald L. Rivest. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_SGTREE_ALGORITHMS_HPP +#define BOOST_INTRUSIVE_SGTREE_ALGORITHMS_HPP + +#include + +#include +#include +#include +#include +#include + + +namespace boost { +namespace intrusive { + +//! sgtree_algorithms is configured with a NodeTraits class, which encapsulates the +//! information about the node to be manipulated. NodeTraits must support the +//! following interface: +//! +//! Typedefs: +//! +//! node: The type of the node that forms the circular list +//! +//! node_ptr: A pointer to a node +//! +//! const_node_ptr: A pointer to a const node +//! +//! Static functions: +//! +//! static node_ptr get_parent(const_node_ptr n); +//! +//! static void set_parent(node_ptr n, node_ptr parent); +//! +//! static node_ptr get_left(const_node_ptr n); +//! +//! static void set_left(node_ptr n, node_ptr left); +//! +//! static node_ptr get_right(const_node_ptr n); +//! +//! static void set_right(node_ptr n, node_ptr right); +template +class sgtree_algorithms +{ + public: + typedef typename NodeTraits::node node; + typedef NodeTraits node_traits; + typedef typename NodeTraits::node_ptr node_ptr; + typedef typename NodeTraits::const_node_ptr const_node_ptr; + + /// @cond + private: + + typedef detail::tree_algorithms tree_algorithms; + + static node_ptr uncast(const_node_ptr ptr) + { + return node_ptr(const_cast(::boost::intrusive::detail::get_pointer(ptr))); + } + /// @endcond + + public: + static node_ptr begin_node(const_node_ptr header) + { return tree_algorithms::begin_node(header); } + + static node_ptr end_node(const_node_ptr header) + { return tree_algorithms::end_node(header); } + + //! This type is the information that will be + //! filled by insert_unique_check + struct insert_commit_data + : tree_algorithms::insert_commit_data + { + std::size_t depth; + }; + + //! Requires: header1 and header2 must be the header nodes + //! of two trees. + //! + //! Effects: Swaps two trees. After the function header1 will contain + //! links to the second tree and header2 will have links to the first tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static void swap_tree(node_ptr header1, node_ptr header2) + { return tree_algorithms::swap_tree(header1, header2); } + + //! Requires: node1 and node2 can't be header nodes + //! of two trees. + //! + //! Effects: Swaps two nodes. After the function node1 will be inserted + //! in the position node2 before the function. node2 will be inserted in the + //! position node1 had before the function. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! node1 and node2 are not equivalent according to the ordering rules. + //! + //!Experimental function + static void swap_nodes(node_ptr node1, node_ptr node2) + { + if(node1 == node2) + return; + + node_ptr header1(tree_algorithms::get_header(node1)), header2(tree_algorithms::get_header(node2)); + swap_nodes(node1, header1, node2, header2); + } + + //! Requires: node1 and node2 can't be header nodes + //! of two trees with header header1 and header2. + //! + //! Effects: Swaps two nodes. After the function node1 will be inserted + //! in the position node2 before the function. node2 will be inserted in the + //! position node1 had before the function. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! node1 and node2 are not equivalent according to the ordering rules. + //! + //!Experimental function + static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, node_ptr header2) + { tree_algorithms::swap_nodes(node1, header1, node2, header2); } + + //! Requires: node_to_be_replaced must be inserted in a tree + //! and new_node must not be inserted in a tree. + //! + //! Effects: Replaces node_to_be_replaced in its position in the + //! tree with new_node. The tree does not need to be rebalanced + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! new_node is not equivalent to node_to_be_replaced according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing and comparison is needed. + //! + //!Experimental function + static void replace_node(node_ptr node_to_be_replaced, node_ptr new_node) + { + if(node_to_be_replaced == new_node) + return; + replace_node(node_to_be_replaced, tree_algorithms::get_header(node_to_be_replaced), new_node); + } + + //! Requires: node_to_be_replaced must be inserted in a tree + //! with header "header" and new_node must not be inserted in a tree. + //! + //! Effects: Replaces node_to_be_replaced in its position in the + //! tree with new_node. The tree does not need to be rebalanced + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! new_node is not equivalent to node_to_be_replaced according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + //! + //!Experimental function + static void replace_node(node_ptr node_to_be_replaced, node_ptr header, node_ptr new_node) + { tree_algorithms::replace_node(node_to_be_replaced, header, new_node); } + + //! Requires: node is a tree node but not the header. + //! + //! Effects: Unlinks the node and rebalances the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + static void unlink(node_ptr node) + { + node_ptr x = NodeTraits::get_parent(node); + if(x){ + while(!is_header(x)) + x = NodeTraits::get_parent(x); + tree_algorithms::erase(x, node); + } + } + + //! Requires: header is the header of a tree. + //! + //! Effects: Unlinks the leftmost node from the tree, and + //! updates the header link to the new leftmost node. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + static node_ptr unlink_leftmost_without_rebalance(node_ptr header) + { return tree_algorithms::unlink_leftmost_without_rebalance(header); } + + //! Requires: node is a node of the tree or an node initialized + //! by init(...). + //! + //! Effects: Returns true if the node is initialized by init(). + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + static bool unique(const_node_ptr node) + { return tree_algorithms::unique(node); } + + //! Requires: node is a node of the tree but it's not the header. + //! + //! Effects: Returns the number of nodes of the subtree. + //! + //! Complexity: Linear time. + //! + //! Throws: Nothing. + static std::size_t count(const_node_ptr node) + { return tree_algorithms::count(node); } + + //! Requires: header is the header node of the tree. + //! + //! Effects: Returns the number of nodes above the header. + //! + //! Complexity: Linear time. + //! + //! Throws: Nothing. + static std::size_t size(const_node_ptr header) + { return tree_algorithms::size(header); } + + //! Requires: p is a node from the tree except the header. + //! + //! Effects: Returns the next node of the tree. + //! + //! Complexity: Average constant time. + //! + //! Throws: Nothing. + static node_ptr next_node(node_ptr p) + { return tree_algorithms::next_node(p); } + + //! Requires: p is a node from the tree except the leftmost node. + //! + //! Effects: Returns the previous node of the tree. + //! + //! Complexity: Average constant time. + //! + //! Throws: Nothing. + static node_ptr prev_node(node_ptr p) + { return tree_algorithms::prev_node(p); } + + //! Requires: node must not be part of any tree. + //! + //! Effects: After the function unique(node) == true. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Nodes: If node is inserted in a tree, this function corrupts the tree. + static void init(node_ptr node) + { tree_algorithms::init(node); } + + //! Requires: node must not be part of any tree. + //! + //! Effects: Initializes the header to represent an empty tree. + //! unique(header) == true. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Nodes: If node is inserted in a tree, this function corrupts the tree. + static void init_header(node_ptr header) + { tree_algorithms::init_header(header); } + + //! Requires: header must be the header of a tree, z a node + //! of that tree and z != header. + //! + //! Effects: Erases node "z" from the tree with header "header". + //! + //! Complexity: Amortized constant time. + //! + //! Throws: Nothing. + template + static node_ptr erase(node_ptr header, node_ptr z, std::size_t tree_size, std::size_t &max_tree_size, AlphaByMaxSize alpha_by_maxsize) + { + //typename tree_algorithms::data_for_rebalance info; + tree_algorithms::erase(header, z); + --tree_size; + if (tree_size > 0 && + tree_size < alpha_by_maxsize(max_tree_size)){ + tree_algorithms::rebalance(header); + max_tree_size = tree_size; + } + return z; + } + + //! Requires: "cloner" must be a function + //! object taking a node_ptr and returning a new cloned node of it. "disposer" must + //! take a node_ptr and shouldn't throw. + //! + //! Effects: First empties target tree calling + //! void disposer::operator()(node_ptr) for every node of the tree + //! except the header. + //! + //! Then, duplicates the entire tree pointed by "source_header" cloning each + //! source node with node_ptr Cloner::operator()(node_ptr) to obtain + //! the nodes of the target tree. If "cloner" throws, the cloned target nodes + //! are disposed using void disposer(node_ptr). + //! + //! Complexity: Linear to the number of element of the source tree plus the. + //! number of elements of tree target tree when calling this function. + //! + //! Throws: If cloner functor throws. If this happens target nodes are disposed. + template + static void clone + (const_node_ptr source_header, node_ptr target_header, Cloner cloner, Disposer disposer) + { + tree_algorithms::clone(source_header, target_header, cloner, disposer); + } + + //! Requires: "disposer" must be an object function + //! taking a node_ptr parameter and shouldn't throw. + //! + //! Effects: Empties the target tree calling + //! void disposer::operator()(node_ptr) for every node of the tree + //! except the header. + //! + //! Complexity: Linear to the number of element of the source tree plus the. + //! number of elements of tree target tree when calling this function. + //! + //! Throws: If cloner functor throws. If this happens target nodes are disposed. + template + static void clear_and_dispose(node_ptr header, Disposer disposer) + { tree_algorithms::clear_and_dispose(header, disposer); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the first element that is + //! not less than "key" according to "comp" or "header" if that element does + //! not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr lower_bound + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { return tree_algorithms::lower_bound(header, key, comp); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the first element that is greater + //! than "key" according to "comp" or "header" if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr upper_bound + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { return tree_algorithms::upper_bound(header, key, comp); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the element that is equivalent to + //! "key" according to "comp" or "header" if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr find + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { return tree_algorithms::find(header, key, comp); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an a pair of node_ptr delimiting a range containing + //! all elements that are equivalent to "key" according to "comp" or an + //! empty range that indicates the position where those elements would be + //! if they there are no equivalent elements. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static std::pair equal_range + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { return tree_algorithms::equal_range(header, key, comp); } + + //! Requires: "h" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. + //! + //! Effects: Inserts new_node into the tree before the upper bound + //! according to "comp". + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr insert_equal_upper_bound + (node_ptr h, node_ptr new_node, NodePtrCompare comp + ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + std::size_t depth; + tree_algorithms::insert_equal_upper_bound(h, new_node, comp, &depth); + rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); + return new_node; + } + + //! Requires: "h" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. + //! + //! Effects: Inserts new_node into the tree before the lower bound + //! according to "comp". + //! + //! Complexity: Average complexity for insert element is at + //! most logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr insert_equal_lower_bound + (node_ptr h, node_ptr new_node, NodePtrCompare comp + ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + std::size_t depth; + tree_algorithms::insert_equal_lower_bound(h, new_node, comp, &depth); + rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from + //! the "header"'s tree. + //! + //! Effects: Inserts new_node into the tree, using "hint" as a hint to + //! where it will be inserted. If "hint" is the upper_bound + //! the insertion takes constant time (two comparisons in the worst case). + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time if new_node is inserted immediately before "hint". + //! + //! Throws: If "comp" throws. + template + static node_ptr insert_equal + (node_ptr header, node_ptr hint, node_ptr new_node, NodePtrCompare comp + ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + std::size_t depth; + tree_algorithms::insert_equal(header, hint, new_node, comp, &depth); + rebalance_after_insertion(new_node, depth, tree_size+1, h_alpha, max_tree_size); + return new_node; + } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares KeyType with a node_ptr. + //! + //! Effects: Checks if there is an equivalent node to "key" in the + //! tree according to "comp" and obtains the needed information to realize + //! a constant-time node insertion if there is no equivalent node. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing a node_ptr to the already present node + //! and false. If there is not equivalent key can be inserted returns true + //! in the returned pair's boolean and fills "commit_data" that is meant to + //! be used with the "insert_commit" function to achieve a constant-time + //! insertion function. + //! + //! Complexity: Average complexity is at most logarithmic. + //! + //! Throws: If "comp" throws. + //! + //! Notes: This function is used to improve performance when constructing + //! a node is expensive and the user does not want to have two equivalent nodes + //! in the tree: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the order is much cheaper to construct + //! than the node and this function offers the possibility to use that part + //! to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the node and use + //! "insert_commit" to insert the node in constant-time. This gives a total + //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_unique_commit" only + //! if no more objects are inserted or erased from the set. + template + static std::pair insert_unique_check + (const_node_ptr header, const KeyType &key + ,KeyNodePtrCompare comp, insert_commit_data &commit_data) + { + std::size_t depth; + std::pair ret = + tree_algorithms::insert_unique_check(header, key, comp, commit_data, &depth); + commit_data.depth = depth; + return ret; + } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares KeyType with a node_ptr. + //! "hint" is node from the "header"'s tree. + //! + //! Effects: Checks if there is an equivalent node to "key" in the + //! tree according to "comp" using "hint" as a hint to where it should be + //! inserted and obtains the needed information to realize + //! a constant-time node insertion if there is no equivalent node. + //! If "hint" is the upper_bound the function has constant time + //! complexity (two comparisons in the worst case). + //! + //! Returns: If there is an equivalent value + //! returns a pair containing a node_ptr to the already present node + //! and false. If there is not equivalent key can be inserted returns true + //! in the returned pair's boolean and fills "commit_data" that is meant to + //! be used with the "insert_commit" function to achieve a constant-time + //! insertion function. + //! + //! Complexity: Average complexity is at most logarithmic, but it is + //! amortized constant time if new_node should be inserted immediately before "hint". + //! + //! Throws: If "comp" throws. + //! + //! Notes: This function is used to improve performance when constructing + //! a node is expensive and the user does not want to have two equivalent nodes + //! in the tree: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the order is much cheaper to construct + //! than the node and this function offers the possibility to use that part + //! to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the node and use + //! "insert_commit" to insert the node in constant-time. This gives a total + //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_unique_commit" only + //! if no more objects are inserted or erased from the set. + template + static std::pair insert_unique_check + (const_node_ptr header, node_ptr hint, const KeyType &key + ,KeyNodePtrCompare comp, insert_commit_data &commit_data) + { + std::size_t depth; + std::pair ret = + tree_algorithms::insert_unique_check + (header, hint, key, comp, commit_data, &depth); + commit_data.depth = depth; + return ret; + } + + //! Requires: "header" must be the header node of a tree. + //! "commit_data" must have been obtained from a previous call to + //! "insert_unique_check". No objects should have been inserted or erased + //! from the set between the "insert_unique_check" that filled "commit_data" + //! and the call to "insert_commit". + //! + //! + //! Effects: Inserts new_node in the set using the information obtained + //! from the "commit_data" that a previous "insert_check" filled. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function has only sense if a "insert_unique_check" has been + //! previously executed to fill "commit_data". No value should be inserted or + //! erased between the "insert_check" and "insert_commit" calls. + template + static void insert_unique_commit + (node_ptr header, node_ptr new_value, const insert_commit_data &commit_data + ,std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + tree_algorithms::insert_unique_commit(header, new_value, commit_data); + rebalance_after_insertion(new_value, commit_data.depth, tree_size+1, h_alpha, max_tree_size); + } + + //! Requires: header must be the header of a tree. + //! + //! Effects: Rebalances the tree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear. + static void rebalance(node_ptr header) + { tree_algorithms::rebalance(header); } + + //! Requires: old_root is a node of a tree. + //! + //! Effects: Rebalances the subtree rooted at old_root. + //! + //! Returns: The new root of the subtree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear. + static node_ptr rebalance_subtree(node_ptr old_root) + { return tree_algorithms::rebalance_subtree(old_root); } + + //! Requires: "n" must be a node inserted in a tree. + //! + //! Effects: Returns a pointer to the header node of the tree. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + static node_ptr get_header(node_ptr n) + { return tree_algorithms::get_header(n); } + + /// @cond + private: + + //! Requires: p is a node of a tree. + //! + //! Effects: Returns true if p is the header of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static bool is_header(const_node_ptr p) + { return tree_algorithms::is_header(p); } + + template + static void rebalance_after_insertion + ( node_ptr x, std::size_t depth + , std::size_t tree_size, H_Alpha h_alpha, std::size_t &max_tree_size) + { + if(tree_size > max_tree_size) + max_tree_size = tree_size; + + if(tree_size != 1 && depth > h_alpha(tree_size)){ + //Find the first non height-balanced node + //as described in the section 4.2 of the paper. + //This method is the alternative method described + //in the paper. Authors claim that this method + //may tend to yield more balanced trees on the average + //than the weight balanced method. + node_ptr s = x; + std::size_t size = 1; + + for(std::size_t i = 1; true; ++i){ + bool rebalance = false; + if(i == depth){ + assert(tree_size == count(s)); + rebalance = true; + } + else if(i > h_alpha(size)){ + node_ptr s_parent = NodeTraits::get_parent(s); + node_ptr s_parent_left = NodeTraits::get_left(s_parent); + size += 1 + tree_algorithms::count + ( s_parent_left == s ? NodeTraits::get_right(s_parent) : s_parent_left ); + s = s_parent; + rebalance = true; + } + if(rebalance){ + rebalance_subtree(s); + break; + } + } + } + } + + /// @endcond +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_SGTREE_ALGORITHMS_HPP diff --git a/win32/include/boost/intrusive/slist.hpp b/win32/include/boost/intrusive/slist.hpp new file mode 100755 index 000000000..a2f7fbf91 --- /dev/null +++ b/win32/include/boost/intrusive/slist.hpp @@ -0,0 +1,1947 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_SLIST_HPP +#define BOOST_INTRUSIVE_SLIST_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //std::size_t +#include //std::pair + +namespace boost { +namespace intrusive { + +/// @cond + +template +struct internal_default_slist_hook +{ + template static detail::one test(...); + template static detail::two test(typename U::default_slist_hook* = 0); + static const bool value = sizeof(test(0)) == sizeof(detail::two); +}; + +template +struct get_default_slist_hook +{ typedef typename T::default_slist_hook type; }; + +template +struct slistopt +{ + typedef ValueTraits value_traits; + typedef SizeType size_type; + static const bool constant_time_size = ConstantTimeSize; + static const bool linear = Linear; + static const bool cache_last = CacheLast; +}; + +template +struct root_plus_last +{ + Node root_; + NodePtr last_; +}; + +template +struct root_plus_last +{ + Node root_; +}; + +template +struct slist_defaults + : pack_options + < none + , base_hook + < typename detail::eval_if_c + < internal_default_slist_hook::value + , get_default_slist_hook + , detail::identity + >::type + > + , constant_time_size + , linear + , size_type + , cache_last + >::type +{}; + +/// @endcond + +//! The class template slist is an intrusive container, that encapsulates +//! a singly-linked list. You can use such a list to squeeze the last bit +//! of performance from your application. Unfortunately, the little gains +//! come with some huge drawbacks. A lot of member functions can't be +//! implemented as efficiently as for standard containers. To overcome +//! this limitation some other member functions with rather unusual semantics +//! have to be introduced. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<>, +//! \c linear<> and \c cache_last<>. +//! +//! The iterators of slist are forward iterators. slist provides a static +//! function called "previous" to compute the previous iterator of a given iterator. +//! This function has linear complexity. To improve the usability esp. with +//! the '*_after' functions, ++end() == begin() and previous(begin()) == end() +//! are defined. An new special function "before_begin()" is defined, which returns +//! an iterator that points one less the beginning of the list: ++before_begin() == begin() +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class slist_impl +{ + //Public typedefs + public: + typedef typename Config::value_traits value_traits; + /// @cond + static const bool external_value_traits = + detail::external_value_traits_is_true::value; + typedef typename detail::eval_if_c + < external_value_traits + , detail::eval_value_traits + , detail::identity + >::type real_value_traits; + /// @endcond + typedef typename real_value_traits::pointer pointer; + typedef typename real_value_traits::const_pointer const_pointer; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::reference reference; + typedef typename std::iterator_traits::reference const_reference; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename Config::size_type size_type; + typedef slist_iterator iterator; + typedef slist_iterator const_iterator; + typedef typename real_value_traits::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + typedef typename detail::if_c + < Config::linear + , linear_slist_algorithms + , circular_slist_algorithms + >::type node_algorithms; + + static const bool constant_time_size = Config::constant_time_size; + static const bool stateful_value_traits = detail::store_cont_ptr_on_it::value; + static const bool linear = Config::linear; + static const bool cache_last = Config::cache_last; + + /// @cond + private: + typedef detail::size_holder size_traits; + + //! This class is + //! non-copyable + slist_impl (const slist_impl&); + + //! This class is + //! non-asignable + slist_impl &operator =(const slist_impl&); + + enum { safemode_or_autounlink = + (int)real_value_traits::link_mode == (int)auto_unlink || + (int)real_value_traits::link_mode == (int)safe_link }; + + //Constant-time size is incompatible with auto-unlink hooks! + BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); + //Linear singly linked lists are incompatible with auto-unlink hooks! + BOOST_STATIC_ASSERT(!(linear && ((int)real_value_traits::link_mode == (int)auto_unlink))); + //A list with cached last node is incompatible with auto-unlink hooks! + BOOST_STATIC_ASSERT(!(cache_last && ((int)real_value_traits::link_mode == (int)auto_unlink))); + + node_ptr get_end_node() + { return node_ptr(linear ? node_ptr(0) : this->get_root_node()); } + + const_node_ptr get_end_node() const + { + return const_node_ptr + (linear ? const_node_ptr(0) : this->get_root_node()); } + + node_ptr get_root_node() + { return node_ptr(&data_.root_plus_size_.root_); } + + const_node_ptr get_root_node() const + { return const_node_ptr(&data_.root_plus_size_.root_); } + + node_ptr get_last_node() + { return this->get_last_node(detail::bool_()); } + + const_node_ptr get_last_node() const + { return this->get_last_node(detail::bool_()); } + + void set_last_node(node_ptr n) + { return this->set_last_node(n, detail::bool_()); } + + static node_ptr get_last_node(detail::bool_) + { return node_ptr(0); } + + static void set_last_node(node_ptr, detail::bool_) + {} + + node_ptr get_last_node(detail::bool_) + { return node_ptr(data_.root_plus_size_.last_); } + + const_node_ptr get_last_node(detail::bool_) const + { return const_node_ptr(data_.root_plus_size_.last_); } + + void set_last_node(node_ptr n, detail::bool_) + { data_.root_plus_size_.last_ = n; } + + static node_ptr uncast(const_node_ptr ptr) + { return node_ptr(const_cast(detail::get_pointer(ptr))); } + + void set_default_constructed_state() + { + node_algorithms::init_header(this->get_root_node()); + this->priv_size_traits().set_size(size_type(0)); + if(cache_last){ + this->set_last_node(this->get_root_node()); + } + } + + struct root_plus_size + : public size_traits + , public root_plus_last + {}; + + struct data_t + : public slist_impl::value_traits + { + typedef typename slist_impl::value_traits value_traits; + data_t(const value_traits &val_traits) + : value_traits(val_traits) + {} + + root_plus_size root_plus_size_; + } data_; + + size_traits &priv_size_traits() + { return data_.root_plus_size_; } + + const size_traits &priv_size_traits() const + { return data_.root_plus_size_; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return data_; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return data_.get_value_traits(*this); } + + real_value_traits &get_real_value_traits(detail::bool_) + { return data_; } + + real_value_traits &get_real_value_traits(detail::bool_) + { return data_.get_value_traits(*this); } + + /// @endcond + + public: + + const real_value_traits &get_real_value_traits() const + { return this->get_real_value_traits(detail::bool_()); } + + real_value_traits &get_real_value_traits() + { return this->get_real_value_traits(detail::bool_()); } + + public: + //! Effects: constructs an empty list. + //! + //! Complexity: Constant + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks). + slist_impl(const value_traits &v_traits = value_traits()) + : data_(v_traits) + { this->set_default_constructed_state(); } + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! + //! Effects: Constructs a list equal to [first,last). + //! + //! Complexity: Linear in std::distance(b, e). No copy constructors are called. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks). + template + slist_impl(Iterator b, Iterator e, const value_traits &v_traits = value_traits()) + : data_(v_traits) + { + this->set_default_constructed_state(); + this->insert_after(this->before_begin(), b, e); + } + + //! Effects: If it's a safe-mode + //! or auto-unlink value, the destructor does nothing + //! (ie. no code is generated). Otherwise it detaches all elements from this. + //! In this case the objects in the list are not deleted (i.e. no destructors + //! are called), but the hooks according to the value_traits template parameter + //! are set to their default value. + //! + //! Complexity: Linear to the number of elements in the list, if + //! it's a safe-mode or auto-unlink value. Otherwise constant. + ~slist_impl() + { this->clear(); } + + //! Effects: Erases all the elements of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements of the list. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Note: Invalidates the iterators (but not the references) to the erased elements. + void clear() + { + if(safemode_or_autounlink){ + this->clear_and_dispose(detail::null_disposer()); + } + else{ + this->set_default_constructed_state(); + } + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements of the container + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements of the list. + //! + //! Note: Invalidates the iterators to the erased elements. + template + void clear_and_dispose(Disposer disposer) + { + iterator it(this->begin()), itend(this->end()); + while(it != itend){ + node_ptr to_erase(it.pointed_node()); + ++it; + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + disposer(get_real_value_traits().to_value_ptr(to_erase)); + } + this->set_default_constructed_state(); + } + + //! Requires: value must be an lvalue. + //! + //! Effects: Inserts the value in the front of the list. + //! No copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Does not affect the validity of iterators and references. + void push_front(reference value) + { + node_ptr to_insert = get_real_value_traits().to_node_ptr(value); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert)); + if(cache_last){ + if(this->empty()){ + this->set_last_node(to_insert); + } + } + node_algorithms::link_after(this->get_root_node(), to_insert); + this->priv_size_traits().increment(); + } + + //! Requires: value must be an lvalue. + //! + //! Effects: Inserts the value in the back of the list. + //! No copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Does not affect the validity of iterators and references. + //! This function is only available is cache_last<> is true. + void push_back(reference value) + { + BOOST_STATIC_ASSERT((cache_last != 0)); + this->insert_after(iterator(this->get_last_node(), this), value); + } + + //! Effects: Erases the first element of the list. + //! No destructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Invalidates the iterators (but not the references) to the erased element. + void pop_front() + { return this->pop_front_and_dispose(detail::null_disposer()); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the first element of the list. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Invalidates the iterators to the erased element. + template + void pop_front_and_dispose(Disposer disposer) + { + node_ptr to_erase = node_traits::get_next(this->get_root_node()); + node_algorithms::unlink_after(this->get_root_node()); + this->priv_size_traits().decrement(); + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + disposer(get_real_value_traits().to_value_ptr(to_erase)); + if(cache_last){ + if(this->empty()){ + this->set_last_node(this->get_root_node()); + } + } + } + + //! Effects: Returns a reference to the first element of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + reference front() + { return *this->get_real_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); } + + //! Effects: Returns a const_reference to the first element of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_reference front() const + { return *this->get_real_value_traits().to_value_ptr(uncast(node_traits::get_next(this->get_root_node()))); } + + //! Effects: Returns a reference to the last element of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Does not affect the validity of iterators and references. + //! This function is only available is cache_last<> is true. + reference back() + { + BOOST_STATIC_ASSERT((cache_last != 0)); + return *this->get_real_value_traits().to_value_ptr(this->get_last_node()); + } + + //! Effects: Returns a const_reference to the last element of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Does not affect the validity of iterators and references. + //! This function is only available is cache_last<> is true. + const_reference back() const + { + BOOST_STATIC_ASSERT((cache_last != 0)); + return *this->get_real_value_traits().to_value_ptr(this->get_last_node()); + } + + //! Effects: Returns an iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator begin() + { return iterator (node_traits::get_next(this->get_root_node()), this); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator begin() const + { return const_iterator (node_traits::get_next(this->get_root_node()), this); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbegin() const + { return const_iterator(node_traits::get_next(this->get_root_node()), this); } + + //! Effects: Returns an iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator end() + { return iterator(this->get_end_node(), this); } + + //! Effects: Returns a const_iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator end() const + { return const_iterator(uncast(this->get_end_node()), this); } + + //! Effects: Returns a const_iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cend() const + { return this->end(); } + + //! Effects: Returns an iterator that points to a position + //! before the first element. Equivalent to "end()" + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + iterator before_begin() + { return iterator(this->get_root_node(), this); } + + //! Effects: Returns an iterator that points to a position + //! before the first element. Equivalent to "end()" + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator before_begin() const + { return const_iterator(uncast(this->get_root_node()), this); } + + //! Effects: Returns an iterator that points to a position + //! before the first element. Equivalent to "end()" + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + const_iterator cbefore_begin() const + { return this->before_begin(); } + + //! Precondition: end_iterator must be a valid end iterator + //! of slist. + //! + //! Effects: Returns a const reference to the slist associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static slist_impl &container_from_end_iterator(iterator end_iterator) + { return slist_impl::priv_container_from_end_iterator(end_iterator); } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of slist. + //! + //! Effects: Returns a const reference to the slist associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const slist_impl &container_from_end_iterator(const_iterator end_iterator) + { return slist_impl::priv_container_from_end_iterator(end_iterator); } + + //! Effects: Returns the number of the elements contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements contained in the list. + //! if constant_time_size is false. Constant time otherwise. + //! + //! Note: Does not affect the validity of iterators and references. + size_type size() const + { + if(constant_time_size) + return this->priv_size_traits().get_size(); + else + return node_algorithms::count(this->get_root_node()) - 1; + } + + //! Effects: Returns true if the list contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Does not affect the validity of iterators and references. + bool empty() const + { return node_algorithms::unique(this->get_root_node()); } + + //! Effects: Swaps the elements of x and *this. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements of both lists. + //! Constant-time if linear<> and/or cache_last<> options are used. + //! + //! Note: Does not affect the validity of iterators and references. + void swap(slist_impl& other) + { + if(cache_last){ + this->priv_swap_cache_last(other); + } + else{ + this->priv_swap_lists(this->get_root_node(), other.get_root_node(), detail::bool_()); + } + if(constant_time_size){ + size_type backup = this->priv_size_traits().get_size(); + this->priv_size_traits().set_size(other.priv_size_traits().get_size()); + other.priv_size_traits().set_size(backup); + } + } + + //! Effects: Moves backwards all the elements, so that the first + //! element becomes the second, the second becomes the third... + //! the last element becomes the first one. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements plus the number shifts. + //! + //! Note: Iterators Does not affect the validity of iterators and references. + void shift_backwards(size_type n = 1) + { this->priv_shift_backwards(n, detail::bool_()); } + + //! Effects: Moves forward all the elements, so that the second + //! element becomes the first, the third becomes the second... + //! the first element becomes the last one. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements plus the number shifts. + //! + //! Note: Does not affect the validity of iterators and references. + void shift_forward(size_type n = 1) + { this->priv_shift_forward(n, detail::bool_()); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. + template + void clone_from(const slist_impl &src, Cloner cloner, Disposer disposer) + { + this->clear_and_dispose(disposer); + detail::exception_disposer + rollback(*this, disposer); + iterator prev(this->before_begin()); + const_iterator b(src.begin()), e(src.end()); + for(; b != e; ++b){ + prev = this->insert_after(prev, *cloner(*b)); + } + rollback.release(); + } + + //! Requires: value must be an lvalue and prev_p must point to an element + //! contained by the list or to end(). + //! + //! Effects: Inserts the value after the position pointed by prev_p. + //! No copy constructor is called. + //! + //! Returns: An iterator to the inserted element. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Does not affect the validity of iterators and references. + iterator insert_after(iterator prev_p, reference value) + { + node_ptr n = get_real_value_traits().to_node_ptr(value); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n)); + node_ptr prev_n(prev_p.pointed_node()); + node_algorithms::link_after(prev_n, n); + if(cache_last && (this->get_last_node() == prev_n)){ + this->set_last_node(n); + } + this->priv_size_traits().increment(); + return iterator (n, this); + } + + //! Requires: Dereferencing iterator must yield + //! an lvalue of type value_type and prev_p must point to an element + //! contained by the list or to the end node. + //! + //! Effects: Inserts the [first, last) + //! after the position prev_p. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements inserted. + //! + //! Note: Does not affect the validity of iterators and references. + template + void insert_after(iterator prev_p, Iterator first, Iterator last) + { + for (; first != last; ++first) + prev_p = this->insert_after(prev_p, *first); + } + + //! Requires: value must be an lvalue and p must point to an element + //! contained by the list or to end(). + //! + //! Effects: Inserts the value before the position pointed by p. + //! No copy constructor is called. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before p. + //! Constant-time if cache_last<> is true and p == end(). + //! + //! Note: Does not affect the validity of iterators and references. + iterator insert(iterator p, reference value) + { return this->insert_after(this->previous(p), value); } + + //! Requires: Dereferencing iterator must yield + //! an lvalue of type value_type and p must point to an element + //! contained by the list or to the end node. + //! + //! Effects: Inserts the pointed by b and e + //! before the position p. No copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements inserted plus linear + //! to the elements before b. + //! Linear to the number of elements to insert if cache_last<> option is true and p == end(). + //! + //! Note: Does not affect the validity of iterators and references. + template + void insert(iterator p, Iterator b, Iterator e) + { return this->insert_after(this->previous(p), b, e); } + + //! Effects: Erases the element after the element pointed by prev of + //! the list. No destructors are called. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Invalidates the iterators (but not the references) to the + //! erased element. + iterator erase_after(iterator prev) + { return this->erase_after_and_dispose(prev, detail::null_disposer()); } + + //! Effects: Erases the range (before_first, last) from + //! the list. No destructors are called. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of erased elements if it's a safe-mode + //! , auto-unlink value or constant-time size is activated. Constant time otherwise. + //! + //! Note: Invalidates the iterators (but not the references) to the + //! erased element. + iterator erase_after(iterator before_first, iterator last) + { + if(safemode_or_autounlink || constant_time_size){ + return this->erase_after_and_dispose(before_first, last, detail::null_disposer()); + } + else{ + node_ptr bfp = before_first.pointed_node(); + node_ptr lp = last.pointed_node(); + if(cache_last){ + if((lp == this->get_end_node())){ + this->set_last_node(bfp); + } + } + node_algorithms::unlink_after(bfp, lp); + return last; + } + } + + //! Effects: Erases the range (before_first, last) from + //! the list. n must be std::distance(before_first, last) - 1. + //! No destructors are called. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: constant-time if link_mode is normal_link. + //! Linear to the elements (last - before_first) otherwise. + //! + //! Note: Invalidates the iterators (but not the references) to the + //! erased element. + iterator erase_after(iterator before_first, iterator last, difference_type n) + { + BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(++iterator(before_first), last) == difference_type(n)); + if(safemode_or_autounlink){ + return this->erase_after(before_first, last); + } + else{ + node_ptr bfp = before_first.pointed_node(); + node_ptr lp = last.pointed_node(); + if(cache_last){ + if((lp == this->get_end_node())){ + this->set_last_node(bfp); + } + } + node_algorithms::unlink_after(bfp, lp); + if(constant_time_size){ + this->priv_size_traits().set_size(this->priv_size_traits().get_size() - n); + } + return last; + } + } + + //! Effects: Erases the element pointed by i of the list. + //! No destructors are called. + //! + //! Returns: the first element remaining beyond the removed element, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements before i. + //! + //! Note: Invalidates the iterators (but not the references) to the + //! erased element. + iterator erase(iterator i) + { return this->erase_after(this->previous(i)); } + + //! Requires: first and last must be valid iterator to elements in *this. + //! + //! Effects: Erases the range pointed by b and e. + //! No destructors are called. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements before last. + //! + //! Note: Invalidates the iterators (but not the references) to the + //! erased elements. + iterator erase(iterator first, iterator last) + { return this->erase_after(this->previous(first), last); } + + //! Effects: Erases the range [first, last) from + //! the list. n must be std::distance(first, last). + //! No destructors are called. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: linear to the elements before first if link_mode is normal_link + //! and constant_time_size is activated. Linear to the elements before last otherwise. + //! + //! Note: Invalidates the iterators (but not the references) to the + //! erased element. + iterator erase(iterator first, iterator last, difference_type n) + { return this->erase_after(this->previous(first), last, n); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element after the element pointed by prev of + //! the list. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Invalidates the iterators to the erased element. + template + iterator erase_after_and_dispose(iterator prev, Disposer disposer) + { + iterator it(prev); + ++it; + node_ptr to_erase(it.pointed_node()); + ++it; + node_ptr prev_n(prev.pointed_node()); + node_algorithms::unlink_after(prev_n); + if(cache_last && (to_erase == this->get_last_node())){ + this->set_last_node(prev_n); + } + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + disposer(get_real_value_traits().to_value_ptr(to_erase)); + this->priv_size_traits().decrement(); + return it; + } + + /// @cond + + template + static iterator s_erase_after_and_dispose(iterator prev, Disposer disposer) + { + BOOST_STATIC_ASSERT(((!cache_last)&&(!constant_time_size)&&(!stateful_value_traits))); + iterator it(prev); + ++it; + node_ptr to_erase(it.pointed_node()); + ++it; + node_ptr prev_n(prev.pointed_node()); + node_algorithms::unlink_after(prev_n); + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + disposer(real_value_traits::to_value_ptr(to_erase)); + return it; + } + + static iterator s_erase_after(iterator prev) + { return s_erase_after_and_dispose(prev, detail::null_disposer()); } + + /// @endcond + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the range (before_first, last) from + //! the list. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Lineal to the elements (last - before_first + 1). + //! + //! Note: Invalidates the iterators to the erased element. + template + iterator erase_after_and_dispose(iterator before_first, iterator last, Disposer disposer) + { + node_ptr bfp(before_first.pointed_node()), lp(last.pointed_node()); + node_ptr fp(node_traits::get_next(bfp)); + node_algorithms::unlink_after(bfp, lp); + while(fp != lp){ + node_ptr to_erase(fp); + fp = node_traits::get_next(fp); + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + disposer(get_real_value_traits().to_value_ptr(to_erase)); + this->priv_size_traits().decrement(); + } + if(cache_last && (node_traits::get_next(bfp) == this->get_end_node())){ + this->set_last_node(bfp); + } + return last; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element pointed by i of the list. + //! No destructors are called. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Returns: the first element remaining beyond the removed element, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements before i. + //! + //! Note: Invalidates the iterators (but not the references) to the + //! erased element. + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { return this->erase_after_and_dispose(this->previous(i), disposer); } + + //! Requires: first and last must be valid iterator to elements in *this. + //! Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the range pointed by b and e. + //! No destructors are called. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of erased elements plus linear + //! to the elements before first. + //! + //! Note: Invalidates the iterators (but not the references) to the + //! erased elements. + template + iterator erase_and_dispose(iterator first, iterator last, Disposer disposer) + { return this->erase_after_and_dispose(this->previous(first), last, disposer); } + + //! Requires: Dereferencing iterator must yield + //! an lvalue of type value_type. + //! + //! Effects: Clears the list and inserts the range pointed by b and e. + //! No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements inserted plus + //! linear to the elements contained in the list if it's a safe-mode + //! or auto-unlink value. + //! Linear to the number of elements inserted in the list otherwise. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. + template + void assign(Iterator b, Iterator e) + { + this->clear(); + this->insert_after(this->before_begin(), b, e); + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Requires: Dereferencing iterator must yield + //! an lvalue of type value_type. + //! + //! Effects: Clears the list and inserts the range pointed by b and e. + //! No destructors or copy constructors are called. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements inserted plus + //! linear to the elements contained in the list. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. + template + void dispose_and_assign(Disposer disposer, Iterator b, Iterator e) + { + this->clear_and_dispose(disposer); + this->insert_after(this->before_begin(), b, e, disposer); + } + + //! Requires: prev is an iterator to an element or x.end()/x.before_begin() in x. + //! + //! Effects: Transfers all the elements of list x to this list, after the + //! the element pointed by prev. No destructors or copy constructors are called. + //! + //! Returns: The last element inserted of x or prev if x is empty. + //! This iterator can be used as new "prev" iterator for a new splice_after call. + //! that will splice new values after the previously spliced values. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements contained in x. + //! Constant-time if cache_last<> option is true. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + iterator splice_after(iterator prev, slist_impl &x) + { + if (!x.empty()){ + iterator last_x(x.previous(x.end())); //<- constant time if cache_last is active + node_ptr prev_n(prev.pointed_node()); + node_ptr last_x_n(last_x.pointed_node()); + if(cache_last){ + x.set_last_node(x.get_root_node()); + if(node_traits::get_next(prev_n) == this->get_end_node()){ + this->set_last_node(last_x_n); + } + } + node_algorithms::transfer_after( prev_n, x.before_begin().pointed_node(), last_x_n); + this->priv_size_traits().set_size(this->priv_size_traits().get_size() + x.priv_size_traits().get_size()); + x.priv_size_traits().set_size(size_type(0)); + return last_x; + } + else{ + return prev; + } + } + + //! Requires: prev must point to an element contained by this list or + //! to the before_begin() element. prev_ele must point to an element contained in list + //! x or must be x.before_begin(). + //! + //! Effects: Transfers the element after prev_ele, from list x to this list, + //! after the element pointed by prev. No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice_after(iterator prev_pos, slist_impl &x, iterator prev_ele) + { + iterator elem = prev_ele; + this->splice_after(prev_pos, x, prev_ele, ++elem, 1); + } + + //! Requires: prev_pos must be a dereferenceable iterator in *this or be + //! before_begin(), and before_first and before_last belong to x and + //! ++before_first != x.end() && before_last != x.end(). + //! + //! Effects: Transfers the range (before_first, before_last] from list x to this + //! list, after the element pointed by prev_pos. + //! No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements transferred + //! if constant_time_size is true. Constant-time otherwise. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice_after(iterator prev_pos, slist_impl &x, iterator before_first, iterator before_last) + { + if(constant_time_size) + this->splice_after(prev_pos, x, before_first, before_last, std::distance(before_first, before_last)); + else + this->priv_splice_after + (prev_pos.pointed_node(), x, before_first.pointed_node(), before_last.pointed_node()); + } + + //! Requires: prev_pos must be a dereferenceable iterator in *this or be + //! before_begin(), and before_first and before_last belong to x and + //! ++before_first != x.end() && before_last != x.end() and + //! n == std::distance(before_first, before_last). + //! + //! Effects: Transfers the range (before_first, before_last] from list x to this + //! list, after the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice_after(iterator prev_pos, slist_impl &x, iterator before_first, iterator before_last, difference_type n) + { + if(n){ + BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(before_first, before_last) == n); + this->priv_splice_after + (prev_pos.pointed_node(), x, before_first.pointed_node(), before_last.pointed_node()); + if(constant_time_size){ + this->priv_size_traits().set_size(this->priv_size_traits().get_size() + n); + x.priv_size_traits().set_size(x.priv_size_traits().get_size() - n); + } + } + } + + //! Requires: it is an iterator to an element in x. + //! + //! Effects: Transfers all the elements of list x to this list, before the + //! the element pointed by it. No destructors or copy constructors are called. + //! + //! Returns: The last element inserted of x or the previous element + //! of it if x is empty. + //! This iterator can be used as new "prev" iterator for a new splice call. + //! that will splice new values after the previously spliced values. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements contained in x plus linear to + //! the elements before it. + //! Linear to the elements before it if cache_last<> option is true. + //! Constant-time if cache_last<> option is true and it == end(). + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + iterator splice(iterator it, slist_impl &x) + { return this->splice_after(this->previous(it), x); } + + //! Requires: it p must be a valid iterator of *this. + //! elem must point to an element contained in list + //! x. + //! + //! Effects: Transfers the element elem, from list x to this list, + //! before the element pointed by pos. No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements before pos and before elem. + //! Linear to the elements before elem if cache_last<> option is true and pos == end(). + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(iterator pos, slist_impl &x, iterator elem) + { return this->splice_after(this->previous(pos), x, x.previous(elem)); } + + //! Requires: pos must be a dereferenceable iterator in *this + //! and first and last belong to x and first and last a valid range on x. + //! + //! Effects: Transfers the range [first, last) from list x to this + //! list, before the element pointed by pos. + //! No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the sum of elements before pos, first, and last + //! plus linear to the number of elements transferred if constant_time_size is true. + //! Linear to the sum of elements before first, and last + //! plus linear to the number of elements transferred if constant_time_size is true + //! if cache_last<> is true and pos == end() + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(iterator pos, slist_impl &x, iterator first, iterator last) + { return this->splice_after(this->previous(pos), x, x.previous(first), x.previous(last)); } + + //! Requires: pos must be a dereferenceable iterator in *this + //! and first and last belong to x and first and last a valid range on x. + //! n == std::distance(first, last). + //! + //! Effects: Transfers the range [first, last) from list x to this + //! list, before the element pointed by pos. + //! No destructors or copy constructors are called. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the sum of elements before pos, first, and last. + //! Linear to the sum of elements before first and last + //! if cache_last<> is true and pos == end(). + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(iterator pos, slist_impl &x, iterator first, iterator last, difference_type n) + { return this->splice_after(this->previous(pos), x, x.previous(first), x.previous(last), n); } + + //! Effects: This function sorts the list *this according to std::less. + //! The sort is stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the predicate throws. Basic guarantee. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + //! + //! Note: Iterators and references are not invalidated + template + void sort(Predicate p) + { + if (node_traits::get_next(node_traits::get_next(this->get_root_node())) + != this->get_root_node()) { + slist_impl carry; + slist_impl counter[64]; + int fill = 0; + iterator last_inserted; + while(!this->empty()){ + last_inserted = this->begin(); + carry.splice_after(carry.before_begin(), *this, this->before_begin()); + int i = 0; + while(i < fill && !counter[i].empty()) { + last_inserted = carry.merge(counter[i++], p); + } + BOOST_INTRUSIVE_INVARIANT_ASSERT(counter[i].empty()); + + node_ptr p = node_algorithms::get_previous_node + (last_inserted.pointed_node(), carry.end().pointed_node()); + iterator last_element(p, this); + if(constant_time_size){ + counter[i].splice_after( counter[i].before_begin(), carry + , carry.before_begin(), last_element + , carry.size()); + } + else{ + counter[i].splice_after( counter[i].before_begin(), carry + , carry.before_begin(), last_element); + } + if(i == fill) + ++fill; + } + + for (int i = 1; i < fill; ++i) + last_inserted = counter[i].merge(counter[i-1], p); + BOOST_INTRUSIVE_INVARIANT_ASSERT(this->empty()); + + node_ptr p = node_algorithms::get_previous_node + (last_inserted.pointed_node(), counter[--fill].end().pointed_node()); + iterator last_element(p, this); + if(constant_time_size){ + this->splice_after( before_begin(), counter[fill], counter[fill].before_begin() + , last_element, counter[fill].size()); + } + else{ + this->splice_after( before_begin(), counter[fill], counter[fill].before_begin() + , last_element); + } + } + } + + //! Requires: p must be a comparison function that induces a strict weak + //! ordering and both *this and x must be sorted according to that ordering + //! The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this. The merge is stable; that is, if an element from *this is + //! equivalent to one from x, then the element from *this will precede the one from x. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or std::less throws. Basic guarantee. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references are not invalidated. + void sort() + { this->sort(std::less()); } + + //! Requires: p must be a comparison function that induces a strict weak + //! ordering and both *this and x must be sorted according to that ordering + //! The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this. The merge is stable; that is, if an element from *this is + //! equivalent to one from x, then the element from *this will precede the one from x. + //! + //! Returns: An iterator to the last transferred value, end() is x is empty. + //! + //! Throws: If the predicate throws. Basic guarantee. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references are not invalidated. + template + iterator merge(slist_impl& x, Predicate p) + { + iterator a(before_begin()), e(end()), ax(x.before_begin()), ex(x.end()); + iterator last_inserted(e); + iterator a_next; + while(++(a_next = a) != e && !x.empty()) { + iterator ix(ax); + iterator cx; + size_type n(0); + while(++(cx = ix) != ex && p(*cx, *a_next)){ + ++ix; ++n; + } + if(ax != ix){ + this->splice_after(a, x, ax, ix, n); + last_inserted = ix; + } + a = a_next; + } + if (!x.empty()){ + last_inserted = this->splice_after(a, x); + } + return last_inserted; + } + + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this according to std::less. The merge is stable; + //! that is, if an element from *this is equivalent to one from x, then the element + //! from *this will precede the one from x. + //! + //! Throws: if std::less throws. Basic guarantee. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references are not invalidated + void merge(slist_impl& x) + { this->merge(x, std::less()); } + + //! Effects: Reverses the order of elements in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear to the contained elements. + //! + //! Note: Iterators and references are not invalidated + void reverse() + { + if(cache_last && !this->empty()){ + this->set_last_node(node_traits::get_next(this->get_root_node())); + } + this->priv_reverse(detail::bool_()); + } + + //! Effects: Removes all the elements that compare equal to value. + //! No destructors are called. + //! + //! Throws: If std::equal_to throws. Basic guarantee. + //! + //! Complexity: Linear time. It performs exactly size() comparisons for equality. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. This function is + //! linear time: it performs exactly size() comparisons for equality. + void remove(const_reference value) + { this->remove_if(detail::equal_to_value(value)); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Removes all the elements that compare equal to value. + //! Disposer::operator()(pointer) is called for every removed element. + //! + //! Throws: If std::equal_to throws. Basic guarantee. + //! + //! Complexity: Linear time. It performs exactly size() comparisons for equality. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void remove_and_dispose(const_reference value, Disposer disposer) + { this->remove_and_dispose_if(detail::equal_to_value(value), disposer); } + + //! Effects: Removes all the elements for which a specified + //! predicate is satisfied. No destructors are called. + //! + //! Throws: If pred throws. Basic guarantee. + //! + //! Complexity: Linear time. It performs exactly size() calls to the predicate. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void remove_if(Pred pred) + { this->remove_and_dispose_if(pred, detail::null_disposer()); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Removes all the elements for which a specified + //! predicate is satisfied. + //! Disposer::operator()(pointer) is called for every removed element. + //! + //! Throws: If pred throws. Basic guarantee. + //! + //! Complexity: Linear time. It performs exactly size() comparisons for equality. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void remove_and_dispose_if(Pred pred, Disposer disposer) + { + iterator bcur(this->before_begin()), cur(this->begin()), e(this->end()); + + while(cur != e){ + if (pred(*cur)){ + cur = this->erase_after_and_dispose(bcur, disposer); + } + else{ + bcur = cur; + ++cur; + } + } + if(cache_last){ + this->set_last_node(bcur.pointed_node()); + } + } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that are equal from the list. No destructors are called. + //! + //! Throws: If std::equal_to throws. Basic guarantee. + //! + //! Complexity: Linear time (size()-1) comparisons calls to pred()). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + void unique() + { this->unique_and_dispose(std::equal_to(), detail::null_disposer()); } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that satisfy some binary predicate from the list. + //! No destructors are called. + //! + //! Throws: If the predicate throws. Basic guarantee. + //! + //! Complexity: Linear time (size()-1) comparisons equality comparisons. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void unique(BinaryPredicate pred) + { this->unique_and_dispose(pred, detail::null_disposer()); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that satisfy some binary predicate from the list. + //! Disposer::operator()(pointer) is called for every removed element. + //! + //! Throws: If std::equal_to throws. Basic guarantee. + //! + //! Complexity: Linear time (size()-1) comparisons equality comparisons. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void unique_and_dispose(Disposer disposer) + { this->unique(std::equal_to(), disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that satisfy some binary predicate from the list. + //! Disposer::operator()(pointer) is called for every removed element. + //! + //! Throws: If the predicate throws. Basic guarantee. + //! + //! Complexity: Linear time (size()-1) comparisons equality comparisons. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void unique_and_dispose(BinaryPredicate pred, Disposer disposer) + { + iterator end_n(this->end()); + iterator bcur(this->begin()); + if(bcur != end_n){ + iterator cur(bcur); + ++cur; + while(cur != end_n) { + if (pred(*bcur, *cur)){ + cur = this->erase_after_and_dispose(bcur, disposer); + } + else{ + bcur = cur; + ++cur; + } + } + if(cache_last){ + this->set_last_node(bcur.pointed_node()); + } + } + } + + //! Requires: value must be a reference to a value inserted in a list. + //! + //! Effects: This function returns a const_iterator pointing to the element + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: Iterators and references are not invalidated. + //! This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(value))); + return iterator (value_traits::to_node_ptr(value), 0); + } + + //! Requires: value must be a const reference to a value inserted in a list. + //! + //! Effects: This function returns an iterator pointing to the element. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: Iterators and references are not invalidated. + //! This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(const_cast (value)))); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), 0); + } + + //! Requires: value must be a reference to a value inserted in a list. + //! + //! Effects: This function returns a const_iterator pointing to the element + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: Iterators and references are not invalidated. + iterator iterator_to(reference value) + { + //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(value))); + return iterator (value_traits::to_node_ptr(value), this); + } + + //! Requires: value must be a const reference to a value inserted in a list. + //! + //! Effects: This function returns an iterator pointing to the element. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: Iterators and references are not invalidated. + const_iterator iterator_to(const_reference value) const + { + //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(const_cast (value)))); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), this); + } + + //! Returns: The iterator to the element before i in the list. + //! Returns the end-iterator, if either i is the begin-iterator or the + //! list is empty. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before i. + //! Constant if cache_last<> is true and i == end(). + iterator previous(iterator i) + { + if(cache_last && (i.pointed_node() == this->get_end_node())){ + return iterator(this->get_last_node(), this); + } + return iterator + (node_algorithms::get_previous_node + (this->before_begin().pointed_node(), i.pointed_node()), this); + } + + //! Returns: The const_iterator to the element before i in the list. + //! Returns the end-const_iterator, if either i is the begin-const_iterator or + //! the list is empty. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before i. + //! Constant if cache_last<> is true and i == end(). + const_iterator previous(const_iterator i) const + { + if(cache_last && (i.pointed_node() == this->get_end_node())){ + return iterator(uncast(this->get_last_node()), this); + } + return const_iterator + (node_algorithms::get_previous_node + (this->before_begin().pointed_node(), i.pointed_node()), this); + } + + private: + void priv_splice_after(node_ptr prev_pos_n, slist_impl &x, node_ptr before_first_n, node_ptr before_last_n) + { + if (before_first_n != before_last_n && prev_pos_n != before_first_n && prev_pos_n != before_last_n) + { + if(cache_last){ + if(node_traits::get_next(prev_pos_n) == this->get_end_node()){ + this->set_last_node(before_last_n); + } + if(node_traits::get_next(before_last_n) == x.get_end_node()){ + x.set_last_node(before_first_n); + } + } + node_algorithms::transfer_after(prev_pos_n, before_first_n, before_last_n); + } + } + + void priv_reverse(detail::bool_) + { node_algorithms::reverse(this->get_root_node()); } + + void priv_reverse(detail::bool_) + { + node_ptr new_first = node_algorithms::reverse + (node_traits::get_next(this->get_root_node())); + node_traits::set_next(this->get_root_node(), new_first); + } + + void priv_shift_backwards(size_type n, detail::bool_) + { + node_ptr last = node_algorithms::move_forward(this->get_root_node(), (std::size_t)n); + if(cache_last && last){ + this->set_last_node(last); + } + } + + void priv_shift_backwards(size_type n, detail::bool_) + { + std::pair ret( + node_algorithms::move_first_n_forward + (node_traits::get_next(this->get_root_node()), (std::size_t)n)); + if(ret.first){ + node_traits::set_next(this->get_root_node(), ret.first); + if(cache_last){ + this->set_last_node(ret.second); + } + } + } + + void priv_shift_forward(size_type n, detail::bool_) + { + node_ptr last = node_algorithms::move_backwards(this->get_root_node(), (std::size_t)n); + if(cache_last && last){ + this->set_last_node(last); + } + } + + void priv_shift_forward(size_type n, detail::bool_) + { + std::pair ret( + node_algorithms::move_first_n_backwards + (node_traits::get_next(this->get_root_node()), (std::size_t)n)); + if(ret.first){ + node_traits::set_next(this->get_root_node(), ret.first); + if(cache_last){ + this->set_last_node(ret.second); + } + } + } + + void priv_swap_cache_last(slist_impl &other) + { + node_ptr other_last(other.get_last_node()); + node_ptr this_last(this->get_last_node()); + node_ptr other_bfirst(other.get_root_node()); + node_ptr this_bfirst(this->get_root_node()); + node_algorithms::transfer_after(this_bfirst, other_bfirst, other_last); + node_algorithms::transfer_after(other_bfirst, other_last != other_bfirst? other_last : this_bfirst, this_last); + node_ptr tmp(this->get_last_node()); + this->set_last_node(other.get_last_node()); + other.set_last_node(tmp); + if(this->get_last_node() == other_bfirst){ + this->set_last_node(this_bfirst); + } + if(other.get_last_node() == this_bfirst){ + other.set_last_node(other_bfirst); + } + } + + //circular version + static void priv_swap_lists(node_ptr this_node, node_ptr other_node, detail::bool_) + { node_algorithms::swap_nodes(this_node, other_node); } + + //linear version + static void priv_swap_lists(node_ptr this_node, node_ptr other_node, detail::bool_) + { node_algorithms::swap_trailing_nodes(this_node, other_node); } + + static slist_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) + { + //Obtaining the container from the end iterator is not possible with linear + //singly linked lists (because "end" is represented by the null pointer) + BOOST_STATIC_ASSERT(!linear); + root_plus_size *r = detail::parent_from_member + ( detail::get_pointer(end_iterator.pointed_node()), (&root_plus_size::root_)); + data_t *d = detail::parent_from_member + ( r, &data_t::root_plus_size_); + slist_impl *s = detail::parent_from_member(d, &slist_impl::data_); + return *s; + } +}; + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator< +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const slist_impl &x, const slist_impl &y) +#else +(const slist_impl &x, const slist_impl &y) +#endif +{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +bool operator== +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const slist_impl &x, const slist_impl &y) +#else +(const slist_impl &x, const slist_impl &y) +#endif +{ + typedef slist_impl slist_type; + typedef typename slist_type::const_iterator const_iterator; + const bool C = slist_type::constant_time_size; + if(C && x.size() != y.size()){ + return false; + } + const_iterator end1 = x.end(); + + const_iterator i1 = x.begin(); + const_iterator i2 = y.begin(); + if(C){ + while (i1 != end1 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1; + } + else{ + const_iterator end2 = y.end(); + while (i1 != end1 && i2 != end2 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1 && i2 == end2; + } +} + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator!= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const slist_impl &x, const slist_impl &y) +#else +(const slist_impl &x, const slist_impl &y) +#endif +{ return !(x == y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator> +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const slist_impl &x, const slist_impl &y) +#else +(const slist_impl &x, const slist_impl &y) +#endif +{ return y < x; } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator<= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const slist_impl &x, const slist_impl &y) +#else +(const slist_impl &x, const slist_impl &y) +#endif +{ return !(y < x); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator>= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const slist_impl &x, const slist_impl &y) +#else +(const slist_impl &x, const slist_impl &y) +#endif +{ return !(x < y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline void swap +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(slist_impl &x, slist_impl &y) +#else +(slist_impl &x, slist_impl &y) +#endif +{ x.swap(y); } + +//! Helper metafunction to define a \c slist that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_slist +{ + /// @cond + typedef typename pack_options + < slist_defaults, O1, O2, O3, O4, O5>::type packed_options; + typedef typename detail::get_value_traits + ::type value_traits; + typedef slist_impl + < + slistopt + < value_traits + , typename packed_options::size_type + , packed_options::constant_time_size + , packed_options::linear + , packed_options::cache_last + > + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class slist + : public make_slist::type +{ + typedef typename make_slist + ::type Base; + typedef typename Base::real_value_traits real_value_traits; + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + public: + typedef typename Base::value_traits value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + slist(const value_traits &v_traits = value_traits()) + : Base(v_traits) + {} + + template + slist(Iterator b, Iterator e, const value_traits &v_traits = value_traits()) + : Base(b, e, v_traits) + {} + + static slist &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const slist &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } +}; + +#endif + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_SLIST_HPP diff --git a/win32/include/boost/intrusive/slist_hook.hpp b/win32/include/boost/intrusive/slist_hook.hpp new file mode 100755 index 000000000..5598c7815 --- /dev/null +++ b/win32/include/boost/intrusive/slist_hook.hpp @@ -0,0 +1,268 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_SLIST_HOOK_HPP +#define BOOST_INTRUSIVE_SLIST_HOOK_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond +template +struct get_slist_node_algo +{ + typedef circular_slist_algorithms > type; +}; + +/// @endcond + +//! Helper metafunction to define a \c slist_base_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_slist_base_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3>::type packed_options; + + typedef detail::generic_hook + < get_slist_node_algo + , typename packed_options::tag + , packed_options::link_mode + , detail::SlistBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Derive a class from slist_base_hook in order to store objects in +//! in an list. slist_base_hook holds the data necessary to maintain the +//! list and provides an appropriate value_traits class for list. +//! +//! The hook admits the following options: \c tag<>, \c void_pointer<> and +//! \c link_mode<>. +//! +//! \c tag<> defines a tag to identify the node. +//! The same tag value can be used in different classes, but if a class is +//! derived from more than one \c list_base_hook, then each \c list_base_hook needs its +//! unique tag. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, +//! \c auto_unlink or \c safe_link). +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class slist_base_hook + : public make_slist_base_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + slist_base_hook(); + + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + slist_base_hook(const slist_base_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + slist_base_hook& operator=(const slist_base_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in an slist an assertion is raised. If link_mode is + //! \c auto_unlink and \c is_linked() is true, the node is unlinked. + //! + //! Throws: Nothing. + ~slist_base_hook(); + + //! Effects: Swapping two nodes swaps the position of the elements + //! related to those nodes in one or two containers. That is, if the node + //! this is part of the element e1, the node x is part of the element e2 + //! and both elements are included in the containers s1 and s2, then after + //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 + //! at the position of e1. If one element is not in a container, then + //! after the swap-operation the other element is not in a container. + //! Iterators to e1 and e2 related to those nodes are invalidated. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + void swap_nodes(slist_base_hook &other); + + //! Precondition: link_mode must be \c safe_link or \c auto_unlink. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c slist::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + + //! Effects: Removes the node if it's inserted in a container. + //! This function is only allowed if link_mode is \c auto_unlink. + //! + //! Throws: Nothing. + void unlink(); + #endif +}; + +//! Helper metafunction to define a \c slist_member_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_slist_member_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3>::type packed_options; + + typedef detail::generic_hook + < get_slist_node_algo + , member_tag + , packed_options::link_mode + , detail::NoBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Put a public data member slist_member_hook in order to store objects of this class in +//! an list. slist_member_hook holds the data necessary for maintaining the list and +//! provides an appropriate value_traits class for list. +//! +//! The hook admits the following options: \c void_pointer<> and +//! \c link_mode<>. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, +//! \c auto_unlink or \c safe_link). +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class slist_member_hook + : public make_slist_member_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + slist_member_hook(); + + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + slist_member_hook(const slist_member_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + slist_member_hook& operator=(const slist_member_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in an slist an assertion is raised. If link_mode is + //! \c auto_unlink and \c is_linked() is true, the node is unlinked. + //! + //! Throws: Nothing. + ~slist_member_hook(); + + //! Effects: Swapping two nodes swaps the position of the elements + //! related to those nodes in one or two containers. That is, if the node + //! this is part of the element e1, the node x is part of the element e2 + //! and both elements are included in the containers s1 and s2, then after + //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 + //! at the position of e1. If one element is not in a container, then + //! after the swap-operation the other element is not in a container. + //! Iterators to e1 and e2 related to those nodes are invalidated. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + void swap_nodes(slist_member_hook &other); + + //! Precondition: link_mode must be \c safe_link or \c auto_unlink. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c slist::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + + //! Effects: Removes the node if it's inserted in a container. + //! This function is only allowed if link_mode is \c auto_unlink. + //! + //! Throws: Nothing. + void unlink(); + #endif +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_SLIST_HOOK_HPP diff --git a/win32/include/boost/intrusive/splay_set.hpp b/win32/include/boost/intrusive/splay_set.hpp new file mode 100755 index 000000000..d44f649b6 --- /dev/null +++ b/win32/include/boost/intrusive/splay_set.hpp @@ -0,0 +1,2289 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_SPLAY_SET_HPP +#define BOOST_INTRUSIVE_SPLAY_SET_HPP + +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +//! The class template splay_set is an intrusive container, that mimics most of +//! the interface of std::set as described in the C++ standard. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<> and +//! \c compare<>. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class splay_set_impl +{ + /// @cond + typedef splaytree_impl tree_type; + //! This class is + //! non-copyable + splay_set_impl (const splay_set_impl&); + + //! This class is + //! non-assignable + splay_set_impl &operator =(const splay_set_impl&); + + typedef tree_type implementation_defined; + /// @endcond + + public: + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::value_traits value_traits; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::insert_commit_data insert_commit_data; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; + + /// @cond + private: + tree_type tree_; + /// @endcond + + public: + //! Effects: Constructs an empty splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor of the value_compare object throws. + splay_set_impl( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(cmp, v_traits) + {} + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! cmp must be a comparison function that induces a strict weak ordering. + //! + //! Effects: Constructs an empty splay_set and inserts elements from + //! [b, e). + //! + //! Complexity: Linear in N if [b, e) is already sorted using + //! comp and otherwise amortized N * log N, where N is std::distance(last, first). + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor/operator() of the value_compare object throws. + template + splay_set_impl( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(true, b, e, cmp, v_traits) + {} + + //! Effects: Detaches all elements from this. The objects in the splay_set + //! are not deleted (i.e. no destructors are called). + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + ~splay_set_impl() + {} + + //! Effects: Returns an iterator pointing to the beginning of the splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator begin() + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator begin() const + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cbegin() const + { return tree_.cbegin(); } + + //! Effects: Returns an iterator pointing to the end of the splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return tree_.cend(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning of the + //! reversed splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rbegin() + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rbegin() const + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crbegin() const + { return tree_.crbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rend() + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rend() const + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crend() const + { return tree_.crend(); } + + //! Precondition: end_iterator must be a valid end iterator + //! of splay_set. + //! + //! Effects: Returns a const reference to the splay_set associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static splay_set_impl &container_from_end_iterator(iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &splay_set_impl::tree_); + } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of splay_set. + //! + //! Effects: Returns a const reference to the splay_set associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const splay_set_impl &container_from_end_iterator(const_iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &splay_set_impl::tree_); + } + + //! Precondition: it must be a valid iterator of set. + //! + //! Effects: Returns a reference to the set associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static splay_set_impl &container_from_iterator(iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &splay_set_impl::tree_); + } + + //! Precondition: it must be a valid const_iterator of set. + //! + //! Effects: Returns a const reference to the set associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static const splay_set_impl &container_from_iterator(const_iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &splay_set_impl::tree_); + } + + //! Effects: Returns the key_compare object used by the splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: If key_compare copy-constructor throws. + key_compare key_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns the value_compare object used by the splay_set. + //! + //! Complexity: Constant. + //! + //! Throws: If value_compare copy-constructor throws. + value_compare value_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bool empty() const + { return tree_.empty(); } + + //! Effects: Returns the number of elements stored in the splay_set. + //! + //! Complexity: Linear to elements contained in *this if, + //! constant-time size option is enabled. Constant-time otherwise. + //! + //! Throws: Nothing. + size_type size() const + { return tree_.size(); } + + //! Effects: Swaps the contents of two splay_sets. + //! + //! Complexity: Constant. + //! + //! Throws: If the swap() call for the comparison functor + //! found using ADL throws. Strong guarantee. + void swap(splay_set_impl& other) + { tree_.swap(other.tree_); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. + template + void clone_from(const splay_set_impl &src, Cloner cloner, Disposer disposer) + { tree_.clone_from(src.tree_, cloner, disposer); } + + //! Requires: value must be an lvalue + //! + //! Effects: Tries to inserts value into the splay_set. + //! + //! Returns: If the value + //! is not already present inserts it and returns a pair containing the + //! iterator to the new value and true. If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + std::pair insert(reference value) + { return tree_.insert_unique(value); } + + //! Requires: value must be an lvalue + //! + //! Effects: Tries to to insert x into the splay_set, using "hint" + //! as a hint to where it will be inserted. + //! + //! Returns: An iterator that points to the position where the + //! new element was inserted into the splay_set. + //! + //! Complexity: Amortized logarithmic in general, but it's amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert(const_iterator hint, reference value) + { return tree_.insert_unique(hint, value); } + + //! Requires: key_value_comp must be a comparison function that induces + //! the same strict weak ordering as value_compare. The difference is that + //! key_value_comp compares an arbitrary key with the contained values. + //! + //! Effects: Checks if a value can be inserted in the splay_set, using + //! a user provided key instead of the value itself. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. If the value can be inserted returns true in the returned + //! pair boolean and fills "commit_data" that is meant to be used with + //! the "insert_commit" function. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! + //! Notes: This function is used to improve performance when constructing + //! a value_type is expensive: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the order is much cheaper to construct + //! than the value_type and this function offers the possibility to use that + //! part to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the value_type and use + //! "insert_commit" to insert the object in constant-time. This gives a total + //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_commit" only if no more + //! objects are inserted or erased from the splay_set. + template + std::pair insert_check + (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { return tree_.insert_unique_check(key, key_value_comp, commit_data); } + + //! Requires: key_value_comp must be a comparison function that induces + //! the same strict weak ordering as value_compare. The difference is that + //! key_value_comp compares an arbitrary key with the contained values. + //! + //! Effects: Checks if a value can be inserted in the splay_set, using + //! a user provided key instead of the value itself, using "hint" + //! as a hint to where it will be inserted. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. If the value can be inserted returns true in the returned + //! pair boolean and fills "commit_data" that is meant to be used with + //! the "insert_commit" function. + //! + //! Complexity: Amortized logarithmic in general, but it's amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the key_value_comp ordering function throws. Strong guarantee. + //! + //! Notes: This function is used to improve performance when constructing + //! a value_type is expensive: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! constructing that is used to impose the order is much cheaper to construct + //! than the value_type and this function offers the possibility to use that key + //! to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the value_type and use + //! "insert_commit" to insert the object in constant-time. This can give a total + //! constant-time complexity to the insertion: check(O(1)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_commit" only if no more + //! objects are inserted or erased from the splay_set. + template + std::pair insert_check + (const_iterator hint, const KeyType &key + ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { return tree_.insert_unique_check(hint, key, key_value_comp, commit_data); } + + //! Requires: value must be an lvalue of type value_type. commit_data + //! must have been obtained from a previous call to "insert_check". + //! No objects should have been inserted or erased from the splay_set between + //! the "insert_check" that filled "commit_data" and the call to "insert_commit". + //! + //! Effects: Inserts the value in the splay_set using the information obtained + //! from the "commit_data" that a previous "insert_check" filled. + //! + //! Returns: An iterator to the newly inserted object. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function has only sense if a "insert_check" has been + //! previously executed to fill "commit_data". No value should be inserted or + //! erased between the "insert_check" and "insert_commit" calls. + iterator insert_commit(reference value, const insert_commit_data &commit_data) + { return tree_.insert_unique_commit(value, commit_data); } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Inserts a range into the splay_set. + //! + //! Complexity: Insert range is amortized O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert(Iterator b, Iterator e) + { tree_.insert_unique(b, e); } + + //! Effects: Erases the element pointed to by pos. + //! + //! Complexity: Average complexity is constant time. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator i) + { return tree_.erase(i); } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Complexity: Average complexity for erase range is amortized + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator b, iterator e) + { return tree_.erase(b, e); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Amortized O(log(size()) + this->count(value)). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return tree_.erase(value); } + + //! Effects: Erases all the elements that compare equal with + //! the given key and the given comparison functor. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Amortized O(log(size() + this->count(key, comp)). + //! + //! Throws: If the comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyValueCompare comp) + { return tree_.erase(key, comp); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element pointed to by pos. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { return tree_.erase_and_dispose(i, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average complexity for erase range is at most + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) + { return tree_.erase_and_dispose(b, e, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: If the internal value_compare ordering function throws. + //! + //! Complexity: Amortized O(log(size() + this->count(value)). Basic guarantee. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { return tree_.erase_and_dispose(value, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Amortized O(log(size() + this->count(key, comp)). + //! + //! Throws: If comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) + { return tree_.erase_and_dispose(key, comp, disposer); } + + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { return tree_.clear(); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + void clear_and_dispose(Disposer disposer) + { return tree_.clear_and_dispose(disposer); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Amortized logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If the internal value_compare ordering function throws. + size_type count(const_reference value) + { return tree_.find(value) != end(); } + + //! Effects: Returns the number of contained elements with the same key + //! compared with the given comparison functor. + //! + //! Complexity: Amortized logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If comp ordering function throws. + template + size_type count(const KeyType& key, KeyValueCompare comp) + { return tree_.find(key, comp) != end(); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If the internal value_compare ordering function throws. + size_type count_dont_splay(const_reference value)const + { return tree_.find_dont_splay(value) != end(); } + + //! Effects: Returns the number of contained elements with the same key + //! compared with the given comparison functor. + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If comp ordering function throws. + template + size_type count_dont_splay(const KeyType& key, KeyValueCompare comp)const + { return tree_.find_dont_splay(key, comp) != end(); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator lower_bound(const_reference value) + { return tree_.lower_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator lower_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.lower_bound(key, comp); } + + //! Effects: Returns a const iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator lower_bound_dont_splay(const_reference value) const + { return tree_.lower_bound_dont_splay(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator lower_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const + { return tree_.lower_bound_dont_splay(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator upper_bound(const_reference value) + { return tree_.upper_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator upper_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.upper_bound(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator upper_bound_dont_splay(const_reference value) const + { return tree_.upper_bound_dont_splay(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator upper_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const + { return tree_.upper_bound_dont_splay(key, comp); } + + //! Effects: Finds an iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator find(const_reference value) + { return tree_.find(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds an iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator find(const KeyType& key, KeyValueCompare comp) + { return tree_.find(key, comp); } + + //! Effects: Finds a const_iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator find_dont_splay(const_reference value) const + { return tree_.find_dont_splay(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a const_iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator find_dont_splay(const KeyType& key, KeyValueCompare comp) const + { return tree_.find_dont_splay(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair equal_range(const_reference value) + { return tree_.equal_range(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return tree_.equal_range(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair + equal_range_dont_splay(const_reference value) const + { return tree_.equal_range_dont_splay(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair + equal_range_dont_splay(const KeyType& key, KeyValueCompare comp) const + { return tree_.equal_range_dont_splay(key, comp); } + + //! Requires: value must be an lvalue and shall be in a splay_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the splay_set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a splay_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! splay_set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a splay_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the splay_set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator iterator_to(reference value) + { return tree_.iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a splay_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! splay_set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator iterator_to(const_reference value) const + { return tree_.iterator_to(value); } + + //! Requires: value shall not be in a splay_set/multisplay_set. + //! + //! Effects: init_node puts the hook of a value in a well-known default + //! state. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This function puts the hook in the well-known default state + //! used by auto_unlink and safe hooks. + static void init_node(reference value) + { tree_type::init_node(value); } + + //! Effects: Unlinks the leftmost node from the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + pointer unlink_leftmost_without_rebalance() + { return tree_.unlink_leftmost_without_rebalance(); } + + //! Requires: replace_this must be a valid iterator of *this + //! and with_this must not be inserted in any tree. + //! + //! Effects: Replaces replace_this in its position in the + //! tree with with_this. The tree does not need to be rebalanced. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! with_this is not equivalent to *replace_this according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + void replace_node(iterator replace_this, reference with_this) + { tree_.replace_node(replace_this, with_this); } + + //! Requires: i must be a valid iterator of *this. + //! + //! Effects: Rearranges the splay set so that the element pointed by i + //! is placed as the root of the tree, improving future searches of this value. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: Nothing. + void splay_up(iterator i) + { tree_.splay_up(i); } + + //! Effects: Rearranges the splay set so that if *this stores an element + //! with a key equivalent to value the element is placed as the root of the + //! tree. If the element is not present returns the last node compared with the key. + //! If the tree is empty, end() is returned. + //! + //! Complexity: Amortized logarithmic. + //! + //! Returns: An iterator to the new root of the tree, end() if the tree is empty. + //! + //! Throws: If the comparison functor throws. + template + iterator splay_down(const KeyType &key, KeyNodePtrCompare comp) + { return tree_.splay_down(key, comp); } + + //! Effects: Rearranges the splay set so that if *this stores an element + //! with a key equivalent to value the element is placed as the root of the + //! tree. + //! + //! Complexity: Amortized logarithmic. + //! + //! Returns: An iterator to the new root of the tree, end() if the tree is empty. + //! + //! Throws: If the predicate throws. + iterator splay_down(const value_type &value) + { return tree_.splay_down(value); } + + //! Effects: Rebalances the tree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear. + void rebalance() + { tree_.rebalance(); } + + //! Requires: old_root is a node of a tree. + //! + //! Effects: Rebalances the subtree rooted at old_root. + //! + //! Returns: The new root of the subtree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements in the subtree. + iterator rebalance_subtree(iterator root) + { return tree_.rebalance_subtree(root); } + + /// @cond + friend bool operator==(const splay_set_impl &x, const splay_set_impl &y) + { return x.tree_ == y.tree_; } + + friend bool operator<(const splay_set_impl &x, const splay_set_impl &y) + { return x.tree_ < y.tree_; } + /// @endcond +}; + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator!= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const splay_set_impl &x, const splay_set_impl &y) +#else +(const splay_set_impl &x, const splay_set_impl &y) +#endif +{ return !(x == y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator> +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const splay_set_impl &x, const splay_set_impl &y) +#else +(const splay_set_impl &x, const splay_set_impl &y) +#endif +{ return y < x; } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator<= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const splay_set_impl &x, const splay_set_impl &y) +#else +(const splay_set_impl &x, const splay_set_impl &y) +#endif +{ return !(y < x); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator>= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const splay_set_impl &x, const splay_set_impl &y) +#else +(const splay_set_impl &x, const splay_set_impl &y) +#endif +{ return !(x < y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline void swap +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(splay_set_impl &x, splay_set_impl &y) +#else +(splay_set_impl &x, splay_set_impl &y) +#endif +{ x.swap(y); } + +//! Helper metafunction to define a \c splay_set that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_splay_set +{ + /// @cond + typedef splay_set_impl + < typename make_splaytree_opt::type + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class splay_set + : public make_splay_set::type +{ + typedef typename make_splay_set + ::type Base; + + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + splay_set( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + splay_set( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(b, e, cmp, v_traits) + {} + + static splay_set &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const splay_set &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static splay_set &container_from_iterator(iterator it) + { return static_cast(Base::container_from_iterator(it)); } + + static const splay_set &container_from_iterator(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } +}; + +#endif + +//! The class template splay_multiset is an intrusive container, that mimics most of +//! the interface of std::multiset as described in the C++ standard. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<> and +//! \c compare<>. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class splay_multiset_impl +{ + /// @cond + typedef splaytree_impl tree_type; + + //Non-copyable and non-assignable + splay_multiset_impl (const splay_multiset_impl&); + splay_multiset_impl &operator =(const splay_multiset_impl&); + typedef tree_type implementation_defined; + /// @endcond + + public: + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::value_traits value_traits; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::value_compare value_compare; + typedef typename implementation_defined::key_compare key_compare; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::reverse_iterator reverse_iterator; + typedef typename implementation_defined::const_reverse_iterator const_reverse_iterator; + typedef typename implementation_defined::insert_commit_data insert_commit_data; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; + + /// @cond + private: + tree_type tree_; + /// @endcond + + public: + //! Effects: Constructs an empty splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor/operator() of the value_compare object throws. + splay_multiset_impl( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(cmp, v_traits) + {} + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! cmp must be a comparison function that induces a strict weak ordering. + //! + //! Effects: Constructs an empty splay_multiset and inserts elements from + //! [b, e). + //! + //! Complexity: Linear in N if [b, e) is already sorted using + //! comp and otherwise amortized N * log N, where N is the distance between first and last. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor/operator() of the value_compare object throws. + template + splay_multiset_impl( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : tree_(false, b, e, cmp, v_traits) + {} + + //! Effects: Detaches all elements from this. The objects in the set + //! are not deleted (i.e. no destructors are called). + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + ~splay_multiset_impl() + {} + + //! Effects: Returns an iterator pointing to the beginning of the splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator begin() + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator begin() const + { return tree_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cbegin() const + { return tree_.cbegin(); } + + //! Effects: Returns an iterator pointing to the end of the splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return tree_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return tree_.cend(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning of the + //! reversed splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rbegin() + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rbegin() const + { return tree_.rbegin(); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crbegin() const + { return tree_.crbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rend() + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rend() const + { return tree_.rend(); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crend() const + { return tree_.crend(); } + + //! Precondition: end_iterator must be a valid end iterator + //! of splay_multiset. + //! + //! Effects: Returns a const reference to the splay_multiset associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static splay_multiset_impl &container_from_end_iterator(iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &splay_multiset_impl::tree_); + } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of splay_multiset. + //! + //! Effects: Returns a const reference to the splay_multiset associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const splay_multiset_impl &container_from_end_iterator(const_iterator end_iterator) + { + return *detail::parent_from_member + ( &tree_type::container_from_end_iterator(end_iterator) + , &splay_multiset_impl::tree_); + } + + //! Precondition: it must be a valid iterator of multiset. + //! + //! Effects: Returns a const reference to the multiset associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static splay_multiset_impl &container_from_iterator(iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &splay_multiset_impl::tree_); + } + + //! Precondition: it must be a valid const_iterator of multiset. + //! + //! Effects: Returns a const reference to the multiset associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const splay_multiset_impl &container_from_iterator(const_iterator it) + { + return *detail::parent_from_member + ( &tree_type::container_from_iterator(it) + , &splay_multiset_impl::tree_); + } + + //! Effects: Returns the key_compare object used by the splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If key_compare copy-constructor throws. + key_compare key_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns the value_compare object used by the splay_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If value_compare copy-constructor throws. + value_compare value_comp() const + { return tree_.value_comp(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bool empty() const + { return tree_.empty(); } + + //! Effects: Returns the number of elements stored in the splay_multiset. + //! + //! Complexity: Linear to elements contained in *this if, + //! constant-time size option is enabled. Constant-time otherwise. + //! + //! Throws: Nothing. + size_type size() const + { return tree_.size(); } + + //! Effects: Swaps the contents of two splay_multisets. + //! + //! Complexity: Constant. + //! + //! Throws: If the swap() call for the comparison functor + //! found using ADL throws. Strong guarantee. + void swap(splay_multiset_impl& other) + { tree_.swap(other.tree_); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. Basic guarantee. + template + void clone_from(const splay_multiset_impl &src, Cloner cloner, Disposer disposer) + { tree_.clone_from(src.tree_, cloner, disposer); } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the splay_multiset. + //! + //! Returns: An iterator that points to the position where the new + //! element was inserted. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert(reference value) + { return tree_.insert_equal(this->end(), value); } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts x into the splay_multiset, using pos as a hint to + //! where it will be inserted. + //! + //! Returns: An iterator that points to the position where the new + //! element was inserted. + //! + //! Complexity: Amortized logarithmic in general, but it is amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: If the internal value_compare ordering function throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert(const_iterator hint, reference value) + { return tree_.insert_equal(hint, value); } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Inserts a range into the splay_multiset. + //! + //! Returns: An iterator that points to the position where the new + //! element was inserted. + //! + //! Complexity: Insert range is amortized O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert(Iterator b, Iterator e) + { tree_.insert_equal(b, e); } + + //! Effects: Erases the element pointed to by pos. + //! + //! Complexity: Average complexity is constant time. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator i) + { return tree_.erase(i); } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Complexity: Average complexity for erase range is amortized + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator b, iterator e) + { return tree_.erase(b, e); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Amortized O(log(size() + this->count(value)). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return tree_.erase(value); } + + //! Effects: Erases all the elements that compare equal with + //! the given key and the given comparison functor. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Amortized O(log(size() + this->count(key, comp)). + //! + //! Throws: If comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyValueCompare comp) + { return tree_.erase(key, comp); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Returns: An iterator to the element after the erased element. + //! + //! Effects: Erases the element pointed to by pos. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { return tree_.erase_and_dispose(i, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Returns: An iterator to the element after the erased elements. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average complexity for erase range is amortized + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) + { return tree_.erase_and_dispose(b, e, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Amortized O(log(size() + this->count(value)). + //! + //! Throws: If the internal value_compare ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { return tree_.erase_and_dispose(value, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Amortized O(log(size() + this->count(key, comp)). + //! + //! Throws: If comp ordering function throws. Basic guarantee. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) + { return tree_.erase_and_dispose(key, comp, disposer); } + + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { return tree_.clear(); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + void clear_and_dispose(Disposer disposer) + { return tree_.clear_and_dispose(disposer); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Amortized logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If the internal value_compare ordering function throws. + size_type count(const_reference value) + { return tree_.count(value); } + + //! Effects: Returns the number of contained elements with the same key + //! compared with the given comparison functor. + //! + //! Complexity: Amortized logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If comp ordering function throws. + template + size_type count(const KeyType& key, KeyValueCompare comp) + { return tree_.count(key, comp); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If the internal value_compare ordering function throws. + size_type count_dont_splay(const_reference value) const + { return tree_.count_dont_splay(value); } + + //! Effects: Returns the number of contained elements with the same key + //! compared with the given comparison functor. + //! + //! Complexity: Logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: If comp ordering function throws. + template + size_type count_dont_splay(const KeyType& key, KeyValueCompare comp) const + { return tree_.count_dont_splay(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator lower_bound(const_reference value) + { return tree_.lower_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator lower_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.lower_bound(key, comp); } + + //! Effects: Returns a const iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator lower_bound_dont_splay(const_reference value) const + { return tree_.lower_bound_dont_splay(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is not less than k or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator lower_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const + { return tree_.lower_bound_dont_splay(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator upper_bound(const_reference value) + { return tree_.upper_bound(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns an iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator upper_bound(const KeyType& key, KeyValueCompare comp) + { return tree_.upper_bound(key, comp); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator upper_bound_dont_splay(const_reference value) const + { return tree_.upper_bound_dont_splay(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Returns a const_iterator to the first element whose + //! key according to the comparison functor is greater than key or + //! end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator upper_bound_dont_splay(const KeyType& key, KeyValueCompare comp) const + { return tree_.upper_bound_dont_splay(key, comp); } + + //! Effects: Finds an iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + iterator find(const_reference value) + { return tree_.find(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds an iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator find(const KeyType& key, KeyValueCompare comp) + { return tree_.find(key, comp); } + + //! Effects: Finds a const_iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + const_iterator find_dont_splay(const_reference value) const + { return tree_.find_dont_splay(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a const_iterator to the first element whose key is + //! "key" according to the comparison functor or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator find_dont_splay(const KeyType& key, KeyValueCompare comp) const + { return tree_.find_dont_splay(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair equal_range(const_reference value) + { return tree_.equal_range(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair equal_range(const KeyType& key, KeyValueCompare comp) + { return tree_.equal_range(key, comp); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If the internal value_compare ordering function throws. + std::pair + equal_range_dont_splay(const_reference value) const + { return tree_.equal_range_dont_splay(value); } + + //! Requires: comp must imply the same element order as + //! value_compare. Usually key is the part of the value_type + //! that is used in the ordering functor. + //! + //! Effects: Finds a range containing all elements whose key is k + //! according to the comparison functor or an empty range + //! that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If comp ordering function throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair + equal_range_dont_splay(const KeyType& key, KeyValueCompare comp) const + { return tree_.equal_range_dont_splay(key, comp); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value) + { return tree_type::s_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator iterator_to(reference value) + { return tree_.iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator iterator_to(const_reference value) const + { return tree_.iterator_to(value); } + + //! Requires: value shall not be in a set/splay_multiset. + //! + //! Effects: init_node puts the hook of a value in a well-known default + //! state. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This function puts the hook in the well-known default state + //! used by auto_unlink and safe hooks. + static void init_node(reference value) + { tree_type::init_node(value); } + + //! Effects: Unlinks the leftmost node from the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + pointer unlink_leftmost_without_rebalance() + { return tree_.unlink_leftmost_without_rebalance(); } + + //! Requires: replace_this must be a valid iterator of *this + //! and with_this must not be inserted in any tree. + //! + //! Effects: Replaces replace_this in its position in the + //! tree with with_this. The tree does not need to be rebalanced. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! with_this is not equivalent to *replace_this according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + void replace_node(iterator replace_this, reference with_this) + { tree_.replace_node(replace_this, with_this); } + + //! Requires: i must be a valid iterator of *this. + //! + //! Effects: Rearranges the splay set so that the element pointed by i + //! is placed as the root of the tree, improving future searches of this value. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: Nothing. + void splay_up(iterator i) + { tree_.splay_up(i); } + + //! Effects: Rearranges the splay set so that if *this stores an element + //! with a key equivalent to value the element is placed as the root of the + //! tree. If the element is not present returns the last node compared with the key. + //! If the tree is empty, end() is returned. + //! + //! Complexity: Amortized logarithmic. + //! + //! Returns: An iterator to the new root of the tree, end() if the tree is empty. + //! + //! Throws: If the comparison functor throws. + template + iterator splay_down(const KeyType &key, KeyNodePtrCompare comp) + { return tree_.splay_down(key, comp); } + + //! Effects: Rearranges the splay set so that if *this stores an element + //! with a key equivalent to value the element is placed as the root of the + //! tree. + //! + //! Complexity: Amortized logarithmic. + //! + //! Returns: An iterator to the new root of the tree, end() if the tree is empty. + //! + //! Throws: If the predicate throws. + iterator splay_down(const value_type &value) + { return tree_.splay_down(value); } + + //! Effects: Rebalances the tree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear. + void rebalance() + { tree_.rebalance(); } + + //! Requires: old_root is a node of a tree. + //! + //! Effects: Rebalances the subtree rooted at old_root. + //! + //! Returns: The new root of the subtree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements in the subtree. + iterator rebalance_subtree(iterator root) + { return tree_.rebalance_subtree(root); } + + /// @cond + friend bool operator==(const splay_multiset_impl &x, const splay_multiset_impl &y) + { return x.tree_ == y.tree_; } + + friend bool operator<(const splay_multiset_impl &x, const splay_multiset_impl &y) + { return x.tree_ < y.tree_; } + /// @endcond +}; + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator!= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const splay_multiset_impl &x, const splay_multiset_impl &y) +#else +(const splay_multiset_impl &x, const splay_multiset_impl &y) +#endif +{ return !(x == y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator> +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const splay_multiset_impl &x, const splay_multiset_impl &y) +#else +(const splay_multiset_impl &x, const splay_multiset_impl &y) +#endif +{ return y < x; } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator<= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const splay_multiset_impl &x, const splay_multiset_impl &y) +#else +(const splay_multiset_impl &x, const splay_multiset_impl &y) +#endif +{ return !(y < x); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator>= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const splay_multiset_impl &x, const splay_multiset_impl &y) +#else +(const splay_multiset_impl &x, const splay_multiset_impl &y) +#endif +{ return !(x < y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline void swap +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(splay_multiset_impl &x, splay_multiset_impl &y) +#else +(splay_multiset_impl &x, splay_multiset_impl &y) +#endif +{ x.swap(y); } + +//! Helper metafunction to define a \c splay_multiset that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_splay_multiset +{ + /// @cond + typedef splay_multiset_impl + < typename make_splaytree_opt::type + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class splay_multiset + : public make_splay_multiset::type +{ + typedef typename make_splay_multiset + ::type Base; + + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + splay_multiset( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + splay_multiset( Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(b, e, cmp, v_traits) + {} + + static splay_multiset &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const splay_multiset &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static splay_multiset &container_from_iterator(iterator it) + { return static_cast(Base::container_from_iterator(it)); } + + static const splay_multiset &container_from_iterator(const_iterator it) + { return static_cast(Base::container_from_iterator(it)); } +}; + +#endif + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_SPLAY_SET_HPP diff --git a/win32/include/boost/intrusive/splay_set_hook.hpp b/win32/include/boost/intrusive/splay_set_hook.hpp new file mode 100755 index 000000000..43ef0c6d5 --- /dev/null +++ b/win32/include/boost/intrusive/splay_set_hook.hpp @@ -0,0 +1,266 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_SPLAY_SET_HOOK_HPP +#define BOOST_INTRUSIVE_SPLAY_SET_HOOK_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond +template +struct get_splay_set_node_algo +{ + typedef splaytree_algorithms > type; +}; +/// @endcond + +//! Helper metafunction to define a \c splay_set_base_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_splay_set_base_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3>::type packed_options; + + typedef detail::generic_hook + < get_splay_set_node_algo + , typename packed_options::tag + , packed_options::link_mode + , detail::SplaySetBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Derive a class from splay_set_base_hook in order to store objects in +//! in a splay_set/splay_multiset. splay_set_base_hook holds the data necessary to maintain +//! the splay_set/splay_multiset and provides an appropriate value_traits class for splay_set/splay_multiset. +//! +//! The hook admits the following options: \c tag<>, \c void_pointer<>, +//! \c link_mode<> and \c optimize_size<>. +//! +//! \c tag<> defines a tag to identify the node. +//! The same tag value can be used in different classes, but if a class is +//! derived from more than one \c list_base_hook, then each \c list_base_hook needs its +//! unique tag. +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, +//! \c auto_unlink or \c safe_link). +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class splay_set_base_hook + : public make_splay_set_base_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + splay_set_base_hook(); + + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + splay_set_base_hook(const splay_set_base_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + splay_set_base_hook& operator=(const splay_set_base_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in a set an assertion is raised. If link_mode is + //! \c auto_unlink and \c is_linked() is true, the node is unlinked. + //! + //! Throws: Nothing. + ~splay_set_base_hook(); + + //! Effects: Swapping two nodes swaps the position of the elements + //! related to those nodes in one or two containers. That is, if the node + //! this is part of the element e1, the node x is part of the element e2 + //! and both elements are included in the containers s1 and s2, then after + //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 + //! at the position of e1. If one element is not in a container, then + //! after the swap-operation the other element is not in a container. + //! Iterators to e1 and e2 related to those nodes are invalidated. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + void swap_nodes(splay_set_base_hook &other); + + //! Precondition: link_mode must be \c safe_link or \c auto_unlink. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c set::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + + //! Effects: Removes the node if it's inserted in a container. + //! This function is only allowed if link_mode is \c auto_unlink. + //! + //! Throws: Nothing. + void unlink(); + #endif +}; + +//! Helper metafunction to define a \c splay_set_member_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_splay_set_member_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3>::type packed_options; + + typedef detail::generic_hook + < get_splay_set_node_algo + , member_tag + , packed_options::link_mode + , detail::NoBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Put a public data member splay_set_member_hook in order to store objects of this +//! class in a splay_set/splay_multiset. splay_set_member_hook holds the data +//! necessary for maintaining the splay_set/splay_multiset and provides an appropriate +//! value_traits class for splay_set/splay_multiset. +//! +//! The hook admits the following options: \c void_pointer<>, +//! \c link_mode<> and \c optimize_size<>. +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, +//! \c auto_unlink or \c safe_link). +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class splay_set_member_hook + : public make_splay_set_member_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + splay_set_member_hook(); + + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + splay_set_member_hook(const splay_set_member_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + splay_set_member_hook& operator=(const splay_set_member_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in a set an assertion is raised. If link_mode is + //! \c auto_unlink and \c is_linked() is true, the node is unlinked. + //! + //! Throws: Nothing. + ~splay_set_member_hook(); + + //! Effects: Swapping two nodes swaps the position of the elements + //! related to those nodes in one or two containers. That is, if the node + //! this is part of the element e1, the node x is part of the element e2 + //! and both elements are included in the containers s1 and s2, then after + //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 + //! at the position of e1. If one element is not in a container, then + //! after the swap-operation the other element is not in a container. + //! Iterators to e1 and e2 related to those nodes are invalidated. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + void swap_nodes(splay_set_member_hook &other); + + //! Precondition: link_mode must be \c safe_link or \c auto_unlink. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c set::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + + //! Effects: Removes the node if it's inserted in a container. + //! This function is only allowed if link_mode is \c auto_unlink. + //! + //! Throws: Nothing. + void unlink(); + #endif +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_SPLAY_SET_HOOK_HPP diff --git a/win32/include/boost/intrusive/splaytree.hpp b/win32/include/boost/intrusive/splaytree.hpp new file mode 100755 index 000000000..1b405e424 --- /dev/null +++ b/win32/include/boost/intrusive/splaytree.hpp @@ -0,0 +1,1543 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_SPLAYTREE_HPP +#define BOOST_INTRUSIVE_SPLAYTREE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { +namespace intrusive { + +/// @cond + +template +struct internal_default_splay_set_hook +{ + template static detail::one test(...); + template static detail::two test(typename U::default_splay_set_hook* = 0); + static const bool value = sizeof(test(0)) == sizeof(detail::two); +}; + +template +struct get_default_splay_set_hook +{ + typedef typename T::default_splay_set_hook type; +}; + +template +struct splaysetopt +{ + typedef ValueTraits value_traits; + typedef Compare compare; + typedef SizeType size_type; + static const bool constant_time_size = ConstantTimeSize; +}; + +template +struct splay_set_defaults + : pack_options + < none + , base_hook + < typename detail::eval_if_c + < internal_default_splay_set_hook::value + , get_default_splay_set_hook + , detail::identity + >::type + > + , constant_time_size + , size_type + , compare > + >::type +{}; + +/// @endcond + +//! The class template splaytree is an intrusive splay tree container that +//! is used to construct intrusive splay_set and splay_multiset containers. The no-throw +//! guarantee holds only, if the value_compare object +//! doesn't throw. +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<> and +//! \c compare<>. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class splaytree_impl +{ + public: + typedef typename Config::value_traits value_traits; + /// @cond + static const bool external_value_traits = + detail::external_value_traits_is_true::value; + typedef typename detail::eval_if_c + < external_value_traits + , detail::eval_value_traits + , detail::identity + >::type real_value_traits; + /// @endcond + typedef typename real_value_traits::pointer pointer; + typedef typename real_value_traits::const_pointer const_pointer; + typedef typename std::iterator_traits::value_type value_type; + typedef value_type key_type; + typedef typename std::iterator_traits::reference reference; + typedef typename std::iterator_traits::reference const_reference; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename Config::size_type size_type; + typedef typename Config::compare value_compare; + typedef value_compare key_compare; + typedef tree_iterator iterator; + typedef tree_iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef typename real_value_traits::node_traits node_traits; + typedef typename node_traits::node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + typedef splaytree_algorithms node_algorithms; + + static const bool constant_time_size = Config::constant_time_size; + static const bool stateful_value_traits = detail::store_cont_ptr_on_it::value; + + /// @cond + private: + typedef detail::size_holder size_traits; + + //noncopyable + splaytree_impl (const splaytree_impl&); + splaytree_impl operator =(const splaytree_impl&); + + enum { safemode_or_autounlink = + (int)real_value_traits::link_mode == (int)auto_unlink || + (int)real_value_traits::link_mode == (int)safe_link }; + + //Constant-time size is incompatible with auto-unlink hooks! + BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); + + struct header_plus_size : public size_traits + { node header_; }; + + struct node_plus_pred_t : public detail::ebo_functor_holder + { + node_plus_pred_t(const value_compare &comp) + : detail::ebo_functor_holder(comp) + {} + header_plus_size header_plus_size_; + }; + + struct data_t : public splaytree_impl::value_traits + { + typedef typename splaytree_impl::value_traits value_traits; + data_t(const value_compare & comp, const value_traits &val_traits) + : value_traits(val_traits), node_plus_pred_(comp) + {} + node_plus_pred_t node_plus_pred_; + } data_; + + const value_compare &priv_comp() const + { return data_.node_plus_pred_.get(); } + + value_compare &priv_comp() + { return data_.node_plus_pred_.get(); } + + const node &priv_header() const + { return data_.node_plus_pred_.header_plus_size_.header_; } + + node &priv_header() + { return data_.node_plus_pred_.header_plus_size_.header_; } + + static node_ptr uncast(const_node_ptr ptr) + { + return node_ptr(const_cast(detail::get_pointer(ptr))); + } + + size_traits &priv_size_traits() + { return data_.node_plus_pred_.header_plus_size_; } + + const size_traits &priv_size_traits() const + { return data_.node_plus_pred_.header_plus_size_; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return data_; } + + const real_value_traits &get_real_value_traits(detail::bool_) const + { return data_.get_value_traits(*this); } + + real_value_traits &get_real_value_traits(detail::bool_) + { return data_; } + + real_value_traits &get_real_value_traits(detail::bool_) + { return data_.get_value_traits(*this); } + + /// @endcond + + public: + + const real_value_traits &get_real_value_traits() const + { return this->get_real_value_traits(detail::bool_()); } + + real_value_traits &get_real_value_traits() + { return this->get_real_value_traits(detail::bool_()); } + + typedef typename node_algorithms::insert_commit_data insert_commit_data; + + //! Effects: Constructs an empty tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing unless the copy constructor of the value_compare object throws. + splaytree_impl( value_compare cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : data_(cmp, v_traits) + { + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(size_type(0)); + } + + //! Requires: Dereferencing iterator must yield an lvalue of type value_type. + //! cmp must be a comparison function that induces a strict weak ordering. + //! + //! Effects: Constructs an empty tree and inserts elements from + //! [b, e). + //! + //! Complexity: Linear in N if [b, e) is already sorted using + //! comp and otherwise amortized N * log N, where N is the distance between first and last. + //! + //! Throws: Nothing unless the copy constructor of the value_compare object throws. + template + splaytree_impl( bool unique, Iterator b, Iterator e + , value_compare cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : data_(cmp, v_traits) + { + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(size_type(0)); + if(unique) + this->insert_unique(b, e); + else + this->insert_equal(b, e); + } + + //! Effects: Detaches all elements from this. The objects in the set + //! are not deleted (i.e. no destructors are called), but the nodes according to + //! the value_traits template parameter are reinitialized and thus can be reused. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + ~splaytree_impl() + { this->clear(); } + + //! Effects: Returns an iterator pointing to the beginning of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator begin() + { return iterator(node_algorithms::begin_node(&priv_header()), this); } + + //! Effects: Returns a const_iterator pointing to the beginning of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator begin() const + { return cbegin(); } + + //! Effects: Returns a const_iterator pointing to the beginning of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cbegin() const + { return const_iterator(node_algorithms::begin_node(&priv_header()), this); } + + //! Effects: Returns an iterator pointing to the end of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return iterator (node_ptr(&priv_header()), this); } + + //! Effects: Returns a const_iterator pointing to the end of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return cend(); } + + //! Effects: Returns a const_iterator pointing to the end of the tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return const_iterator (uncast(const_node_ptr(&priv_header())), this); } + + //! Effects: Returns a reverse_iterator pointing to the beginning of the + //! reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rbegin() + { return reverse_iterator(end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rbegin() const + { return const_reverse_iterator(end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crbegin() const + { return const_reverse_iterator(end()); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + reverse_iterator rend() + { return reverse_iterator(begin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator rend() const + { return const_reverse_iterator(begin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_reverse_iterator crend() const + { return const_reverse_iterator(begin()); } + + //! Precondition: end_iterator must be a valid end iterator + //! of splaytree. + //! + //! Effects: Returns a const reference to the splaytree associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static splaytree_impl &container_from_end_iterator(iterator end_iterator) + { return priv_container_from_end_iterator(end_iterator); } + + //! Precondition: end_iterator must be a valid end const_iterator + //! of splaytree. + //! + //! Effects: Returns a const reference to the splaytree associated to the end iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + static const splaytree_impl &container_from_end_iterator(const_iterator end_iterator) + { return priv_container_from_end_iterator(end_iterator); } + + //! Precondition: it must be a valid iterator + //! of rbtree. + //! + //! Effects: Returns a const reference to the tree associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static splaytree_impl &container_from_iterator(iterator it) + { return priv_container_from_iterator(it); } + + //! Precondition: it must be a valid end const_iterator + //! of rbtree. + //! + //! Effects: Returns a const reference to the tree associated to the iterator + //! + //! Throws: Nothing. + //! + //! Complexity: Logarithmic. + static const splaytree_impl &container_from_iterator(const_iterator it) + { return priv_container_from_iterator(it); } + + //! Effects: Returns the value_compare object used by the tree. + //! + //! Complexity: Constant. + //! + //! Throws: If value_compare copy-constructor throws. + value_compare value_comp() const + { return priv_comp(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bool empty() const + { return this->cbegin() == this->cend(); } + + //! Effects: Returns the number of elements stored in the tree. + //! + //! Complexity: Linear to elements contained in *this. + //! + //! Throws: Nothing. + size_type size() const + { + if(constant_time_size){ + return this->priv_size_traits().get_size(); + } + else{ + return (size_type)node_algorithms::size(const_node_ptr(&priv_header())); + } + } + + //! Effects: Swaps the contents of two multisets. + //! + //! Complexity: Constant. + //! + //! Throws: If the comparison functor's swap call throws. + void swap(splaytree_impl& other) + { + //This can throw + using std::swap; + swap(priv_comp(), priv_comp()); + //These can't throw + node_algorithms::swap_tree(node_ptr(&priv_header()), node_ptr(&other.priv_header())); + if(constant_time_size){ + size_type backup = this->priv_size_traits().get_size(); + this->priv_size_traits().set_size(other.priv_size_traits().get_size()); + other.priv_size_traits().set_size(backup); + } + } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the tree before the lower bound. + //! + //! Complexity: Average complexity for insert element is amortized + //! logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_equal(reference value) + { + detail::key_nodeptr_comp + key_node_comp(priv_comp(), this); + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + return iterator(node_algorithms::insert_equal_lower_bound + (node_ptr(&priv_header()), to_insert, key_node_comp), this); + } + + //! Requires: value must be an lvalue, and "hint" must be + //! a valid iterator. + //! + //! Effects: Inserts x into the tree, using "hint" as a hint to + //! where it will be inserted. If "hint" is the upper_bound + //! the insertion takes constant time (two comparisons in the worst case) + //! + //! Complexity: Amortized logarithmic in general, but it is amortized + //! constant time if t is inserted immediately before hint. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_equal(const_iterator hint, reference value) + { + detail::key_nodeptr_comp + key_node_comp(priv_comp(), this); + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + return iterator(node_algorithms::insert_equal + (node_ptr(&priv_header()), hint.pointed_node(), to_insert, key_node_comp), this); + } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Inserts a each element of a range into the tree + //! before the upper bound of the key of each element. + //! + //! Complexity: Insert range is in general amortized O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert_equal(Iterator b, Iterator e) + { + if(this->empty()){ + iterator end(this->end()); + for (; b != e; ++b) + this->insert_equal(end, *b); + } + } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the tree if the value + //! is not already present. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + std::pair insert_unique(reference value) + { + insert_commit_data commit_data; + std::pair ret = insert_unique_check(value, commit_data); + if(!ret.second) + return ret; + return std::pair (insert_unique_commit(value, commit_data), true); + } + + //! Requires: value must be an lvalue, and "hint" must be + //! a valid iterator + //! + //! Effects: Tries to insert x into the tree, using "hint" as a hint + //! to where it will be inserted. + //! + //! Complexity: Amortized logarithmic in general, but it is amortized + //! constant time (two comparisons in the worst case) + //! if t is inserted immediately before hint. + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert_unique(const_iterator hint, reference value) + { + insert_commit_data commit_data; + std::pair ret = insert_unique_check(hint, value, commit_data); + if(!ret.second) + return ret.first; + return insert_unique_commit(value, commit_data); + } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Tries to insert each element of a range into the tree. + //! + //! Complexity: Insert range is in general amortized O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: Nothing. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert_unique(Iterator b, Iterator e) + { + for (; b != e; ++b) + this->insert_unique(*b); + } + + std::pair insert_unique_check + (const_reference value, insert_commit_data &commit_data) + { return insert_unique_check(value, priv_comp(), commit_data); } + + template + std::pair insert_unique_check + (const KeyType &key, KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { + detail::key_nodeptr_comp + comp(key_value_comp, this); + std::pair ret = + (node_algorithms::insert_unique_check + (node_ptr(&priv_header()), key, comp, commit_data)); + return std::pair(iterator(ret.first, this), ret.second); + } + + std::pair insert_unique_check + (const_iterator hint, const_reference value, insert_commit_data &commit_data) + { return insert_unique_check(hint, value, priv_comp(), commit_data); } + + template + std::pair insert_unique_check + (const_iterator hint, const KeyType &key + ,KeyValueCompare key_value_comp, insert_commit_data &commit_data) + { + detail::key_nodeptr_comp + comp(key_value_comp, this); + std::pair ret = + node_algorithms::insert_unique_check + (node_ptr(&priv_header()), hint.pointed_node(), key, comp, commit_data); + return std::pair(iterator(ret.first, this), ret.second); + } + + iterator insert_unique_commit(reference value, const insert_commit_data &commit_data) + { + node_ptr to_insert(get_real_value_traits().to_node_ptr(value)); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::unique(to_insert)); + this->priv_size_traits().increment(); + node_algorithms::insert_unique_commit + (node_ptr(&priv_header()), to_insert, commit_data); + return iterator(to_insert, this); + } + + //! Effects: Erases the element pointed to by pos. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator i) + { + iterator ret(i); + ++ret; + node_ptr to_erase(i.pointed_node()); + if(safemode_or_autounlink) + BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(!node_algorithms::unique(to_erase)); + node_algorithms::erase(&priv_header(), to_erase); + this->priv_size_traits().decrement(); + if(safemode_or_autounlink) + node_algorithms::init(to_erase); + return ret; + } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Complexity: Average complexity for erase range is amortized + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + iterator erase(iterator b, iterator e) + { size_type n; return private_erase(b, e, n); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Amortized O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return this->erase(value, priv_comp()); } + + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Amortized O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyValueCompare comp) + { + std::pair p = this->equal_range(key, comp); + size_type n; + private_erase(p.first, p.second, n); + return n; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element pointed to by pos. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average complexity for erase element is constant time. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator i, Disposer disposer) + { + node_ptr to_erase(i.pointed_node()); + iterator ret(this->erase(i)); + disposer(get_real_value_traits().to_value_ptr(to_erase)); + return ret; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average complexity for erase range is amortized + //! O(log(size() + N)), where N is the number of elements in the range. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(iterator b, iterator e, Disposer disposer) + { size_type n; return private_erase(b, e, n, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Amortized O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { + std::pair p = this->equal_range(value); + size_type n; + private_erase(p.first, p.second, n, disposer); + return n; + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "comp". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Amortized O(log(size() + N). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyValueCompare comp, Disposer disposer) + { + std::pair p = this->equal_range(key, comp); + size_type n; + private_erase(p.first, p.second, n, disposer); + return n; + } + + //! Effects: Erases all of the elements. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { + if(safemode_or_autounlink){ + this->clear_and_dispose(detail::null_disposer()); + } + else{ + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(0); + } + } + + //! Effects: Erases all of the elements calling disposer(p) for + //! each node to be erased. + //! Complexity: Amortized O(log(size() + N)), + //! where N is the number of elements in the container. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. Calls N times to disposer functor. + template + void clear_and_dispose(Disposer disposer) + { + node_algorithms::clear_and_dispose(node_ptr(&priv_header()) + , detail::node_disposer(disposer, this)); + node_algorithms::init_header(&priv_header()); + this->priv_size_traits().set_size(0); + } + + //! Effects: Returns the number of contained elements with the given value + //! + //! Complexity: Amortized logarithmic to the number of elements contained plus lineal + //! to number of objects with the given value. + //! + //! Throws: Nothing. + size_type count(const_reference value) + { return this->count(value, priv_comp()); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Amortized logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: Nothing. + template + size_type count(const KeyType &key, KeyValueCompare comp) + { + std::pair ret = this->equal_range(key, comp); + return std::distance(ret.first, ret.second); + } + + //! Effects: Returns the number of contained elements with the given value + //! + //! Complexity: Amortized logarithmic to the number of elements contained plus lineal + //! to number of objects with the given value. + //! + //! Throws: Nothing. + size_type count_dont_splay(const_reference value) const + { return this->count_dont_splay(value, priv_comp()); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Amortized logarithmic to the number of elements contained plus lineal + //! to number of objects with the given key. + //! + //! Throws: Nothing. + template + size_type count_dont_splay(const KeyType &key, KeyValueCompare comp) const + { + std::pair ret = this->equal_range_dont_splay(key, comp); + return std::distance(ret.first, ret.second); + } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: Nothing. + iterator lower_bound(const_reference value) + { return this->lower_bound(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator lower_bound_dont_splay(const_reference value) const + { return this->lower_bound_dont_splay(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + iterator lower_bound(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return iterator(node_algorithms::lower_bound + (const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Returns a const iterator to the first element whose + //! key is not less than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator lower_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return const_iterator(node_algorithms::lower_bound + (const_node_ptr(&priv_header()), key, key_node_comp, false), this); + } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: Nothing. + iterator upper_bound(const_reference value) + { return this->upper_bound(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k according to comp or end() if that element + //! does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: Nothing. + template + iterator upper_bound(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return iterator(node_algorithms::upper_bound + (const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator upper_bound_dont_splay(const_reference value) const + { return this->upper_bound_dont_splay(value, priv_comp()); } + + //! Effects: Returns an iterator to the first element whose + //! key is greater than k according to comp or end() if that element + //! does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator upper_bound_dont_splay(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return const_iterator(node_algorithms::upper_bound_dont_splay + (const_node_ptr(&priv_header()), key, key_node_comp, false), this); + } + + //! Effects: Finds an iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: Nothing. + iterator find(const_reference value) + { return this->find(value, priv_comp()); } + + //! Effects: Finds an iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: Nothing. + template + iterator find(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return iterator + (node_algorithms::find(const_node_ptr(&priv_header()), key, key_node_comp), this); + } + + //! Effects: Finds a const_iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + const_iterator find_dont_splay(const_reference value) const + { return this->find_dont_splay(value, priv_comp()); } + + //! Effects: Finds a const_iterator to the first element whose key is + //! k or end() if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + const_iterator find_dont_splay(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + return const_iterator + (node_algorithms::find(const_node_ptr(&priv_header()), key, key_node_comp, false), this); + } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: Nothing. + std::pair equal_range(const_reference value) + { return this->equal_range(value, priv_comp()); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: Nothing. + template + std::pair equal_range(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + std::pair ret + (node_algorithms::equal_range(const_node_ptr(&priv_header()), key, key_node_comp)); + return std::pair(iterator(ret.first, this), iterator(ret.second, this)); + } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + std::pair + equal_range_dont_splay(const_reference value) const + { return this->equal_range_dont_splay(value, priv_comp()); } + + //! Effects: Finds a range containing all elements whose key is k or + //! an empty range that indicates the position where those elements would be + //! if they there is no elements with key k. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + template + std::pair + equal_range_dont_splay(const KeyType &key, KeyValueCompare comp) const + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + std::pair ret + (node_algorithms::equal_range(const_node_ptr(&priv_header()), key, key_node_comp, false)); + return std::pair(const_iterator(ret.first, this), const_iterator(ret.second, this)); + } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. + template + void clone_from(const splaytree_impl &src, Cloner cloner, Disposer disposer) + { + this->clear_and_dispose(disposer); + if(!src.empty()){ + node_algorithms::clone + (const_node_ptr(&src.priv_header()) + ,node_ptr(&this->priv_header()) + ,detail::node_cloner(cloner, this) + ,detail::node_disposer(disposer, this)); + this->priv_size_traits().set_size(src.priv_size_traits().get_size()); + } + } + + //! Effects: Unlinks the leftmost node from the tree. + //! + //! Complexity: Average complexity is constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function breaks the tree and the tree can + //! only be used for more unlink_leftmost_without_rebalance calls. + //! This function is normally used to achieve a step by step + //! controlled destruction of the tree. + pointer unlink_leftmost_without_rebalance() + { + node_ptr to_be_disposed(node_algorithms::unlink_leftmost_without_rebalance + (node_ptr(&priv_header()))); + if(!to_be_disposed) + return 0; + this->priv_size_traits().decrement(); + if(safemode_or_autounlink)//If this is commented does not work with normal_link + node_algorithms::init(to_be_disposed); + return get_real_value_traits().to_value_ptr(to_be_disposed); + } + + //! Requires: i must be a valid iterator of *this. + //! + //! Effects: Rearranges the splay set so that the element pointed by i + //! is placed as the root of the tree, improving future searches of this value. + //! + //! Complexity: Amortized logarithmic. + //! + //! Throws: Nothing. + void splay_up(iterator i) + { return node_algorithms::splay_up(i.pointed_node(), &priv_header()); } + + //! Effects: Rearranges the splay set so that if *this stores an element + //! with a key equivalent to value the element is placed as the root of the + //! tree. If the element is not present returns the last node compared with the key. + //! If the tree is empty, end() is returned. + //! + //! Complexity: Amortized logarithmic. + //! + //! Returns: An iterator to the new root of the tree, end() if the tree is empty. + //! + //! Throws: If the comparison functor throws. + template + iterator splay_down(const KeyType &key, KeyValueCompare comp) + { + detail::key_nodeptr_comp + key_node_comp(comp, this); + node_ptr r = node_algorithms::splay_down(&priv_header(), key, key_node_comp); + return iterator(r, this); + } + + //! Effects: Rearranges the splay set so that if *this stores an element + //! with a key equivalent to value the element is placed as the root of the + //! tree. + //! + //! Complexity: Amortized logarithmic. + //! + //! Returns: An iterator to the new root of the tree, end() if the tree is empty. + //! + //! Throws: If the predicate throws. + iterator splay_down(const value_type &value) + { return this->splay_down(value, priv_comp()); } + + //! Requires: replace_this must be a valid iterator of *this + //! and with_this must not be inserted in any tree. + //! + //! Effects: Replaces replace_this in its position in the + //! tree with with_this. The tree does not need to be rebalanced. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! with_this is not equivalent to *replace_this according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + void replace_node(iterator replace_this, reference with_this) + { + node_algorithms::replace_node( get_real_value_traits().to_node_ptr(*replace_this) + , node_ptr(&priv_header()) + , get_real_value_traits().to_node_ptr(with_this)); + } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static iterator s_iterator_to(reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + return iterator (value_traits::to_node_ptr(value), 0); + } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_iterator s_iterator_to(const_reference value) + { + BOOST_STATIC_ASSERT((!stateful_value_traits)); + return const_iterator (value_traits::to_node_ptr(const_cast (value)), 0); + } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator i belonging to the set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator iterator_to(reference value) + { return iterator (value_traits::to_node_ptr(value), this); } + + //! Requires: value must be an lvalue and shall be in a set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator i belonging to the + //! set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator iterator_to(const_reference value) const + { return const_iterator (value_traits::to_node_ptr(const_cast (value)), this); } + + //! Requires: value shall not be in a tree. + //! + //! Effects: init_node puts the hook of a value in a well-known default + //! state. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This function puts the hook in the well-known default state + //! used by auto_unlink and safe hooks. + static void init_node(reference value) + { node_algorithms::init(value_traits::to_node_ptr(value)); } + + //! Effects: Rebalances the tree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear. + void rebalance() + { node_algorithms::rebalance(node_ptr(&priv_header())); } + + //! Requires: old_root is a node of a tree. + //! + //! Effects: Rebalances the subtree rooted at old_root. + //! + //! Returns: The new root of the subtree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the elements in the subtree. + iterator rebalance_subtree(iterator root) + { return iterator(node_algorithms::rebalance_subtree(root.pointed_node()), this); } + +/* + //! Effects: removes x from a tree of the appropriate type. It has no effect, + //! if x is not in such a tree. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant time. + //! + //! Note: This static function is only usable with the "safe mode" + //! hook and non-constant time size lists. Otherwise, the user must use + //! the non-static "erase(reference )" member. If the user calls + //! this function with a non "safe mode" or constant time size list + //! a compilation error will be issued. + template + static void remove_node(T& value) + { + //This function is only usable for safe mode hooks and non-constant + //time lists. + //BOOST_STATIC_ASSERT((!(safemode_or_autounlink && constant_time_size))); + BOOST_STATIC_ASSERT((!constant_time_size)); + BOOST_STATIC_ASSERT((boost::is_convertible::value)); + node_ptr to_remove(value_traits::to_node_ptr(value)); + node_algorithms::unlink_and_rebalance(to_remove); + if(safemode_or_autounlink) + node_algorithms::init(to_remove); + } +*/ + + /// @cond + private: + template + iterator private_erase(iterator b, iterator e, size_type &n, Disposer disposer) + { + for(n = 0; b != e; ++n) + this->erase_and_dispose(b++, disposer); + return b; + } + + iterator private_erase(iterator b, iterator e, size_type &n) + { + for(n = 0; b != e; ++n) + this->erase(b++); + return b; + } + /// @endcond + + private: + static splaytree_impl &priv_container_from_end_iterator(const const_iterator &end_iterator) + { + header_plus_size *r = detail::parent_from_member + ( detail::get_pointer(end_iterator.pointed_node()), &header_plus_size::header_); + node_plus_pred_t *n = detail::parent_from_member + (r, &node_plus_pred_t::header_plus_size_); + data_t *d = detail::parent_from_member(n, &data_t::node_plus_pred_); + splaytree_impl *rb = detail::parent_from_member(d, &splaytree_impl::data_); + return *rb; + } + + static splaytree_impl &priv_container_from_iterator(const const_iterator &it) + { return priv_container_from_end_iterator(it.end_iterator_from_it()); } +}; + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator< +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const splaytree_impl &x, const splaytree_impl &y) +#else +(const splaytree_impl &x, const splaytree_impl &y) +#endif +{ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +bool operator== +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const splaytree_impl &x, const splaytree_impl &y) +#else +(const splaytree_impl &x, const splaytree_impl &y) +#endif +{ + typedef splaytree_impl tree_type; + typedef typename tree_type::const_iterator const_iterator; + + if(tree_type::constant_time_size && x.size() != y.size()){ + return false; + } + const_iterator end1 = x.end(); + const_iterator i1 = x.begin(); + const_iterator i2 = y.begin(); + if(tree_type::constant_time_size){ + while (i1 != end1 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1; + } + else{ + const_iterator end2 = y.end(); + while (i1 != end1 && i2 != end2 && *i1 == *i2) { + ++i1; + ++i2; + } + return i1 == end1 && i2 == end2; + } +} + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator!= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const splaytree_impl &x, const splaytree_impl &y) +#else +(const splaytree_impl &x, const splaytree_impl &y) +#endif +{ return !(x == y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator> +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const splaytree_impl &x, const splaytree_impl &y) +#else +(const splaytree_impl &x, const splaytree_impl &y) +#endif +{ return y < x; } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator<= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const splaytree_impl &x, const splaytree_impl &y) +#else +(const splaytree_impl &x, const splaytree_impl &y) +#endif +{ return !(y < x); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline bool operator>= +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(const splaytree_impl &x, const splaytree_impl &y) +#else +(const splaytree_impl &x, const splaytree_impl &y) +#endif +{ return !(x < y); } + +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +inline void swap +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +(splaytree_impl &x, splaytree_impl &y) +#else +(splaytree_impl &x, splaytree_impl &y) +#endif +{ x.swap(y); } + +/// @cond +template +struct make_splaytree_opt +{ + typedef typename pack_options + < splay_set_defaults, O1, O2, O3, O4>::type packed_options; + typedef typename detail::get_value_traits + ::type value_traits; + + typedef splaysetopt + < value_traits + , typename packed_options::compare + , typename packed_options::size_type + , packed_options::constant_time_size + > type; +}; +/// @endcond + +//! Helper metafunction to define a \c splaytree that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_splaytree +{ + /// @cond + typedef splaytree_impl + < typename make_splaytree_opt::type + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class splaytree + : public make_splaytree::type +{ + typedef typename make_splaytree + ::type Base; + + public: + typedef typename Base::value_compare value_compare; + typedef typename Base::value_traits value_traits; + typedef typename Base::real_value_traits real_value_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + splaytree( const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(cmp, v_traits) + {} + + template + splaytree( bool unique, Iterator b, Iterator e + , const value_compare &cmp = value_compare() + , const value_traits &v_traits = value_traits()) + : Base(unique, b, e, cmp, v_traits) + {} + + static splaytree &container_from_end_iterator(iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } + + static const splaytree &container_from_end_iterator(const_iterator end_iterator) + { return static_cast(Base::container_from_end_iterator(end_iterator)); } +}; + +#endif + + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_SPLAYTREE_HPP diff --git a/win32/include/boost/intrusive/splaytree_algorithms.hpp b/win32/include/boost/intrusive/splaytree_algorithms.hpp new file mode 100755 index 000000000..6b738a7f4 --- /dev/null +++ b/win32/include/boost/intrusive/splaytree_algorithms.hpp @@ -0,0 +1,893 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2007. +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +// The implementation of splay trees is based on the article and code published +// in C++ Users Journal "Implementing Splay Trees in C++" (September 1, 2005). +// +// The code has been modified and (supposely) improved by Ion Gaztanaga. +// Here is the header of the file used as base code: +// +// splay_tree.h -- implementation of a STL complatible splay tree. +// +// Copyright (c) 2004 Ralf Mattethat +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// Please send questions, comments, complaints, performance data, etc to +// ralf.mattethat@teknologisk.dk +// +// Requirements for element type +// * must be copy-constructible +// * destructor must not throw exception +// +// Methods marked with note A only throws an exception if the evaluation of the +// predicate throws an exception. If an exception is thrown the call has no +// effect on the containers state +// +// Methods marked with note B only throws an exception if the coppy constructor +// or assignment operator of the predicate throws an exception. If an exception +// is thrown the call has no effect on the containers state +// +// iterators are only invalidated, if the element pointed to by the iterator +// is deleted. The same goes for element references +// + +#ifndef BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP +#define BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond +namespace detail { + +template +struct splaydown_rollback +{ + typedef typename NodeTraits::node_ptr node_ptr; + splaydown_rollback( const node_ptr *pcur_subtree, node_ptr header + , node_ptr leftmost , node_ptr rightmost) + : pcur_subtree_(pcur_subtree) , header_(header) + , leftmost_(leftmost) , rightmost_(rightmost) + {} + + void release() + { pcur_subtree_ = 0; } + + ~splaydown_rollback() + { + if(pcur_subtree_){ + //Exception can only be thrown by comp, but + //tree invariants still hold. *pcur_subtree is the current root + //so link it to the header. + NodeTraits::set_parent(*pcur_subtree_, header_); + NodeTraits::set_parent(header_, *pcur_subtree_); + //Recover leftmost/rightmost pointers + NodeTraits::set_left (header_, leftmost_); + NodeTraits::set_right(header_, rightmost_); + } + } + const node_ptr *pcur_subtree_; + node_ptr header_, leftmost_, rightmost_; +}; + +} //namespace detail { +/// @endcond + +//! A splay tree is an implementation of a binary search tree. The tree is +//! self balancing using the splay algorithm as described in +//! +//! "Self-Adjusting Binary Search Trees +//! by Daniel Dominic Sleator and Robert Endre Tarjan +//! AT&T Bell Laboratories, Murray Hill, NJ +//! Journal of the ACM, Vol 32, no 3, July 1985, pp 652-686 + +//! splaytree_algorithms is configured with a NodeTraits class, which encapsulates the +//! information about the node to be manipulated. NodeTraits must support the +//! following interface: +//! +//! Typedefs: +//! +//! node: The type of the node that forms the circular list +//! +//! node_ptr: A pointer to a node +//! +//! const_node_ptr: A pointer to a const node +//! +//! Static functions: +//! +//! static node_ptr get_parent(const_node_ptr n); +//! +//! static void set_parent(node_ptr n, node_ptr parent); +//! +//! static node_ptr get_left(const_node_ptr n); +//! +//! static void set_left(node_ptr n, node_ptr left); +//! +//! static node_ptr get_right(const_node_ptr n); +//! +//! static void set_right(node_ptr n, node_ptr right); +template +class splaytree_algorithms +{ + /// @cond + private: + typedef detail::tree_algorithms tree_algorithms; + /// @endcond + + public: + typedef typename NodeTraits::node node; + typedef NodeTraits node_traits; + typedef typename NodeTraits::node_ptr node_ptr; + typedef typename NodeTraits::const_node_ptr const_node_ptr; + + //! This type is the information that will be + //! filled by insert_unique_check + typedef typename tree_algorithms::insert_commit_data insert_commit_data; + + /// @cond + private: + static node_ptr uncast(const_node_ptr ptr) + { + return node_ptr(const_cast(::boost::intrusive::detail::get_pointer(ptr))); + } + /// @endcond + + public: + static node_ptr begin_node(const_node_ptr header) + { return tree_algorithms::begin_node(header); } + + static node_ptr end_node(const_node_ptr header) + { return tree_algorithms::end_node(header); } + + //! Requires: node is a node of the tree or an node initialized + //! by init(...). + //! + //! Effects: Returns true if the node is initialized by init(). + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + static bool unique(const_node_ptr node) + { return tree_algorithms::unique(node); } + + static void unlink(node_ptr node) + { tree_algorithms::unlink(node); } + + //! Requires: node1 and node2 can't be header nodes + //! of two trees. + //! + //! Effects: Swaps two nodes. After the function node1 will be inserted + //! in the position node2 before the function. node2 will be inserted in the + //! position node1 had before the function. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! node1 and node2 are not equivalent according to the ordering rules. + //! + //!Experimental function + static void swap_nodes(node_ptr node1, node_ptr node2) + { + if(node1 == node2) + return; + + node_ptr header1(tree_algorithms::get_header(node1)), header2(tree_algorithms::get_header(node2)); + swap_nodes(node1, header1, node2, header2); + } + + //! Requires: node1 and node2 can't be header nodes + //! of two trees with header header1 and header2. + //! + //! Effects: Swaps two nodes. After the function node1 will be inserted + //! in the position node2 before the function. node2 will be inserted in the + //! position node1 had before the function. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! node1 and node2 are not equivalent according to the ordering rules. + //! + //!Experimental function + static void swap_nodes(node_ptr node1, node_ptr header1, node_ptr node2, node_ptr header2) + { tree_algorithms::swap_nodes(node1, header1, node2, header2); } + + //! Requires: node_to_be_replaced must be inserted in a tree + //! and new_node must not be inserted in a tree. + //! + //! Effects: Replaces node_to_be_replaced in its position in the + //! tree with new_node. The tree does not need to be rebalanced + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! new_node is not equivalent to node_to_be_replaced according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing and comparison is needed. + //! + //!Experimental function + static void replace_node(node_ptr node_to_be_replaced, node_ptr new_node) + { + if(node_to_be_replaced == new_node) + return; + replace_node(node_to_be_replaced, tree_algorithms::get_header(node_to_be_replaced), new_node); + } + + //! Requires: node_to_be_replaced must be inserted in a tree + //! with header "header" and new_node must not be inserted in a tree. + //! + //! Effects: Replaces node_to_be_replaced in its position in the + //! tree with new_node. The tree does not need to be rebalanced + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This function will break container ordering invariants if + //! new_node is not equivalent to node_to_be_replaced according to the + //! ordering rules. This function is faster than erasing and inserting + //! the node, since no rebalancing or comparison is needed. + //! + //!Experimental function + static void replace_node(node_ptr node_to_be_replaced, node_ptr header, node_ptr new_node) + { tree_algorithms::replace_node(node_to_be_replaced, header, new_node); } + + //! Requires: p is a node from the tree except the header. + //! + //! Effects: Returns the next node of the tree. + //! + //! Complexity: Average constant time. + //! + //! Throws: Nothing. + static node_ptr next_node(node_ptr p) + { return tree_algorithms::next_node(p); } + + //! Requires: p is a node from the tree except the leftmost node. + //! + //! Effects: Returns the previous node of the tree. + //! + //! Complexity: Average constant time. + //! + //! Throws: Nothing. + static node_ptr prev_node(node_ptr p) + { return tree_algorithms::prev_node(p); } + + //! Requires: node must not be part of any tree. + //! + //! Effects: After the function unique(node) == true. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Nodes: If node is inserted in a tree, this function corrupts the tree. + static void init(node_ptr node) + { tree_algorithms::init(node); } + + //! Requires: node must not be part of any tree. + //! + //! Effects: Initializes the header to represent an empty tree. + //! unique(header) == true. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Nodes: If node is inserted in a tree, this function corrupts the tree. + static void init_header(node_ptr header) + { tree_algorithms::init_header(header); } + + //! Requires: "disposer" must be an object function + //! taking a node_ptr parameter and shouldn't throw. + //! + //! Effects: Empties the target tree calling + //! void disposer::operator()(node_ptr) for every node of the tree + //! except the header. + //! + //! Complexity: Linear to the number of element of the source tree plus the. + //! number of elements of tree target tree when calling this function. + //! + //! Throws: If cloner functor throws. If this happens target nodes are disposed. + template + static void clear_and_dispose(node_ptr header, Disposer disposer) + { tree_algorithms::clear_and_dispose(header, disposer); } + + //! Requires: node is a node of the tree but it's not the header. + //! + //! Effects: Returns the number of nodes of the subtree. + //! + //! Complexity: Linear time. + //! + //! Throws: Nothing. + static std::size_t count(const_node_ptr node) + { return tree_algorithms::count(node); } + + //! Requires: header is the header node of the tree. + //! + //! Effects: Returns the number of nodes above the header. + //! + //! Complexity: Linear time. + //! + //! Throws: Nothing. + static std::size_t size(const_node_ptr header) + { return tree_algorithms::size(header); } + + //! Requires: header1 and header2 must be the header nodes + //! of two trees. + //! + //! Effects: Swaps two trees. After the function header1 will contain + //! links to the second tree and header2 will have links to the first tree. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + static void swap_tree(node_ptr header1, node_ptr header2) + { return tree_algorithms::swap_tree(header1, header2); } + + //! Requires: "header" must be the header node of a tree. + //! "commit_data" must have been obtained from a previous call to + //! "insert_unique_check". No objects should have been inserted or erased + //! from the set between the "insert_unique_check" that filled "commit_data" + //! and the call to "insert_commit". + //! + //! + //! Effects: Inserts new_node in the set using the information obtained + //! from the "commit_data" that a previous "insert_check" filled. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function has only sense if a "insert_unique_check" has been + //! previously executed to fill "commit_data". No value should be inserted or + //! erased between the "insert_check" and "insert_commit" calls. + static void insert_unique_commit + (node_ptr header, node_ptr new_value, const insert_commit_data &commit_data) + { tree_algorithms::insert_unique_commit(header, new_value, commit_data); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares KeyType with a node_ptr. + //! + //! Effects: Checks if there is an equivalent node to "key" in the + //! tree according to "comp" and obtains the needed information to realize + //! a constant-time node insertion if there is no equivalent node. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing a node_ptr to the already present node + //! and false. If there is not equivalent key can be inserted returns true + //! in the returned pair's boolean and fills "commit_data" that is meant to + //! be used with the "insert_commit" function to achieve a constant-time + //! insertion function. + //! + //! Complexity: Average complexity is at most logarithmic. + //! + //! Throws: If "comp" throws. + //! + //! Notes: This function is used to improve performance when constructing + //! a node is expensive and the user does not want to have two equivalent nodes + //! in the tree: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the order is much cheaper to construct + //! than the node and this function offers the possibility to use that part + //! to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the node and use + //! "insert_commit" to insert the node in constant-time. This gives a total + //! logarithmic complexity to the insertion: check(O(log(N)) + commit(O(1)). + //! + //! "commit_data" remains valid for a subsequent "insert_unique_commit" only + //! if no more objects are inserted or erased from the set. + template + static std::pair insert_unique_check + (node_ptr header, const KeyType &key + ,KeyNodePtrCompare comp, insert_commit_data &commit_data) + { + splay_down(header, key, comp); + return tree_algorithms::insert_unique_check(header, key, comp, commit_data); + } + + template + static std::pair insert_unique_check + (node_ptr header, node_ptr hint, const KeyType &key + ,KeyNodePtrCompare comp, insert_commit_data &commit_data) + { + splay_down(header, key, comp); + return tree_algorithms::insert_unique_check(header, hint, key, comp, commit_data); + } + + static bool is_header(const_node_ptr p) + { return tree_algorithms::is_header(p); } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the element that is equivalent to + //! "key" according to "comp" or "header" if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr find + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + { + if(splay) + splay_down(uncast(header), key, comp); + node_ptr end = uncast(header); + node_ptr y = lower_bound(header, key, comp, false); + node_ptr r = (y == end || comp(key, y)) ? end : y; + return r; + } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an a pair of node_ptr delimiting a range containing + //! all elements that are equivalent to "key" according to "comp" or an + //! empty range that indicates the position where those elements would be + //! if they there are no equivalent elements. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static std::pair equal_range + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + { + //if(splay) + //splay_down(uncast(header), key, comp); + std::pair ret = + tree_algorithms::equal_range(header, key, comp); + + if(splay) + splay_up(ret.first, uncast(header)); + return ret; + } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the first element that is + //! not less than "key" according to "comp" or "header" if that element does + //! not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr lower_bound + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + { + //if(splay) + //splay_down(uncast(header), key, comp); + node_ptr y = tree_algorithms::lower_bound(header, key, comp); + if(splay) + splay_up(y, uncast(header)); + return y; + } + + //! Requires: "header" must be the header node of a tree. + //! KeyNodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. KeyNodePtrCompare can compare KeyType with tree's node_ptrs. + //! + //! Effects: Returns an node_ptr to the first element that is greater + //! than "key" according to "comp" or "header" if that element does not exist. + //! + //! Complexity: Logarithmic. + //! + //! Throws: If "comp" throws. + template + static node_ptr upper_bound + (const_node_ptr header, const KeyType &key, KeyNodePtrCompare comp, bool splay = true) + { + //if(splay) + //splay_down(uncast(header), key, comp); + node_ptr y = tree_algorithms::upper_bound(header, key, comp); + if(splay) + splay_up(y, uncast(header)); + return y; + } + + //! Requires: "header" must be the header node of a tree. + //! NodePtrCompare is a function object that induces a strict weak + //! ordering compatible with the strict weak ordering used to create the + //! the tree. NodePtrCompare compares two node_ptrs. "hint" is node from + //! the "header"'s tree. + //! + //! Effects: Inserts new_node into the tree, using "hint" as a hint to + //! where it will be inserted. If "hint" is the upper_bound + //! the insertion takes constant time (two comparisons in the worst case). + //! + //! Complexity: Logarithmic in general, but it is amortized + //! constant time if new_node is inserted immediately before "hint". + //! + //! Throws: If "comp" throws. + template + static node_ptr insert_equal + (node_ptr header, node_ptr hint, node_ptr new_node, NodePtrCompare comp) + { + splay_down(header, new_node, comp); + return tree_algorithms::insert_equal(header, hint, new_node, comp); + } + + template + static node_ptr insert_equal_upper_bound + (node_ptr header, node_ptr new_node, NodePtrCompare comp) + { + splay_down(header, new_node, comp); + return tree_algorithms::insert_equal_upper_bound(header, new_node, comp); + } + + template + static node_ptr insert_equal_lower_bound + (node_ptr header, node_ptr new_node, NodePtrCompare comp) + { + splay_down(header, new_node, comp); + return tree_algorithms::insert_equal_lower_bound(header, new_node, comp); + } + + //! Requires: "cloner" must be a function + //! object taking a node_ptr and returning a new cloned node of it. "disposer" must + //! take a node_ptr and shouldn't throw. + //! + //! Effects: First empties target tree calling + //! void disposer::operator()(node_ptr) for every node of the tree + //! except the header. + //! + //! Then, duplicates the entire tree pointed by "source_header" cloning each + //! source node with node_ptr Cloner::operator()(node_ptr) to obtain + //! the nodes of the target tree. If "cloner" throws, the cloned target nodes + //! are disposed using void disposer(node_ptr). + //! + //! Complexity: Linear to the number of element of the source tree plus the. + //! number of elements of tree target tree when calling this function. + //! + //! Throws: If cloner functor throws. If this happens target nodes are disposed. + template + static void clone + (const_node_ptr source_header, node_ptr target_header, Cloner cloner, Disposer disposer) + { tree_algorithms::clone(source_header, target_header, cloner, disposer); } + + // delete node | complexity : constant | exception : nothrow + static void erase(node_ptr header, node_ptr z, bool splay = true) + { +// node_base* n = t->right; +// if( t->left != 0 ){ +// node_base* l = t->previous(); +// splay_up( l , t ); +// n = t->left; +// n->right = t->right; +// if( n->right != 0 ) +// n->right->parent = n; +// } +// +// if( n != 0 ) +// n->parent = t->parent; +// +// if( t->parent->left == t ) +// t->parent->left = n; +// else // must be ( t->parent->right == t ) +// t->parent->right = n; +// +// if( data_->parent == t ) +// data_->parent = find_leftmost(); + //posibility 1 + if(splay && NodeTraits::get_left(z) != 0 ){ + node_ptr l = prev_node(z); + splay_up(l, header); + } + /* + //possibility 2 + if(splay && NodeTraits::get_left(z) != 0 ){ + node_ptr l = NodeTraits::get_left(z); + splay_up(l, header); + }*//* + if(splay && NodeTraits::get_left(z) != 0 ){ + node_ptr l = prev_node(z); + splay_up_impl(l, z); + }*/ + /* + //possibility 4 + if(splay){ + splay_up(z, header); + }*/ + + //if(splay) + //splay_up(z, header); + tree_algorithms::erase(header, z); + } + + // bottom-up splay, use data_ as parent for n | complexity : logarithmic | exception : nothrow + static void splay_up(node_ptr n, node_ptr header) + { + if(n == header){ // do a splay for the right most node instead + // this is to boost performance of equal_range/count on equivalent containers in the case + // where there are many equal elements at the end + n = NodeTraits::get_right(header); + } + + node_ptr t = header; + + if( n == t ) return; + + for( ;; ){ + node_ptr p = NodeTraits::get_parent(n); + node_ptr g = NodeTraits::get_parent(p); + + if( p == t ) break; + + if( g == t ){ + // zig + rotate(n); + } + else if ((NodeTraits::get_left(p) == n && NodeTraits::get_left(g) == p) || + (NodeTraits::get_right(p) == n && NodeTraits::get_right(g) == p) ){ + // zig-zig + rotate(p); + rotate(n); + } + else{ + // zig-zag + rotate(n); + rotate(n); + } + } + } + + // top-down splay | complexity : logarithmic | exception : strong, note A + template + static node_ptr splay_down(node_ptr header, const KeyType &key, KeyNodePtrCompare comp) + { + if(!NodeTraits::get_parent(header)) + return header; + //Most splay tree implementations use a dummy/null node to implement. + //this function. This has some problems for a generic library like Intrusive: + // + // * The node might not have a default constructor. + // * The default constructor could throw. + // + //We already have a header node. Leftmost and rightmost nodes of the tree + //are not changed when splaying (because the invariants of the tree don't + //change) We can back up them, use the header as the null node and + //reassign old values after the function has been completed. + node_ptr t = NodeTraits::get_parent(header); + //Check if tree has a single node + if(!NodeTraits::get_left(t) && !NodeTraits::get_right(t)) + return t; + //Backup leftmost/rightmost + node_ptr leftmost = NodeTraits::get_left(header); + node_ptr rightmost = NodeTraits::get_right(header); + + { + detail::splaydown_rollback rollback(&t, header, leftmost, rightmost); + node_ptr null = header; + node_ptr l = null; + node_ptr r = null; + + for( ;; ){ + if(comp(key, t)){ + if(NodeTraits::get_left(t) == 0 ) + break; + if(comp(key, NodeTraits::get_left(t))){ + t = tree_algorithms::rotate_right(t); + + if(NodeTraits::get_left(t) == 0) + break; + link_right(t, r); + } + else if(comp(NodeTraits::get_left(t), key)){ + link_right(t, r); + + if(NodeTraits::get_right(t) == 0 ) + break; + link_left(t, l); + } + else{ + link_right(t, r); + } + } + else if(comp(t, key)){ + if(NodeTraits::get_right(t) == 0 ) + break; + + if(comp(NodeTraits::get_right(t), key)){ + t = tree_algorithms::rotate_left( t ); + + if(NodeTraits::get_right(t) == 0 ) + break; + link_left(t, l); + } + else if(comp(key, NodeTraits::get_right(t))){ + link_left(t, l); + + if(NodeTraits::get_left(t) == 0) + break; + + link_right(t, r); + } + else{ + link_left(t, l); + } + } + else{ + break; + } + } + + assemble(t, l, r, null); + rollback.release(); + } + + //t is the current root + NodeTraits::set_parent(header, t); + NodeTraits::set_parent(t, header); + //Recover leftmost/rightmost pointers + NodeTraits::set_left (header, leftmost); + NodeTraits::set_right(header, rightmost); + return t; + } + + //! Requires: header must be the header of a tree. + //! + //! Effects: Rebalances the tree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear. + static void rebalance(node_ptr header) + { tree_algorithms::rebalance(header); } + + //! Requires: old_root is a node of a tree. + //! + //! Effects: Rebalances the subtree rooted at old_root. + //! + //! Returns: The new root of the subtree. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear. + static node_ptr rebalance_subtree(node_ptr old_root) + { return tree_algorithms::rebalance_subtree(old_root); } + + + //! Requires: "n" must be a node inserted in a tree. + //! + //! Effects: Returns a pointer to the header node of the tree. + //! + //! Complexity: Logarithmic. + //! + //! Throws: Nothing. + static node_ptr get_header(node_ptr n) + { return tree_algorithms::get_header(n); } + + private: + + /// @cond + + // assemble the three sub-trees into new tree pointed to by t | complexity : constant | exception : nothrow + static void assemble( node_ptr t, node_ptr l, node_ptr r, const_node_ptr null_node ) + { + NodeTraits::set_right(l, NodeTraits::get_left(t)); + NodeTraits::set_left(r, NodeTraits::get_right(t)); + + if(NodeTraits::get_right(l) != 0){ + NodeTraits::set_parent(NodeTraits::get_right(l), l); + } + + if(NodeTraits::get_left(r) != 0){ + NodeTraits::set_parent(NodeTraits::get_left(r), r); + } + + NodeTraits::set_left (t, NodeTraits::get_right(null_node)); + NodeTraits::set_right(t, NodeTraits::get_left(null_node)); + + if( NodeTraits::get_left(t) != 0 ){ + NodeTraits::set_parent(NodeTraits::get_left(t), t); + } + + if( NodeTraits::get_right(t) ){ + NodeTraits::set_parent(NodeTraits::get_right(t), t); + } + } + + // break link to left child node and attach it to left tree pointed to by l | complexity : constant | exception : nothrow + static void link_left(node_ptr& t, node_ptr& l) + { + NodeTraits::set_right(l, t); + NodeTraits::set_parent(t, l); + l = t; + t = NodeTraits::get_right(t); + } + + // break link to right child node and attach it to right tree pointed to by r | complexity : constant | exception : nothrow + static void link_right(node_ptr& t, node_ptr& r) + { + NodeTraits::set_left(r, t); + NodeTraits::set_parent(t, r); + r = t; + t = NodeTraits::get_left(t); + } + + // rotate n with its parent | complexity : constant | exception : nothrow + static void rotate(node_ptr n) + { + node_ptr p = NodeTraits::get_parent(n); + node_ptr g = NodeTraits::get_parent(p); + //Test if g is header before breaking tree + //invariants that would make is_header invalid + bool g_is_header = is_header(g); + + if(NodeTraits::get_left(p) == n){ + NodeTraits::set_left(p, NodeTraits::get_right(n)); + if(NodeTraits::get_left(p) != 0) + NodeTraits::set_parent(NodeTraits::get_left(p), p); + NodeTraits::set_right(n, p); + } + else{ // must be ( p->right == n ) + NodeTraits::set_right(p, NodeTraits::get_left(n)); + if(NodeTraits::get_right(p) != 0) + NodeTraits::set_parent(NodeTraits::get_right(p), p); + NodeTraits::set_left(n, p); + } + + NodeTraits::set_parent(p, n); + NodeTraits::set_parent(n, g); + + if(g_is_header){ + if(NodeTraits::get_parent(g) == p) + NodeTraits::set_parent(g, n); + else{//must be ( g->right == p ) + assert(0); + NodeTraits::set_right(g, n); + } + } + else{ + if(NodeTraits::get_left(g) == p) + NodeTraits::set_left(g, n); + else //must be ( g->right == p ) + NodeTraits::set_right(g, n); + } + } + + /// @endcond +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_SPLAYTREE_ALGORITHMS_HPP diff --git a/win32/include/boost/intrusive/trivial_value_traits.hpp b/win32/include/boost/intrusive/trivial_value_traits.hpp new file mode 100755 index 000000000..982213e67 --- /dev/null +++ b/win32/include/boost/intrusive/trivial_value_traits.hpp @@ -0,0 +1,43 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP +#define BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP + +#include + +namespace boost { +namespace intrusive { + +//!This value traits template is used to create value traits +//!from user defined node traits where value_traits::value_type and +//!node_traits::node should be equal +template +struct trivial_value_traits +{ + typedef NodeTraits node_traits; + typedef typename node_traits::node_ptr node_ptr; + typedef typename node_traits::const_node_ptr const_node_ptr; + typedef typename node_traits::node value_type; + typedef node_ptr pointer; + typedef const_node_ptr const_pointer; + static const link_mode_type link_mode = LinkMode; + static node_ptr to_node_ptr (value_type &value) { return node_ptr(&value); } + static const_node_ptr to_node_ptr (const value_type &value) { return const_node_ptr(&value); } + static pointer to_value_ptr(node_ptr n) { return pointer(n); } + static const_pointer to_value_ptr(const_node_ptr n) { return const_pointer(n); } +}; + +} //namespace intrusive +} //namespace boost + +#endif //BOOST_INTRUSIVE_TRIVIAL_VALUE_TRAITS_HPP diff --git a/win32/include/boost/intrusive/unordered_set.hpp b/win32/include/boost/intrusive/unordered_set.hpp new file mode 100755 index 000000000..01c278049 --- /dev/null +++ b/win32/include/boost/intrusive/unordered_set.hpp @@ -0,0 +1,1957 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTRUSIVE_UNORDERED_SET_HPP +#define BOOST_INTRUSIVE_UNORDERED_SET_HPP + +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +//! The class template unordered_set is an intrusive container, that mimics most of +//! the interface of std::tr1::unordered_set as described in the C++ TR1. +//! +//! unordered_set is a semi-intrusive container: each object to be stored in the +//! container must contain a proper hook, but the container also needs +//! additional auxiliary memory to work: unordered_set needs a pointer to an array +//! of type `bucket_type` to be passed in the constructor. This bucket array must +//! have at least the same lifetime as the container. This makes the use of +//! unordered_set more complicated than purely intrusive containers. +//! `bucket_type` is default-constructible, copyable and assignable +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<> +//! \c bucket_traits<>, power_2_buckets<> and cache_begin<>. +//! +//! unordered_set only provides forward iterators but it provides 4 iterator types: +//! iterator and const_iterator to navigate through the whole container and +//! local_iterator and const_local_iterator to navigate through the values +//! stored in a single bucket. Local iterators are faster and smaller. +//! +//! It's not recommended to use non constant-time size unordered_sets because several +//! key functions, like "empty()", become non-constant time functions. Non +//! constant-time size unordered_sets are mainly provided to support auto-unlink hooks. +//! +//! unordered_set, unlike std::unordered_set, does not make automatic rehashings nor +//! offers functions related to a load factor. Rehashing can be explicitly requested +//! and the user must provide a new bucket array that will be used from that moment. +//! +//! Since no automatic rehashing is done, iterators are never invalidated when +//! inserting or erasing elements. Iterators are only invalidated when rehasing. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class unordered_set_impl +{ + /// @cond + private: + typedef hashtable_impl table_type; + + //! This class is + //! non-copyable + unordered_set_impl (const unordered_set_impl&); + + //! This class is + //! non-assignable + unordered_set_impl &operator =(const unordered_set_impl&); + + typedef table_type implementation_defined; + /// @endcond + + public: + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::value_traits value_traits; + typedef typename implementation_defined::bucket_traits bucket_traits; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_equal key_equal; + typedef typename implementation_defined::hasher hasher; + typedef typename implementation_defined::bucket_type bucket_type; + typedef typename implementation_defined::bucket_ptr bucket_ptr; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::insert_commit_data insert_commit_data; + typedef typename implementation_defined::local_iterator local_iterator; + typedef typename implementation_defined::const_local_iterator const_local_iterator; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; + + /// @cond + private: + table_type table_; + /// @endcond + + public: + + //! Requires: buckets must not be being used by any other resource. + //! + //! Effects: Constructs an empty unordered_set_impl, storing a reference + //! to the bucket array and copies of the hasher and equal functors. + //! + //! Complexity: Constant. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor or invocation of Hash or Equal throws. + //! + //! Notes: buckets array must be disposed only after + //! *this is disposed. + unordered_set_impl( const bucket_traits &b_traits + , const hasher & hash_func = hasher() + , const key_equal &equal_func = key_equal() + , const value_traits &v_traits = value_traits()) + : table_(b_traits, hash_func, equal_func, v_traits) + {} + + //! Requires: buckets must not be being used by any other resource + //! and Dereferencing iterator must yield an lvalue of type value_type. + //! + //! Effects: Constructs an empty unordered_set and inserts elements from + //! [b, e). + //! + //! Complexity: If N is std::distance(b, e): Average case is O(N) + //! (with a good hash function and with buckets_len >= N),worst case O(N2). + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor or invocation of hasher or key_equal throws. + //! + //! Notes: buckets array must be disposed only after + //! *this is disposed. + template + unordered_set_impl( Iterator b + , Iterator e + , const bucket_traits &b_traits + , const hasher & hash_func = hasher() + , const key_equal &equal_func = key_equal() + , const value_traits &v_traits = value_traits()) + : table_(b_traits, hash_func, equal_func, v_traits) + { table_.insert_unique(b, e); } + + //! Effects: Detaches all elements from this. The objects in the unordered_set + //! are not deleted (i.e. no destructors are called). + //! + //! Complexity: Linear to the number of elements in the unordered_set, if + //! it's a safe-mode or auto-unlink value. Otherwise constant. + //! + //! Throws: Nothing. + ~unordered_set_impl() + {} + + //! Effects: Returns an iterator pointing to the beginning of the unordered_set. + //! + //! Complexity: Constant time if `cache_begin<>` is true. Amortized + //! constant time with worst case (empty unordered_set) O(this->bucket_count()) + //! + //! Throws: Nothing. + iterator begin() + { return table_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning + //! of the unordered_set. + //! + //! Complexity: Constant time if `cache_begin<>` is true. Amortized + //! constant time with worst case (empty unordered_set) O(this->bucket_count()) + //! + //! Throws: Nothing. + const_iterator begin() const + { return table_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning + //! of the unordered_set. + //! + //! Complexity: Constant time if `cache_begin<>` is true. Amortized + //! constant time with worst case (empty unordered_set) O(this->bucket_count()) + //! + //! Throws: Nothing. + const_iterator cbegin() const + { return table_.cbegin(); } + + //! Effects: Returns an iterator pointing to the end of the unordered_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return table_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the unordered_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return table_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the unordered_set. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return table_.cend(); } + + //! Effects: Returns the hasher object used by the unordered_set. + //! + //! Complexity: Constant. + //! + //! Throws: If hasher copy-constructor throws. + hasher hash_function() const + { return table_.hash_function(); } + + //! Effects: Returns the key_equal object used by the unordered_set. + //! + //! Complexity: Constant. + //! + //! Throws: If key_equal copy-constructor throws. + key_equal key_eq() const + { return table_.key_eq(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: if constant-time size and cache_last options are disabled, + //! average constant time (worst case, with empty() == true: O(this->bucket_count()). + //! Otherwise constant. + //! + //! Throws: Nothing. + bool empty() const + { return table_.empty(); } + + //! Effects: Returns the number of elements stored in the unordered_set. + //! + //! Complexity: Linear to elements contained in *this if + //! constant-time size option is enabled. Constant-time otherwise. + //! + //! Throws: Nothing. + size_type size() const + { return table_.size(); } + + //! Requires: the hasher and the equality function unqualified swap + //! call should not throw. + //! + //! Effects: Swaps the contents of two unordered_sets. + //! Swaps also the contained bucket array and equality and hasher functors. + //! + //! Complexity: Constant. + //! + //! Throws: If the swap() call for the comparison or hash functors + //! found using ADL throw. Basic guarantee. + void swap(unordered_set_impl& other) + { table_.swap(other.table_); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. Basic guarantee. + template + void clone_from(const unordered_set_impl &src, Cloner cloner, Disposer disposer) + { table_.clone_from(src.table_, cloner, disposer); } + + //! Requires: value must be an lvalue + //! + //! Effects: Tries to inserts value into the unordered_set. + //! + //! Returns: If the value + //! is not already present inserts it and returns a pair containing the + //! iterator to the new value and true. If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + std::pair insert(reference value) + { return table_.insert_unique(value); } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Equivalent to this->insert(t) for each element in [b, e). + //! + //! Complexity: Average case O(N), where N is std::distance(b, e). + //! Worst case O(N*this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert(Iterator b, Iterator e) + { table_.insert_unique(b, e); } + + //! Requires: "hasher" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hasher" hashes the given key instead of the value_type. + //! + //! "key_value_equal" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "key_value_equal" compares an arbitrary key with the contained values. + //! + //! Effects: Checks if a value can be inserted in the unordered_set, using + //! a user provided key instead of the value itself. + //! + //! Returns: If there is an equivalent value + //! returns a pair containing an iterator to the already present value + //! and false. If the value can be inserted returns true in the returned + //! pair boolean and fills "commit_data" that is meant to be used with + //! the "insert_commit" function. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If hasher or key_value_equal throw. Strong guarantee. + //! + //! Notes: This function is used to improve performance when constructing + //! a value_type is expensive: if there is an equivalent value + //! the constructed object must be discarded. Many times, the part of the + //! node that is used to impose the hash or the equality is much cheaper to + //! construct than the value_type and this function offers the possibility to + //! use that the part to check if the insertion will be successful. + //! + //! If the check is successful, the user can construct the value_type and use + //! "insert_commit" to insert the object in constant-time. + //! + //! "commit_data" remains valid for a subsequent "insert_commit" only if no more + //! objects are inserted or erased from the unordered_set. + //! + //! After a successful rehashing insert_commit_data remains valid. + template + std::pair insert_check + (const KeyType &key, KeyHasher hasher, KeyValueEqual key_value_equal, insert_commit_data &commit_data) + { return table_.insert_unique_check(key, hasher, key_value_equal, commit_data); } + + //! Requires: value must be an lvalue of type value_type. commit_data + //! must have been obtained from a previous call to "insert_check". + //! No objects should have been inserted or erased from the unordered_set between + //! the "insert_check" that filled "commit_data" and the call to "insert_commit". + //! + //! Effects: Inserts the value in the unordered_set using the information obtained + //! from the "commit_data" that a previous "insert_check" filled. + //! + //! Returns: An iterator to the newly inserted object. + //! + //! Complexity: Constant time. + //! + //! Throws: Nothing. + //! + //! Notes: This function has only sense if a "insert_check" has been + //! previously executed to fill "commit_data". No value should be inserted or + //! erased between the "insert_check" and "insert_commit" calls. + //! + //! After a successful rehashing insert_commit_data remains valid. + iterator insert_commit(reference value, const insert_commit_data &commit_data) + { return table_.insert_unique_commit(value, commit_data); } + + //! Effects: Erases the element pointed to by i. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased element. No destructors are called. + void erase(const_iterator i) + { table_.erase(i); } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Complexity: Average case O(std::distance(b, e)), + //! worst case O(this->size()). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void erase(const_iterator b, const_iterator e) + { table_.erase(b, e); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Average case O(this->count(value)). + //! Worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return table_.erase(value); } + + //! Requires: "hasher" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hasher" hashes the given key instead of the value_type. + //! + //! "key_value_equal" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "key_value_equal" compares an arbitrary key with the contained values. + //! + //! Effects: Erases all the elements that have the same hash and + //! compare equal with the given key. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Average case O(this->count(value)). + //! Worst case O(this->size()). + //! + //! Throws: If hash_func or equal_func throw. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) + { return table_.erase(key, hash_func, equal_func); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element pointed to by i. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(const_iterator i, Disposer disposer) + { return table_.erase_and_dispose(i, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average case O(std::distance(b, e)), + //! worst case O(this->size()). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) + { return table_.erase_and_dispose(b, e, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Average case O(this->count(value)). + //! Worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { return table_.erase_and_dispose(value, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "equal_func". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Average case O(this->count(value)). + //! Worst case O(this->size()). + //! + //! Throws: If hash_func or equal_func throw. Basic guarantee. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func, Disposer disposer) + { return table_.erase_and_dispose(key, hash_func, equal_func, disposer); } + + //! Effects: Erases all of the elements. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { return table_.clear(); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all of the elements. + //! + //! Complexity: Linear to the number of elements on the container. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + void clear_and_dispose(Disposer disposer) + { return table_.clear_and_dispose(disposer); } + + //! Effects: Returns the number of contained elements with the given value + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + size_type count(const_reference value) const + { return table_.find(value) != end(); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "equal_func" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "equal_func" compares an arbitrary key with the contained values. + //! + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If hash_func or equal_func throw. + template + size_type count(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const + { return table_.find(key, hash_func, equal_func) != end(); } + + //! Effects: Finds an iterator to the first element is equal to + //! "value" or end() if that element does not exist. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + iterator find(const_reference value) + { return table_.find(value); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "equal_func" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "equal_func" compares an arbitrary key with the contained values. + //! + //! Effects: Finds an iterator to the first element whose key is + //! "key" according to the given hasher and equality functor or end() if + //! that element does not exist. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If hash_func or equal_func throw. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) + { return table_.find(key, hash_func, equal_func); } + + //! Effects: Finds a const_iterator to the first element whose key is + //! "key" or end() if that element does not exist. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + const_iterator find(const_reference value) const + { return table_.find(value); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "equal_func" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "equal_func" compares an arbitrary key with the contained values. + //! + //! Effects: Finds an iterator to the first element whose key is + //! "key" according to the given hasher and equality functor or end() if + //! that element does not exist. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If hash_func or equal_func throw. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const + { return table_.find(key, hash_func, equal_func); } + + //! Effects: Returns a range containing all elements with values equivalent + //! to value. Returns std::make_pair(this->end(), this->end()) if no such + //! elements exist. + //! + //! Complexity: Average case O(this->count(value)). Worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + std::pair equal_range(const_reference value) + { return table_.equal_range(value); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "equal_func" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "equal_func" compares an arbitrary key with the contained values. + //! + //! Effects: Returns a range containing all elements with equivalent + //! keys. Returns std::make_pair(this->end(), this->end()) if no such + //! elements exist. + //! + //! Complexity: Average case O(this->count(key, hash_func, hash_func)). + //! Worst case O(this->size()). + //! + //! Throws: If hash_func or the equal_func throw. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair equal_range(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) + { return table_.equal_range(key, hash_func, equal_func); } + + //! Effects: Returns a range containing all elements with values equivalent + //! to value. Returns std::make_pair(this->end(), this->end()) if no such + //! elements exist. + //! + //! Complexity: Average case O(this->count(value)). Worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + std::pair + equal_range(const_reference value) const + { return table_.equal_range(value); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "equal_func" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "equal_func" compares an arbitrary key with the contained values. + //! + //! Effects: Returns a range containing all elements with equivalent + //! keys. Returns std::make_pair(this->end(), this->end()) if no such + //! elements exist. + //! + //! Complexity: Average case O(this->count(key, hash_func, equal_func)). + //! Worst case O(this->size()). + //! + //! Throws: If the hash_func or equal_func throw. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair + equal_range(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const + { return table_.equal_range(key, hash_func, equal_func); } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator belonging to the unordered_set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: If the internal hash function throws. + iterator iterator_to(reference value) + { return table_.iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator belonging to the + //! unordered_set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: If the internal hash function throws. + const_iterator iterator_to(const_reference value) const + { return table_.iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid local_iterator belonging to the unordered_set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static local_iterator s_local_iterator_to(reference value) + { return table_type::s_local_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_local_iterator belonging to + //! the unordered_set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_local_iterator s_local_iterator_to(const_reference value) + { return table_type::s_local_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid local_iterator belonging to the unordered_set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + local_iterator local_iterator_to(reference value) + { return table_.local_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_local_iterator belonging to + //! the unordered_set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_local_iterator local_iterator_to(const_reference value) const + { return table_.local_iterator_to(value); } + + //! Effects: Returns the number of buckets passed in the constructor + //! or the last rehash function. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + size_type bucket_count() const + { return table_.bucket_count(); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns the number of elements in the nth bucket. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + size_type bucket_size(size_type n) const + { return table_.bucket_size(n); } + + //! Effects: Returns the index of the bucket in which elements + //! with keys equivalent to k would be found, if any such element existed. + //! + //! Complexity: Constant. + //! + //! Throws: If the hash functor throws. + //! + //! Note: the return value is in the range [0, this->bucket_count()). + size_type bucket(const value_type& k) const + { return table_.bucket(k); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! Effects: Returns the index of the bucket in which elements + //! with keys equivalent to k would be found, if any such element existed. + //! + //! Complexity: Constant. + //! + //! Throws: If hash_func throws. + //! + //! Note: the return value is in the range [0, this->bucket_count()). + template + size_type bucket(const KeyType& k, KeyHasher hash_func) const + { return table_.bucket(k, hash_func); } + + //! Effects: Returns the bucket array pointer passed in the constructor + //! or the last rehash function. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bucket_ptr bucket_pointer() const + { return table_.bucket_pointer(); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a local_iterator pointing to the beginning + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + local_iterator begin(size_type n) + { return table_.begin(n); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a const_local_iterator pointing to the beginning + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + const_local_iterator begin(size_type n) const + { return table_.begin(n); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a const_local_iterator pointing to the beginning + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + const_local_iterator cbegin(size_type n) const + { return table_.cbegin(n); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a local_iterator pointing to the end + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + local_iterator end(size_type n) + { return table_.end(n); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a const_local_iterator pointing to the end + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + const_local_iterator end(size_type n) const + { return table_.end(n); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a const_local_iterator pointing to the end + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + const_local_iterator cend(size_type n) const + { return table_.cend(n); } + + //! Requires: new_buckets must be a pointer to a new bucket array + //! or the same as the old bucket array. new_size is the length of the + //! the array pointed by new_buckets. If new_buckets == this->bucket_pointer() + //! n can be bigger or smaller than this->bucket_count(). + //! + //! Effects: Updates the internal reference with the new bucket erases + //! the values from the old bucket and inserts then in the new one. + //! + //! Complexity: Average case linear in this->size(), worst case quadratic. + //! + //! Throws: If the hasher functor throws. Basic guarantee. + void rehash(const bucket_traits &new_bucket_traits) + { table_.rehash(new_bucket_traits); } + + //! Effects: Returns the nearest new bucket count optimized for + //! the container that is bigger than n. This suggestion can be used + //! to create bucket arrays with a size that will usually improve + //! container's performance. If such value does not exist, the + //! higher possible value is returned. + //! + //! Complexity: Amortized constant time. + //! + //! Throws: Nothing. + static size_type suggested_upper_bucket_count(size_type n) + { return table_type::suggested_upper_bucket_count(n); } + + //! Effects: Returns the nearest new bucket count optimized for + //! the container that is smaller than n. This suggestion can be used + //! to create bucket arrays with a size that will usually improve + //! container's performance. If such value does not exist, the + //! lower possible value is returned. + //! + //! Complexity: Amortized constant time. + //! + //! Throws: Nothing. + static size_type suggested_lower_bucket_count(size_type n) + { return table_type::suggested_lower_bucket_count(n); } +}; + +//! Helper metafunction to define an \c unordered_set that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_unordered_set +{ + /// @cond + typedef unordered_set_impl + < typename make_hashtable_opt + ::type + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class unordered_set + : public make_unordered_set::type +{ + typedef typename make_unordered_set + ::type Base; + + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + public: + typedef typename Base::value_traits value_traits; + typedef typename Base::bucket_traits bucket_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + typedef typename Base::bucket_ptr bucket_ptr; + typedef typename Base::size_type size_type; + typedef typename Base::hasher hasher; + typedef typename Base::key_equal key_equal; + + unordered_set ( const bucket_traits &b_traits + , const hasher & hash_func = hasher() + , const key_equal &equal_func = key_equal() + , const value_traits &v_traits = value_traits()) + : Base(b_traits, hash_func, equal_func, v_traits) + {} + + template + unordered_set ( Iterator b + , Iterator e + , const bucket_traits &b_traits + , const hasher & hash_func = hasher() + , const key_equal &equal_func = key_equal() + , const value_traits &v_traits = value_traits()) + : Base(b, e, b_traits, hash_func, equal_func, v_traits) + {} +}; + +#endif + + +//! The class template unordered_multiset is an intrusive container, that mimics most of +//! the interface of std::tr1::unordered_multiset as described in the C++ TR1. +//! +//! unordered_multiset is a semi-intrusive container: each object to be stored in the +//! container must contain a proper hook, but the container also needs +//! additional auxiliary memory to work: unordered_multiset needs a pointer to an array +//! of type `bucket_type` to be passed in the constructor. This bucket array must +//! have at least the same lifetime as the container. This makes the use of +//! unordered_multiset more complicated than purely intrusive containers. +//! `bucket_type` is default-constructible, copyable and assignable +//! +//! The template parameter \c T is the type to be managed by the container. +//! The user can specify additional options and if no options are provided +//! default options are used. +//! +//! The container supports the following options: +//! \c base_hook<>/member_hook<>/value_traits<>, +//! \c constant_time_size<>, \c size_type<>, \c hash<> and \c equal<> +//! \c bucket_traits<>, power_2_buckets<> and cache_begin<>. +//! +//! unordered_multiset only provides forward iterators but it provides 4 iterator types: +//! iterator and const_iterator to navigate through the whole container and +//! local_iterator and const_local_iterator to navigate through the values +//! stored in a single bucket. Local iterators are faster and smaller. +//! +//! It's not recommended to use non constant-time size unordered_multisets because several +//! key functions, like "empty()", become non-constant time functions. Non +//! constant-time size unordered_multisets are mainly provided to support auto-unlink hooks. +//! +//! unordered_multiset, unlike std::unordered_set, does not make automatic rehashings nor +//! offers functions related to a load factor. Rehashing can be explicitly requested +//! and the user must provide a new bucket array that will be used from that moment. +//! +//! Since no automatic rehashing is done, iterators are never invalidated when +//! inserting or erasing elements. Iterators are only invalidated when rehasing. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class unordered_multiset_impl +{ + /// @cond + private: + typedef hashtable_impl table_type; + /// @endcond + + //! This class is + //! non-copyable + unordered_multiset_impl (const unordered_multiset_impl&); + + //! This class is + //! non-assignable + unordered_multiset_impl &operator =(const unordered_multiset_impl&); + + typedef table_type implementation_defined; + + public: + typedef typename implementation_defined::value_type value_type; + typedef typename implementation_defined::value_traits value_traits; + typedef typename implementation_defined::bucket_traits bucket_traits; + typedef typename implementation_defined::pointer pointer; + typedef typename implementation_defined::const_pointer const_pointer; + typedef typename implementation_defined::reference reference; + typedef typename implementation_defined::const_reference const_reference; + typedef typename implementation_defined::difference_type difference_type; + typedef typename implementation_defined::size_type size_type; + typedef typename implementation_defined::key_type key_type; + typedef typename implementation_defined::key_equal key_equal; + typedef typename implementation_defined::hasher hasher; + typedef typename implementation_defined::bucket_type bucket_type; + typedef typename implementation_defined::bucket_ptr bucket_ptr; + typedef typename implementation_defined::iterator iterator; + typedef typename implementation_defined::const_iterator const_iterator; + typedef typename implementation_defined::insert_commit_data insert_commit_data; + typedef typename implementation_defined::local_iterator local_iterator; + typedef typename implementation_defined::const_local_iterator const_local_iterator; + typedef typename implementation_defined::node_traits node_traits; + typedef typename implementation_defined::node node; + typedef typename implementation_defined::node_ptr node_ptr; + typedef typename implementation_defined::const_node_ptr const_node_ptr; + typedef typename implementation_defined::node_algorithms node_algorithms; + + /// @cond + private: + table_type table_; + /// @endcond + + public: + + //! Requires: buckets must not be being used by any other resource. + //! + //! Effects: Constructs an empty unordered_multiset, storing a reference + //! to the bucket array and copies of the hasher and equal functors. + //! + //! Complexity: Constant. + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor or invocation of Hash or Equal throws. + //! + //! Notes: buckets array must be disposed only after + //! *this is disposed. + unordered_multiset_impl ( const bucket_traits &b_traits + , const hasher & hash_func = hasher() + , const key_equal &equal_func = key_equal() + , const value_traits &v_traits = value_traits()) + : table_(b_traits, hash_func, equal_func, v_traits) + {} + + //! Requires: buckets must not be being used by any other resource + //! and Dereferencing iterator must yield an lvalue of type value_type. + //! + //! Effects: Constructs an empty unordered_multiset and inserts elements from + //! [b, e). + //! + //! Complexity: If N is std::distance(b, e): Average case is O(N) + //! (with a good hash function and with buckets_len >= N),worst case O(N2). + //! + //! Throws: If value_traits::node_traits::node + //! constructor throws (this does not happen with predefined Boost.Intrusive hooks) + //! or the copy constructor or invocation of hasher or key_equal throws. + //! + //! Notes: buckets array must be disposed only after + //! *this is disposed. + template + unordered_multiset_impl ( Iterator b + , Iterator e + , const bucket_traits &b_traits + , const hasher & hash_func = hasher() + , const key_equal &equal_func = key_equal() + , const value_traits &v_traits = value_traits()) + : table_(b_traits, hash_func, equal_func, v_traits) + { table_.insert_equal(b, e); } + + //! Effects: Detaches all elements from this. The objects in the unordered_multiset + //! are not deleted (i.e. no destructors are called). + //! + //! Complexity: Linear to the number of elements in the unordered_multiset, if + //! it's a safe-mode or auto-unlink value. Otherwise constant. + //! + //! Throws: Nothing. + ~unordered_multiset_impl() + {} + + //! Effects: Returns an iterator pointing to the beginning of the unordered_multiset. + //! + //! Complexity: Constant time if `cache_begin<>` is true. Amortized + //! constant time with worst case (empty unordered_set) O(this->bucket_count()) + //! + //! Throws: Nothing. + iterator begin() + { return table_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning + //! of the unordered_multiset. + //! + //! Complexity: Constant time if `cache_begin<>` is true. Amortized + //! constant time with worst case (empty unordered_set) O(this->bucket_count()) + //! + //! Throws: Nothing. + const_iterator begin() const + { return table_.begin(); } + + //! Effects: Returns a const_iterator pointing to the beginning + //! of the unordered_multiset. + //! + //! Complexity: Constant time if `cache_begin<>` is true. Amortized + //! constant time with worst case (empty unordered_set) O(this->bucket_count()) + //! + //! Throws: Nothing. + const_iterator cbegin() const + { return table_.cbegin(); } + + //! Effects: Returns an iterator pointing to the end of the unordered_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + iterator end() + { return table_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the unordered_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator end() const + { return table_.end(); } + + //! Effects: Returns a const_iterator pointing to the end of the unordered_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_iterator cend() const + { return table_.cend(); } + + //! Effects: Returns the hasher object used by the unordered_set. + //! + //! Complexity: Constant. + //! + //! Throws: If hasher copy-constructor throws. + hasher hash_function() const + { return table_.hash_function(); } + + //! Effects: Returns the key_equal object used by the unordered_multiset. + //! + //! Complexity: Constant. + //! + //! Throws: If key_equal copy-constructor throws. + key_equal key_eq() const + { return table_.key_eq(); } + + //! Effects: Returns true is the container is empty. + //! + //! Complexity: if constant-time size and cache_last options are disabled, + //! average constant time (worst case, with empty() == true: O(this->bucket_count()). + //! Otherwise constant. + //! + //! Throws: Nothing. + bool empty() const + { return table_.empty(); } + + //! Effects: Returns the number of elements stored in the unordered_multiset. + //! + //! Complexity: Linear to elements contained in *this if + //! constant-time size option is enabled. Constant-time otherwise. + //! + //! Throws: Nothing. + size_type size() const + { return table_.size(); } + + //! Requires: the hasher and the equality function unqualified swap + //! call should not throw. + //! + //! Effects: Swaps the contents of two unordered_multisets. + //! Swaps also the contained bucket array and equality and hasher functors. + //! + //! + //! Complexity: Constant. + //! + //! Throws: If the swap() call for the comparison or hash functors + //! found using ADL throw. Basic guarantee. + void swap(unordered_multiset_impl& other) + { table_.swap(other.table_); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements from *this + //! calling Disposer::operator()(pointer), clones all the + //! elements from src calling Cloner::operator()(const_reference ) + //! and inserts them on *this. + //! + //! If cloner throws, all cloned elements are unlinked and disposed + //! calling Disposer::operator()(pointer). + //! + //! Complexity: Linear to erased plus inserted elements. + //! + //! Throws: If cloner throws. + template + void clone_from(const unordered_multiset_impl &src, Cloner cloner, Disposer disposer) + { table_.clone_from(src.table_, cloner, disposer); } + + //! Requires: value must be an lvalue + //! + //! Effects: Inserts value into the unordered_multiset. + //! + //! Returns: An iterator to the new inserted value. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. Strong guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + iterator insert(reference value) + { return table_.insert_equal(value); } + + //! Requires: Dereferencing iterator must yield an lvalue + //! of type value_type. + //! + //! Effects: Equivalent to this->insert(t) for each element in [b, e). + //! + //! Complexity: Insert range is in general O(N * log(N)), where N is the + //! size of the range. However, it is linear in N if the range is already sorted + //! by value_comp(). + //! + //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. + //! + //! Note: Does not affect the validity of iterators and references. + //! No copy-constructors are called. + template + void insert(Iterator b, Iterator e) + { table_.insert_equal(b, e); } + + //! Effects: Erases the element pointed to by i. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased element. No destructors are called. + void erase(const_iterator i) + { table_.erase(i); } + + //! Effects: Erases the range pointed to by b end e. + //! + //! Complexity: Average case O(std::distance(b, e)), + //! worst case O(this->size()). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void erase(const_iterator b, const_iterator e) + { table_.erase(b, e); } + + //! Effects: Erases all the elements with the given value. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Average case O(this->count(value)). + //! Worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + size_type erase(const_reference value) + { return table_.erase(value); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "key_value_equal" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "key_value_equal" compares an arbitrary key with the contained values. + //! + //! Effects: Erases all the elements that have the same hash and + //! compare equal with the given key. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Average case O(this->count(value)). + //! Worst case O(this->size()). + //! + //! Throws: If the hash_func or the equal_func functors throws. + //! Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) + { return table_.erase(key, hash_func, equal_func); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the element pointed to by i. + //! Disposer::operator()(pointer) is called for the removed element. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + void erase_and_dispose(const_iterator i, Disposer disposer) + { table_.erase_and_dispose(i, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases the range pointed to by b end e. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Complexity: Average case O(std::distance(b, e)), + //! worst case O(this->size()). + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + void erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer) + { table_.erase_and_dispose(b, e, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given value. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Average case O(this->count(value)). + //! Worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. Basic guarantee. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + size_type erase_and_dispose(const_reference value, Disposer disposer) + { return table_.erase_and_dispose(value, disposer); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements with the given key. + //! according to the comparison functor "equal_func". + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Returns: The number of erased elements. + //! + //! Complexity: Average case O(this->count(value)). + //! Worst case O(this->size()). + //! + //! Throws: If hash_func or equal_func throw. Basic guarantee. + //! + //! Note: Invalidates the iterators + //! to the erased elements. + template + size_type erase_and_dispose(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func, Disposer disposer) + { return table_.erase_and_dispose(key, hash_func, equal_func, disposer); } + + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + void clear() + { return table_.clear(); } + + //! Requires: Disposer::operator()(pointer) shouldn't throw. + //! + //! Effects: Erases all the elements of the container. + //! + //! Complexity: Linear to the number of elements on the container. + //! Disposer::operator()(pointer) is called for the removed elements. + //! + //! Throws: Nothing. + //! + //! Note: Invalidates the iterators (but not the references) + //! to the erased elements. No destructors are called. + template + void clear_and_dispose(Disposer disposer) + { return table_.clear_and_dispose(disposer); } + + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + size_type count(const_reference value) const + { return table_.count(value); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "key_value_equal" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "key_value_equal" compares an arbitrary key with the contained values. + //! + //! Effects: Returns the number of contained elements with the given key + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + template + size_type count(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const + { return table_.count(key, hash_func, equal_func); } + + //! Effects: Finds an iterator to the first element whose value is + //! "value" or end() if that element does not exist. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + iterator find(const_reference value) + { return table_.find(value); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "key_value_equal" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "key_value_equal" compares an arbitrary key with the contained values. + //! + //! Effects: Finds an iterator to the first element whose key is + //! "key" according to the given hasher and equality functor or end() if + //! that element does not exist. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) + { return table_.find(key, hash_func, equal_func); } + + //! Effects: Finds a const_iterator to the first element whose key is + //! "key" or end() if that element does not exist. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + const_iterator find(const_reference value) const + { return table_.find(value); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "key_value_equal" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "key_value_equal" compares an arbitrary key with the contained values. + //! + //! Effects: Finds an iterator to the first element whose key is + //! "key" according to the given hasher and equality functor or end() if + //! that element does not exist. + //! + //! Complexity: Average case O(1), worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + const_iterator find(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const + { return table_.find(key, hash_func, equal_func); } + + //! Effects: Returns a range containing all elements with values equivalent + //! to value. Returns std::make_pair(this->end(), this->end()) if no such + //! elements exist. + //! + //! Complexity: Average case O(this->count(value)). Worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + std::pair equal_range(const_reference value) + { return table_.equal_range(value); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "key_value_equal" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "key_value_equal" compares an arbitrary key with the contained values. + //! + //! Effects: Returns a range containing all elements with equivalent + //! keys. Returns std::make_pair(this->end(), this->end()) if no such + //! elements exist. + //! + //! Complexity: Average case O(this->count(key, hash_func, equal_func)). + //! Worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair equal_range + (const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) + { return table_.equal_range(key, hash_func, equal_func); } + + //! Effects: Returns a range containing all elements with values equivalent + //! to value. Returns std::make_pair(this->end(), this->end()) if no such + //! elements exist. + //! + //! Complexity: Average case O(this->count(value)). Worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + std::pair + equal_range(const_reference value) const + { return table_.equal_range(value); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! "key_value_equal" must be a equality function that induces + //! the same equality as key_equal. The difference is that + //! "key_value_equal" compares an arbitrary key with the contained values. + //! + //! Effects: Returns a range containing all elements with equivalent + //! keys. Returns std::make_pair(this->end(), this->end()) if no such + //! elements exist. + //! + //! Complexity: Average case O(this->count(key, hash_func, equal_func)). + //! Worst case O(this->size()). + //! + //! Throws: If the internal hasher or the equality functor throws. + //! + //! Note: This function is used when constructing a value_type + //! is expensive and the value_type can be compared with a cheaper + //! key type. Usually this key is part of the value_type. + template + std::pair + equal_range(const KeyType& key, KeyHasher hash_func, KeyValueEqual equal_func) const + { return table_.equal_range(key, hash_func, equal_func); } + + //! Requires: value must be an lvalue and shall be in a unordered_multiset of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid iterator belonging to the unordered_multiset + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: If the hash function throws. + iterator iterator_to(reference value) + { return table_.iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a unordered_multiset of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_iterator belonging to the + //! unordered_multiset that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: If the hash function throws. + const_iterator iterator_to(const_reference value) const + { return table_.iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid local_iterator belonging to the unordered_set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static local_iterator s_local_iterator_to(reference value) + { return table_type::s_local_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_local_iterator belonging to + //! the unordered_set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: This static function is available only if the value traits + //! is stateless. + static const_local_iterator s_local_iterator_to(const_reference value) + { return table_type::s_local_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid local_iterator belonging to the unordered_set + //! that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + local_iterator local_iterator_to(reference value) + { return table_.local_iterator_to(value); } + + //! Requires: value must be an lvalue and shall be in a unordered_set of + //! appropriate type. Otherwise the behavior is undefined. + //! + //! Effects: Returns: a valid const_local_iterator belonging to + //! the unordered_set that points to the value + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + const_local_iterator local_iterator_to(const_reference value) const + { return table_.local_iterator_to(value); } + + //! Effects: Returns the number of buckets passed in the constructor + //! or the last rehash function. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + size_type bucket_count() const + { return table_.bucket_count(); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns the number of elements in the nth bucket. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + size_type bucket_size(size_type n) const + { return table_.bucket_size(n); } + + //! Effects: Returns the index of the bucket in which elements + //! with keys equivalent to k would be found, if any such element existed. + //! + //! Complexity: Constant. + //! + //! Throws: If the hash functor throws. + //! + //! Note: the return value is in the range [0, this->bucket_count()). + size_type bucket(const value_type& k) const + { return table_.bucket(k); } + + //! Requires: "hash_func" must be a hash function that induces + //! the same hash values as the stored hasher. The difference is that + //! "hash_func" hashes the given key instead of the value_type. + //! + //! Effects: Returns the index of the bucket in which elements + //! with keys equivalent to k would be found, if any such element existed. + //! + //! Complexity: Constant. + //! + //! Throws: If the hash functor throws. + //! + //! Note: the return value is in the range [0, this->bucket_count()). + template + size_type bucket(const KeyType& k, const KeyHasher &hash_func) const + { return table_.bucket(k, hash_func); } + + //! Effects: Returns the bucket array pointer passed in the constructor + //! or the last rehash function. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + bucket_ptr bucket_pointer() const + { return table_.bucket_pointer(); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a local_iterator pointing to the beginning + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + local_iterator begin(size_type n) + { return table_.begin(n); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a const_local_iterator pointing to the beginning + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + const_local_iterator begin(size_type n) const + { return table_.begin(n); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a const_local_iterator pointing to the beginning + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + const_local_iterator cbegin(size_type n) const + { return table_.cbegin(n); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a local_iterator pointing to the end + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + local_iterator end(size_type n) + { return table_.end(n); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a const_local_iterator pointing to the end + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + const_local_iterator end(size_type n) const + { return table_.end(n); } + + //! Requires: n is in the range [0, this->bucket_count()). + //! + //! Effects: Returns a const_local_iterator pointing to the end + //! of the sequence stored in the bucket n. + //! + //! Complexity: Constant. + //! + //! Throws: Nothing. + //! + //! Note: [this->begin(n), this->end(n)) is a valid range + //! containing all of the elements in the nth bucket. + const_local_iterator cend(size_type n) const + { return table_.cend(n); } + + //! Requires: new_buckets must be a pointer to a new bucket array + //! or the same as the old bucket array. new_size is the length of the + //! the array pointed by new_buckets. If new_buckets == this->bucket_pointer() + //! n can be bigger or smaller than this->bucket_count(). + //! + //! Effects: Updates the internal reference with the new bucket erases + //! the values from the old bucket and inserts then in the new one. + //! + //! Complexity: Average case linear in this->size(), worst case quadratic. + //! + //! Throws: If the hasher functor throws. + void rehash(const bucket_traits &new_bucket_traits) + { table_.rehash(new_bucket_traits); } + + //! Effects: Returns the nearest new bucket count optimized for + //! the container that is bigger than n. This suggestion can be used + //! to create bucket arrays with a size that will usually improve + //! container's performance. If such value does not exist, the + //! higher possible value is returned. + //! + //! Complexity: Amortized constant time. + //! + //! Throws: Nothing. + static size_type suggested_upper_bucket_count(size_type n) + { return table_type::suggested_upper_bucket_count(n); } + + //! Effects: Returns the nearest new bucket count optimized for + //! the container that is smaller than n. This suggestion can be used + //! to create bucket arrays with a size that will usually improve + //! container's performance. If such value does not exist, the + //! lower possible value is returned. + //! + //! Complexity: Amortized constant time. + //! + //! Throws: Nothing. + static size_type suggested_lower_bucket_count(size_type n) + { return table_type::suggested_lower_bucket_count(n); } +}; + +//! Helper metafunction to define an \c unordered_multiset that yields to the same type when the +//! same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_unordered_multiset +{ + /// @cond + typedef unordered_multiset_impl + < typename make_hashtable_opt + ::type + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +class unordered_multiset + : public make_unordered_multiset::type +{ + typedef typename make_unordered_multiset + ::type Base; + //Assert if passed value traits are compatible with the type + BOOST_STATIC_ASSERT((detail::is_same::value)); + + public: + typedef typename Base::value_traits value_traits; + typedef typename Base::bucket_traits bucket_traits; + typedef typename Base::iterator iterator; + typedef typename Base::const_iterator const_iterator; + typedef typename Base::bucket_ptr bucket_ptr; + typedef typename Base::size_type size_type; + typedef typename Base::hasher hasher; + typedef typename Base::key_equal key_equal; + + unordered_multiset( const bucket_traits &b_traits + , const hasher & hash_func = hasher() + , const key_equal &equal_func = key_equal() + , const value_traits &v_traits = value_traits()) + : Base(b_traits, hash_func, equal_func, v_traits) + {} + + template + unordered_multiset( Iterator b + , Iterator e + , const bucket_traits &b_traits + , const hasher & hash_func = hasher() + , const key_equal &equal_func = key_equal() + , const value_traits &v_traits = value_traits()) + : Base(b, e, b_traits, hash_func, equal_func, v_traits) + {} +}; + +#endif + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_UNORDERED_SET_HPP diff --git a/win32/include/boost/intrusive/unordered_set_hook.hpp b/win32/include/boost/intrusive/unordered_set_hook.hpp new file mode 100755 index 000000000..89efd59db --- /dev/null +++ b/win32/include/boost/intrusive/unordered_set_hook.hpp @@ -0,0 +1,401 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Olaf Krzikalla 2004-2006. +// (C) Copyright Ion Gaztanaga 2006-2007 +// +// 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) +// +// See http://www.boost.org/libs/intrusive for documentation. +// +///////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTRUSIVE_UNORDERED_SET_HOOK_HPP +#define BOOST_INTRUSIVE_UNORDERED_SET_HOOK_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace intrusive { + +/// @cond + +template +struct unordered_node + : public slist_node +{ + typedef typename boost::pointer_to_other + < VoidPointer + , unordered_node + >::type node_ptr; + node_ptr prev_in_group_; + std::size_t hash_; +}; + +template +struct unordered_node + : public slist_node +{ + typedef typename boost::pointer_to_other + < VoidPointer + , unordered_node + >::type node_ptr; + node_ptr prev_in_group_; +}; + +template +struct unordered_node + : public slist_node +{ + typedef typename boost::pointer_to_other + < VoidPointer + , unordered_node + >::type node_ptr; + std::size_t hash_; +}; + +template +struct unordered_node_traits + : public slist_node_traits +{ + typedef slist_node_traits reduced_slist_node_traits; + typedef unordered_node node; + typedef typename boost::pointer_to_other + ::type node_ptr; + typedef typename boost::pointer_to_other + ::type const_node_ptr; + + static const bool store_hash = StoreHash; + static const bool optimize_multikey = OptimizeMultiKey; + + static node_ptr get_next(const_node_ptr n) + { return node_ptr(&static_cast(*n->next_)); } + + static void set_next(node_ptr n, node_ptr next) + { n->next_ = next; } + + static node_ptr get_prev_in_group(const_node_ptr n) + { return n->prev_in_group_; } + + static void set_prev_in_group(node_ptr n, node_ptr prev) + { n->prev_in_group_ = prev; } + + static std::size_t get_hash(const_node_ptr n) + { return n->hash_; } + + static void set_hash(node_ptr n, std::size_t h) + { n->hash_ = h; } +}; + +template +struct unordered_group_adapter +{ + typedef typename NodeTraits::node node; + typedef typename NodeTraits::node_ptr node_ptr; + typedef typename NodeTraits::const_node_ptr const_node_ptr; + + static node_ptr get_next(const_node_ptr n) + { return NodeTraits::get_prev_in_group(n); } + + static void set_next(node_ptr n, node_ptr next) + { NodeTraits::set_prev_in_group(n, next); } +}; + +template +struct unordered_algorithms + : public circular_slist_algorithms +{ + typedef circular_slist_algorithms base_type; + typedef unordered_group_adapter group_traits; + typedef circular_slist_algorithms group_algorithms; + + static void init(typename base_type::node_ptr n) + { + base_type::init(n); + group_algorithms::init(n); + } + + static void init_header(typename base_type::node_ptr n) + { + base_type::init_header(n); + group_algorithms::init_header(n); + } + + static void unlink(typename base_type::node_ptr n) + { + base_type::unlink(n); + group_algorithms::unlink(n); + } +}; + +template +struct get_uset_node_algo +{ + typedef typename detail::if_c + < (StoreHash || OptimizeMultiKey) + , unordered_node_traits + , slist_node_traits + >::type node_traits_type; + typedef typename detail::if_c + < OptimizeMultiKey + , unordered_algorithms + , circular_slist_algorithms + >::type type; +}; +/// @endcond + +//! Helper metafunction to define a \c unordered_set_base_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_unordered_set_base_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3, O4>::type packed_options; + + typedef detail::generic_hook + < get_uset_node_algo + , typename packed_options::tag + , packed_options::link_mode + , detail::UsetBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Derive a class from unordered_set_base_hook in order to store objects in +//! in an unordered_set/unordered_multi_set. unordered_set_base_hook holds the data necessary to maintain +//! the unordered_set/unordered_multi_set and provides an appropriate value_traits class for unordered_set/unordered_multi_set. +//! +//! The hook admits the following options: \c tag<>, \c void_pointer<>, +//! \c link_mode<>, \c store_hash<> and \c optimize_multikey<>. +//! +//! \c tag<> defines a tag to identify the node. +//! The same tag value can be used in different classes, but if a class is +//! derived from more than one \c list_base_hook, then each \c list_base_hook needs its +//! unique tag. +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, +//! \c auto_unlink or \c safe_link). +//! +//! \c store_hash<> will tell the hook to store the hash of the value +//! to speed up rehashings. +//! +//! \c optimize_multikey<> will tell the hook to store a link to form a group +//! with other value with the same value to speed up searches and insertions +//! in unordered_multisets with a great number of with equivalent keys. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class unordered_set_base_hook + : public make_unordered_set_base_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + unordered_set_base_hook(); + + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + unordered_set_base_hook(const unordered_set_base_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + unordered_set_base_hook& operator=(const unordered_set_base_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in an unordered_set an assertion is raised. If link_mode is + //! \c auto_unlink and \c is_linked() is true, the node is unlinked. + //! + //! Throws: Nothing. + ~unordered_set_base_hook(); + + //! Effects: Swapping two nodes swaps the position of the elements + //! related to those nodes in one or two containers. That is, if the node + //! this is part of the element e1, the node x is part of the element e2 + //! and both elements are included in the containers s1 and s2, then after + //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 + //! at the position of e1. If one element is not in a container, then + //! after the swap-operation the other element is not in a container. + //! Iterators to e1 and e2 related to those nodes are invalidated. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + void swap_nodes(unordered_set_base_hook &other); + + //! Precondition: link_mode must be \c safe_link or \c auto_unlink. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c unordered_set::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + + //! Effects: Removes the node if it's inserted in a container. + //! This function is only allowed if link_mode is \c auto_unlink. + //! + //! Throws: Nothing. + void unlink(); + #endif +}; + + +//! Helper metafunction to define a \c unordered_set_member_hook that yields to the same +//! type when the same options (either explicitly or implicitly) are used. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +struct make_unordered_set_member_hook +{ + /// @cond + typedef typename pack_options + < hook_defaults, O1, O2, O3, O4>::type packed_options; + + typedef detail::generic_hook + < get_uset_node_algo< typename packed_options::void_pointer + , packed_options::store_hash + , packed_options::optimize_multikey + > + , member_tag + , packed_options::link_mode + , detail::NoBaseHook + > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +//! Put a public data member unordered_set_member_hook in order to store objects of this class in +//! an unordered_set/unordered_multi_set. unordered_set_member_hook holds the data necessary for maintaining the +//! unordered_set/unordered_multi_set and provides an appropriate value_traits class for unordered_set/unordered_multi_set. +//! +//! The hook admits the following options: \c void_pointer<>, +//! \c link_mode<> and \c store_hash<>. +//! +//! \c void_pointer<> is the pointer type that will be used internally in the hook +//! and the the container configured to use this hook. +//! +//! \c link_mode<> will specify the linking mode of the hook (\c normal_link, +//! \c auto_unlink or \c safe_link). +//! +//! \c store_hash<> will tell the hook to store the hash of the value +//! to speed up rehashings. +#ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED +template +#else +template +#endif +class unordered_set_member_hook + : public make_unordered_set_member_hook::type +{ + #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. + //! + //! Throws: Nothing. + unordered_set_member_hook(); + + //! Effects: If link_mode is \c auto_unlink or \c safe_link + //! initializes the node to an unlinked state. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing a copy-constructor + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + unordered_set_member_hook(const unordered_set_member_hook& ); + + //! Effects: Empty function. The argument is ignored. + //! + //! Throws: Nothing. + //! + //! Rationale: Providing an assignment operator + //! makes classes using the hook STL-compliant without forcing the + //! user to do some additional work. \c swap can be used to emulate + //! move-semantics. + unordered_set_member_hook& operator=(const unordered_set_member_hook& ); + + //! Effects: If link_mode is \c normal_link, the destructor does + //! nothing (ie. no code is generated). If link_mode is \c safe_link and the + //! object is stored in an unordered_set an assertion is raised. If link_mode is + //! \c auto_unlink and \c is_linked() is true, the node is unlinked. + //! + //! Throws: Nothing. + ~unordered_set_member_hook(); + + //! Effects: Swapping two nodes swaps the position of the elements + //! related to those nodes in one or two containers. That is, if the node + //! this is part of the element e1, the node x is part of the element e2 + //! and both elements are included in the containers s1 and s2, then after + //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 + //! at the position of e1. If one element is not in a container, then + //! after the swap-operation the other element is not in a container. + //! Iterators to e1 and e2 related to those nodes are invalidated. + //! + //! Complexity: Constant + //! + //! Throws: Nothing. + void swap_nodes(unordered_set_member_hook &other); + + //! Precondition: link_mode must be \c safe_link or \c auto_unlink. + //! + //! Returns: true, if the node belongs to a container, false + //! otherwise. This function can be used to test whether \c unordered_set::iterator_to + //! will return a valid iterator. + //! + //! Complexity: Constant + bool is_linked() const; + + //! Effects: Removes the node if it's inserted in a container. + //! This function is only allowed if link_mode is \c auto_unlink. + //! + //! Throws: Nothing. + void unlink(); + #endif +}; + +} //namespace intrusive +} //namespace boost + +#include + +#endif //BOOST_INTRUSIVE_UNORDERED_SET_HOOK_HPP diff --git a/win32/include/boost/intrusive_ptr.hpp b/win32/include/boost/intrusive_ptr.hpp new file mode 100755 index 000000000..f2b93ab59 --- /dev/null +++ b/win32/include/boost/intrusive_ptr.hpp @@ -0,0 +1,311 @@ +#ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED +#define BOOST_INTRUSIVE_PTR_HPP_INCLUDED + +// +// intrusive_ptr.hpp +// +// Copyright (c) 2001, 2002 Peter Dimov +// +// 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) +// +// See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation. +// + +#include + +#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash +# pragma warning(push) +# pragma warning(disable:4284) // odd return type for operator-> +#endif + +#include +#include +#include + +#include // for std::less + +#if !defined(BOOST_NO_IOSTREAM) +#if !defined(BOOST_NO_IOSFWD) +#include // for std::basic_ostream +#else +#include +#endif +#endif + + +namespace boost +{ + +// +// intrusive_ptr +// +// A smart pointer that uses intrusive reference counting. +// +// Relies on unqualified calls to +// +// void intrusive_ptr_add_ref(T * p); +// void intrusive_ptr_release(T * p); +// +// (p != 0) +// +// The object is responsible for destroying itself. +// + +template class intrusive_ptr +{ +private: + + typedef intrusive_ptr this_type; + +public: + + typedef T element_type; + + intrusive_ptr(): p_(0) + { + } + + intrusive_ptr(T * p, bool add_ref = true): p_(p) + { + if(p_ != 0 && add_ref) intrusive_ptr_add_ref(p_); + } + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + intrusive_ptr( intrusive_ptr const & rhs, typename detail::sp_enable_if_convertible::type = detail::sp_empty() ) + +#else + + intrusive_ptr( intrusive_ptr const & rhs ) + +#endif + : p_( rhs.get() ) + { + if( p_ != 0 ) intrusive_ptr_add_ref( p_ ); + } + +#endif + + intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_) + { + if(p_ != 0) intrusive_ptr_add_ref(p_); + } + + ~intrusive_ptr() + { + if(p_ != 0) intrusive_ptr_release(p_); + } + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) + + template intrusive_ptr & operator=(intrusive_ptr const & rhs) + { + this_type(rhs).swap(*this); + return *this; + } + +#endif + + intrusive_ptr & operator=(intrusive_ptr const & rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + intrusive_ptr & operator=(T * rhs) + { + this_type(rhs).swap(*this); + return *this; + } + + void reset() + { + this_type().swap( *this ); + } + + void reset( T * rhs ) + { + this_type( rhs ).swap( *this ); + } + + T * get() const + { + return p_; + } + + T & operator*() const + { + BOOST_ASSERT( p_ != 0 ); + return *p_; + } + + T * operator->() const + { + BOOST_ASSERT( p_ != 0 ); + return p_; + } + +#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) + + operator bool () const + { + return p_ != 0; + } + +#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + typedef T * (this_type::*unspecified_bool_type)() const; + + operator unspecified_bool_type() const // never throws + { + return p_ == 0? 0: &this_type::get; + } + +#else + + typedef T * this_type::*unspecified_bool_type; + + operator unspecified_bool_type () const + { + return p_ == 0? 0: &this_type::p_; + } + +#endif + + // operator! is a Borland-specific workaround + bool operator! () const + { + return p_ == 0; + } + + void swap(intrusive_ptr & rhs) + { + T * tmp = p_; + p_ = rhs.p_; + rhs.p_ = tmp; + } + +private: + + T * p_; +}; + +template inline bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() == b.get(); +} + +template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() != b.get(); +} + +template inline bool operator==(intrusive_ptr const & a, U * b) +{ + return a.get() == b; +} + +template inline bool operator!=(intrusive_ptr const & a, U * b) +{ + return a.get() != b; +} + +template inline bool operator==(T * a, intrusive_ptr const & b) +{ + return a == b.get(); +} + +template inline bool operator!=(T * a, intrusive_ptr const & b) +{ + return a != b.get(); +} + +#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 + +// Resolve the ambiguity between our op!= and the one in rel_ops + +template inline bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return a.get() != b.get(); +} + +#endif + +template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) +{ + return std::less()(a.get(), b.get()); +} + +template void swap(intrusive_ptr & lhs, intrusive_ptr & rhs) +{ + lhs.swap(rhs); +} + +// mem_fn support + +template T * get_pointer(intrusive_ptr const & p) +{ + return p.get(); +} + +template intrusive_ptr static_pointer_cast(intrusive_ptr const & p) +{ + return static_cast(p.get()); +} + +template intrusive_ptr const_pointer_cast(intrusive_ptr const & p) +{ + return const_cast(p.get()); +} + +template intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & p) +{ + return dynamic_cast(p.get()); +} + +// operator<< + +#if !defined(BOOST_NO_IOSTREAM) + +#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) ) + +template std::ostream & operator<< (std::ostream & os, intrusive_ptr const & p) +{ + os << p.get(); + return os; +} + +#else + +// in STLport's no-iostreams mode no iostream symbols can be used +#ifndef _STLP_NO_IOSTREAMS + +# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) +// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL +using std::basic_ostream; +template basic_ostream & operator<< (basic_ostream & os, intrusive_ptr const & p) +# else +template std::basic_ostream & operator<< (std::basic_ostream & os, intrusive_ptr const & p) +# endif +{ + os << p.get(); + return os; +} + +#endif // _STLP_NO_IOSTREAMS + +#endif // __GNUC__ < 3 + +#endif // !defined(BOOST_NO_IOSTREAM) + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED diff --git a/win32/include/boost/io/ios_state.hpp b/win32/include/boost/io/ios_state.hpp new file mode 100755 index 000000000..848e6fdfb --- /dev/null +++ b/win32/include/boost/io/ios_state.hpp @@ -0,0 +1,431 @@ +// Boost io/ios_state.hpp header file --------------------------------------// + +// Copyright 2002, 2005 Daryle Walker. Use, modification, and distribution +// are subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or a copy at .) + +// See for the library's home page. + +#ifndef BOOST_IO_IOS_STATE_HPP +#define BOOST_IO_IOS_STATE_HPP + +#include // self include +#include + +#include // for std::ios_base, std::basic_ios, etc. +#ifndef BOOST_NO_STD_LOCALE +#include // for std::locale +#endif +#include // for std::basic_ostream +#include // for std::basic_streambuf +#include // for std::char_traits + + +namespace boost +{ +namespace io +{ + + +// Basic stream state saver class declarations -----------------------------// + +class ios_flags_saver +{ +public: + typedef ::std::ios_base state_type; + typedef ::std::ios_base::fmtflags aspect_type; + + explicit ios_flags_saver( state_type &s ) + : s_save_( s ), a_save_( s.flags() ) + {} + ios_flags_saver( state_type &s, aspect_type const &a ) + : s_save_( s ), a_save_( s.flags(a) ) + {} + ~ios_flags_saver() + { this->restore(); } + + void restore() + { s_save_.flags( a_save_ ); } + +private: + state_type & s_save_; + aspect_type const a_save_; + + ios_flags_saver& operator=(const ios_flags_saver&); +}; + +class ios_precision_saver +{ +public: + typedef ::std::ios_base state_type; + typedef ::std::streamsize aspect_type; + + explicit ios_precision_saver( state_type &s ) + : s_save_( s ), a_save_( s.precision() ) + {} + ios_precision_saver( state_type &s, aspect_type const &a ) + : s_save_( s ), a_save_( s.precision(a) ) + {} + ~ios_precision_saver() + { this->restore(); } + + void restore() + { s_save_.precision( a_save_ ); } + +private: + state_type & s_save_; + aspect_type const a_save_; + + ios_precision_saver& operator=(const ios_precision_saver&); +}; + +class ios_width_saver +{ +public: + typedef ::std::ios_base state_type; + typedef ::std::streamsize aspect_type; + + explicit ios_width_saver( state_type &s ) + : s_save_( s ), a_save_( s.width() ) + {} + ios_width_saver( state_type &s, aspect_type const &a ) + : s_save_( s ), a_save_( s.width(a) ) + {} + ~ios_width_saver() + { this->restore(); } + + void restore() + { s_save_.width( a_save_ ); } + +private: + state_type & s_save_; + aspect_type const a_save_; + ios_width_saver& operator=(const ios_width_saver&); +}; + + +// Advanced stream state saver class template declarations -----------------// + +template < typename Ch, class Tr > +class basic_ios_iostate_saver +{ +public: + typedef ::std::basic_ios state_type; + typedef ::std::ios_base::iostate aspect_type; + + explicit basic_ios_iostate_saver( state_type &s ) + : s_save_( s ), a_save_( s.rdstate() ) + {} + basic_ios_iostate_saver( state_type &s, aspect_type const &a ) + : s_save_( s ), a_save_( s.rdstate() ) + { s.clear(a); } + ~basic_ios_iostate_saver() + { this->restore(); } + + void restore() + { s_save_.clear( a_save_ ); } + +private: + state_type & s_save_; + aspect_type const a_save_; +}; + +template < typename Ch, class Tr > +class basic_ios_exception_saver +{ +public: + typedef ::std::basic_ios state_type; + typedef ::std::ios_base::iostate aspect_type; + + explicit basic_ios_exception_saver( state_type &s ) + : s_save_( s ), a_save_( s.exceptions() ) + {} +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) + basic_ios_exception_saver( state_type &s, aspect_type a ) +#else + basic_ios_exception_saver( state_type &s, aspect_type const &a ) +#endif + : s_save_( s ), a_save_( s.exceptions() ) + { s.exceptions(a); } + ~basic_ios_exception_saver() + { this->restore(); } + + void restore() + { s_save_.exceptions( a_save_ ); } + +private: + state_type & s_save_; + aspect_type const a_save_; +}; + +template < typename Ch, class Tr > +class basic_ios_tie_saver +{ +public: + typedef ::std::basic_ios state_type; + typedef ::std::basic_ostream * aspect_type; + + explicit basic_ios_tie_saver( state_type &s ) + : s_save_( s ), a_save_( s.tie() ) + {} + basic_ios_tie_saver( state_type &s, aspect_type const &a ) + : s_save_( s ), a_save_( s.tie(a) ) + {} + ~basic_ios_tie_saver() + { this->restore(); } + + void restore() + { s_save_.tie( a_save_ ); } + +private: + state_type & s_save_; + aspect_type const a_save_; +}; + +template < typename Ch, class Tr > +class basic_ios_rdbuf_saver +{ +public: + typedef ::std::basic_ios state_type; + typedef ::std::basic_streambuf * aspect_type; + + explicit basic_ios_rdbuf_saver( state_type &s ) + : s_save_( s ), a_save_( s.rdbuf() ) + {} + basic_ios_rdbuf_saver( state_type &s, aspect_type const &a ) + : s_save_( s ), a_save_( s.rdbuf(a) ) + {} + ~basic_ios_rdbuf_saver() + { this->restore(); } + + void restore() + { s_save_.rdbuf( a_save_ ); } + +private: + state_type & s_save_; + aspect_type const a_save_; +}; + +template < typename Ch, class Tr > +class basic_ios_fill_saver +{ +public: + typedef ::std::basic_ios state_type; + typedef typename state_type::char_type aspect_type; + + explicit basic_ios_fill_saver( state_type &s ) + : s_save_( s ), a_save_( s.fill() ) + {} + basic_ios_fill_saver( state_type &s, aspect_type const &a ) + : s_save_( s ), a_save_( s.fill(a) ) + {} + ~basic_ios_fill_saver() + { this->restore(); } + + void restore() + { s_save_.fill( a_save_ ); } + +private: + state_type & s_save_; + aspect_type const a_save_; +}; + +#ifndef BOOST_NO_STD_LOCALE +template < typename Ch, class Tr > +class basic_ios_locale_saver +{ +public: + typedef ::std::basic_ios state_type; + typedef ::std::locale aspect_type; + + explicit basic_ios_locale_saver( state_type &s ) + : s_save_( s ), a_save_( s.getloc() ) + {} + basic_ios_locale_saver( state_type &s, aspect_type const &a ) + : s_save_( s ), a_save_( s.imbue(a) ) + {} + ~basic_ios_locale_saver() + { this->restore(); } + + void restore() + { s_save_.imbue( a_save_ ); } + +private: + state_type & s_save_; + aspect_type const a_save_; +}; +#endif + + +// User-defined stream state saver class declarations ----------------------// + +class ios_iword_saver +{ +public: + typedef ::std::ios_base state_type; + typedef int index_type; + typedef long aspect_type; + + explicit ios_iword_saver( state_type &s, index_type i ) + : s_save_( s ), a_save_( s.iword(i) ), i_save_( i ) + {} + ios_iword_saver( state_type &s, index_type i, aspect_type const &a ) + : s_save_( s ), a_save_( s.iword(i) ), i_save_( i ) + { s.iword(i) = a; } + ~ios_iword_saver() + { this->restore(); } + + void restore() + { s_save_.iword( i_save_ ) = a_save_; } + +private: + state_type & s_save_; + aspect_type const a_save_; + index_type const i_save_; + + ios_iword_saver& operator=(const ios_iword_saver&); +}; + +class ios_pword_saver +{ +public: + typedef ::std::ios_base state_type; + typedef int index_type; + typedef void * aspect_type; + + explicit ios_pword_saver( state_type &s, index_type i ) + : s_save_( s ), a_save_( s.pword(i) ), i_save_( i ) + {} + ios_pword_saver( state_type &s, index_type i, aspect_type const &a ) + : s_save_( s ), a_save_( s.pword(i) ), i_save_( i ) + { s.pword(i) = a; } + ~ios_pword_saver() + { this->restore(); } + + void restore() + { s_save_.pword( i_save_ ) = a_save_; } + +private: + state_type & s_save_; + aspect_type const a_save_; + index_type const i_save_; + + ios_pword_saver operator=(const ios_pword_saver&); +}; + + +// Combined stream state saver class (template) declarations ---------------// + +class ios_base_all_saver +{ +public: + typedef ::std::ios_base state_type; + + explicit ios_base_all_saver( state_type &s ) + : s_save_( s ), a1_save_( s.flags() ), a2_save_( s.precision() ) + , a3_save_( s.width() ) + {} + + ~ios_base_all_saver() + { this->restore(); } + + void restore() + { + s_save_.width( a3_save_ ); + s_save_.precision( a2_save_ ); + s_save_.flags( a1_save_ ); + } + +private: + state_type & s_save_; + state_type::fmtflags const a1_save_; + ::std::streamsize const a2_save_; + ::std::streamsize const a3_save_; + + ios_base_all_saver& operator=(const ios_base_all_saver&); +}; + +template < typename Ch, class Tr > +class basic_ios_all_saver +{ +public: + typedef ::std::basic_ios state_type; + + explicit basic_ios_all_saver( state_type &s ) + : s_save_( s ), a1_save_( s.flags() ), a2_save_( s.precision() ) + , a3_save_( s.width() ), a4_save_( s.rdstate() ) + , a5_save_( s.exceptions() ), a6_save_( s.tie() ) + , a7_save_( s.rdbuf() ), a8_save_( s.fill() ) + #ifndef BOOST_NO_STD_LOCALE + , a9_save_( s.getloc() ) + #endif + {} + + ~basic_ios_all_saver() + { this->restore(); } + + void restore() + { + #ifndef BOOST_NO_STD_LOCALE + s_save_.imbue( a9_save_ ); + #endif + s_save_.fill( a8_save_ ); + s_save_.rdbuf( a7_save_ ); + s_save_.tie( a6_save_ ); + s_save_.exceptions( a5_save_ ); + s_save_.clear( a4_save_ ); + s_save_.width( a3_save_ ); + s_save_.precision( a2_save_ ); + s_save_.flags( a1_save_ ); + } + +private: + state_type & s_save_; + typename state_type::fmtflags const a1_save_; + ::std::streamsize const a2_save_; + ::std::streamsize const a3_save_; + typename state_type::iostate const a4_save_; + typename state_type::iostate const a5_save_; + ::std::basic_ostream * const a6_save_; + ::std::basic_streambuf * const a7_save_; + typename state_type::char_type const a8_save_; + #ifndef BOOST_NO_STD_LOCALE + ::std::locale const a9_save_; + #endif +}; + +class ios_all_word_saver +{ +public: + typedef ::std::ios_base state_type; + typedef int index_type; + + ios_all_word_saver( state_type &s, index_type i ) + : s_save_( s ), i_save_( i ), a1_save_( s.iword(i) ) + , a2_save_( s.pword(i) ) + {} + + ~ios_all_word_saver() + { this->restore(); } + + void restore() + { + s_save_.pword( i_save_ ) = a2_save_; + s_save_.iword( i_save_ ) = a1_save_; + } + +private: + state_type & s_save_; + index_type const i_save_; + long const a1_save_; + void * const a2_save_; + + ios_all_word_saver& operator=(const ios_all_word_saver&); +}; + + +} // namespace io +} // namespace boost + + +#endif // BOOST_IO_IOS_STATE_HPP diff --git a/win32/include/boost/io_fwd.hpp b/win32/include/boost/io_fwd.hpp new file mode 100755 index 000000000..0ed46ea10 --- /dev/null +++ b/win32/include/boost/io_fwd.hpp @@ -0,0 +1,67 @@ +// Boost io_fwd.hpp header file --------------------------------------------// + +// Copyright 2002 Daryle Walker. Use, modification, and distribution are subject +// to the Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or a copy at .) + +// See for the library's home page. + +#ifndef BOOST_IO_FWD_HPP +#define BOOST_IO_FWD_HPP + +#include // for std::char_traits (declaration) + + +namespace boost +{ +namespace io +{ + + +// From -------------------------------------------// + +class ios_flags_saver; +class ios_precision_saver; +class ios_width_saver; +class ios_base_all_saver; + +template < typename Ch, class Tr = ::std::char_traits > + class basic_ios_iostate_saver; +template < typename Ch, class Tr = ::std::char_traits > + class basic_ios_exception_saver; +template < typename Ch, class Tr = ::std::char_traits > + class basic_ios_tie_saver; +template < typename Ch, class Tr = ::std::char_traits > + class basic_ios_rdbuf_saver; +template < typename Ch, class Tr = ::std::char_traits > + class basic_ios_fill_saver; +template < typename Ch, class Tr = ::std::char_traits > + class basic_ios_locale_saver; +template < typename Ch, class Tr = ::std::char_traits > + class basic_ios_all_saver; + +typedef basic_ios_iostate_saver ios_iostate_saver; +typedef basic_ios_iostate_saver wios_iostate_saver; +typedef basic_ios_exception_saver ios_exception_saver; +typedef basic_ios_exception_saver wios_exception_saver; +typedef basic_ios_tie_saver ios_tie_saver; +typedef basic_ios_tie_saver wios_tie_saver; +typedef basic_ios_rdbuf_saver ios_rdbuf_saver; +typedef basic_ios_rdbuf_saver wios_rdbuf_saver; +typedef basic_ios_fill_saver ios_fill_saver; +typedef basic_ios_fill_saver wios_fill_saver; +typedef basic_ios_locale_saver ios_locale_saver; +typedef basic_ios_locale_saver wios_locale_saver; +typedef basic_ios_all_saver ios_all_saver; +typedef basic_ios_all_saver wios_all_saver; + +class ios_iword_saver; +class ios_pword_saver; +class ios_all_word_saver; + + +} // namespace io +} // namespace boost + + +#endif // BOOST_IO_FWD_HPP diff --git a/win32/include/boost/iostreams/categories.hpp b/win32/include/boost/iostreams/categories.hpp new file mode 100755 index 000000000..2c8b83b4a --- /dev/null +++ b/win32/include/boost/iostreams/categories.hpp @@ -0,0 +1,175 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains category and mode tags for classifying filters, devices and +// standard stream and stream buffers types. + +#ifndef BOOST_IOSTREAMS_CATEGORIES_HPP_INCLUDED +#define BOOST_IOSTREAMS_CATEGORIES_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +namespace boost { namespace iostreams { + +//------------------Tags for dispatch according to i/o mode-------------------// + +struct any_tag { }; +namespace detail { struct two_sequence : virtual any_tag { }; } +namespace detail { struct random_access : virtual any_tag { }; } +namespace detail { struct one_head : virtual any_tag { }; } +namespace detail { struct two_head : virtual any_tag { }; } +struct input : virtual any_tag { }; +struct output : virtual any_tag { }; +struct bidirectional : virtual input, virtual output, detail::two_sequence { }; +struct dual_use : virtual input, virtual output { }; // Pseudo-mode. +struct input_seekable : virtual input, virtual detail::random_access { }; +struct output_seekable : virtual output, virtual detail::random_access { }; +struct seekable + : virtual input_seekable, + virtual output_seekable, + detail::one_head + { }; +struct dual_seekable + : virtual input_seekable, + virtual output_seekable, + detail::two_head + { }; +struct bidirectional_seekable + : input_seekable, output_seekable, + bidirectional, detail::two_head + { }; + +//------------------Tags for use as i/o categories----------------------------// + +struct device_tag : virtual any_tag { }; +struct filter_tag : virtual any_tag { }; + + // + // Tags for optional behavior. + // + +struct peekable_tag : virtual any_tag { }; // Devices. +struct closable_tag : virtual any_tag { }; +struct flushable_tag : virtual any_tag { }; +struct localizable_tag : virtual any_tag { }; +struct optimally_buffered_tag : virtual any_tag { }; +struct direct_tag : virtual any_tag { }; // Devices. +struct multichar_tag : virtual any_tag { }; // Filters. + +struct source_tag : device_tag, input { }; +struct sink_tag : device_tag, output { }; +struct bidirectional_device_tag : device_tag, bidirectional { }; +struct seekable_device_tag : virtual device_tag, seekable { }; + +struct input_filter_tag : filter_tag, input { }; +struct output_filter_tag : filter_tag, output { }; +struct bidirectional_filter_tag : filter_tag, bidirectional { }; +struct seekable_filter_tag : filter_tag, seekable { }; +struct dual_use_filter_tag : filter_tag, dual_use { }; + +struct multichar_input_filter_tag + : multichar_tag, + input_filter_tag + { }; +struct multichar_output_filter_tag + : multichar_tag, + output_filter_tag + { }; +struct multichar_bidirectional_filter_tag + : multichar_tag, + bidirectional_filter_tag + { }; +struct multichar_seekable_filter_tag + : multichar_tag, + seekable_filter_tag + { }; +struct multichar_dual_use_filter_tag + : filter_tag, + dual_use + { }; + + // + // Tags for standard streams and streambufs. + // + +struct std_io_tag : virtual localizable_tag { }; +struct istream_tag + : virtual device_tag, + virtual peekable_tag, + virtual std_io_tag + { }; +struct ostream_tag + : virtual device_tag, + virtual std_io_tag + { }; +struct iostream_tag + : istream_tag, + ostream_tag + { }; +struct streambuf_tag + : device_tag, + peekable_tag, + std_io_tag + { }; +struct ifstream_tag + : input_seekable, + closable_tag, + istream_tag + { }; +struct ofstream_tag + : output_seekable, + closable_tag, + ostream_tag + { }; +struct fstream_tag + : seekable, + closable_tag, + iostream_tag + { }; +struct filebuf_tag + : seekable, + closable_tag, + streambuf_tag + { }; +struct istringstream_tag + : input_seekable, + istream_tag + { }; +struct ostringstream_tag + : output_seekable, + ostream_tag + { }; +struct stringstream_tag + : dual_seekable, + iostream_tag + { }; +struct stringbuf_tag + : dual_seekable, + streambuf_tag + { }; +struct generic_istream_tag + : input_seekable, + istream_tag + { }; +struct generic_ostream_tag + : output_seekable, + ostream_tag + { }; +struct generic_iostream_tag + : seekable, + iostream_tag + { }; +struct generic_streambuf_tag + : seekable, + streambuf_tag + { }; + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_CATEGORIES_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/chain.hpp b/win32/include/boost/iostreams/chain.hpp new file mode 100755 index 000000000..d96dab747 --- /dev/null +++ b/win32/include/boost/iostreams/chain.hpp @@ -0,0 +1,585 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include // unary_function. +#include // advance. +#include +#include // allocator, auto_ptr. +#include +#include // logic_error, out_of_range. +#include +#include // BOOST_MSVC, template friends, +#include // BOOST_NESTED_TEMPLATE +#include +#include +#include +#include +#include // pubsync. +#include +#include +#include +#include // is_filter. +#include +#include +#include +#include +#include +#include +#include // VC6.5 requires this +#if BOOST_WORKAROUND(BOOST_MSVC, < 1310) // #include order +# include +#endif + +// Sometimes type_info objects must be compared by name. Borrowed from +// Boost.Python and Boost.Function. +#if (defined(__GNUC__) && __GNUC__ >= 3) || \ + defined(_AIX) || \ + (defined(__sgi) && defined(__host_mips)) || \ + (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC)) \ + /**/ +# include +# define BOOST_IOSTREAMS_COMPARE_TYPE_ID(X,Y) \ + (std::strcmp((X).name(),(Y).name()) == 0) +#else +# define BOOST_IOSTREAMS_COMPARE_TYPE_ID(X,Y) ((X)==(Y)) +#endif + +// Deprecated +#define BOOST_IOSTREAMS_COMPONENT_TYPE(chain, index) \ + chain.component_type( index ) \ + /**/ + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) +# define BOOST_IOSTREAMS_COMPONENT(chain, index, target) \ + chain.component< target >( index ) \ + /**/ +#else +# define BOOST_IOSTREAMS_COMPONENT(chain, index, target) \ + chain.component( index, ::boost::type< target >() ) \ + /**/ +#endif + +namespace boost { namespace iostreams { + +//--------------Definition of chain and wchain--------------------------------// + +namespace detail { + +template class chain_client; + +// +// Concept name: Chain. +// Description: Represents a chain of stream buffers which provides access +// to the first buffer in the chain and send notifications when the +// streambufs are added to or removed from chain. +// Refines: Closable device with mode equal to typename Chain::mode. +// Models: chain, converting_chain. +// Example: +// +// class chain { +// public: +// typedef xxx chain_type; +// typedef xxx client_type; +// typedef xxx mode; +// bool is_complete() const; // Ready for i/o. +// template +// void push( const T& t, // Adds a stream buffer to +// streamsize, // chain, based on t, with +// streamsize ); // given buffer and putback +// // buffer sizes. Pass -1 to +// // request default size. +// protected: +// void register_client(client_type* client); // Associate client. +// void notify(); // Notify client. +// }; +// + +// +// Description: Represents a chain of filters with an optional device at the +// end. +// Template parameters: +// Self - A class deriving from the current instantiation of this template. +// This is an example of the Curiously Recurring Template Pattern. +// Ch - The character type. +// Tr - The character traits type. +// Alloc - The allocator type. +// Mode - A mode tag. +// +template +class chain_base { +public: + typedef Ch char_type; + BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr) + typedef Alloc allocator_type; + typedef Mode mode; + struct category + : Mode, + device_tag + { }; + typedef chain_client client_type; + friend class chain_client; +private: + typedef linked_streambuf streambuf_type; + typedef std::list list_type; + typedef chain_base my_type; +protected: + chain_base() : pimpl_(new chain_impl) { } + chain_base(const chain_base& rhs): pimpl_(rhs.pimpl_) { } +public: + + //----------Buffer sizing-------------------------------------------------// + + // Sets the size of the buffer created for the devices to be added to this + // chain. Does not affect the size of the buffer for devices already + // added. + void set_device_buffer_size(int n) { pimpl_->device_buffer_size_ = n; } + + // Sets the size of the buffer created for the filters to be added + // to this chain. Does not affect the size of the buffer for filters already + // added. + void set_filter_buffer_size(int n) { pimpl_->filter_buffer_size_ = n; } + + // Sets the size of the putback buffer for filters and devices to be added + // to this chain. Does not affect the size of the buffer for filters or + // devices already added. + void set_pback_size(int n) { pimpl_->pback_size_ = n; } + + //----------Device interface----------------------------------------------// + + std::streamsize read(char_type* s, std::streamsize n); + std::streamsize write(const char_type* s, std::streamsize n); + std::streampos seek(stream_offset off, BOOST_IOS::seekdir way); + + //----------Direct component access---------------------------------------// + + const std::type_info& component_type(int n) const + { + if (static_cast(n) >= size()) + throw std::out_of_range("bad chain offset"); + return (*boost::next(list().begin(), n))->component_type(); + } + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) + // Deprecated. + template + const std::type_info& component_type() const { return component_type(N); } + + template + T* component(int n) const { return component(n, boost::type()); } + + // Deprecated. + template + T* component() const { return component(N); } +#endif + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) + private: +#endif + template + T* component(int n, boost::type) const + { + if (static_cast(n) >= size()) + throw std::out_of_range("bad chain offset"); + streambuf_type* link = *boost::next(list().begin(), n); + if (BOOST_IOSTREAMS_COMPARE_TYPE_ID(link->component_type(), typeid(T))) + return static_cast(link->component_impl()); + else + return 0; + } +public: + + //----------Container-like interface--------------------------------------// + + typedef typename list_type::size_type size_type; + streambuf_type& front() { return *list().front(); } + BOOST_IOSTREAMS_DEFINE_PUSH(push, mode, char_type, push_impl) + void pop(); + bool empty() const { return list().empty(); } + size_type size() const { return list().size(); } + void reset(); + + //----------Additional i/o functions--------------------------------------// + + // Returns true if this chain is non-empty and its final link + // is a source or sink, i.e., if it is ready to perform i/o. + bool is_complete() const; + bool auto_close() const; + void set_auto_close(bool close); + bool sync() { return front().BOOST_IOSTREAMS_PUBSYNC() != -1; } + bool strict_sync(); +private: + template + void push_impl(const T& t, int buffer_size = -1, int pback_size = -1) + { + typedef typename iostreams::category_of::type category; + typedef typename unwrap_ios::type policy_type; + typedef stream_buffer< + policy_type, + BOOST_IOSTREAMS_CHAR_TRAITS(char_type), + Alloc, Mode + > streambuf_t; + typedef typename list_type::iterator iterator; + BOOST_STATIC_ASSERT((is_convertible::value)); + if (is_complete()) + throw std::logic_error("chain complete"); + streambuf_type* prev = !empty() ? list().back() : 0; + buffer_size = + buffer_size != -1 ? + buffer_size : + iostreams::optimal_buffer_size(t); + pback_size = + pback_size != -1 ? + pback_size : + pimpl_->pback_size_; + std::auto_ptr + buf(new streambuf_t(t, buffer_size, pback_size)); + list().push_back(buf.get()); + buf.release(); + if (is_device::value) { + pimpl_->flags_ |= f_complete | f_open; + for ( iterator first = list().begin(), + last = list().end(); + first != last; + ++first ) + { + (*first)->set_needs_close(); + } + } + if (prev) prev->set_next(list().back()); + notify(); + } + + list_type& list() { return pimpl_->links_; } + const list_type& list() const { return pimpl_->links_; } + void register_client(client_type* client) { pimpl_->client_ = client; } + void notify() { if (pimpl_->client_) pimpl_->client_->notify(); } + + //----------Nested classes------------------------------------------------// + + static void close(streambuf_type* b, BOOST_IOS::openmode m) + { + if (m == BOOST_IOS::out && is_convertible::value) + b->BOOST_IOSTREAMS_PUBSYNC(); + b->close(m); + } + + static void set_next(streambuf_type* b, streambuf_type* next) + { b->set_next(next); } + + static void set_auto_close(streambuf_type* b, bool close) + { b->set_auto_close(close); } + + struct closer : public std::unary_function { + closer(BOOST_IOS::openmode m) : mode_(m) { } + void operator() (streambuf_type* b) + { + close(b, mode_); + } + BOOST_IOS::openmode mode_; + }; + friend struct closer; + + enum flags { + f_complete = 1, + f_open = 2, + f_auto_close = 4 + }; + + struct chain_impl { + chain_impl() + : client_(0), device_buffer_size_(default_device_buffer_size), + filter_buffer_size_(default_filter_buffer_size), + pback_size_(default_pback_buffer_size), + flags_(f_auto_close) + { } + ~chain_impl() { try { close(); reset(); } catch (...) { } } + void close() + { + if ((flags_ & f_open) != 0) { + flags_ &= ~f_open; + stream_buffer< basic_null_device > null; + if ((flags_ & f_complete) == 0) { + null.open(basic_null_device()); + set_next(links_.back(), &null); + } + links_.front()->BOOST_IOSTREAMS_PUBSYNC(); + try { + boost::iostreams::detail::execute_foreach( + links_.rbegin(), links_.rend(), + closer(BOOST_IOS::in) + ); + } catch (...) { + try { + boost::iostreams::detail::execute_foreach( + links_.begin(), links_.end(), + closer(BOOST_IOS::out) + ); + } catch (...) { } + throw; + } + boost::iostreams::detail::execute_foreach( + links_.begin(), links_.end(), + closer(BOOST_IOS::out) + ); + } + } + void reset() + { + typedef typename list_type::iterator iterator; + for ( iterator first = links_.begin(), + last = links_.end(); + first != last; + ++first ) + { + if ( (flags_ & f_complete) == 0 || + (flags_ & f_auto_close) == 0 ) + { + set_auto_close(*first, false); + } + streambuf_type* buf = 0; + std::swap(buf, *first); + delete buf; + } + links_.clear(); + flags_ &= ~f_complete; + flags_ &= ~f_open; + } + list_type links_; + client_type* client_; + int device_buffer_size_, + filter_buffer_size_, + pback_size_; + int flags_; + }; + friend struct chain_impl; + + //----------Member data---------------------------------------------------// + +private: + shared_ptr pimpl_; +}; + +} // End namespace detail. + +// +// Macro: BOOST_IOSTREAMS_DECL_CHAIN(name, category) +// Description: Defines a template derived from chain_base appropriate for a +// particular i/o category. The template has the following parameters: +// Ch - The character type. +// Tr - The character traits type. +// Alloc - The allocator type. +// Macro parameters: +// name_ - The name of the template to be defined. +// category_ - The i/o category of the template to be defined. +// +#define BOOST_IOSTREAMS_DECL_CHAIN(name_, default_char_) \ + template< typename Mode, typename Ch = default_char_, \ + typename Tr = BOOST_IOSTREAMS_CHAR_TRAITS(Ch), \ + typename Alloc = std::allocator > \ + class name_ : public boost::iostreams::detail::chain_base< \ + name_, \ + Ch, Tr, Alloc, Mode \ + > \ + { \ + public: \ + struct category : device_tag, Mode { }; \ + typedef Mode mode; \ + private: \ + typedef boost::iostreams::detail::chain_base< \ + name_, \ + Ch, Tr, Alloc, Mode \ + > base_type; \ + public: \ + typedef Ch char_type; \ + typedef Tr traits_type; \ + typedef typename traits_type::int_type int_type; \ + typedef typename traits_type::off_type off_type; \ + name_() { } \ + name_(const name_& rhs) { *this = rhs; } \ + name_& operator=(const name_& rhs) \ + { base_type::operator=(rhs); return *this; } \ + }; \ + /**/ +BOOST_IOSTREAMS_DECL_CHAIN(chain, char) +BOOST_IOSTREAMS_DECL_CHAIN(wchain, wchar_t) +#undef BOOST_IOSTREAMS_DECL_CHAIN + +//--------------Definition of chain_client------------------------------------// + +namespace detail { + +// +// Template name: chain_client +// Description: Class whose instances provide access to an underlying chain +// using an interface similar to the chains. +// Subclasses: the various stream and stream buffer templates. +// +template +class chain_client { +public: + typedef Chain chain_type; + typedef typename chain_type::char_type char_type; + typedef typename chain_type::traits_type traits_type; + typedef typename chain_type::size_type size_type; + typedef typename chain_type::mode mode; + + chain_client(chain_type* chn = 0) : chain_(chn ) { } + chain_client(chain_client* client) : chain_(client->chain_) { } + virtual ~chain_client() { } + + const std::type_info& component_type(int n) const + { return chain_->component_type(n); } + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) + // Deprecated. + template + const std::type_info& component_type() const + { return chain_->BOOST_NESTED_TEMPLATE component_type(); } + + template + T* component(int n) const + { return chain_->BOOST_NESTED_TEMPLATE component(n); } + + // Deprecated. + template + T* component() const + { return chain_->BOOST_NESTED_TEMPLATE component(); } +#else + template + T* component(int n, boost::type t) const + { return chain_->component(n, t); } +#endif + + bool is_complete() const { return chain_->is_complete(); } + bool auto_close() const { return chain_->auto_close(); } + void set_auto_close(bool close) { chain_->set_auto_close(close); } + bool strict_sync() { return chain_->strict_sync(); } + void set_device_buffer_size(std::streamsize n) + { chain_->set_device_buffer_size(n); } + void set_filter_buffer_size(std::streamsize n) + { chain_->set_filter_buffer_size(n); } + void set_pback_size(std::streamsize n) { chain_->set_pback_size(n); } + BOOST_IOSTREAMS_DEFINE_PUSH(push, mode, char_type, push_impl) + void pop() { chain_->pop(); } + bool empty() const { return chain_->empty(); } + size_type size() { return chain_->size(); } + void reset() { chain_->reset(); } + + // Returns a copy of the underlying chain. + chain_type filters() { return *chain_; } + chain_type filters() const { return *chain_; } +protected: + template + void push_impl(const T& t BOOST_IOSTREAMS_PUSH_PARAMS()) + { chain_->push(t BOOST_IOSTREAMS_PUSH_ARGS()); } + chain_type& ref() { return *chain_; } + void set_chain(chain_type* c) + { chain_ = c; chain_->register_client(this); } +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && \ + (!BOOST_WORKAROUND(__BORLANDC__, < 0x600)) + template + friend class chain_base; +#else + public: +#endif + virtual void notify() { } +private: + chain_type* chain_; +}; + +//--------------Implementation of chain_base----------------------------------// + +template +inline std::streamsize chain_base::read + (char_type* s, std::streamsize n) +{ return iostreams::read(*list().front(), s, n); } + +template +inline std::streamsize chain_base::write + (const char_type* s, std::streamsize n) +{ return iostreams::write(*list().front(), s, n); } + +template +inline std::streampos chain_base::seek + (stream_offset off, BOOST_IOS::seekdir way) +{ return iostreams::seek(*list().front(), off, way); } + +template +void chain_base::reset() +{ + using namespace std; + pimpl_->close(); + pimpl_->reset(); +} + +template +bool chain_base::is_complete() const +{ + return (pimpl_->flags_ & f_complete) != 0; +} + +template +bool chain_base::auto_close() const +{ + return (pimpl_->flags_ & f_auto_close) != 0; +} + +template +void chain_base::set_auto_close(bool close) +{ + pimpl_->flags_ = + (pimpl_->flags_ & ~f_auto_close) | + (close ? f_auto_close : 0); +} + +template +bool chain_base::strict_sync() +{ + typedef typename list_type::iterator iterator; + bool result = true; + for ( iterator first = list().begin(), + last = list().end(); + first != last; + ++first ) + { + bool s = (*first)->strict_sync(); + result = result && s; + } + return result; +} + +template +void chain_base::pop() +{ + assert(!empty()); + if (auto_close()) + pimpl_->close(); + streambuf_type* buf = 0; + std::swap(buf, list().back()); + buf->set_auto_close(false); + buf->set_next(0); + delete buf; + list().pop_back(); + pimpl_->flags_ &= ~f_complete; + if (auto_close() || list().empty()) + pimpl_->flags_ &= ~f_open; +} + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/char_traits.hpp b/win32/include/boost/iostreams/char_traits.hpp new file mode 100755 index 000000000..107a57606 --- /dev/null +++ b/win32/include/boost/iostreams/char_traits.hpp @@ -0,0 +1,73 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_CHAR_TRAITS_HPP_INCLUDED +#define BOOST_IOSTREAMS_CHAR_TRAITS_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include // EOF. +#include // std::char_traits. +#include +#include +#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS +# include +#endif + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::wint_t; } +#endif + +namespace boost { namespace iostreams { + +// Dinkumware that comes with QNX Momentics 6.3.0, 4.0.2, incorrectly defines +// the EOF and WEOF macros to not std:: qualify the wint_t type (and so does +// Sun C++ 5.8 + STLport 4). Fix by placing the def in this scope. +// NOTE: Use BOOST_WORKAROUND? +#if (defined(__QNX__) && defined(BOOST_DINKUMWARE_STDLIB)) \ + || defined(__SUNPRO_CC) +using ::std::wint_t; +#endif + +const int WOULD_BLOCK = (int) (EOF - 1); + +#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS +const std::wint_t WWOULD_BLOCK = (std::wint_t) (WEOF - 1); +#endif + +template +struct char_traits; + +template<> +struct char_traits : BOOST_IOSTREAMS_CHAR_TRAITS(char) { + static char newline() { return '\n'; } + static int good() { return '\n'; } + static int would_block() { return WOULD_BLOCK; } + static bool is_good(int c) { return c != EOF && c != WOULD_BLOCK; } + static bool is_eof(int c) { return c == EOF; } + static bool would_block(int c) { return c == WOULD_BLOCK; } +}; + +#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS +template<> +struct char_traits : std::char_traits { + static wchar_t newline() { return L'\n'; } + static std::wint_t good() { return L'\n'; } + static std::wint_t would_block() { return WWOULD_BLOCK; } + static bool is_good(std::wint_t c) { return c != WEOF && c != WWOULD_BLOCK; } + static bool is_eof(std::wint_t c) { return c == WEOF; } + static bool would_block(std::wint_t c) { return c == WWOULD_BLOCK; } +}; +#endif + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_CHAR_TRAITS_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/checked_operations.hpp b/win32/include/boost/iostreams/checked_operations.hpp new file mode 100755 index 000000000..2d26fe2a5 --- /dev/null +++ b/win32/include/boost/iostreams/checked_operations.hpp @@ -0,0 +1,151 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains implementations of get, read, put, write and seek which +// check a device's mode at runtime instead of compile time. + +#ifndef BOOST_IOSTREAMS_DETAIL_CHECKED_OPERATIONS_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CHECKED_OPERATIONS_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Must come last. +#include // MSVC. + +namespace boost { namespace iostreams { + +namespace detail { + +template +struct read_write_if_impl; + +template +struct seek_if_impl; + +} // End namespace detail. + +template +typename int_type_of::type get_if(T& t) +{ + typedef typename detail::dispatch::type tag; + return detail::read_write_if_impl::get(t); +} + +template +inline std::streamsize +read_if(T& t, typename char_type_of::type* s, std::streamsize n) +{ + typedef typename detail::dispatch::type tag; + return detail::read_write_if_impl::read(t, s, n); +} + +template +bool put_if(T& t, typename char_type_of::type c) +{ + typedef typename detail::dispatch::type tag; + return detail::read_write_if_impl::put(t, c); +} + +template +inline std::streamsize write_if + (T& t, const typename char_type_of::type* s, std::streamsize n) +{ + typedef typename detail::dispatch::type tag; + return detail::read_write_if_impl::write(t, s, n); +} + +template +inline std::streampos +seek_if( T& t, stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which = BOOST_IOS::in | BOOST_IOS::out ) +{ + using namespace detail; + typedef typename dispatch::type tag; + return seek_if_impl::seek(t, off, way, which); +} + +namespace detail { + +//------------------Specializations of read_write_if_impl---------------------// + +template<> +struct read_write_if_impl { + template + static typename int_type_of::type get(T& t) + { return iostreams::get(t); } + + template + static std::streamsize + read(T& t, typename char_type_of::type* s, std::streamsize n) + { return iostreams::read(t, s, n); } + + template + static bool put(T&, typename char_type_of::type) + { throw cant_write(); } + + template + static std::streamsize + write(T&, const typename char_type_of::type*, std::streamsize) + { throw cant_write(); } +}; + +template<> +struct read_write_if_impl { + template + static typename int_type_of::type get(T&) + { throw cant_read(); } + + template + static std::streamsize + read(T&, typename char_type_of::type*, std::streamsize) + { throw cant_read(); } + + template + static bool put(T& t, typename char_type_of::type c) + { return iostreams::put(t, c); } + + template + static std::streamsize + write( T& t, const typename char_type_of::type* s, + std::streamsize n ) + { return iostreams::write(t, s, n); } +}; + +//------------------Specializations of seek_if_impl---------------------------// + +template<> +struct seek_if_impl { + template + static std::streampos + seek( T& t, stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which ) + { return iostreams::seek(t, off, way, which); } +}; + +template<> +struct seek_if_impl { + template + static std::streampos + seek(T&, stream_offset, BOOST_IOS::seekdir, BOOST_IOS::openmode) + { throw cant_seek(); } +}; + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#include // MSVC. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CHECKED_OPERATIONS_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/close.hpp b/win32/include/boost/iostreams/close.hpp new file mode 100755 index 000000000..e77893201 --- /dev/null +++ b/win32/include/boost/iostreams/close.hpp @@ -0,0 +1,260 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_CLOSE_HPP_INCLUDED +#define BOOST_IOSTREAMS_CLOSE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // DEDUCED_TYPENAME, MSVC. +#include +#include +#include +#include +#include // BOOST_IOS +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Must come last. +#include + +namespace boost { namespace iostreams { + +template +void close(T& t); + +template +void close(T& t, BOOST_IOS::openmode which); + +template +void close(T& t, Sink& snk, BOOST_IOS::openmode which); + +namespace detail { + +template +void close_all(T& t) +{ + try { + boost::iostreams::close(t, BOOST_IOS::in); + } catch (...) { + try { + boost::iostreams::close(t, BOOST_IOS::out); + } catch (...) { } + throw; + } + boost::iostreams::close(t, BOOST_IOS::out); +} + +template +void close_all(T& t, Sink& snk) +{ + try { + boost::iostreams::close(t, snk, BOOST_IOS::in); + } catch (...) { + try { + boost::iostreams::close(t, snk, BOOST_IOS::out); + } catch (...) { } + throw; + } + boost::iostreams::close(t, snk, BOOST_IOS::out); +} + +} // End namespaces detail. + +} } // End namespaces iostreams, boost. + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //-----------------------------------// +# include +#else // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //--------------------------// + +namespace boost { namespace iostreams { + +namespace detail { + +template +struct close_impl; + +} // End namespace detail. + +template +void close(T& t) { detail::close_all(t); } + +template +void close(T& t, BOOST_IOS::openmode which) +{ +#ifdef BOOST_IOSTREAMS_STRICT + assert(which == BOOST_IOS::in || which == BOOST_IOS::out); +#else + if (which == (BOOST_IOS::in | BOOST_IOS::out)) { + detail::close_all(t); + return; + } +#endif + detail::close_impl::close(detail::unwrap(t), which); +} + +template +void close(T& t, Sink& snk, BOOST_IOS::openmode which) +{ +#ifdef BOOST_IOSTREAMS_STRICT + assert(which == BOOST_IOS::in || which == BOOST_IOS::out); +#else + if (which == (BOOST_IOS::in | BOOST_IOS::out)) { + detail::close_all(t, snk); + return; + } +#endif + detail::close_impl::close(detail::unwrap(t), snk, which); +} + +namespace detail { + +//------------------Definition of close_impl----------------------------------// + +struct close_boost_stream { }; +struct close_filtering_stream { }; + +template +struct close_tag { + typedef typename category_of::type category; + typedef typename detail::unwrapped_type::type unwrapped; + typedef typename + iostreams::select< + mpl::not_< is_convertible >, + any_tag, + mpl::or_< + is_boost_stream, + is_boost_stream_buffer + >, + close_boost_stream, + mpl::or_< + is_filtering_stream, + is_filtering_streambuf + >, + close_filtering_stream, + mpl::or_< + is_convertible, + is_convertible + >, + two_sequence, + else_, + closable_tag + >::type type; +}; + +template +struct close_impl + : mpl::if_< + is_custom, + operations, + close_impl::type> + >::type + { }; + +template<> +struct close_impl { + template + static void close(T& t, BOOST_IOS::openmode which) + { + if (which == BOOST_IOS::out) + iostreams::flush(t); + } + + template + static void close(T& t, Sink& snk, BOOST_IOS::openmode which) + { + if (which == BOOST_IOS::out) { + non_blocking_adapter nb(snk); + iostreams::flush(t, nb); + } + } +}; + +template<> +struct close_impl { + template + static void close(T& t) + { + t.close(); + } + template + static void close(T& t, BOOST_IOS::openmode which) + { + if (which == BOOST_IOS::out) + t.close(); + } +}; + +template<> +struct close_impl { + template + static void close(T& t, BOOST_IOS::openmode which) + { + typedef typename category_of::type category; + const bool in = is_convertible::value && + !is_convertible::value; + if (in == (which == BOOST_IOS::in) && t.is_complete()) + t.pop(); + } +}; + +#include // Borland. +template<> +struct close_impl { + template + static void close(T& t, BOOST_IOS::openmode which) + { + typedef typename category_of::type category; + const bool in = is_convertible::value && + !is_convertible::value; + if (in == (which == BOOST_IOS::in)) + t.close(); + } + template + static void close(T& t, Sink& snk, BOOST_IOS::openmode which) + { + typedef typename category_of::type category; + const bool in = is_convertible::value && + !is_convertible::value; + if (in == (which == BOOST_IOS::in)) { + non_blocking_adapter nb(snk); + t.close(nb); + } + } +}; + +template<> +struct close_impl { + template + static void close(T& t, BOOST_IOS::openmode which) { t.close(which); } + template + static void close(T& t, Sink& snk, BOOST_IOS::openmode which) + { + non_blocking_adapter nb(snk); + t.close(nb, which); + } +}; + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#endif // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //-------------------------// + +#include + +#endif // #ifndef BOOST_IOSTREAMS_CLOSE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/code_converter.hpp b/win32/include/boost/iostreams/code_converter.hpp new file mode 100755 index 000000000..a562932f7 --- /dev/null +++ b/win32/include/boost/iostreams/code_converter.hpp @@ -0,0 +1,422 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains machinery for performing code conversion. + +#ifndef BOOST_IOSTREAMS_CODE_CONVERTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_CODE_CONVERTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#if defined(BOOST_IOSTREAMS_NO_WIDE_STREAMS) || \ + defined(BOOST_IOSTREAMS_NO_LOCALE) \ + /**/ +# error code conversion not supported on this platform +#endif + +#include // max. +#include // memcpy. +#include +#include // DEDUCED_TYPENAME, +#include +#include // default_filter_buffer_size. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // failure, openmode, int types. +#include +#include +#include +#include +#include +#include +#include +#include + +// Must come last. +#include // Borland 5.x + +namespace boost { namespace iostreams { + +struct code_conversion_error : BOOST_IOSTREAMS_FAILURE { + code_conversion_error() + : BOOST_IOSTREAMS_FAILURE("code conversion error") + { } +}; + +namespace detail { + +//--------------Definition of strncpy_if_same---------------------------------// + +// Helper template for strncpy_if_same, below. +template +struct strncpy_if_same_impl; + +template<> +struct strncpy_if_same_impl { + template + static Ch* copy(Ch* tgt, const Ch* src, std::streamsize n) + { return BOOST_IOSTREAMS_CHAR_TRAITS(Ch)::copy(tgt, src, n); } +}; + +template<> +struct strncpy_if_same_impl { + template + static Tgt* copy(Tgt* tgt, const Src*, std::streamsize) { return tgt; } +}; + +template +Tgt* strncpy_if_same(Tgt* tgt, const Src* src, std::streamsize n) +{ + typedef strncpy_if_same_impl::value> impl; + return impl::copy(tgt, src, n); +} + +//--------------Definition of conversion_buffer-------------------------------// + +// Buffer and conversion state for reading. +template +class conversion_buffer + : public buffer< + BOOST_DEDUCED_TYPENAME detail::codecvt_extern::type, + Alloc + > +{ +public: + typedef typename Codecvt::state_type state_type; + conversion_buffer() + : buffer< + BOOST_DEDUCED_TYPENAME detail::codecvt_extern::type, + Alloc + >(0) + { + reset(); + } + state_type& state() { return state_; } + void reset() + { + if (this->size()) + this->set(0, 0); + state_ = state_type(); + } +private: + state_type state_; +}; + +//--------------Definition of converter_impl----------------------------------// + +// Contains member data, open/is_open/close and buffer management functions. +template +struct code_converter_impl { + typedef typename codecvt_extern::type extern_type; + typedef typename category_of::type device_category; + typedef is_convertible can_read; + typedef is_convertible can_write; + typedef is_convertible is_bidir; + typedef typename + iostreams::select< // Disambiguation for Tru64. + is_bidir, bidirectional, + can_read, input, + can_write, output + >::type mode; + typedef typename + mpl::if_< + is_direct, + direct_adapter, + Device + >::type policy_type; + typedef optional< concept_adapter > storage_type; + typedef is_convertible is_double; + typedef conversion_buffer buffer_type; + + code_converter_impl() : cvt_(), flags_(0) { } + + ~code_converter_impl() + { + try { + if (flags_ & f_open) close(); + } catch (...) { /* */ } + } + + void open(const Device& dev, int buffer_size) + { + if (flags_ & f_open) + throw BOOST_IOSTREAMS_FAILURE("already open"); + if (buffer_size == -1) + buffer_size = default_filter_buffer_size; + int max_length = cvt_.get().max_length(); + buffer_size = (std::max)(buffer_size, 2 * max_length); + if (can_read::value) { + buf_.first().resize(buffer_size); + buf_.first().set(0, 0); + } + if (can_write::value && !is_double::value) { + buf_.second().resize(buffer_size); + buf_.second().set(0, 0); + } + dev_.reset(concept_adapter(dev)); + flags_ = f_open; + } + + void close() + { + detail::execute_all( + detail::call_member_close(*this, BOOST_IOS::in), + detail::call_member_close(*this, BOOST_IOS::out) + ); + } + + void close(BOOST_IOS::openmode which) + { + if (which == BOOST_IOS::in && (flags_ & f_input_closed) == 0) { + flags_ |= f_input_closed; + iostreams::close(dev(), BOOST_IOS::in); + } + if (which == BOOST_IOS::out && (flags_ & f_output_closed) == 0) { + flags_ |= f_output_closed; + detail::execute_all( + detail::flush_buffer(buf_.second(), dev(), can_write::value), + detail::call_close(dev(), BOOST_IOS::out), + detail::call_reset(dev_), + detail::call_reset(buf_.first()), + detail::call_reset(buf_.second()) + ); + } + } + + bool is_open() const { return (flags_ & f_open) != 0;} + + policy_type& dev() { return **dev_; } + + enum flag_type { + f_open = 1, + f_input_closed = f_open << 1, + f_output_closed = f_input_closed << 1 + }; + + codecvt_holder cvt_; + storage_type dev_; + double_object< + buffer_type, + is_double + > buf_; + int flags_; +}; + +} // End namespace detail. + +//--------------Definition of converter---------------------------------------// + +#define BOOST_IOSTREAMS_CONVERTER_PARAMS() , int buffer_size = -1 +#define BOOST_IOSTREAMS_CONVERTER_ARGS() , buffer_size + +template +struct code_converter_base { + typedef detail::code_converter_impl< + Device, Codecvt, Alloc + > impl_type; + code_converter_base() : pimpl_(new impl_type) { } + shared_ptr pimpl_; +}; + +template< typename Device, + typename Codecvt = detail::default_codecvt, + typename Alloc = std::allocator > +class code_converter + : protected code_converter_base +{ +private: + typedef detail::code_converter_impl< + Device, Codecvt, Alloc + > impl_type; + typedef typename impl_type::policy_type policy_type; + typedef typename impl_type::buffer_type buffer_type; + typedef typename detail::codecvt_holder::codecvt_type codecvt_type; + typedef typename detail::codecvt_intern::type intern_type; + typedef typename detail::codecvt_extern::type extern_type; + typedef typename detail::codecvt_state::type state_type; +public: + typedef intern_type char_type; + struct category + : impl_type::mode, device_tag, closable_tag, localizable_tag + { }; + BOOST_STATIC_ASSERT(( + is_same< + extern_type, + BOOST_DEDUCED_TYPENAME char_type_of::type + >::value + )); +public: + code_converter() { } +#if BOOST_WORKAROUND(__GNUC__, < 3) + code_converter(code_converter& rhs) + : code_converter_base(rhs) + { } + code_converter(const code_converter& rhs) + : code_converter_base(rhs) + { } +#endif + BOOST_IOSTREAMS_FORWARD( code_converter, open_impl, Device, + BOOST_IOSTREAMS_CONVERTER_PARAMS, + BOOST_IOSTREAMS_CONVERTER_ARGS ) + + // fstream-like interface. + + bool is_open() const { return this->pimpl_->is_open(); } + void close(BOOST_IOS::openmode which = BOOST_IOS::in | BOOST_IOS::out ) + { impl().close(which); } + + // Device interface. + + std::streamsize read(char_type*, std::streamsize); + std::streamsize write(const char_type*, std::streamsize); + void imbue(const std::locale& loc) { impl().cvt_.imbue(loc); } + + // Direct device access. + + Device& operator*() { return detail::unwrap_direct(dev()); } + Device* operator->() { return &detail::unwrap_direct(dev()); } +private: + template // Used for forwarding. + void open_impl(const T& t BOOST_IOSTREAMS_CONVERTER_PARAMS()) + { + impl().open(t BOOST_IOSTREAMS_CONVERTER_ARGS()); + } + + const codecvt_type& cvt() { return impl().cvt_.get(); } + policy_type& dev() { return impl().dev(); } + buffer_type& in() { return impl().buf_.first(); } + buffer_type& out() { return impl().buf_.second(); } + impl_type& impl() { return *this->pimpl_; } +}; + +//--------------Implementation of converter-----------------------------------// + +// Implementation note: if end of stream contains a partial character, +// it is ignored. +template +std::streamsize code_converter::read + (char_type* s, std::streamsize n) +{ + const extern_type* next; // Next external char. + intern_type* nint; // Next internal char. + std::streamsize total = 0; // Characters read. + int status = iostreams::char_traits::good(); + bool partial = false; + buffer_type& buf = in(); + + do { + + // Fill buffer. + if (buf.ptr() == buf.eptr() || partial) { + status = buf.fill(dev()); + if (buf.ptr() == buf.eptr()) + break; + partial = false; + } + + // Convert. + std::codecvt_base::result result = + cvt().in( buf.state(), + buf.ptr(), buf.eptr(), next, + s + total, s + n, nint ); + buf.ptr() += next - buf.ptr(); + total = static_cast(nint - s); + + switch (result) { + case std::codecvt_base::partial: + partial = true; + break; + case std::codecvt_base::ok: + break; + case std::codecvt_base::noconv: + { + std::streamsize amt = + std::min(next - buf.ptr(), n - total); + detail::strncpy_if_same(s + total, buf.ptr(), amt); + total += amt; + } + break; + case std::codecvt_base::error: + default: + buf.state() = state_type(); + throw code_conversion_error(); + } + + } while (total < n && status != EOF && status != WOULD_BLOCK); + + return total == 0 && status == EOF ? -1 : total; +} + +template +std::streamsize code_converter::write + (const char_type* s, std::streamsize n) +{ + buffer_type& buf = out(); + extern_type* next; // Next external char. + const intern_type* nint; // Next internal char. + std::streamsize total = 0; // Characters written. + bool partial = false; + + while (total < n) { + + // Empty buffer. + if (buf.eptr() == buf.end() || partial) { + if (!buf.flush(dev())) + break; + partial = false; + } + + // Convert. + std::codecvt_base::result result = + cvt().out( buf.state(), + s + total, s + n, nint, + buf.eptr(), buf.end(), next ); + int progress = (int) (next - buf.eptr()); + buf.eptr() += progress; + + switch (result) { + case std::codecvt_base::partial: + partial = true; // Fall through. + case std::codecvt_base::ok: + total = static_cast(nint - s); + break; + case std::codecvt_base::noconv: + { + std::streamsize amt = + std::min( nint - total - s, + buf.end() - buf.eptr() ); + detail::strncpy_if_same(buf.eptr(), s + total, amt); + total += amt; + } + break; + case std::codecvt_base::error: + default: + buf.state() = state_type(); + throw code_conversion_error(); + } + } + return total; +} + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#include // Borland 5.x + +#endif // #ifndef BOOST_IOSTREAMS_CODE_CONVERTER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/combine.hpp b/win32/include/boost/iostreams/combine.hpp new file mode 100755 index 000000000..c82c5c296 --- /dev/null +++ b/win32/include/boost/iostreams/combine.hpp @@ -0,0 +1,249 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// To do: add support for random-access. + +#ifndef BOOST_IOSTREAMS_COMBINE_HPP_INCLUDED +#define BOOST_IOSTREAMS_COMBINE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // NO_STD_LOCALE, DEDUCED_TYPENAME. +#ifndef BOOST_NO_STD_LOCALE +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +// Must come last. +#include + +namespace boost { namespace iostreams { + +namespace detail { + +// +// Template name: combined_device. +// Description: Model of Device defined in terms of a Source/Sink pair. +// Template paramters: +// Source - A model of Source, with the same char_type and traits_type +// as Sink. +// Sink - A model of Sink, with the same char_type and traits_type +// as Source. +// +template +class combined_device { +public: + typedef typename char_type_of::type char_type; + struct category + : bidirectional, + device_tag, + closable_tag, + localizable_tag + { }; + combined_device(const Source& src, const Sink& snk); + std::streamsize read(char_type* s, std::streamsize n); + std::streamsize write(const char_type* s, std::streamsize n); + void close(BOOST_IOS::openmode); + #ifndef BOOST_NO_STD_LOCALE + void imbue(const std::locale& loc); + #endif +private: + typedef typename char_type_of::type sink_char_type; + BOOST_STATIC_ASSERT((is_same::value)); + Source src_; + Sink sink_; +}; + +// +// Template name: combined_filter. +// Description: Model of Device defined in terms of a Source/Sink pair. +// Template paramters: +// InputFilter - A model of InputFilter, with the same char_type as +// OutputFilter. +// OutputFilter - A model of OutputFilter, with the same char_type as +// InputFilter. +// +template +class combined_filter { +private: + typedef typename category_of::type in_category; + typedef typename category_of::type out_category; +public: + typedef typename char_type_of::type char_type; + struct category + : multichar_bidirectional_filter_tag, + closable_tag, + localizable_tag + { }; + combined_filter(const InputFilter& in, const OutputFilter& out); + + template + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { return boost::iostreams::read(in_, src, s, n); } + + template + std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) + { return boost::iostreams::write(out_, snk, s, n); } + + template + void close(Sink& snk, BOOST_IOS::openmode which) + { + if (which == BOOST_IOS::in) { + if (is_convertible::value) { + iostreams::close(in_, snk, BOOST_IOS::in); + } else { + detail::close_all(in_, snk); + } + } + if (which == BOOST_IOS::out) { + if (is_convertible::value) { + iostreams::close(out_, snk, BOOST_IOS::out); + } else { + detail::close_all(out_, snk); + } + } + } + #ifndef BOOST_NO_STD_LOCALE + void imbue(const std::locale& loc); + #endif +private: + typedef typename char_type_of::type output_char_type; + BOOST_STATIC_ASSERT((is_same::value)); + InputFilter in_; + OutputFilter out_; +}; + +template +struct combination_traits + : mpl::if_< + is_device, + combined_device< + typename wrapped_type::type, + typename wrapped_type::type + >, + combined_filter< + typename wrapped_type::type, + typename wrapped_type::type + > + > + { }; + +} // End namespace detail. + +template +struct combination : detail::combination_traits::type { + typedef typename detail::combination_traits::type base_type; + typedef typename detail::wrapped_type::type in_type; + typedef typename detail::wrapped_type::type out_type; + combination(const in_type& in, const out_type& out) + : base_type(in, out) { } +}; + +namespace detail { + +// Workaround for VC6 ETI bug. +template +struct combine_traits { + typedef combination< + BOOST_DEDUCED_TYPENAME detail::unwrapped_type::type, + BOOST_DEDUCED_TYPENAME detail::unwrapped_type::type + > type; +}; + +} // End namespace detail. + +// +// Template name: combine. +// Description: Takes a Source/Sink pair or InputFilter/OutputFilter pair and +// returns a Reource or Filter which performs input using the first member +// of the pair and output using the second member of the pair. +// Template paramters: +// In - A model of Source or InputFilter, with the same char_type as Out. +// Out - A model of Sink or OutputFilter, with the same char_type as In. +// +template +typename detail::combine_traits::type +combine(const In& in, const Out& out) +{ + typedef typename detail::combine_traits::type return_type; + return return_type(in, out); +} + +//----------------------------------------------------------------------------// + +namespace detail { + +//--------------Implementation of combined_device-----------------------------// + +template +inline combined_device::combined_device + (const Source& src, const Sink& snk) + : src_(src), sink_(snk) { } + +template +inline std::streamsize +combined_device::read(char_type* s, std::streamsize n) +{ return iostreams::read(src_, s, n); } + +template +inline std::streamsize +combined_device::write(const char_type* s, std::streamsize n) +{ return iostreams::write(sink_, s, n); } + +template +inline void +combined_device::close(BOOST_IOS::openmode which) +{ + if (which == BOOST_IOS::in) + detail::close_all(src_); + if (which == BOOST_IOS::out) + detail::close_all(sink_); +} + +#ifndef BOOST_NO_STD_LOCALE + template + void combined_device::imbue(const std::locale& loc) + { + iostreams::imbue(src_, loc); + iostreams::imbue(sink_, loc); + } +#endif + +//--------------Implementation of filter_pair---------------------------------// + +template +inline combined_filter::combined_filter + (const InputFilter& in, const OutputFilter& out) : in_(in), out_(out) + { } + +#ifndef BOOST_NO_STD_LOCALE + template + void combined_filter::imbue + (const std::locale& loc) + { + iostreams::imbue(in_, loc); + iostreams::imbue(out_, loc); + } +#endif + + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#include + +#endif // #ifndef BOOST_IOSTREAMS_COMBINE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/compose.hpp b/win32/include/boost/iostreams/compose.hpp new file mode 100755 index 000000000..471ec5317 --- /dev/null +++ b/win32/include/boost/iostreams/compose.hpp @@ -0,0 +1,490 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Note: bidirectional streams are not supported. + +#ifndef BOOST_IOSTREAMS_COMPOSE_HPP_INCLUDED +#define BOOST_IOSTREAMS_COMPOSE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // min. +#include // pair. +#include // DEDUCED_TYPENAME. +#include +#include +#include +#include +#include +#include +#include +#include // mode_of, is_direct. +#include +#include +#include +#include + +// Must come last. +#include // MSVC. + +namespace boost { namespace iostreams { + +namespace detail { + +template< typename First, + typename Second, + typename FirstMode = + BOOST_DEDUCED_TYPENAME mode_of::type, + typename SecondMode = + BOOST_DEDUCED_TYPENAME mode_of::type > +struct composite_mode + : select< + is_convertible, FirstMode, + is_convertible, SecondMode, + is_convertible, input, + else_, output + > + { }; + +// +// Template name: composite_device. +// Description: Provides a Device view of a Filter, Device pair. +// Template paramters: +// Filter - A model of Filter. +// Device - An indirect model of Device. +// +template< typename Filter, + typename Device, + typename Mode = + BOOST_DEDUCED_TYPENAME composite_mode::type > +class composite_device { +private: + typedef typename detail::param_type::type param_type; + typedef typename mode_of::type filter_mode; + typedef typename mode_of::type device_mode; + typedef typename + iostreams::select< // Disambiguation for Tru64. + is_direct, direct_adapter, + is_std_io, Device&, + else_, Device + >::type value_type; +public: + typedef typename char_type_of::type char_type; + struct category + : Mode, + device_tag, + closable_tag, + flushable_tag, + localizable_tag, + optimally_buffered_tag + { }; + composite_device(const Filter& flt, param_type dev); + std::streamsize read(char_type* s, std::streamsize n); + std::streamsize write(const char_type* s, std::streamsize n); + std::streampos seek( stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which = + BOOST_IOS::in | BOOST_IOS::out ); + + void close(); + void close(BOOST_IOS::openmode which); + bool flush(); + std::streamsize optimal_buffer_size() const; + + template // Avoid dependency on + void imbue(const Locale& loc) + { + iostreams::imbue(filter_, loc); + iostreams::imbue(device_, loc); + } + + Filter& first() { return filter_; } + Device& second() { return device_; } +private: + Filter filter_; + value_type device_; +}; + +// +// Template name: composite_device. +// Description: Provides a Device view of a Filter, Device pair. +// Template paramters: +// Filter - A model of Filter. +// Device - An indirect model of Device. +// +template< typename Filter1, + typename Filter2, + typename Mode = + BOOST_DEDUCED_TYPENAME composite_mode::type > +class composite_filter { +private: + typedef reference_wrapper filter_ref; + typedef typename mode_of::type first_mode; + typedef typename mode_of::type second_mode; + + // A dual-use filter cannot be composed with a read-write filter + BOOST_STATIC_ASSERT( + !(is_convertible::value) || + !(is_convertible::value) || + !(is_convertible::value) || + (is_convertible::value) + ); + BOOST_STATIC_ASSERT( + !(is_convertible::value) || + !(is_convertible::value) || + !(is_convertible::value) || + (is_convertible::value) + ); +public: + typedef typename char_type_of::type char_type; + struct category + : Mode, + filter_tag, + multichar_tag, + closable_tag, + flushable_tag, + localizable_tag, + optimally_buffered_tag + { }; + composite_filter(const Filter1& filter1, const Filter2& filter2) + : filter1_(filter1), filter2_(filter2) + { } + + template + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { + composite_device cmp(boost::ref(filter2_), src); + return iostreams::read(filter1_, cmp, s, n); + } + + template + std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) + { + composite_device cmp(boost::ref(filter2_), snk); + return iostreams::write(filter1_, cmp, s, n); + } + + template + std::streampos seek( Device& dev, stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which = + BOOST_IOS::in | BOOST_IOS::out ) + { + composite_device cmp(boost::ref(filter2_), dev); + return iostreams::seek(filter1_, cmp, off, way, which); + } + + template + void close(Device& dev) + { + BOOST_STATIC_ASSERT((!is_convertible::value)); + BOOST_STATIC_ASSERT((!is_convertible::value)); + + // Create a new device by composing the second filter2_ with dev. + composite_device cmp(boost::ref(filter2_), dev); + + // Close input sequences in reverse order and output sequences in + // forward order + if (!is_convertible::value) { + detail::execute_all( + detail::call_close(filter2_, dev, BOOST_IOS::in), + detail::call_close(filter1_, cmp, BOOST_IOS::in), + detail::call_close(filter1_, cmp, BOOST_IOS::out), + detail::call_close(filter2_, dev, BOOST_IOS::out) + ); + } else if (is_convertible::value) { + detail::execute_all( + detail::call_close(filter2_, dev, BOOST_IOS::in), + detail::call_close(filter1_, cmp, BOOST_IOS::in) + ); + } else { + detail::execute_all( + detail::call_close(filter1_, cmp, BOOST_IOS::out), + detail::call_close(filter2_, dev, BOOST_IOS::out) + ); + } + } + + template + void close(Device& dev, BOOST_IOS::openmode which) + { + BOOST_STATIC_ASSERT( + (is_convertible::value) || + (is_convertible::value) + ); + + // Create a new device by composing the second filter2_ with dev. + composite_device cmp(boost::ref(filter2_), dev); + + // Close input sequences in reverse order + if ( which == BOOST_IOS::in && + ( !is_convertible::value || + is_convertible::value ) ) + { + detail::execute_all( + detail::call_close(filter2_, dev, BOOST_IOS::in), + detail::call_close(filter1_, cmp, BOOST_IOS::in) + ); + } + + // Close output sequences in forward order + if ( which == BOOST_IOS::out && + ( !is_convertible::value || + is_convertible::value ) ) + { + detail::execute_all( + detail::call_close(filter1_, cmp, BOOST_IOS::out), + detail::call_close(filter2_, dev, BOOST_IOS::out) + ); + } + } + + template + bool flush(Device& dev) + { + composite_device cmp(filter2_, dev); + return iostreams::flush(filter1_, cmp); + } + + std::streamsize optimal_buffer_size() const + { + std::streamsize first = iostreams::optimal_buffer_size(filter1_); + std::streamsize second = iostreams::optimal_buffer_size(filter2_); + return first < second ? second : first; + } + + template // Avoid dependency on + void imbue(const Locale& loc) + { // To do: consider using RAII. + iostreams::imbue(filter1_, loc); + iostreams::imbue(filter2_, loc); + } + + Filter1& first() { return filter1_; } + Filter2& second() { return filter2_; } +private: + Filter1 filter1_; + Filter2 filter2_; +}; + +template +struct composite_traits + : mpl::if_< + is_device, + composite_device, + composite_filter + > + { }; + +} // End namespace detail. + +template +struct composite : detail::composite_traits::type { + typedef typename detail::param_type::type param_type; + typedef typename detail::composite_traits::type base; + composite(const Filter& flt, param_type dev) + : base(flt, dev) + { } +}; + +//--------------Implementation of compose-------------------------------------// + +// Note: The following workarounds are patterned after resolve.hpp. It has not +// yet been confirmed that they are necessary. + +#ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //-------------------------// +# ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //-------------------------------// + +template +composite +compose( const Filter& filter, const FilterOrDevice& fod + BOOST_IOSTREAMS_DISABLE_IF_STREAM(FilterOrDevice) ) +{ return composite(filter, fod); } + +template +composite< Filter, std::basic_streambuf > +compose(const Filter& filter, std::basic_streambuf& sb) +{ return composite< Filter, std::basic_streambuf >(filter, sb); } + +template +composite< Filter, std::basic_istream > +compose(const Filter& filter, std::basic_istream& is) +{ return composite< Filter, std::basic_istream >(filter, is); } + +template +composite< Filter, std::basic_ostream > +compose(const Filter& filter, std::basic_ostream& os) +{ return composite< Filter, std::basic_ostream >(filter, os); } + +template +composite< Filter, std::basic_iostream > +compose(const Filter& filter, std::basic_iostream& io) +{ return composite< Filter, std::basic_iostream >(filter, io); } + +# else // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //---------------------// + +template +composite +compose( const Filter& filter, const FilterOrDevice& fod + BOOST_IOSTREAMS_DISABLE_IF_STREAM(FilterOrDevice) ) +{ return composite(filter, fod); } + +template +composite +compose(const Filter& filter, std::streambuf& sb) +{ return composite(filter, sb); } + +template +composite +compose(const Filter& filter, std::istream& is) +{ return composite(filter, is); } + +template +composite +compose(const Filter& filter, std::ostream& os) +{ return composite(filter, os); } + +template +composite +compose(const Filter& filter, std::iostream& io) +{ return composite(filter, io); } + +# endif // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //--------------------// +#else // #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //----------------// + +template +composite +compose(const Filter& flt, const Stream& strm, mpl::true_) +{ // Bad overload resolution. + return composite(flt, const_cast(strm)); +} + +template +composite +compose(const Filter& flt, const FilterOrDevice& fod, mpl::false_) +{ return composite(flt, fod); } + +template +composite +compose( const Filter& flt, const FilterOrDevice& fod + BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) ) +{ return compose(flt, fod, is_std_io()); } + +# if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) && \ + !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \ + !defined(__GNUC__) // ---------------------------------------------------// + +template +composite +compose (const Filter& filter, FilterOrDevice& fod) +{ return composite(filter, fod); } + +# endif // Borland 5.x, VC6-7.0 or GCC 2.9x //--------------------------------// +#endif // #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //---------------// + +//----------------------------------------------------------------------------// + +namespace detail { + +//--------------Implementation of composite_device---------------------------// + +template +composite_device::composite_device + (const Filter& flt, param_type dev) + : filter_(flt), device_(dev) + { } + +template +inline std::streamsize composite_device::read + (char_type* s, std::streamsize n) +{ return iostreams::read(filter_, device_, s, n); } + +template +inline std::streamsize composite_device::write + (const char_type* s, std::streamsize n) +{ return iostreams::write(filter_, device_, s, n); } + +template +std::streampos composite_device::seek + (stream_offset off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which) +{ return iostreams::seek(filter_, device_, off, way, which); } + +template +void composite_device::close() +{ + BOOST_STATIC_ASSERT((!is_convertible::value)); + BOOST_STATIC_ASSERT( + !(is_convertible::value) || + !(is_convertible::value) || + !(is_convertible::value) + ); + + // Close input sequences in reverse order and output sequences + // in forward order + if (!is_convertible::value) { + detail::execute_all( + detail::call_close(device_, BOOST_IOS::in), + detail::call_close(filter_, device_, BOOST_IOS::in), + detail::call_close(filter_, device_, BOOST_IOS::out), + detail::call_close(device_, BOOST_IOS::out) + ); + } else if (is_convertible::value) { + detail::execute_all( + detail::call_close(device_, BOOST_IOS::in), + detail::call_close(filter_, device_, BOOST_IOS::in) + ); + } else { + detail::execute_all( + detail::call_close(filter_, device_, BOOST_IOS::out), + detail::call_close(device_, BOOST_IOS::out) + ); + } +} + +template +void composite_device::close(BOOST_IOS::openmode which) +{ + BOOST_STATIC_ASSERT((is_convertible::value)); + BOOST_STATIC_ASSERT(!(is_convertible::value)); + + // Close input sequences in reverse order + if (which == BOOST_IOS::in) { + detail::execute_all( + detail::call_close(device_, BOOST_IOS::in), + detail::call_close(filter_, device_, BOOST_IOS::in) + ); + } + + // Close output sequences in forward order + if (which == BOOST_IOS::out) { + detail::execute_all( + detail::call_close(filter_, device_, BOOST_IOS::out), + detail::call_close(device_, BOOST_IOS::out) + ); + } +} + +template +bool composite_device::flush() +{ + bool r1 = iostreams::flush(filter_, device_); + bool r2 = iostreams::flush(device_); + return r1 && r2; +} + +template +std::streamsize +composite_device::optimal_buffer_size() const +{ return iostreams::optimal_buffer_size(device_); } + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#include + +#endif // #ifndef BOOST_IOSTREAMS_COMPOSE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/concepts.hpp b/win32/include/boost/iostreams/concepts.hpp new file mode 100755 index 000000000..1e11929cf --- /dev/null +++ b/win32/include/boost/iostreams/concepts.hpp @@ -0,0 +1,129 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_CONCEPTS_HPP_INCLUDED +#define BOOST_IOSTREAMS_CONCEPTS_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // BOOST_MSVC +#include +#include +#include +#include // openmode. +#include +#include +#include + +namespace boost { namespace iostreams { + +//--------------Definitions of helper templates for device concepts-----------// + +template +struct device { + typedef Ch char_type; + struct category + : Mode, + device_tag, + closable_tag, + localizable_tag + { }; + + void close() + { + using namespace detail; + BOOST_STATIC_ASSERT((!is_convertible::value)); + } + + void close(BOOST_IOS::openmode) + { + using namespace detail; + BOOST_STATIC_ASSERT((is_convertible::value)); + } + + template + void imbue(const Locale&) { } +}; + +template +struct wdevice : device { }; + +typedef device source; +typedef wdevice wsource; +typedef device sink; +typedef wdevice wsink; + +//--------------Definitions of helper templates for simple filter concepts----// + +template +struct filter { + typedef Ch char_type; + struct category + : Mode, + filter_tag, + closable_tag, + localizable_tag + { }; + + template + void close(Device&) + { + using namespace detail; + BOOST_STATIC_ASSERT((!is_convertible::value)); + BOOST_STATIC_ASSERT((!is_convertible::value)); + } + + template + void close(Device&, BOOST_IOS::openmode) + { + using namespace detail; + BOOST_STATIC_ASSERT( + (is_convertible::value) || + (is_convertible::value) + ); + } + + template + void imbue(const Locale&) { } +}; + +template +struct wfilter : filter { }; + +typedef filter input_filter; +typedef wfilter input_wfilter; +typedef filter output_filter; +typedef wfilter output_wfilter; +typedef filter seekable_filter; +typedef wfilter seekable_wfilter; +typedef filter dual_use_filter; +typedef wfilter dual_use_wfilter; + +//------Definitions of helper templates for multi-character filter cncepts----// + +template +struct multichar_filter : filter { + struct category : filter::category, multichar_tag { }; +}; + +template +struct multichar_wfilter : multichar_filter { }; + +typedef multichar_filter multichar_input_filter; +typedef multichar_wfilter multichar_input_wfilter; +typedef multichar_filter multichar_output_filter; +typedef multichar_wfilter multichar_output_wfilter; +typedef multichar_filter multichar_dual_use_filter; +typedef multichar_wfilter multichar_dual_use_wfilter; + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_CONCEPTS_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/constants.hpp b/win32/include/boost/iostreams/constants.hpp new file mode 100755 index 000000000..dda7f3505 --- /dev/null +++ b/win32/include/boost/iostreams/constants.hpp @@ -0,0 +1,42 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains constants used by library. + +#ifndef BOOST_IOSTREAMS_CONSTANTS_HPP_INCLUDED +#define BOOST_IOSTREAMS_CONSTANTS_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#ifndef BOOST_IOSTREAMS_DEFAULT_DEVICE_BUFFER_SIZE +# define BOOST_IOSTREAMS_DEFAULT_DEVICE_BUFFER_SIZE 4096 +#endif + +#ifndef BOOST_IOSTREAMS_DEFAULT_FILTER_BUFFER_SIZE +# define BOOST_IOSTREAMS_DEFAULT_FILTER_BUFFER_SIZE 128 +#endif + +#ifndef BOOST_IOSTREAMS_DEFAULT_PBACK_BUFFER_SIZE +# define BOOST_IOSTREAMS_DEFAULT_PBACK_BUFFER_SIZE 4 +#endif + +#include // streamsize. + +namespace boost { namespace iostreams { + +const std::streamsize default_device_buffer_size = + BOOST_IOSTREAMS_DEFAULT_DEVICE_BUFFER_SIZE; +const std::streamsize default_filter_buffer_size = + BOOST_IOSTREAMS_DEFAULT_FILTER_BUFFER_SIZE; +const std::streamsize default_pback_buffer_size = + BOOST_IOSTREAMS_DEFAULT_PBACK_BUFFER_SIZE; + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_CONSTANTS_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/copy.hpp b/win32/include/boost/iostreams/copy.hpp new file mode 100755 index 000000000..fc9a61b92 --- /dev/null +++ b/win32/include/boost/iostreams/copy.hpp @@ -0,0 +1,252 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains: The function template copy, which reads data from a Source +// and writes it to a Sink until the end of the sequence is reached, returning +// the number of characters transfered. + +// The implementation is complicated by the need to handle smart adapters +// and direct devices. + +#ifndef BOOST_IOSTREAMS_COPY_HPP_INCLUDED +#define BOOST_IOSTREAMS_COPY_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // Make sure ptrdiff_t is in std. +#include // copy, min. +#include // ptrdiff_t. +#include // pair. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // failure, streamsize. +#include +#include +#include // read, write, close. +#include +#include +#include + +namespace boost { namespace iostreams { + +namespace detail { + + // The following four overloads of copy_impl() optimize + // copying in the case that one or both of the two devices + // models Direct (see + // http://www.boost.org/libs/iostreams/doc/index.html?path=4.1.1.4) + +// Copy from a direct source to a direct sink +template +std::streamsize copy_impl( Source& src, Sink& snk, + std::streamsize /* buffer_size */, + mpl::true_, mpl::true_ ) +{ + using namespace std; + typedef typename char_type_of::type char_type; + typedef std::pair pair_type; + pair_type p1 = iostreams::input_sequence(src); + pair_type p2 = iostreams::output_sequence(snk); + std::streamsize total = + static_cast( + (std::min)(p1.second - p1.first, p2.second - p2.first) + ); + std::copy(p1.first, p1.first + total, p2.first); + return total; +} + +// Copy from a direct source to an indirect sink +template +std::streamsize copy_impl( Source& src, Sink& snk, + std::streamsize /* buffer_size */, + mpl::true_, mpl::false_ ) +{ + using namespace std; + typedef typename char_type_of::type char_type; + typedef std::pair pair_type; + pair_type p = iostreams::input_sequence(src); + std::streamsize size, total; + for ( total = 0, size = static_cast(p.second - p.first); + total < size; ) + { + std::streamsize amt = + iostreams::write(snk, p.first + total, size - total); + total += amt; + } + return total; +} + +// Copy from an indirect source to a direct sink +template +std::streamsize copy_impl( Source& src, Sink& snk, + std::streamsize buffer_size, + mpl::false_, mpl::true_ ) +{ + typedef typename char_type_of::type char_type; + typedef std::pair pair_type; + detail::basic_buffer buf(buffer_size); + pair_type p = snk.output_sequence(); + std::streamsize total = 0; + std::ptrdiff_t capacity = p.second - p.first; + while (true) { + std::streamsize amt = + iostreams::read( + src, + buf.data(), + buffer_size < capacity - total ? + buffer_size : + static_cast(capacity - total) + ); + if (amt == -1) + break; + std::copy(buf.data(), buf.data() + amt, p.first + total); + total += amt; + } + return total; +} + +// Copy from an indirect source to an indirect sink +template +std::streamsize copy_impl( Source& src, Sink& snk, + std::streamsize buffer_size, + mpl::false_, mpl::false_ ) +{ + typedef typename char_type_of::type char_type; + detail::basic_buffer buf(buffer_size); + non_blocking_adapter nb(snk); + std::streamsize total = 0; + bool done = false; + while (!done) { + std::streamsize amt; + done = (amt = iostreams::read(src, buf.data(), buffer_size)) == -1; + if (amt != -1) { + iostreams::write(nb, buf.data(), amt); + total += amt; + } + } + return total; +} + + // The following function object is used with + // boost::iostreams::detail::execute() in the primary + // overload of copy_impl(), below + +// Function object that delegates to one of the above four +// overloads of compl_impl() +template +class copy_operation { +public: + typedef std::streamsize result_type; + copy_operation(Source& src, Sink& snk, std::streamsize buffer_size) + : src_(src), snk_(snk), buffer_size_(buffer_size) + { } + std::streamsize operator()() + { + return copy_impl( src_, snk_, buffer_size_, + is_direct(), is_direct() ); + } +private: + copy_operation& operator=(const copy_operation&); + Source& src_; + Sink& snk_; + std::streamsize buffer_size_; +}; + +// Primary overload of copy_impl. Delegates to one of the above four +// overloads of compl_impl(), depending on which of the two given +// devices, if any, models Direct (see +// http://www.boost.org/libs/iostreams/doc/index.html?path=4.1.1.4) +template +std::streamsize copy_impl(Source src, Sink snk, std::streamsize buffer_size) +{ + using namespace std; + typedef typename char_type_of::type src_char; + typedef typename char_type_of::type snk_char; + BOOST_STATIC_ASSERT((is_same::value)); + return detail::execute_all( + copy_operation(src, snk, buffer_size), + detail::call_close_all(src), + detail::call_close_all(snk) + ); +} + +} // End namespace detail. + +//------------------Definition of copy----------------------------------------// + +// Overload of copy() for the case where neither the source nor the sink is +// a standard stream or stream buffer +template +std::streamsize +copy( const Source& src, const Sink& snk, + std::streamsize buffer_size = default_device_buffer_size + BOOST_IOSTREAMS_DISABLE_IF_STREAM(Source) + BOOST_IOSTREAMS_DISABLE_IF_STREAM(Sink) ) +{ + typedef typename char_type_of::type char_type; + return detail::copy_impl( detail::resolve(src), + detail::resolve(snk), + buffer_size ); +} + +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------// + +// Overload of copy() for the case where the source, but not the sink, is +// a standard stream or stream buffer +template +std::streamsize +copy( Source& src, const Sink& snk, + std::streamsize buffer_size = default_device_buffer_size + BOOST_IOSTREAMS_ENABLE_IF_STREAM(Source) + BOOST_IOSTREAMS_DISABLE_IF_STREAM(Sink) ) +{ + typedef typename char_type_of::type char_type; + return detail::copy_impl( detail::wrap(src), + detail::resolve(snk), + buffer_size ); +} + +// Overload of copy() for the case where the sink, but not the source, is +// a standard stream or stream buffer +template +std::streamsize +copy( const Source& src, Sink& snk, + std::streamsize buffer_size = default_device_buffer_size + BOOST_IOSTREAMS_DISABLE_IF_STREAM(Source) + BOOST_IOSTREAMS_ENABLE_IF_STREAM(Sink) ) +{ + typedef typename char_type_of::type char_type; + return detail::copy_impl( detail::resolve(src), + detail::wrap(snk), buffer_size ); +} + +// Overload of copy() for the case where neither the source nor the sink is +// a standard stream or stream buffer +template +std::streamsize +copy( Source& src, Sink& snk, + std::streamsize buffer_size = default_device_buffer_size + BOOST_IOSTREAMS_ENABLE_IF_STREAM(Source) + BOOST_IOSTREAMS_ENABLE_IF_STREAM(Sink) ) +{ + return detail::copy_impl(detail::wrap(src), detail::wrap(snk), buffer_size); +} + +#endif // #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //-----------------------// + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_COPY_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/absolute_path.hpp b/win32/include/boost/iostreams/detail/absolute_path.hpp new file mode 100755 index 000000000..9d5729a01 --- /dev/null +++ b/win32/include/boost/iostreams/detail/absolute_path.hpp @@ -0,0 +1,46 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + + * File: boost/iostreams/detail/execute.hpp + * Date: Thu Dec 06 13:21:54 MST 2007 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + * + * Defines the function boost::iostreams::detail::absolute_path, used for + * debug output for mapped files. + */ + +#ifndef BOOST_IOSTREAMS_DETAIL_ABSOLUTE_PATH_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_ABSOLUTE_PATH_HPP_INCLUDED + +#include +#include +#ifdef BOOST_IOSTREAMS_WINDOWS +# include +#endif +#include + +namespace boost { namespace iostreams { namespace detail { + +// Resolves the given path relative to the current working directory +inline std::string absolute_path(const std::string& path) +{ +#ifdef BOOST_IOSTREAMS_WINDOWS + return path.size() && (path[0] == '/' || path[0] == '\\') || + path.size() > 1 && std::isalpha(path[0]) && path[1] == ':' ? + path : + current_directory() + '\\' + path; +#else // #ifdef BOOST_IOSTREAMS_WINDOWS + return path.size() && (path[0] == '/') ? + path : + current_directory() + '/' + path; +#endif // #ifdef BOOST_IOSTREAMS_WINDOWS +} + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_ABSOLUTE_PATH_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/access_control.hpp b/win32/include/boost/iostreams/detail/access_control.hpp new file mode 100755 index 000000000..a1c53a51c --- /dev/null +++ b/win32/include/boost/iostreams/detail/access_control.hpp @@ -0,0 +1,87 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains the definition of the class template access_control, which +// allows the type of inheritance from a provided base class to be specified +// using a template parameter. + + +#ifndef BOOST_IOSTREAMS_ACCESS_CONTROL_HPP_INCLUDED +#define BOOST_IOSTREAMS_ACCESS_CONTROL_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include + +namespace boost { namespace iostreams { + +struct protected_ { }; // Represents protected inheritance. +struct public_ { }; // Represents public inheritance. + + +namespace detail { + + // Implements protected inheritance. + template + struct prot_ : protected U + { + prot_() { } + template prot_(V v) : U(v) { } + }; + + // Implements public inheritance. + template struct pub_ : public U { + pub_() { } + template pub_(V v) : U(v) { } + }; + +// +// Used to deduce the base type for the template access_control. +// +template +struct access_control_base { + typedef int bad_access_specifier; + typedef typename + iostreams::select< // Disambiguation for Tru64 + ::boost::is_same< + Access, protected_ + >, prot_, + ::boost::is_same< + Access, public_ + >, pub_, + else_, bad_access_specifier + >::type type; +}; + +} // End namespace detail. + +// +// Template name: access_control. +// Description: Allows the type of inheritance from a provided base class +// to be specified using an int template parameter. +// Template parameters: +// Base - The class from which to inherit (indirectly.) +// Access - The type of access desired. Must be one of the +// values access_base::prot or access_base::pub. +// +template< typename T, typename Access, + typename Base = // VC6 workaraound (Compiler Error C2516) + typename detail::access_control_base::type > +struct access_control : public Base { + access_control() { } + template explicit access_control(U u) : Base(u) { } +}; + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_ACCESS_CONTROL_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/adapter/concept_adapter.hpp b/win32/include/boost/iostreams/detail/adapter/concept_adapter.hpp new file mode 100755 index 000000000..1b219754b --- /dev/null +++ b/win32/include/boost/iostreams/detail/adapter/concept_adapter.hpp @@ -0,0 +1,278 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_CONCEPT_ADAPTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CONCEPT_ADAPTER_HPP_INCLUDED + +#include // SFINAE. +#include +#include +#include +#include +#include +#include +#include +#include // pubsync. +#include +#include +#include +#include +#include + +// Must come last. +#include // MSVC. + +namespace boost { namespace iostreams { namespace detail { + +template struct device_wrapper_impl; +template struct flt_wrapper_impl; + +template +class concept_adapter { +private: + typedef typename detail::value_type::type value_type; + typedef typename dispatch::type input_tag; + typedef typename dispatch::type output_tag; + typedef typename + mpl::if_< + is_device, + device_wrapper_impl, + flt_wrapper_impl + >::type input_impl; + typedef typename + mpl::if_< + is_device, + device_wrapper_impl, + flt_wrapper_impl + >::type output_impl; + typedef typename + mpl::if_< + is_device, + device_wrapper_impl, + flt_wrapper_impl + >::type any_impl; +public: + typedef typename char_type_of::type char_type; + typedef typename category_of::type category; + + explicit concept_adapter(const reference_wrapper& ref) : t_(ref.get()) + { BOOST_STATIC_ASSERT(is_std_io::value); } + explicit concept_adapter(const T& t) : t_(t) + { BOOST_STATIC_ASSERT(!is_std_io::value); } + + T& operator*() { return t_; } + T* operator->() { return &t_; } + + std::streamsize read(char_type* s, std::streamsize n) + { return this->read(s, n, (basic_null_source*) 0); } + + template + std::streamsize read(char_type* s, std::streamsize n, Source* src) + { return input_impl::read(t_, src, s, n); } + + std::streamsize write(const char_type* s, std::streamsize n) + { return this->write(s, n, (basic_null_sink*) 0); } + + template + std::streamsize write(const char_type* s, std::streamsize n, Sink* snk) + { return output_impl::write(t_, snk, s, n); } + + std::streampos seek( stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which ) + { + return this->seek( off, way, which, + (basic_null_device*) 0); + } + + template + std::streampos seek( stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which, Device* dev ) + { return any_impl::seek(t_, dev, off, way, which); } + + void close(BOOST_IOS::openmode which) + { this->close(which, (basic_null_device*) 0); } + + template + void close(BOOST_IOS::openmode which, Device* dev) + { any_impl::close(t_, dev, which); } + + bool flush( BOOST_IOSTREAMS_BASIC_STREAMBUF(char_type, + BOOST_IOSTREAMS_CHAR_TRAITS(char_type))* sb ) + { + bool result = any_impl::flush(t_, sb); + if (sb && sb->BOOST_IOSTREAMS_PUBSYNC() == -1) + result = false; + return result; + } + + template // Avoid dependency on + void imbue(const Locale& loc) { iostreams::imbue(t_, loc); } + + std::streamsize optimal_buffer_size() const + { return iostreams::optimal_buffer_size(t_); } +public: + concept_adapter& operator=(const concept_adapter&); + value_type t_; +}; + +//------------------Specializations of device_wrapper_impl--------------------// + +template<> +struct device_wrapper_impl { + template + static std::streampos + seek( Device& dev, Dummy*, stream_offset off, + BOOST_IOS::seekdir way, BOOST_IOS::openmode which ) + { + typedef typename category_of::type category; + return seek(dev, off, way, which, category()); + } + + template + static std::streampos + seek( Device&, stream_offset, BOOST_IOS::seekdir, + BOOST_IOS::openmode, any_tag ) + { + throw cant_seek(); + } + + template + static std::streampos + seek( Device& dev, stream_offset off, + BOOST_IOS::seekdir way, BOOST_IOS::openmode which, + random_access ) + { + return iostreams::seek(dev, off, way, which); + } + + template + static void close(Device& dev, Dummy*, BOOST_IOS::openmode which) + { iostreams::close(dev, which); } + + template + static bool flush(Device& dev, Dummy*) + { return iostreams::flush(dev); } +}; + + +template<> +struct device_wrapper_impl : device_wrapper_impl { + template + static std::streamsize + read( Device& dev, Dummy*, typename char_type_of::type* s, + std::streamsize n ) + { return iostreams::read(dev, s, n); } + + template + static std::streamsize + write( Device&, Dummy*, const typename char_type_of::type*, + std::streamsize ) + { throw cant_write(); } +}; + +template<> +struct device_wrapper_impl { + template + static std::streamsize + read(Device&, Dummy*, typename char_type_of::type*, std::streamsize) + { throw cant_read(); } + + template + static std::streamsize + write( Device& dev, Dummy*, const typename char_type_of::type* s, + std::streamsize n ) + { return iostreams::write(dev, s, n); } +}; + +//------------------Specializations of flt_wrapper_impl--------------------// + +template<> +struct flt_wrapper_impl { + template + static std::streampos + seek( Filter& f, Device* dev, stream_offset off, + BOOST_IOS::seekdir way, BOOST_IOS::openmode which ) + { + typedef typename category_of::type category; + return seek(f, dev, off, way, which, category()); + } + + template + static std::streampos + seek( Filter&, Device*, stream_offset, + BOOST_IOS::seekdir, BOOST_IOS::openmode, any_tag ) + { throw cant_seek(); } + + template + static std::streampos + seek( Filter& f, Device* dev, stream_offset off, + BOOST_IOS::seekdir way, BOOST_IOS::openmode which, + random_access tag ) + { + typedef typename category_of::type category; + return seek(f, dev, off, way, which, tag, category()); + } + + template + static std::streampos + seek( Filter& f, Device* dev, stream_offset off, + BOOST_IOS::seekdir way, BOOST_IOS::openmode, + random_access, any_tag ) + { return f.seek(*dev, off, way); } + + template + static std::streampos + seek( Filter& f, Device* dev, stream_offset off, + BOOST_IOS::seekdir way, BOOST_IOS::openmode which, + random_access, two_sequence ) + { return f.seek(*dev, off, way, which); } + + template + static void close(Filter& f, Device* dev, BOOST_IOS::openmode which) + { iostreams::close(f, *dev, which); } + + template + static bool flush(Filter& f, Device* dev) + { return iostreams::flush(f, *dev); } +}; + +template<> +struct flt_wrapper_impl { + template + static std::streamsize + read( Filter& f, Source* src, typename char_type_of::type* s, + std::streamsize n ) + { return iostreams::read(f, *src, s, n); } + + template + static std::streamsize + write( Filter&, Sink*, const typename char_type_of::type*, + std::streamsize ) + { throw cant_write(); } +}; + +template<> +struct flt_wrapper_impl { + template + static std::streamsize + read(Filter&, Source*, typename char_type_of::type*,std::streamsize) + { throw cant_read(); } + + template + static std::streamsize + write( Filter& f, Sink* snk, const typename char_type_of::type* s, + std::streamsize n ) + { return iostreams::write(f, *snk, s, n); } +}; + +//----------------------------------------------------------------------------// + +} } } // End namespaces detail, iostreams, boost. + +#include // MSVC. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CONCEPT_ADAPTER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/adapter/device_adapter.hpp b/win32/include/boost/iostreams/detail/adapter/device_adapter.hpp new file mode 100755 index 000000000..6e9dffe6e --- /dev/null +++ b/win32/include/boost/iostreams/detail/adapter/device_adapter.hpp @@ -0,0 +1,67 @@ +/* + * Defines the class template boost::iostreams::detail::device_adapter, + * a convenience base class for device adapters. + * + * File: boost/iostreams/detail/adapter/filter_adapter.hpp + * Date: Mon Nov 26 14:35:48 MST 2007 + * + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + * + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + */ + +#ifndef BOOST_IOSTREAMS_DETAIL_DEVICE_ADAPTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_DEVICE_ADAPTER_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace iostreams { namespace detail { + +template +class device_adapter { +private: + typedef typename detail::value_type::type value_type; + typedef typename detail::param_type::type param_type; +public: + explicit device_adapter(param_type t) : t_(t) { } + T& component() { return t_; } + + void close() + { + detail::close_all(t_); + } + + void close(BOOST_IOS::openmode which) + { + iostreams::close(t_, which); + } + + bool flush() + { + return iostreams::flush(t_); + } + + template // Avoid dependency on + void imbue(const Locale& loc) { iostreams::imbue(t_, loc); } + + std::streamsize optimal_buffer_size() const + { return iostreams::optimal_buffer_size(t_); } +public: + value_type t_; +}; + +//----------------------------------------------------------------------------// + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_DEVICE_ADAPTER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/adapter/direct_adapter.hpp b/win32/include/boost/iostreams/detail/adapter/direct_adapter.hpp new file mode 100755 index 000000000..f0b50ab4f --- /dev/null +++ b/win32/include/boost/iostreams/detail/adapter/direct_adapter.hpp @@ -0,0 +1,280 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_DIRECT_ADAPTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_DIRECT_ADAPTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // SFINAE, MSVC, put ptrdiff_t in std. +#include // copy, min. +#include // ptrdiff_t. +#include +#include +#include // forwarding. +#include // locale. +#include +#include +#include // openmode, seekdir, int types. +#include // mode_of, is_direct. +#include +#include +#include +#include +#include +#include +#include +#include + +// Must come last. +#include // VC7.1 + +namespace boost { namespace iostreams { namespace detail { + +//------------------Definition of direct_adapter_base-------------------------// + +// Put all initialization in base class to faciliate forwarding. +template +class direct_adapter_base { +public: + typedef typename char_type_of::type char_type; + typedef typename mode_of::type mode_type; + struct category + : mode_type, + device_tag, + closable_tag + #ifndef BOOST_IOSTREAMS_NO_LOCALE + , localizable_tag + #endif + { }; +protected: + explicit direct_adapter_base(const Direct& d); + typedef is_convertible is_double; + struct pointers { + char_type *beg, *ptr, *end; + }; + void init_input(mpl::true_); + void init_input(mpl::false_) { } + void init_output(mpl::true_); + void init_output(mpl::false_) { } + double_object ptrs_; + Direct d_; +}; + +template +class direct_adapter : private direct_adapter_base { +private: + typedef direct_adapter_base base_type; + typedef typename base_type::pointers pointers; + typedef typename base_type::is_double is_double; + using base_type::ptrs_; + using base_type::d_; +public: + typedef typename base_type::char_type char_type; + typedef typename base_type::category category; + + // Constructors + +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1310) + direct_adapter(const Direct& d) : base_type(d) { } + direct_adapter(const direct_adapter& d) : base_type(d) { } +# define BOOST_PP_LOCAL_LIMITS (1, BOOST_IOSTREAMS_MAX_FORWARDING_ARITY) +#else + template + struct is_direct + : mpl::or_< + is_same >, + is_same + > + { }; + template + direct_adapter(const U& u) + : base_type(forward(u, is_direct())) + { } +# define BOOST_PP_LOCAL_LIMITS (2, BOOST_IOSTREAMS_MAX_FORWARDING_ARITY) +#endif + +#define BOOST_PP_LOCAL_MACRO(n) \ + template \ + direct_adapter(BOOST_PP_ENUM_BINARY_PARAMS(n, const P, &p)) \ + : base_type(Direct(BOOST_PP_ENUM_PARAMS(n, p))) \ + { } \ + /**/ +#include BOOST_PP_LOCAL_ITERATE() +#undef BOOST_PP_LOCAL_MACRO + + // Device interface. + + std::streamsize read(char_type* s, std::streamsize n); + std::streamsize write(const char_type* s, std::streamsize n); + std::streampos seek( stream_offset, BOOST_IOS::seekdir, + BOOST_IOS::openmode = BOOST_IOS::in | BOOST_IOS::out ); + void close(); + void close(BOOST_IOS::openmode which); +#ifndef BOOST_IOSTREAMS_NO_LOCALE + void imbue(const std::locale&); +#endif + + // Direct device access. + + Direct& operator*() { return d_; } + Direct* operator->() { return &d_; } +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310) +private: + template + static Direct forward(const U& u, mpl::true_) { return u; } + template + static Direct forward(const U& u, mpl::false_) { return Direct(u); } +#endif +}; + +//--------------Definition of wrap_direct and unwrap_direct-------------------// + +template +struct wrap_direct_traits + : mpl::if_< + is_direct, + direct_adapter, + Device + > + { }; + +template +typename wrap_direct_traits::type +inline wrap_direct(Device dev) +{ + typedef typename wrap_direct_traits::type type; + return type(dev); +} + +template +inline Device& unwrap_direct(Device& d) { return d; } + +template +inline Device& unwrap_direct(direct_adapter& d) { return *d; } + +//--------------Implementation of direct_adapter_base-------------------------// + +template +direct_adapter_base::direct_adapter_base(const Direct& d) : d_(d) +{ + init_input(is_convertible()); + init_output(is_convertible()); +} + +template +void direct_adapter_base::init_input(mpl::true_) +{ + std::pair seq = iostreams::input_sequence(d_); + ptrs_.first().beg = seq.first; + ptrs_.first().ptr = seq.first; + ptrs_.first().end = seq.second; +} + +template +void direct_adapter_base::init_output(mpl::true_) +{ + std::pair seq = iostreams::output_sequence(d_); + ptrs_.second().beg = seq.first; + ptrs_.second().ptr = seq.first; + ptrs_.second().end = seq.second; +} + +//--------------Implementation of direct_adapter------------------------------// + +template +inline std::streamsize direct_adapter::read + (char_type* s, std::streamsize n) +{ + using namespace std; + pointers& get = ptrs_.first(); + std::streamsize avail = + static_cast(get.end - get.ptr); + std::streamsize result = (std::min)(n, avail); + std::copy(get.ptr, get.ptr + result, s); + get.ptr += result; + return result != 0 ? result : -1; +} + +template +inline std::streamsize direct_adapter::write + (const char_type* s, std::streamsize n) +{ + using namespace std; + pointers& put = ptrs_.second(); + if (n > static_cast(put.end - put.ptr)) + throw write_area_exhausted(); + std::copy(s, s + n, put.ptr); + put.ptr += n; + return n; +} + +template +inline std::streampos direct_adapter::seek + ( stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which ) +{ + using namespace std; + pointers& get = ptrs_.first(); + pointers& put = ptrs_.second(); + if (way == BOOST_IOS::cur && get.ptr != put.ptr) + throw bad_seek(); + ptrdiff_t next = 0; + if ((which & BOOST_IOS::in) || !is_double::value) { + if (way == BOOST_IOS::beg) + next = off; + else if (way == BOOST_IOS::cur) + next = get.ptr - get.beg + off; + else + next = get.end - get.beg + off; + if (next >= 0 && next <= get.end - get.beg) + get.ptr = get.beg + next; + else + throw bad_seek(); + } + if ((which & BOOST_IOS::out) && is_double::value) { + if (way == BOOST_IOS::beg) + next = off; + else if (way == BOOST_IOS::cur) + next = put.ptr - put.beg + off; + else + next = put.end - put.beg + off; + if (next >= 0 && next <= put.end - put.beg) + put.ptr = put.beg + next; + else + throw bad_seek(); + } + return offset_to_position(next); +} + +template +void direct_adapter::close() +{ + BOOST_STATIC_ASSERT((!is_convertible::value)); + detail::close_all(d_); +} + +template +void direct_adapter::close(BOOST_IOS::openmode which) +{ + BOOST_STATIC_ASSERT((is_convertible::value)); + boost::iostreams::close(d_, which); +} + +#ifndef BOOST_IOSTREAMS_NO_LOCALE + template + void direct_adapter::imbue(const std::locale& loc) + { boost::iostreams::imbue(d_, loc); } +#endif + +} } } // End namespaces detail, iostreams, boost. + +#include + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_DIRECT_ADAPTER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/adapter/filter_adapter.hpp b/win32/include/boost/iostreams/detail/adapter/filter_adapter.hpp new file mode 100755 index 000000000..1fea16af0 --- /dev/null +++ b/win32/include/boost/iostreams/detail/adapter/filter_adapter.hpp @@ -0,0 +1,69 @@ +/* + * Defines the class template boost::iostreams::detail::filter_adapter, + * a convenience base class for filter adapters. + * + * File: boost/iostreams/detail/adapter/filter_adapter.hpp + * Date: Mon Nov 26 14:35:48 MST 2007 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + * + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + */ + +#ifndef BOOST_IOSTREAMS_DETAIL_FILTER_ADAPTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_FILTER_ADAPTER_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace iostreams { namespace detail { + +template +class filter_adapter { +private: + typedef typename detail::value_type::type value_type; + typedef typename detail::param_type::type param_type; +public: + explicit filter_adapter(param_type t) : t_(t) { } + T& component() { return t_; } + + template + void close(Device& dev) + { + detail::close_all(t_, dev); + } + + template + void close(Device& dev, BOOST_IOS::openmode which) + { + iostreams::close(t_, dev, which); + } + + template + void flush(Device& dev) + { + return iostreams::flush(t_, dev); + } + + template // Avoid dependency on + void imbue(const Locale& loc) { iostreams::imbue(t_, loc); } + + std::streamsize optimal_buffer_size() const + { return iostreams::optimal_buffer_size(t_); } +public: + value_type t_; +}; + +//----------------------------------------------------------------------------// + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_FILTER_ADAPTER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/adapter/mode_adapter.hpp b/win32/include/boost/iostreams/detail/adapter/mode_adapter.hpp new file mode 100755 index 000000000..5c7f709ea --- /dev/null +++ b/win32/include/boost/iostreams/detail/adapter/mode_adapter.hpp @@ -0,0 +1,123 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_MODE_ADAPTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_MODE_ADAPTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// Contains the definition of the class template mode_adapter, which allows +// a filter or device to function as if it has a different i/o mode than that +// deduced by the metafunction mode_of. + +#include // BOOST_MSVC. +#include +#include +#include // openmode, seekdir, int types. +#include +#include +#include + +namespace boost { namespace iostreams { namespace detail { + +template +class mode_adapter { +private: + struct empty_base { }; +public: + typedef typename wrapped_type::type policy_type; + typedef typename char_type_of::type char_type; + struct category + : Mode, + device_tag, + mpl::if_, filter_tag, device_tag>, + mpl::if_, multichar_tag, empty_base>, + #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + closable_tag, // VC6 can't see member close()! + #endif + localizable_tag + { }; + explicit mode_adapter(const policy_type& t) : t_(t) { } + + // Device member functions. + + std::streamsize read(char_type* s, std::streamsize n); + std::streamsize write(const char_type* s, std::streamsize n); + std::streampos seek( stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which = + BOOST_IOS::in | BOOST_IOS::out ); +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + void close(); + void close(BOOST_IOS::openmode which); +#endif + + // Filter member functions. + + template + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { return iostreams::read(t_, src, s, n); } + + template + std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) + { return iostreams::write(t_, snk, s, n); } + + template + std::streampos seek(Device& dev, stream_offset off, BOOST_IOS::seekdir way) + { return iostreams::seek(t_, dev, off, way); } + + template + std::streampos seek( Device& dev, stream_offset off, + BOOST_IOS::seekdir way, BOOST_IOS::openmode which ) + { return iostreams::seek(t_, dev, off, way, which); } + + template + void close(Device& dev) + { detail::close_all(t_, dev); } + + template + void close(Device& dev, BOOST_IOS::openmode which) + { iostreams::close(t_, dev, which); } + + template + void imbue(const Locale& loc) + { iostreams::imbue(t_, loc); } +private: + policy_type t_; +}; + +//------------------Implementation of mode_adapter----------------------------// + +template +std::streamsize mode_adapter::read + (char_type* s, std::streamsize n) +{ return boost::iostreams::read(t_, s, n); } + +template +std::streamsize mode_adapter::write + (const char_type* s, std::streamsize n) +{ return boost::iostreams::write(t_, s, n); } + +template +std::streampos mode_adapter::seek + (stream_offset off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which) +{ return boost::iostreams::seek(t_, off, way, which); } + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + template + void mode_adapter::close() + { detail::close_all(t_); } + + template + void mode_adapter::close(BOOST_IOS::openmode which) + { iostreams::close(t_, which); } +#endif + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_MODE_ADAPTER_HPP_INCLUDED //-----// diff --git a/win32/include/boost/iostreams/detail/adapter/non_blocking_adapter.hpp b/win32/include/boost/iostreams/detail/adapter/non_blocking_adapter.hpp new file mode 100755 index 000000000..1e0992638 --- /dev/null +++ b/win32/include/boost/iostreams/detail/adapter/non_blocking_adapter.hpp @@ -0,0 +1,59 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_NON_BLOCKING_ADAPTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_NON_BLOCKING_ADAPTER_HPP_INCLUDED + +#include // streamsize, seekdir, openmode. +#include +#include +#include +#include + +namespace boost { namespace iostreams { + +template +class non_blocking_adapter { +public: + typedef typename char_type_of::type char_type; + struct category + : mode_of::type, device_tag + { }; + explicit non_blocking_adapter(Device& dev) : device_(dev) { } + std::streamsize read(char_type* s, std::streamsize n) + { + std::streamsize result = 0; + while (result < n) { + std::streamsize amt = iostreams::read(device_, s, n); + if (amt == -1) + break; + result += amt; + } + return result != 0 ? result : -1; + } + std::streamsize write(const char_type* s, std::streamsize n) + { + std::streamsize result = 0; + while (result < n) { + std::streamsize amt = + iostreams::write(device_, s + result, n - result); + result += amt; + } + return result; + } + std::streampos seek( stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which = + BOOST_IOS::in | BOOST_IOS::out ) + { return iostreams::seek(device_, off, way, which); } +public: + non_blocking_adapter& operator=(const non_blocking_adapter&); + Device& device_; +}; + +} } // End namespace iostreams. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_NON_BLOCKING_ADAPTER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/adapter/output_iterator_adapter.hpp b/win32/include/boost/iostreams/detail/adapter/output_iterator_adapter.hpp new file mode 100755 index 000000000..a2eef3788 --- /dev/null +++ b/win32/include/boost/iostreams/detail/adapter/output_iterator_adapter.hpp @@ -0,0 +1,41 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_OUTPUT_ITERATOR_ADAPTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_OUTPUT_ITERATOR_ADAPTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // copy. +#include // streamsize. +#include // tags. +#include +#include + +namespace boost { namespace iostreams { namespace detail { + +template +class output_iterator_adapter { +public: + BOOST_STATIC_ASSERT((is_convertible::value)); + typedef Ch char_type; + typedef sink_tag category; + explicit output_iterator_adapter(OutIt out) : out_(out) { } + std::streamsize write(const char_type* s, std::streamsize n) + { + std::copy(s, s + n, out_); + return n; + } +private: + OutIt out_; +}; + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_OUTPUT_ITERATOR_ADAPTER_HPP_INCLUDED //-----// diff --git a/win32/include/boost/iostreams/detail/adapter/range_adapter.hpp b/win32/include/boost/iostreams/detail/adapter/range_adapter.hpp new file mode 100755 index 000000000..e010d1629 --- /dev/null +++ b/win32/include/boost/iostreams/detail/adapter/range_adapter.hpp @@ -0,0 +1,183 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_RANGE_ADAPTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_RANGE_ADAPTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // min. +#include +#include // ptrdiff_t. +#include // streamsize, streamoff. +#include // boost::iterator_traits. +#include +#include +#include +#include +#include +#include + +// Must come last. +#include // MSVC. + +namespace boost { namespace iostreams { namespace detail { + +// Used for simulated tag dispatch. +template struct range_adapter_impl; + +// +// Template name: range_adapter +// Description: Device based on an instance of boost::iterator_range. +// Template paramters: +// Mode - A mode tag. +// Range - An instance of iterator_range. +// +template +class range_adapter { +private: + typedef typename Range::iterator iterator; + typedef boost::detail::iterator_traits iter_traits; + typedef typename iter_traits::iterator_category iter_cat; +public: + typedef typename Range::value_type char_type; + struct category : Mode, device_tag { }; + typedef typename + mpl::if_< + is_convertible< + iter_cat, + std::random_access_iterator_tag + >, + std::random_access_iterator_tag, + std::forward_iterator_tag + >::type tag; + typedef range_adapter_impl impl; + + explicit range_adapter(const Range& rng); + range_adapter(iterator first, iterator last); + std::streamsize read(char_type* s, std::streamsize n); + std::streamsize write(const char_type* s, std::streamsize n); + std::streampos seek(stream_offset off, BOOST_IOS::seekdir way); +private: + iterator first_, cur_, last_; +}; + +//------------------Implementation of range_adapter---------------------------// + +template +range_adapter::range_adapter(const Range& rng) + : first_(rng.begin()), cur_(rng.begin()), last_(rng.end()) { } + +template +range_adapter::range_adapter(iterator first, iterator last) + : first_(first), cur_(first), last_(last) { } + +template +inline std::streamsize range_adapter::read + (char_type* s, std::streamsize n) +{ return impl::read(cur_, last_, s, n); } + +template +inline std::streamsize range_adapter::write + (const char_type* s, std::streamsize n) +{ return impl::write(cur_, last_, s, n); } + + +template +std::streampos range_adapter::seek + (stream_offset off, BOOST_IOS::seekdir way) +{ + impl::seek(first_, cur_, last_, off, way); + return offset_to_position(cur_ - first_); +} + +//------------------Implementation of range_adapter_impl----------------------// + +template<> +struct range_adapter_impl { + template + static std::streamsize read + (Iter& cur, Iter& last, Ch* s,std::streamsize n) + { + std::streamsize rem = n; // No. of chars remaining. + while (cur != last && rem-- > 0) *s++ = *cur++; + return n - rem != 0 ? n - rem : -1; + } + + template + static std::streamsize write + (Iter& cur, Iter& last, const Ch* s, std::streamsize n) + { + while (cur != last && n-- > 0) *cur++ = *s++; + if (cur == last && n > 0) + throw write_area_exhausted(); + return n; + } +}; + +template<> +struct range_adapter_impl { + template + static std::streamsize read + (Iter& cur, Iter& last, Ch* s,std::streamsize n) + { + std::streamsize result = + (std::min)(static_cast(last - cur), n); + if (result) + std::copy(cur, cur + result, s); + cur += result; + return result != 0 ? result : -1; + } + + template + static std::streamsize write + (Iter& cur, Iter& last, const Ch* s, std::streamsize n) + { + std::streamsize count = + (std::min)(static_cast(last - cur), n); + std::copy(s, s + count, cur); + cur += count; + if (count < n) + throw write_area_exhausted(); + return n; + } + + template + static void seek + ( Iter& first, Iter& cur, Iter& last, stream_offset off, + BOOST_IOS::seekdir way ) + { + using namespace std; + switch (way) { + case BOOST_IOS::beg: + if (off > last - first || off < 0) throw bad_seek(); + cur = first + off; + break; + case BOOST_IOS::cur: + { + std::ptrdiff_t newoff = cur - first + off; + if (newoff > last - first || newoff < 0) throw bad_seek(); + cur += off; + break; + } + case BOOST_IOS::end: + if (last - first + off < 0 || off > 0) throw bad_seek(); + cur = last + off; + break; + default: + assert(0); + } + } +}; + +} } } // End namespaces detail, iostreams, boost. + +#include // MSVC. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_RANGE_ADAPTER_HPP_INCLUDED //---------------// diff --git a/win32/include/boost/iostreams/detail/add_facet.hpp b/win32/include/boost/iostreams/detail/add_facet.hpp new file mode 100755 index 000000000..3a2244e98 --- /dev/null +++ b/win32/include/boost/iostreams/detail/add_facet.hpp @@ -0,0 +1,49 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Borrowed from + +#ifndef BOOST_IOSTREAMS_DETAIL_ADD_FACET_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_ADD_FACET_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // BOOST_DINKUMWARE_STDLIB. +#include + +//------------------Definition of add_facet-----------------------------------// + +// Does STLport uses old Dinkumware locale? +#if (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) && \ + defined(_STLP_NO_OWN_IOSTREAMS) \ + /**/ +# if (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER) +# define BOOST_IOSTREMS_STLPORT_WITH_OLD_DINKUMWARE +# endif +#endif + +namespace boost { namespace iostreams { namespace detail { + +template +inline std::locale add_facet(const std::locale &l, Facet * f) +{ + return + #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) || \ + defined(BOOST_IOSTREMS_STLPORT_WITH_OLD_DINKUMWARE) \ + /**/ + std::locale(std::_Addfac(l, f)); + #else + // standard compatible + std::locale(l, f); + #endif +} + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_ADD_FACET_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/bool_trait_def.hpp b/win32/include/boost/iostreams/detail/bool_trait_def.hpp new file mode 100755 index 000000000..a120a1952 --- /dev/null +++ b/win32/include/boost/iostreams/detail/bool_trait_def.hpp @@ -0,0 +1,49 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_BOOL_TRAIT_DEF_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_BOOL_TRAIT_DEF_HPP_INCLUDED + +#include // BOOST_STATIC_CONSTANT. +#include +#include +#include +#include +#include +#include + +// +// Macro name: BOOST_IOSTREAMS_BOOL_TRAIT_DEF +// Description: Used to generate the traits classes is_istream, is_ostream, +// etc. +// +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) +# define BOOST_IOSTREAMS_TRAIT_NAMESPACE(trait) +#else +# define BOOST_IOSTREAMS_TRAIT_NAMESPACE(trait) BOOST_PP_CAT(trait, _impl_):: +#endif +#define BOOST_IOSTREAMS_BOOL_TRAIT_DEF(trait, type, arity) \ + namespace BOOST_PP_CAT(trait, _impl_) { \ + BOOST_IOSTREAMS_TEMPLATE_PARAMS(arity, T) \ + type_traits::yes_type helper \ + (const volatile type BOOST_IOSTREAMS_TEMPLATE_ARGS(arity, T)*); \ + type_traits::no_type helper(...); \ + template \ + struct impl { \ + BOOST_STATIC_CONSTANT(bool, value = \ + (sizeof(BOOST_IOSTREAMS_TRAIT_NAMESPACE(trait) \ + helper(static_cast(0))) == \ + sizeof(type_traits::yes_type))); \ + }; \ + } \ + template \ + struct trait \ + : mpl::bool_::value> \ + { BOOST_MPL_AUX_LAMBDA_SUPPORT(1, trait, (T)) }; \ + /**/ + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_BOOL_TRAIT_DEF_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/broken_overload_resolution/forward.hpp b/win32/include/boost/iostreams/detail/broken_overload_resolution/forward.hpp new file mode 100755 index 000000000..f97267e9c --- /dev/null +++ b/win32/include/boost/iostreams/detail/broken_overload_resolution/forward.hpp @@ -0,0 +1,31 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_BROKEN_OVERLOAD_RESOLUTION_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_BROKEN_OVERLOAD_RESOLUTION_HPP_INCLUDED + +#include // BOOST_STATIC_CONSANT. +#include +#include + +namespace boost { namespace iostreams { namespace detail { + +template +struct forward_impl { + BOOST_STATIC_CONSTANT(bool, value = + ( !is_same< U, Device >::value && + !is_same< U, reference_wrapper >::value )); +}; + +template +struct forward + : mpl::bool_::value> + { }; + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_BROKEN_OVERLOAD_RESOLUTION_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/broken_overload_resolution/stream.hpp b/win32/include/boost/iostreams/detail/broken_overload_resolution/stream.hpp new file mode 100755 index 000000000..8daf05b39 --- /dev/null +++ b/win32/include/boost/iostreams/detail/broken_overload_resolution/stream.hpp @@ -0,0 +1,185 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_BROKEN_OVERLOAD_RESOLUTION_STREAM_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_BROKEN_OVERLOAD_RESOLUTION_STREAM_HPP_INCLUDED + +#include + +namespace boost { namespace iostreams { + +template< typename Device, + typename Tr = + BOOST_IOSTREAMS_CHAR_TRAITS( + BOOST_DEDUCED_TYPENAME char_type_of::type + ), + typename Alloc = + std::allocator< + BOOST_DEDUCED_TYPENAME char_type_of::type + > > +struct stream : detail::stream_base { +public: + typedef typename char_type_of::type char_type; + struct category + : mode_of::type, + closable_tag, + detail::stream_traits::stream_tag + { }; + BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr) +private: + typedef typename + detail::stream_traits< + Device, Tr + >::stream_type stream_type; + typedef Device policy_type; +public: + stream() { } + template + stream(const U0& u0) + { + open_impl(detail::forward(), u0); + } + template + stream(const U0& u0, const U1& u1) + { + open_impl(detail::forward(), u0, u1); + } + template + stream(const U0& u0, const U1& u1, const U2& u2) + { + open_impl(detail::forward(), u0, u1, u2); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------// + template + stream(U0& u0) + { + open_impl(detail::forward(), u0); + } + template + stream(U0& u0, const U1& u1) + { + open_impl(detail::forward(), u0, u1); + } + template + stream(U0& u0, const U1& u1, const U2& u2) + { + open_impl(detail::forward(), u0, u1, u2); + } +#endif // !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------// + template + void open(const U0& u0) + { + open_impl(detail::forward(), u0); + } + template + void open(const U0& u0, const U1& u1) + { + open_impl(detail::forward(), u0, u1); + } + template + void open(const U0& u0, const U1& u1, const U2& u2) + { + open_impl(detail::forward(), u0, u1, u2); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------// + template + void open(U0& u0) + { + open_impl(detail::forward(), u0); + } + template + void open(U0& u0, const U1& u1) + { + open_impl(detail::forward(), u0, u1); + } + template + void open(U0& u0, const U1& u1, const U2& u2) + { + open_impl(detail::forward(), u0, u1, u2); + } +#endif // !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------// + bool is_open() const { return this->member.is_open(); } + void close() { this->member.close(); } + bool auto_close() const { return this->member.auto_close(); } + void set_auto_close(bool close) { this->member.set_auto_close(close); } + bool strict_sync() { return this->member.strict_sync(); } + Device& operator*() { return *this->member; } + Device* operator->() { return &*this->member; } +private: + template + void open_impl(mpl::false_, const U0& u0) + { + this->clear(); + this->member.open(u0); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------// + template + void open_impl(mpl::false_, U0& u0) + { + this->clear(); + this->member.open(detail::wrap(u0)); + } +#endif // !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------// + template + void open_impl(mpl::true_, const U0& u0) + { + this->clear(); + this->member.open(Device(const_cast(u0))); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------// + template + void open_impl(mpl::true_, U0& u0) + { + this->clear(); + this->member.open(Device(u0)); + } +#endif // !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------// + template + void open_impl(mpl::false_, const U0& u0, const U1& u1) + { + this->clear(); + this->member.open(u0, u1); + } + template + void open_impl(mpl::true_, const U0& u0, const U1& u1) + { + this->clear(); + this->member.open(Device(const_cast(u0), u1)); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------// + template + void open_impl(mpl::true_, U0& u0, const U1& u1) + { + this->clear(); + this->member.open(Device(u0, u1)); + } +#endif // !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------// + template + void open_impl(mpl::false_, const U0& u0, const U1& u1, const U2& u2) + { + this->clear(); + this->member.open(u0, u1, u2); + } + template + void open_impl(mpl::true_, const U0& u0, const U1& u1, const U2& u2) + { + this->clear(); + this->member.open(Device(const_cast(u0), u1, u2)); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------// + template + void open_impl(mpl::true_, U0& u0, const U1& u1, const U2& u2) + { + this->clear(); + this->member.open(Device(u0, u1, u2)); + } +#endif +}; + +} } // End namespaces iostreams, boost. + +#endif BOOST_IOSTREAMS_DETAIL_BROKEN_OVERLOAD_RESOLUTION_STREAM_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/broken_overload_resolution/stream_buffer.hpp b/win32/include/boost/iostreams/detail/broken_overload_resolution/stream_buffer.hpp new file mode 100755 index 000000000..78404d1d9 --- /dev/null +++ b/win32/include/boost/iostreams/detail/broken_overload_resolution/stream_buffer.hpp @@ -0,0 +1,189 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_BROKEN_OVERLOAD_RESOLUTION_STREAM_BUFFER_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_BROKEN_OVERLOAD_RESOLUTION_STREAM_BUFFER_HPP_INCLUDED + +#include + +namespace boost { namespace iostreams { + +template< typename T, + typename Tr = + BOOST_IOSTREAMS_CHAR_TRAITS( + BOOST_DEDUCED_TYPENAME char_type_of::type + ), + typename Alloc = + std::allocator< + BOOST_DEDUCED_TYPENAME char_type_of::type + >, + typename Mode = BOOST_DEDUCED_TYPENAME mode_of::type > +class stream_buffer + : public detail::stream_buffer_traits::type +{ +private: + BOOST_STATIC_ASSERT(( + is_convertible< + BOOST_DEDUCED_TYPENAME iostreams::category_of::type, Mode + >::value + )); + typedef typename + detail::stream_buffer_traits< + T, Tr, Alloc, Mode + >::type base_type; + typedef T policy_type; +public: + typedef typename char_type_of::type char_type; + struct category + : Mode, + closable_tag, + streambuf_tag + { }; + BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr) + stream_buffer() { } + ~stream_buffer() + { + try { + if (this->is_open() && this->auto_close()) + this->close(); + } catch (...) { } + } + template + stream_buffer(const U0& u0) + { + open_impl(detail::forward(), u0); + } + template + stream_buffer(const U0& u0, const U1& u1) + { + open_impl(detail::forward(), u0, u1); + } + template + stream_buffer(const U0& u0, const U1& u1, const U2& u2) + { + open_impl(detail::forward(), u0, u1, u2); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------// + template + stream_buffer(U0& u0) + { + open_impl(detail::forward(), u0); + } + template + stream_buffer(U0& u0, const U1& u1) + { + open_impl(detail::forward(), u0, u1); + } + template + stream_buffer(U0& u0, const U1& u1, const U2& u2) + { + open_impl(detail::forward(), u0, u1, u2); + } +#endif // !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------// + template + void open(const U0& u0) + { + open_impl(detail::forward(), u0); + } + template + void open(const U0& u0, const U1& u1) + { + open_impl(detail::forward(), u0, u1); + } + template + void open(const U0& u0, const U1& u1, const U2& u2) + { + open_impl(detail::forward(), u0, u1, u2); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------// + template + void open(U0& u0) + { + open_impl(detail::forward(), u0); + } + template + void open(U0& u0, const U1& u1) + { + open_impl(detail::forward(), u0, u1); + } + template + void open(U0& u0, const U1& u1, const U2& u2) + { + open_impl(detail::forward(), u0, u1, u2); + } +#endif // !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------// + T& operator*() { return *this->component(); } + T* operator->() { return this->component(); } +private: + template + void open_impl(mpl::false_, const U0& u0) + { + base_type::open(const_cast(u0), -1, -1); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------// + template + void open_impl(mpl::false_, U0& u0) + { + base_type::open(detail::wrap(u0), -1, -1); + } +#endif // !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------// + template + void open_impl(mpl::true_, const U0& u0) + { + base_type::open(T(const_cast(u0)), -1, -1); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------// + template + void open_impl(mpl::true_, U0& u0) + { + base_type::open(T(u0), -1, -1); + } +#endif // !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------// + template + void open_impl(mpl::false_, const U0& u0, const U1& u1) + { + base_type::open(u0, u1, -1); + } + template + void open_impl(mpl::true_, const U0& u0, const U1& u1) + { + base_type::open(T(const_cast(u0), u1), -1, -1); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------// + template + void open_impl(mpl::true_, U0& u0, const U1& u1) + { + base_type::open(T(u0, u1), -1, -1); + } +#endif // !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------// + template + void open_impl(mpl::false_, const U0& u0, const U1& u1, const U2& u2) + { + base_type::open(u0, u1, u2); + } + template + void open_impl(mpl::true_, const U0& u0, const U1& u1, const U2& u2) + { + base_type::open(T(const_cast(u0), u1, u2), -1, -1); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------// + template + void open_impl(mpl::true_, U0& u0, const U1& u1, const U2& u2) + { + base_type::open(T(u0, u1, u2), -1, -1); + } +#endif // !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------// + void check_open() + { + if (this->is_open()) + throw BOOST_IOSTREAMS_FAILURE("already open"); + } +}; + +} } // End namespaces iostreams, boost. + +#endif // BOOST_IOSTREAMS_DETAIL_BROKEN_OVERLOAD_RESOLUTION_STREAM_BUFFER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/buffer.hpp b/win32/include/boost/iostreams/detail/buffer.hpp new file mode 100755 index 000000000..c67e440a5 --- /dev/null +++ b/win32/include/boost/iostreams/detail/buffer.hpp @@ -0,0 +1,200 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_BUFFERS_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_BUFFERS_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // swap. +#include // allocator. +#include // member templates. +#include +#include // streamsize. +#include +#include // int_type_of. +#include +#include +#include + +namespace boost { namespace iostreams { namespace detail { + +//----------------Buffers-----------------------------------------------------// + +// +// Template name: buffer +// Description: Character buffer. +// Template paramters: +// Ch - The character type. +// Alloc - The Allocator type. +// +template< typename Ch, + typename Alloc = std::allocator > +class basic_buffer { +private: +#ifndef BOOST_NO_STD_ALLOCATOR + typedef typename Alloc::template rebind::other allocator_type; +#else + typedef std::allocator allocator_type; +#endif +public: + basic_buffer(); + basic_buffer(int buffer_size); + ~basic_buffer(); + void resize(int buffer_size); + Ch* begin() const { return buf_; } + Ch* end() const { return buf_ + size_; } + Ch* data() const { return buf_; } + std::streamsize size() const { return size_; } + void swap(basic_buffer& rhs); +private: + // Disallow copying and assignment. + basic_buffer(const basic_buffer&); + basic_buffer& operator=(const basic_buffer&); + Ch* buf_; + std::streamsize size_; +}; + +template +void swap(basic_buffer& lhs, basic_buffer& rhs) +{ lhs.swap(rhs); } + +// +// Template name: buffer +// Description: Character buffer with two pointers accessible via ptr() and +// eptr(). +// Template paramters: +// Ch - A character type. +// +template< typename Ch, + typename Alloc = std::allocator > +class buffer : public basic_buffer { +private: + typedef basic_buffer base; +public: + typedef iostreams::char_traits traits_type; + using base::resize; + using base::data; + using base::size; + typedef Ch* const const_pointer; + buffer(int buffer_size); + Ch* & ptr() { return ptr_; } + const_pointer& ptr() const { return ptr_; } + Ch* & eptr() { return eptr_; } + const_pointer& eptr() const { return eptr_; } + void set(std::streamsize ptr, std::streamsize end); + void swap(buffer& rhs); + + // Returns an int_type as a status code. + template + typename int_type_of::type fill(Source& src) + { + using namespace std; + std::streamsize keep; + if ((keep = static_cast(eptr_ - ptr_)) > 0) + traits_type::move(this->data(), ptr_, keep); + set(0, keep); + std::streamsize result = + iostreams::read(src, this->data() + keep, this->size() - keep); + if (result != -1) + this->set(0, keep + result); + //return result == this->size() - keep ? + // traits_type::good() : + // keep == -1 ? + // traits_type::eof() : + // traits_type::would_block(); + return result == -1 ? + traits_type::eof() : + result == 0 ? + traits_type::would_block() : + traits_type::good(); + + } + + // Returns true if one or more characters were written. + template + bool flush(Sink& dest) + { + using namespace std; + std::streamsize amt = static_cast(eptr_ - ptr_); + std::streamsize result = iostreams::write_if(dest, ptr_, amt); + if (result < amt) { + traits_type::move( this->data(), + ptr_ + result, + amt - result ); + } + this->set(0, amt - result); + return result != 0; + } +private: + Ch *ptr_, *eptr_; +}; + +template +void swap(buffer& lhs, buffer& rhs) +{ lhs.swap(rhs); } + +//--------------Implementation of basic_buffer--------------------------------// + +template +basic_buffer::basic_buffer() : buf_(0), size_(0) { } + +template +basic_buffer::basic_buffer(int buffer_size) + : buf_(static_cast(allocator_type().allocate(buffer_size, 0))), + size_(buffer_size) // Cast for SunPro 5.3. + { } + +template +inline basic_buffer::~basic_buffer() +{ if (buf_) allocator_type().deallocate(buf_, size_); } + +template +inline void basic_buffer::resize(int buffer_size) +{ + if (size_ != buffer_size) { + basic_buffer temp(buffer_size); + std::swap(size_, temp.size_); + std::swap(buf_, temp.buf_); + } +} + +template +void basic_buffer::swap(basic_buffer& rhs) +{ + std::swap(buf_, rhs.buf_); + std::swap(size_, rhs.size_); +} + +//--------------Implementation of buffer--------------------------------------// + +template +buffer::buffer(int buffer_size) + : basic_buffer(buffer_size) { } + +template +inline void buffer::set(std::streamsize ptr, std::streamsize end) +{ + ptr_ = data() + ptr; + eptr_ = data() + end; +} + +template +inline void buffer::swap(buffer& rhs) +{ + base::swap(rhs); + std::swap(ptr_, rhs.ptr_); + std::swap(eptr_, rhs.eptr_); +} + +//----------------------------------------------------------------------------// + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_BUFFERS_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/call_traits.hpp b/win32/include/boost/iostreams/detail/call_traits.hpp new file mode 100755 index 000000000..3a6b1ff81 --- /dev/null +++ b/win32/include/boost/iostreams/detail/call_traits.hpp @@ -0,0 +1,32 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_VALUE_TYPE_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_VALUE_TYPE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include + +namespace boost { namespace iostreams { namespace detail { + +template +struct param_type { + typedef typename mpl::if_, T&, const T&>::type type; +}; + +template +struct value_type { + typedef typename mpl::if_, T&, T>::type type; +}; + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_VALUE_TYPE_HPP_INCLUDED //-----------// diff --git a/win32/include/boost/iostreams/detail/char_traits.hpp b/win32/include/boost/iostreams/detail/char_traits.hpp new file mode 100755 index 000000000..734599e87 --- /dev/null +++ b/win32/include/boost/iostreams/detail/char_traits.hpp @@ -0,0 +1,63 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// Provides std::char_traits for libraries without templated streams. Should not +// be confused with , which defines the +// template boost::iostreams::char_traits. + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_CHAR_TRAITS_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CHAR_TRAITS_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#ifdef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +# include // Make sure size_t is in std. +# include +# include +# include +#endif + +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //--------------------------------// +# define BOOST_IOSTREAMS_CHAR_TRAITS(ch) std::char_traits< ch > +#else +# define BOOST_IOSTREAMS_CHAR_TRAITS(ch) boost::iostreams::detail::char_traits + +namespace boost { namespace iostreams { namespace detail { + +struct char_traits { + typedef char char_type; + typedef int int_type; + typedef std::streampos pos_type; + typedef std::streamoff off_type; + + // Note: this may not be not conforming, since it treats chars as unsigned, + // but is only used to test for equality. + static int compare(const char* lhs, const char* rhs, std::size_t n) + { return std::strncmp(lhs, rhs, n); } + static char* copy(char *dest, const char *src, std::size_t n) + { return static_cast(std::memcpy(dest, src, n)); } + static char* move(char *dest, const char *src, std::size_t n) + { return static_cast(std::memmove(dest, src, n)); } + static const char* find(const char* s, std::size_t n, const char& c) + { return (const char*) (const void*) std::memchr(s, c, n); } + static char to_char_type(const int& c) { return c; } + static int to_int_type(const char& c) { return c; } + static bool eq_int_type(const int& lhs, const int& rhs) + { return lhs == rhs; } + static int eof() { return EOF; } + static int not_eof(const int& c) { return c != EOF ? c : '\n'; } +}; + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifdef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //-----------------------// + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CHAR_TRAITS_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/codecvt_helper.hpp b/win32/include/boost/iostreams/detail/codecvt_helper.hpp new file mode 100755 index 000000000..b3635436b --- /dev/null +++ b/win32/include/boost/iostreams/detail/codecvt_helper.hpp @@ -0,0 +1,238 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains the definition of the template codecvt_helper, useful for +// defining specializations of std::codecvt where state_type != mbstate_t. +// Compensates for the fact that some standard library implementations +// do not derive the primiary codecvt template from locale::facet or +// provide the correct member types and functions. + +// Usage: +// +// // In global namespace: +// BOOST_IOSTREAMS_CODECVT_SPEC(mystate) +// +// // In user namespace: +// template +// struct mycodecvt : codecvt_helper { ... }; +// +// // Or: +// struct mycodecvt : codecvt_helper { ... }; +// +// Etc. + +#ifndef BOOST_IOSTREAMS_DETAIL_CODECVT_HELPER_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CODECVT_HELPER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // Put size_t in std, BOOST_MSVC, Dinkum. +#include +#include // min. +#include // size_t. +#include // locale, codecvt_base, codecvt. +#include + +//------------------Definition of traits--------------------------------------// + +namespace boost { namespace iostreams { namespace detail { + +#if !BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) //-----------------------// + +template +struct codecvt_intern { typedef typename T::intern_type type; }; + +template +struct codecvt_extern { typedef typename T::extern_type type; }; + +#else // #if !BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) //--------------// + +template +struct codecvt_intern { typedef typename T::from_type type; }; + +template +struct codecvt_extern { typedef typename T::to_type type; }; + +#endif // #if !BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) //-------------// + +template +struct codecvt_state { typedef typename T::state_type type; }; + +} } } // End namespaces detail, iostreams, boost. + +//------------------Definition of codecvt_impl--------------------------------// + +#if defined(BOOST_IOSTREAMS_NO_PRIMARY_CODECVT_DEFINITION) || \ + defined(BOOST_IOSTREAMS_EMPTY_PRIMARY_CODECVT_DEFINITION) || \ + defined(BOOST_IOSTREAMS_NO_LOCALE) \ + /**/ + +namespace boost { namespace iostreams { namespace detail { + +template +struct codecvt_impl : std::locale::facet, std::codecvt_base { +public: + typedef Intern intern_type; + typedef Extern extern_type; + typedef State state_type; + + codecvt_impl(std::size_t refs = 0) : std::locale::facet(refs) { } + + std::codecvt_base::result + in( State& state, const Extern* first1, const Extern* last1, + const Extern*& next1, Intern* first2, Intern* last2, + Intern*& next2 ) const + { + return do_in(state, first1, last1, next1, first2, last2, next2); + } + + std::codecvt_base::result + out( State& state, const Intern* first1, const Intern* last1, + const Intern*& next1, Extern* first2, Extern* last2, + Extern*& next2 ) const + { + return do_out(state, first1, last1, next1, first2, last2, next2); + } + + std::codecvt_base::result + unshift(State& state, Extern* first2, Extern* last2, Extern*& next2) const + { + return do_unshift(state, first2, last2, next2); + } + + bool always_noconv() const throw() { return do_always_noconv(); } + + int max_length() const throw() { return do_max_length(); } + + int encoding() const throw() { return do_encoding(); } + + int length( BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER State& state, + const Extern* first1, const Extern* last1, + std::size_t len2 ) const throw() + { + return do_length(state, first1, last1, len2); + } +protected: + std::codecvt_base::result + virtual do_in( State&, const Extern*, const Extern*, const Extern*&, + Intern*, Intern*, Intern*& ) const + { + return std::codecvt_base::noconv; + } + + std::codecvt_base::result + virtual do_out( State&, const Intern*, const Intern*, const Intern*&, + Extern*, Extern*, Extern*& ) const + { + return std::codecvt_base::noconv; + } + + std::codecvt_base::result + virtual do_unshift( State& state, Extern* first2, Extern* last2, + Extern*& next2 ) const + { + return std::codecvt_base::ok; + } + + virtual bool do_always_noconv() const throw() { return true; } + + virtual int do_max_length() const throw() { return 1; } + + virtual int do_encoding() const throw() { return 1; } + + virtual int do_length( BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER State& state, + const Extern* first1, const Extern* last1, + std::size_t len2 ) const throw() + { + return (std::min)(static_cast(last1 - first1), len2); + } +}; + +} } } // End namespaces detail, iostreams, boost. + +#endif // no primary codecvt definition, empty definition. + +//------------------Definition of BOOST_IOSTREAMS_CODECVT_SPEC----------------// + +#if defined(BOOST_IOSTREAMS_NO_PRIMARY_CODECVT_DEFINITION) || \ + defined(BOOST_IOSTREAMS_EMPTY_PRIMARY_CODECVT_DEFINITION) \ + /**/ +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# define BOOST_IOSTREAMS_CODECVT_SPEC(state) \ + namespace std { \ + template \ + class codecvt \ + : public ::boost::iostreams::detail::codecvt_impl< \ + Intern, Extern, state \ + > \ + { \ + public: \ + codecvt(std::size_t refs = 0) \ + : ::boost::iostreams::detail::codecvt_impl< \ + Intern, Extern, state \ + >(refs) \ + { } \ + static std::locale::id id; \ + }; \ + template \ + std::locale::id codecvt::id; \ + } \ + /**/ +# else +# define BOOST_IOSTREAMS_CODECVT_SPEC(state) \ + namespace std { \ + template<> \ + class codecvt \ + : public ::boost::iostreams::detail::codecvt_impl< \ + wchar_t, char, state \ + > \ + { \ + public: \ + codecvt(std::size_t refs = 0) \ + : ::boost::iostreams::detail::codecvt_impl< \ + wchar_t, char, state \ + >(refs) \ + { } \ + static std::locale::id id; \ + }; \ + template<> \ + std::locale::id codecvt::id; \ + } \ + /**/ +# endif +#else +# define BOOST_IOSTREAMS_CODECVT_SPEC(state) +#endif // no primary codecvt definition, or empty definition. + +namespace boost { namespace iostreams { namespace detail { + +//------------------Definition of codecvt_helper------------------------------// + +template +struct codecvt_helper : std::codecvt { + typedef Intern intern_type; + typedef Extern extern_type; + typedef State state_type; + codecvt_helper(std::size_t refs = 0) + #if !defined(BOOST_IOSTREAMS_NO_CODECVT_CTOR_FROM_SIZE_T) + : std::codecvt(refs) + #else + : std::codecvt() + #endif + { } +#ifdef BOOST_IOSTREAMS_NO_CODECVT_MAX_LENGTH + int max_length() const throw() { return do_max_length(); } +protected: + virtual int do_max_length() const throw() { return 1; } +#endif +}; + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CODECVT_HELPER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/codecvt_holder.hpp b/win32/include/boost/iostreams/detail/codecvt_holder.hpp new file mode 100755 index 000000000..a0b730a1f --- /dev/null +++ b/win32/include/boost/iostreams/detail/codecvt_holder.hpp @@ -0,0 +1,63 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains machinery for performing code conversion. + +#ifndef BOOST_IOSTREAMS_DETAIL_CODECVT_HOLDER_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CODECVT_HOLDER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // mbstate_t. +#include // codecvt, locale. +#include // HAS_MACRO_USE_FACET. +#include + +namespace boost { namespace iostreams { namespace detail { + +struct default_codecvt { + typedef wchar_t intern_type, from_type; + typedef char extern_type, to_type; + typedef std::mbstate_t state_type; +}; + +template +struct codecvt_holder { + typedef Codecvt codecvt_type; + const codecvt_type& get() const { return codecvt_; } + void imbue(const std::locale&) { } + Codecvt codecvt_; +}; + +template<> +struct codecvt_holder { + typedef std::codecvt codecvt_type; + codecvt_holder() { reset_codecvt(); } + const codecvt_type& get() const { return *codecvt_; } + void imbue(const std::locale& loc) + { + loc_ = loc; + reset_codecvt(); + } + void reset_codecvt() + { + using namespace std; + #ifndef BOOST_HAS_MACRO_USE_FACET + codecvt_ = & use_facet< codecvt_type >(loc_); + #else + codecvt_ = & _USE(loc_, codecvt_type); + #endif + } + std::locale loc_; // Prevent codecvt_ from being freed. + const codecvt_type* codecvt_; +}; + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CODECVT_HOLDER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/config/auto_link.hpp b/win32/include/boost/iostreams/detail/config/auto_link.hpp new file mode 100755 index 000000000..6806e829e --- /dev/null +++ b/win32/include/boost/iostreams/detail/config/auto_link.hpp @@ -0,0 +1,49 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Adapted from and from +// http://www.boost.org/more/separate_compilation.html, by John Maddock. + +#ifndef BOOST_IOSTREAMS_DETAIL_AUTO_LINK_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_AUTO_LINK_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#if defined(BOOST_EXTERNAL_LIB_NAME) +# if defined(BOOST_MSVC) \ + || defined(__BORLANDC__) \ + || (defined(__MWERKS__) && defined(_WIN32) && (__MWERKS__ >= 0x3000)) \ + || (defined(__ICL) && defined(_MSC_EXTENSIONS) && (_MSC_VER >= 1200)) \ + /**/ +# pragma comment(lib, BOOST_EXTERNAL_LIB_NAME) +# endif +# undef BOOST_EXTERNAL_LIB_NAME +#endif + +//------------------Enable automatic library variant selection----------------// + +#if !defined(BOOST_IOSTREAMS_SOURCE) && \ + !defined(BOOST_ALL_NO_LIB) && \ + !defined(BOOST_IOSTREAMS_NO_LIB) \ + /**/ + +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it. +# define BOOST_LIB_NAME boost_iostreams + +// If we're importing code from a dll, then tell auto_link.hpp about it. +# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_IOSTREAMS_DYN_LINK) +# define BOOST_DYN_LINK +# endif + +// And include the header that does the work. +# include +#endif // auto-linking disabled + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_AUTO_LINK_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/config/bzip2.hpp b/win32/include/boost/iostreams/detail/config/bzip2.hpp new file mode 100755 index 000000000..9fc85487f --- /dev/null +++ b/win32/include/boost/iostreams/detail/config/bzip2.hpp @@ -0,0 +1,48 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Adapted from and from +// http://www.boost.org/more/separate_compilation.html, by John Maddock. + +#ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_BZIP2_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CONFIG_BZIP2_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#if defined(BOOST_BZIP2_BINARY) +# if defined(BOOST_MSVC) || \ + defined(__BORLANDC__) || \ + (defined(__MWERKS__) && defined(_WIN32) && (__MWERKS__ >= 0x3000)) || \ + (defined(__ICL) && defined(_MSC_EXTENSIONS) && (_MSC_VER >= 1200)) \ + /**/ + +// Specify the name of the .lib file. +# pragma comment(lib, BOOST_STRINGIZE(BOOST_BZIP2_BINARY)) +# endif +#else +# if !defined(BOOST_IOSTREAMS_SOURCE) && \ + !defined(BOOST_ALL_NO_LIB) && \ + !defined(BOOST_IOSTREAMS_NO_LIB) \ + /**/ + +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it. +# define BOOST_LIB_NAME boost_bzip2 + +// If we're importing code from a dll, then tell auto_link.hpp about it. +# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_IOSTREAMS_DYN_LINK) +# define BOOST_DYN_LINK +# endif + +// And include the header that does the work. +# include +# endif +#endif + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_BZIP2_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/config/codecvt.hpp b/win32/include/boost/iostreams/detail/config/codecvt.hpp new file mode 100755 index 000000000..7bb1307e5 --- /dev/null +++ b/win32/include/boost/iostreams/detail/config/codecvt.hpp @@ -0,0 +1,80 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_CODECVT_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CONFIG_CODECVT_HPP_INCLUDED + +#include +#include +#include +#include + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +//------------------Support for codecvt with user-defined state types---------// + +#if defined(__MSL_CPP__) || defined(__LIBCOMO__) || \ + BOOST_WORKAROUND(_STLPORT_VERSION, <= 0x450) \ + /**/ +# define BOOST_IOSTREAMS_NO_PRIMARY_CODECVT_DEFINITION +#endif + +#if defined(__GLIBCPP__) || defined(__GLIBCXX__) || \ + BOOST_WORKAROUND(_STLPORT_VERSION, > 0x450) \ + /**/ +# define BOOST_IOSTREAMS_EMPTY_PRIMARY_CODECVT_DEFINITION +#endif + +//------------------Check for codecvt ctor taking a reference count-----------// + +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) || \ + BOOST_WORKAROUND(_STLPORT_VERSION, < 0x461) \ + /**/ +# define BOOST_IOSTREAMS_NO_CODECVT_CTOR_FROM_SIZE_T +#endif + +//------------------Normalize codecvt::length---------------------------------// + +#if !defined(__MSL_CPP__) && !defined(__LIBCOMO__) && \ + (!defined(BOOST_RWSTD_VER) || BOOST_RWSTD_VER < 0x04010300) && \ + (!defined(__MACH__) || !defined(__INTEL_COMPILER)) + /**/ +# define BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER const +#else +# define BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER +#endif + +//------------------Check for codecvt::max_length-----------------------------// + +#if BOOST_WORKAROUND(_STLPORT_VERSION, < 0x461) +# define BOOST_IOSTREAMS_NO_CODECVT_MAX_LENGTH +#endif + +//------------------Put mbstate_t and codecvt in std--------------------------// + +#ifndef BOOST_IOSTREAMS_NO_LOCALE +# include +#endif + +// From Robert Ramey's version of utf8_codecvt_facet. +namespace std { + +#if defined(__LIBCOMO__) + using ::mbstate_t; +#elif defined(BOOST_DINKUMWARE_STDLIB) && !defined(__BORLANDC__) + using ::mbstate_t; +#elif defined(__SGI_STL_PORT) +#elif defined(BOOST_NO_STDC_NAMESPACE) + using ::codecvt; + using ::mbstate_t; +#endif + +} // End namespace std. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_CODECVT_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/config/disable_warnings.hpp b/win32/include/boost/iostreams/detail/config/disable_warnings.hpp new file mode 100755 index 000000000..3241e2770 --- /dev/null +++ b/win32/include/boost/iostreams/detail/config/disable_warnings.hpp @@ -0,0 +1,27 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#include // BOOST_MSVC. +#include // BOOST_WORKAROUND. + +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable:4127) // Conditional expression is constant. +# pragma warning(disable:4130) // Logical operation on address of string constant. +# pragma warning(disable:4224) // Parameter previously defined as type. +# pragma warning(disable:4244) // Conversion: possible loss of data. +# pragma warning(disable:4512) // Assignment operator could not be generated. +# pragma warning(disable:4706) // Assignment within conditional expression. +#else +# if BOOST_WORKAROUND(__BORLANDC__, < 0x600) +# pragma warn -8008 // Condition always true/false. +# pragma warn -8066 // Unreachable code. +# pragma warn -8071 // Conversion may lose significant digits. +# pragma warn -8072 // Suspicious pointer arithmetic. +# pragma warn -8080 // identifier declared but never used. +# endif +#endif diff --git a/win32/include/boost/iostreams/detail/config/dyn_link.hpp b/win32/include/boost/iostreams/detail/config/dyn_link.hpp new file mode 100755 index 000000000..d41b64f6c --- /dev/null +++ b/win32/include/boost/iostreams/detail/config/dyn_link.hpp @@ -0,0 +1,37 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Adapted from http://www.boost.org/more/separate_compilation.html, by +// John Maddock. + +#ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_DYN_LINK_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CONFIG_DYN_LINK_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include + +//------------------Enable dynamic linking on windows-------------------------// + +#ifdef BOOST_HAS_DECLSPEC +# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_IOSTREAMS_DYN_LINK) +# ifdef BOOST_IOSTREAMS_SOURCE +# define BOOST_IOSTREAMS_DECL __declspec(dllexport) +# else +# define BOOST_IOSTREAMS_DECL __declspec(dllimport) +# endif +# endif +#endif + +#ifndef BOOST_IOSTREAMS_DECL +# define BOOST_IOSTREAMS_DECL +#endif + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_DYN_LINK_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/config/enable_warnings.hpp b/win32/include/boost/iostreams/detail/config/enable_warnings.hpp new file mode 100755 index 000000000..3e039dfe4 --- /dev/null +++ b/win32/include/boost/iostreams/detail/config/enable_warnings.hpp @@ -0,0 +1,18 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#else +# if BOOST_WORKAROUND(__BORLANDC__, < 0x600) +# pragma warn .8008 // Condition always true/false. +# pragma warn .8066 // Unreachable code. +# pragma warn .8071 // Conversion may lose significant digits. +# pragma warn .8072 // Suspicious pointer arithmetic. +# pragma warn .8080 // identifier declared but never used. +# endif +#endif diff --git a/win32/include/boost/iostreams/detail/config/fpos.hpp b/win32/include/boost/iostreams/detail/config/fpos.hpp new file mode 100755 index 000000000..0bb4f5231 --- /dev/null +++ b/win32/include/boost/iostreams/detail/config/fpos.hpp @@ -0,0 +1,31 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + + * File: boost/iostreams/detail/execute.hpp + * Date: Thu Dec 06 13:21:54 MST 2007 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + * + * Defines the preprocessor symbol BOOST_IOSTREAMS_HAS_DINKUMWARE_FPOS for + * platforms that use the implementation of std::fpos from the Dinkumware + * Standard Library. + */ + +#ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_FPOS_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CONFIG_FPOS_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +# if (defined(_YVALS) || defined(_CPPLIB_VER)) && !defined(__SGI_STL_PORT) && \ + !defined(_STLPORT_VERSION) && !defined(__QNX__) + /**/ +# define BOOST_IOSTREAMS_HAS_DINKUMWARE_FPOS +# endif + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_FPOS_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/config/gcc.hpp b/win32/include/boost/iostreams/detail/config/gcc.hpp new file mode 100755 index 000000000..4eab94c13 --- /dev/null +++ b/win32/include/boost/iostreams/detail/config/gcc.hpp @@ -0,0 +1,24 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Adapted from and from +// http://www.boost.org/more/separate_compilation.html, by John Maddock. + +#ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_GCC_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CONFIG_GCC_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // BOOST_INTEL. + +#if defined(__GNUC__) && !defined(BOOST_INTEL) +# define BOOST_IOSTREAMS_GCC (__GNUC__ * 100 + __GNUC_MINOR__) +#endif + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_GCC_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/config/limits.hpp b/win32/include/boost/iostreams/detail/config/limits.hpp new file mode 100755 index 000000000..3f8c3cd32 --- /dev/null +++ b/win32/include/boost/iostreams/detail/config/limits.hpp @@ -0,0 +1,19 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_LIMITS_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CONFIG_LIMITS_HPP_INCLUDED + +#ifndef BOOST_IOSTREAMS_MAX_FORWARDING_ARITY +# define BOOST_IOSTREAMS_MAX_FORWARDING_ARITY 3 +#endif + +#ifndef BOOST_IOSTREAMS_MAX_EXECUTE_ARITY +# define BOOST_IOSTREAMS_MAX_EXECUTE_ARITY 5 +#endif + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_LIMITS_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/config/overload_resolution.hpp b/win32/include/boost/iostreams/detail/config/overload_resolution.hpp new file mode 100755 index 000000000..f16fa7a46 --- /dev/null +++ b/win32/include/boost/iostreams/detail/config/overload_resolution.hpp @@ -0,0 +1,32 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Adapted from and from +// http://www.boost.org/more/separate_compilation.html, by John Maddock. + +#ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_BROKEN_OVERLOAD_RESOLUTION_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CONFIG_BROKEN_OVERLOAD_RESOLUTION_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // BOOST_MSVC. +#include +#include + +#if !defined(BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION) +# if BOOST_WORKAROUND(__MWERKS__, <= 0x3003) || \ + BOOST_WORKAROUND(__BORLANDC__, < 0x600) || \ + BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || \ + BOOST_WORKAROUND(BOOST_IOSTREAMS_GCC, <= 295) \ + /**/ +# define BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION +# endif +#endif + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_BROKEN_OVERLOAD_RESOLUTION_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/config/rtl.hpp b/win32/include/boost/iostreams/detail/config/rtl.hpp new file mode 100755 index 000000000..e5fd7f4b3 --- /dev/null +++ b/win32/include/boost/iostreams/detail/config/rtl.hpp @@ -0,0 +1,68 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + * + * Defines preprocessor symbols expanding to the names of functions in the + * C runtime library used to access file descriptors and to the type used + * to store file offsets for seeking. + * + * File: boost/iostreams/detail/config/rtl.hpp + * Date: Wed Dec 26 11:58:11 MST 2007 + * + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + */ + +#ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_RTL_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CONFIG_RTL_HPP_INCLUDED + +#include +#include + +// Handle open, close, read, and write +#ifdef __BORLANDC__ +# define BOOST_IOSTREAMS_RTL(x) BOOST_JOIN(_rtl_, x) +#elif defined BOOST_IOSTREAMS_WINDOWS +# define BOOST_IOSTREAMS_RTL(x) BOOST_JOIN(_, x) +#else +# define BOOST_IOSTREAMS_RTL(x) ::x // Distinguish from member function named x +#endif +#define BOOST_IOSTREAMS_FD_OPEN BOOST_IOSTREAMS_RTL(open) +#define BOOST_IOSTREAMS_FD_CLOSE BOOST_IOSTREAMS_RTL(close) +#define BOOST_IOSTREAMS_FD_READ BOOST_IOSTREAMS_RTL(read) +#define BOOST_IOSTREAMS_FD_WRITE BOOST_IOSTREAMS_RTL(write) + +// Handle lseek, off_t, ftruncate, and stat +#ifdef BOOST_IOSTREAMS_WINDOWS +# if defined(BOOST_MSVC) || defined(__MSVCRT__) // MSVC, MinGW +# define BOOST_IOSTREAMS_FD_SEEK _lseeki64 +# define BOOST_IOSTREAMS_FD_OFFSET __int64 +# else // Borland, Metrowerks, ... +# define BOOST_IOSTREAMS_FD_SEEK lseek +# define BOOST_IOSTREAMS_FD_OFFSET long +# endif +#else // Non-windows +# if defined(_LARGEFILE64_SOURCE) && \ + (!defined(_FILE_OFFSET_BITS) || _FILE_OFFSET_BITS != 64) || \ + defined(_AIX) && !defined(_LARGE_FILES) || \ + defined(BOOST_IOSTREAMS_HAS_LARGE_FILE_EXTENSIONS) + /**/ + + /* Systems with transitional extensions for large file support */ + +# define BOOST_IOSTREAMS_FD_SEEK lseek64 +# define BOOST_IOSTREAMS_FD_TRUNCATE ftruncate64 +# define BOOST_IOSTREAMS_FD_STAT stat64 +# define BOOST_IOSTREAMS_FD_OFFSET off64_t +# else +# define BOOST_IOSTREAMS_FD_SEEK lseek +# define BOOST_IOSTREAMS_FD_TRUNCATE ftruncate +# define BOOST_IOSTREAMS_FD_STAT stat +# define BOOST_IOSTREAMS_FD_OFFSET off_t +# endif +#endif + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_RTL_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/config/wide_streams.hpp b/win32/include/boost/iostreams/detail/config/wide_streams.hpp new file mode 100755 index 000000000..274590bc7 --- /dev/null +++ b/win32/include/boost/iostreams/detail/config/wide_streams.hpp @@ -0,0 +1,55 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Adapted from http://www.boost.org/more/separate_compilation.html, by +// John Maddock. + +#ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_WIDE_STREAMS_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CONFIG_WIDE_STREAMS_HPP_INCLUDED + +#include +#include +#include + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +//------------------Templated stream support----------------------------------// + +// From boost/dynamic_bitset.hpp; thanks to Matthias Troyer for cray patch. +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +# if defined(__STL_CONFIG_H) && \ + !defined (__STL_USE_NEW_IOSTREAMS) && !defined(__crayx1) \ + /**/ +# define BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +# endif +#endif // #ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES + +//------------------Wide stream support---------------------------------------// + +#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS +# if defined(BOOST_IOSTREAMS_NO_STREAM_TEMPLATES) || \ + defined (BOOST_NO_STD_WSTREAMBUF) && \ + ( !defined(__MSL_CPP__) || defined(_MSL_NO_WCHART_CPP_SUPPORT) ) \ + /**/ +# define BOOST_IOSTREAMS_NO_WIDE_STREAMS +# endif +#endif // #ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS + +//------------------Locale support--------------------------------------------// + +#ifndef BOOST_IOSTREAMS_NO_LOCALE +# if defined(BOOST_NO_STD_LOCALE) || \ + defined(__CYGWIN__) && \ + ( !defined(__MSL_CPP__) || defined(_MSL_NO_WCHART_CPP_SUPPORT) ) \ + /**/ +# define BOOST_IOSTREAMS_NO_LOCALE +# endif +#endif // #ifndef BOOST_IOSTREAMS_NO_LOCALE + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_WIDE_STREAMS_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/config/windows_posix.hpp b/win32/include/boost/iostreams/detail/config/windows_posix.hpp new file mode 100755 index 000000000..8873339df --- /dev/null +++ b/win32/include/boost/iostreams/detail/config/windows_posix.hpp @@ -0,0 +1,25 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// (C) Copyright 2002, 2003 Beman Dawes Boost.Filesystem +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_WINDOWS_POSIX_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CONFIG_WINDOWS_POSIX_HPP_INCLUDED + +//------------------From boost/libs/filesystem/src/path_posix_windows.cpp-----// + +// BOOST_IOSTREAMS_POSIX or BOOST_IOSTREAMS_WINDOWS specify which API to use. +#if !defined( BOOST_IOSTREAMS_WINDOWS ) && !defined( BOOST_IOSTREAMS_POSIX ) +# if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && \ + !defined(__CYGWIN__) \ + /**/ +# define BOOST_IOSTREAMS_WINDOWS +# else +# define BOOST_IOSTREAMS_POSIX +# endif +#endif + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_WINDOWS_POSIX_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/config/zlib.hpp b/win32/include/boost/iostreams/detail/config/zlib.hpp new file mode 100755 index 000000000..db8ba6e5f --- /dev/null +++ b/win32/include/boost/iostreams/detail/config/zlib.hpp @@ -0,0 +1,50 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Adapted from and from +// http://www.boost.org/more/separate_compilation.html, by John Maddock. + +#ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_ZLIB_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CONFIG_ZLIB_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // BOOST_STRINGIZE. + +#if defined(BOOST_ZLIB_BINARY) +# if defined(BOOST_MSVC) || \ + defined(__BORLANDC__) || \ + (defined(__MWERKS__) && defined(_WIN32) && (__MWERKS__ >= 0x3000)) || \ + (defined(__ICL) && defined(_MSC_EXTENSIONS) && (_MSC_VER >= 1200)) \ + /**/ + +// Specify the name of the .lib file. +# pragma comment(lib, BOOST_STRINGIZE(BOOST_ZLIB_BINARY)) +# endif +#else +# if !defined(BOOST_IOSTREAMS_SOURCE) && \ + !defined(BOOST_ALL_NO_LIB) && \ + !defined(BOOST_IOSTREAMS_NO_LIB) \ + /**/ + +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it. +# define BOOST_LIB_NAME boost_zlib + +// If we're importing code from a dll, then tell auto_link.hpp about it. +# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_IOSTREAMS_DYN_LINK) +# define BOOST_DYN_LINK +# endif + +// And include the header that does the work. +# include +# endif +#endif + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CONFIG_ZLIB_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/counted_array.hpp b/win32/include/boost/iostreams/detail/counted_array.hpp new file mode 100755 index 000000000..a2c5ba160 --- /dev/null +++ b/win32/include/boost/iostreams/detail/counted_array.hpp @@ -0,0 +1,64 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_COUNTED_ARRAY_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_COUNTED_ARRAY_HPP_INCLUDED + +#include // min. +#include +#include +#include // streamsize. + +namespace boost { namespace iostreams { namespace detail { + +template +class counted_array_source { +public: + typedef Ch char_type; + typedef source_tag category; + counted_array_source(const Ch* buf, std::streamsize size) + : buf_(buf), ptr_(0), end_(size) + { } + std::streamsize read(Ch* s, std::streamsize n) + { + std::streamsize result = (std::min)(n, end_ - ptr_); + BOOST_IOSTREAMS_CHAR_TRAITS(char_type)::copy + (s, buf_ + ptr_, result); + ptr_ += result; + return result; + } + std::streamsize count() const { return ptr_; } +private: + const Ch* buf_; + std::streamsize ptr_, end_; +}; + +template +struct counted_array_sink { +public: + typedef Ch char_type; + typedef sink_tag category; + counted_array_sink(Ch* buf, std::streamsize size) + : buf_(buf), ptr_(0), end_(size) + { } + std::streamsize write(const Ch* s, std::streamsize n) + { + std::streamsize result = (std::min)(n, end_ - ptr_); + BOOST_IOSTREAMS_CHAR_TRAITS(char_type)::copy + (buf_ + ptr_, s, result); + ptr_ += result; + return result; + } + std::streamsize count() const { return ptr_; } +private: + Ch* buf_; + std::streamsize ptr_, end_; +}; + +} } } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_COUNTED_ARRAY_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/current_directory.hpp b/win32/include/boost/iostreams/detail/current_directory.hpp new file mode 100755 index 000000000..930b7ed53 --- /dev/null +++ b/win32/include/boost/iostreams/detail/current_directory.hpp @@ -0,0 +1,60 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + + * File: boost/iostreams/detail/execute.hpp + * Date: Thu Dec 06 13:21:54 MST 2007 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + * + * Defines the function boost::iostreams::detail::current_directory, used by + * boost::iostreams::detail::absolute_path. + */ + +#ifndef BOOST_IOSTREAMS_DETAIL_CURRENT_DIRECTORY_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CURRENT_DIRECTORY_HPP_INCLUDED + +#include // make sure size_t is in std. +#include // size_t +#include +#include +#include +#include +#ifdef BOOST_IOSTREAMS_WINDOWS +# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +# include +#else +# include // sysconf. +#endif + +namespace boost { namespace iostreams { namespace detail { + +// Returns the current working directory +inline std::string current_directory() +{ +#ifdef BOOST_IOSTREAMS_WINDOWS + DWORD length; + basic_buffer buf(MAX_PATH); + while (true) { + length = ::GetCurrentDirectoryA(buf.size(), buf.data()); + if (!length) + throw_system_failure("failed determining current directory"); + if (length < static_cast(buf.size())) + break; + buf.resize(buf.size() * 2); + } + return std::string(buf.data(), length); +#else // #ifdef BOOST_IOSTREAMS_WINDOWS + basic_buffer buf(pathconf(".", _PC_PATH_MAX)); + if (!getcwd(buf.data(), static_cast(buf.size()))) + throw_system_failure("failed determining current directory"); + return std::string(buf.data()); +#endif // #ifdef BOOST_IOSTREAMS_WINDOWS +} + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CURRENT_DIRECTORY_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/default_arg.hpp b/win32/include/boost/iostreams/detail/default_arg.hpp new file mode 100755 index 000000000..0d09a68f4 --- /dev/null +++ b/win32/include/boost/iostreams/detail/default_arg.hpp @@ -0,0 +1,25 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_DEFAULT_ARG_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_DEFAULT_ARG_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +# include +# define BOOST_IOSTREAMS_DEFAULT_ARG(arg) mpl::identity< arg >::type +#else +# define BOOST_IOSTREAMS_DEFAULT_ARG(arg) arg +#endif + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_DEFAULT_ARG_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/dispatch.hpp b/win32/include/boost/iostreams/detail/dispatch.hpp new file mode 100755 index 000000000..1ececca54 --- /dev/null +++ b/win32/include/boost/iostreams/detail/dispatch.hpp @@ -0,0 +1,41 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_DISPATCH_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_DISPATCH_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // BOOST_DEDUCED_TYPENAME. +#include +#include // category_of. +#include +#include + +namespace boost { namespace iostreams {namespace detail { + +template< typename T, typename Tag1, typename Tag2, + typename Tag3 = mpl::void_, typename Tag4 = mpl::void_, + typename Tag5 = mpl::void_, typename Tag6 = mpl::void_, + typename Category = + BOOST_DEDUCED_TYPENAME category_of::type > +struct dispatch + : iostreams::select< // Disambiguation for Tru64. + is_convertible, Tag1, + is_convertible, Tag2, + is_convertible, Tag3, + is_convertible, Tag4, + is_convertible, Tag5, + is_convertible, Tag6 + > + { }; + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_DISPATCH_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/double_object.hpp b/win32/include/boost/iostreams/detail/double_object.hpp new file mode 100755 index 000000000..6c9680362 --- /dev/null +++ b/win32/include/boost/iostreams/detail/double_object.hpp @@ -0,0 +1,114 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains the definition of the class template +// boost::iostreams::detail::double_object, which is similar to compressed pair +// except that both members of the pair have the same type, and +// compression occurs only if requested using a boolean template +// parameter. + +#ifndef BOOST_IOSTREAMS_DETAIL_DOUBLE_OBJECT_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_DOUBLE_OBJECT_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // swap. +#include +#include +#if BOOST_WORKAROUND(__MWERKS__, > 0x3003) +# include +#else +# include +#endif + +namespace boost { namespace iostreams { namespace detail { + +template +class single_object_holder { +public: +#if BOOST_WORKAROUND(__MWERKS__, > 0x3003) + typedef Metrowerks::call_traits traits_type; +#else + typedef boost::call_traits traits_type; +#endif + typedef typename traits_type::param_type param_type; + typedef typename traits_type::reference reference; + typedef typename traits_type::const_reference const_reference; + single_object_holder() { } + single_object_holder(param_type t) : first_(t) { } + reference first() { return first_; } + const_reference first() const { return first_; } + reference second() { return first_; } + const_reference second() const { return first_; } + void swap(single_object_holder& o) + { std::swap(first_, o.first_); } +private: + T first_; +}; + +template +struct double_object_holder { +public: +#if BOOST_WORKAROUND(__MWERKS__, > 0x3003) + typedef Metrowerks::call_traits traits_type; +#else + typedef boost::call_traits traits_type; +#endif + typedef typename traits_type::param_type param_type; + typedef typename traits_type::reference reference; + typedef typename traits_type::const_reference const_reference; + double_object_holder() { } + double_object_holder(param_type t1, param_type t2) + : first_(t1), second_(t2) { } + reference first() { return first_; } + const_reference first() const { return first_; } + reference second() { return second_; } + const_reference second() const { return second_; } + void swap(double_object_holder& d) + { + std::swap(first_, d.first_); + std::swap(second_, d.second_); + } +private: + T first_, second_; +}; + +template +class double_object + : public mpl::if_< + IsDouble, + double_object_holder, + single_object_holder + >::type +{ +private: + typedef typename + mpl::if_< + IsDouble, + double_object_holder, + single_object_holder + >::type base_type; +public: +#if BOOST_WORKAROUND(__MWERKS__, > 0x3003) + typedef Metrowerks::call_traits traits_type; +#else + typedef boost::call_traits traits_type; +#endif + typedef typename traits_type::param_type param_type; + typedef typename traits_type::reference reference; + typedef typename traits_type::const_reference const_reference; + double_object() : base_type() {} + double_object(param_type t1, param_type t2) + : base_type(t1, t2) { } + bool is_double() const { return IsDouble::value; } +}; + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_DOUBLE_OBJECT_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/enable_if_stream.hpp b/win32/include/boost/iostreams/detail/enable_if_stream.hpp new file mode 100755 index 000000000..5f0076e60 --- /dev/null +++ b/win32/include/boost/iostreams/detail/enable_if_stream.hpp @@ -0,0 +1,32 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_ENABLE_IF_STREAM_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_ENABLE_IF_STREAM_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // BOOST_NO_SFINAE. +#include +#include // is_std_io. + +#if !defined(BOOST_NO_SFINAE) && \ + !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) +# define BOOST_IOSTREAMS_ENABLE_IF_STREAM(T) \ + , typename boost::enable_if< boost::iostreams::is_std_io >::type* = 0 \ + /**/ +# define BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) \ + , typename boost::disable_if< boost::iostreams::is_std_io >::type* = 0 \ + /**/ +#else +# define BOOST_IOSTREAMS_ENABLE_IF_STREAM(T) +# define BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) +#endif + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_ENABLE_IF_STREAM_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/error.hpp b/win32/include/boost/iostreams/detail/error.hpp new file mode 100755 index 000000000..d5b9a3b20 --- /dev/null +++ b/win32/include/boost/iostreams/detail/error.hpp @@ -0,0 +1,45 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_ERROR_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_ERROR_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // failure. + +namespace boost { namespace iostreams { namespace detail { + +inline BOOST_IOSTREAMS_FAILURE cant_read() +{ return BOOST_IOSTREAMS_FAILURE("no read access"); } + +inline BOOST_IOSTREAMS_FAILURE cant_write() +{ return BOOST_IOSTREAMS_FAILURE("no write access"); } + +inline BOOST_IOSTREAMS_FAILURE cant_seek() +{ return BOOST_IOSTREAMS_FAILURE("no random access"); } + +inline BOOST_IOSTREAMS_FAILURE bad_read() +{ return BOOST_IOSTREAMS_FAILURE("bad read"); } + +inline BOOST_IOSTREAMS_FAILURE bad_putback() +{ return BOOST_IOSTREAMS_FAILURE("putback buffer full"); } + +inline BOOST_IOSTREAMS_FAILURE bad_write() +{ return BOOST_IOSTREAMS_FAILURE("bad write"); } + +inline BOOST_IOSTREAMS_FAILURE write_area_exhausted() +{ return BOOST_IOSTREAMS_FAILURE("write area exhausted"); } + +inline BOOST_IOSTREAMS_FAILURE bad_seek() +{ return BOOST_IOSTREAMS_FAILURE("bad seek"); } + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_ERROR_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/execute.hpp b/win32/include/boost/iostreams/detail/execute.hpp new file mode 100755 index 000000000..8e7f1664d --- /dev/null +++ b/win32/include/boost/iostreams/detail/execute.hpp @@ -0,0 +1,135 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + + * File: boost/iostreams/detail/execute.hpp + * Date: Thu Dec 06 13:21:54 MST 2007 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + + * Defines the overloaded function template + * boost::iostreams::detail::execute_all() and the function template + * boost::iostreams::detail::execute_foreach(). + * + * execute_all() invokes a primary operation and performs a sequence of cleanup + * operations, returning the result of the primary operation if no exceptions + * are thrown. If one of the operations throws an exception, performs the + * remaining operations and rethrows the initial exception. + * + * execute_foreach() is a variant of std::foreach which invokes a function + * object for each item in a sequence, catching all execptions and rethrowing + * the first caught exception after the function object has been invoked on each + * item. + */ + +#ifndef BOOST_IOSTREAMS_DETAIL_EXECUTE_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_EXECUTE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include // MAX_EXECUTE_ARITY +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace iostreams { namespace detail { + +// Helper for class template execute_traits. +template +struct execute_traits_impl { + typedef Result result_type; + template + static Result execute(Op op) { return op(); } +}; + +// Specialization for void return. For simplicity, execute() returns int +// for operations returning void. This could be avoided with additional work. +template<> +struct execute_traits_impl { + typedef int result_type; + template + static int execute(Op op) { op(); return 0; } +}; + +// Deduces the result type of Op and allows uniform treatment of operations +// returning void and non-void. +template< typename Op, + typename Result = // VC6.5 workaround. + #if !defined(BOOST_NO_RESULT_OF) && \ + !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) + typename boost::result_of::type + #else + BOOST_DEDUCED_TYPENAME Op::result_type + #endif + > +struct execute_traits + : execute_traits_impl + { }; + +// Implementation with no cleanup operations. +template +typename execute_traits::result_type +execute_all(Op op) +{ + return execute_traits::execute(op); +} + +// Implementation with one or more cleanup operations +#define BOOST_PP_LOCAL_MACRO(n) \ + template \ + typename execute_traits::result_type \ + execute_all(Op op, BOOST_PP_ENUM_BINARY_PARAMS(n, C, c)) \ + { \ + typename execute_traits::result_type r; \ + try { \ + r = boost::iostreams::detail::execute_all( \ + op BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \ + BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(n), c) \ + ); \ + } catch (...) { \ + try { \ + BOOST_PP_CAT(c, BOOST_PP_DEC(n))(); \ + } catch (...) { } \ + throw; \ + } \ + BOOST_PP_CAT(c, BOOST_PP_DEC(n))(); \ + return r; \ + } \ + /**/ + +#define BOOST_PP_LOCAL_LIMITS (1, BOOST_IOSTREAMS_MAX_EXECUTE_ARITY) +#include BOOST_PP_LOCAL_ITERATE() +#undef BOOST_PP_LOCAL_MACRO + +template +Op execute_foreach(InIt first, InIt last, Op op) +{ + if (first == last) + return op; + try { + op(*first); + } catch (...) { + try { + ++first; + boost::iostreams::detail::execute_foreach(first, last, op); + } catch (...) { } + throw; + } + ++first; + return boost::iostreams::detail::execute_foreach(first, last, op); +} + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_EXECUTE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/forward.hpp b/win32/include/boost/iostreams/detail/forward.hpp new file mode 100755 index 000000000..6feb5ccc1 --- /dev/null +++ b/win32/include/boost/iostreams/detail/forward.hpp @@ -0,0 +1,102 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_FORWARD_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_FORWARD_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // BOOST_MSVC +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//------Macros for defining forwarding constructors and open overloads--------// + +// +// Macro: BOOST_IOSTREAMS_DEFINE_FORWARDING_FUNCTIONS(mode, name, helper). +// Description: Defines constructors and overloads of 'open' which construct +// a device using the given argument list and pass it to 'open_impl'. +// Assumes that 'policy_type' is an alias for the device type. +// Not supported on Intel 7.1 and VC6.5. +// +#define BOOST_IOSTREAMS_FORWARD(class, impl, policy, params, args) \ + class(const policy& t params()) \ + { this->impl(::boost::iostreams::detail::wrap(t) args()); } \ + class(policy& t params()) \ + { this->impl(::boost::iostreams::detail::wrap(t) args()); } \ + class(const ::boost::reference_wrapper& ref params()) \ + { this->impl(ref args()); } \ + void open(const policy& t params()) \ + { this->impl(::boost::iostreams::detail::wrap(t) args()); } \ + void open(policy& t params()) \ + { this->impl(::boost::iostreams::detail::wrap(t) args()); } \ + void open(const ::boost::reference_wrapper& ref params()) \ + { this->impl(ref args()); } \ + BOOST_PP_REPEAT_FROM_TO( \ + 1, BOOST_PP_INC(BOOST_IOSTREAMS_MAX_FORWARDING_ARITY), \ + BOOST_IOSTREAMS_FORWARDING_CTOR, (class, impl, policy) \ + ) \ + BOOST_PP_REPEAT_FROM_TO( \ + 1, BOOST_PP_INC(BOOST_IOSTREAMS_MAX_FORWARDING_ARITY), \ + BOOST_IOSTREAMS_FORWARDING_FN, (class, impl, policy) \ + ) \ + /**/ +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) +# define BOOST_IOSTREAMS_FORWARDING_CTOR_I(z, n, tuple) \ + template< typename U100 BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \ + BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), typename U) > \ + BOOST_PP_TUPLE_ELEM(3, 0, tuple) \ + ( U100& u100 BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \ + BOOST_PP_ENUM_BINARY_PARAMS_Z(z, BOOST_PP_DEC(n), const U, &u)) \ + { this->BOOST_PP_TUPLE_ELEM(3, 1, tuple) \ + ( BOOST_PP_TUPLE_ELEM(3, 2, tuple) \ + ( u100 BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \ + BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), u)) ); } \ + /**/ +# define BOOST_IOSTREAMS_FORWARDING_FN_I(z, n, tuple) \ + template< typename U100 BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \ + BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), typename U) > \ + void open \ + ( U100& u100 BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \ + BOOST_PP_ENUM_BINARY_PARAMS_Z(z, BOOST_PP_DEC(n), const U, &u)) \ + { this->BOOST_PP_TUPLE_ELEM(3, 1, tuple) \ + ( u100 BOOST_PP_COMMA_IF(BOOST_PP_DEC(n)) \ + BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_DEC(n), u) ); } \ + /**/ +#else +# define BOOST_IOSTREAMS_FORWARDING_CTOR_I(z, n, tuple) +# define BOOST_IOSTREAMS_FORWARDING_FN_I(z, n, tuple) +#endif +#define BOOST_IOSTREAMS_FORWARDING_CTOR(z, n, tuple) \ + template \ + BOOST_PP_TUPLE_ELEM(3, 0, tuple) \ + (BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, const U, &u)) \ + { this->BOOST_PP_TUPLE_ELEM(3, 1, tuple) \ + ( BOOST_PP_TUPLE_ELEM(3, 2, tuple) \ + (BOOST_PP_ENUM_PARAMS_Z(z, n, u)) ); } \ + BOOST_IOSTREAMS_FORWARDING_CTOR_I(z, n, tuple) \ + /**/ +#define BOOST_IOSTREAMS_FORWARDING_FN(z, n, tuple) \ + template \ + void open(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, const U, &u)) \ + { this->BOOST_PP_TUPLE_ELEM(3, 1, tuple) \ + ( BOOST_PP_TUPLE_ELEM(3, 2, tuple) \ + (BOOST_PP_ENUM_PARAMS_Z(z, n, u)) ); } \ + BOOST_IOSTREAMS_FORWARDING_FN_I(z, n, tuple) \ + /**/ + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_FORWARD_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/fstream.hpp b/win32/include/boost/iostreams/detail/fstream.hpp new file mode 100755 index 000000000..f2ef8c1cb --- /dev/null +++ b/win32/include/boost/iostreams/detail/fstream.hpp @@ -0,0 +1,33 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_FSTREAM_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_FSTREAM_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +# include +#else +# include +#endif + +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +# define BOOST_IOSTREAMS_BASIC_IFSTREAM(Ch, Tr) std::basic_ifstream +# define BOOST_IOSTREAMS_BASIC_OFSTREAM(Ch, Tr) std::basic_ofstream +# define BOOST_IOSTREAMS_BASIC_FSTREAM(Ch, Tr) std::basic_fstream +# define BOOST_IOSTREAMS_BASIC_FILEBUF(Ch) std::basic_filebuf +#else +# define BOOST_IOSTREAMS_BASIC_IFSTREAM(Ch, Tr) std::ifstream +# define BOOST_IOSTREAMS_BASIC_OFSTREAM(Ch, Tr) std::ofstream +# define BOOST_IOSTREAMS_BASIC_FILEBUF(Ch) std::filebuf +#endif + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_FSTREAM_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/functional.hpp b/win32/include/boost/iostreams/detail/functional.hpp new file mode 100755 index 000000000..cec322a7d --- /dev/null +++ b/win32/include/boost/iostreams/detail/functional.hpp @@ -0,0 +1,189 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + + * File: boost/iostreams/detail/functional.hpp + * Date: Sun Dec 09 05:38:03 MST 2007 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + + * Defines several function objects and object generators for use with + * execute_all() + */ + +#ifndef BOOST_IOSTREAMS_DETAIL_FUNCTIONAL_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_FUNCTIONAL_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include // BOOST_IOS + +namespace boost { namespace iostreams { namespace detail { + + // Function objects and object generators for invoking + // boost::iostreams::close + +template +class device_close_operation { +public: + typedef void result_type; + device_close_operation(T& t, BOOST_IOS::openmode which) + : t_(t), which_(which) + { } + void operator()() const { boost::iostreams::close(t_, which_); } +private: + device_close_operation& operator=(const device_close_operation&); + T& t_; + BOOST_IOS::openmode which_; +}; + +template +class filter_close_operation { +public: + typedef void result_type; + filter_close_operation(T& t, Sink& snk, BOOST_IOS::openmode which) + : t_(t), snk_(snk), which_(which) + { } + void operator()() const { boost::iostreams::close(t_, snk_, which_); } +private: + filter_close_operation& operator=(const filter_close_operation&); + T& t_; + Sink& snk_; + BOOST_IOS::openmode which_; +}; + +template +device_close_operation +call_close(T& t, BOOST_IOS::openmode which) +{ return device_close_operation(t, which); } + +template +filter_close_operation +call_close(T& t, Sink& snk, BOOST_IOS::openmode which) +{ return filter_close_operation(t, snk, which); } + + // Function objects and object generators for invoking + // boost::iostreams::detail::close_all + +template +class device_close_all_operation { +public: + typedef void result_type; + device_close_all_operation(T& t) : t_(t) { } + void operator()() const { detail::close_all(t_); } +private: + device_close_all_operation& operator=(const device_close_all_operation&); + T& t_; +}; + +template +class filter_close_all_operation { +public: + typedef void result_type; + filter_close_all_operation(T& t, Sink& snk) : t_(t), snk_(snk) { } + void operator()() const { detail::close_all(t_, snk_); } +private: + filter_close_all_operation& operator=(const filter_close_all_operation&); + T& t_; + Sink& snk_; +}; + +template +device_close_all_operation call_close_all(T& t) +{ return device_close_all_operation(t); } + +template +filter_close_all_operation +call_close_all(T& t, Sink& snk) +{ return filter_close_all_operation(t, snk); } + + // Function object and object generator for invoking a + // member function void close(std::ios_base::openmode) + +template +class member_close_operation { +public: + typedef void result_type; + member_close_operation(T& t, BOOST_IOS::openmode which) + : t_(t), which_(which) + { } + void operator()() const { t_.close(which_); } +private: + member_close_operation& operator=(const member_close_operation&); + T& t_; + BOOST_IOS::openmode which_; +}; + +template +member_close_operation call_member_close(T& t, BOOST_IOS::openmode which) +{ return member_close_operation(t, which); } + + // Function object and object generator for invoking a + // member function void reset() + +template +class reset_operation { +public: + reset_operation(T& t) : t_(t) { } + void operator()() const { t_.reset(); } +private: + reset_operation& operator=(const reset_operation&); + T& t_; +}; + +template +reset_operation call_reset(T& t) { return reset_operation(t); } + + // Function object and object generator for clearing a flag + +template +class clear_flags_operation { +public: + typedef void result_type; + clear_flags_operation(T& t) : t_(t) { } + void operator()() const { t_ = 0; } +private: + clear_flags_operation& operator=(const clear_flags_operation&); + T& t_; +}; + +template +clear_flags_operation clear_flags(T& t) +{ return clear_flags_operation(t); } + + // Function object and generator for flushing a buffer + +// Function object for use with execute_all() +template +class flush_buffer_operation { +public: + typedef void result_type; + flush_buffer_operation(Buffer& buf, Device& dev, bool flush) + : buf_(buf), dev_(dev), flush_(flush) + { } + void operator()() const + { + if (flush_) + buf_.flush(dev_); + } +private: + flush_buffer_operation& operator=(const flush_buffer_operation&); + Buffer& buf_; + Device& dev_; + bool flush_; +}; + +template +flush_buffer_operation +flush_buffer(Buffer& buf, Device& dev, bool flush) +{ return flush_buffer_operation(buf, dev, flush); } + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_FUNCTIONAL_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/ios.hpp b/win32/include/boost/iostreams/detail/ios.hpp new file mode 100755 index 000000000..cde8c97d4 --- /dev/null +++ b/win32/include/boost/iostreams/detail/ios.hpp @@ -0,0 +1,66 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_IOS_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_IOS_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // BOOST_MSVC. +#include +#include +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +# if !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) +# include +# else +# include +# include +# endif +#else +# include +# include +#endif + +namespace boost { namespace iostreams { namespace detail { + +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //--------------------------------// +# define BOOST_IOSTREAMS_BASIC_IOS(ch, tr) std::basic_ios< ch, tr > +# if !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) && \ + !BOOST_WORKAROUND(__BORLANDC__, < 0x600) && \ + !BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ + /**/ + +#define BOOST_IOS std::ios +#define BOOST_IOSTREAMS_FAILURE std::ios::failure + +# else + +#define BOOST_IOS std::ios_base +#define BOOST_IOSTREAMS_FAILURE std::ios_base::failure + +# endif +#else // #ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //-----------------------// + +#define BOOST_IOS std::ios +#define BOOST_IOSTREAMS_BASIC_IOS(ch, tr) std::ios +#define BOOST_IOSTREAMS_FAILURE boost::iostreams::detail::failure + +class failure : std::exception { +public: + explicit failure(const std::string& what_arg) : what_(what_arg) { } + const char* what() const { return what_.c_str(); } +private: + std::string what_; +}; + +#endif // #ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //----------------------// + +} } } // End namespace failure, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_IOS_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/iostream.hpp b/win32/include/boost/iostreams/detail/iostream.hpp new file mode 100755 index 000000000..3679868d7 --- /dev/null +++ b/win32/include/boost/iostreams/detail/iostream.hpp @@ -0,0 +1,34 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_IOSTREAM_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_IOSTREAM_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +# include +# include +#else +# include +#endif + +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +# define BOOST_IOSTREAMS_BASIC_ISTREAM(ch, tr) std::basic_istream< ch, tr > +# define BOOST_IOSTREAMS_BASIC_OSTREAM(ch, tr) std::basic_ostream< ch, tr > +# define BOOST_IOSTREAMS_BASIC_IOSTREAM(ch, tr) std::basic_iostream< ch, tr > +#else +# define BOOST_IOSTREAMS_BASIC_STREAMBUF(ch, tr) std::streambuf +# define BOOST_IOSTREAMS_BASIC_ISTREAM(ch, tr) std::istream +# define BOOST_IOSTREAMS_BASIC_OSTREAM(ch, tr) std::ostream +# define BOOST_IOSTREAMS_BASIC_IOSTREAM(ch, tr) std::iostream +#endif + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_IOSTREAM_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/is_dereferenceable.hpp b/win32/include/boost/iostreams/detail/is_dereferenceable.hpp new file mode 100755 index 000000000..84ee19b14 --- /dev/null +++ b/win32/include/boost/iostreams/detail/is_dereferenceable.hpp @@ -0,0 +1,85 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// (C) Copyright David Abrahams 2004. +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_IS_DEREFERENCEABLE_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_IS_DEREFERENCEABLE_HPP_INCLUDED + +# include +# include +# include +# include +# include +# include + +namespace boost { namespace iostreams { namespace detail { + +// is_dereferenceable metafunction +// +// Requires: Given x of type T&, if the expression *x is well-formed +// it must have complete type; otherwise, it must neither be ambiguous +// nor violate access. + +// This namespace ensures that ADL doesn't mess things up. +namespace is_dereferenceable_ +{ + // a type returned from operator* when no increment is found in the + // type's own namespace + struct tag {}; + + // any soaks up implicit conversions and makes the following + // operator* less-preferred than any other such operator that + // might be found via ADL. + struct any { template any(T const&); }; + + // This is a last-resort operator* for when none other is found + tag operator*(any const&); + +# if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3202)) \ + || BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +# define BOOST_comma(a,b) (a) +# else + // In case an operator++ is found that returns void, we'll use ++x,0 + tag operator,(tag,int); +# define BOOST_comma(a,b) (a,b) +# endif + + // two check overloads help us identify which operator++ was picked + char (& check(tag) )[2]; + + template + char check(T const&); + + template + struct impl + { + static typename boost::remove_cv::type& x; + + BOOST_STATIC_CONSTANT( + bool + , value = sizeof(is_dereferenceable_::check(BOOST_comma(*x,0))) == 1 + ); + }; +} + +# undef BOOST_comma + +template +struct is_dereferenceable + BOOST_TT_AUX_BOOL_C_BASE(is_dereferenceable_::impl::value) +{ + BOOST_TT_AUX_BOOL_TRAIT_VALUE_DECL(is_dereferenceable_::impl::value) + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_dereferenceable,(T)) +}; + +} } + +BOOST_TT_AUX_TEMPLATE_ARITY_SPEC(1, ::boost::iostreams::detail::is_dereferenceable) + +} // End namespaces detail, iostreams, boost. + +#endif // BOOST_IOSTREAMS_DETAIL_IS_DEREFERENCEABLE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/is_iterator_range.hpp b/win32/include/boost/iostreams/detail/is_iterator_range.hpp new file mode 100755 index 000000000..66e47f42a --- /dev/null +++ b/win32/include/boost/iostreams/detail/is_iterator_range.hpp @@ -0,0 +1,42 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_IS_ITERATOR_RANGE_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_IS_ITERATOR_RANGE_HPP_INCLUDED + +#include + +namespace boost { + +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //---------------------------------// + +// We avoid dependence on Boost.Range by using a forward declaration. +template +class iterator_range; + +namespace iostreams { + +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_iterator_range, boost::iterator_range, 1) + +} // End namespace iostreams. + +# else // # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) //-----------------------// + +namespace iostreams { + + template + struct is_iterator_range { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + +} // End namespace iostreams. + +# endif // # if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) //----------------------// + +} // End namespace boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_IS_ITERATOR_RANGE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/newline.hpp b/win32/include/boost/iostreams/detail/newline.hpp new file mode 100755 index 000000000..c7f39b1de --- /dev/null +++ b/win32/include/boost/iostreams/detail/newline.hpp @@ -0,0 +1,32 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_NEWLINE_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_NEWLINE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +namespace boost { namespace iostreams { namespace detail { + +template +struct newline; + +template<> +struct newline { + BOOST_STATIC_CONSTANT(char, value = '\n'); +}; + +template<> +struct newline { + BOOST_STATIC_CONSTANT(wchar_t, value = L'\n'); +}; + +} } } // End namespaces detaill, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_NEWLINE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/optional.hpp b/win32/include/boost/iostreams/detail/optional.hpp new file mode 100755 index 000000000..144f79087 --- /dev/null +++ b/win32/include/boost/iostreams/detail/optional.hpp @@ -0,0 +1,114 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Recent changes to Boost.Optional involving assigment broke Boost.Iostreams, +// in a way which could be remedied only by relying on the deprecated reset +// functions; with VC6, even reset didn't work. Until this problem is +// understood, Iostreams will use a private version of optional with a smart +// pointer interface. + +#ifndef BOOST_IOSTREAMS_DETAIL_OPTIONAL_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_OPTIONAL_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include +#include + +namespace boost { namespace iostreams { namespace detail { + +// Taken from . +template +class aligned_storage +{ + // Borland ICEs if unnamed unions are used for this! + union dummy_u + { + char data[ sizeof(T) ]; + BOOST_DEDUCED_TYPENAME type_with_alignment< + ::boost::alignment_of::value >::type aligner_; + } dummy_ ; + + public: + + void const* address() const { return &dummy_.data[0]; } + void * address() { return &dummy_.data[0]; } +}; + +template +class optional { +public: + typedef T element_type; + optional() : initialized_(false) { } + optional(const T& t) : initialized_(false) { reset(t); } + ~optional() { reset(); } + T& operator*() + { + assert(initialized_); + return *static_cast(address()); + } + const T& operator*() const + { + assert(initialized_); + return *static_cast(address()); + } + T* operator->() + { + assert(initialized_); + return static_cast(address()); + } + const T* operator->() const + { + assert(initialized_); + return static_cast(address()); + } + T* get() + { + assert(initialized_); + return static_cast(address()); + } + const T* get() const + { + assert(initialized_); + return static_cast(address()); + } + void reset() + { + if (initialized_) { + #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) || \ + BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) \ + /**/ + T* t = static_cast(address()); + t->~T(); + #else + static_cast(address())->T::~T(); + #endif + initialized_ = false; + } + } + void reset(const T& t) + { + reset(); + new (address()) T(t); + initialized_ = true; + } +private: + optional(const optional&); + optional& operator=(const optional&); + void* address() { return &storage_; } + const void* address() const { return &storage_; } + aligned_storage storage_; + bool initialized_; +}; + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_OPTIONAL_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/param_type.hpp b/win32/include/boost/iostreams/detail/param_type.hpp new file mode 100755 index 000000000..7f859166b --- /dev/null +++ b/win32/include/boost/iostreams/detail/param_type.hpp @@ -0,0 +1,27 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_PARAM_TYPE_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_PARAM_TYPE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include + +namespace boost { namespace iostreams { namespace detail { + +template +struct param_type { + typedef typename mpl::if_, T&, const T&>::type type; +}; + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_PARAM_TYPE_HPP_INCLUDED //-----------// diff --git a/win32/include/boost/iostreams/detail/push.hpp b/win32/include/boost/iostreams/detail/push.hpp new file mode 100755 index 000000000..390e1046b --- /dev/null +++ b/win32/include/boost/iostreams/detail/push.hpp @@ -0,0 +1,154 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_PUSH_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_PUSH_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // BOOST_MSVC. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Macro: BOOST_IOSTREAMS_DEFINE_PUSH_CONSTRUCTOR(name, mode, ch, helper). +// Description: Defines overloads with name 'name' which forward to a function +// 'helper' which takes a filter or devide by const reference. +// +#define BOOST_IOSTREAMS_DEFINE_PUSH_CONSTRUCTOR(name, mode, ch, helper) \ + BOOST_IOSTREAMS_DEFINE_PUSH_IMPL(name, mode, ch, helper, 0, ?) \ + /**/ + +// +// Macro: BOOST_IOSTREAMS_DEFINE_PUSH(name, mode, ch, helper). +// Description: Defines constructors which forward to a function +// 'helper' which takes a filter or device by const reference. +// +#define BOOST_IOSTREAMS_DEFINE_PUSH(name, mode, ch, helper) \ + BOOST_IOSTREAMS_DEFINE_PUSH_IMPL(name, mode, ch, helper, 1, void) \ + /**/ + +//--------------------Definition of BOOST_IOSTREAMS_DEFINE_PUSH_IMPL----------// + +#define BOOST_IOSTREAMS_ADAPT_STREAM(mode, ch, arg, helper, has_return) \ + this->helper( ::boost::iostreams::detail::resolve(arg) \ + BOOST_IOSTREAMS_PUSH_ARGS() ); \ + /**/ + +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \ + !BOOST_WORKAROUND(__BORLANDC__, < 0x600) \ + /**/ +# ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +# define BOOST_IOSTREAMS_DEFINE_PUSH_IMPL(name, mode, ch, helper, has_return, result) \ + template \ + BOOST_PP_IIF(has_return, result, explicit) \ + name(::std::basic_streambuf& sb BOOST_IOSTREAMS_PUSH_PARAMS()) \ + { BOOST_IOSTREAMS_ADAPT_STREAM(mode, ch, sb, helper, has_return); } \ + template \ + BOOST_PP_IIF(has_return, result, explicit) \ + name(::std::basic_istream& is BOOST_IOSTREAMS_PUSH_PARAMS()) \ + { BOOST_STATIC_ASSERT((!is_convertible::value)); \ + BOOST_IOSTREAMS_ADAPT_STREAM(mode, ch, is, helper, has_return); } \ + template \ + BOOST_PP_IIF(has_return, result, explicit) \ + name(::std::basic_ostream& os BOOST_IOSTREAMS_PUSH_PARAMS()) \ + { BOOST_STATIC_ASSERT((!is_convertible::value)); \ + BOOST_IOSTREAMS_ADAPT_STREAM(mode, ch, os, helper, has_return); } \ + template \ + BOOST_PP_IIF(has_return, result, explicit) \ + name(::std::basic_iostream& io BOOST_IOSTREAMS_PUSH_PARAMS()) \ + { BOOST_IOSTREAMS_ADAPT_STREAM(mode, ch, io, helper, has_return); } \ + template \ + BOOST_PP_IIF(has_return, result, explicit) \ + name(const iterator_range& rng BOOST_IOSTREAMS_PUSH_PARAMS()) \ + { BOOST_PP_EXPR_IF(has_return, return) \ + this->helper( ::boost::iostreams::detail::range_adapter< \ + mode, iterator_range \ + >(rng) \ + BOOST_IOSTREAMS_PUSH_ARGS() ); } \ + template \ + BOOST_PP_IIF(has_return, result, explicit) \ + name(const ::boost::iostreams::pipeline& p) \ + { p.push(*this); } \ + template \ + BOOST_PP_IIF(has_return, result, explicit) \ + name(const T& t BOOST_IOSTREAMS_PUSH_PARAMS() BOOST_IOSTREAMS_DISABLE_IF_STREAM(T)) \ + { this->helper( ::boost::iostreams::detail::resolve(t) \ + BOOST_IOSTREAMS_PUSH_ARGS() ); } \ + /**/ +# else // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +# define BOOST_IOSTREAMS_DEFINE_PUSH_IMPL(name, mode, ch, helper, has_return, result) \ + BOOST_PP_IF(has_return, result, explicit) \ + name(::std::streambuf& sb BOOST_IOSTREAMS_PUSH_PARAMS()) \ + { BOOST_IOSTREAMS_ADAPT_STREAM(mode, ch, sb, helper, has_return); } \ + BOOST_PP_IF(has_return, result, explicit) \ + name(::std::istream& is BOOST_IOSTREAMS_PUSH_PARAMS()) \ + { BOOST_STATIC_ASSERT((!is_convertible::value)); \ + BOOST_IOSTREAMS_ADAPT_STREAM(mode, ch, is, helper, has_return); } \ + BOOST_PP_IF(has_return, result, explicit) \ + name(::std::ostream& os BOOST_IOSTREAMS_PUSH_PARAMS()) \ + { BOOST_STATIC_ASSERT((!is_convertible::value)); \ + BOOST_IOSTREAMS_ADAPT_STREAM(mode, ch, os, helper, has_return); } \ + BOOST_PP_IF(has_return, result, explicit) \ + name(::std::iostream& io BOOST_IOSTREAMS_PUSH_PARAMS()) \ + { BOOST_IOSTREAMS_ADAPT_STREAM(mode, ch, io, helper, has_return); } \ + template \ + BOOST_PP_IF(has_return, result, explicit) \ + name(const iterator_range& rng BOOST_IOSTREAMS_PUSH_PARAMS()) \ + { BOOST_PP_EXPR_IF(has_return, return) \ + this->helper( ::boost::iostreams::detail::range_adapter< \ + mode, iterator_range \ + >(rng) \ + BOOST_IOSTREAMS_PUSH_ARGS() ); } \ + template \ + BOOST_PP_IF(has_return, result, explicit) \ + name(const ::boost::iostreams::pipeline& p) \ + { p.push(*this); } \ + template \ + BOOST_PP_EXPR_IF(has_return, result) \ + name(const T& t BOOST_IOSTREAMS_PUSH_PARAMS() BOOST_IOSTREAMS_DISABLE_IF_STREAM(T)) \ + { this->helper( ::boost::iostreams::detail::resolve(t) \ + BOOST_IOSTREAMS_PUSH_ARGS() ); } \ + /**/ +# endif // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +#else // #if VC6, VC7.0, Borland 5.x +# define BOOST_IOSTREAMS_DEFINE_PUSH_IMPL(name, mode, ch, helper, has_return, result) \ + template \ + void BOOST_PP_CAT(name, _msvc_impl) \ + ( ::boost::mpl::true_, const T& t BOOST_IOSTREAMS_PUSH_PARAMS() ) \ + { t.push(*this); } \ + template \ + void BOOST_PP_CAT(name, _msvc_impl) \ + ( ::boost::mpl::false_, const T& t BOOST_IOSTREAMS_PUSH_PARAMS() ) \ + { this->helper( ::boost::iostreams::detail::resolve(t) \ + BOOST_IOSTREAMS_PUSH_ARGS() ); } \ + template \ + BOOST_PP_IF(has_return, result, explicit) \ + name(const T& t BOOST_IOSTREAMS_PUSH_PARAMS()) \ + { \ + this->BOOST_PP_CAT(name, _msvc_impl) \ + ( ::boost::iostreams::detail::is_pipeline(), \ + t BOOST_IOSTREAMS_PUSH_ARGS() ); \ + } \ + /**/ +#endif // #if VC6, VC7.0, Borland 5.x + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_PUSH_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/push_params.hpp b/win32/include/boost/iostreams/detail/push_params.hpp new file mode 100755 index 000000000..1f2e41e20 --- /dev/null +++ b/win32/include/boost/iostreams/detail/push_params.hpp @@ -0,0 +1,21 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_PUSH_PARAMS_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_PUSH_PARAMS_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#define BOOST_IOSTREAMS_PUSH_PARAMS() \ + , int buffer_size = -1 , int pback_size = -1 \ + /**/ + +#define BOOST_IOSTREAMS_PUSH_ARGS() , buffer_size, pback_size + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_PUSH_PARAMS_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/resolve.hpp b/win32/include/boost/iostreams/detail/resolve.hpp new file mode 100755 index 000000000..26763a70b --- /dev/null +++ b/win32/include/boost/iostreams/detail/resolve.hpp @@ -0,0 +1,234 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_RESOLVE_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_RESOLVE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // partial spec, put size_t in std. +#include // std::size_t. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // true_. +#include +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +# include +#endif // #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +#include + +// Must come last. +#include // VC7.1 C4224. + +namespace boost { namespace iostreams { namespace detail { + +//------------------Definition of resolve-------------------------------------// + +#ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //-------------------------// + +template +struct resolve_traits { + typedef typename + mpl::if_< + boost::detail::is_incrementable, + output_iterator_adapter, + const T& + >::type type; +}; + +# ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //-------------------------------// + +template +typename resolve_traits::type +resolve( const T& t + BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) + + // I suspect that the compilers which require this workaround may + // be correct, but I'm not sure why :( + #if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, BOOST_TESTED_AT(810)) ||\ + BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) || \ + BOOST_WORKAROUND(BOOST_IOSTREAMS_GCC, BOOST_TESTED_AT(400)) \ + /**/ + , typename disable_if< is_iterator_range >::type* = 0 + #endif + ) +{ + typedef typename resolve_traits::type return_type; + return return_type(t); +} + +template +mode_adapter< Mode, std::basic_streambuf > +resolve(std::basic_streambuf& sb) +{ return mode_adapter< Mode, std::basic_streambuf >(wrap(sb)); } + +template +mode_adapter< Mode, std::basic_istream > +resolve(std::basic_istream& is) +{ return mode_adapter< Mode, std::basic_istream >(wrap(is)); } + +template +mode_adapter< Mode, std::basic_ostream > +resolve(std::basic_ostream& os) +{ return mode_adapter< Mode, std::basic_ostream >(wrap(os)); } + +template +mode_adapter< Mode, std::basic_iostream > +resolve(std::basic_iostream& io) +{ return mode_adapter< Mode, std::basic_iostream >(wrap(io)); } + +template +array_adapter resolve(Ch (&array)[N]) +{ return array_adapter(array); } + +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + template + range_adapter< Mode, boost::iterator_range > + resolve(const boost::iterator_range& rng) + { return range_adapter< Mode, boost::iterator_range >(rng); } +# endif // #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + +# else // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //---------------------// + +template +typename resolve_traits::type +resolve( const T& t + BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) + #if defined(__GNUC__) + , typename disable_if< is_iterator_range >::type* = 0 + #endif + ) +{ + typedef typename resolve_traits::type return_type; + return return_type(t); +} + +template +mode_adapter +resolve(std::streambuf& sb) +{ return mode_adapter(wrap(sb)); } + +template +mode_adapter +resolve(std::istream& is) +{ return mode_adapter(wrap(is)); } + +template +mode_adapter +resolve(std::ostream& os) +{ return mode_adapter(wrap(os)); } + +template +mode_adapter +resolve(std::iostream& io) +{ return mode_adapter(wrap(io)); } + +template +array_adapter resolve(Ch (&array)[N]) +{ return array_adapter(array); } + +template +range_adapter< Mode, boost::iterator_range > +resolve(const boost::iterator_range& rng) +{ return range_adapter< Mode, boost::iterator_range >(rng); } + +# endif // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //--------------------// +#else // #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //----------------// + +template +struct resolve_traits { + // Note: test for is_iterator_range must come before test for output + // iterator. + typedef typename + iostreams::select< // Disambiguation for Tru64. + is_std_io, + mode_adapter, + is_iterator_range, + range_adapter, + is_dereferenceable, + output_iterator_adapter, + is_array, + array_adapter, + else_, + #if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) + const T& + #else + T + #endif + >::type type; +}; + +template +typename resolve_traits::type +resolve(const T& t, mpl::true_) +{ // Bad overload resolution. + typedef typename resolve_traits::type return_type; + return return_type(wrap(const_cast(t))); +} + +template +typename resolve_traits::type +resolve(const T& t, mpl::false_) +{ + typedef typename resolve_traits::type return_type; + return return_type(t); +} + +template +typename resolve_traits::type +resolve(const T& t BOOST_IOSTREAMS_DISABLE_IF_STREAM(T)) +{ return resolve(t, is_std_io()); } + +# if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) && \ + !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \ + !defined(__GNUC__) // ---------------------------------------------------// + +template +typename resolve_traits::type +resolve(T& t, mpl::true_) +{ + typedef typename resolve_traits::type return_type; + return return_type(wrap(t)); +} + +template +typename resolve_traits::type +resolve(T& t, mpl::false_) +{ + typedef typename resolve_traits::type return_type; + return return_type(t); +} + +template +typename resolve_traits::type +resolve(T& t BOOST_IOSTREAMS_ENABLE_IF_STREAM(T)) +{ return resolve(t, is_std_io()); } + +# endif // Borland 5.x, VC6-7.0 or GCC 2.9x //--------------------------------// +#endif // #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //---------------// + +} } } // End namespaces detail, iostreams, boost. + +#include // VC7.1 4224. + +#endif // BOOST_IOSTREAMS_DETAIL_RESOLVE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/restrict_impl.hpp b/win32/include/boost/iostreams/detail/restrict_impl.hpp new file mode 100755 index 000000000..0b7332a69 --- /dev/null +++ b/win32/include/boost/iostreams/detail/restrict_impl.hpp @@ -0,0 +1,474 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + + * File: boost/iostreams/detail/restrict_impl.hpp + * Date: Sun Jan 06 12:57:30 MST 2008 + * Copyright: 2007-2008 CodeRage, LLC + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + * + * If included with the macro BOOST_IOSTREAMS_RESTRICT undefined, defines the + * class template boost::iostreams::restriction. If included with the macro + * BOOST_IOSTREAMS_RESTRICT defined as an identifier, defines the overloaded + * function template boost::iostreams::BOOST_IOSTREAMS_RESTRICT, and object + * generator for boost::iostreams::restriction. + * + * This design allows and + * to share an implementation. + */ + +#if !defined(BOOST_IOSTREAMS_RESTRICT_IMPL_HPP_INCLUDED) && \ + !defined(BOOST_IOSTREAMS_RESTRICT) +# define BOOST_IOSTREAMS_RESTRICT_IMPL_HPP_INCLUDED + +//------------------Implementation of restriction-----------------------------// + +# include // min. +# include // pair. +# include // intmax_t. +# include // DEDUCED_TYPENAME. +# include +# include +# include +# include +# include +# include +# include +# include // failure. +# include +# include +# include +# include // mode_of, is_direct. +# include +# include +# include + +# include + +namespace boost { namespace iostreams { + +namespace detail { + +// +// Template name: restricted_indirect_device. +// Description: Provides an restricted view of an indirect Device. +// Template paramters: +// Device - An indirect model of Device that models either Source or +// SeekableDevice. +// +template +class restricted_indirect_device : public device_adapter { +private: + typedef typename detail::param_type::type param_type; +public: + typedef typename char_type_of::type char_type; + typedef typename mode_of::type mode; + BOOST_STATIC_ASSERT(!(is_convertible::value)); + struct category + : mode, + device_tag, + closable_tag, + flushable_tag, + localizable_tag, + optimally_buffered_tag + { }; + restricted_indirect_device( param_type dev, stream_offset off, + stream_offset len = -1 ); + std::streamsize read(char_type* s, std::streamsize n); + std::streamsize write(const char_type* s, std::streamsize n); + std::streampos seek(stream_offset off, BOOST_IOS::seekdir way); +private: + stream_offset beg_, pos_, end_; +}; + +// +// Template name: restricted_direct_device. +// Description: Provides an restricted view of a Direct Device. +// Template paramters: +// Device - A model of Direct and Device. +// +template +class restricted_direct_device : public device_adapter { +public: + typedef typename char_type_of::type char_type; + typedef std::pair pair_type; + typedef typename mode_of::type mode; + BOOST_STATIC_ASSERT(!(is_convertible::value)); + struct category + : mode_of::type, + device_tag, + direct_tag, + closable_tag, + localizable_tag + { }; + restricted_direct_device( const Device& dev, stream_offset off, + stream_offset len = -1 ); + pair_type input_sequence(); + pair_type output_sequence(); +private: + pair_type sequence(mpl::true_); + pair_type sequence(mpl::false_); + char_type *beg_, *end_; +}; + +// +// Template name: restricted_filter. +// Description: Provides an restricted view of a Filter. +// Template paramters: +// Filter - An indirect model of Filter. +// +template +class restricted_filter : public filter_adapter { +public: + typedef typename char_type_of::type char_type; + typedef typename mode_of::type mode; + BOOST_STATIC_ASSERT(!(is_convertible::value)); + struct category + : mode, + filter_tag, + multichar_tag, + closable_tag, + localizable_tag, + optimally_buffered_tag + { }; + restricted_filter( const Filter& flt, stream_offset off, + stream_offset len = -1 ); + + template + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { + using namespace std; + if (!open_) + open(src, BOOST_IOS::in); + std::streamsize amt = + end_ != -1 ? + (std::min) (n, static_cast(end_ - pos_)) : + n; + std::streamsize result = + iostreams::read(this->component(), src, s, amt); + if (result != -1) + pos_ += result; + return result; + } + + template + std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) + { + if (!open_) + open(snk, BOOST_IOS::out); + if (end_ != -1 && pos_ + n >= end_) + bad_write(); + std::streamsize result = + iostreams::write(this->component(), snk, s, n); + pos_ += result; + return result; + } + + template + std::streampos seek(Device& dev, stream_offset off, BOOST_IOS::seekdir way) + { + stream_offset next; + if (way == BOOST_IOS::beg) { + next = beg_ + off; + } else if (way == BOOST_IOS::cur) { + next = pos_ + off; + } else if (end_ != -1) { + next = end_ + off; + } else { + // Restriction is half-open; seek relative to the actual end. + pos_ = this->component().seek(dev, off, BOOST_IOS::end); + if (pos_ < beg_) + bad_seek(); + return offset_to_position(pos_ - beg_); + } + if (next < beg_ || end_ != -1 && next >= end_) + bad_seek(); + pos_ = this->component().seek(dev, next, BOOST_IOS::cur); + return offset_to_position(pos_ - beg_); + } + + template + void close(Device& dev) + { + open_ = false; + detail::close_all(this->component(), dev); + } + + template + void close(Device& dev, BOOST_IOS::openmode which) + { + open_ = false; + iostreams::close(this->component(), dev, which); + } +private: + template + void open(Device& dev, BOOST_IOS::openmode which) + { + typedef typename is_convertible::type is_dual_use; + open_ = true; + which = is_dual_use() ? which : (BOOST_IOS::in | BOOST_IOS::out); + iostreams::skip(this->component(), dev, beg_, which); + } + + stream_offset beg_, pos_, end_; + bool open_; +}; + +template +struct restriction_traits + : iostreams::select< // Disambiguation for Tru64. + is_filter, restricted_filter, + is_direct, restricted_direct_device, + else_, restricted_indirect_device + > + { }; + +} // End namespace detail. + +template +struct restriction : public detail::restriction_traits::type { + typedef typename detail::param_type::type param_type; + typedef typename detail::restriction_traits::type base_type; + restriction(param_type t, stream_offset off, stream_offset len = -1) + : base_type(t, off, len) + { } +}; + +namespace detail { + +//--------------Implementation of restricted_indirect_device------------------// + +template +restricted_indirect_device::restricted_indirect_device + (param_type dev, stream_offset off, stream_offset len) + : device_adapter(dev), beg_(off), pos_(off), + end_(len != -1 ? off + len : -1) +{ + if (len < -1 || off < 0) + throw BOOST_IOSTREAMS_FAILURE("bad offset"); + iostreams::skip(this->component(), off); +} + +template +inline std::streamsize restricted_indirect_device::read + (char_type* s, std::streamsize n) +{ + using namespace std; + std::streamsize amt = + end_ != -1 ? + (std::min) (n, static_cast(end_ - pos_)) : + n; + std::streamsize result = iostreams::read(this->component(), s, amt); + if (result != -1) + pos_ += result; + return result; +} + +template +inline std::streamsize restricted_indirect_device::write + (const char_type* s, std::streamsize n) +{ + if (end_ != -1 && pos_ + n >= end_) + bad_write(); + std::streamsize result = iostreams::write(this->component(), s, n); + pos_ += result; + return result; +} + +template +std::streampos restricted_indirect_device::seek + (stream_offset off, BOOST_IOS::seekdir way) +{ + stream_offset next; + if (way == BOOST_IOS::beg) { + next = beg_ + off; + } else if (way == BOOST_IOS::cur) { + next = pos_ + off; + } else if (end_ != -1) { + next = end_ + off; + } else { + // Restriction is half-open; seek relative to the actual end. + pos_ = iostreams::seek(this->component(), off, BOOST_IOS::end); + if (pos_ < beg_) + bad_seek(); + return offset_to_position(pos_ - beg_); + } + if (next < beg_ || end_ != -1 && next >= end_) + bad_seek(); + pos_ = iostreams::seek(this->component(), next - pos_, BOOST_IOS::cur); + return offset_to_position(pos_ - beg_); +} + +//--------------Implementation of restricted_direct_device--------------------// + +template +restricted_direct_device::restricted_direct_device + (const Device& dev, stream_offset off, stream_offset len) + : device_adapter(dev), beg_(0), end_(0) +{ + std::pair seq = + sequence(is_convertible()); + if ( off < 0 || len < -1 || + len != -1 && off + len > seq.second - seq.first ) + { + throw BOOST_IOSTREAMS_FAILURE("bad offset"); + } + beg_ = seq.first + off; + end_ = len != -1 ? + seq.first + off + len : + seq.second; +} + +template +typename restricted_direct_device::pair_type +restricted_direct_device::input_sequence() +{ + BOOST_STATIC_ASSERT((is_convertible::value)); + return std::make_pair(beg_, end_); +} + +template +typename restricted_direct_device::pair_type +restricted_direct_device::output_sequence() +{ + BOOST_STATIC_ASSERT((is_convertible::value)); + return std::make_pair(beg_, end_); +} + +template +typename restricted_direct_device::pair_type +restricted_direct_device::sequence(mpl::true_) +{ return iostreams::input_sequence(this->component()); } + +template +typename restricted_direct_device::pair_type +restricted_direct_device::sequence(mpl::false_) +{ return iostreams::output_sequence(this->component()); } + +//--------------Implementation of restricted_filter---------------------------// + +template +restricted_filter::restricted_filter + (const Filter& flt, stream_offset off, stream_offset len) + : filter_adapter(flt), beg_(off), + pos_(off), end_(len != -1 ? off + len : -1), open_(false) +{ + if (len < -1 || off < 0) + throw BOOST_IOSTREAMS_FAILURE("bad offset"); +} + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#elif defined(BOOST_IOSTREAMS_RESTRICT) + +namespace boost { namespace iostreams { + +//--------------Implementation of restrict/slice------------------------------// + +// Note: The following workarounds are patterned after resolve.hpp. It has not +// yet been confirmed that they are necessary. + +# ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //------------------------// +# ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //------------------------------// + +template +restriction +BOOST_IOSTREAMS_RESTRICT( const T& t, stream_offset off, stream_offset len = -1 + BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) ) +{ return restriction(t, off, len); } + +template +restriction< std::basic_streambuf > +BOOST_IOSTREAMS_RESTRICT( std::basic_streambuf& sb, stream_offset off, + stream_offset len = -1 ) +{ return restriction< std::basic_streambuf >(sb, off, len); } + +template +restriction< std::basic_istream > +BOOST_IOSTREAMS_RESTRICT + (std::basic_istream& is, stream_offset off, stream_offset len = -1) +{ return restriction< std::basic_istream >(is, off, len); } + +template +restriction< std::basic_ostream > +BOOST_IOSTREAMS_RESTRICT + (std::basic_ostream& os, stream_offset off, stream_offset len = -1) +{ return restriction< std::basic_ostream >(os, off, len); } + +template +restriction< std::basic_iostream > +BOOST_IOSTREAMS_RESTRICT + (std::basic_iostream& io, stream_offset off, stream_offset len = -1) +{ return restriction< std::basic_iostream >(io, off, len); } + +# else // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //--------------------// + +template +restriction +BOOST_IOSTREAMS_RESTRICT( const T& t, stream_offset off, stream_offset len = -1 + BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) ) +{ return restriction(t, off, len); } + +restriction +BOOST_IOSTREAMS_RESTRICT + (std::streambuf& sb, stream_offset off, stream_offset len = -1) +{ return restriction(sb, off, len); } + +restriction +BOOST_IOSTREAMS_RESTRICT + (std::istream& is, stream_offset off, stream_offset len = -1) +{ return restriction(is, off, len); } + +restriction +BOOST_IOSTREAMS_RESTRICT + (std::ostream& os, stream_offset off, stream_offset len = -1) +{ return restriction(os, off, len); } + +restriction +BOOST_IOSTREAMS_RESTRICT + (std::iostream& io, stream_offset off, stream_offset len = -1) +{ return restriction(io, off, len); } + +# endif // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //-------------------// +# else // #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //---------------// + +template +restriction +BOOST_IOSTREAMS_RESTRICT + (const T& t, stream_offset off, stream_offset len, mpl::true_) +{ // Bad overload resolution. + return restriction(const_cast(t, off, len)); +} + +template +restriction +BOOST_IOSTREAMS_RESTRICT + (const T& t, stream_offset off, stream_offset len, mpl::false_) +{ return restriction(t, off, len); } + +template +restriction +BOOST_IOSTREAMS_RESTRICT( const T& t, stream_offset off, stream_offset len = -1 + BOOST_IOSTREAMS_DISABLE_IF_STREAM(T) ) +{ return BOOST_IOSTREAMS_RESTRICT(t, off, len, is_std_io()); } + +# if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) && \ + !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \ + !defined(__GNUC__) // ---------------------------------------------------// + +template +restriction +BOOST_IOSTREAMS_RESTRICT(T& t, stream_offset off, stream_offset len = -1) +{ return restriction(t, off, len); } + +# endif // Borland 5.x, VC6-7.0 or GCC 2.9x //-------------------------------// +# endif // #ifndef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION //--------------// + +} } // End namespaces iostreams, boost. + +#endif // #if !defined(BOOST_IOSTREAMS_RESTRICT_IMPL_HPP_INCLUDED) ... diff --git a/win32/include/boost/iostreams/detail/select.hpp b/win32/include/boost/iostreams/detail/select.hpp new file mode 100755 index 000000000..556531ebd --- /dev/null +++ b/win32/include/boost/iostreams/detail/select.hpp @@ -0,0 +1,86 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains the metafunction select, which mimics the effect of a chain of +// nested mpl if_'s. +// +// ----------------------------------------------------------------------------- +// +// Usage: +// +// typedef typename select< +// case1, type1, +// case2, type2, +// ... +// true_, typen +// >::type selection; +// +// Here case1, case2, ... are models of MPL::IntegralConstant with value type +// bool, and n <= 12. + +#ifndef BOOST_IOSTREAMS_SELECT_HPP_INCLUDED +#define BOOST_IOSTREAMS_SELECT_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include +#include +#include + +namespace boost { namespace iostreams { + +typedef mpl::true_ else_; + +template< typename Case1 = mpl::true_, + typename Type1 = mpl::void_, + typename Case2 = mpl::true_, + typename Type2 = mpl::void_, + typename Case3 = mpl::true_, + typename Type3 = mpl::void_, + typename Case4 = mpl::true_, + typename Type4 = mpl::void_, + typename Case5 = mpl::true_, + typename Type5 = mpl::void_, + typename Case6 = mpl::true_, + typename Type6 = mpl::void_, + typename Case7 = mpl::true_, + typename Type7 = mpl::void_, + typename Case8 = mpl::true_, + typename Type8 = mpl::void_, + typename Case9 = mpl::true_, + typename Type9 = mpl::void_, + typename Case10 = mpl::true_, + typename Type10 = mpl::void_, + typename Case11 = mpl::true_, + typename Type11 = mpl::void_, + typename Case12 = mpl::true_, + typename Type12 = mpl::void_ > +struct select { + typedef typename + mpl::eval_if< + Case1, mpl::identity, mpl::eval_if< + Case2, mpl::identity, mpl::eval_if< + Case3, mpl::identity, mpl::eval_if< + Case4, mpl::identity, mpl::eval_if< + Case5, mpl::identity, mpl::eval_if< + Case6, mpl::identity, mpl::eval_if< + Case7, mpl::identity, mpl::eval_if< + Case8, mpl::identity, mpl::eval_if< + Case9, mpl::identity, mpl::eval_if< + Case10, mpl::identity, mpl::eval_if< + Case11, mpl::identity, mpl::if_< + Case12, Type12, mpl::void_ > > > > > > > > > > > + >::type type; +}; + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_SELECT_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/select_by_size.hpp b/win32/include/boost/iostreams/detail/select_by_size.hpp new file mode 100755 index 000000000..2d0cf0679 --- /dev/null +++ b/win32/include/boost/iostreams/detail/select_by_size.hpp @@ -0,0 +1,160 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// +// Intended as an alternative to type_traits::yes_type and type_traits::no_type. +// Provides an arbitrary number of types (case_<0>, case_<1>, ...) for +// determining the results of overload resultion using 'sizeof', plus a uniform +// means of using the result. yes_type and no_type are typedefs for case_<1> +// and case_<0>. A single case with negative argument, case_<-1>, is also +// provided, for convenience. +// +// This header may be included any number of times, with +// BOOST_SELECT_BY_SIZE_MAX_CASE defined to be the largest N such that case_ +// is needed for a particular application. It defaults to 20. +// +// This header depends only on Boost.Config and Boost.Preprocessor. Dependence +// on Type Traits or MPL was intentionally avoided, to leave open the +// possibility that select_by_size could be used by these libraries. +// +// Example usage: +// +// #define BOOST_SELECT_BY_SIZE_MAX_CASE 7 // (Needed when default was 2) +// #include +// +// using namespace boost::utility; +// +// case_<0> helper(bool); +// case_<1> helper(int); +// case_<2> helper(unsigned); +// case_<3> helper(long); +// case_<4> helper(unsigned long); +// case_<5> helper(float); +// case_<6> helper(double); +// case_<7> helper(const char*); +// +// struct test { +// static const int value = +// select_by_size< sizeof(helper(9876UL)) >::value; +// BOOST_STATIC_ASSERT(value == 4); +// }; +// +// For compilers with integral constant expression problems, e.g. Borland 5.x, +// one can also write +// +// struct test { +// BOOST_SELECT_BY_SIZE(int, value, helper(9876UL)); +// }; +// +// to define a static integral constant 'value' equal to +// +// select_by_size< sizeof(helper(9876UL)) >::value. +// + +// Include guards surround all contents of this header except for explicit +// specializations of select_by_size for case_ with N > 2. + +#ifndef BOOST_IOSTREAMS_DETAIL_SELECT_BY_SIZE_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_SELECT_BY_SIZE_HPP_INCLUDED + +// The lowest N for which select_by_size< sizeof(case_) > has not been +// specialized. +#define SELECT_BY_SIZE_MAX_SPECIALIZED 20 + +#include // BOOST_STATIC_CONSTANT. +#include +#include + +/* Alternative implementation using max_align. + +#include +#include + +namespace boost { namespace utility { + +template +struct case_ { char c[(N + 1) * alignment_of::value]; }; + +template +struct select_by_size { + BOOST_STATIC_CONSTANT(int, value = + (Size / alignment_of::value - 1)); +}; + +} } // End namespaces utility, boost. + +*/ // End alternate implementation. + +namespace boost { namespace iostreams { namespace detail { + +//--------------Definition of case_-------------------------------------------// + +template struct case_ { char c1; case_ c2; }; +template<> struct case_<-1> { char c; }; +typedef case_ yes_type; +typedef case_ no_type; + +//--------------Declaration of select_by_size---------------------------------// + +template struct select_by_size; + +} } } // End namespaces detail, iostreams, boost. + +//--------------Definition of SELECT_BY_SIZE_SPEC-----------------------------// + +// Sepecializes select_by_size for sizeof(case). The decrement is used +// here because the preprocessor library doesn't handle negative integers. +#define SELECT_BY_SIZE_SPEC(n) \ + namespace boost { namespace iostreams { namespace detail { \ + static const int BOOST_PP_CAT(sizeof_case_, n) = sizeof(case_); \ + template<> \ + struct select_by_size< BOOST_PP_CAT(sizeof_case_, n) > { \ + struct type { BOOST_STATIC_CONSTANT(int, value = n - 1); }; \ + BOOST_STATIC_CONSTANT(int, value = type::value); \ + }; \ + } } } \ + /**/ + +//--------------Default specializations of select_by_size---------------------// + +#define BOOST_PP_LOCAL_MACRO(n) SELECT_BY_SIZE_SPEC(n) +#define BOOST_PP_LOCAL_LIMITS (0, 20) +#include BOOST_PP_LOCAL_ITERATE() +#undef BOOST_PP_LOCAL_MACRO + +//--------------Definition of SELECT_BY_SIZE----------------------------------// + +#define BOOST_SELECT_BY_SIZE(type_, name, expr) \ + BOOST_STATIC_CONSTANT( \ + unsigned, \ + BOOST_PP_CAT(boost_select_by_size_temp_, name) = sizeof(expr) \ + ); \ + BOOST_STATIC_CONSTANT( \ + type_, \ + name = \ + ( ::boost::iostreams::detail::select_by_size< \ + BOOST_PP_CAT(boost_select_by_size_temp_, name) \ + >::value ) \ + ) \ + /**/ + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_SELECT_BY_SIZE_HPP_INCLUDED + +//----------Specializations of SELECT_BY_SIZE (outside main inclued guards)---// + +#if BOOST_SELECT_BY_SIZE_MAX_CASE > SELECT_BY_SIZE_MAX_SPECIALIZED + +#define BOOST_PP_LOCAL_MACRO(n) SELECT_BY_SIZE_SPEC(n) +#define BOOST_PP_LOCAL_LIMITS \ + (SELECT_BY_SIZE_MAX_SPECIALIZED, BOOST_SELECT_BY_SIZE_MAX_CASE) \ + /**/ +#include BOOST_PP_LOCAL_ITERATE() +#undef BOOST_PP_LOCAL_MACRO +#undef SELECT_BY_SIZE_MAX_SPECIALIZED +#define SELECT_BY_SIZE_MAX_SPECIALIZED BOOST_SELECT_BY_SIZE_MAX_CASE + +#endif diff --git a/win32/include/boost/iostreams/detail/streambuf.hpp b/win32/include/boost/iostreams/detail/streambuf.hpp new file mode 100755 index 000000000..53d811c59 --- /dev/null +++ b/win32/include/boost/iostreams/detail/streambuf.hpp @@ -0,0 +1,34 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_STREAMBUF_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_STREAMBUF_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +# include +#else +# include +#endif + +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES +# define BOOST_IOSTREAMS_BASIC_STREAMBUF(ch, tr) std::basic_streambuf< ch, tr > +# define BOOST_IOSTREAMS_PUBSYNC pubsync +# define BOOST_IOSTREAMS_PUBSEEKOFF pubseekoff +# define BOOST_IOSTREAMS_PUBSEEKPOS pubseekpos +#else +# define BOOST_IOSTREAMS_BASIC_STREAMBUF(ch, tr) std::streambuf +# define BOOST_IOSTREAMS_PUBSYNC sync +# define BOOST_IOSTREAMS_PUBSEEKOFF seekoff +# define BOOST_IOSTREAMS_PUBSEEKPOS seekpos +#endif + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_STREAMBUF_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/streambuf/chainbuf.hpp b/win32/include/boost/iostreams/detail/streambuf/chainbuf.hpp new file mode 100755 index 000000000..82ad4bd02 --- /dev/null +++ b/win32/include/boost/iostreams/detail/streambuf/chainbuf.hpp @@ -0,0 +1,116 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_CHAINBUF_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_CHAINBUF_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // BOOST_MSVC, template friends. +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace iostreams { namespace detail { + +//--------------Definition of chainbuf----------------------------------------// + +// +// Template name: chainbuf. +// Description: Stream buffer which operates by delegating to the first +// linked_streambuf in a chain. +// Template paramters: +// Chain - The chain type. +// +template +class chainbuf + : public BOOST_IOSTREAMS_BASIC_STREAMBUF( + typename Chain::char_type, + typename Chain::traits_type + ), + public access_control, + private noncopyable +{ +private: + typedef access_control, Access> client_type; +public: + typedef typename Chain::char_type char_type; + BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(typename Chain::traits_type) +protected: + typedef linked_streambuf delegate_type; + chainbuf() { client_type::set_chain(&chain_); } + int_type underflow() + { sentry t(this); return translate(delegate().underflow()); } + int_type pbackfail(int_type c) + { sentry t(this); return translate(delegate().pbackfail(c)); } + std::streamsize xsgetn(char_type* s, std::streamsize n) + { sentry t(this); return delegate().xsgetn(s, n); } + int_type overflow(int_type c) + { sentry t(this); return translate(delegate().overflow(c)); } + std::streamsize xsputn(const char_type* s, std::streamsize n) + { sentry t(this); return delegate().xsputn(s, n); } + int sync() { sentry t(this); return delegate().sync(); } + pos_type seekoff( off_type off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which = + BOOST_IOS::in | BOOST_IOS::out ) + { sentry t(this); return delegate().seekoff(off, way, which); } + pos_type seekpos( pos_type sp, + BOOST_IOS::openmode which = + BOOST_IOS::in | BOOST_IOS::out ) + { sentry t(this); return delegate().seekpos(sp, which); } +protected: + typedef BOOST_IOSTREAMS_BASIC_STREAMBUF( + typename Chain::char_type, + typename Chain::traits_type + ) base_type; +//#if !BOOST_WORKAROUND(__GNUC__, == 2) +// BOOST_IOSTREAMS_USING_PROTECTED_STREAMBUF_MEMBERS(base_type) +//#endif +private: + + // Translate from std int_type to chain's int_type. + typedef BOOST_IOSTREAMS_CHAR_TRAITS(char_type) std_traits; + typedef typename Chain::traits_type chain_traits; + static typename chain_traits::int_type + translate(typename std_traits::int_type c) + { return translate_int_type(c); } + + delegate_type& delegate() + { return static_cast(chain_.front()); } + void get_pointers() + { + this->setg(delegate().eback(), delegate().gptr(), delegate().egptr()); + this->setp(delegate().pbase(), delegate().epptr()); + this->pbump((int) (delegate().pptr() - delegate().pbase())); + } + void set_pointers() + { + delegate().setg(this->eback(), this->gptr(), this->egptr()); + delegate().setp(this->pbase(), this->epptr()); + delegate().pbump((int) (this->pptr() - this->pbase())); + } + struct sentry { + sentry(chainbuf* buf) : buf_(buf) + { buf_->set_pointers(); } + ~sentry() { buf_->get_pointers(); } + chainbuf* buf_; + }; + friend struct sentry; + Chain chain_; +}; + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_CHAINBUF_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/streambuf/direct_streambuf.hpp b/win32/include/boost/iostreams/detail/streambuf/direct_streambuf.hpp new file mode 100755 index 000000000..0c257cfb6 --- /dev/null +++ b/win32/include/boost/iostreams/detail/streambuf/direct_streambuf.hpp @@ -0,0 +1,306 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_DIRECT_STREAMBUF_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_DIRECT_STREAMBUF_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include +#include // pair. +#include // BOOST_DEDUCED_TYPENAME, +#include // member template friends. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Must come last. +#include // MSVC. + +namespace boost { namespace iostreams { + +namespace detail { + +template< typename T, + typename Tr = + BOOST_IOSTREAMS_CHAR_TRAITS( + BOOST_DEDUCED_TYPENAME char_type_of::type + ) > +class direct_streambuf + : public linked_streambuf::type, Tr> +{ +public: + typedef typename char_type_of::type char_type; + BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr) +private: + typedef linked_streambuf base_type; + typedef typename category_of::type category; + typedef BOOST_IOSTREAMS_BASIC_STREAMBUF( + char_type, traits_type + ) streambuf_type; +public: // stream needs access. + void open(const T& t, int buffer_size, int pback_size); + bool is_open() const; + void close(); + bool auto_close() const { return auto_close_; } + void set_auto_close(bool close) { auto_close_ = close; } + bool strict_sync() { return true; } + + // Declared in linked_streambuf. + T* component() { return storage_.get(); } +protected: +#if !BOOST_WORKAROUND(__GNUC__, == 2) + BOOST_IOSTREAMS_USING_PROTECTED_STREAMBUF_MEMBERS(base_type) +#endif + direct_streambuf(); + + //--------------Virtual functions-----------------------------------------// + + // Declared in linked_streambuf. + void close_impl(BOOST_IOS::openmode m); + const std::type_info& component_type() const { return typeid(T); } + void* component_impl() { return component(); } +#ifdef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES + public: +#endif + + // Declared in basic_streambuf. + int_type underflow(); + int_type pbackfail(int_type c); + int_type overflow(int_type c); + pos_type seekoff( off_type off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which ); + pos_type seekpos(pos_type sp, BOOST_IOS::openmode which); +private: + pos_type seek_impl( stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which ); + void init_input(any_tag) { } + void init_input(input); + void init_output(any_tag) { } + void init_output(output); + void init_get_area(); + void init_put_area(); + bool one_head() const; + bool two_head() const; + optional storage_; + char_type *ibeg_, *iend_, *obeg_, *oend_; + bool auto_close_; +}; + +//------------------Implementation of direct_streambuf------------------------// + +template +direct_streambuf::direct_streambuf() + : ibeg_(0), iend_(0), obeg_(0), oend_(0), auto_close_(true) +{ this->set_true_eof(true); } + +template +void direct_streambuf::open(const T& t, int, int) +{ + storage_.reset(t); + init_input(category()); + init_output(category()); + setg(0, 0, 0); + setp(0, 0); +} + +template +bool direct_streambuf::is_open() const +{ return ibeg_ != 0 || obeg_ != 0; } + +template +void direct_streambuf::close() +{ + base_type* self = this; + detail::execute_all( detail::call_member_close(*self, BOOST_IOS::in), + detail::call_member_close(*self, BOOST_IOS::out), + detail::call_reset(storage_) ); +} + +template +typename direct_streambuf::int_type +direct_streambuf::underflow() +{ + if (!ibeg_) + throw cant_read(); + if (!gptr()) + init_get_area(); + return gptr() != iend_ ? + traits_type::to_int_type(*gptr()) : + traits_type::eof(); +} + +template +typename direct_streambuf::int_type +direct_streambuf::pbackfail(int_type c) +{ + using namespace std; + if (!ibeg_) + throw cant_read(); + if (gptr() != 0 && gptr() != ibeg_) { + gbump(-1); + if (!traits_type::eq_int_type(c, traits_type::eof())) + *gptr() = traits_type::to_char_type(c); + return traits_type::not_eof(c); + } + throw bad_putback(); +} + +template +typename direct_streambuf::int_type +direct_streambuf::overflow(int_type c) +{ + using namespace std; + if (!obeg_) throw BOOST_IOSTREAMS_FAILURE("no write access"); + if (!pptr()) init_put_area(); + if (!traits_type::eq_int_type(c, traits_type::eof())) { + if (pptr() == oend_) + throw BOOST_IOSTREAMS_FAILURE("write area exhausted"); + *pptr() = traits_type::to_char_type(c); + pbump(1); + return c; + } + return traits_type::not_eof(c); +} + +template +inline typename direct_streambuf::pos_type +direct_streambuf::seekoff + (off_type off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which) +{ return seek_impl(off, way, which); } + +template +inline typename direct_streambuf::pos_type +direct_streambuf::seekpos + (pos_type sp, BOOST_IOS::openmode which) +{ + return seek_impl(position_to_offset(sp), BOOST_IOS::beg, which); +} + +template +void direct_streambuf::close_impl(BOOST_IOS::openmode which) +{ + if (which == BOOST_IOS::in && ibeg_ != 0) { + setg(0, 0, 0); + ibeg_ = iend_ = 0; + } + if (which == BOOST_IOS::out && obeg_ != 0) { + sync(); + setp(0, 0); + obeg_ = oend_ = 0; + } + boost::iostreams::close(*storage_, which); +} + +template +typename direct_streambuf::pos_type direct_streambuf::seek_impl + (stream_offset off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which) +{ + using namespace std; + BOOST_IOS::openmode both = BOOST_IOS::in | BOOST_IOS::out; + if (two_head() && (which & both) == both) + throw bad_seek(); + stream_offset result = -1; + bool one = one_head(); + if (one && (pptr() != 0 || gptr()== 0)) + init_get_area(); // Switch to input mode, for code reuse. + if (one || (which & BOOST_IOS::in) != 0 && ibeg_ != 0) { + if (!gptr()) setg(ibeg_, ibeg_, iend_); + ptrdiff_t next = 0; + switch (way) { + case BOOST_IOS::beg: next = off; break; + case BOOST_IOS::cur: next = (gptr() - ibeg_) + off; break; + case BOOST_IOS::end: next = (iend_ - ibeg_) + off; break; + default: assert(0); + } + if (next < 0 || next > (iend_ - ibeg_)) + throw bad_seek(); + setg(ibeg_, ibeg_ + next, iend_); + result = next; + } + if (!one && (which & BOOST_IOS::out) != 0 && obeg_ != 0) { + if (!pptr()) setp(obeg_, oend_); + ptrdiff_t next = 0; + switch (way) { + case BOOST_IOS::beg: next = off; break; + case BOOST_IOS::cur: next = (pptr() - obeg_) + off; break; + case BOOST_IOS::end: next = (oend_ - obeg_) + off; break; + default: assert(0); + } + if (next < 0 || next > (oend_ - obeg_)) + throw bad_seek(); + pbump(static_cast(next - (pptr() - obeg_))); + result = next; + } + return offset_to_position(result); +} + +template +void direct_streambuf::init_input(input) +{ + std::pair p = input_sequence(*storage_); + ibeg_ = p.first; + iend_ = p.second; +} + +template +void direct_streambuf::init_output(output) +{ + std::pair p = output_sequence(*storage_); + obeg_ = p.first; + oend_ = p.second; +} + +template +void direct_streambuf::init_get_area() +{ + setg(ibeg_, ibeg_, iend_); + if (one_head() && pptr()) { + gbump(static_cast(pptr() - obeg_)); + setp(0, 0); + } +} + +template +void direct_streambuf::init_put_area() +{ + setp(obeg_, oend_); + if (one_head() && gptr()) { + pbump(static_cast(gptr() - ibeg_)); + setg(0, 0, 0); + } +} + +template +inline bool direct_streambuf::one_head() const +{ return ibeg_ && obeg_ && ibeg_ == obeg_; } + +template +inline bool direct_streambuf::two_head() const +{ return ibeg_ && obeg_ && ibeg_ != obeg_; } + +//----------------------------------------------------------------------------// + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#include // MSVC + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_DIRECT_STREAMBUF_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/streambuf/indirect_streambuf.hpp b/win32/include/boost/iostreams/detail/streambuf/indirect_streambuf.hpp new file mode 100755 index 000000000..23b590e38 --- /dev/null +++ b/win32/include/boost/iostreams/detail/streambuf/indirect_streambuf.hpp @@ -0,0 +1,430 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) +// See http://www.boost.org/libs/iostreams for documentation. + +// This material is heavily indebted to the discussion and code samples in +// A. Langer and K. Kreft, "Standard C++ IOStreams and Locales", +// Addison-Wesley, 2000, pp. 228-43. + +// User "GMSB" provided an optimization for small seeks. + +#ifndef BOOST_IOSTREAMS_DETAIL_INDIRECT_STREAMBUF_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_INDIRECT_STREAMBUF_HPP_INCLUDED + +#include // min, max. +#include +#include +#include +#include // Member template friends. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Must come last. +#include // MSVC, BCC 5.x + +namespace boost { namespace iostreams { namespace detail { + +// +// Description: The implementation of basic_streambuf used by chains. +// +template +class indirect_streambuf + : public linked_streambuf::type, Tr> +{ +public: + typedef typename char_type_of::type char_type; + BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr) +private: + typedef typename category_of::type category; + typedef concept_adapter wrapper; + typedef detail::basic_buffer buffer_type; + typedef indirect_streambuf my_type; + typedef detail::linked_streambuf base_type; + typedef linked_streambuf streambuf_type; +public: + indirect_streambuf(); + + void open(const T& t BOOST_IOSTREAMS_PUSH_PARAMS()); + bool is_open() const; + void close(); + bool auto_close() const; + void set_auto_close(bool close); + bool strict_sync(); + + // Declared in linked_streambuf. + T* component() { return &*obj(); } +protected: +#if !BOOST_WORKAROUND(__GNUC__, == 2) + BOOST_IOSTREAMS_USING_PROTECTED_STREAMBUF_MEMBERS(base_type) +#endif + + //----------virtual functions---------------------------------------------// + +#ifndef BOOST_IOSTREAMS_NO_LOCALE + void imbue(const std::locale& loc); +#endif +#ifdef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES + public: +#endif + int_type underflow(); + int_type pbackfail(int_type c); + int_type overflow(int_type c); + int sync(); + pos_type seekoff( off_type off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which ); + pos_type seekpos(pos_type sp, BOOST_IOS::openmode which); + + // Declared in linked_streambuf. + void set_next(streambuf_type* next); + void close_impl(BOOST_IOS::openmode m); + const std::type_info& component_type() const { return typeid(T); } + void* component_impl() { return component(); } +private: + + //----------Accessor functions--------------------------------------------// + + wrapper& obj() { return *storage_; } + streambuf_type* next() const { return next_; } + buffer_type& in() { return buffer_.first(); } + buffer_type& out() { return buffer_.second(); } + bool can_read() const { return is_convertible::value; } + bool can_write() const { return is_convertible::value; } + bool output_buffered() const { return (flags_ & f_output_buffered) != 0; } + bool shared_buffer() const { return is_convertible::value; } + void set_flags(int f) { flags_ = f; } + + //----------State changing functions--------------------------------------// + + virtual void init_get_area(); + virtual void init_put_area(); + + //----------Utility function----------------------------------------------// + + pos_type seek_impl( stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which ); + void sync_impl(); + + enum flag_type { + f_open = 1, + f_output_buffered = f_open << 1, + f_auto_close = f_output_buffered << 1 + }; + + optional storage_; + streambuf_type* next_; + double_object< + buffer_type, + is_convertible< + Mode, + two_sequence + > + > buffer_; + std::streamsize pback_size_; + int flags_; +}; + +//--------------Implementation of indirect_streambuf--------------------------// + +template +indirect_streambuf::indirect_streambuf() + : next_(0), pback_size_(0), flags_(f_auto_close) { } + +//--------------Implementation of open, is_open and close---------------------// + +template +void indirect_streambuf::open + (const T& t, int buffer_size, int pback_size) +{ + using namespace std; + + // Normalize buffer sizes. + buffer_size = + (buffer_size != -1) ? + buffer_size : + iostreams::optimal_buffer_size(t); + pback_size = + (pback_size != -1) ? + pback_size : + default_pback_buffer_size; + + // Construct input buffer. + if (can_read()) { + pback_size_ = (std::max)(2, pback_size); // STLPort needs 2. + std::streamsize size = + pback_size_ + + ( buffer_size ? buffer_size: 1 ); + in().resize(size); + if (!shared_buffer()) + init_get_area(); + } + + // Construct output buffer. + if (can_write() && !shared_buffer()) { + if (buffer_size != 0) + out().resize(buffer_size); + init_put_area(); + } + + storage_.reset(wrapper(t)); + flags_ |= f_open; + if (can_write() && buffer_size > 1) + flags_ |= f_output_buffered; + this->set_true_eof(false); +} + +template +inline bool indirect_streambuf::is_open() const +{ return (flags_ & f_open) != 0; } + +template +void indirect_streambuf::close() +{ + using namespace std; + base_type* self = this; + detail::execute_all( + detail::call_member_close(*self, BOOST_IOS::in), + detail::call_member_close(*self, BOOST_IOS::out), + detail::call_reset(storage_), + detail::clear_flags(flags_) + ); +} + +template +bool indirect_streambuf::auto_close() const +{ return (flags_ & f_auto_close) != 0; } + +template +void indirect_streambuf::set_auto_close(bool close) +{ flags_ = (flags_ & ~f_auto_close) | (close ? f_auto_close : 0); } + +//--------------Implementation virtual functions------------------------------// + +#ifndef BOOST_IOSTREAMS_NO_LOCALE +template +void indirect_streambuf::imbue(const std::locale& loc) +{ + if (is_open()) { + obj().imbue(loc); + if (next_) + next_->pubimbue(loc); + } +} +#endif + +template +typename indirect_streambuf::int_type +indirect_streambuf::underflow() +{ + using namespace std; + if (!gptr()) init_get_area(); + buffer_type& buf = in(); + if (gptr() < egptr()) return traits_type::to_int_type(*gptr()); + + // Fill putback buffer. + std::streamsize keep = + (std::min)( static_cast(gptr() - eback()), + pback_size_ ); + if (keep) + traits_type::move( buf.data() + (pback_size_ - keep), + gptr() - keep, keep ); + + // Set pointers to reasonable values in case read throws. + setg( buf.data() + pback_size_ - keep, + buf.data() + pback_size_, + buf.data() + pback_size_ ); + + // Read from source. + std::streamsize chars = + obj().read(buf.data() + pback_size_, buf.size() - pback_size_, next_); + if (chars == -1) { + this->set_true_eof(true); + chars = 0; + } + setg(eback(), gptr(), buf.data() + pback_size_ + chars); + return chars != 0 ? + traits_type::to_int_type(*gptr()) : + traits_type::eof(); +} + +template +typename indirect_streambuf::int_type +indirect_streambuf::pbackfail(int_type c) +{ + if (gptr() != eback()) { + gbump(-1); + if (!traits_type::eq_int_type(c, traits_type::eof())) + *gptr() = traits_type::to_char_type(c); + return traits_type::not_eof(c); + } else { + throw bad_putback(); + } +} + +template +typename indirect_streambuf::int_type +indirect_streambuf::overflow(int_type c) +{ + if ( output_buffered() && pptr() == 0 || + shared_buffer() && gptr() != 0 ) + { + init_put_area(); + } + if (!traits_type::eq_int_type(c, traits_type::eof())) { + if (output_buffered()) { + if (pptr() == epptr()) { + sync_impl(); + if (pptr() == epptr()) + return traits_type::eof(); + } + *pptr() = traits_type::to_char_type(c); + pbump(1); + } else { + char_type d = traits_type::to_char_type(c); + if (obj().write(&d, 1, next_) != 1) + return traits_type::eof(); + } + } + return traits_type::not_eof(c); +} + +template +int indirect_streambuf::sync() +{ + try { // sync() is no-throw. + sync_impl(); + obj().flush(next_); + return 0; + } catch (...) { return -1; } +} + +template +bool indirect_streambuf::strict_sync() +{ + try { // sync() is no-throw. + sync_impl(); + return obj().flush(next_); + } catch (...) { return false; } +} + +template +inline typename indirect_streambuf::pos_type +indirect_streambuf::seekoff + (off_type off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which) +{ return seek_impl(off, way, which); } + +template +inline typename indirect_streambuf::pos_type +indirect_streambuf::seekpos + (pos_type sp, BOOST_IOS::openmode which) +{ + return seek_impl(position_to_offset(sp), BOOST_IOS::beg, which); +} + +template +typename indirect_streambuf::pos_type +indirect_streambuf::seek_impl + (stream_offset off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which) +{ + if ( gptr() != 0 && way == BOOST_IOS::cur && which == BOOST_IOS::in && + eback() - gptr() <= off && off <= egptr() - gptr() ) + { // Small seek optimization + gbump(off); + return obj().seek(0, BOOST_IOS::cur, BOOST_IOS::in, next_) - + static_cast(egptr() - gptr()); + } + if (pptr() != 0) + this->BOOST_IOSTREAMS_PUBSYNC(); // sync() confuses VisualAge 6. + if (way == BOOST_IOS::cur && gptr()) + off -= static_cast(egptr() - gptr()); + setg(0, 0, 0); + setp(0, 0); + return obj().seek(off, way, which, next_); +} + +template +inline void indirect_streambuf::set_next + (streambuf_type* next) +{ next_ = next; } + +template +inline void indirect_streambuf::close_impl + (BOOST_IOS::openmode which) +{ + if (which == BOOST_IOS::in && is_convertible::value) { + setg(0, 0, 0); + } + if (which == BOOST_IOS::out && is_convertible::value) { + sync(); + setp(0, 0); + } + if ( !is_convertible::value || + is_convertible::value == (which == BOOST_IOS::in) ) + { + obj().close(which, next_); + } +} + +//----------State changing functions------------------------------------------// + +template +void indirect_streambuf::sync_impl() +{ + std::streamsize avail, amt; + if ((avail = static_cast(pptr() - pbase())) > 0) { + if ((amt = obj().write(pbase(), avail, next())) == avail) + setp(out().begin(), out().end()); + else { + const char_type* ptr = pptr(); + setp(out().begin() + amt, out().end()); + pbump(ptr - pptr()); + } + } +} + +template +void indirect_streambuf::init_get_area() +{ + if (shared_buffer() && pptr() != 0) { + sync_impl(); + setp(0, 0); + } + setg(in().begin(), in().begin(), in().begin()); +} + +template +void indirect_streambuf::init_put_area() +{ + using namespace std; + if (shared_buffer() && gptr() != 0) + setg(0, 0, 0); + if (output_buffered()) + setp(out().begin(), out().end()); + else + setp(0, 0); +} + +//----------------------------------------------------------------------------// + +} } } // End namespaces detail, iostreams, boost. + +#include // MSVC, BCC 5.x + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_INDIRECT_STREAMBUF_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/streambuf/linked_streambuf.hpp b/win32/include/boost/iostreams/detail/streambuf/linked_streambuf.hpp new file mode 100755 index 000000000..c167e318e --- /dev/null +++ b/win32/include/boost/iostreams/detail/streambuf/linked_streambuf.hpp @@ -0,0 +1,114 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_LINKED_STREAMBUF_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_LINKED_STREAMBUF_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include // member template friends. +#include +#include // openmode. +#include + +// Must come last. +#include // MSVC. + +namespace boost { namespace iostreams { namespace detail { + +template +class chain_base; + +template class chainbuf; + +#define BOOST_IOSTREAMS_USING_PROTECTED_STREAMBUF_MEMBERS(base) \ + using base::eback; using base::gptr; using base::egptr; \ + using base::setg; using base::gbump; using base::pbase; \ + using base::pptr; using base::epptr; using base::setp; \ + using base::pbump; using base::underflow; using base::pbackfail; \ + using base::xsgetn; using base::overflow; using base::xsputn; \ + using base::sync; using base::seekoff; using base::seekpos; \ + /**/ + +template +class linked_streambuf : public BOOST_IOSTREAMS_BASIC_STREAMBUF(Ch, Tr) { +protected: + linked_streambuf() : flags_(0) { } + void set_true_eof(bool eof) + { + flags_ = (flags_ & ~f_true_eof) | (eof ? f_true_eof : 0); + } +public: + + // Should be called only after receiving an ordinary EOF indication, + // to confirm that it represents EOF rather than WOULD_BLOCK. + bool true_eof() const { return (flags_ & f_true_eof) != 0; } +protected: + + //----------grant friendship to chain_base and chainbuf-------------------// + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + template< typename Self, typename ChT, typename TrT, + typename Alloc, typename Mode > + friend class chain_base; + template + friend class chainbuf; + template + friend class member_close_operation; +#else + public: + typedef BOOST_IOSTREAMS_BASIC_STREAMBUF(Ch, Tr) base; + BOOST_IOSTREAMS_USING_PROTECTED_STREAMBUF_MEMBERS(base) +#endif + void close(BOOST_IOS::openmode which) + { + if ( which == BOOST_IOS::in && + (flags_ & f_input_closed) == 0 ) + { + flags_ |= f_input_closed; + close_impl(which); + } + if ( which == BOOST_IOS::out && + (flags_ & f_output_closed) == 0 ) + { + flags_ |= f_output_closed; + close_impl(which); + } + } + void set_needs_close() + { + flags_ &= ~(f_input_closed | f_output_closed); + } + virtual void set_next(linked_streambuf* /* next */) { } + virtual void close_impl(BOOST_IOS::openmode) = 0; + virtual bool auto_close() const = 0; + virtual void set_auto_close(bool) = 0; + virtual bool strict_sync() = 0; + virtual const std::type_info& component_type() const = 0; + virtual void* component_impl() = 0; +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + private: +#else + public: +#endif +private: + enum flag_type { + f_true_eof = 1, + f_input_closed = f_true_eof << 1, + f_output_closed = f_input_closed << 1 + }; + int flags_; +}; + +} } } // End namespaces detail, iostreams, boost. + +#include // MSVC. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_LINKED_STREAMBUF_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/system_failure.hpp b/win32/include/boost/iostreams/detail/system_failure.hpp new file mode 100755 index 000000000..197a73c1b --- /dev/null +++ b/win32/include/boost/iostreams/detail/system_failure.hpp @@ -0,0 +1,83 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// (C) Copyright Jonathan Graehl 2004. +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Used by mapped_file.cpp. + +#ifndef BOOST_IOSTREAMS_DETAIL_SYSTEM_FAILURE_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_SYSTEM_FAILURE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include +#include +#include // failure. + +#if defined(BOOST_NO_STDC_NAMESPACE) && !defined(__LIBCOMO__) +namespace std { using ::strlen; } +#endif + +#ifdef BOOST_IOSTREAMS_WINDOWS +# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +# include +#else +# include +# include +#endif + +namespace boost { namespace iostreams { namespace detail { + +inline BOOST_IOSTREAMS_FAILURE system_failure(const char* msg) +{ + std::string result; +#ifdef BOOST_IOSTREAMS_WINDOWS + DWORD err; + LPVOID lpMsgBuf; + if ( (err = ::GetLastError()) != NO_ERROR && + ::FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR) &lpMsgBuf, + 0, + NULL ) != 0 ) + { + result.reserve(std::strlen(msg) + 2 + std::strlen((LPSTR)lpMsgBuf)); + result.append(msg); + result.append(": "); + result.append((LPSTR) lpMsgBuf); + ::LocalFree(lpMsgBuf); + } else { + result += msg; + } +#else + const char* system_msg = errno ? strerror(errno) : ""; + result.reserve(std::strlen(msg) + 2 + std::strlen(system_msg)); + result.append(msg); + result.append(": "); + result.append(system_msg); +#endif + return BOOST_IOSTREAMS_FAILURE(result); +} + +inline BOOST_IOSTREAMS_FAILURE system_failure(const std::string& msg) +{ return system_failure(msg.c_str()); } + +inline void throw_system_failure(const char* msg) +{ throw system_failure(msg); } + +inline void throw_system_failure(const std::string& msg) +{ throw system_failure(msg); } + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_SYSTEM_FAILURE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/template_params.hpp b/win32/include/boost/iostreams/detail/template_params.hpp new file mode 100755 index 000000000..54f426b08 --- /dev/null +++ b/win32/include/boost/iostreams/detail/template_params.hpp @@ -0,0 +1,26 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_TEMPLATE_PARAMS_HPP_INCLUDED + +#include +#include +#include + +#define BOOST_IOSTREAMS_TEMPLATE_PARAMS(arity, param) \ + BOOST_PP_EXPR_IF(arity, template<) \ + BOOST_PP_ENUM_PARAMS(arity, typename param) \ + BOOST_PP_EXPR_IF(arity, >) \ + /**/ + +#define BOOST_IOSTREAMS_TEMPLATE_ARGS(arity, param) \ + BOOST_PP_EXPR_IF(arity, <) \ + BOOST_PP_ENUM_PARAMS(arity, param) \ + BOOST_PP_EXPR_IF(arity, >) \ + /**/ + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_BUFFERS_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/translate_int_type.hpp b/win32/include/boost/iostreams/detail/translate_int_type.hpp new file mode 100755 index 000000000..f5fa3176e --- /dev/null +++ b/win32/include/boost/iostreams/detail/translate_int_type.hpp @@ -0,0 +1,62 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_TRANSLATE_INT_TYPE_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_TRANSLATE_INT_TYPE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include + +namespace boost { namespace iostreams { namespace detail { + +template +struct translate_int_type_impl; + +// +// Template name: translate_char. +// Description: Translates a character or an end-of-file indicator from the +// int_type of one character traits type to the int_type of another. +// +template +typename TargetTr::int_type +translate_int_type(typename SourceTr::int_type c) +{ + typedef translate_int_type_impl::value> impl; + return impl::template inner::translate(c); +} + +//----------------------------------------------------------------------------// + +template<> +struct translate_int_type_impl { + template + struct inner { + static typename TargetTr::int_type + translate(typename SourceTr::int_type c) { return c; } + }; +}; + +template<> +struct translate_int_type_impl { + template + struct inner { + static typename TargetTr::int_type + translate(typename SourceTr::int_type c) + { + return SourceTr::eq_int_type(SourceTr::eof()) ? + TargetTr::eof() : + TargetTr::to_int_type(SourceTr::to_char_type(c)); + } + }; +}; + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_TRANSLATE_INT_TYPE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/detail/vc6/close.hpp b/win32/include/boost/iostreams/detail/vc6/close.hpp new file mode 100755 index 000000000..921225fbe --- /dev/null +++ b/win32/include/boost/iostreams/detail/vc6/close.hpp @@ -0,0 +1,129 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +namespace boost { namespace iostreams { + +namespace detail { + +template +struct close_impl; + +} // End namespace detail. + +template +void close(T& t) { detail::close_all(t); } + +template +void close(T& t, BOOST_IOS::openmode which) +{ + typedef typename detail::unwrapped_type::type unwrapped; + detail::close_impl::inner::close(detail::unwrap(t), which); +} + +template +void close(T& t, Sink& snk, BOOST_IOS::openmode which) +{ + typedef typename detail::unwrapped_type::type unwrapped; + detail::close_impl::inner::close(detail::unwrap(t), snk, which); +} + +namespace detail { + +//------------------Definition of close_impl----------------------------------// + +template +struct close_tag { + typedef typename category_of::type category; + typedef typename + mpl::eval_if< + is_convertible, + mpl::if_< + mpl::or_< + is_convertible, + is_convertible + >, + two_sequence, + closable_tag + >, + mpl::identity + >::type type; +}; + +template +struct close_impl + : mpl::if_< + is_custom, + operations, + close_impl::type> + >::type + { }; + +template<> +struct close_impl { + template + struct inner { + static void close(T& t, BOOST_IOS::openmode which) + { + if (which == BOOST_IOS::out) + iostreams::flush(t); + } + + template + static void close(T& t, Sink& snk, BOOST_IOS::openmode which) + { + if (which == BOOST_IOS::out) { + non_blocking_adapter nb(snk); + iostreams::flush(t, nb); + } + } + }; +}; + +template<> +struct close_impl { + template + struct inner { + static void close(T& t, BOOST_IOS::openmode which) + { + typedef typename category_of::type category; + const bool in = is_convertible::value && + !is_convertible::value; + if (in == (which == BOOST_IOS::in)) + t.close(); + } + template + static void close(T& t, Sink& snk, BOOST_IOS::openmode which) + { + typedef typename category_of::type category; + const bool in = is_convertible::value && + !is_convertible::value; + if (in == (which == BOOST_IOS::in)) { + non_blocking_adapter nb(snk); + t.close(nb); + } + } + }; +}; + +template<> +struct close_impl { + template + struct inner { + static void close(T& t, BOOST_IOS::openmode which) { t.close(which); } + + template + static void close(T& t, Sink& snk, BOOST_IOS::openmode which) + { + non_blocking_adapter nb(snk); + t.close(nb, which); + } + }; +}; + +} // End namespace detail. + +} } // End namespaces iostreams, boost. diff --git a/win32/include/boost/iostreams/detail/vc6/read.hpp b/win32/include/boost/iostreams/detail/vc6/read.hpp new file mode 100755 index 000000000..518f70f20 --- /dev/null +++ b/win32/include/boost/iostreams/detail/vc6/read.hpp @@ -0,0 +1,238 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +namespace boost { namespace iostreams { + +namespace detail { + +template +struct read_device_impl; + +template +struct read_filter_impl; + +} // End namespace detail. + +template +typename int_type_of::type get(T& t) +{ + typedef typename detail::unwrapped_type::type unwrapped; + return detail::read_device_impl::inner::get(detail::unwrap(t)); +} + +template +inline std::streamsize +read(T& t, typename char_type_of::type* s, std::streamsize n) +{ + typedef typename detail::unwrapped_type::type unwrapped; + return detail::read_device_impl::inner::read(detail::unwrap(t), s, n); +} + +template +std::streamsize +read(T& t, Source& src, typename char_type_of::type* s, std::streamsize n) +{ + typedef typename detail::unwrapped_type::type unwrapped; + return detail::read_filter_impl::inner::read(detail::unwrap(t), src, s, n); +} + +template +bool putback(T& t, typename char_type_of::type c) +{ + typedef typename detail::unwrapped_type::type unwrapped; + return detail::read_device_impl::inner::putback(detail::unwrap(t), c); +} + +//----------------------------------------------------------------------------// + +namespace detail { + +// Helper function for adding -1 as EOF indicator. +inline std::streamsize check_eof(std::streamsize n) { return n != 0 ? n : -1; } + +// Helper templates for reading from streambufs. +template +struct true_eof_impl; + +template<> +struct true_eof_impl { + template + static bool true_eof(T& t) { return t.true_eof(); } +}; + +template<> +struct true_eof_impl { + template + static bool true_eof(T& t) { return true; } +}; + +template +inline bool true_eof(T& t) +{ + const bool linked = is_linked::value; + return true_eof_impl::true_eof(t); +} + +//------------------Definition of read_device_impl----------------------------// + +template +struct read_device_impl + : mpl::if_< + detail::is_custom, + operations, + read_device_impl< + BOOST_DEDUCED_TYPENAME + detail::dispatch< + T, istream_tag, streambuf_tag, input + >::type + > + >::type + { }; + +template<> +struct read_device_impl { + template + struct inner { + static typename int_type_of::type get(T& t) + { return t.get(); } + + static std::streamsize + read(T& t, typename char_type_of::type* s, std::streamsize n) + { return check_eof(t.rdbuf()->sgetn(s, n)); } + + static bool putback(T& t, typename char_type_of::type c) + { + typedef typename char_type_of::type char_type; + typedef BOOST_IOSTREAMS_CHAR_TRAITS(char_type) traits_type; + return !traits_type::eq_int_type( t.rdbuf()->sputbackc(c), + traits_type::eof() ); + } + }; +}; + +template<> +struct read_device_impl { + template + struct inner { + static typename int_type_of::type + get(T& t) + { + typedef typename char_type_of::type char_type; + typedef char_traits traits_type; + typename int_type_of::type c; + return !traits_type::is_eof(c = t.sbumpc()) || + detail::true_eof(t) + ? + c : traits_type::would_block(); + } + + static std::streamsize + read(T& t, typename char_type_of::type* s, std::streamsize n) + { + std::streamsize amt; + return (amt = t.sgetn(s, n)) != 0 ? + amt : + detail::true_eof(t) ? + -1 : + 0; + } + + static bool putback(T& t, typename char_type_of::type c) + { + typedef typename char_type_of::type char_type; + typedef char_traits traits_type; + return !traits_type::is_eof(t.sputbackc(c)); + } + }; +}; + +template<> +struct read_device_impl { + template + struct inner { + static typename int_type_of::type + get(T& t) + { + typedef typename char_type_of::type char_type; + typedef char_traits traits_type; + char_type c; + std::streamsize amt; + return (amt = t.read(&c, 1)) == 1 ? + traits_type::to_int_type(c) : + amt == -1 ? + traits_type::eof() : + traits_type::would_block(); + } + + template + static std::streamsize + read(T& t, typename char_type_of::type* s, std::streamsize n) + { return t.read(s, n); } + + template + static bool putback(T& t, typename char_type_of::type c) + { // T must be Peekable. + return t.putback(c); + } + }; +}; + +//------------------Definition of read_filter_impl----------------------------// + +template +struct read_filter_impl + : mpl::if_< + detail::is_custom, + operations, + read_filter_impl< + BOOST_DEDUCED_TYPENAME + detail::dispatch< + T, multichar_tag, any_tag + >::type + > + >::type + { }; + +template<> +struct read_filter_impl { + template + struct inner { + template + static std::streamsize read + ( T& t, Source& src, typename char_type_of::type* s, + std::streamsize n ) + { return t.read(src, s, n); } + }; +}; + +template<> +struct read_filter_impl { + template + struct inner { + template + static std::streamsize read + ( T& t, Source& src, typename char_type_of::type* s, + std::streamsize n ) + { + typedef typename char_type_of::type char_type; + typedef char_traits traits_type; + for (std::streamsize off = 0; off < n; ++off) { + typename traits_type::int_type c = t.get(src); + if (traits_type::is_eof(c)) + return check_eof(off); + if (traits_type::would_block(c)) + return off; + s[off] = traits_type::to_char_type(c); + } + return n; + } + }; +}; + +} // End namespace detail. + +} } // End namespaces iostreams, boost. diff --git a/win32/include/boost/iostreams/detail/vc6/write.hpp b/win32/include/boost/iostreams/detail/vc6/write.hpp new file mode 100755 index 000000000..692ea2876 --- /dev/null +++ b/win32/include/boost/iostreams/detail/vc6/write.hpp @@ -0,0 +1,159 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +namespace boost { namespace iostreams { + +namespace detail { + +template +struct write_device_impl; + +template +struct write_filter_impl; + +} // End namespace detail. + +template +bool put(T& t, typename char_type_of::type c) +{ + typedef typename detail::unwrapped_type::type unwrapped; + return detail::write_device_impl::inner::put(detail::unwrap(t), c); +} + +template +inline std::streamsize write + (T& t, const typename char_type_of::type* s, std::streamsize n) +{ + typedef typename detail::unwrapped_type::type unwrapped; + return detail::write_device_impl::inner::write(detail::unwrap(t), s, n); +} + +template +inline std::streamsize +write( T& t, Sink& snk, const typename char_type_of::type* s, + std::streamsize n ) +{ + typedef typename detail::unwrapped_type::type unwrapped; + return detail::write_filter_impl::inner::write(detail::unwrap(t), snk, s, n); +} + +namespace detail { + +//------------------Definition of write_device_impl---------------------------// + +template +struct write_device_impl + : mpl::if_< + is_custom, + operations, + write_device_impl< + BOOST_DEDUCED_TYPENAME + dispatch< + T, ostream_tag, streambuf_tag, output + >::type + > + >::type + { }; + +template<> +struct write_device_impl { + template + struct inner { + static bool put(T& t, typename char_type_of::type c) + { + typedef typename char_type_of::type char_type; + typedef BOOST_IOSTREAMS_CHAR_TRAITS(char_type) traits_type; + return !traits_type::eq_int_type( t.rdbuf()->s.sputc(), + traits_type::eof() ); + } + + static std::streamsize write + (T& t, const typename char_type_of::type* s, std::streamsize n) + { return t.rdbuf()->sputn(s, n); } + }; +}; + +template<> +struct write_device_impl { + template + struct inner { + static bool put(T& t, typename char_type_of::type c) + { + typedef typename char_type_of::type char_type; + typedef BOOST_IOSTREAMS_CHAR_TRAITS(char_type) traits_type; + return !traits_type::eq_int_type(t.sputc(c), traits_type::eof()); + } + + template + static std::streamsize write + (T& t, const typename char_type_of::type* s, std::streamsize n) + { return t.sputn(s, n); } + }; +}; + +template<> +struct write_device_impl { + template + struct inner { + static bool put(T& t, typename char_type_of::type c) + { return t.write(&c, 1) == 1; } + + template + static std::streamsize + write(T& t, const typename char_type_of::type* s, std::streamsize n) + { return t.write(s, n); } + }; +}; + +//------------------Definition of write_filter_impl---------------------------// + +template +struct write_filter_impl + : mpl::if_< + is_custom, + operations, + write_filter_impl< + BOOST_DEDUCED_TYPENAME + dispatch< + T, multichar_tag, any_tag + >::type + > + >::type + { }; + +template<> +struct write_filter_impl { + template + struct inner { + template + static std::streamsize + write( T& t, Sink& snk, const typename char_type_of::type* s, + std::streamsize n ) + { return t.write(snk, s, n); } + }; +}; + +template<> +struct write_filter_impl { + template + struct inner { + template + static std::streamsize + write( T& t, Sink& snk, const typename char_type_of::type* s, + std::streamsize n ) + { + for (std::streamsize off = 0; off < n; ++off) + if (!t.put(snk, s[off])) + return off; + return n; + } + }; +}; + +} // End namespace detail. + +} } // End namespaces iostreams, boost. diff --git a/win32/include/boost/iostreams/detail/wrap_unwrap.hpp b/win32/include/boost/iostreams/detail/wrap_unwrap.hpp new file mode 100755 index 000000000..ceedd0fc0 --- /dev/null +++ b/win32/include/boost/iostreams/detail/wrap_unwrap.hpp @@ -0,0 +1,127 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_DETAIL_WRAP_UNWRAP_HPP_INCLUDED +#define BOOST_IOSTREAMS_DETAIL_WRAP_UNWRAP_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // SFINAE, MSVC. +#include +#include +#include // is_std_io. +#include +#include +#include +#include +#include + +namespace boost { namespace iostreams { namespace detail { + +//------------------Definition of wrap/unwrap traits--------------------------// + +template +struct wrapped_type + : mpl::if_, reference_wrapper, T> + { }; + +template +struct unwrapped_type + : unwrap_reference + { }; + +template +struct unwrap_ios + : mpl::eval_if< + is_std_io, + unwrap_reference, + mpl::identity + > + { }; + +//------------------Definition of wrap----------------------------------------// + +#ifndef BOOST_NO_SFINAE //----------------------------------------------------// + template + inline T wrap(const T& t BOOST_IOSTREAMS_DISABLE_IF_STREAM(T)) + { return t; } + + template + inline typename wrapped_type::type + wrap(T& t BOOST_IOSTREAMS_ENABLE_IF_STREAM(T)) { return boost::ref(t); } +#else // #ifndef BOOST_NO_SFINAE //-------------------------------------------// + template + inline typename wrapped_type::type // BCC 5.x needs namespace qualification. + wrap_impl(const T& t, mpl::true_) { return boost::ref(const_cast(t)); } + + template + inline typename wrapped_type::type // BCC 5.x needs namespace qualification. + wrap_impl(T& t, mpl::true_) { return boost::ref(t); } + + template + inline typename wrapped_type::type + wrap_impl(const T& t, mpl::false_) { return t; } + + template + inline typename wrapped_type::type + wrap_impl(T& t, mpl::false_) { return t; } + + template + inline typename wrapped_type::type + wrap(const T& t) { return wrap_impl(t, is_std_io()); } + + template + inline typename wrapped_type::type + wrap(T& t) { return wrap_impl(t, is_std_io()); } +#endif // #ifndef BOOST_NO_SFINAE //------------------------------------------// + +//------------------Definition of unwrap--------------------------------------// + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) //----------------------------------// + +template +typename unwrapped_type::type& +unwrap(const reference_wrapper& ref) { return ref.get(); } + +template +typename unwrapped_type::type& unwrap(T& t) { return t; } + +template +const typename unwrapped_type::type& unwrap(const T& t) { return t; } + +#else // #if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) //-------------------------// + +// Since unwrap is a potential bottleneck, we avoid runtime tag dispatch. +template +struct unwrap_impl; + +template<> +struct unwrap_impl { + template + static typename unwrapped_type::type& unwrap(const T& t) + { return t.get(); } +}; + +template<> +struct unwrap_impl { + template + static typename unwrapped_type::type& unwrap(const T& t) + { return const_cast(t); } +}; + +template +typename unwrapped_type::type& +unwrap(const T& t) +{ return unwrap_impl::value>::unwrap(t); } + +#endif // #if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) //------------------------// + +} } } // End namespaces detail, iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_DETAIL_WRAP_UNWRAP_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/device/array.hpp b/win32/include/boost/iostreams/device/array.hpp new file mode 100755 index 000000000..55363f01a --- /dev/null +++ b/win32/include/boost/iostreams/device/array.hpp @@ -0,0 +1,144 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_ARRAY_HPP_INCLUDED +#define BOOST_IOSTREAMS_ARRAY_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // BOOST_MSVC, make sure size_t is in std. +#include +#include // std::size_t. +#include // pair. +#include +#include +#include +#include +#include + +namespace boost { namespace iostreams { + +namespace detail { + +template +class array_adapter { +public: + typedef Ch char_type; + typedef std::pair pair_type; + struct category + : public Mode, + public device_tag, + public direct_tag + { }; + array_adapter(char_type* begin, char_type* end); + array_adapter(char_type* begin, std::size_t length); + array_adapter(const char_type* begin, const char_type* end); + array_adapter(const char_type* begin, std::size_t length); +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + template + array_adapter(char_type (&ar)[N]) + : begin_(ar), end_(ar + N) + { } +#endif + pair_type input_sequence(); + pair_type output_sequence(); +private: + char_type* begin_; + char_type* end_; +}; + +} // End namespace detail. + +// Local macros, #undef'd below. +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +# define BOOST_IOSTREAMS_ARRAY_CTOR(name, ch) \ + template \ + BOOST_PP_CAT(basic_, name)(ch (&ar)[N]) \ + : base_type(ar) { } \ + /**/ +#else +# define BOOST_IOSTREAMS_ARRAY_CTOR(name, ch) +#endif +#define BOOST_IOSTREAMS_ARRAY(name, mode) \ + template \ + struct BOOST_PP_CAT(basic_, name) : detail::array_adapter { \ + private: \ + typedef detail::array_adapter base_type; \ + public: \ + typedef typename base_type::char_type char_type; \ + typedef typename base_type::category category; \ + BOOST_PP_CAT(basic_, name)(char_type* begin, char_type* end) \ + : base_type(begin, end) { } \ + BOOST_PP_CAT(basic_, name)(char_type* begin, std::size_t length) \ + : base_type(begin, length) { } \ + BOOST_PP_CAT(basic_, name)(const char_type* begin, const char_type* end) \ + : base_type(begin, end) { } \ + BOOST_PP_CAT(basic_, name)(const char_type* begin, std::size_t length) \ + : base_type(begin, length) { } \ + BOOST_IOSTREAMS_ARRAY_CTOR(name, Ch) \ + }; \ + typedef BOOST_PP_CAT(basic_, name) name; \ + typedef BOOST_PP_CAT(basic_, name) BOOST_PP_CAT(w, name); \ + /**/ +BOOST_IOSTREAMS_ARRAY(array_source, input_seekable) +BOOST_IOSTREAMS_ARRAY(array_sink, output_seekable) +BOOST_IOSTREAMS_ARRAY(array, seekable) +#undef BOOST_IOSTREAMS_ARRAY_CTOR +#undef BOOST_IOSTREAMS_ARRAY + + +//------------------Implementation of array_adapter---------------------------// + +namespace detail { + +template +array_adapter::array_adapter + (char_type* begin, char_type* end) + : begin_(begin), end_(end) + { } + +template +array_adapter::array_adapter + (char_type* begin, std::size_t length) + : begin_(begin), end_(begin + length) + { } + +template +array_adapter::array_adapter + (const char_type* begin, const char_type* end) + : begin_(const_cast(begin)), // Treated as read-only. + end_(const_cast(end)) // Treated as read-only. +{ BOOST_STATIC_ASSERT((!is_convertible::value)); } + +template +array_adapter::array_adapter + (const char_type* begin, std::size_t length) + : begin_(const_cast(begin)), // Treated as read-only. + end_(const_cast(begin) + length) // Treated as read-only. +{ BOOST_STATIC_ASSERT((!is_convertible::value)); } + +template +typename array_adapter::pair_type +array_adapter::input_sequence() +{ BOOST_STATIC_ASSERT((is_convertible::value)); + return pair_type(begin_, end_); } + +template +typename array_adapter::pair_type +array_adapter::output_sequence() +{ BOOST_STATIC_ASSERT((is_convertible::value)); + return pair_type(begin_, end_); } + +} // End namespace detail. + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_ARRAY_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/device/back_inserter.hpp b/win32/include/boost/iostreams/device/back_inserter.hpp new file mode 100755 index 000000000..0d32c3410 --- /dev/null +++ b/win32/include/boost/iostreams/device/back_inserter.hpp @@ -0,0 +1,41 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_BACK_INSERTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_BACK_INSERTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // streamsize. +#include + +namespace boost { namespace iostreams { + +template +class back_insert_device { +public: + typedef typename Container::value_type char_type; + typedef sink_tag category; + back_insert_device(Container& cnt) : container(&cnt) { } + std::streamsize write(const char_type* s, std::streamsize n) + { + container->insert(container->end(), s, s + n); + return n; + } +protected: + Container* container; +}; + +template +back_insert_device back_inserter(Container& cnt) +{ return back_insert_device(cnt); } + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_BACK_INSERTER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/device/file.hpp b/win32/include/boost/iostreams/device/file.hpp new file mode 100755 index 000000000..d47dea480 --- /dev/null +++ b/win32/include/boost/iostreams/device/file.hpp @@ -0,0 +1,183 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// +// Contains wrappers for standard file buffers, together +// with convenience typedefs: +// - basic_file_source +// - basic_file_sink +// - basic_file +// + +#ifndef BOOST_IOSTREAMS_FILE_HPP_INCLUDED +#define BOOST_IOSTREAMS_FILE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#ifndef BOOST_IOSTREAMS_NO_LOCALE +# include +#endif +#include // pathnames, char_traits. +#include +#include // openmode, seekdir, int types. +#include +#include // seek. +#include + +// Must come last. +#include // MSVC. + +namespace boost { namespace iostreams { + +template +class basic_file { +public: + typedef Ch char_type; + struct category + : public seekable_device_tag, + public closable_tag, + public localizable_tag + { }; + basic_file( const std::string& path, + BOOST_IOS::openmode mode = + BOOST_IOS::in | BOOST_IOS::out, + BOOST_IOS::openmode base_mode = + BOOST_IOS::in | BOOST_IOS::out ); + std::streamsize read(char_type* s, std::streamsize n); + std::streamsize write(const char_type* s, std::streamsize n); + std::streampos seek( stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which = + BOOST_IOS::in | BOOST_IOS::out ); + void open( const std::string& path, + BOOST_IOS::openmode mode = + BOOST_IOS::in | BOOST_IOS::out, + BOOST_IOS::openmode base_mode = + BOOST_IOS::in | BOOST_IOS::out ); + bool is_open() const; + void close(); +#ifndef BOOST_IOSTREAMS_NO_LOCALE + void imbue(const std::locale& loc) { pimpl_->file_.pubimbue(loc); } +#endif +private: + struct impl { + impl(const std::string& path, BOOST_IOS::openmode mode) + { file_.open(path.c_str(), mode); } + ~impl() { if (file_.is_open()) file_.close(); } + BOOST_IOSTREAMS_BASIC_FILEBUF(Ch) file_; + }; + shared_ptr pimpl_; +}; + +typedef basic_file file; +typedef basic_file wfile; + +template +struct basic_file_source : private basic_file { + typedef Ch char_type; + struct category + : input_seekable, + device_tag, + closable_tag + { }; + using basic_file::read; + using basic_file::seek; + using basic_file::is_open; + using basic_file::close; + basic_file_source( const std::string& path, + BOOST_IOS::openmode mode = + BOOST_IOS::in ) + : basic_file(path, mode & ~BOOST_IOS::out, BOOST_IOS::in) + { } + void open( const std::string& path, + BOOST_IOS::openmode mode = BOOST_IOS::in ) + { + basic_file::open(path, mode & ~BOOST_IOS::out, BOOST_IOS::in); + } +}; + +typedef basic_file_source file_source; +typedef basic_file_source wfile_source; + +template +struct basic_file_sink : private basic_file { + typedef Ch char_type; + struct category + : output_seekable, + device_tag, + closable_tag + { }; + using basic_file::write; + using basic_file::seek; + using basic_file::is_open; + using basic_file::close; + basic_file_sink( const std::string& path, + BOOST_IOS::openmode mode = BOOST_IOS::out ) + : basic_file(path, mode & ~BOOST_IOS::in, BOOST_IOS::out) + { } + void open( const std::string& path, + BOOST_IOS::openmode mode = BOOST_IOS::out ) + { + basic_file::open(path, mode & ~BOOST_IOS::in, BOOST_IOS::out); + } +}; + +typedef basic_file_sink file_sink; +typedef basic_file_sink wfile_sink; + +//------------------Implementation of basic_file------------------------------// + +template +basic_file::basic_file + ( const std::string& path, BOOST_IOS::openmode mode, + BOOST_IOS::openmode base_mode ) +{ + open(path, mode, base_mode); +} + +template +inline std::streamsize basic_file::read + (char_type* s, std::streamsize n) +{ + std::streamsize result = pimpl_->file_.sgetn(s, n); + return result != 0 ? result : -1; +} + +template +inline std::streamsize basic_file::write + (const char_type* s, std::streamsize n) +{ return pimpl_->file_.sputn(s, n); } + +template +std::streampos basic_file::seek + ( stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode ) +{ return iostreams::seek(pimpl_->file_, off, way); } + +template +void basic_file::open + ( const std::string& path, BOOST_IOS::openmode mode, + BOOST_IOS::openmode base_mode ) +{ + pimpl_.reset(new impl(path, mode | base_mode)); +} + +template +bool basic_file::is_open() const { return pimpl_->file_.is_open(); } + +template +void basic_file::close() { pimpl_->file_.close(); } + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#include // MSVC + +#endif // #ifndef BOOST_IOSTREAMS_FILE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/device/file_descriptor.hpp b/win32/include/boost/iostreams/device/file_descriptor.hpp new file mode 100755 index 000000000..1020730b0 --- /dev/null +++ b/win32/include/boost/iostreams/device/file_descriptor.hpp @@ -0,0 +1,186 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Inspired by fdstream.hpp, (C) Copyright Nicolai M. Josuttis 2001, +// available at http://www.josuttis.com/cppcode/fdstream.html. + +#ifndef BOOST_IOSTREAMS_FILE_DESCRIPTOR_HPP_INCLUDED +#define BOOST_IOSTREAMS_FILE_DESCRIPTOR_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // file pathnames. +#include // intmax_t. +#include // tags. +#include +#include +#include +#include // openmode, seekdir, int types. +#include +#include + +// Must come last. +#include + +namespace boost { namespace iostreams { + +class BOOST_IOSTREAMS_DECL file_descriptor { +public: +#ifdef BOOST_IOSTREAMS_WINDOWS + typedef void* handle_type; // A.k.a HANDLE +#else + typedef int handle_type; +#endif + typedef char char_type; + struct category + : seekable_device_tag, + closable_tag + { }; + file_descriptor(); + explicit file_descriptor(handle_type fd, bool close_on_exit = false); +#ifdef BOOST_IOSTREAMS_WINDOWS + explicit file_descriptor(int fd, bool close_on_exit = false); +#endif + explicit file_descriptor( const std::string& path, + BOOST_IOS::openmode mode = + BOOST_IOS::in | BOOST_IOS::out, + BOOST_IOS::openmode base_mode = + BOOST_IOS::in | BOOST_IOS::out ); + explicit file_descriptor( const char* path, + BOOST_IOS::openmode mode = + BOOST_IOS::in | BOOST_IOS::out, + BOOST_IOS::openmode base_mode = + BOOST_IOS::in | BOOST_IOS::out ); + void open( const std::string& path, + BOOST_IOS::openmode = + BOOST_IOS::in | BOOST_IOS::out, + BOOST_IOS::openmode base_mode = + BOOST_IOS::in | BOOST_IOS::out ); + void open( const char* path, + BOOST_IOS::openmode = + BOOST_IOS::in | BOOST_IOS::out, + BOOST_IOS::openmode base_mode = + BOOST_IOS::in | BOOST_IOS::out ); + bool is_open() const { return pimpl_->flags_ != 0; } + std::streamsize read(char_type* s, std::streamsize n); + std::streamsize write(const char_type* s, std::streamsize n); + std::streampos seek(stream_offset off, BOOST_IOS::seekdir way); + void close(); + handle_type handle() const { return pimpl_->handle_; } +private: + struct impl { + impl() : + #ifdef BOOST_IOSTREAMS_WINDOWS + handle_(reinterpret_cast(-1)), + #else + handle_(-1), + #endif + flags_(0) + { } + impl(handle_type fd, bool close_on_exit) + : handle_(fd), flags_(0) + { if (close_on_exit) flags_ |= impl::close_on_exit; } + ~impl() + { if (flags_ & close_on_exit) close_impl(*this); } + enum flags { + close_on_exit = 1, + append = 4 + }; + handle_type handle_; + int flags_; + }; + friend struct impl; + + static void close_impl(impl&); +#ifdef BOOST_IOSTREAMS_WINDOWS + static handle_type int_to_handle(int fd); +#endif + + shared_ptr pimpl_; +}; + +struct file_descriptor_source : private file_descriptor { +#ifdef BOOST_IOSTREAMS_WINDOWS + typedef void* handle_type; // A.k.a HANDLE +#else + typedef int handle_type; +#endif + typedef char char_type; + struct category + : input_seekable, + device_tag, + closable_tag + { }; + using file_descriptor::read; + using file_descriptor::seek; + using file_descriptor::open; + using file_descriptor::is_open; + using file_descriptor::close; + using file_descriptor::handle; + file_descriptor_source() { } + explicit file_descriptor_source(handle_type fd, bool close_on_exit = false) + : file_descriptor(fd, close_on_exit) + { } +#ifdef BOOST_IOSTREAMS_WINDOWS + explicit file_descriptor_source(int fd, bool close_on_exit = false) + : file_descriptor(fd, close_on_exit) + { } +#endif + explicit file_descriptor_source( const std::string& path, + BOOST_IOS::openmode m = BOOST_IOS::in ) + : file_descriptor(path, m & ~BOOST_IOS::out, BOOST_IOS::in) + { } + explicit file_descriptor_source( const char* path, + BOOST_IOS::openmode m = BOOST_IOS::in ) + : file_descriptor(path, m & ~BOOST_IOS::out, BOOST_IOS::in) + { } +}; + +struct file_descriptor_sink : private file_descriptor { +#ifdef BOOST_IOSTREAMS_WINDOWS + typedef void* handle_type; // A.k.a HANDLE +#else + typedef int handle_type; +#endif + typedef char char_type; + struct category + : output_seekable, + device_tag, + closable_tag + { }; + using file_descriptor::write; + using file_descriptor::seek; + using file_descriptor::open; + using file_descriptor::is_open; + using file_descriptor::close; + using file_descriptor::handle; + file_descriptor_sink() { } + explicit file_descriptor_sink(handle_type fd, bool close_on_exit = false) + : file_descriptor(fd, close_on_exit) + { } +#ifdef BOOST_IOSTREAMS_WINDOWS + explicit file_descriptor_sink(int fd, bool close_on_exit = false) + : file_descriptor(fd, close_on_exit) + { } +#endif + explicit file_descriptor_sink( const std::string& path, + BOOST_IOS::openmode m = BOOST_IOS::out ) + : file_descriptor(path, m & ~BOOST_IOS::in, BOOST_IOS::out) + { } + explicit file_descriptor_sink( const char* path, + BOOST_IOS::openmode m = BOOST_IOS::out ) + : file_descriptor(path, m & ~BOOST_IOS::in, BOOST_IOS::out) + { } +}; + +} } // End namespaces iostreams, boost. + +#include // pops abi_suffix.hpp pragmas + +#endif // #ifndef BOOST_IOSTREAMS_FILE_DESCRIPTOR_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/device/mapped_file.hpp b/win32/include/boost/iostreams/device/mapped_file.hpp new file mode 100755 index 000000000..11150e21c --- /dev/null +++ b/win32/include/boost/iostreams/device/mapped_file.hpp @@ -0,0 +1,285 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// (C) Copyright Craig Henderson 2002. 'boost/memmap.hpp' from sandbox +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// +// This header and its accompanying source file libs/iostreams/memmap.cpp are +// an adaptation of Craig Henderson's memmory mapped file library. The +// interface has been revised significantly, but the underlying OS-specific +// code is essentially the same, with some code from Boost.Filesystem +// mixed in. (See notations in source.) +// +// The following changes have been made: +// +// 1. OS-specific code put in a .cpp file. +// 2. Name of main class changed to mapped_file. +// 3. mapped_file given an interface similar to std::fstream (open(), +// is_open(), close()) and std::string (data(), size(), begin(), end()). +// 4. An additional class readonly_mapped_file has been provided as a +// convenience. +// 5. [Obsolete: Error states are reported using filesystem::error_code.] +// 6. Read-only or read-write states are specified using ios_base::openmode. +// 7. Access to the underlying file handles and to security parameters +// has been removed. +// + +#ifndef BOOST_IOSTREAMS_MAPPED_FILE_HPP_INCLUDED +#define BOOST_IOSTREAMS_MAPPED_FILE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // make sure size_t is in std. +#include // size_t. +#include // pathnames. +#include // pair. +#include // BOOST_MSVC. +#include +#include +#include +#include +#include +#include // openmode. +#include +#include +#include + +// Must come last. +#include +#include + +namespace boost { namespace iostreams { + +namespace detail { + +struct mapped_file_impl; + +} // End namespace detail. + +struct mapped_file_params { + explicit mapped_file_params() + #if BOOST_WORKAROUND(BOOST_MSVC, < 1400) && defined(BOOST_RWSTD_VER) || \ + defined(__BORLANDC__) && defined(_CPPLIB_VER) + /**/ + : mode(std::ios_base::openmode(0)), + #else + : mode(), + #endif + offset(0), length(static_cast(-1)), + new_file_size(0), hint(0) + { } + explicit mapped_file_params(const std::string& path) + : path(path), + #if BOOST_WORKAROUND(BOOST_MSVC, < 1400) && defined(BOOST_RWSTD_VER) || \ + defined(__BORLANDC__) && defined(_CPPLIB_VER) + mode(std::ios_base::openmode(0)), + #else + mode(), + #endif + offset(0), length(static_cast(-1)), + new_file_size(0), hint(0) + { } + std::string path; + BOOST_IOS::openmode mode; + stream_offset offset; + std::size_t length; + stream_offset new_file_size; + const char* hint; +}; + +//------------------Definition of mapped_file_source--------------------------// + +class BOOST_IOSTREAMS_DECL mapped_file_source { +private: + struct safe_bool_helper { int x; }; // From Bronek Kozicki. + typedef int safe_bool_helper::* safe_bool; + friend struct operations; +public: + typedef char char_type; + struct category + : public source_tag, + public direct_tag, + public closable_tag + { }; + typedef std::size_t size_type; + typedef const char* iterator; + BOOST_STATIC_CONSTANT(size_type, max_length = static_cast(-1)); + + mapped_file_source() { } + explicit mapped_file_source(mapped_file_params); + explicit mapped_file_source( const std::string& path, + size_type length = max_length, + boost::intmax_t offset = 0 ); + + //--------------Stream interface------------------------------------------// + + void open(mapped_file_params params); + void open( const std::string& path, + size_type length = max_length, + boost::intmax_t offset = 0 ); + bool is_open() const; + void close(); + + operator safe_bool() const; + bool operator!() const; + BOOST_IOS::openmode mode() const; + + //--------------Container interface---------------------------------------// + + size_type size() const; + const char* data() const; + iterator begin() const; + iterator end() const; + + //--------------Query admissible offsets----------------------------------// + + // Returns the allocation granularity for virtual memory. Values passed + // as offsets must be multiples of this value. + static int alignment(); +private: + friend class mapped_file; + typedef detail::mapped_file_impl impl_type; + void open_impl(mapped_file_params); + + boost::shared_ptr pimpl_; +}; + +//------------------Definition of mapped_file---------------------------------// + +class BOOST_IOSTREAMS_DECL mapped_file { +private: + typedef mapped_file_source delegate_type; + delegate_type delegate_; + friend struct operations; +public: + typedef char char_type; + struct category + : public seekable_device_tag, + public direct_tag, + public closable_tag + { }; + typedef mapped_file_source::size_type size_type; + typedef char* iterator; + typedef const char* const_iterator; + BOOST_STATIC_CONSTANT(size_type, max_length = delegate_type::max_length); + mapped_file() { } + explicit mapped_file(mapped_file_params p); + explicit mapped_file( const std::string& path, + BOOST_IOS::openmode mode = + BOOST_IOS::in | BOOST_IOS::out, + size_type length = max_length, + stream_offset offset = 0 ); + + //--------------Conversion to readonly_mapped_file------------------------// + + operator mapped_file_source&() { return delegate_; } + operator const mapped_file_source&() const { return delegate_; } + + //--------------Stream interface------------------------------------------// + + void open(mapped_file_params p); + void open( const std::string& path, + BOOST_IOS::openmode mode = + BOOST_IOS::in | BOOST_IOS::out, + size_type length = max_length, + stream_offset offset = 0 ); + bool is_open() const { return delegate_.is_open(); } + void close() { delegate_.close(); } + operator delegate_type::safe_bool() const { return delegate_; } + bool operator!() const { return !is_open(); } + BOOST_IOS::openmode mode() const { return delegate_.mode(); } + + //--------------Container interface---------------------------------------// + + size_type size() const { return delegate_.size(); } + char* data() const + { + return (mode() & BOOST_IOS::out) ? + const_cast(delegate_.data()) : + 0; + } + const char* const_data() const { return delegate_.data(); } + iterator begin() const { return data(); } + const_iterator const_begin() const { return data(); } + iterator end() const { return data() + size(); } + const_iterator const_end() const { return data() + size(); } + + //--------------Query admissible offsets----------------------------------// + + // Returns the allocation granularity for virtual memory. Values passed + // as offsets must be multiples of this value. + static int alignment() { return mapped_file_source::alignment(); } +}; + +struct BOOST_IOSTREAMS_DECL mapped_file_sink : private mapped_file { + friend struct operations; + typedef char char_type; + struct category + : public sink_tag, + public direct_tag, + public closable_tag + { }; + using mapped_file::close; + using mapped_file::size; + explicit mapped_file_sink(mapped_file_params p); + explicit mapped_file_sink( const std::string& path, + size_type length = max_length, + boost::intmax_t offset = 0 ); + void open(mapped_file_params p); + void open( const std::string& path, + size_type length = max_length, + boost::intmax_t offset = 0 ); +}; + +//------------------Specialization of direct_impl-----------------------------// + +template<> +struct operations + : detail::close_impl +{ + static std::pair + input_sequence(boost::iostreams::mapped_file_source& src) + { + return std::make_pair( const_cast(src.begin()), + const_cast(src.end()) ); + } +}; + +template<> +struct operations + : detail::close_impl +{ + static std::pair + output_sequence(boost::iostreams::mapped_file_sink& sink) + { + return std::make_pair(sink.begin(), sink.end()); + } +}; + +template<> +struct operations + : detail::close_impl +{ + static std::pair + input_sequence(boost::iostreams::mapped_file& file) + { + return std::make_pair(file.begin(), file.end()); + } + static std::pair + output_sequence(boost::iostreams::mapped_file& file) + { + return std::make_pair(file.begin(), file.end()); + } +}; + +} } // End namespaces iostreams, boost. + +#include // pops abi_suffix.hpp pragmas +#include // MSVC. + +#endif // #ifndef BOOST_IOSTREAMS_MAPPED_FILE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/device/null.hpp b/win32/include/boost/iostreams/device/null.hpp new file mode 100755 index 000000000..fcae14aa0 --- /dev/null +++ b/win32/include/boost/iostreams/device/null.hpp @@ -0,0 +1,66 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Inspired by Daryle Walker's nullbuf from his More I/O submission. + +#ifndef BOOST_IOSTREAMS_NULL_HPP_INCLUDED +#define BOOST_IOSTREAMS_NULL_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include // openmode, streamsize. +#include + +namespace boost { namespace iostreams { + +template +class basic_null_device { +public: + typedef Ch char_type; + struct category + : public Mode, + public device_tag, + public closable_tag + { }; + std::streamsize read(Ch*, std::streamsize) { return 0; } + std::streamsize write(const Ch*, std::streamsize n) { return n; } + std::streampos seek( stream_offset, BOOST_IOS::seekdir, + BOOST_IOS::openmode = + BOOST_IOS::in | BOOST_IOS::out ) + { return -1; } + void close() { } + void close(BOOST_IOS::openmode) { } +}; + +template +struct basic_null_source : private basic_null_device { + typedef Ch char_type; + typedef source_tag category; + using basic_null_device::read; + using basic_null_device::close; +}; + +typedef basic_null_source null_source; +typedef basic_null_source wnull_source; + +template +struct basic_null_sink : private basic_null_device { + typedef Ch char_type; + typedef sink_tag category; + using basic_null_device::write; + using basic_null_device::close; +}; + +typedef basic_null_sink null_sink; +typedef basic_null_sink wnull_sink; + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_NULL_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/filter/aggregate.hpp b/win32/include/boost/iostreams/filter/aggregate.hpp new file mode 100755 index 000000000..6ff9c5654 --- /dev/null +++ b/win32/include/boost/iostreams/filter/aggregate.hpp @@ -0,0 +1,168 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_AGGREGATE_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_AGGREGATE_FILTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // copy, min. +#include +#include // back_inserter +#include +#include // default_device_buffer_size +#include +#include +#include // openmode, streamsize. +#include +#include // check_eof +#include +#include +#include + +// Must come last. +#include // MSVC. + +namespace boost { namespace iostreams { + +// +// Template name: aggregate_filter. +// Template paramters: +// Ch - The character type. +// Alloc - The allocator type. +// Description: Utility for defining DualUseFilters which filter an +// entire stream at once. To use, override the protected virtual +// member do_filter. +// Note: This filter should not be copied while it is in use. +// +template > +class aggregate_filter { +public: + typedef Ch char_type; + struct category + : dual_use, + filter_tag, + multichar_tag, + closable_tag + { }; + aggregate_filter() : ptr_(0), state_(0) { } + virtual ~aggregate_filter() { } + + template + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { + using namespace std; + assert(!(state_ & f_write)); + state_ |= f_read; + if (!(state_ & f_eof)) + do_read(src); + std::streamsize amt = + (std::min)(n, static_cast(data_.size() - ptr_)); + if (amt) { + BOOST_IOSTREAMS_CHAR_TRAITS(char_type)::copy(s, &data_[ptr_], amt); + ptr_ += amt; + } + return detail::check_eof(amt); + } + + template + std::streamsize write(Sink&, const char_type* s, std::streamsize n) + { + assert(!(state_ & f_read)); + state_ |= f_write; + data_.insert(data_.end(), s, s + n); + return n; + } + + template + void close(Sink& sink, BOOST_IOS::openmode which) + { + if ((state_ & f_read) != 0 && which == BOOST_IOS::in) + close_impl(); + if ((state_ & f_write) != 0 && which == BOOST_IOS::out) { + try { + vector_type filtered; + do_filter(data_, filtered); + do_write( + sink, &filtered[0], + static_cast(filtered.size()) + ); + } catch (...) { + close_impl(); + throw; + } + close_impl(); + } + } + +protected: + typedef std::vector vector_type; + typedef typename vector_type::size_type size_type; +private: + virtual void do_filter(const vector_type& src, vector_type& dest) = 0; + virtual void do_close() { } + + template + void do_read(Source& src) + { + using std::streamsize; + vector_type data; + while (true) { + const std::streamsize size = default_device_buffer_size; + Ch buf[size]; + std::streamsize amt; + if ((amt = boost::iostreams::read(src, buf, size)) == -1) + break; + data.insert(data.end(), buf, buf + amt); + } + do_filter(data, data_); + state_ |= f_eof; + } + + template + void do_write(Sink& sink, const char* s, std::streamsize n) + { + typedef typename iostreams::category_of::type category; + typedef is_convertible can_write; + do_write(sink, s, n, can_write()); + } + + template + void do_write(Sink& sink, const char* s, std::streamsize n, mpl::true_) + { iostreams::write(sink, s, n); } + + template + void do_write(Sink&, const char*, std::streamsize, mpl::false_) { } + + void close_impl() + { + data_.clear(); + ptr_ = 0; + state_ = 0; + do_close(); + } + + enum flag_type { + f_read = 1, + f_write = f_read << 1, + f_eof = f_write << 1 + }; + + // Note: typically will not be copied while vector contains data. + vector_type data_; + size_type ptr_; + int state_; +}; +BOOST_IOSTREAMS_PIPABLE(aggregate_filter, 1) + +} } // End namespaces iostreams, boost. + +#include // MSVC. + +#endif // #ifndef BOOST_IOSTREAMS_AGGREGATE_FILTER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/filter/bzip2.hpp b/win32/include/boost/iostreams/filter/bzip2.hpp new file mode 100755 index 000000000..565475a56 --- /dev/null +++ b/win32/include/boost/iostreams/filter/bzip2.hpp @@ -0,0 +1,397 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Note: custom allocators are not supported on VC6, since that compiler +// had trouble finding the function zlib_base::do_init. + +#ifndef BOOST_IOSTREAMS_BZIP2_HPP_INCLUDED +#define BOOST_IOSTREAMS_BZIP2_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include // allocator. +#include // bad_alloc. +#include // MSVC, STATIC_CONSTANT, DEDUCED_TYPENAME, DINKUM. +#include +#include // buffer size. +#include +#include +#include +#include +#include // failure, streamsize. +#include +#include +#include + +// Must come last. +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4251 4231 4660) +#endif +#include + +// Temporary fix. +#undef small + +namespace boost { namespace iostreams { + +namespace bzip2 { + + // Typedefs. + +typedef void* (*alloc_func)(void*, int, int); +typedef void (*free_func)(void*, void*); + + // Status codes + +BOOST_IOSTREAMS_DECL extern const int ok; +BOOST_IOSTREAMS_DECL extern const int run_ok; +BOOST_IOSTREAMS_DECL extern const int flush_ok; +BOOST_IOSTREAMS_DECL extern const int finish_ok; +BOOST_IOSTREAMS_DECL extern const int stream_end; +BOOST_IOSTREAMS_DECL extern const int sequence_error; +BOOST_IOSTREAMS_DECL extern const int param_error; +BOOST_IOSTREAMS_DECL extern const int mem_error; +BOOST_IOSTREAMS_DECL extern const int data_error; +BOOST_IOSTREAMS_DECL extern const int data_error_magic; +BOOST_IOSTREAMS_DECL extern const int io_error; +BOOST_IOSTREAMS_DECL extern const int unexpected_eof; +BOOST_IOSTREAMS_DECL extern const int outbuff_full; +BOOST_IOSTREAMS_DECL extern const int config_error; + + // Action codes + +BOOST_IOSTREAMS_DECL extern const int finish; +BOOST_IOSTREAMS_DECL extern const int run; + + // Default values + +const int default_block_size = 9; +const int default_work_factor = 30; +const bool default_small = false; + +} // End namespace bzip2. + +// +// Class name: bzip2_params. +// Description: Encapsulates the parameters passed to deflateInit2 +// to customize compression. +// +struct bzip2_params { + + // Non-explicit constructor for compression. + bzip2_params( int block_size = bzip2::default_block_size, + int work_factor = bzip2::default_work_factor ) + : block_size(block_size), work_factor(work_factor) + { } + + // Constructor for decompression. + bzip2_params(bool small) + : small(small), work_factor(0) + { } + + union { + int block_size; // For compression. + bool small; // For decompression. + }; + int work_factor; +}; + +// +// Class name: bzip2_error. +// Description: Subclass of std::ios_base::failure thrown to indicate +// bzip2 errors other than out-of-memory conditions. +// +class BOOST_IOSTREAMS_DECL bzip2_error : public BOOST_IOSTREAMS_FAILURE { +public: + explicit bzip2_error(int error); + int error() const { return error_; } + static void check(int error); +private: + int error_; +}; + +namespace detail { + +template +struct bzip2_allocator_traits { +#ifndef BOOST_NO_STD_ALLOCATOR + typedef typename Alloc::template rebind::other type; +#else + typedef std::allocator type; +#endif +}; + +template< typename Alloc, + typename Base = // VC6 workaround (C2516) + BOOST_DEDUCED_TYPENAME bzip2_allocator_traits::type > +struct bzip2_allocator : private Base { +private: + typedef typename Base::size_type size_type; +public: + BOOST_STATIC_CONSTANT(bool, custom = + (!is_same, Base>::value)); + typedef typename bzip2_allocator_traits::type allocator_type; + static void* allocate(void* self, int items, int size); + static void deallocate(void* self, void* address); +}; + +class BOOST_IOSTREAMS_DECL bzip2_base { +public: + typedef char char_type; +protected: + bzip2_base(const bzip2_params& params); + ~bzip2_base(); + bzip2_params& params() { return params_; } + bool& ready() { return ready_; } + template + void init( bool compress, + bzip2_allocator& alloc ) + { + bool custom = bzip2_allocator::custom; + do_init( compress, + #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + custom ? bzip2_allocator::allocate : 0, + custom ? bzip2_allocator::deallocate : 0, + #endif + custom ? &alloc : 0 ); + } + void before( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end ); + void after(const char*& src_begin, char*& dest_begin); + int compress(int action); + int decompress(); + void end(bool compress); +private: + void do_init( bool compress, + #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + bzip2::alloc_func, + bzip2::free_func, + #endif + void* derived ); + bzip2_params params_; + void* stream_; // Actual type: bz_stream*. + bool ready_; +}; + +// +// Template name: bzip2_compressor_impl +// Description: Model of SymmetricFilter implementing compression by +// delegating to the libbzip2 function BZ_bzCompress. +// +template > +class bzip2_compressor_impl + : public bzip2_base, + #if BOOST_WORKAROUND(__BORLANDC__, < 0x600) + public + #endif + bzip2_allocator +{ +public: + bzip2_compressor_impl(const bzip2_params&); + bool filter( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end, bool flush ); + void close(); +private: + void init(); +}; + +// +// Template name: bzip2_compressor +// Description: Model of SymmetricFilter implementing decompression by +// delegating to the libbzip2 function BZ_bzDecompress. +// +template > +class bzip2_decompressor_impl + : public bzip2_base, + #if BOOST_WORKAROUND(__BORLANDC__, < 0x600) + public + #endif + bzip2_allocator +{ +public: + bzip2_decompressor_impl(bool small = bzip2::default_small); + bool filter( const char*& begin_in, const char* end_in, + char*& begin_out, char* end_out, bool flush ); + void close(); +private: + void init(); + bool eof_; // Guard to make sure filter() isn't called after it returns false. +}; + +} // End namespace detail. + +// +// Template name: bzip2_compressor +// Description: Model of InputFilter and OutputFilter implementing +// compression using libbzip2. +// +template > +struct basic_bzip2_compressor + : symmetric_filter, Alloc> +{ +private: + typedef detail::bzip2_compressor_impl impl_type; + typedef symmetric_filter base_type; +public: + typedef typename base_type::char_type char_type; + typedef typename base_type::category category; + basic_bzip2_compressor( const bzip2_params& = bzip2::default_block_size, + int buffer_size = default_device_buffer_size ); +}; +BOOST_IOSTREAMS_PIPABLE(basic_bzip2_compressor, 1) + +typedef basic_bzip2_compressor<> bzip2_compressor; + +// +// Template name: bzip2_decompressor +// Description: Model of InputFilter and OutputFilter implementing +// decompression using libbzip2. +// +template > +struct basic_bzip2_decompressor + : symmetric_filter, Alloc> +{ +private: + typedef detail::bzip2_decompressor_impl impl_type; + typedef symmetric_filter base_type; +public: + typedef typename base_type::char_type char_type; + typedef typename base_type::category category; + basic_bzip2_decompressor( bool small = bzip2::default_small, + int buffer_size = default_device_buffer_size ); +}; +BOOST_IOSTREAMS_PIPABLE(basic_bzip2_decompressor, 1) + +typedef basic_bzip2_decompressor<> bzip2_decompressor; + +//----------------------------------------------------------------------------// + +//------------------Implementation of bzip2_allocator-------------------------// + +namespace detail { + +template +void* bzip2_allocator::allocate(void* self, int items, int size) +{ + size_type len = items * size; + char* ptr = + static_cast(self)->allocate + (len + sizeof(size_type) + #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) + , (char*)0 + #endif + ); + *reinterpret_cast(ptr) = len; + return ptr + sizeof(size_type); +} + +template +void bzip2_allocator::deallocate(void* self, void* address) +{ + char* ptr = reinterpret_cast(address) - sizeof(size_type); + size_type len = *reinterpret_cast(ptr) + sizeof(size_type); + static_cast(self)->deallocate(ptr, len); +} + +//------------------Implementation of bzip2_compressor_impl-------------------// + +template +bzip2_compressor_impl::bzip2_compressor_impl(const bzip2_params& p) + : bzip2_base(p) { } + +template +bool bzip2_compressor_impl::filter + ( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end, bool flush ) +{ + if (!ready()) init(); + before(src_begin, src_end, dest_begin, dest_end); + int result = compress(flush ? bzip2::finish : bzip2::run); + after(src_begin, dest_begin); + bzip2_error::check(result); + return result != bzip2::stream_end; +} + +template +void bzip2_compressor_impl::close() +{ + end(true); +} + +template +inline void bzip2_compressor_impl::init() +{ bzip2_base::init(true, static_cast&>(*this)); } + +//------------------Implementation of bzip2_decompressor_impl-----------------// + +template +bzip2_decompressor_impl::bzip2_decompressor_impl(bool small) + : bzip2_base(bzip2_params(small)), eof_(false) { } + +template +bool bzip2_decompressor_impl::filter + ( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end, bool /* flush */ ) +{ + if (!ready()) + init(); + if (eof_) + return false; + before(src_begin, src_end, dest_begin, dest_end); + int result = decompress(); + after(src_begin, dest_begin); + bzip2_error::check(result); + return !(eof_ = result == bzip2::stream_end); +} + +template +void bzip2_decompressor_impl::close() +{ + try { + end(false); + } catch (...) { + eof_ = false; + throw; + } + eof_ = false; +} + +template +inline void bzip2_decompressor_impl::init() +{ bzip2_base::init(false, static_cast&>(*this)); } +} // End namespace detail. + +//------------------Implementation of bzip2_decompressor----------------------// + +template +basic_bzip2_compressor::basic_bzip2_compressor + (const bzip2_params& p, int buffer_size) + : base_type(buffer_size, p) + { } + +//------------------Implementation of bzip2_decompressor----------------------// + +template +basic_bzip2_decompressor::basic_bzip2_decompressor + (bool small, int buffer_size) + : base_type(buffer_size, small) + { } + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#include // Pops abi_suffix.hpp pragmas. +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_IOSTREAMS_BZIP2_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/filter/counter.hpp b/win32/include/boost/iostreams/filter/counter.hpp new file mode 100755 index 000000000..b8365b2a4 --- /dev/null +++ b/win32/include/boost/iostreams/filter/counter.hpp @@ -0,0 +1,82 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_COUNTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_COUNTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // count. +#include +#include +#include +#include + +// Must come last. +#include // VC7.1 C4244. + +namespace boost { namespace iostreams { + +// +// Template name: basic_counter. +// Template paramters: +// Ch - The character type. +// Description: Filter which counts lines and characters. +// +template +class basic_counter { +public: + typedef Ch char_type; + struct category + : dual_use, + filter_tag, + multichar_tag, + optimally_buffered_tag + { }; + explicit basic_counter(int first_line = 0, int first_char = 0) + : lines_(first_line), chars_(first_char) + { } + int lines() const { return lines_; } + int characters() const { return chars_; } + std::streamsize optimal_buffer_size() const { return 0; } + + template + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { + std::streamsize result = iostreams::read(src, s, n); + if (result == -1) + return -1; + lines_ += std::count(s, s + result, char_traits::newline()); + chars_ += result; + return result; + } + + template + std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) + { + std::streamsize result = iostreams::write(snk, s, n); + lines_ += std::count(s, s + result, char_traits::newline()); + chars_ += result; + return result; + } +private: + int lines_; + int chars_; +}; +BOOST_IOSTREAMS_PIPABLE(basic_counter, 1) + + +typedef basic_counter counter; +typedef basic_counter wcounter; + +} } // End namespaces iostreams, boost. + +#include + +#endif // #ifndef BOOST_IOSTREAMS_COUNTER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/filter/gzip.hpp b/win32/include/boost/iostreams/filter/gzip.hpp new file mode 100755 index 000000000..14d3667cb --- /dev/null +++ b/win32/include/boost/iostreams/filter/gzip.hpp @@ -0,0 +1,604 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains the definitions of the class templates gzip_compressor and +// gzip_decompressor for reading and writing files in the gzip file format +// (RFC 1952). Based in part on work of Jonathan de Halleux; see [...] + +#ifndef BOOST_IOSTREAMS_GZIP_HPP_INCLUDED +#define BOOST_IOSTREAMS_GZIP_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // STATIC_CONSTANT, STDC_NAMESPACE, + // DINKUMWARE_STDLIB, __STL_CONFIG_H. +#include // min. +#include // EOF. +#include // size_t. +#include // std::time_t. +#include // allocator. +#include // Put size_t in std. +#include +#include // uint8_t, uint32_t. +#include // buffer size. +#include +#include +#include +#include // failure. +#include +#include +#include +#include + +// Must come last. +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable: 4309) // Truncation of constant value. +#endif + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::time_t; } +#endif + +namespace boost { namespace iostreams { + +namespace gzip { + +using namespace boost::iostreams::zlib; + + // Error codes used by gzip_error. + +const int zlib_error = 1; +const int bad_crc = 2; // Recorded crc doesn't match data. +const int bad_length = 3; // Recorded length doesn't match data. +const int bad_header = 4; // Malformed header. +const int bad_footer = 5; // Malformed footer. + +namespace magic { + + // Magic numbers used by gzip header. + +const int id1 = 0x1f; +const int id2 = 0x8b; + +} // End namespace magic. + +namespace method { + + // Codes used for the 'CM' byte of the gzip header. + +const int deflate = 8; + +} // End namespace method. + +namespace flags { + + // Codes used for the 'FLG' byte of the gzip header. + +const int text = 1; +const int header_crc = 2; +const int extra = 4; +const int name = 8; +const int comment = 16; + +} // End namespace flags. + +namespace extra_flags { + + // Codes used for the 'XFL' byte of the gzip header. + +const int best_compression = 2; +const int best_speed = 4; + +} // End namespace extra_flags. + + // Codes used for the 'OS' byte of the gzip header. + +const int os_fat = 0; +const int os_amiga = 1; +const int os_vms = 2; +const int os_unix = 3; +const int os_vm_cms = 4; +const int os_atari = 5; +const int os_hpfs = 6; +const int os_macintosh = 7; +const int os_z_system = 8; +const int os_cp_m = 9; +const int os_tops_20 = 10; +const int os_ntfs = 11; +const int os_qdos = 12; +const int os_acorn = 13; +const int os_unknown = 255; + +} // End namespace gzip. + +// +// Class name: gzip_params. +// Description: Subclass of zlib_params with an additional field +// representing a file name. +// +struct gzip_params : zlib_params { + + // Non-explicit constructor. + gzip_params( int level = gzip::default_compression, + int method = gzip::deflated, + int window_bits = gzip::default_window_bits, + int mem_level = gzip::default_mem_level, + int strategy = gzip::default_strategy, + std::string file_name = "", + std::string comment = "", + std::time_t mtime = 0 ) + : zlib_params(level, method, window_bits, mem_level, strategy), + file_name(file_name), comment(comment), mtime(mtime) + { } + std::string file_name; + std::string comment; + std::time_t mtime; +}; + +// +// Class name: gzip_error. +// Description: Subclass of std::ios_base::failure thrown to indicate +// zlib errors other than out-of-memory conditions. +// +class gzip_error : public BOOST_IOSTREAMS_FAILURE { +public: + explicit gzip_error(int error) + : BOOST_IOSTREAMS_FAILURE("gzip error"), + error_(error), zlib_error_code_(zlib::okay) { } + explicit gzip_error(const zlib_error& e) + : BOOST_IOSTREAMS_FAILURE("gzip error"), + error_(gzip::zlib_error), zlib_error_code_(e.error()) + { } + int error() const { return error_; } + int zlib_error_code() const { return zlib_error_code_; } +private: + int error_; + int zlib_error_code_; +}; + +// +// Template name: gzip_compressor +// Description: Model of OutputFilter implementing compression in the +// gzip format. +// +template > +class basic_gzip_compressor : basic_zlib_compressor { +private: + typedef basic_zlib_compressor base_type; +public: + typedef char char_type; + struct category + : dual_use, + filter_tag, + multichar_tag, + closable_tag + { }; + basic_gzip_compressor( const gzip_params& = gzip::default_compression, + int buffer_size = default_device_buffer_size ); + + template + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { + std::streamsize result = 0; + + // Read header. + if (!(flags_ & f_header_done)) + result += read_string(s, n, header_); + + // Read body. + if (!(flags_ & f_body_done)) { + + // Read from basic_zlib_filter. + std::streamsize amt = base_type::read(src, s + result, n - result); + if (amt != -1) { + result += amt; + if (amt < n - result) { // Double-check for EOF. + amt = base_type::read(src, s + result, n - result); + if (amt != -1) + result += amt; + } + } + if (amt == -1) + prepare_footer(); + } + + // Read footer. + if ((flags_ & f_body_done) != 0 && result < n) + result += read_string(s + result, n - result, footer_); + + return result != 0 ? result : -1; + } + + template + std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) + { + if (!(flags_ & f_header_done)) { + std::streamsize amt = + static_cast(header_.size() - offset_); + offset_ += boost::iostreams::write(snk, header_.data() + offset_, amt); + if (offset_ == header_.size()) + flags_ |= f_header_done; + else + return 0; + } + return base_type::write(snk, s, n); + } + + template + void close(Sink& snk, BOOST_IOS::openmode m) + { + if (m == BOOST_IOS::out) { + try { + + // Close zlib compressor. + base_type::close(snk, BOOST_IOS::out); + + if (flags_ & f_header_done) { + + // Write final fields of gzip file format. + write_long(this->crc(), snk); + write_long(this->total_in(), snk); + } + + } catch (...) { + close_impl(); + throw; + } + close_impl(); + } else { + close_impl(); + } + } +private: + static gzip_params normalize_params(gzip_params p); + void prepare_footer(); + std::streamsize read_string(char* s, std::streamsize n, std::string& str); + + template + static void write_long(long n, Sink& next) + { + boost::iostreams::put(next, static_cast(0xFF & n)); + boost::iostreams::put(next, static_cast(0xFF & (n >> 8))); + boost::iostreams::put(next, static_cast(0xFF & (n >> 16))); + boost::iostreams::put(next, static_cast(0xFF & (n >> 24))); + } + + void close_impl() + { + #if BOOST_WORKAROUND(__GNUC__, == 2) && defined(__STL_CONFIG_H) || \ + BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) \ + /**/ + footer_.erase(0, std::string::npos); + #else + footer_.clear(); + #endif + offset_ = 0; + flags_ = 0; + } + + enum flag_type { + f_header_done = 1, + f_body_done = f_header_done << 1, + f_footer_done = f_body_done << 1 + }; + std::string header_; + std::string footer_; + std::size_t offset_; + int flags_; +}; +BOOST_IOSTREAMS_PIPABLE(basic_gzip_compressor, 1) + +typedef basic_gzip_compressor<> gzip_compressor; + +// +// Template name: basic_gzip_decompressor +// Description: Model of InputFilter implementing compression in the +// gzip format. +// +template > +class basic_gzip_decompressor : basic_zlib_decompressor { +public: + typedef char char_type; + struct category + : multichar_input_filter_tag, + closable_tag + { }; + basic_gzip_decompressor( int window_bits = gzip::default_window_bits, + int buffer_size = default_device_buffer_size ); + + template + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { + if ((flags_ & f_header_read) == 0) { + non_blocking_adapter nb(src); + read_header(nb); + flags_ |= f_header_read; + } + + if ((flags_ & f_footer_read) != 0) + return -1; + + try { + std::streamsize result = 0; + std::streamsize amt; + if ((amt = base_type::read(src, s, n)) != -1) { + result += amt; + if (amt < n) { // Double check for EOF. + amt = base_type::read(src, s + result, n - result); + if (amt != -1) + result += amt; + } + } + if (amt == -1) { + non_blocking_adapter nb(src); + read_footer(nb); + flags_ |= f_footer_read; + } + return result; + } catch (const zlib_error& e) { + throw gzip_error(e); + } + } + + template + void close(Source& src) + { + try { + base_type::close(src, BOOST_IOS::in); + } catch (const zlib_error& e) { + flags_ = 0; + throw gzip_error(e); + } + flags_ = 0; + } + + std::string file_name() const { return file_name_; } + std::string comment() const { return comment_; } + bool text() const { return (flags_ & gzip::flags::text) != 0; } + int os() const { return os_; } + std::time_t mtime() const { return mtime_; } +private: + typedef basic_zlib_decompressor base_type; + typedef BOOST_IOSTREAMS_CHAR_TRAITS(char) traits_type; + static bool is_eof(int c) { return traits_type::eq_int_type(c, EOF); } + static gzip_params make_params(int window_bits); + + template + static uint8_t read_uint8(Source& src, int error) + { + int c; + if ((c = boost::iostreams::get(src)) == EOF || c == WOULD_BLOCK) + throw gzip_error(error); + return static_cast(traits_type::to_char_type(c)); + } + + template + static uint32_t read_uint32(Source& src, int error) + { + uint8_t b1 = read_uint8(src, error); + uint8_t b2 = read_uint8(src, error); + uint8_t b3 = read_uint8(src, error); + uint8_t b4 = read_uint8(src, error); + return b1 + (b2 << 8) + (b3 << 16) + (b4 << 24); + } + + template + std::string read_string(Source& src) + { + std::string result; + while (true) { + int c; + if (is_eof(c = boost::iostreams::get(src))) + throw gzip_error(gzip::bad_header); + else if (c == 0) + return result; + else + result += static_cast(c); + } + } + + template + void read_header(Source& src) // Source is non-blocking. + { + // Reset saved values. + #if BOOST_WORKAROUND(__GNUC__, == 2) && defined(__STL_CONFIG_H) || \ + BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) \ + /**/ + file_name_.erase(0, std::string::npos); + comment_.erase(0, std::string::npos); + #else + file_name_.clear(); + comment_.clear(); + #endif + os_ = gzip::os_unknown; + mtime_ = 0; + + int flags; + + // Read header, without checking header crc. + if ( boost::iostreams::get(src) != gzip::magic::id1 || // ID1. + boost::iostreams::get(src) != gzip::magic::id2 || // ID2. + is_eof(boost::iostreams::get(src)) || // CM. + is_eof(flags = boost::iostreams::get(src)) ) // FLG. + { + throw gzip_error(gzip::bad_header); + } + mtime_ = read_uint32(src, gzip::bad_header); // MTIME. + read_uint8(src, gzip::bad_header); // XFL. + os_ = read_uint8(src, gzip::bad_header); // OS. + if (flags & boost::iostreams::gzip::flags::text) + flags_ |= f_text; + + // Skip extra field. (From J. Halleaux; see note at top.) + if (flags & gzip::flags::extra) { + int length = + static_cast( + read_uint8(src, gzip::bad_header) + + (read_uint8(src, gzip::bad_header) << 8) + ); + // length is garbage if EOF but the loop below will quit anyway. + do { } + while (length-- != 0 && !is_eof(boost::iostreams::get(src))); + } + + if (flags & gzip::flags::name) // Read file name. + file_name_ = read_string(src); + if (flags & gzip::flags::comment) // Read comment. + comment_ = read_string(src); + if (flags & gzip::flags::header_crc) { // Skip header crc. + read_uint8(src, gzip::bad_header); + read_uint8(src, gzip::bad_header); + } + } + + template + void read_footer(Source& src) + { + typename base_type::string_type footer = + this->unconsumed_input(); + int c; + while (!is_eof(c = boost::iostreams::get(src))) + footer += c; + detail::range_adapter + rng(footer.begin(), footer.end()); + if (read_uint32(rng, gzip::bad_footer) != this->crc()) + throw gzip_error(gzip::bad_crc); + if (static_cast(read_uint32(rng, gzip::bad_footer)) != this->total_out()) + throw gzip_error(gzip::bad_length); + } + enum flag_type { + f_header_read = 1, + f_footer_read = f_header_read << 1, + f_text = f_footer_read << 1 + }; + std::string file_name_; + std::string comment_; + int os_; + std::time_t mtime_; + int flags_; +}; +BOOST_IOSTREAMS_PIPABLE(basic_gzip_decompressor, 1) + +typedef basic_gzip_decompressor<> gzip_decompressor; + +//------------------Implementation of gzip_compressor-------------------------// + +template +basic_gzip_compressor::basic_gzip_compressor + (const gzip_params& p, int buffer_size) + : base_type(normalize_params(p), buffer_size), + offset_(0), flags_(0) +{ + // Calculate gzip header. + bool has_name = !p.file_name.empty(); + bool has_comment = !p.comment.empty(); + + std::string::size_type length = + 10 + + (has_name ? p.file_name.size() + 1 : 0) + + (has_comment ? p.comment.size() + 1 : 0); + // + 2; // Header crc confuses gunzip. + int flags = + //gzip::flags::header_crc + + (has_name ? gzip::flags::name : 0) + + (has_comment ? gzip::flags::comment : 0); + int extra_flags = + ( p.level == zlib::best_compression ? + gzip::extra_flags::best_compression : + 0 ) + + ( p.level == zlib::best_speed ? + gzip::extra_flags::best_speed : + 0 ); + header_.reserve(length); + header_ += gzip::magic::id1; // ID1. + header_ += gzip::magic::id2; // ID2. + header_ += gzip::method::deflate; // CM. + header_ += static_cast(flags); // FLG. + header_ += static_cast(0xFF & p.mtime); // MTIME. + header_ += static_cast(0xFF & (p.mtime >> 8)); + header_ += static_cast(0xFF & (p.mtime >> 16)); + header_ += static_cast(0xFF & (p.mtime >> 24)); + header_ += static_cast(extra_flags); // XFL. + header_ += static_cast(gzip::os_unknown); // OS. + if (has_name) { + header_ += p.file_name; + header_ += '\0'; + } + if (has_comment) { + header_ += p.comment; + header_ += '\0'; + } +} + +template +gzip_params basic_gzip_compressor::normalize_params(gzip_params p) +{ + p.noheader = true; + p.calculate_crc = true; + return p; +} + +template +void basic_gzip_compressor::prepare_footer() +{ + boost::iostreams::back_insert_device out(footer_); + write_long(this->crc(), out); + write_long(this->total_in(), out); + flags_ |= f_body_done; + offset_ = 0; +} + +template +std::streamsize basic_gzip_compressor::read_string + (char* s, std::streamsize n, std::string& str) +{ + std::streamsize avail = + static_cast(str.size() - offset_); + std::streamsize amt = (std::min)(avail, n); + std::copy( str.data() + offset_, + str.data() + offset_ + amt, + s ); + offset_ += amt; + if ( !(flags_ & f_header_done) && + offset_ == static_cast(str.size()) ) + { + flags_ |= f_header_done; + } + return amt; +} + +//------------------Implementation of gzip_decompressor-----------------------// + +template +basic_gzip_decompressor::basic_gzip_decompressor + (int window_bits, int buffer_size) + : base_type(make_params(window_bits), buffer_size), + os_(gzip::os_unknown), mtime_(0), flags_(0) + { } + +template +gzip_params basic_gzip_decompressor::make_params(int window_bits) +{ + gzip_params p; + p.window_bits = window_bits; + p.noheader = true; + p.calculate_crc = true; + return p; +} + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_IOSTREAMS_GZIP_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/filter/line.hpp b/win32/include/boost/iostreams/filter/line.hpp new file mode 100755 index 000000000..295549400 --- /dev/null +++ b/win32/include/boost/iostreams/filter/line.hpp @@ -0,0 +1,220 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_LINE_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_LINE_FILTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // min. +#include +#include // allocator. +#include +#include // BOOST_STATIC_CONSTANT. +#include +#include // openmode, streamsize. +#include // check_eof +#include +#include + +// Must come last. +#include // VC7.1 C4244. + +namespace boost { namespace iostreams { + +// +// Template name: line_filter. +// Template paramters: +// Ch - The character type. +// Alloc - The allocator type. +// Description: Filter which processes data one line at a time. +// +template< typename Ch, + typename Alloc = + #if BOOST_WORKAROUND(__GNUC__, < 3) + typename std::basic_string::allocator_type + #else + std::allocator + #endif + > +class basic_line_filter { +private: + typedef typename std::basic_string::traits_type string_traits; +public: + typedef Ch char_type; + typedef char_traits traits_type; + typedef std::basic_string< + Ch, + string_traits, + Alloc + > string_type; + struct category + : dual_use, + filter_tag, + multichar_tag, + closable_tag + { }; +protected: + basic_line_filter() : pos_(string_type::npos), state_(0) { } +public: + virtual ~basic_line_filter() { } + + template + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { + using namespace std; + assert(!(state_ & f_write)); + state_ |= f_read; + + // Handle unfinished business. + std::streamsize result = 0; + if (!cur_line_.empty() && (result = read_line(s, n)) == n) + return n; + + typename traits_type::int_type status = traits_type::good(); + while (result < n && !traits_type::is_eof(status)) { + + // Call next_line() to retrieve a line of filtered test, and + // read_line() to copy it into buffer s. + if (traits_type::would_block(status = next_line(src))) + return result; + result += read_line(s + result, n - result); + } + + return detail::check_eof(result); + } + + template + std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) + { + using namespace std; + assert(!(state_ & f_read)); + state_ |= f_write; + + // Handle unfinished business. + if (pos_ != string_type::npos && !write_line(snk)) + return 0; + + const char_type *cur = s, *next; + while (true) { + + // Search for the next full line in [cur, s + n), filter it + // and write it to snk. + typename string_type::size_type rest = n - (cur - s); + if ((next = traits_type::find(cur, rest, traits_type::newline()))) { + cur_line_.append(cur, next - cur); + cur = next + 1; + if (!write_line(snk)) + return static_cast(cur - s); + } else { + cur_line_.append(cur, rest); + return n; + } + } + } + + template + void close(Sink& snk, BOOST_IOS::openmode which) + { + if ((state_ & f_read) && which == BOOST_IOS::in) + close_impl(); + + if ((state_ & f_write) && which == BOOST_IOS::out) { + try { + if (!cur_line_.empty()) + write_line(snk); + } catch (...) { + try { + close_impl(); + } catch (...) { } + throw; + } + close_impl(); + } + } +private: + virtual string_type do_filter(const string_type& line) = 0; + + // Copies filtered characters fron the current line into + // the given buffer. + std::streamsize read_line(char_type* s, std::streamsize n) + { + using namespace std; + std::streamsize result = + (std::min) (n, static_cast(cur_line_.size())); + traits_type::copy(s, cur_line_.data(), result); + cur_line_.erase(0, result); + return result; + } + + // Attempts to retrieve a line of text from the given source; returns + // an int_type as a good/eof/would_block status code. + template + typename traits_type::int_type next_line(Source& src) + { + using namespace std; + typename traits_type::int_type c; + while ( traits_type::is_good(c = iostreams::get(src)) && + c != traits_type::newline() ) + { + cur_line_ += traits_type::to_int_type(c); + } + if (!traits_type::would_block(c)) { + if (!cur_line_.empty() || c == traits_type::newline()) + cur_line_ = do_filter(cur_line_); + if (c == traits_type::newline()) + cur_line_ += c; + } + return c; // status indicator. + } + + // Filters the current line and attemps to write it to the given sink. + // Returns true for success. + template + bool write_line(Sink& snk) + { + string_type line = do_filter(cur_line_) + traits_type::newline(); + std::streamsize amt = static_cast(line.size()); + bool result = iostreams::write(snk, line.data(), amt) == amt; + if (result) + clear(); + return result; + } + + void close_impl() + { + clear(); + state_ = 0; + } + + void clear() + { + cur_line_.erase(); + pos_ = string_type::npos; + } + + enum flag_type { + f_read = 1, + f_write = f_read << 1 + }; + + string_type cur_line_; + typename string_type::size_type pos_; + int state_; +}; +BOOST_IOSTREAMS_PIPABLE(basic_line_filter, 2) + +typedef basic_line_filter line_filter; +typedef basic_line_filter wline_filter; + +} } // End namespaces iostreams, boost. + +#include + +#endif // #ifndef BOOST_IOSTREAMS_LINE_FILTER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/filter/newline.hpp b/win32/include/boost/iostreams/filter/newline.hpp new file mode 100755 index 000000000..4503e70a9 --- /dev/null +++ b/win32/include/boost/iostreams/filter/newline.hpp @@ -0,0 +1,441 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// NOTE: I hope to replace the current implementation with a much simpler +// one. + +#ifndef BOOST_IOSTREAMS_NEWLINE_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_NEWLINE_FILTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include // logic_error. +#include // BOOST_STATIC_CONSTANT. +#include +#include +#include // BOOST_IOSTREAMS_FAILURE +#include // get +#include // put +#include +#include +#include +#include + +// Must come last. +#include + +#define BOOST_IOSTREAMS_ASSERT_UNREACHABLE(val) \ + (assert("unreachable code" == 0), val) \ + /**/ + +namespace boost { namespace iostreams { + +namespace newline { + +const char CR = 0x0D; +const char LF = 0x0A; + + // Flags for configuring newline_filter. + +// Exactly one of the following three flags must be present. + +const int posix = 1; // Use CR as line separator. +const int mac = 2; // Use LF as line separator. +const int dos = 4; // Use CRLF as line separator. +const int mixed = 8; // Mixed line endings. +const int final_newline = 16; +const int platform_mask = posix | dos | mac; + +} // End namespace newline. + +namespace detail { + +class newline_base { +public: + bool is_posix() const + { + return !is_mixed() && (flags_ & newline::posix) != 0; + } + bool is_dos() const + { + return !is_mixed() && (flags_ & newline::dos) != 0; + } + bool is_mac() const + { + return !is_mixed() && (flags_ & newline::mac) != 0; + } + bool is_mixed_posix() const { return (flags_ & newline::posix) != 0; } + bool is_mixed_dos() const { return (flags_ & newline::dos) != 0; } + bool is_mixed_mac() const { return (flags_ & newline::mac) != 0; } + bool is_mixed() const + { + int platform = + (flags_ & newline::posix) != 0 ? + newline::posix : + (flags_ & newline::dos) != 0 ? + newline::dos : + (flags_ & newline::mac) != 0 ? + newline::mac : + 0; + return (flags_ & ~platform & newline::platform_mask) != 0; + } + bool has_final_newline() const + { + return (flags_ & newline::final_newline) != 0; + } +protected: + newline_base(int flags) : flags_(flags) { } + int flags_; +}; + +} // End namespace detail. + +class newline_error + : public BOOST_IOSTREAMS_FAILURE, public detail::newline_base +{ +private: + friend class newline_checker; + newline_error(int flags) + : BOOST_IOSTREAMS_FAILURE("bad line endings"), + detail::newline_base(flags) + { } +}; + +class newline_filter { +public: + typedef char char_type; + struct category + : dual_use, + filter_tag, + closable_tag + { }; + + explicit newline_filter(int target) : flags_(target) + { + if ( target != newline::posix && + target != newline::dos && + target != newline::mac ) + { + throw std::logic_error("bad flags"); + } + } + + template + int get(Source& src) + { + using iostreams::newline::CR; + using iostreams::newline::LF; + + assert((flags_ & f_write) == 0); + flags_ |= f_read; + + if (flags_ & (f_has_LF | f_has_EOF)) { + if (flags_ & f_has_LF) + return newline(); + else + return EOF; + } + + int c = + (flags_ & f_has_CR) == 0 ? + iostreams::get(src) : + CR; + + if (c == WOULD_BLOCK ) + return WOULD_BLOCK; + + if (c == CR) { + flags_ |= f_has_CR; + + int d; + if ((d = iostreams::get(src)) == WOULD_BLOCK) + return WOULD_BLOCK; + + if (d == LF) { + flags_ &= ~f_has_CR; + return newline(); + } + + if (d == EOF) { + flags_ |= f_has_EOF; + } else { + iostreams::putback(src, d); + } + + flags_ &= ~f_has_CR; + return newline(); + } + + if (c == LF) + return newline(); + + return c; + } + + template + bool put(Sink& dest, char c) + { + using iostreams::newline::CR; + using iostreams::newline::LF; + + assert((flags_ & f_read) == 0); + flags_ |= f_write; + + if ((flags_ & f_has_LF) != 0) + return c == LF ? + newline(dest) : + newline(dest) && this->put(dest, c); + + if (c == LF) + return newline(dest); + + if ((flags_ & f_has_CR) != 0) + return newline(dest) ? + this->put(dest, c) : + false; + + if (c == CR) { + flags_ |= f_has_CR; + return true; + } + + return iostreams::put(dest, c); + } + + template + void close(Sink& dest, BOOST_IOS::openmode which) + { + typedef typename iostreams::category_of::type category; + if ((flags_ & f_write) != 0 && (flags_ & f_has_CR) != 0) + newline_if_sink(dest); + flags_ &= ~f_has_LF; // Restore original flags. + } +private: + + // Returns the appropriate element of a newline sequence. + int newline() + { + using iostreams::newline::CR; + using iostreams::newline::LF; + + switch (flags_ & newline::platform_mask) { + case newline::posix: + return LF; + case newline::mac: + return CR; + case newline::dos: + if (flags_ & f_has_LF) { + flags_ &= ~f_has_LF; + return LF; + } else { + flags_ |= f_has_LF; + return CR; + } + } + return BOOST_IOSTREAMS_ASSERT_UNREACHABLE(0); + } + + // Writes a newline sequence. + template + bool newline(Sink& dest) + { + using iostreams::newline::CR; + using iostreams::newline::LF; + + bool success = false; + switch (flags_ & newline::platform_mask) { + case newline::posix: + success = boost::iostreams::put(dest, LF); + break; + case newline::mac: + success = boost::iostreams::put(dest, CR); + break; + case newline::dos: + if ((flags_ & f_has_LF) != 0) { + if ((success = boost::iostreams::put(dest, LF))) + flags_ &= ~f_has_LF; + } else if (boost::iostreams::put(dest, CR)) { + if (!(success = boost::iostreams::put(dest, LF))) + flags_ |= f_has_LF; + } + break; + } + if (success) + flags_ &= ~f_has_CR; + return success; + } + + // Writes a newline sequence if the given device is a Sink. + template + void newline_if_sink(Device& dest) + { + typedef typename iostreams::category_of::type category; + newline_if_sink(dest, is_convertible()); + } + + template + void newline_if_sink(Sink& dest, mpl::true_) { newline(dest); } + + template + void newline_if_sink(Source&, mpl::false_) { } + + enum flags { + f_has_LF = 32768, + f_has_CR = f_has_LF << 1, + f_has_newline = f_has_CR << 1, + f_has_EOF = f_has_newline << 1, + f_read = f_has_EOF << 1, + f_write = f_read << 1 + }; + int flags_; +}; +BOOST_IOSTREAMS_PIPABLE(newline_filter, 0) + +class newline_checker : public detail::newline_base { +public: + typedef char char_type; + struct category + : dual_use_filter_tag, + closable_tag + { }; + explicit newline_checker(int target = newline::mixed) + : detail::newline_base(0), target_(target), open_(false) + { } + template + int get(Source& src) + { + using newline::CR; + using newline::LF; + + if (!open_) { + open_ = true; + source() = 0; + } + + int c; + if ((c = iostreams::get(src)) == WOULD_BLOCK) + return WOULD_BLOCK; + + // Update source flags. + if (c != EOF) + source() &= ~f_line_complete; + if ((source() & f_has_CR) != 0) { + if (c == LF) { + source() |= newline::dos; + source() |= f_line_complete; + } else { + source() |= newline::mac; + if (c == EOF) + source() |= f_line_complete; + } + } else if (c == LF) { + source() |= newline::posix; + source() |= f_line_complete; + } + source() = (source() & ~f_has_CR) | (c == CR ? f_has_CR : 0); + + // Check for errors. + if ( c == EOF && + (target_ & newline::final_newline) != 0 && + (source() & f_line_complete) == 0 ) + { + fail(); + } + if ( (target_ & newline::platform_mask) != 0 && + (source() & ~target_ & newline::platform_mask) != 0 ) + { + fail(); + } + + return c; + } + + template + bool put(Sink& dest, int c) + { + using iostreams::newline::CR; + using iostreams::newline::LF; + + if (!open_) { + open_ = true; + source() = 0; + } + + if (!iostreams::put(dest, c)) + return false; + + // Update source flags. + source() &= ~f_line_complete; + if ((source() & f_has_CR) != 0) { + if (c == LF) { + source() |= newline::dos; + source() |= f_line_complete; + } else { + source() |= newline::mac; + } + } else if (c == LF) { + source() |= newline::posix; + source() |= f_line_complete; + } + source() = (source() & ~f_has_CR) | (c == CR ? f_has_CR : 0); + + // Check for errors. + if ( (target_ & newline::platform_mask) != 0 && + (source() & ~target_ & newline::platform_mask) != 0 ) + { + fail(); + } + + return true; + } + + template + void close(Sink&, BOOST_IOS::openmode which) + { + using iostreams::newline::final_newline; + + // Update final_newline flag. + if ( (source() & f_has_CR) != 0 || + (source() & f_line_complete) != 0 ) + { + source() |= final_newline; + } + + // Clear non-sticky flags. + source() &= ~(f_has_CR | f_line_complete); + + // Check for errors. + if ( (target_ & final_newline) != 0 && + (source() & final_newline) == 0 ) + { + fail(); + } + } +private: + void fail() { throw newline_error(source()); } + int& source() { return flags_; } + int source() const { return flags_; } + + enum flags { + f_has_CR = 32768, + f_line_complete = f_has_CR << 1 + }; + + int target_; // Represents expected input. + bool open_; +}; +BOOST_IOSTREAMS_PIPABLE(newline_checker, 0) + +} } // End namespaces iostreams, boost. + +#include + +#endif // #ifndef BOOST_IOSTREAMS_NEWLINE_FILTER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/filter/regex.hpp b/win32/include/boost/iostreams/filter/regex.hpp new file mode 100755 index 000000000..7fa3f64c9 --- /dev/null +++ b/win32/include/boost/iostreams/filter/regex.hpp @@ -0,0 +1,98 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_REGEX_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_REGEX_FILTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // allocator. +#include +#include +#include +#include + +namespace boost { namespace iostreams { + +template< typename Ch, + typename Tr = regex_traits, + typename Alloc = std::allocator > +class basic_regex_filter : public aggregate_filter { +private: + typedef aggregate_filter base_type; +public: + typedef typename base_type::char_type char_type; + typedef typename base_type::category category; + typedef std::basic_string string_type; + typedef basic_regex regex_type; + typedef regex_constants::match_flag_type flag_type; + typedef match_results match_type; + typedef function1 formatter; + + basic_regex_filter( const regex_type& re, + const formatter& replace, + flag_type flags = regex_constants::match_default ) + : re_(re), replace_(replace), flags_(flags) { } + basic_regex_filter( const regex_type& re, + const string_type& fmt, + flag_type flags = regex_constants::match_default, + flag_type fmt_flags = regex_constants::format_default ) + : re_(re), replace_(simple_formatter(fmt, fmt_flags)), flags_(flags) { } + basic_regex_filter( const regex_type& re, + const char_type* fmt, + flag_type flags = regex_constants::match_default, + flag_type fmt_flags = regex_constants::format_default ) + : re_(re), replace_(simple_formatter(fmt, fmt_flags)), flags_(flags) { } +private: + typedef typename base_type::vector_type vector_type; + void do_filter(const vector_type& src, vector_type& dest) + { + typedef regex_iterator iterator; + if (src.empty()) + return; + iterator first(&src[0], &src[0] + src.size(), re_, flags_); + iterator last; + const Ch* suffix = 0; + for (; first != last; ++first) { + dest.insert( dest.end(), + first->prefix().first, + first->prefix().second ); + string_type replacement = replace_(*first); + dest.insert( dest.end(), + replacement.begin(), + replacement.end() ); + suffix = first->suffix().first; + } + if (suffix) { + dest.insert(dest.end(), suffix, &src[0] + src.size()); + } else { + dest.insert(dest.end(), &src[0], &src[0] + src.size()); + } + } + struct simple_formatter { + simple_formatter(const string_type& fmt, flag_type fmt_flags) + : fmt_(fmt), fmt_flags_(fmt_flags) { } + string_type operator() (const match_type& match) const + { return match.format(fmt_, fmt_flags_); } + string_type fmt_; + flag_type fmt_flags_; + }; + regex_type re_; + formatter replace_; + flag_type flags_; +}; +BOOST_IOSTREAMS_PIPABLE(basic_regex_filter, 3) + +typedef basic_regex_filter regex_filter; +typedef basic_regex_filter wregex_filter; + + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_REGEX_FILTER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/filter/stdio.hpp b/win32/include/boost/iostreams/filter/stdio.hpp new file mode 100755 index 000000000..d4b92a413 --- /dev/null +++ b/win32/include/boost/iostreams/filter/stdio.hpp @@ -0,0 +1,84 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Based on the work of Christopher Diggins. + +#ifndef BOOST_IOSTREAMS_STDIO_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_STDIO_FILTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include // allocator. +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace iostreams { + +namespace detail { + +} // End namespace detail. + +template > +class basic_stdio_filter : public aggregate_filter { +private: + typedef aggregate_filter base_type; +public: + typedef typename base_type::char_type char_type; + typedef typename base_type::category category; + typedef typename base_type::vector_type vector_type; +private: + static std::istream& standard_input(char*) { return std::cin; } + static std::ostream& standard_output(char*) { return std::cout; } +#ifndef BOOST_IOSTREAMS_NO_WIDE_STREAMS + static std::wistream& standard_input(wchar_t*) { return std::wcin; } + static std::wostream& standard_output(wchar_t*) { return std::wcout; } +#endif // BOOST_IOSTREAMS_NO_WIDE_STREAMS + + struct scoped_redirector { // Thanks to Maxim Egorushkin. + typedef BOOST_IOSTREAMS_CHAR_TRAITS(Ch) traits_type; + typedef BOOST_IOSTREAMS_BASIC_IOS(Ch, traits_type) ios_type; + typedef BOOST_IOSTREAMS_BASIC_STREAMBUF(Ch, traits_type) streambuf_type; + scoped_redirector( ios_type& ios, + streambuf_type* newbuf ) + : ios_(ios), old_(ios.rdbuf(newbuf)) + { } + ~scoped_redirector() { ios_.rdbuf(old_); } + scoped_redirector& operator=(const scoped_redirector&); + ios_type& ios_; + streambuf_type* old_; + }; + + virtual void do_filter() = 0; + virtual void do_filter(const vector_type& src, vector_type& dest) + { + stream_buffer< basic_array_source > + srcbuf(&src[0], &src[0] + src.size()); + stream_buffer< back_insert_device > + destbuf(iostreams::back_inserter(dest)); + scoped_redirector redirect_input(standard_input((Ch*)0), &srcbuf); + scoped_redirector redirect_output(standard_output((Ch*)0), &destbuf); + do_filter(); + } +}; +BOOST_IOSTREAMS_PIPABLE(basic_stdio_filter, 2) + +typedef basic_stdio_filter stdio_filter; +typedef basic_stdio_filter wstdio_wfilter; + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_STDIO_FILTER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/filter/symmetric.hpp b/win32/include/boost/iostreams/filter/symmetric.hpp new file mode 100755 index 000000000..132c2a6b7 --- /dev/null +++ b/win32/include/boost/iostreams/filter/symmetric.hpp @@ -0,0 +1,304 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Contains the definitions of the class templates symmetric_filter, +// which models DualUseFilter based on a model of the Symmetric Filter. + +// +// Roughly, a Symmetric Filter is a class type with the following interface: +// +// struct symmetric_filter { +// typedef xxx char_type; +// +// bool filter( const char*& begin_in, const char* end_in, +// char*& begin_out, char* end_out, bool flush ) +// { +// // Consume as many characters as possible from the interval +// // [begin_in, end_in), without exhausting the output range +// // [begin_out, end_out). If flush is true, write as mush output +// // as possible. +// // A return value of true indicates that filter should be called +// // again. More precisely, if flush is false, a return value of +// // false indicates that the natural end of stream has been reached +// // and that all filtered data has been forwarded; if flush is +// // true, a return value of false indicates that all filtered data +// // has been forwarded. +// } +// void close() { /* Reset filter's state. */ } +// }; +// +// Symmetric Filter filters need not be CopyConstructable. +// + +#ifndef BOOST_IOSTREAMS_SYMMETRIC_FILTER_HPP_INCLUDED +#define BOOST_IOSTREAMS_SYMMETRIC_FILTER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include // allocator, auto_ptr. +#include // BOOST_DEDUCED_TYPENAME. +#include +#include // buffer size. +#include +#include +#include +#include +#include +#include // read, write. +#include +#include +#include +#include +#include +#include + +// Must come last. +#include // MSVC. + +namespace boost { namespace iostreams { + +template< typename SymmetricFilter, + typename Alloc = + std::allocator< + BOOST_DEDUCED_TYPENAME char_type_of::type + > > +class symmetric_filter { +public: + typedef typename char_type_of::type char_type; + typedef std::basic_string string_type; + struct category + : dual_use, + filter_tag, + multichar_tag, + closable_tag + { }; + + // Expands to a sequence of ctors which forward to impl. + #define BOOST_PP_LOCAL_MACRO(n) \ + BOOST_IOSTREAMS_TEMPLATE_PARAMS(n, T) \ + explicit symmetric_filter( \ + int buffer_size BOOST_PP_COMMA_IF(n) \ + BOOST_PP_ENUM_BINARY_PARAMS(n, const T, &t) ) \ + : pimpl_(new impl(buffer_size BOOST_PP_COMMA_IF(n) \ + BOOST_PP_ENUM_PARAMS(n, t))) \ + { } \ + /**/ + #define BOOST_PP_LOCAL_LIMITS (0, BOOST_IOSTREAMS_MAX_FORWARDING_ARITY) + #include BOOST_PP_LOCAL_ITERATE() + #undef BOOST_PP_LOCAL_MACRO + + template + std::streamsize read(Source& src, char_type* s, std::streamsize n) + { + using namespace std; + if (!(state() & f_read)) + begin_read(); + + buffer_type& buf = pimpl_->buf_; + int status = (state() & f_eof) != 0 ? f_eof : f_good; + char_type *next_s = s, + *end_s = s + n; + while (true) + { + // Invoke filter if there are unconsumed characters in buffer or if + // filter must be flushed. + bool flush = status == f_eof; + if (buf.ptr() != buf.eptr() || flush) { + const char_type* next = buf.ptr(); + bool done = + !filter().filter(next, buf.eptr(), next_s, end_s, flush); + buf.ptr() = buf.data() + (next - buf.data()); + if (done) + return detail::check_eof( + static_cast(next_s - s) + ); + } + + // If no more characters are available without blocking, or + // if read request has been satisfied, return. + if ( status == f_would_block && buf.ptr() == buf.eptr() || + next_s == end_s ) + { + return static_cast(next_s - s); + } + + // Fill buffer. + if (status == f_good) + status = fill(src); + } + } + + template + std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) + { + if (!(state() & f_write)) + begin_write(); + + buffer_type& buf = pimpl_->buf_; + const char_type *next_s, *end_s; + for (next_s = s, end_s = s + n; next_s != end_s; ) { + if (buf.ptr() == buf.eptr() && !flush(snk)) + break; + filter().filter(next_s, end_s, buf.ptr(), buf.eptr(), false); + } + return static_cast(next_s - s); + } + + template + void close(Sink& snk, BOOST_IOS::openmode which) + { + if ((state() & f_write) != 0) { + + // Repeatedly invoke filter() with no input. + try { + buffer_type& buf = pimpl_->buf_; + char dummy; + const char* end = &dummy; + bool again = true; + while (again) { + if (buf.ptr() != buf.eptr()) + again = filter().filter( end, end, buf.ptr(), + buf.eptr(), true ); + flush(snk); + } + } catch (...) { + try { close_impl(); } catch (...) { } + throw; + } + close_impl(); + } else { + close_impl(); + } + } + SymmetricFilter& filter() { return *pimpl_; } + string_type unconsumed_input() const; + +// Give impl access to buffer_type on Tru64 +#if !BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) + private: +#endif + typedef detail::buffer buffer_type; +private: + buffer_type& buf() { return pimpl_->buf_; } + const buffer_type& buf() const { return pimpl_->buf_; } + int& state() { return pimpl_->state_; } + void begin_read(); + void begin_write(); + + template + int fill(Source& src) + { + std::streamsize amt = iostreams::read(src, buf().data(), buf().size()); + if (amt == -1) { + state() |= f_eof; + return f_eof; + } + buf().set(0, amt); + return amt == buf().size() ? f_good : f_would_block; + } + + // Attempts to write the contents of the buffer the given Sink. + // Returns true if at least on character was written. + template + bool flush(Sink& snk) + { + typedef typename iostreams::category_of::type category; + typedef is_convertible can_write; + return flush(snk, can_write()); + } + + template + bool flush(Sink& snk, mpl::true_) + { + typedef char_traits traits_type; + std::streamsize amt = + static_cast(buf().ptr() - buf().data()); + std::streamsize result = + boost::iostreams::write(snk, buf().data(), amt); + if (result < amt && result > 0) + traits_type::move(buf().data(), buf().data() + result, amt - result); + buf().set(amt - result, buf().size()); + return result != 0; + } + + template + bool flush(Sink&, mpl::false_) { return true;} + + void close_impl(); + + enum flag_type { + f_read = 1, + f_write = f_read << 1, + f_eof = f_write << 1, + f_good, + f_would_block + }; + + struct impl : SymmetricFilter { + + // Expands to a sequence of ctors which forward to SymmetricFilter. + #define BOOST_PP_LOCAL_MACRO(n) \ + BOOST_IOSTREAMS_TEMPLATE_PARAMS(n, T) \ + impl( int buffer_size BOOST_PP_COMMA_IF(n) \ + BOOST_PP_ENUM_BINARY_PARAMS(n, const T, &t) ) \ + : SymmetricFilter(BOOST_PP_ENUM_PARAMS(n, t)), \ + buf_(buffer_size), state_(0) \ + { } \ + /**/ + #define BOOST_PP_LOCAL_LIMITS (0, BOOST_IOSTREAMS_MAX_FORWARDING_ARITY) + #include BOOST_PP_LOCAL_ITERATE() + #undef BOOST_PP_LOCAL_MACRO + + buffer_type buf_; + int state_; + }; + + shared_ptr pimpl_; +}; +BOOST_IOSTREAMS_PIPABLE(symmetric_filter, 2) + +//------------------Implementation of symmetric_filter----------------// + +template +void symmetric_filter::begin_read() +{ + assert(!(state() & f_write)); + state() |= f_read; + buf().set(0, 0); +} + +template +void symmetric_filter::begin_write() +{ + assert(!(state() & f_read)); + state() |= f_write; + buf().set(0, buf().size()); +} + +template +void symmetric_filter::close_impl() +{ + state() = 0; + buf().set(0, 0); + filter().close(); +} + +template +typename symmetric_filter::string_type +symmetric_filter::unconsumed_input() const +{ return string_type(buf().ptr(), buf().eptr()); } + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#include // MSVC. + +#endif // #ifndef BOOST_IOSTREAMS_SYMMETRIC_FILTER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/filter/test.hpp b/win32/include/boost/iostreams/filter/test.hpp new file mode 100755 index 000000000..c54abf380 --- /dev/null +++ b/win32/include/boost/iostreams/filter/test.hpp @@ -0,0 +1,278 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // BOOST_MSVC,put size_t in std. +#include +#include // min. +#include // size_t. +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || \ + BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) || \ + BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \ + /**/ +# include // rand. +#endif +#include // memcpy, strlen. +#include +#include +#include +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \ + !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \ + !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \ + /**/ +# include +# include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef memcpy +#undef rand +#undef strlen + +#if defined(BOOST_NO_STDC_NAMESPACE) && !defined(__LIBCOMO__) +namespace std { + using ::memcpy; + using ::strlen; + #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || \ + BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) || \ + BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \ + /**/ + using ::rand; + #endif +} +#endif + +namespace boost { namespace iostreams { + +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_string, std::basic_string, 3) + +const std::streamsize default_increment = 5; + +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && \ + !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) && \ + !BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \ + /**/ + std::streamsize rand(int inc) + { + static rand48 random_gen; + static uniform_smallint random_dist(0, inc); + return random_dist(random_gen); + } +#else + std::streamsize rand(int inc) + { + return (std::rand() * inc + 1) / RAND_MAX; + } +#endif + +class non_blocking_source { +public: + typedef char char_type; + struct category + : source_tag, + peekable_tag + { }; + explicit non_blocking_source( const std::string& data, + std::streamsize inc = default_increment ) + : data_(data), inc_(inc), pos_(0) + { } + std::streamsize read(char* s, std::streamsize n) + { + if (pos_ == static_cast(data_.size())) + return -1; + std::streamsize avail = + (std::min) (n, static_cast(data_.size() - pos_)); + std::streamsize amt = (std::min) (rand(inc_), avail); + if (amt) + std::memcpy(s, data_.c_str() + pos_, amt); + pos_ += amt; + return amt; + } + + bool putback(char c) + { + if (pos_ > 0) { + data_[--pos_] = c; + return true; + } + return false; + } +private: + std::string data_; + std::streamsize inc_, pos_; +}; + +class non_blocking_sink : public sink { +public: + non_blocking_sink( std::string& dest, + std::streamsize inc = default_increment ) + : dest_(dest), inc_(inc) + { } + std::streamsize write(const char* s, std::streamsize n) + { + std::streamsize amt = (std::min) (rand(inc_), n); + dest_.insert(dest_.end(), s, s + amt); + return amt; + } +private: + non_blocking_sink& operator=(const non_blocking_sink&); + std::string& dest_; + std::streamsize inc_; +}; + +//--------------Definition of test_input_filter-------------------------------// + +template +bool test_input_filter( Filter filter, + const std::string& input, + const std::string& output, + mpl::true_ ) +{ + for ( int inc = default_increment; + inc < default_increment * 40; + inc += default_increment ) + { + non_blocking_source src(input, inc); + std::string dest; + iostreams::copy(compose(filter, src), iostreams::back_inserter(dest)); + if (dest != output) + return false; + } + return true; +} + +template +bool test_input_filter( Filter filter, + const Source1& input, + const Source2& output, + mpl::false_ ) +{ + std::string in; + std::string out; + iostreams::copy(input, iostreams::back_inserter(in)); + iostreams::copy(output, iostreams::back_inserter(out)); + return test_input_filter(filter, in, out); +} + +template +bool test_input_filter( Filter filter, + const Source1& input, + const Source2& output ) +{ + // Use tag dispatch to compensate for bad overload resolution. + return test_input_filter( filter, input, output, + is_string() ); +} + +//--------------Definition of test_output_filter------------------------------// + +template +bool test_output_filter( Filter filter, + const std::string& input, + const std::string& output, + mpl::true_ ) +{ + for ( int inc = default_increment; + inc < default_increment * 40; + inc += default_increment ) + { + array_source src(input.data(), input.data() + input.size()); + std::string dest; + iostreams::copy(src, compose(filter, non_blocking_sink(dest, inc))); + if (dest != output ) + return false; + } + return true; +} + +template +bool test_output_filter( Filter filter, + const Source1& input, + const Source2& output, + mpl::false_ ) +{ + std::string in; + std::string out; + iostreams::copy(input, iostreams::back_inserter(in)); + iostreams::copy(output, iostreams::back_inserter(out)); + return test_output_filter(filter, in, out); +} + +template +bool test_output_filter( Filter filter, + const Source1& input, + const Source2& output ) +{ + // Use tag dispatch to compensate for bad overload resolution. + return test_output_filter( filter, input, output, + is_string() ); +} + +//--------------Definition of test_filter_pair--------------------------------// + +template +bool test_filter_pair( OutputFilter out, + InputFilter in, + const std::string& data, + mpl::true_ ) +{ + for ( int inc = default_increment; + inc <= default_increment * 40; + inc += default_increment ) + { + array_source src(data.data(), data.data() + data.size()); + std::string temp; + std::string dest; + iostreams::copy(src, compose(out, non_blocking_sink(temp, inc))); + iostreams::copy( + compose(in, non_blocking_source(temp, inc)), + iostreams::back_inserter(dest) + ); + if (dest != data) + return false; + } + return true; +} + +template +bool test_filter_pair( OutputFilter out, + InputFilter in, + const Source& data, + mpl::false_ ) +{ + std::string str; + iostreams::copy(data, iostreams::back_inserter(str)); + return test_filter_pair(out, in, str); +} + +template +bool test_filter_pair( OutputFilter out, + InputFilter in, + const Source& data ) +{ + // Use tag dispatch to compensate for bad overload resolution. + return test_filter_pair(out, in, data, is_string()); +} + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_FILTER_TEST_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/filter/zlib.hpp b/win32/include/boost/iostreams/filter/zlib.hpp new file mode 100755 index 000000000..ca2468676 --- /dev/null +++ b/win32/include/boost/iostreams/filter/zlib.hpp @@ -0,0 +1,416 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Note: custom allocators are not supported on VC6, since that compiler +// had trouble finding the function zlib_base::do_init. + +#ifndef BOOST_IOSTREAMS_ZLIB_HPP_INCLUDED +#define BOOST_IOSTREAMS_ZLIB_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include // streamsize. +#include // allocator, bad_alloc. +#include +#include // MSVC, STATIC_CONSTANT, DEDUCED_TYPENAME, DINKUM. +#include +#include // buffer size. +#include +#include +#include +#include +#include // failure, streamsize. +#include +#include +#include + +// Must come last. +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4251 4231 4660) // Dependencies not exported. +#endif +#include + +namespace boost { namespace iostreams { + +namespace zlib { + // Typedefs + +typedef unsigned int uint; +typedef unsigned char byte; +typedef unsigned long ulong; + +typedef void* (*alloc_func)(void*, zlib::uint, zlib::uint); +typedef void (*free_func)(void*, void*); + + // Compression levels + +BOOST_IOSTREAMS_DECL extern const int no_compression; +BOOST_IOSTREAMS_DECL extern const int best_speed; +BOOST_IOSTREAMS_DECL extern const int best_compression; +BOOST_IOSTREAMS_DECL extern const int default_compression; + + // Compression methods + +BOOST_IOSTREAMS_DECL extern const int deflated; + + // Compression strategies + +BOOST_IOSTREAMS_DECL extern const int default_strategy; +BOOST_IOSTREAMS_DECL extern const int filtered; +BOOST_IOSTREAMS_DECL extern const int huffman_only; + + // Status codes + +BOOST_IOSTREAMS_DECL extern const int okay; +BOOST_IOSTREAMS_DECL extern const int stream_end; +BOOST_IOSTREAMS_DECL extern const int stream_error; +BOOST_IOSTREAMS_DECL extern const int version_error; +BOOST_IOSTREAMS_DECL extern const int data_error; +BOOST_IOSTREAMS_DECL extern const int mem_error; +BOOST_IOSTREAMS_DECL extern const int buf_error; + + // Flush codes + +BOOST_IOSTREAMS_DECL extern const int finish; +BOOST_IOSTREAMS_DECL extern const int no_flush; +BOOST_IOSTREAMS_DECL extern const int sync_flush; + + // Code for current OS + +//BOOST_IOSTREAMS_DECL extern const int os_code; + + // Null pointer constant. + +const int null = 0; + + // Default values + +const int default_window_bits = 15; +const int default_mem_level = 8; +const bool default_crc = false; +const bool default_noheader = false; + +} // End namespace zlib. + +// +// Class name: zlib_params. +// Description: Encapsulates the parameters passed to deflateInit2 +// and inflateInit2 to customize compression and decompression. +// +struct zlib_params { + + // Non-explicit constructor. + zlib_params( int level = zlib::default_compression, + int method = zlib::deflated, + int window_bits = zlib::default_window_bits, + int mem_level = zlib::default_mem_level, + int strategy = zlib::default_strategy, + bool noheader = zlib::default_noheader, + bool calculate_crc = zlib::default_crc ) + : level(level), method(method), window_bits(window_bits), + mem_level(mem_level), strategy(strategy), + noheader(noheader), calculate_crc(calculate_crc) + { } + int level; + int method; + int window_bits; + int mem_level; + int strategy; + bool noheader; + bool calculate_crc; +}; + +// +// Class name: zlib_error. +// Description: Subclass of std::ios::failure thrown to indicate +// zlib errors other than out-of-memory conditions. +// +class BOOST_IOSTREAMS_DECL zlib_error : public BOOST_IOSTREAMS_FAILURE { +public: + explicit zlib_error(int error); + int error() const { return error_; } + static void check(int error); +private: + int error_; +}; + +namespace detail { + +template +struct zlib_allocator_traits { +#ifndef BOOST_NO_STD_ALLOCATOR + typedef typename Alloc::template rebind::other type; +#else + typedef std::allocator type; +#endif +}; + +template< typename Alloc, + typename Base = // VC6 workaround (C2516) + BOOST_DEDUCED_TYPENAME zlib_allocator_traits::type > +struct zlib_allocator : private Base { +private: + typedef typename Base::size_type size_type; +public: + BOOST_STATIC_CONSTANT(bool, custom = + (!is_same, Base>::value)); + typedef typename zlib_allocator_traits::type allocator_type; + static void* allocate(void* self, zlib::uint items, zlib::uint size); + static void deallocate(void* self, void* address); +}; + +class BOOST_IOSTREAMS_DECL zlib_base { +public: + typedef char char_type; +protected: + zlib_base(); + ~zlib_base(); + void* stream() { return stream_; } + template + void init( const zlib_params& p, + bool compress, + zlib_allocator& zalloc ) + { + bool custom = zlib_allocator::custom; + do_init( p, compress, + #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + custom ? zlib_allocator::allocate : 0, + custom ? zlib_allocator::deallocate : 0, + #endif + &zalloc ); + } + void before( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end ); + void after( const char*& src_begin, char*& dest_begin, + bool compress ); + int deflate(int flush); + int inflate(int flush); + void reset(bool compress, bool realloc); +public: + zlib::ulong crc() const { return crc_; } + int total_in() const { return total_in_; } + int total_out() const { return total_out_; } +private: + void do_init( const zlib_params& p, bool compress, + #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + zlib::alloc_func, + zlib::free_func, + #endif + void* derived ); + void* stream_; // Actual type: z_stream*. + bool calculate_crc_; + zlib::ulong crc_; + int total_in_; + int total_out_; +}; + +// +// Template name: zlib_compressor_impl +// Description: Model of C-Style Filte implementing compression by +// delegating to the zlib function deflate. +// +template > +class zlib_compressor_impl : public zlib_base, public zlib_allocator { +public: + zlib_compressor_impl(const zlib_params& = zlib::default_compression); + ~zlib_compressor_impl(); + bool filter( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end, bool flush ); + void close(); +}; + +// +// Template name: zlib_compressor +// Description: Model of C-Style Filte implementing decompression by +// delegating to the zlib function inflate. +// +template > +class zlib_decompressor_impl : public zlib_base, public zlib_allocator { +public: + zlib_decompressor_impl(const zlib_params&); + zlib_decompressor_impl(int window_bits = zlib::default_window_bits); + ~zlib_decompressor_impl(); + bool filter( const char*& begin_in, const char* end_in, + char*& begin_out, char* end_out, bool flush ); + void close(); +}; + +} // End namespace detail. + +// +// Template name: zlib_compressor +// Description: Model of InputFilter and OutputFilter implementing +// compression using zlib. +// +template > +struct basic_zlib_compressor + : symmetric_filter, Alloc> +{ +private: + typedef detail::zlib_compressor_impl impl_type; + typedef symmetric_filter base_type; +public: + typedef typename base_type::char_type char_type; + typedef typename base_type::category category; + basic_zlib_compressor( const zlib_params& = zlib::default_compression, + int buffer_size = default_device_buffer_size ); + zlib::ulong crc() { return this->filter().crc(); } + int total_in() { return this->filter().total_in(); } +}; +BOOST_IOSTREAMS_PIPABLE(basic_zlib_compressor, 1) + +typedef basic_zlib_compressor<> zlib_compressor; + +// +// Template name: zlib_decompressor +// Description: Model of InputFilter and OutputFilter implementing +// decompression using zlib. +// +template > +struct basic_zlib_decompressor + : symmetric_filter, Alloc> +{ +private: + typedef detail::zlib_decompressor_impl impl_type; + typedef symmetric_filter base_type; +public: + typedef typename base_type::char_type char_type; + typedef typename base_type::category category; + basic_zlib_decompressor( int window_bits = zlib::default_window_bits, + int buffer_size = default_device_buffer_size ); + basic_zlib_decompressor( const zlib_params& p, + int buffer_size = default_device_buffer_size ); + zlib::ulong crc() { return this->filter().crc(); } + int total_out() { return this->filter().total_out(); } +}; +BOOST_IOSTREAMS_PIPABLE(basic_zlib_decompressor, 1) + +typedef basic_zlib_decompressor<> zlib_decompressor; + +//----------------------------------------------------------------------------// + +//------------------Implementation of zlib_allocator--------------------------// + +namespace detail { + +template +void* zlib_allocator::allocate + (void* self, zlib::uint items, zlib::uint size) +{ + size_type len = items * size; + char* ptr = + static_cast(self)->allocate + (len + sizeof(size_type) + #if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) + , (char*)0 + #endif + ); + *reinterpret_cast(ptr) = len; + return ptr + sizeof(size_type); +} + +template +void zlib_allocator::deallocate(void* self, void* address) +{ + char* ptr = reinterpret_cast(address) - sizeof(size_type); + size_type len = *reinterpret_cast(ptr) + sizeof(size_type); + static_cast(self)->deallocate(ptr, len); +} + +//------------------Implementation of zlib_compressor_impl--------------------// + +template +zlib_compressor_impl::zlib_compressor_impl(const zlib_params& p) +{ init(p, true, static_cast&>(*this)); } + +template +zlib_compressor_impl::~zlib_compressor_impl() +{ reset(true, false); } + +template +bool zlib_compressor_impl::filter + ( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end, bool flush ) +{ + before(src_begin, src_end, dest_begin, dest_end); + int result = deflate(flush ? zlib::finish : zlib::no_flush); + after(src_begin, dest_begin, true); + zlib_error::check(result); + return result != zlib::stream_end; +} + +template +void zlib_compressor_impl::close() { reset(true, true); } + +//------------------Implementation of zlib_decompressor_impl------------------// + +template +zlib_decompressor_impl::zlib_decompressor_impl(const zlib_params& p) +{ init(p, false, static_cast&>(*this)); } + +template +zlib_decompressor_impl::~zlib_decompressor_impl() +{ reset(false, false); } + +template +zlib_decompressor_impl::zlib_decompressor_impl(int window_bits) +{ + zlib_params p; + p.window_bits = window_bits; + init(p, false, static_cast&>(*this)); +} + +template +bool zlib_decompressor_impl::filter + ( const char*& src_begin, const char* src_end, + char*& dest_begin, char* dest_end, bool /* flush */ ) +{ + before(src_begin, src_end, dest_begin, dest_end); + int result = inflate(zlib::sync_flush); + after(src_begin, dest_begin, false); + zlib_error::check(result); + return result != zlib::stream_end; +} + +template +void zlib_decompressor_impl::close() { reset(false, true); } + +} // End namespace detail. + +//------------------Implementation of zlib_decompressor-----------------------// + +template +basic_zlib_compressor::basic_zlib_compressor + (const zlib_params& p, int buffer_size) + : base_type(buffer_size, p) { } + +//------------------Implementation of zlib_decompressor-----------------------// + +template +basic_zlib_decompressor::basic_zlib_decompressor + (int window_bits, int buffer_size) + : base_type(buffer_size, window_bits) { } + +template +basic_zlib_decompressor::basic_zlib_decompressor + (const zlib_params& p, int buffer_size) + : base_type(buffer_size, p) { } + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#include // Pops abi_suffix.hpp pragmas. +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // #ifndef BOOST_IOSTREAMS_ZLIB_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/filtering_stream.hpp b/win32/include/boost/iostreams/filtering_stream.hpp new file mode 100755 index 000000000..f71969ccc --- /dev/null +++ b/win32/include/boost/iostreams/filtering_stream.hpp @@ -0,0 +1,166 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2004-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_FILTER_STREAM_HPP_INCLUDED +#define BOOST_IOSTREAMS_FILTER_STREAM_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // allocator. +#include +#include +#include // standard streams. +#include +#include +#include // pubsync. +#include +#include +#include +#include +#include + +// Must come last. +#include // MSVC. + +namespace boost { namespace iostreams { + +//--------------Definition of filtered_istream--------------------------------// + +namespace detail { + +template +struct filtering_stream_traits { + typedef typename + iostreams::select< // Disambiguation for Tru64 + mpl::and_< + is_convertible, + is_convertible + >, + BOOST_IOSTREAMS_BASIC_IOSTREAM(Ch, Tr), + is_convertible, + BOOST_IOSTREAMS_BASIC_ISTREAM(Ch, Tr), + else_, + BOOST_IOSTREAMS_BASIC_OSTREAM(Ch, Tr) + >::type stream_type; + typedef typename + iostreams::select< // Dismbiguation required for Tru64. + mpl::and_< + is_convertible, + is_convertible + >, + iostream_tag, + is_convertible, + istream_tag, + else_, + ostream_tag + >::type stream_tag; +}; + +template +class filtering_stream_base + : public access_control< + boost::iostreams::detail::chain_client, + Access + >, + public filtering_stream_traits< + typename Chain::mode, + typename Chain::char_type, + typename Chain::traits_type + >::stream_type +{ +public: + typedef Chain chain_type; + typedef access_control< + boost::iostreams::detail::chain_client, + Access + > client_type; +protected: + typedef typename + filtering_stream_traits< + typename Chain::mode, + typename Chain::char_type, + typename Chain::traits_type + >::stream_type stream_type; + filtering_stream_base() : stream_type(0) { this->set_chain(&chain_); } +private: + void notify() { this->rdbuf(chain_.empty() ? 0 : &chain_.front()); } + Chain chain_; +}; + +} // End namespace detail. + +// +// Macro: BOOST_IOSTREAMS_DEFINE_FILTER_STREAM(name_, chain_type_, default_char_) +// Description: Defines a template derived from std::basic_streambuf which uses +// a chain to perform i/o. The template has the following parameters: +// Mode - the i/o mode. +// Ch - The character type. +// Tr - The character traits type. +// Alloc - The allocator type. +// Access - Indicates accessibility of the chain interface; must be either +// public_ or protected_; defaults to public_. +// Macro parameters: +// name_ - The name of the template to be defined. +// chain_type_ - The name of the chain template. +// default_char_ - The default value for the char template parameter. +// +#define BOOST_IOSTREAMS_DEFINE_FILTER_STREAM(name_, chain_type_, default_char_) \ + template< typename Mode, \ + typename Ch = default_char_, \ + typename Tr = BOOST_IOSTREAMS_CHAR_TRAITS(Ch), \ + typename Alloc = std::allocator, \ + typename Access = public_ > \ + class name_ \ + : public boost::iostreams::detail::filtering_stream_base< \ + chain_type_, Access \ + > \ + { \ + public: \ + typedef Ch char_type; \ + struct category \ + : Mode, \ + closable_tag, \ + detail::filtering_stream_traits::stream_tag \ + { }; \ + BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr) \ + typedef Mode mode; \ + typedef chain_type_ chain_type; \ + name_() { } \ + BOOST_IOSTREAMS_DEFINE_PUSH_CONSTRUCTOR(name_, mode, Ch, push_impl) \ + ~name_() { \ + if (this->is_complete()) \ + this->rdbuf()->BOOST_IOSTREAMS_PUBSYNC(); \ + } \ + private: \ + typedef access_control< \ + boost::iostreams::detail::chain_client< \ + chain_type_ \ + >, \ + Access \ + > client_type; \ + template \ + void push_impl(const T& t BOOST_IOSTREAMS_PUSH_PARAMS()) \ + { client_type::push(t BOOST_IOSTREAMS_PUSH_ARGS()); } \ + }; \ + /**/ +BOOST_IOSTREAMS_DEFINE_FILTER_STREAM(filtering_stream, boost::iostreams::chain, char) +BOOST_IOSTREAMS_DEFINE_FILTER_STREAM(wfiltering_stream, boost::iostreams::chain, wchar_t) + +typedef filtering_stream filtering_istream; +typedef filtering_stream filtering_ostream; +typedef wfiltering_stream filtering_wistream; +typedef wfiltering_stream filtering_wostream; + +//----------------------------------------------------------------------------// + +} } // End namespace iostreams, boost + +#include // MSVC + +#endif // #ifndef BOOST_IOSTREAMS_FILTER_STREAM_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/filtering_streambuf.hpp b/win32/include/boost/iostreams/filtering_streambuf.hpp new file mode 100755 index 000000000..08d97fe2e --- /dev/null +++ b/win32/include/boost/iostreams/filtering_streambuf.hpp @@ -0,0 +1,70 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_FILTERING_STREAMBUF_HPP_INCLUDED +#define BOOST_IOSTREAMS_FILTERING_STREAMBUF_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include // allocator. +#include +#include +#include +#include +#include // pubsync. +#include +#include + +namespace boost { namespace iostreams { + +// +// Macro: BOOST_IOSTREAMS_DEFINE_FILTERBUF(name_, chain_type_, default_char_) +// Description: Defines a template derived from std::basic_streambuf which uses +// a chain to perform i/o. The template has the following parameters: +// Ch - The character type. +// Tr - The character traits type. +// Alloc - The allocator type. +// Access - Indicates accessibility of the chain interface; must be either +// public_ or protected_; defaults to public_. +// +#define BOOST_IOSTREAMS_DEFINE_FILTER_STREAMBUF(name_, chain_type_, default_char_) \ + template< typename Mode, \ + typename Ch = default_char_, \ + typename Tr = BOOST_IOSTREAMS_CHAR_TRAITS(Ch), \ + typename Alloc = std::allocator, \ + typename Access = public_ > \ + class name_ : public boost::iostreams::detail::chainbuf< \ + chain_type_, Mode, Access \ + > \ + { \ + public: \ + typedef Ch char_type; \ + struct category \ + : Mode, closable_tag, streambuf_tag \ + { }; \ + BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr) \ + typedef Mode mode; \ + typedef chain_type_ chain_type; \ + name_() { } \ + BOOST_IOSTREAMS_DEFINE_PUSH_CONSTRUCTOR(name_, mode, Ch, push_impl) \ + ~name_() { if (this->is_complete()) this->BOOST_IOSTREAMS_PUBSYNC(); } \ + }; \ + /**/ +BOOST_IOSTREAMS_DEFINE_FILTER_STREAMBUF(filtering_streambuf, boost::iostreams::chain, char) +BOOST_IOSTREAMS_DEFINE_FILTER_STREAMBUF(filtering_wstreambuf, boost::iostreams::chain, wchar_t) + +typedef filtering_streambuf filtering_istreambuf; +typedef filtering_streambuf filtering_ostreambuf; +typedef filtering_wstreambuf filtering_wistreambuf; +typedef filtering_wstreambuf filtering_wostreambuf; + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_FILTERING_STREAMBUF_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/flush.hpp b/win32/include/boost/iostreams/flush.hpp new file mode 100755 index 000000000..2f2849e49 --- /dev/null +++ b/win32/include/boost/iostreams/flush.hpp @@ -0,0 +1,125 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_FLUSH_HPP_INCLUDED +#define BOOST_IOSTREAMS_FLUSH_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // DEDUCED_TYPENAME, MSVC. +#include +#include +#include +#include +#include +#include +#include + +// Must come last. +#include + +namespace boost { namespace iostreams { + +namespace detail { + +template +struct flush_device_impl; + +template +struct flush_filter_impl; + +} // End namespace detail. + +template +bool flush(T& t) +{ return detail::flush_device_impl::flush(detail::unwrap(t)); } + +template +bool flush(T& t, Sink& snk) +{ return detail::flush_filter_impl::flush(detail::unwrap(t), snk); } + +namespace detail { + +//------------------Definition of flush_device_impl---------------------------// + +template +struct flush_device_impl + : mpl::if_< + is_custom, + operations, + flush_device_impl< + BOOST_DEDUCED_TYPENAME + dispatch< + T, ostream_tag, streambuf_tag, flushable_tag, any_tag + >::type + > + >::type + { }; + +template<> +struct flush_device_impl { + template + static bool flush(T& t) + { return t.rdbuf()->BOOST_IOSTREAMS_PUBSYNC() == 0; } +}; + +template<> +struct flush_device_impl { + template + static bool flush(T& t) + { return t.BOOST_IOSTREAMS_PUBSYNC() == 0; } +}; + +template<> +struct flush_device_impl { + template + static bool flush(T& t) { return t.flush(); } +}; + +template<> +struct flush_device_impl { + template + static bool flush(T&) { return true; } +}; + +//------------------Definition of flush_filter_impl---------------------------// + +template +struct flush_filter_impl + : mpl::if_< + is_custom, + operations, + flush_filter_impl< + BOOST_DEDUCED_TYPENAME + dispatch< + T, flushable_tag, any_tag + >::type + > + >::type + { }; + +template<> +struct flush_filter_impl { + template + static bool flush(T& t, Sink& snk) { return t.flush(snk); } +}; + +template<> +struct flush_filter_impl { + template + static bool flush(T&, Sink&) { return false; } +}; + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#include + +#endif // #ifndef BOOST_IOSTREAMS_FLUSH_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/get.hpp b/win32/include/boost/iostreams/get.hpp new file mode 100755 index 000000000..c6efbc374 --- /dev/null +++ b/win32/include/boost/iostreams/get.hpp @@ -0,0 +1,17 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_GET_HPP_INCLUDED +#define BOOST_IOSTREAMS_GET_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include + +#endif // #ifndef BOOST_IOSTREAMS_GET_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/imbue.hpp b/win32/include/boost/iostreams/imbue.hpp new file mode 100755 index 000000000..33c3261de --- /dev/null +++ b/win32/include/boost/iostreams/imbue.hpp @@ -0,0 +1,82 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_IMBUE_HPP_INCLUDED +#define BOOST_IOSTREAMS_IMBUE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // DEDUCED_TYPENAME, MSVC. +#include +#include +#include +#include +#include +#include + +// Must come last. +#include + +namespace boost { namespace iostreams { + +namespace detail { + +// Implementation templates for simulated tag dispatch. +template +struct imbue_impl; + +} // End namespace detail. + +template +void imbue(T& t, const Locale& loc) +{ detail::imbue_impl::imbue(detail::unwrap(t), loc); } + +namespace detail { + +//------------------Definition of imbue_impl----------------------------------// + +template +struct imbue_impl + : mpl::if_< + is_custom, + operations, + imbue_impl< + BOOST_DEDUCED_TYPENAME + dispatch< + T, streambuf_tag, localizable_tag, any_tag + >::type + > + >::type + { }; + +template<> +struct imbue_impl { + template + static void imbue(T&, const Locale&) { } +}; + +template<> +struct imbue_impl { + template + static void imbue(T& t, const Locale& loc) { t.pubimbue(loc); } +}; + +template<> +struct imbue_impl { + template + static void imbue(T& t, const Locale& loc) { t.imbue(loc); } +}; + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#include + +#endif // #ifndef BOOST_IOSTREAMS_IMBUE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/input_sequence.hpp b/win32/include/boost/iostreams/input_sequence.hpp new file mode 100755 index 000000000..c73364623 --- /dev/null +++ b/win32/include/boost/iostreams/input_sequence.hpp @@ -0,0 +1,72 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_INPUT_SEQUENCE_HPP_INCLUDED +#define BOOST_IOSTREAMS_INPUT_SEQUENCE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // pair. +#include // DEDUCED_TYPENAME, MSVC. +#include +#include +#include // is_custom +#include +#include + +// Must come last. +#include + +namespace boost { namespace iostreams { + +namespace detail { + +template +struct input_sequence_impl; + +} // End namespace detail. + +template +inline std::pair< + BOOST_DEDUCED_TYPENAME char_type_of::type*, + BOOST_DEDUCED_TYPENAME char_type_of::type* +> +input_sequence(T& t) +{ return detail::input_sequence_impl::input_sequence(t); } + +namespace detail { + +//------------------Definition of direct_impl-------------------------------// + +template +struct input_sequence_impl + : mpl::if_< + detail::is_custom, + operations, + input_sequence_impl + >::type + { }; + +template<> +struct input_sequence_impl { + template + static std::pair< + BOOST_DEDUCED_TYPENAME char_type_of::type*, + BOOST_DEDUCED_TYPENAME char_type_of::type* + > + input_sequence(U& u) { return u.input_sequence(); } +}; + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#include + +#endif // #ifndef BOOST_IOSTREAMS_INPUT_SEQUENCE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/invert.hpp b/win32/include/boost/iostreams/invert.hpp new file mode 100755 index 000000000..da81f04df --- /dev/null +++ b/win32/include/boost/iostreams/invert.hpp @@ -0,0 +1,166 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_INVERT_HPP_INCLUDED +#define BOOST_IOSTREAMS_INVERT_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // copy, min. +#include +#include // BOOST_DEDUCED_TYPENAME. +#include // default_filter_buffer_size. +#include +#include +#include +#include +#include +#include +#include +#include // clear_flags, call_reset +#include +#include +#include +#include + +// Must come last. +#include // MSVC. + +namespace boost { namespace iostreams { + +// +// Template name: inverse. +// Template paramters: +// Filter - A model of InputFilter or OutputFilter. +// Description: Generates an InputFilter from an OutputFilter or +// vice versa. +// +template +class inverse { +private: + typedef typename category_of::type base_category; + typedef reference_wrapper filter_ref; +public: + typedef typename char_type_of::type char_type; + typedef typename int_type_of::type int_type; + typedef char_traits traits_type; + typedef typename + mpl::if_< + is_convertible< + base_category, + input + >, + output, + input + >::type mode; + struct category + : mode, + filter_tag, + multichar_tag, + closable_tag + { }; + explicit inverse( const Filter& filter, + std::streamsize buffer_size = + default_filter_buffer_size) + : pimpl_(new impl(filter, buffer_size)) + { } + + template + std::streamsize read(Source& src, char* s, std::streamsize n) + { + typedef detail::counted_array_sink array_sink; + typedef composite filtered_array_sink; + + assert((flags() & f_write) == 0); + if (flags() == 0) { + flags() = f_read; + buf().set(0, 0); + } + + filtered_array_sink snk(filter(), array_sink(s, n)); + int_type status; + for ( status = traits_type::good(); + snk.second().count() < n && status == traits_type::good(); ) + { + status = buf().fill(src); + buf().flush(snk); + } + return snk.second().count() == 0 && + status == traits_type::eof() + ? + -1 + : + snk.second().count(); + } + + template + std::streamsize write(Sink& dest, const char* s, std::streamsize n) + { + typedef detail::counted_array_source array_source; + typedef composite filtered_array_source; + + assert((flags() & f_read) == 0); + if (flags() == 0) { + flags() = f_write; + buf().set(0, 0); + } + + filtered_array_source src(filter(), array_source(s, n)); + for (bool good = true; src.second().count() < n && good; ) { + buf().fill(src); + good = buf().flush(dest); + } + return src.second().count(); + } + + template + void close(Device& dev) + { + detail::execute_all( + detail::flush_buffer(buf(), dev, (flags() & f_write) != 0), + detail::call_close_all(pimpl_->filter_, dev), + detail::clear_flags(flags()) + ); + } +private: + filter_ref filter() { return boost::ref(pimpl_->filter_); } + detail::buffer& buf() { return pimpl_->buf_; } + int& flags() { return pimpl_->flags_; } + + enum flags_ { + f_read = 1, f_write = 2 + }; + + struct impl { + impl(const Filter& filter, std::streamsize n) + : filter_(filter), buf_(n), flags_(0) + { buf_.set(0, 0); } + Filter filter_; + detail::buffer buf_; + int flags_; + }; + shared_ptr pimpl_; +}; + +// +// Template name: invert. +// Template paramters: +// Filter - A model of InputFilter or OutputFilter. +// Description: Returns an instance of an appropriate specialization of inverse. +// +template +inverse invert(const Filter& f) { return inverse(f); } + +//----------------------------------------------------------------------------// + +} } // End namespaces iostreams, boost. + +#include // MSVC. + +#endif // #ifndef BOOST_IOSTREAMS_INVERT_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/operations.hpp b/win32/include/boost/iostreams/operations.hpp new file mode 100755 index 000000000..5c45c4c9a --- /dev/null +++ b/win32/include/boost/iostreams/operations.hpp @@ -0,0 +1,26 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_OPERATIONS_HPP_INCLUDED +#define BOOST_IOSTREAMS_OPERATIONS_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // #ifndef BOOST_IOSTREAMS_OPERATIONS_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/operations_fwd.hpp b/win32/include/boost/iostreams/operations_fwd.hpp new file mode 100755 index 000000000..6bbd1610b --- /dev/null +++ b/win32/include/boost/iostreams/operations_fwd.hpp @@ -0,0 +1,41 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_OPERATIONS_FWD_HPP_INCLUDED +#define BOOST_IOSTREAMS_OPERATIONS_FWD_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include + +namespace boost { namespace iostreams { + +template +struct operations; + +namespace detail { + +struct custom_tag { }; + +template +struct is_custom + : mpl::not_< + is_base_and_derived< custom_tag, operations > + > + { }; + +} // End namespace detail. + +template +struct operations : detail::custom_tag { }; + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_OPERATIONS_FWD_HPP_INCLUDED //--------------// diff --git a/win32/include/boost/iostreams/optimal_buffer_size.hpp b/win32/include/boost/iostreams/optimal_buffer_size.hpp new file mode 100755 index 000000000..585021a84 --- /dev/null +++ b/win32/include/boost/iostreams/optimal_buffer_size.hpp @@ -0,0 +1,87 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_OPTIMAL_BUFFER_SIZE_HPP_INCLUDED +#define BOOST_IOSTREAMS_OPTIMAL_BUFFER_SIZE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // DEDUCED_TYPENAME, MSVC. +#include +#include // constants. +#include +#include +#include +#include + +// Must come last. +#include + +namespace boost { namespace iostreams { + +namespace detail { + +template +struct optimal_buffer_size_impl; + +} // End namespace detail. + +template +std::streamsize optimal_buffer_size(const T& t) +{ + typedef detail::optimal_buffer_size_impl impl; + return impl::optimal_buffer_size(detail::unwrap(t)); +} + +namespace detail { + +//------------------Definition of optimal_buffer_size_impl--------------------// + +template +struct optimal_buffer_size_impl + : mpl::if_< + is_custom, + operations, + optimal_buffer_size_impl< + BOOST_DEDUCED_TYPENAME + dispatch< + T, optimally_buffered_tag, device_tag, filter_tag + >::type + > + >::type + { }; + +template<> +struct optimal_buffer_size_impl { + template + static std::streamsize optimal_buffer_size(const T& t) + { return t.optimal_buffer_size(); } +}; + +template<> +struct optimal_buffer_size_impl { + template + static std::streamsize optimal_buffer_size(const T&) + { return default_device_buffer_size; } +}; + +template<> +struct optimal_buffer_size_impl { + template + static std::streamsize optimal_buffer_size(const T&) + { return default_filter_buffer_size; } +}; + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#include + +#endif // #ifndef BOOST_IOSTREAMS_OPTIMAL_BUFFER_SIZE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/output_sequence.hpp b/win32/include/boost/iostreams/output_sequence.hpp new file mode 100755 index 000000000..80ffebb05 --- /dev/null +++ b/win32/include/boost/iostreams/output_sequence.hpp @@ -0,0 +1,72 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_OUTPUT_SEQUENCE_HPP_INCLUDED +#define BOOST_IOSTREAMS_OUTPUT_SEQUENCE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // pair. +#include // DEDUCED_TYPENAME, MSVC. +#include +#include +#include // is_custom +#include +#include + +// Must come last. +#include + +namespace boost { namespace iostreams { + +namespace detail { + +template +struct output_sequence_impl; + +} // End namespace detail. + +template +inline std::pair< + BOOST_DEDUCED_TYPENAME char_type_of::type*, + BOOST_DEDUCED_TYPENAME char_type_of::type* +> +output_sequence(T& t) +{ return detail::output_sequence_impl::output_sequence(t); } + +namespace detail { + +//------------------Definition of output_sequence_impl------------------------// + +template +struct output_sequence_impl + : mpl::if_< + detail::is_custom, + operations, + output_sequence_impl + >::type + { }; + +template<> +struct output_sequence_impl { + template + static std::pair< + BOOST_DEDUCED_TYPENAME char_type_of::type*, + BOOST_DEDUCED_TYPENAME char_type_of::type* + > + output_sequence(U& u) { return u.output_sequence(); } +}; + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#include + +#endif // #ifndef BOOST_IOSTREAMS_OUTPUT_SEQUENCE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/pipeline.hpp b/win32/include/boost/iostreams/pipeline.hpp new file mode 100755 index 000000000..4636dc4cd --- /dev/null +++ b/win32/include/boost/iostreams/pipeline.hpp @@ -0,0 +1,128 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_PIPABLE_HPP_INCLUDED +#define BOOST_IOSTREAMS_PIPABLE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // BOOST_MSVC. +#include +#include +#include +#include +#include +#include +#include +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +# include +#endif + +#define BOOST_IOSTREAMS_PIPABLE(filter, arity) \ + template< BOOST_PP_ENUM_PARAMS(arity, typename T) \ + BOOST_PP_COMMA_IF(arity) typename Component> \ + ::boost::iostreams::pipeline< \ + ::boost::iostreams::detail::pipeline_segment< \ + filter BOOST_IOSTREAMS_TEMPLATE_ARGS(arity, T) \ + >, \ + Component \ + > operator|( const filter BOOST_IOSTREAMS_TEMPLATE_ARGS(arity, T)& f, \ + const Component& c ) \ + { \ + typedef ::boost::iostreams::detail::pipeline_segment< \ + filter BOOST_IOSTREAMS_TEMPLATE_ARGS(arity, T) \ + > segment; \ + return ::boost::iostreams::pipeline \ + (segment(f), c); \ + } \ + /**/ + +namespace boost { namespace iostreams { + +template +struct pipeline; + +namespace detail { + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + struct pipeline_base { }; + + template + struct is_pipeline + : is_base_and_derived + { }; +#endif +#if BOOST_WORKAROUND(__BORLANDC__, < 0x600) + template + struct is_pipeline : mpl::false_ { }; + + template + struct is_pipeline< pipeline > : mpl::true_ { }; +#endif + +template +class pipeline_segment +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + : pipeline_base +#endif +{ +public: + pipeline_segment(const Component& component) + : component_(component) + { } + template + void for_each(Fn fn) const { fn(component_); } + template + void push(Chain& chn) const { chn.push(component_); } +private: + pipeline_segment operator=(const pipeline_segment&); + const Component& component_; +}; + +} // End namespace detail. + +//------------------Definition of Pipeline------------------------------------// + +template +struct pipeline : Pipeline { + typedef Pipeline pipeline_type; + typedef Component component_type; + pipeline(const Pipeline& p, const Component& component) + : Pipeline(p), component_(component) + { } + template + void for_each(Fn fn) const + { + Pipeline::for_each(fn); + fn(component_); + } + template + void push(Chain& chn) const + { + Pipeline::push(chn); + chn.push(component_); + } + const Pipeline& tail() const { return *this; } + const Component& head() const { return component_; } +private: + pipeline operator=(const pipeline&); + const Component& component_; +}; + +template +pipeline, Component> +operator|(const pipeline& p, const Component& cmp) +{ + BOOST_STATIC_ASSERT(is_filter::value); + return pipeline, Component>(p, cmp); +} + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_PIPABLE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/positioning.hpp b/win32/include/boost/iostreams/positioning.hpp new file mode 100755 index 000000000..ade7189f7 --- /dev/null +++ b/win32/include/boost/iostreams/positioning.hpp @@ -0,0 +1,115 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Thanks to Gareth Sylvester-Bradley for the Dinkumware versions of the +// positioning functions. + +#ifndef BOOST_IOSTREAMS_POSITIONING_HPP_INCLUDED +#define BOOST_IOSTREAMS_POSITIONING_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include +#include // mbstate_t. +#include +#include // streamoff, streampos. + +// Must come last. +#include + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { using ::fpos_t; } +#endif + +namespace boost { namespace iostreams { + +//------------------Definition of stream_offset-------------------------------// + +typedef boost::intmax_t stream_offset; + +//------------------Definition of stream_offset_to_streamoff------------------// + +inline std::streamoff stream_offset_to_streamoff(stream_offset off) +{ return static_cast(off); } + +//------------------Definition of offset_to_position--------------------------// + +# ifndef BOOST_IOSTREAMS_HAS_DINKUMWARE_FPOS + +inline std::streampos offset_to_position(stream_offset off) { return off; } + +# else // # ifndef BOOST_IOSTREAMS_HAS_DINKUMWARE_FPOS + +inline std::streampos offset_to_position(stream_offset off) +{ return std::streampos(std::mbstate_t(), off); } + +# endif // # ifndef BOOST_IOSTREAMS_HAS_DINKUMWARE_FPOS + +//------------------Definition of position_to_offset--------------------------// + +// Hande custom pos_type's +template +inline stream_offset position_to_offset(PosType pos) +{ return std::streamoff(pos); } + +# ifndef BOOST_IOSTREAMS_HAS_DINKUMWARE_FPOS + +inline stream_offset position_to_offset(std::streampos pos) { return pos; } + +# else // # ifndef BOOST_IOSTREAMS_HAS_DINKUMWARE_FPOS + +// In the Dinkumware standard library, a std::streampos consists of two stream +// offsets -- _Fpos, of type std::fpos_t, and _Myoff, of type std::streamoff -- +// together with a conversion state. A std::streampos is converted to a +// boost::iostreams::stream_offset by extracting the two stream offsets and +// summing them. The value of _Fpos can be extracted using the implementation- +// defined member functions seekpos() or get_fpos_t(), depending on the +// Dinkumware version. The value of _Myoff cannot be extracted directly, but can +// be calculated as the difference between the result of converting the +// std::fpos to a std::streamoff and the result of converting the member _Fpos +// to a long. The latter operation is accomplished with the macro _FPOSOFF, +// which works correctly on platforms where std::fpos_t is an integral type and +// platforms where it is a struct + +// Converts a std::fpos_t to a stream_offset +inline stream_offset fpos_t_to_offset(std::fpos_t pos) +{ +# if defined(_POSIX_) || (_INTEGRAL_MAX_BITS >= 64) || defined(__IBMCPP__) + return pos; +# else + return _FPOSOFF(pos); +# endif +} + +// Extracts the member _Fpos from a std::fpos +inline std::fpos_t streampos_to_fpos_t(std::streampos pos) +{ +# if defined (_CPPLIB_VER) || defined(__IBMCPP__) + return pos.seekpos(); +# else + return pos.get_fpos_t(); +# endif +} + +inline stream_offset position_to_offset(std::streampos pos) +{ + return fpos_t_to_offset(streampos_to_fpos_t(pos)) + + static_cast(static_cast(pos)) - + static_cast(_FPOSOFF(streampos_to_fpos_t(pos))); +} + +# endif // # ifndef BOOST_IOSTREAMS_HAS_DINKUMWARE_FPOS + +} } // End namespaces iostreams, boost. + +#include + +#endif // #ifndef BOOST_IOSTREAMS_POSITIONING_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/put.hpp b/win32/include/boost/iostreams/put.hpp new file mode 100755 index 000000000..4cdc65ac1 --- /dev/null +++ b/win32/include/boost/iostreams/put.hpp @@ -0,0 +1,17 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_PUT_HPP_INCLUDED +#define BOOST_IOSTREAMS_PUT_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include + +#endif // #ifndef BOOST_IOSTREAMS_PUT_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/putback.hpp b/win32/include/boost/iostreams/putback.hpp new file mode 100755 index 000000000..242440bac --- /dev/null +++ b/win32/include/boost/iostreams/putback.hpp @@ -0,0 +1,17 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_PUTBACK_HPP_INCLUDED +#define BOOST_IOSTREAMS_PUTBACK_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include + +#endif // #ifndef BOOST_IOSTREAMS_PUTBACK_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/read.hpp b/win32/include/boost/iostreams/read.hpp new file mode 100755 index 000000000..7656a1bc1 --- /dev/null +++ b/win32/include/boost/iostreams/read.hpp @@ -0,0 +1,247 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_READ_HPP_INCLUDED +#define BOOST_IOSTREAMS_READ_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // DEDUCED_TYPENAME, MSVC. +#include +#include +#include +#include +#include // streamsize. +#include +#include +#include +#include + +// Must come last. +#include + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //-----------------------------------// +# include +#else // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //--------------------------// + +namespace boost { namespace iostreams { + +namespace detail { + +template +struct read_device_impl; + +template +struct read_filter_impl; + +} // End namespace detail. + +template +typename int_type_of::type get(T& t) +{ return detail::read_device_impl::get(detail::unwrap(t)); } + +template +inline std::streamsize +read(T& t, typename char_type_of::type* s, std::streamsize n) +{ return detail::read_device_impl::read(detail::unwrap(t), s, n); } + +template +std::streamsize +read(T& t, Source& src, typename char_type_of::type* s, std::streamsize n) +{ return detail::read_filter_impl::read(detail::unwrap(t), src, s, n); } + +template +bool putback(T& t, typename char_type_of::type c) +{ return detail::read_device_impl::putback(detail::unwrap(t), c); } + +//----------------------------------------------------------------------------// + +namespace detail { + +// Helper function for adding -1 as EOF indicator. +inline std::streamsize check_eof(std::streamsize n) { return n != 0 ? n : -1; } + +// Helper templates for reading from streambufs. +template +struct true_eof_impl; + +template<> +struct true_eof_impl { + template + static bool true_eof(T& t) { return t.true_eof(); } +}; + +template<> +struct true_eof_impl { + template + static bool true_eof(T&) { return true; } +}; + +template +inline bool true_eof(T& t) +{ + const bool linked = is_linked::value; + return true_eof_impl::true_eof(t); +} + +//------------------Definition of read_device_impl----------------------------// + +template +struct read_device_impl + : mpl::if_< + detail::is_custom, + operations, + read_device_impl< + BOOST_DEDUCED_TYPENAME + detail::dispatch< + T, istream_tag, streambuf_tag, input + >::type + > + >::type + { }; + +template<> +struct read_device_impl { + template + static typename int_type_of::type get(T& t) + { return t.get(); } + + template + static std::streamsize + read(T& t, typename char_type_of::type* s, std::streamsize n) + { return check_eof(t.rdbuf()->sgetn(s, n)); } + + template + static bool putback(T& t, typename char_type_of::type c) + { + typedef typename char_type_of::type char_type; + typedef BOOST_IOSTREAMS_CHAR_TRAITS(char_type) traits_type; + return !traits_type::eq_int_type( t.rdbuf()->sputbackc(c), + traits_type::eof() ); + } +}; + +template<> +struct read_device_impl { + template + static typename int_type_of::type + get(T& t) + { // gcc 2.95 needs namespace qualification for char_traits. + typedef typename char_type_of::type char_type; + typedef iostreams::char_traits traits_type; + typename int_type_of::type c; + return !traits_type::is_eof(c = t.sbumpc()) || + detail::true_eof(t) + ? + c : traits_type::would_block(); + } + + template + static std::streamsize + read(T& t, typename char_type_of::type* s, std::streamsize n) + { + std::streamsize amt; + return (amt = t.sgetn(s, n)) != 0 ? + amt : + detail::true_eof(t) ? + -1 : + 0; + } + + template + static bool putback(T& t, typename char_type_of::type c) + { // gcc 2.95 needs namespace qualification for char_traits. + typedef typename char_type_of::type char_type; + typedef iostreams::char_traits traits_type; + return !traits_type::is_eof(t.sputbackc(c)); + } +}; + +template<> +struct read_device_impl { + template + static typename int_type_of::type + get(T& t) + { // gcc 2.95 needs namespace qualification for char_traits. + typedef typename char_type_of::type char_type; + typedef iostreams::char_traits traits_type; + char_type c; + std::streamsize amt; + return (amt = t.read(&c, 1)) == 1 ? + traits_type::to_int_type(c) : + amt == -1 ? + traits_type::eof() : + traits_type::would_block(); + } + + template + static std::streamsize + read(T& t, typename char_type_of::type* s, std::streamsize n) + { return t.read(s, n); } + + template + static bool putback(T& t, typename char_type_of::type c) + { // T must be Peekable. + return t.putback(c); + } +}; + +//------------------Definition of read_filter_impl----------------------------// + +template +struct read_filter_impl + : mpl::if_< + detail::is_custom, + operations, + read_filter_impl< + BOOST_DEDUCED_TYPENAME + detail::dispatch< + T, multichar_tag, any_tag + >::type + > + >::type + { }; + +template<> +struct read_filter_impl { + template + static std::streamsize read + (T& t, Source& src, typename char_type_of::type* s, std::streamsize n) + { return t.read(src, s, n); } +}; + +template<> +struct read_filter_impl { + template + static std::streamsize read + (T& t, Source& src, typename char_type_of::type* s, std::streamsize n) + { // gcc 2.95 needs namespace qualification for char_traits. + typedef typename char_type_of::type char_type; + typedef iostreams::char_traits traits_type; + for (std::streamsize off = 0; off < n; ++off) { + typename traits_type::int_type c = t.get(src); + if (traits_type::is_eof(c)) + return check_eof(off); + if (traits_type::would_block(c)) + return off; + s[off] = traits_type::to_char_type(c); + } + return n; + } +}; + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#endif // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //-------------------------// + +#include + +#endif // #ifndef BOOST_IOSTREAMS_READ_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/restrict.hpp b/win32/include/boost/iostreams/restrict.hpp new file mode 100755 index 000000000..b456829c3 --- /dev/null +++ b/win32/include/boost/iostreams/restrict.hpp @@ -0,0 +1,26 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + * + * File: boost/iostreams/detail/restrict.hpp + * Date: Sun Jan 06 12:57:30 MST 2008 + * Copyright: 2008 CodeRage, LLC + 2004-2007 Jonathan Turkanis + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + * + * Defines the class template boost::iostreams::restriction and the + * overloaded function template boost::iostreams::restrict + */ + +#ifndef BOOST_IOSTREAMS_RESTRICT_HPP_INCLUDED +#define BOOST_IOSTREAMS_RESTRICT_HPP_INCLUDED + +#include +#define BOOST_IOSTREAMS_RESTRICT restrict +#include +#undef BOOST_IOSTREAMS_RESTRICT + +#endif // #ifndef BOOST_IOSTREAMS_RESTRICT_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/seek.hpp b/win32/include/boost/iostreams/seek.hpp new file mode 100755 index 000000000..7d5bc9fae --- /dev/null +++ b/win32/include/boost/iostreams/seek.hpp @@ -0,0 +1,180 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_SEEK_HPP_INCLUDED +#define BOOST_IOSTREAMS_SEEK_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // DEDUCED_TYPENAME, MSVC. +#include +#include +#include +#include // streamsize, seekdir, openmode. +#include +#include +#include +#include +#include + +// Must come last. +#include + +namespace boost { namespace iostreams { + +namespace detail { + +template +struct seek_device_impl; + +template +struct seek_filter_impl; + +} // End namespace detail. + +template +inline std::streampos +seek( T& t, stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which = BOOST_IOS::in | BOOST_IOS::out ) +{ + using namespace detail; + return seek_device_impl::seek(detail::unwrap(t), off, way, which); +} + +template +inline std::streampos +seek( T& t, Device& dev, stream_offset off, BOOST_IOS::seekdir way, + BOOST_IOS::openmode which = BOOST_IOS::in | BOOST_IOS::out ) +{ + using namespace detail; + return seek_filter_impl::seek(detail::unwrap(t), dev, off, way, which); +} + +namespace detail { + +//------------------Definition of seek_device_impl----------------------------// + +template +struct seek_device_impl + : mpl::if_< + is_custom, + operations, + seek_device_impl< + BOOST_DEDUCED_TYPENAME + dispatch< + T, iostream_tag, istream_tag, ostream_tag, + streambuf_tag, two_head, any_tag + >::type + > + >::type + { }; + +struct seek_impl_basic_ios { + template + static std::streampos seek( T& t, stream_offset off, + BOOST_IOS::seekdir way, + BOOST_IOS::openmode which ) + { + if ( way == BOOST_IOS::beg && + ( off < integer_traits::const_min || + off > integer_traits::const_max ) ) + { + return t.rdbuf()->pubseekpos(offset_to_position(off)); + } else { + return t.rdbuf()->pubseekoff(off, way, which); + } + } +}; + +template<> +struct seek_device_impl : seek_impl_basic_ios { }; + +template<> +struct seek_device_impl : seek_impl_basic_ios { }; + +template<> +struct seek_device_impl : seek_impl_basic_ios { }; + +template<> +struct seek_device_impl { + template + static std::streampos seek( T& t, stream_offset off, + BOOST_IOS::seekdir way, + BOOST_IOS::openmode which ) + { + if ( way == BOOST_IOS::beg && + ( off < integer_traits::const_min || + off > integer_traits::const_max ) ) + { + return t.BOOST_IOSTREAMS_PUBSEEKPOS(offset_to_position(off)); + } else { + return t.BOOST_IOSTREAMS_PUBSEEKOFF(off, way, which); + } + } +}; + +template<> +struct seek_device_impl { + template + static std::streampos seek( T& t, stream_offset off, + BOOST_IOS::seekdir way, + BOOST_IOS::openmode which ) + { return t.seek(off, way, which); } +}; + +template<> +struct seek_device_impl { + template + static std::streampos seek( T& t, stream_offset off, + BOOST_IOS::seekdir way, + BOOST_IOS::openmode ) + { return t.seek(off, way); } +}; + +//------------------Definition of seek_filter_impl----------------------------// + +template +struct seek_filter_impl + : mpl::if_< + is_custom, + operations, + seek_filter_impl< + BOOST_DEDUCED_TYPENAME + dispatch::type + > + >::type + { }; + +template<> +struct seek_filter_impl { + template + static std::streampos seek( T& t, Device& d, + stream_offset off, + BOOST_IOS::seekdir way, + BOOST_IOS::openmode which ) + { return t.seek(d, off, way, which); } +}; + +template<> +struct seek_filter_impl { + template + static std::streampos seek( T& t, Device& d, + stream_offset off, + BOOST_IOS::seekdir way, + BOOST_IOS::openmode ) + { return t.seek(d, off, way); } +}; + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#include + +#endif // #ifndef BOOST_IOSTREAMS_SEEK_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/skip.hpp b/win32/include/boost/iostreams/skip.hpp new file mode 100755 index 000000000..2307d6168 --- /dev/null +++ b/win32/include/boost/iostreams/skip.hpp @@ -0,0 +1,111 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// To do: handle bidirection streams and output-seekable components. + +#ifndef BOOST_IOSTREAMS_SKIP_HPP_INCLUDED +#define BOOST_IOSTREAMS_SKIP_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include // failure. +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace iostreams { + +namespace detail { + +template +void skip(Device& dev, stream_offset off, mpl::true_) +{ iostreams::seek(dev, off, BOOST_IOS::cur); } + +template +void skip(Device& dev, stream_offset off, mpl::false_) +{ // gcc 2.95 needs namespace qualification for char_traits. + typedef typename char_type_of::type char_type; + typedef iostreams::char_traits traits_type; + for (stream_offset z = 0; z < off; ) { + typename traits_type::int_type c; + if (traits_type::is_eof(c = iostreams::get(dev))) + throw BOOST_IOSTREAMS_FAILURE("bad skip offset"); + if (!traits_type::would_block(c)) + ++z; + } +} + +template +void skip( Filter& flt, Device& dev, stream_offset off, + BOOST_IOS::openmode which, mpl::true_ ) +{ boost::iostreams::seek(flt, dev, off, BOOST_IOS::cur, which); } + +template +void skip( Filter& flt, Device& dev, stream_offset off, + BOOST_IOS::openmode, mpl::false_ ) +{ + typedef typename char_type_of::type char_type; + char_type c; + for (stream_offset z = 0; z < off; ) { + std::streamsize amt; + if ((amt = iostreams::read(flt, dev, &c, 1)) == -1) + throw BOOST_IOSTREAMS_FAILURE("bad skip offset"); + if (amt == 1) + ++z; + } +} + +} // End namespace detail. + +template +void skip(Device& dev, stream_offset off) +{ + typedef typename mode_of::type mode; + typedef mpl::or_< + is_convertible, + is_convertible + > can_seek; + BOOST_STATIC_ASSERT( + (can_seek::value || is_convertible::value) + ); + detail::skip(dev, off, can_seek()); +} + +template +void skip( Filter& flt, Device& dev, stream_offset off, + BOOST_IOS::openmode which = BOOST_IOS::in | BOOST_IOS::out ) +{ + typedef typename mode_of::type filter_mode; + typedef typename mode_of::type device_mode; + typedef mpl::or_< + mpl::and_< + is_convertible, + is_convertible + >, + mpl::and_< + is_convertible, + is_convertible + > + > can_seek; + BOOST_STATIC_ASSERT( + ( can_seek::value || + is_convertible::value && + is_convertible::value ) + ); + detail::skip(flt, dev, off, which, can_seek()); +} + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_SKIP_HPP_INCLUDED //------------------------// diff --git a/win32/include/boost/iostreams/slice.hpp b/win32/include/boost/iostreams/slice.hpp new file mode 100755 index 000000000..72c9db95e --- /dev/null +++ b/win32/include/boost/iostreams/slice.hpp @@ -0,0 +1,28 @@ +/* + * 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.) + * + * See http://www.boost.org/libs/iostreams for documentation. + * + * File: boost/iostreams/detail/restrict.hpp + * Date: Sun Jan 06 12:57:30 MST 2008 + * Copyright: 2008 CodeRage, LLC + 2004-2007 Jonathan Turkanis + * Author: Jonathan Turkanis + * Contact: turkanis at coderage dot com + * + * Defines the class template boost::iostreams::restriction and the + * overloaded function template boost::iostreams::slice. + * + * This header is provided for platforms on which "restrict" is a keyword. + */ + +#ifndef BOOST_IOSTREAMS_RESTRICT_HPP_INCLUDED +#define BOOST_IOSTREAMS_RESTRICT_HPP_INCLUDED + +#include +#define BOOST_IOSTREAMS_RESTRICT slice +#include +#undef BOOST_IOSTREAMS_RESTRICT + +#endif // #ifndef BOOST_IOSTREAMS_RESTRICT_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/stream.hpp b/win32/include/boost/iostreams/stream.hpp new file mode 100755 index 000000000..e849e471f --- /dev/null +++ b/win32/include/boost/iostreams/stream.hpp @@ -0,0 +1,152 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_STREAM_HPP_INCLUDED +#define BOOST_IOSTREAMS_STREAM_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include +#include +#include +#include // standard streams. +#include +#include +#include +#include +#include + +namespace boost { namespace iostreams { namespace detail { + +template +struct stream_traits { + typedef typename char_type_of::type char_type; + typedef Tr traits_type; + typedef typename category_of::type mode; + typedef typename + iostreams::select< // Dismbiguation required for Tru64. + mpl::and_< + is_convertible, + is_convertible + >, + BOOST_IOSTREAMS_BASIC_IOSTREAM(char_type, traits_type), + is_convertible, + BOOST_IOSTREAMS_BASIC_ISTREAM(char_type, traits_type), + else_, + BOOST_IOSTREAMS_BASIC_OSTREAM(char_type, traits_type) + >::type stream_type; + typedef typename + iostreams::select< // Dismbiguation required for Tru64. + mpl::and_< + is_convertible, + is_convertible + >, + iostream_tag, + is_convertible, + istream_tag, + else_, + ostream_tag + >::type stream_tag; +}; + +// By encapsulating initialization in a base, we can define the macro +// BOOST_IOSTREAMS_DEFINE_FORWARDING_FUNCTIONS to generate constuctors +// without base member initializer lists. +template< typename Device, + typename Tr = + BOOST_IOSTREAMS_CHAR_TRAITS( + BOOST_DEDUCED_TYPENAME char_type_of::type + ), + typename Alloc = + std::allocator< + BOOST_DEDUCED_TYPENAME char_type_of::type + >, + typename Base = // VC6 Workaround. + BOOST_DEDUCED_TYPENAME + detail::stream_traits::stream_type > +class stream_base + : protected base_from_member< stream_buffer >, + public Base +{ +private: + typedef base_from_member< stream_buffer > pbase_type; + typedef typename stream_traits::stream_type stream_type; +protected: + using pbase_type::member; // Avoid warning about 'this' in initializer list. +public: + stream_base() : pbase_type(), stream_type(&member) { } +}; + +} } } // End namespaces detail, iostreams, boost. + +#ifdef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION +# include +#else + +namespace boost { namespace iostreams { + +// +// Template name: stream. +// Description: A iostream which reads from and writes to an instance of a +// designated device type. +// Template paramters: +// Device - A device type. +// Alloc - The allocator type. +// +template< typename Device, + typename Tr = + BOOST_IOSTREAMS_CHAR_TRAITS( + BOOST_DEDUCED_TYPENAME char_type_of::type + ), + typename Alloc = + std::allocator< + BOOST_DEDUCED_TYPENAME char_type_of::type + > > +struct stream : detail::stream_base { +public: + typedef typename char_type_of::type char_type; + struct category + : mode_of::type, + closable_tag, + detail::stream_traits::stream_tag + { }; + BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr) +private: + typedef typename + detail::stream_traits< + Device, Tr + >::stream_type stream_type; + typedef Device policy_type; +public: + stream() { } + BOOST_IOSTREAMS_FORWARD( stream, open_impl, Device, + BOOST_IOSTREAMS_PUSH_PARAMS, + BOOST_IOSTREAMS_PUSH_ARGS ) + bool is_open() const { return this->member.is_open(); } + void close() { this->member.close(); } + bool auto_close() const { return this->member.auto_close(); } + void set_auto_close(bool close) { this->member.set_auto_close(close); } + bool strict_sync() { return this->member.strict_sync(); } + Device& operator*() { return *this->member; } + Device* operator->() { return &*this->member; } + Device* component() { return this->member.component(); } +private: + void open_impl(const Device& dev BOOST_IOSTREAMS_PUSH_PARAMS()) // For forwarding. + { + this->clear(); + this->member.open(dev BOOST_IOSTREAMS_PUSH_ARGS()); + } +}; + +} } // End namespaces iostreams, boost. + +#endif // #ifdef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION + +#endif // #ifndef BOOST_IOSTREAMS_stream_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/stream_buffer.hpp b/win32/include/boost/iostreams/stream_buffer.hpp new file mode 100755 index 000000000..8c2ea83cc --- /dev/null +++ b/win32/include/boost/iostreams/stream_buffer.hpp @@ -0,0 +1,114 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_STREAM_BUFFER_HPP_INCLUDED +#define BOOST_IOSTREAMS_STREAM_BUFFER_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // allocator. +#include // BOOST_DEDUCED_TYPENAME. +#include +#include +#include +#include // failure, streamsize. +#include +#include +#include +#include +#include + +// Must come last. +#include // MSVC. + +namespace boost { namespace iostreams { namespace detail { + +template +struct stream_buffer_traits { + typedef typename + mpl::if_< + is_convertible< + BOOST_DEDUCED_TYPENAME category_of::type, + direct_tag + >, + direct_streambuf, + indirect_streambuf + >::type type; +}; + +} } } // End namespaces detail, iostreams, boost + +#ifdef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION +# include +#else + +namespace boost { namespace iostreams { + +template< typename T, + typename Tr = + BOOST_IOSTREAMS_CHAR_TRAITS( + BOOST_DEDUCED_TYPENAME char_type_of::type + ), + typename Alloc = + std::allocator< + BOOST_DEDUCED_TYPENAME char_type_of::type + >, + typename Mode = BOOST_DEDUCED_TYPENAME mode_of::type > +class stream_buffer + : public detail::stream_buffer_traits::type +{ +private: + BOOST_STATIC_ASSERT(( + is_convertible< + BOOST_DEDUCED_TYPENAME iostreams::category_of::type, Mode + >::value + )); + typedef typename + detail::stream_buffer_traits< + T, Tr, Alloc, Mode + >::type base_type; + typedef T policy_type; +public: + typedef typename char_type_of::type char_type; + struct category + : Mode, + closable_tag, + streambuf_tag + { }; + BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr) +public: + stream_buffer() { } + ~stream_buffer() + { + try { + if (this->is_open() && this->auto_close()) + this->close(); + } catch (...) { } + } + BOOST_IOSTREAMS_FORWARD( stream_buffer, open_impl, T, + BOOST_IOSTREAMS_PUSH_PARAMS, + BOOST_IOSTREAMS_PUSH_ARGS ) + T& operator*() { return *this->component(); } + T* operator->() { return this->component(); } +private: + void open_impl(const T& t BOOST_IOSTREAMS_PUSH_PARAMS()) + { // Used for forwarding. + if (this->is_open()) + BOOST_IOSTREAMS_FAILURE("already open"); + base_type::open(t BOOST_IOSTREAMS_PUSH_ARGS()); + } +}; + +} } // End namespaces iostreams, boost. + +#endif // #ifdef BOOST_IOSTREAMS_BROKEN_OVERLOAD_RESOLUTION + +#include // MSVC. + +#endif // #ifndef BOOST_IOSTREAMS_STREAM_BUFFER_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/tee.hpp b/win32/include/boost/iostreams/tee.hpp new file mode 100755 index 000000000..0d8c36ac3 --- /dev/null +++ b/win32/include/boost/iostreams/tee.hpp @@ -0,0 +1,173 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2005-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_TEE_HPP_INCLUDED +#define BOOST_IOSTREAMS_TEE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include +#include // BOOST_DEDUCE_TYPENAME. +#include +#include +#include +#include +#include +#include // call_close_all +#include +#include +#include +#include +#include +#include + +namespace boost { namespace iostreams { + +// +// Template name: tee_filter. +// Template paramters: +// Device - A blocking Sink. +// +template +class tee_filter : public detail::filter_adapter { +public: + typedef typename detail::param_type::type param_type; + typedef typename char_type_of::type char_type; + struct category + : multichar_output_filter_tag, + closable_tag, + flushable_tag, + localizable_tag, + optimally_buffered_tag + { }; + + BOOST_STATIC_ASSERT(( + is_convertible< // Using mode_of causes failures on VC6-7.0. + BOOST_DEDUCED_TYPENAME iostreams::category_of::type, output + >::value + )); + + explicit tee_filter(param_type dev) + : detail::filter_adapter(dev) + { } + + template + std::streamsize write(Sink& snk, const char_type* s, std::streamsize n) + { + std::streamsize result = iostreams::write(snk, s, n); + std::streamsize result2 = iostreams::write(this->component(), s, result); + (void) result2; // Suppress 'unused variable' warning. + assert(result == result2); + return result; + } + + template + void close(Next&) + { + detail::close_all(this->component()); + } + + template + bool flush(Sink& snk) + { + bool r1 = iostreams::flush(snk); + bool r2 = iostreams::flush(this->component()); + return r1 && r2; + } +}; +BOOST_IOSTREAMS_PIPABLE(tee_filter, 1) + +// +// Template name: tee_device. +// Template paramters: +// Sink1 - A blocking Sink. +// Sink2 - A blocking Sink. +// +template +class tee_device { +public: + typedef typename detail::param_type::type param_type1; + typedef typename detail::param_type::type param_type2; + typedef typename detail::value_type::type value_type1; + typedef typename detail::value_type::type value_type2; + typedef typename char_type_of::type char_type; + BOOST_STATIC_ASSERT(( + is_same< + char_type, + BOOST_DEDUCED_TYPENAME char_type_of::type + >::value + )); + BOOST_STATIC_ASSERT(( + is_convertible< // Using mode_of causes failures on VC6-7.0. + BOOST_DEDUCED_TYPENAME iostreams::category_of::type, output + >::value + )); + BOOST_STATIC_ASSERT(( + is_convertible< // Using mode_of causes failures on VC6-7.0. + BOOST_DEDUCED_TYPENAME iostreams::category_of::type, output + >::value + )); + struct category + : output, + device_tag, + closable_tag, + flushable_tag, + localizable_tag, + optimally_buffered_tag + { }; + tee_device(param_type1 sink1, param_type2 sink2) + : sink1_(sink1), sink2_(sink2) + { } + std::streamsize write(const char_type* s, std::streamsize n) + { + std::streamsize result1 = iostreams::write(sink1_, s, n); + std::streamsize result2 = iostreams::write(sink2_, s, n); + (void) result1; // Suppress 'unused variable' warning. + (void) result2; + assert(result1 == n && result2 == n); + return n; + } + void close() + { + detail::execute_all( detail::call_close_all(sink1_), + detail::call_close_all(sink2_) ); + } + bool flush() + { + bool r1 = iostreams::flush(sink1_); + bool r2 = iostreams::flush(sink2_); + return r1 && r2; + } + template + void imbue(const Locale& loc) + { + iostreams::imbue(sink1_, loc); + iostreams::imbue(sink2_, loc); + } + std::streamsize optimal_buffer_size() const + { + return (std::max) ( iostreams::optimal_buffer_size(sink1_), + iostreams::optimal_buffer_size(sink2_) ); + } +private: + value_type1 sink1_; + value_type2 sink2_; +}; + +template +tee_filter tee(const Sink& snk) +{ return tee_filter(snk); } + +template +tee_device tee(const Sink1& sink1, const Sink2& sink2) +{ return tee_device(sink1, sink2); } + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_TEE_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/traits.hpp b/win32/include/boost/iostreams/traits.hpp new file mode 100755 index 000000000..47a584dac --- /dev/null +++ b/win32/include/boost/iostreams/traits.hpp @@ -0,0 +1,364 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// +// Contains metafunctions char_type_of, category_of and mode_of used for +// deducing the i/o category and i/o mode of a model of Filter or Device. +// +// Also contains several utility metafunctions, functions and macros. +// + +#ifndef BOOST_IOSTREAMS_IO_TRAITS_HPP_INCLUDED +#define BOOST_IOSTREAMS_IO_TRAITS_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // stream types, char_traits. +#include // partial spec, deduced typename. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +# include +# include +#endif // #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +#include + +namespace boost { namespace iostreams { + +//----------Definitions of predicates for streams and stream buffers----------// + +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //--------------------------------// + +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_istream, std::basic_istream, 2) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_ostream, std::basic_ostream, 2) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_iostream, std::basic_iostream, 2) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_streambuf, std::basic_streambuf, 2) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_ifstream, std::basic_ifstream, 2) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_ofstream, std::basic_ofstream, 2) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_fstream, std::basic_fstream, 2) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_filebuf, std::basic_filebuf, 2) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_istringstream, std::basic_istringstream, 3) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_ostringstream, std::basic_ostringstream, 3) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_stringstream, std::basic_stringstream, 3) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_stringbuf, std::basic_stringbuf, 3) + +#else // #ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //-----------------------// + +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_istream, std::istream, 0) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_ostream, std::ostream, 0) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_iostream, std::iostream, 0) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_streambuf, std::streambuf, 0) + +#endif // #ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //----------------------// + +template +struct is_std_io + : mpl::or_< is_istream, is_ostream, is_streambuf > + { }; + +template +struct is_std_file_device + : mpl::or_< + is_ifstream, + is_ofstream, + is_fstream, + is_filebuf + > + { }; + +template +struct is_std_string_device + : mpl::or_< + is_istringstream, + is_ostringstream, + is_stringstream, + is_stringbuf + > + { }; + +template +struct stream; + +template +class stream_buffer; + +template< typename Mode, typename Ch, typename Tr, + typename Alloc, typename Access > +class filtering_stream; + +template< typename Mode, typename Ch, typename Tr, + typename Alloc, typename Access > +class wfiltering_stream; + +template< typename Mode, typename Ch, typename Tr, + typename Alloc, typename Access > +class filtering_streambuf; + +template< typename Mode, typename Ch, typename Tr, + typename Alloc, typename Access > +class filtering_wstreambuf; + +namespace detail { + +template +class linked_streambuf; + +BOOST_IOSTREAMS_BOOL_TRAIT_DEF( is_boost_stream, + boost::iostreams::stream, + 3 ) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF( is_boost_stream_buffer, + boost::iostreams::stream_buffer, + 4 ) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF( is_filtering_stream_impl, + boost::iostreams::filtering_stream, + 5 ) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF( is_filtering_wstream_impl, + boost::iostreams::wfiltering_stream, + 5 ) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF( is_filtering_streambuf_impl, + boost::iostreams::filtering_streambuf, + 5 ) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF( is_filtering_wstreambuf_impl, + boost::iostreams::filtering_wstreambuf, + 5 ) +BOOST_IOSTREAMS_BOOL_TRAIT_DEF(is_linked, linked_streambuf, 2) + +template +struct is_filtering_stream + : mpl::or_< + is_filtering_stream_impl, + is_filtering_wstream_impl + > + { }; + +template +struct is_filtering_streambuf + : mpl::or_< + is_filtering_streambuf_impl, + is_filtering_wstreambuf_impl + > + { }; + +template +struct is_boost + : mpl::or_< + is_boost_stream, + is_boost_stream_buffer, + is_filtering_stream, + is_filtering_streambuf + > + { }; + +} // End namespace detail. + +//------------------Definitions of char_type_of-------------------------------// + +namespace detail { + +template +struct member_char_type { typedef typename T::char_type type; }; + +} // End namespace detail. + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION //---------------------------// +# ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //-------------------------------// + +template +struct char_type_of + : detail::member_char_type< + typename detail::unwrapped_type::type + > + { }; + +# else // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //---------------------// + +template +struct char_type_of { + typedef typename detail::unwrapped_type::type U; + typedef typename + mpl::eval_if< + is_std_io, + mpl::identity, + detail::member_char_type + >::type type; +}; + +# endif // # ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES //--------------------// + +template +struct char_type_of< iterator_range > { + typedef typename iterator_value::type type; +}; + +#else // #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION //------------------// + +template +struct char_type_of { + template + struct get_value_type { + #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + typedef typename range_value::type type; + #endif // #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + }; + typedef typename + mpl::eval_if< + is_iterator_range, + get_value_type, + detail::member_char_type< + BOOST_DEDUCED_TYPENAME detail::unwrapped_type::type + > + >::type type; +}; + +#endif // #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION //-----------------// + +//------------------Definitions of category_of--------------------------------// + +namespace detail { + +template +struct member_category { typedef typename T::category type; }; + +} // End namespace detail. + +template +struct category_of { + template + struct member_category { + typedef typename U::category type; + }; + typedef typename detail::unwrapped_type::type U; + typedef typename + mpl::eval_if< + mpl::and_< + is_std_io, + mpl::not_< detail::is_boost > + >, + iostreams::select< // Disambiguation for Tru64 + is_filebuf, filebuf_tag, + is_ifstream, ifstream_tag, + is_ofstream, ofstream_tag, + is_fstream, fstream_tag, + is_stringbuf, stringbuf_tag, + is_istringstream, istringstream_tag, + is_ostringstream, ostringstream_tag, + is_stringstream, stringstream_tag, + is_streambuf, generic_streambuf_tag, + is_iostream, generic_iostream_tag, + is_istream, generic_istream_tag, + is_ostream, generic_ostream_tag + >, + detail::member_category + >::type type; +}; + +//------------------Definition of get_category--------------------------------// + +// +// Returns an object of type category_of::type. +// +template +inline typename category_of::type get_category(const T&) +{ typedef typename category_of::type category; return category(); } + +//------------------Definition of int_type_of---------------------------------// + +template +struct int_type_of { +#ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES + typedef std::char_traits< + BOOST_DEDUCED_TYPENAME char_type_of::type + > traits_type; + typedef typename traits_type::int_type type; +#else + typedef int type; +#endif +}; + +//------------------Definition of mode----------------------------------------// + +namespace detail { + +template struct io_mode_impl; + +#define BOOST_IOSTREAMS_MODE_HELPER(tag_, id_) \ + case_ io_mode_impl_helper(tag_); \ + template<> struct io_mode_impl { typedef tag_ type; }; \ + /**/ +BOOST_IOSTREAMS_MODE_HELPER(input, 1) +BOOST_IOSTREAMS_MODE_HELPER(output, 2) +BOOST_IOSTREAMS_MODE_HELPER(bidirectional, 3) +BOOST_IOSTREAMS_MODE_HELPER(input_seekable, 4) +BOOST_IOSTREAMS_MODE_HELPER(output_seekable, 5) +BOOST_IOSTREAMS_MODE_HELPER(seekable, 6) +BOOST_IOSTREAMS_MODE_HELPER(dual_seekable, 7) +BOOST_IOSTREAMS_MODE_HELPER(bidirectional_seekable, 8) +BOOST_IOSTREAMS_MODE_HELPER(dual_use, 9) +#undef BOOST_IOSTREAMS_MODE_HELPER + +template +struct io_mode_id { + typedef typename category_of::type category; + BOOST_SELECT_BY_SIZE(int, value, detail::io_mode_impl_helper(category())); +}; + +} // End namespace detail. + +template // Borland 5.6.4 requires this circumlocution. +struct mode_of : detail::io_mode_impl< detail::io_mode_id::value > { }; + +//------------------Definition of is_device, is_filter and is_direct----------// + +namespace detail { + +template +struct has_trait_impl { + typedef typename category_of::type category; + BOOST_STATIC_CONSTANT(bool, value = (is_convertible::value)); +}; + +template +struct has_trait + : mpl::bool_::value> + { }; + +} // End namespace detail. + +template +struct is_device : detail::has_trait { }; + +template +struct is_filter : detail::has_trait { }; + +template +struct is_direct : detail::has_trait { }; + +//------------------Definition of BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS----------// + +#define BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr) \ + typedef Tr traits_type; \ + typedef typename traits_type::int_type int_type; \ + typedef typename traits_type::off_type off_type; \ + typedef typename traits_type::pos_type pos_type; \ + /**/ + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_IO_TRAITS_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/traits_fwd.hpp b/win32/include/boost/iostreams/traits_fwd.hpp new file mode 100755 index 000000000..57ba5c215 --- /dev/null +++ b/win32/include/boost/iostreams/traits_fwd.hpp @@ -0,0 +1,111 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +// Forward declarations of templates defined in traits.hpp. + +#ifndef BOOST_IOSTREAMS_IO_TRAITS_FWD_HPP_INCLUDED +#define BOOST_IOSTREAMS_IO_TRAITS_FWD_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // stream types, char_traits. + +namespace boost { namespace iostreams { + +template +struct is_istream; + +template +struct is_ostream; + +template +struct is_iostream; + +template +struct is_streambuf; + +template +struct is_istringstream; + +template +struct is_ostringstream; + +template +struct is_stringstream; + +template +struct is_stringbuf; + +template +struct is_ifstream; + +template +struct is_ofstream; + +template +struct is_fstream; + +template +struct is_filebuf; + +template +struct is_std_io; + +template +struct is_std_file_device; + +template +struct is_std_string_device; + +template +struct char_type_of; + +template +struct category_of; + +template +struct int_type_of; + +template +struct mode_of; + +template +struct is_device; + +template +struct is_filter; + +template +struct is_direct; + +namespace detail { + +template +struct is_boost_stream; + +template +struct is_boost_stream_buffer; + +template +struct is_filtering_stream; + +template +struct is_filtering_streambuf; + +template +struct is_linked; + +template +struct is_boost; + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#endif // #ifndef BOOST_IOSTREAMS_IO_TRAITS_FWD_HPP_INCLUDED diff --git a/win32/include/boost/iostreams/write.hpp b/win32/include/boost/iostreams/write.hpp new file mode 100755 index 000000000..6097e5ee4 --- /dev/null +++ b/win32/include/boost/iostreams/write.hpp @@ -0,0 +1,171 @@ +// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) +// (C) Copyright 2003-2007 Jonathan Turkanis +// 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.) + +// See http://www.boost.org/libs/iostreams for documentation. + +#ifndef BOOST_IOSTREAMS_WRITE_HPP_INCLUDED +#define BOOST_IOSTREAMS_WRITE_HPP_INCLUDED + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +#include // DEDUCED_TYPENAME, MSVC. +#include +#include +#include +#include +#include // streamsize. +#include +#include +#include +#include +#include + +// Must come last. +#include + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //-----------------------------------// +# include +#else // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //--------------------------// + +namespace boost { namespace iostreams { + +namespace detail { + +template +struct write_device_impl; + +template +struct write_filter_impl; + +} // End namespace detail. + +template +bool put(T& t, typename char_type_of::type c) +{ return detail::write_device_impl::put(detail::unwrap(t), c); } + +template +inline std::streamsize write + (T& t, const typename char_type_of::type* s, std::streamsize n) +{ return detail::write_device_impl::write(detail::unwrap(t), s, n); } + +template +inline std::streamsize +write( T& t, Sink& snk, const typename char_type_of::type* s, + std::streamsize n ) +{ return detail::write_filter_impl::write(detail::unwrap(t), snk, s, n); } + +namespace detail { + +//------------------Definition of write_device_impl---------------------------// + +template +struct write_device_impl + : mpl::if_< + is_custom, + operations, + write_device_impl< + BOOST_DEDUCED_TYPENAME + dispatch< + T, ostream_tag, streambuf_tag, output + >::type + > + >::type + { }; + +template<> +struct write_device_impl { + template + static bool put(T& t, typename char_type_of::type c) + { + typedef typename char_type_of::type char_type; + typedef BOOST_IOSTREAMS_CHAR_TRAITS(char_type) traits_type; + return !traits_type::eq_int_type( t.rdbuf()->s.sputc(), + traits_type::eof() ); + } + + template + static std::streamsize write + (T& t, const typename char_type_of::type* s, std::streamsize n) + { return t.rdbuf()->sputn(s, n); } +}; + +template<> +struct write_device_impl { + template + static bool put(T& t, typename char_type_of::type c) + { + typedef typename char_type_of::type char_type; + typedef BOOST_IOSTREAMS_CHAR_TRAITS(char_type) traits_type; + return !traits_type::eq_int_type(t.sputc(c), traits_type::eof()); + } + + template + static std::streamsize write + (T& t, const typename char_type_of::type* s, std::streamsize n) + { return t.sputn(s, n); } +}; + +template<> +struct write_device_impl { + template + static bool put(T& t, typename char_type_of::type c) + { return t.write(&c, 1) == 1; } + + template + static std::streamsize + write(T& t, const typename char_type_of::type* s, std::streamsize n) + { return t.write(s, n); } +}; + +//------------------Definition of write_filter_impl---------------------------// + +template +struct write_filter_impl + : mpl::if_< + is_custom, + operations, + write_filter_impl< + BOOST_DEDUCED_TYPENAME + dispatch< + T, multichar_tag, any_tag + >::type + > + >::type + { }; + +template<> +struct write_filter_impl { + template + static std::streamsize + write( T& t, Sink& snk, const typename char_type_of::type* s, + std::streamsize n ) + { return t.write(snk, s, n); } +}; + +template<> +struct write_filter_impl { + template + static std::streamsize + write( T& t, Sink& snk, const typename char_type_of::type* s, + std::streamsize n ) + { + for (std::streamsize off = 0; off < n; ++off) + if (!t.put(snk, s[off])) + return off; + return n; + } +}; + +} // End namespace detail. + +} } // End namespaces iostreams, boost. + +#endif // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //-------------------------// + +#include + +#endif // #ifndef BOOST_IOSTREAMS_WRITE_HPP_INCLUDED diff --git a/win32/include/boost/is_placeholder.hpp b/win32/include/boost/is_placeholder.hpp new file mode 100755 index 000000000..cd061cbe2 --- /dev/null +++ b/win32/include/boost/is_placeholder.hpp @@ -0,0 +1,31 @@ +#ifndef BOOST_IS_PLACEHOLDER_HPP_INCLUDED +#define BOOST_IS_PLACEHOLDER_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined( _MSC_VER ) && ( _MSC_VER >= 1020 ) +# pragma once +#endif + + +// is_placeholder.hpp - TR1 is_placeholder metafunction +// +// Copyright (c) 2006 Peter Dimov +// +// 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 + + +namespace boost +{ + +template< class T > struct is_placeholder +{ + enum _vt { value = 0 }; +}; + +} // namespace boost + +#endif // #ifndef BOOST_IS_PLACEHOLDER_HPP_INCLUDED diff --git a/win32/include/boost/iterator.hpp b/win32/include/boost/iterator.hpp new file mode 100755 index 000000000..8d54784f4 --- /dev/null +++ b/win32/include/boost/iterator.hpp @@ -0,0 +1,59 @@ +// interator.hpp workarounds for non-conforming standard libraries ---------// + +// (C) Copyright Beman Dawes 2000. 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) + +// See http://www.boost.org/libs/utility for documentation. + +// Revision History +// 12 Jan 01 added for std::ptrdiff_t (Jens Maurer) +// 28 Jun 00 Workarounds to deal with known MSVC bugs (David Abrahams) +// 26 Jun 00 Initial version (Jeremy Siek) + +#ifndef BOOST_ITERATOR_HPP +#define BOOST_ITERATOR_HPP + +#include +#include // std::ptrdiff_t +#include + +namespace boost +{ +# if defined(BOOST_NO_STD_ITERATOR) && !defined(BOOST_MSVC_STD_ITERATOR) + template + struct iterator + { + typedef T value_type; + typedef Distance difference_type; + typedef Pointer pointer; + typedef Reference reference; + typedef Category iterator_category; + }; +# else + + // declare iterator_base in namespace detail to work around MSVC bugs which + // prevent derivation from an identically-named class in a different namespace. + namespace detail { + template +# if !defined(BOOST_MSVC_STD_ITERATOR) + struct iterator_base : std::iterator {}; +# else + struct iterator_base : std::iterator + { + typedef Reference reference; + typedef Pointer pointer; + typedef Distance difference_type; + }; +# endif + } + + template + struct iterator : boost::detail::iterator_base {}; +# endif +} // namespace boost + +#endif // BOOST_ITERATOR_HPP diff --git a/win32/include/boost/iterator/counting_iterator.hpp b/win32/include/boost/iterator/counting_iterator.hpp new file mode 100755 index 000000000..09fc5a718 --- /dev/null +++ b/win32/include/boost/iterator/counting_iterator.hpp @@ -0,0 +1,215 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef COUNTING_ITERATOR_DWA200348_HPP +# define COUNTING_ITERATOR_DWA200348_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { + +template < + class Incrementable + , class CategoryOrTraversal + , class Difference +> +class counting_iterator; + +namespace detail +{ + // Try to detect numeric types at compile time in ways compatible + // with the limitations of the compiler and library. + template + struct is_numeric_impl + { + // For a while, this wasn't true, but we rely on it below. This is a regression assert. + BOOST_STATIC_ASSERT(::boost::is_integral::value); + +# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + + BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_specialized); + +# else + +# if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + BOOST_STATIC_CONSTANT( + bool, value = ( + boost::is_convertible::value + && boost::is_convertible::value + )); +# else + BOOST_STATIC_CONSTANT(bool, value = ::boost::is_arithmetic::value); +# endif + +# endif + }; + + template + struct is_numeric + : mpl::bool_<(::boost::detail::is_numeric_impl::value)> + {}; + +# if defined(BOOST_HAS_LONG_LONG) + template <> + struct is_numeric< ::boost::long_long_type> + : mpl::true_ {}; + + template <> + struct is_numeric< ::boost::ulong_long_type> + : mpl::true_ {}; +# endif + + // Some compilers fail to have a numeric_limits specialization + template <> + struct is_numeric + : mpl::true_ {}; + + template + struct numeric_difference + { + typedef typename boost::detail::numeric_traits::difference_type type; + }; + + BOOST_STATIC_ASSERT(is_numeric::value); + + template + struct counting_iterator_base + { + typedef typename detail::ia_dflt_help< + CategoryOrTraversal + , mpl::eval_if< + is_numeric + , mpl::identity + , iterator_traversal + > + >::type traversal; + + typedef typename detail::ia_dflt_help< + Difference + , mpl::eval_if< + is_numeric + , numeric_difference + , iterator_difference + > + >::type difference; + + typedef iterator_adaptor< + counting_iterator // self + , Incrementable // Base + , Incrementable // Value +# ifndef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY + const // MSVC won't strip this. Instead we enable Thomas' + // criterion (see boost/iterator/detail/facade_iterator_category.hpp) +# endif + , traversal + , Incrementable const& // reference + , difference + > type; + }; + + // Template class distance_policy_select -- choose a policy for computing the + // distance between counting_iterators at compile-time based on whether or not + // the iterator wraps an integer or an iterator, using "poor man's partial + // specialization". + + template struct distance_policy_select; + + // A policy for wrapped iterators + template + struct iterator_distance + { + static Difference distance(Incrementable1 x, Incrementable2 y) + { + return y - x; + } + }; + + // A policy for wrapped numbers + template + struct number_distance + { + static Difference distance(Incrementable1 x, Incrementable2 y) + { + return numeric_distance(x, y); + } + }; +} + +template < + class Incrementable + , class CategoryOrTraversal = use_default + , class Difference = use_default +> +class counting_iterator + : public detail::counting_iterator_base< + Incrementable, CategoryOrTraversal, Difference + >::type +{ + typedef typename detail::counting_iterator_base< + Incrementable, CategoryOrTraversal, Difference + >::type super_t; + + friend class iterator_core_access; + + public: + typedef typename super_t::difference_type difference_type; + + counting_iterator() { } + + counting_iterator(counting_iterator const& rhs) : super_t(rhs.base()) {} + + counting_iterator(Incrementable x) + : super_t(x) + { + } + +# if 0 + template + counting_iterator( + counting_iterator const& t + , typename enable_if_convertible::type* = 0 + ) + : super_t(t.base()) + {} +# endif + + private: + + typename super_t::reference dereference() const + { + return this->base_reference(); + } + + template + difference_type + distance_to(counting_iterator const& y) const + { + typedef typename mpl::if_< + detail::is_numeric + , detail::number_distance + , detail::iterator_distance + >::type d; + + return d::distance(this->base(), y.base()); + } +}; + +// Manufacture a counting iterator for an arbitrary incrementable type +template +inline counting_iterator +make_counting_iterator(Incrementable x) +{ + typedef counting_iterator result_t; + return result_t(x); +} + + +} // namespace boost::iterator + +#endif // COUNTING_ITERATOR_DWA200348_HPP diff --git a/win32/include/boost/iterator/detail/any_conversion_eater.hpp b/win32/include/boost/iterator/detail/any_conversion_eater.hpp new file mode 100755 index 000000000..ce9e04323 --- /dev/null +++ b/win32/include/boost/iterator/detail/any_conversion_eater.hpp @@ -0,0 +1,19 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef ANY_CONVERSION_EATER_DWA20031117_HPP +# define ANY_CONVERSION_EATER_DWA20031117_HPP + +namespace boost { namespace detail { + +// This type can be used in traits to "eat" up the one user-defined +// implicit conversion allowed. +struct any_conversion_eater +{ + template + any_conversion_eater(T const&); +}; + +}} // namespace boost::detail + +#endif // ANY_CONVERSION_EATER_DWA20031117_HPP diff --git a/win32/include/boost/iterator/detail/config_def.hpp b/win32/include/boost/iterator/detail/config_def.hpp new file mode 100755 index 000000000..2c34701fc --- /dev/null +++ b/win32/include/boost/iterator/detail/config_def.hpp @@ -0,0 +1,137 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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) + +// no include guard multiple inclusion intended + +// +// This is a temporary workaround until the bulk of this is +// available in boost config. +// 23/02/03 thw +// + +#include // for prior +#include + +#ifdef BOOST_ITERATOR_CONFIG_DEF +# error you have nested config_def #inclusion. +#else +# define BOOST_ITERATOR_CONFIG_DEF +#endif + +// We enable this always now. Otherwise, the simple case in +// libs/iterator/test/constant_iterator_arrow.cpp fails to compile +// because the operator-> return is improperly deduced as a non-const +// pointer. +#if 1 || defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531)) + +// Recall that in general, compilers without partial specialization +// can't strip constness. Consider counting_iterator, which normally +// passes a const Value to iterator_facade. As a result, any code +// which makes a std::vector of the iterator's value_type will fail +// when its allocator declares functions overloaded on reference and +// const_reference (the same type). +// +// Furthermore, Borland 5.5.1 drops constness in enough ways that we +// end up using a proxy for operator[] when we otherwise shouldn't. +// Using reference constness gives it an extra hint that it can +// return the value_type from operator[] directly, but is not +// strictly necessary. Not sure how best to resolve this one. + +# define BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY 1 + +#endif + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531)) \ + || (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER)) \ + || BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) \ + || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) + +# define BOOST_NO_LVALUE_RETURN_DETECTION + +# if 0 // test code + struct v {}; + + typedef char (&no)[3]; + + template + no foo(T const&, ...); + + template + char foo(T&, int); + + + struct value_iterator + { + v operator*() const; + }; + + template + struct lvalue_deref_helper + { + static T& x; + enum { value = (sizeof(foo(*x,0)) == 1) }; + }; + + int z2[(lvalue_deref_helper::value == 1) ? 1 : -1]; + int z[(lvalue_deref_helper::value) == 1 ? -1 : 1 ]; +# endif + +#endif + +#if BOOST_WORKAROUND(__MWERKS__, <=0x2407) +# define BOOST_NO_IS_CONVERTIBLE // "is_convertible doesn't work for simple types" +#endif + +#if BOOST_WORKAROUND(__GNUC__, == 2) \ + || BOOST_WORKAROUND(__GNUC__, == 3) && BOOST_WORKAROUND(__GNUC_MINOR__, < 4) && !defined(__EDG_VERSION__) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) +# define BOOST_NO_IS_CONVERTIBLE_TEMPLATE // The following program fails to compile: + +# if 0 // test code + #include + template + struct foo + { + foo(T); + + template + foo(foo const& other) : p(other.p) { } + + T p; + }; + + bool x = boost::is_convertible, foo >::value; +# endif + +#endif + + +#if !defined(BOOST_MSVC) && (defined(BOOST_NO_SFINAE) || defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_IS_CONVERTIBLE_TEMPLATE)) +# define BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY +#endif + +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) +# define BOOST_ARG_DEPENDENT_TYPENAME typename +# else +# define BOOST_ARG_DEPENDENT_TYPENAME +# endif + +# if BOOST_WORKAROUND(__GNUC__, == 2) && BOOST_WORKAROUND(__GNUC_MINOR__, BOOST_TESTED_AT(95)) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + +// GCC-2.95 eagerly instantiates templated constructors and conversion +// operators in convertibility checks, causing premature errors. +// +// Borland's problems are harder to diagnose due to lack of an +// instantiation stack backtrace. They may be due in part to the fact +// that it drops cv-qualification willy-nilly in templates. +# define BOOST_NO_ONE_WAY_ITERATOR_INTEROP +# endif + +// no include guard; multiple inclusion intended diff --git a/win32/include/boost/iterator/detail/config_undef.hpp b/win32/include/boost/iterator/detail/config_undef.hpp new file mode 100755 index 000000000..9b0477569 --- /dev/null +++ b/win32/include/boost/iterator/detail/config_undef.hpp @@ -0,0 +1,25 @@ +// (C) Copyright Thomas Witt 2002. +// 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) + +// no include guard multiple inclusion intended + +// +// This is a temporary workaround until the bulk of this is +// available in boost config. +// 23/02/03 thw +// + +#undef BOOST_NO_IS_CONVERTIBLE +#undef BOOST_NO_IS_CONVERTIBLE_TEMPLATE +#undef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY +#undef BOOST_ARG_DEPENDENT_TYPENAME +#undef BOOST_NO_LVALUE_RETURN_DETECTION +#undef BOOST_NO_ONE_WAY_ITERATOR_INTEROP + +#ifdef BOOST_ITERATOR_CONFIG_DEF +# undef BOOST_ITERATOR_CONFIG_DEF +#else +# error missing or nested #include config_def +#endif diff --git a/win32/include/boost/iterator/detail/enable_if.hpp b/win32/include/boost/iterator/detail/enable_if.hpp new file mode 100755 index 000000000..2c261f87d --- /dev/null +++ b/win32/include/boost/iterator/detail/enable_if.hpp @@ -0,0 +1,86 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_ENABLE_IF_23022003THW_HPP +#define BOOST_ENABLE_IF_23022003THW_HPP + +#include +#include + +#include + +// +// Boost iterators uses its own enable_if cause we need +// special semantics for deficient compilers. +// 23/02/03 thw +// + +namespace boost +{ + + namespace iterators + { + // + // Base machinery for all kinds of enable if + // + template + struct enabled + { + template + struct base + { + typedef T type; + }; + }; + + // + // For compilers that don't support "Substitution Failure Is Not An Error" + // enable_if falls back to always enabled. See comments + // on operator implementation for consequences. + // + template<> + struct enabled + { + template + struct base + { +#ifdef BOOST_NO_SFINAE + + typedef T type; + + // This way to do it would give a nice error message containing + // invalid overload, but has the big disadvantage that + // there is no reference to user code in the error message. + // + // struct invalid_overload; + // typedef invalid_overload type; + // +#endif + }; + }; + + + template + struct enable_if +# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE) + : enabled<(Cond::value)>::template base +# else + : mpl::identity +# endif + { +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + typedef Return type; +# endif + }; + + } // namespace iterators + +} // namespace boost + +#include + +#endif // BOOST_ENABLE_IF_23022003THW_HPP diff --git a/win32/include/boost/iterator/detail/facade_iterator_category.hpp b/win32/include/boost/iterator/detail/facade_iterator_category.hpp new file mode 100755 index 000000000..2c528d818 --- /dev/null +++ b/win32/include/boost/iterator/detail/facade_iterator_category.hpp @@ -0,0 +1,200 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef FACADE_ITERATOR_CATEGORY_DWA20031118_HPP +# define FACADE_ITERATOR_CATEGORY_DWA20031118_HPP + +# include + +# include // used in iterator_tag inheritance logic +# include +# include +# include +# include +# include + +# include +# include +# include +# include + +# include + +# include // try to keep this last + +# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY +# include +# endif + +// +// iterator_category deduction for iterator_facade +// + +// forward declaration +namespace boost { struct use_default; } + +namespace boost { namespace detail { + +struct input_output_iterator_tag + : std::input_iterator_tag +{ + // Using inheritance for only input_iterator_tag helps to avoid + // ambiguities when a stdlib implementation dispatches on a + // function which is overloaded on both input_iterator_tag and + // output_iterator_tag, as STLPort does, in its __valid_range + // function. I claim it's better to avoid the ambiguity in these + // cases. + operator std::output_iterator_tag() const + { + return std::output_iterator_tag(); + } +}; + +// +// True iff the user has explicitly disabled writability of this +// iterator. Pass the iterator_facade's Value parameter and its +// nested ::reference type. +// +template +struct iterator_writability_disabled +# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic? + : mpl::or_< + is_const + , boost::detail::indirect_traits::is_reference_to_const + , is_const + > +# else + : is_const +# endif +{}; + + +// +// Convert an iterator_facade's traversal category, Value parameter, +// and ::reference type to an appropriate old-style category. +// +// If writability has been disabled per the above metafunction, the +// result will not be convertible to output_iterator_tag. +// +// Otherwise, if Traversal == single_pass_traversal_tag, the following +// conditions will result in a tag that is convertible both to +// input_iterator_tag and output_iterator_tag: +// +// 1. Reference is a reference to non-const +// 2. Reference is not a reference and is convertible to Value +// +template +struct iterator_facade_default_category + : mpl::eval_if< + mpl::and_< + is_reference + , is_convertible + > + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::if_< + is_convertible + , std::bidirectional_iterator_tag + , std::forward_iterator_tag + > + > + , typename mpl::eval_if< + mpl::and_< + is_convertible + + // check for readability + , is_convertible + > + , mpl::identity + , mpl::identity + > + > +{ +}; + +// True iff T is convertible to an old-style iterator category. +template +struct is_iterator_category + : mpl::or_< + is_convertible + , is_convertible + > +{ +}; + +template +struct is_iterator_traversal + : is_convertible +{}; + +// +// A composite iterator_category tag convertible to Category (a pure +// old-style category) and Traversal (a pure traversal tag). +// Traversal must be a strict increase of the traversal power given by +// Category. +// +template +struct iterator_category_with_traversal + : Category, Traversal +{ +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + // Make sure this isn't used to build any categories where + // convertibility to Traversal is redundant. Should just use the + // Category element in that case. + BOOST_MPL_ASSERT_NOT(( + is_convertible< + typename iterator_category_to_traversal::type + , Traversal + >)); + + BOOST_MPL_ASSERT((is_iterator_category)); + BOOST_MPL_ASSERT_NOT((is_iterator_category)); + BOOST_MPL_ASSERT_NOT((is_iterator_traversal)); +# if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) + BOOST_MPL_ASSERT((is_iterator_traversal)); +# endif +# endif +}; + +// Computes an iterator_category tag whose traversal is Traversal and +// which is appropriate for an iterator +template +struct facade_iterator_category_impl +{ +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + BOOST_MPL_ASSERT_NOT((is_iterator_category)); +# endif + + typedef typename iterator_facade_default_category< + Traversal,ValueParam,Reference + >::type category; + + typedef typename mpl::if_< + is_same< + Traversal + , typename iterator_category_to_traversal::type + > + , category + , iterator_category_with_traversal + >::type type; +}; + +// +// Compute an iterator_category for iterator_facade +// +template +struct facade_iterator_category + : mpl::eval_if< + is_iterator_category + , mpl::identity // old-style categories are fine as-is + , facade_iterator_category_impl + > +{ +}; + +}} // namespace boost::detail + +# include + +#endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP diff --git a/win32/include/boost/iterator/detail/minimum_category.hpp b/win32/include/boost/iterator/detail/minimum_category.hpp new file mode 100755 index 000000000..804f9186f --- /dev/null +++ b/win32/include/boost/iterator/detail/minimum_category.hpp @@ -0,0 +1,116 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef MINIMUM_CATEGORY_DWA20031119_HPP +# define MINIMUM_CATEGORY_DWA20031119_HPP + +# include +# include + +# include + +namespace boost { namespace detail { +// +// Returns the minimum category type or error_type +// if T1 and T2 are unrelated. +// +// For compilers not supporting is_convertible this only +// works with the new boost return and traversal category +// types. The exact boost _types_ are required. No derived types +// will work. +// +// +template +struct minimum_category_impl +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +{ + template struct apply + { + typedef T2 type; + }; + typedef void type; +} +# endif +; + +template +struct error_not_related_by_convertibility; + +template <> +struct minimum_category_impl +{ + template struct apply + { + typedef T2 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + { + typedef T1 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + { + BOOST_STATIC_ASSERT((is_same::value)); + typedef T1 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + : error_not_related_by_convertibility + { + }; +}; + +template +struct minimum_category +{ + typedef minimum_category_impl< +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) // ETI workaround + is_same::value || +# endif + ::boost::is_convertible::value + , ::boost::is_convertible::value +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) // ETI workaround + || is_same::value +# endif + > outer; + + typedef typename outer::template apply inner; + typedef typename inner::type type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2)) +}; + +template <> +struct minimum_category +{ + template + struct apply : minimum_category + {}; + + BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(2,minimum_category,(mpl::_1,mpl::_2)) +}; + +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) // ETI workaround +template <> +struct minimum_category +{ + typedef int type; +}; +# endif + +}} // namespace boost::detail + +#endif // MINIMUM_CATEGORY_DWA20031119_HPP diff --git a/win32/include/boost/iterator/filter_iterator.hpp b/win32/include/boost/iterator/filter_iterator.hpp new file mode 100755 index 000000000..84bd054d0 --- /dev/null +++ b/win32/include/boost/iterator/filter_iterator.hpp @@ -0,0 +1,135 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_FILTER_ITERATOR_23022003THW_HPP +#define BOOST_FILTER_ITERATOR_23022003THW_HPP + +#include +#include +#include + +#include +#include + +namespace boost +{ + template + class filter_iterator; + + namespace detail + { + template + struct filter_iterator_base + { + typedef iterator_adaptor< + filter_iterator + , Iterator + , use_default + , typename mpl::if_< + is_convertible< + typename iterator_traversal::type + , random_access_traversal_tag + > + , bidirectional_traversal_tag + , use_default + >::type + > type; + }; + } + + template + class filter_iterator + : public detail::filter_iterator_base::type + { + typedef typename detail::filter_iterator_base< + Predicate, Iterator + >::type super_t; + + friend class iterator_core_access; + + public: + filter_iterator() { } + + filter_iterator(Predicate f, Iterator x, Iterator end_ = Iterator()) + : super_t(x), m_predicate(f), m_end(end_) + { + satisfy_predicate(); + } + + filter_iterator(Iterator x, Iterator end_ = Iterator()) + : super_t(x), m_predicate(), m_end(end_) + { + // Pro8 is a little too aggressive about instantiating the + // body of this function. +#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + // Don't allow use of this constructor if Predicate is a + // function pointer type, since it will be 0. + BOOST_STATIC_ASSERT(is_class::value); +#endif + satisfy_predicate(); + } + + template + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::type* = 0 + ) + : super_t(t.base()), m_predicate(t.predicate()), m_end(t.end()) {} + + Predicate predicate() const { return m_predicate; } + + Iterator end() const { return m_end; } + + private: + void increment() + { + ++(this->base_reference()); + satisfy_predicate(); + } + + void decrement() + { + while(!this->m_predicate(*--(this->base_reference()))){}; + } + + void satisfy_predicate() + { + while (this->base() != this->m_end && !this->m_predicate(*this->base())) + ++(this->base_reference()); + } + + // Probably should be the initial base class so it can be + // optimized away via EBO if it is an empty class. + Predicate m_predicate; + Iterator m_end; + }; + + template + filter_iterator + make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()) + { + return filter_iterator(f,x,end); + } + + template + filter_iterator + make_filter_iterator( + typename iterators::enable_if< + is_class + , Iterator + >::type x + , Iterator end = Iterator() +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + , Predicate* = 0 +#endif + ) + { + return filter_iterator(x,end); + } + +} // namespace boost + +#endif // BOOST_FILTER_ITERATOR_23022003THW_HPP diff --git a/win32/include/boost/iterator/indirect_iterator.hpp b/win32/include/boost/iterator/indirect_iterator.hpp new file mode 100755 index 000000000..cff79a5b5 --- /dev/null +++ b/win32/include/boost/iterator/indirect_iterator.hpp @@ -0,0 +1,139 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_INDIRECT_ITERATOR_23022003THW_HPP +#define BOOST_INDIRECT_ITERATOR_23022003THW_HPP + +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#ifdef BOOST_MPL_CFG_NO_HAS_XXX +# include +# include +# include +# include +#endif + +#include // must be last #include + +namespace boost +{ + template + class indirect_iterator; + + namespace detail + { + template + struct indirect_base + { + typedef typename iterator_traits::value_type dereferenceable; + + typedef iterator_adaptor< + indirect_iterator + , Iter + , typename ia_dflt_help< + Value, pointee + >::type + , Category + , typename ia_dflt_help< + Reference + , mpl::eval_if< + is_same + , indirect_reference + , add_reference + > + >::type + , Difference + > type; + }; + + template <> + struct indirect_base {}; + } // namespace detail + + + template < + class Iterator + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class indirect_iterator + : public detail::indirect_base< + Iterator, Value, Category, Reference, Difference + >::type + { + typedef typename detail::indirect_base< + Iterator, Value, Category, Reference, Difference + >::type super_t; + + friend class iterator_core_access; + + public: + indirect_iterator() {} + + indirect_iterator(Iterator iter) + : super_t(iter) {} + + template < + class Iterator2, class Value2, class Category2 + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Category2, Reference2, Difference2 + > const& y + , typename enable_if_convertible::type* = 0 + ) + : super_t(y.base()) + {} + + private: + typename super_t::reference dereference() const + { +# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + return const_cast(**this->base()); +# else + return **this->base(); +# endif + } + }; + + template + inline + indirect_iterator make_indirect_iterator(Iter x) + { + return indirect_iterator(x); + } + + template + inline + indirect_iterator make_indirect_iterator(Iter x, Traits* = 0) + { + return indirect_iterator(x); + } + +} // namespace boost + +#include + +#endif // BOOST_INDIRECT_ITERATOR_23022003THW_HPP diff --git a/win32/include/boost/iterator/interoperable.hpp b/win32/include/boost/iterator/interoperable.hpp new file mode 100755 index 000000000..08b29c36b --- /dev/null +++ b/win32/include/boost/iterator/interoperable.hpp @@ -0,0 +1,50 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_INTEROPERABLE_23022003THW_HPP +# define BOOST_INTEROPERABLE_23022003THW_HPP + +# include +# include + +# include + +# include // must appear last + +namespace boost +{ + + // + // Meta function that determines whether two + // iterator types are considered interoperable. + // + // Two iterator types A,B are considered interoperable if either + // A is convertible to B or vice versa. + // This interoperability definition is in sync with the + // standards requirements on constant/mutable container + // iterators (23.1 [lib.container.requirements]). + // + // For compilers that don't support is_convertible + // is_interoperable gives false positives. See comments + // on operator implementation for consequences. + // + template + struct is_interoperable +# ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY + : mpl::true_ +# else + : mpl::or_< + is_convertible< A, B > + , is_convertible< B, A > > +# endif + { + }; + +} // namespace boost + +# include + +#endif // BOOST_INTEROPERABLE_23022003THW_HPP diff --git a/win32/include/boost/iterator/is_lvalue_iterator.hpp b/win32/include/boost/iterator/is_lvalue_iterator.hpp new file mode 100755 index 000000000..1db6ee432 --- /dev/null +++ b/win32/include/boost/iterator/is_lvalue_iterator.hpp @@ -0,0 +1,150 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef IS_LVALUE_ITERATOR_DWA2003112_HPP +# define IS_LVALUE_ITERATOR_DWA2003112_HPP + +#include + +#include +#include + +#include + +// should be the last #includes +#include +#include + +#ifndef BOOST_NO_IS_CONVERTIBLE + +namespace boost { + +namespace detail +{ +#ifndef BOOST_NO_LVALUE_RETURN_DETECTION + // Calling lvalue_preserver( , 0 ) returns a reference + // to the expression's result if is an lvalue, or + // not_an_lvalue() otherwise. + struct not_an_lvalue {}; + + template + T& lvalue_preserver(T&, int); + + template + not_an_lvalue lvalue_preserver(U const&, ...); + +# define BOOST_LVALUE_PRESERVER(expr) detail::lvalue_preserver(expr,0) + +#else + +# define BOOST_LVALUE_PRESERVER(expr) expr + +#endif + + // Guts of is_lvalue_iterator. Value is the iterator's value_type + // and the result is computed in the nested rebind template. + template + struct is_lvalue_iterator_impl + { + // Eat implicit conversions so we don't report true for things + // convertible to Value const& + struct conversion_eater + { + conversion_eater(Value&); + }; + + static char tester(conversion_eater, int); + static char (& tester(any_conversion_eater, ...) )[2]; + + template + struct rebind + { + static It& x; + + BOOST_STATIC_CONSTANT( + bool + , value = ( + sizeof( + is_lvalue_iterator_impl::tester( + BOOST_LVALUE_PRESERVER(*x), 0 + ) + ) == 1 + ) + ); + }; + }; + +#undef BOOST_LVALUE_PRESERVER + + // + // void specializations to handle std input and output iterators + // + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; +#endif + + // + // This level of dispatching is required for Borland. We might save + // an instantiation by removing it for others. + // + template + struct is_readable_lvalue_iterator_impl + : is_lvalue_iterator_impl< + BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits::value_type const + >::template rebind + {}; + + template + struct is_non_const_lvalue_iterator_impl + : is_lvalue_iterator_impl< + BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits::value_type + >::template rebind + {}; +} // namespace detail + +// Define the trait with full mpl lambda capability and various broken +// compiler workarounds +BOOST_TT_AUX_BOOL_TRAIT_DEF1( + is_lvalue_iterator,T,::boost::detail::is_readable_lvalue_iterator_impl::value) + +BOOST_TT_AUX_BOOL_TRAIT_DEF1( + is_non_const_lvalue_iterator,T,::boost::detail::is_non_const_lvalue_iterator_impl::value) + +} // namespace boost + +#endif + +#include +#include + +#endif // IS_LVALUE_ITERATOR_DWA2003112_HPP diff --git a/win32/include/boost/iterator/is_readable_iterator.hpp b/win32/include/boost/iterator/is_readable_iterator.hpp new file mode 100755 index 000000000..036585eff --- /dev/null +++ b/win32/include/boost/iterator/is_readable_iterator.hpp @@ -0,0 +1,108 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef IS_READABLE_ITERATOR_DWA2003112_HPP +# define IS_READABLE_ITERATOR_DWA2003112_HPP + +#include +#include + +#include +#include + +// should be the last #include +#include + +#ifndef BOOST_NO_IS_CONVERTIBLE + +namespace boost { + +namespace detail +{ + // Guts of is_readable_iterator. Value is the iterator's value_type + // and the result is computed in the nested rebind template. + template + struct is_readable_iterator_impl + { + static char tester(Value&, int); + static char (& tester(any_conversion_eater, ...) )[2]; + + template + struct rebind + { + static It& x; + + BOOST_STATIC_CONSTANT( + bool + , value = ( + sizeof( + is_readable_iterator_impl::tester(*x, 1) + ) == 1 + ) + ); + }; + }; + +#undef BOOST_READABLE_PRESERVER + + // + // void specializations to handle std input and output iterators + // + template <> + struct is_readable_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS + template <> + struct is_readable_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + + template <> + struct is_readable_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + + template <> + struct is_readable_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; +#endif + + // + // This level of dispatching is required for Borland. We might save + // an instantiation by removing it for others. + // + template + struct is_readable_iterator_impl2 + : is_readable_iterator_impl< + BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits::value_type const + >::template rebind + {}; +} // namespace detail + +// Define the trait with full mpl lambda capability and various broken +// compiler workarounds +BOOST_TT_AUX_BOOL_TRAIT_DEF1( + is_readable_iterator,T,::boost::detail::is_readable_iterator_impl2::value) + +} // namespace boost + +#endif + +#include + +#endif // IS_READABLE_ITERATOR_DWA2003112_HPP diff --git a/win32/include/boost/iterator/iterator_adaptor.hpp b/win32/include/boost/iterator/iterator_adaptor.hpp new file mode 100755 index 000000000..d9c290dab --- /dev/null +++ b/win32/include/boost/iterator/iterator_adaptor.hpp @@ -0,0 +1,366 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_ITERATOR_ADAPTOR_23022003THW_HPP +#define BOOST_ITERATOR_ADAPTOR_23022003THW_HPP + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY +# include +#else +# include +#endif + +#include + +#include + +namespace boost +{ + // Used as a default template argument internally, merely to + // indicate "use the default", this can also be passed by users + // explicitly in order to specify that the default should be used. + struct use_default; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // the incompleteness of use_default causes massive problems for + // is_convertible (naturally). This workaround is fortunately not + // needed for vc6/vc7. + template + struct is_convertible + : mpl::false_ {}; +# endif + + namespace detail + { + + // + // Result type used in enable_if_convertible meta function. + // This can be an incomplete type, as only pointers to + // enable_if_convertible< ... >::type are used. + // We could have used void for this, but conversion to + // void* is just to easy. + // + struct enable_type; + } + + + // + // enable_if for use in adapted iterators constructors. + // + // In order to provide interoperability between adapted constant and + // mutable iterators, adapted iterators will usually provide templated + // conversion constructors of the following form + // + // template + // class adapted_iterator : + // public iterator_adaptor< adapted_iterator, Iterator > + // { + // public: + // + // ... + // + // template + // adapted_iterator( + // OtherIterator const& it + // , typename enable_if_convertible::type* = 0); + // + // ... + // }; + // + // enable_if_convertible is used to remove those overloads from the overload + // set that cannot be instantiated. For all practical purposes only overloads + // for constant/mutable interaction will remain. This has the advantage that + // meta functions like boost::is_convertible do not return false positives, + // as they can only look at the signature of the conversion constructor + // and not at the actual instantiation. + // + // enable_if_interoperable can be safely used in user code. It falls back to + // always enabled for compilers that don't support enable_if or is_convertible. + // There is no need for compiler specific workarounds in user code. + // + // The operators implementation relies on boost::is_convertible not returning + // false positives for user/library defined iterator types. See comments + // on operator implementation for consequences. + // +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + + template + struct enable_if_convertible + { + typedef typename mpl::if_< + mpl::or_< + is_same + , is_convertible + > + , boost::detail::enable_type + , int& + >::type type; + }; + +# elif defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_SFINAE) + + template + struct enable_if_convertible + { + typedef boost::detail::enable_type type; + }; + +# elif BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) && BOOST_MSVC > 1300 + + // For some reason vc7.1 needs us to "cut off" instantiation + // of is_convertible in a few cases. + template + struct enable_if_convertible + : iterators::enable_if< + mpl::or_< + is_same + , is_convertible + > + , boost::detail::enable_type + > + {}; + +# else + + template + struct enable_if_convertible + : iterators::enable_if< + is_convertible + , boost::detail::enable_type + > + {}; + +# endif + + // + // Default template argument handling for iterator_adaptor + // + namespace detail + { + // If T is use_default, return the result of invoking + // DefaultNullaryFn, otherwise return T. + template + struct ia_dflt_help + : mpl::eval_if< + is_same + , DefaultNullaryFn + , mpl::identity + > + { + }; + + // A metafunction which computes an iterator_adaptor's base class, + // a specialization of iterator_facade. + template < + class Derived + , class Base + , class Value + , class Traversal + , class Reference + , class Difference + > + struct iterator_adaptor_base + { + typedef iterator_facade< + Derived + +# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY + , typename boost::detail::ia_dflt_help< + Value + , mpl::eval_if< + is_same + , iterator_value + , remove_reference + > + >::type +# else + , typename boost::detail::ia_dflt_help< + Value, iterator_value + >::type +# endif + + , typename boost::detail::ia_dflt_help< + Traversal + , iterator_traversal + >::type + + , typename boost::detail::ia_dflt_help< + Reference + , mpl::eval_if< + is_same + , iterator_reference + , add_reference + > + >::type + + , typename boost::detail::ia_dflt_help< + Difference, iterator_difference + >::type + > + type; + }; + + // workaround for aC++ CR JAGaf33512 + template + inline void iterator_adaptor_assert_traversal () + { + BOOST_STATIC_ASSERT((is_convertible::value)); + } + } + + // + // Iterator Adaptor + // + // The parameter ordering changed slightly with respect to former + // versions of iterator_adaptor The idea is that when the user needs + // to fiddle with the reference type it is highly likely that the + // iterator category has to be adjusted as well. Any of the + // following four template arguments may be ommitted or explicitly + // replaced by use_default. + // + // Value - if supplied, the value_type of the resulting iterator, unless + // const. If const, a conforming compiler strips constness for the + // value_type. If not supplied, iterator_traits::value_type is used + // + // Category - the traversal category of the resulting iterator. If not + // supplied, iterator_traversal::type is used. + // + // Reference - the reference type of the resulting iterator, and in + // particular, the result type of operator*(). If not supplied but + // Value is supplied, Value& is used. Otherwise + // iterator_traits::reference is used. + // + // Difference - the difference_type of the resulting iterator. If not + // supplied, iterator_traits::difference_type is used. + // + template < + class Derived + , class Base + , class Value = use_default + , class Traversal = use_default + , class Reference = use_default + , class Difference = use_default + > + class iterator_adaptor + : public boost::detail::iterator_adaptor_base< + Derived, Base, Value, Traversal, Reference, Difference + >::type + { + friend class iterator_core_access; + + protected: + typedef typename boost::detail::iterator_adaptor_base< + Derived, Base, Value, Traversal, Reference, Difference + >::type super_t; + public: + iterator_adaptor() {} + + explicit iterator_adaptor(Base const &iter) + : m_iterator(iter) + { + } + + typedef Base base_type; + + Base const& base() const + { return m_iterator; } + + protected: + // for convenience in derived classes + typedef iterator_adaptor iterator_adaptor_; + + // + // lvalue access to the Base object for Derived + // + Base const& base_reference() const + { return m_iterator; } + + Base& base_reference() + { return m_iterator; } + + private: + // + // Core iterator interface for iterator_facade. This is private + // to prevent temptation for Derived classes to use it, which + // will often result in an error. Derived classes should use + // base_reference(), above, to get direct access to m_iterator. + // + typename super_t::reference dereference() const + { return *m_iterator; } + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + bool equal(iterator_adaptor const& x) const + { + // Maybe readd with same_distance + // BOOST_STATIC_ASSERT( + // (detail::same_category_and_difference::value) + // ); + return m_iterator == x.base(); + } + + typedef typename iterator_category_to_traversal< + typename super_t::iterator_category + >::type my_traversal; + +# define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \ + boost::detail::iterator_adaptor_assert_traversal(); + + void advance(typename super_t::difference_type n) + { + BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag) + m_iterator += n; + } + + void increment() { ++m_iterator; } + + void decrement() + { + BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag) + --m_iterator; + } + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + typename super_t::difference_type distance_to( + iterator_adaptor const& y) const + { + BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag) + // Maybe readd with same_distance + // BOOST_STATIC_ASSERT( + // (detail::same_category_and_difference::value) + // ); + return y.base() - m_iterator; + } + +# undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL + + private: // data members + Base m_iterator; + }; + +} // namespace boost + +#include + +#endif // BOOST_ITERATOR_ADAPTOR_23022003THW_HPP diff --git a/win32/include/boost/iterator/iterator_archetypes.hpp b/win32/include/boost/iterator/iterator_archetypes.hpp new file mode 100755 index 000000000..74b250b10 --- /dev/null +++ b/win32/include/boost/iterator/iterator_archetypes.hpp @@ -0,0 +1,515 @@ +// (C) Copyright Jeremy Siek 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ITERATOR_ARCHETYPES_HPP +#define BOOST_ITERATOR_ARCHETYPES_HPP + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { + +template +struct access_archetype; + +template +struct traversal_archetype; + +namespace iterator_archetypes +{ + enum { + readable_iterator_bit = 1 + , writable_iterator_bit = 2 + , swappable_iterator_bit = 4 + , lvalue_iterator_bit = 8 + }; + + // Not quite tags, since dispatching wouldn't work. + typedef mpl::int_::type readable_iterator_t; + typedef mpl::int_::type writable_iterator_t; + + typedef mpl::int_< + (readable_iterator_bit|writable_iterator_bit) + >::type readable_writable_iterator_t; + + typedef mpl::int_< + (readable_iterator_bit|lvalue_iterator_bit) + >::type readable_lvalue_iterator_t; + + typedef mpl::int_< + (lvalue_iterator_bit|writable_iterator_bit) + >::type writable_lvalue_iterator_t; + + typedef mpl::int_::type swappable_iterator_t; + typedef mpl::int_::type lvalue_iterator_t; + + template + struct has_access + : mpl::equal_to< + mpl::bitand_ + , Base + > + {}; +} + +namespace detail +{ + template + struct assign_proxy + { + assign_proxy& operator=(T) { return *this; } + }; + + template + struct read_proxy + { + operator T() { return static_object::get(); } + }; + + template + struct read_write_proxy + : read_proxy // Use to inherit from assign_proxy, but that doesn't work. -JGS + { + read_write_proxy& operator=(T) { return *this; } + }; + + template + struct arrow_proxy + { + T const* operator->() const { return 0; } + }; + + struct no_operator_brackets {}; + + template + struct readable_operator_brackets + { + read_proxy operator[](std::ptrdiff_t n) const { return read_proxy(); } + }; + + template + struct writable_operator_brackets + { + read_write_proxy operator[](std::ptrdiff_t n) const { return read_write_proxy(); } + }; + + template + struct operator_brackets + : mpl::aux::msvc_eti_base< + typename mpl::eval_if< + is_convertible + , mpl::eval_if< + iterator_archetypes::has_access< + AccessCategory + , iterator_archetypes::writable_iterator_t + > + , mpl::identity > + , mpl::if_< + iterator_archetypes::has_access< + AccessCategory + , iterator_archetypes::readable_iterator_t + > + , readable_operator_brackets + , no_operator_brackets + > + > + , mpl::identity + >::type + >::type + {}; + + template + struct traversal_archetype_impl + { + template struct archetype; + }; + + // Constructor argument for those iterators that + // are not default constructible + struct ctor_arg {}; + + template + struct traversal_archetype_ + : mpl::aux::msvc_eti_base< + typename traversal_archetype_impl::template archetype + >::type + { + typedef typename + traversal_archetype_impl::template archetype + base; + + traversal_archetype_() {} + + traversal_archetype_(ctor_arg arg) + : base(arg) + {} + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + { + explicit archetype(ctor_arg) {} + + struct bogus { }; // This use to be void, but that causes trouble for iterator_facade. Need more research. -JGS + typedef bogus difference_type; + + Derived& operator++() { return (Derived&)static_object::get(); } + Derived operator++(int) const { return (Derived&)static_object::get(); } + }; + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public equality_comparable< traversal_archetype_ >, + public traversal_archetype_ + { + explicit archetype(ctor_arg arg) + : traversal_archetype_(arg) + {} + + typedef std::ptrdiff_t difference_type; + }; + }; + + template + bool operator==(traversal_archetype_ const&, + traversal_archetype_ const&) { return true; } + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + // doesn't seem to pick up != from equality_comparable + template + bool operator!=(traversal_archetype_ const&, + traversal_archetype_ const&) { return true; } +#endif + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + archetype() + : traversal_archetype_(ctor_arg()) + {} + }; + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + Derived& operator--() { return static_object::get(); } + Derived operator--(int) const { return static_object::get(); } + }; + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + Derived& operator+=(std::ptrdiff_t) { return static_object::get(); } + Derived& operator-=(std::ptrdiff_t) { return static_object::get(); } + }; + }; + + template + Derived& operator+(traversal_archetype_ const&, + std::ptrdiff_t) { return static_object::get(); } + + template + Derived& operator+(std::ptrdiff_t, + traversal_archetype_ const&) + { return static_object::get(); } + + template + Derived& operator-(traversal_archetype_ const&, + std::ptrdiff_t) + { return static_object::get(); } + + template + std::ptrdiff_t operator-(traversal_archetype_ const&, + traversal_archetype_ const&) + { return 0; } + + template + bool operator<(traversal_archetype_ const&, + traversal_archetype_ const&) + { return true; } + + template + bool operator>(traversal_archetype_ const&, + traversal_archetype_ const&) + { return true; } + + template + bool operator<=(traversal_archetype_ const&, + traversal_archetype_ const&) + { return true; } + + template + bool operator>=(traversal_archetype_ const&, + traversal_archetype_ const&) + { return true; } + + struct bogus_type; + + template + struct convertible_type + : mpl::if_< is_const, + typename remove_const::type, + bogus_type > + {}; + +} // namespace detail + + +template struct undefined; + +template +struct iterator_access_archetype_impl +{ + template struct archetype; +}; + +template +struct iterator_access_archetype + : mpl::aux::msvc_eti_base< + typename iterator_access_archetype_impl< + AccessCategory + >::template archetype + >::type +{ +}; + +template <> +struct iterator_access_archetype_impl< + iterator_archetypes::readable_iterator_t +> +{ + template + struct archetype + { + typedef typename remove_cv::type value_type; + typedef Value reference; + typedef Value* pointer; + + value_type operator*() const { return static_object::get(); } + + detail::arrow_proxy operator->() const { return detail::arrow_proxy(); } + }; +}; + +template <> +struct iterator_access_archetype_impl< + iterator_archetypes::writable_iterator_t +> +{ + template + struct archetype + { +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + BOOST_STATIC_ASSERT(!is_const::value); +# endif + typedef void value_type; + typedef void reference; + typedef void pointer; + + detail::assign_proxy operator*() const { return detail::assign_proxy(); } + }; +}; + +template <> +struct iterator_access_archetype_impl< + iterator_archetypes::readable_writable_iterator_t +> +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, iterator_archetypes::readable_iterator_t + > + { + typedef detail::read_write_proxy reference; + + detail::read_write_proxy operator*() const { return detail::read_write_proxy(); } + }; +}; + +template <> +struct iterator_access_archetype_impl +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, iterator_archetypes::readable_iterator_t + > + { + typedef Value& reference; + + Value& operator*() const { return static_object::get(); } + Value* operator->() const { return 0; } + }; +}; + +template <> +struct iterator_access_archetype_impl +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, iterator_archetypes::readable_lvalue_iterator_t + > + { +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + BOOST_STATIC_ASSERT((!is_const::value)); +# endif + }; +}; + + +template +struct iterator_archetype; + +template +struct traversal_archetype_base + : detail::operator_brackets< + typename remove_cv::type + , AccessCategory + , TraversalCategory + > + , detail::traversal_archetype_< + iterator_archetype + , Value + , TraversalCategory + > +{ +}; + +namespace detail +{ + template + struct iterator_archetype_base + : iterator_access_archetype + , traversal_archetype_base + { + typedef iterator_access_archetype access; + + typedef typename detail::facade_iterator_category< + TraversalCategory + , typename mpl::eval_if< + iterator_archetypes::has_access< + AccessCategory, iterator_archetypes::writable_iterator_t + > + , remove_const + , add_const + >::type + , typename access::reference + >::type iterator_category; + + // Needed for some broken libraries (see below) + typedef boost::iterator< + iterator_category + , Value + , typename traversal_archetype_base< + Value, AccessCategory, TraversalCategory + >::difference_type + , typename access::pointer + , typename access::reference + > workaround_iterator_base; + }; +} + +template +struct iterator_archetype + : public detail::iterator_archetype_base + + // These broken libraries require derivation from std::iterator + // (or related magic) in order to handle iter_swap and other + // iterator operations +# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ + || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) + , public detail::iterator_archetype_base< + Value, AccessCategory, TraversalCategory + >::workaround_iterator_base +# endif +{ + // Derivation from std::iterator above caused references to nested + // types to be ambiguous, so now we have to redeclare them all + // here. +# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ + || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) + + typedef detail::iterator_archetype_base< + Value,AccessCategory,TraversalCategory + > base; + + typedef typename base::value_type value_type; + typedef typename base::reference reference; + typedef typename base::pointer pointer; + typedef typename base::difference_type difference_type; + typedef typename base::iterator_category iterator_category; +# endif + + iterator_archetype() { } + iterator_archetype(iterator_archetype const& x) + : detail::iterator_archetype_base< + Value + , AccessCategory + , TraversalCategory + >(x) + {} + + iterator_archetype& operator=(iterator_archetype const&) + { return *this; } + +# if 0 + // Optional conversion from mutable + iterator_archetype( + iterator_archetype< + typename detail::convertible_type::type + , AccessCategory + , TraversalCategory> const& + ); +# endif +}; + +} // namespace boost + + +#endif // BOOST_ITERATOR_ARCHETYPES_HPP diff --git a/win32/include/boost/iterator/iterator_categories.hpp b/win32/include/boost/iterator/iterator_categories.hpp new file mode 100755 index 000000000..9a0be36cc --- /dev/null +++ b/win32/include/boost/iterator/iterator_categories.hpp @@ -0,0 +1,188 @@ +// (C) Copyright Jeremy Siek 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ITERATOR_CATEGORIES_HPP +# define BOOST_ITERATOR_CATEGORIES_HPP + +# include +# include +# include + +# include + +# include +# include +# include +# include + +# include + +# include + +namespace boost { + +// +// Traversal Categories +// + +struct no_traversal_tag {}; + +struct incrementable_traversal_tag + : no_traversal_tag +{ +// incrementable_traversal_tag() {} +// incrementable_traversal_tag(std::output_iterator_tag const&) {}; +}; + +struct single_pass_traversal_tag + : incrementable_traversal_tag +{ +// single_pass_traversal_tag() {} +// single_pass_traversal_tag(std::input_iterator_tag const&) {}; +}; + +struct forward_traversal_tag + : single_pass_traversal_tag +{ +// forward_traversal_tag() {} +// forward_traversal_tag(std::forward_iterator_tag const&) {}; +}; + +struct bidirectional_traversal_tag + : forward_traversal_tag +{ +// bidirectional_traversal_tag() {}; +// bidirectional_traversal_tag(std::bidirectional_iterator_tag const&) {}; +}; + +struct random_access_traversal_tag + : bidirectional_traversal_tag +{ +// random_access_traversal_tag() {}; +// random_access_traversal_tag(std::random_access_iterator_tag const&) {}; +}; + +namespace detail +{ + // + // Convert a "strictly old-style" iterator category to a traversal + // tag. This is broken out into a separate metafunction to reduce + // the cost of instantiating iterator_category_to_traversal, below, + // for new-style types. + // + template + struct old_category_to_traversal + : mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , void + > + > + > + > + > + {}; + +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + template <> + struct old_category_to_traversal + { + typedef int type; + }; +# endif + + template + struct pure_traversal_tag + : mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , void + > + > + > + > + > + { + }; + +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + template <> + struct pure_traversal_tag + { + typedef int type; + }; +# endif + +} // namespace detail + + +// +// Convert an iterator category into a traversal tag +// +template +struct iterator_category_to_traversal + : mpl::eval_if< // if already convertible to a traversal tag, we're done. + is_convertible + , mpl::identity + , boost::detail::old_category_to_traversal + > +{}; + +// Trait to get an iterator's traversal category +template +struct iterator_traversal + : iterator_category_to_traversal< + typename boost::detail::iterator_traits::iterator_category + > +{}; + +# ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT +// Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work +// out well. Instantiating the nested apply template also +// requires instantiating iterator_traits on the +// placeholder. Instead we just specialize it as a metafunction +// class. +template <> +struct iterator_traversal +{ + template + struct apply : iterator_traversal + {}; +}; +template <> +struct iterator_traversal + : iterator_traversal +{}; +# endif + +} // namespace boost + +#include + +#endif // BOOST_ITERATOR_CATEGORIES_HPP diff --git a/win32/include/boost/iterator/iterator_concepts.hpp b/win32/include/boost/iterator/iterator_concepts.hpp new file mode 100755 index 000000000..732ad887a --- /dev/null +++ b/win32/include/boost/iterator/iterator_concepts.hpp @@ -0,0 +1,284 @@ +// (C) Copyright Jeremy Siek 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ITERATOR_CONCEPTS_HPP +#define BOOST_ITERATOR_CONCEPTS_HPP + +#include +#include + +// Use boost::detail::iterator_traits to work around some MSVC/Dinkumware problems. +#include + +#include +#include + +#include +#include +#include +#include + +#include + +// Use boost/limits to work around missing limits headers on some compilers +#include +#include + +#include + +#include + +namespace boost_concepts +{ + // Used a different namespace here (instead of "boost") so that the + // concept descriptions do not take for granted the names in + // namespace boost. + + //=========================================================================== + // Iterator Access Concepts + + BOOST_concept(ReadableIterator,(Iterator)) + : boost::Assignable + , boost::CopyConstructible + + { + typedef BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits::reference reference; + + BOOST_CONCEPT_USAGE(ReadableIterator) + { + + value_type v = *i; + boost::ignore_unused_variable_warning(v); + } + private: + Iterator i; + }; + + template < + typename Iterator + , typename ValueType = BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits::value_type + > + struct WritableIterator + : boost::CopyConstructible + { + BOOST_CONCEPT_USAGE(WritableIterator) + { + *i = v; + } + private: + ValueType v; + Iterator i; + }; + + template < + typename Iterator + , typename ValueType = BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits::value_type + > + struct WritableIteratorConcept : WritableIterator {}; + + BOOST_concept(SwappableIterator,(Iterator)) + { + BOOST_CONCEPT_USAGE(SwappableIterator) + { + std::iter_swap(i1, i2); + } + private: + Iterator i1; + Iterator i2; + }; + + BOOST_concept(LvalueIterator,(Iterator)) + { + typedef typename boost::detail::iterator_traits::value_type value_type; + + BOOST_CONCEPT_USAGE(LvalueIterator) + { + value_type& r = const_cast(*i); + boost::ignore_unused_variable_warning(r); + } + private: + Iterator i; + }; + + + //=========================================================================== + // Iterator Traversal Concepts + + BOOST_concept(IncrementableIterator,(Iterator)) + : boost::Assignable + , boost::CopyConstructible + { + typedef typename boost::iterator_traversal::type traversal_category; + + BOOST_CONCEPT_ASSERT(( + boost::Convertible< + traversal_category + , boost::incrementable_traversal_tag + >)); + + BOOST_CONCEPT_USAGE(IncrementableIterator) + { + ++i; + (void)i++; + } + private: + Iterator i; + }; + + BOOST_concept(SinglePassIterator,(Iterator)) + : IncrementableIterator + , boost::EqualityComparable + + { + BOOST_CONCEPT_ASSERT(( + boost::Convertible< + BOOST_DEDUCED_TYPENAME SinglePassIterator::traversal_category + , boost::single_pass_traversal_tag + > )); + }; + + BOOST_concept(ForwardTraversal,(Iterator)) + : SinglePassIterator + , boost::DefaultConstructible + { + typedef typename boost::detail::iterator_traits::difference_type difference_type; + + BOOST_MPL_ASSERT((boost::is_integral)); + BOOST_MPL_ASSERT_RELATION(std::numeric_limits::is_signed, ==, true); + + BOOST_CONCEPT_ASSERT(( + boost::Convertible< + BOOST_DEDUCED_TYPENAME ForwardTraversal::traversal_category + , boost::forward_traversal_tag + > )); + }; + + BOOST_concept(BidirectionalTraversal,(Iterator)) + : ForwardTraversal + { + BOOST_CONCEPT_ASSERT(( + boost::Convertible< + BOOST_DEDUCED_TYPENAME BidirectionalTraversal::traversal_category + , boost::bidirectional_traversal_tag + > )); + + BOOST_CONCEPT_USAGE(BidirectionalTraversal) + { + --i; + (void)i--; + } + private: + Iterator i; + }; + + BOOST_concept(RandomAccessTraversal,(Iterator)) + : BidirectionalTraversal + { + BOOST_CONCEPT_ASSERT(( + boost::Convertible< + BOOST_DEDUCED_TYPENAME RandomAccessTraversal::traversal_category + , boost::random_access_traversal_tag + > )); + + BOOST_CONCEPT_USAGE(RandomAccessTraversal) + { + i += n; + i = i + n; + i = n + i; + i -= n; + i = i - n; + n = i - j; + } + + private: + typename BidirectionalTraversal::difference_type n; + Iterator i, j; + }; + + //=========================================================================== + // Iterator Interoperability + + namespace detail + { + template + void interop_single_pass_constraints(Iterator1 const& i1, Iterator2 const& i2) + { + bool b; + b = i1 == i2; + b = i1 != i2; + + b = i2 == i1; + b = i2 != i1; + boost::ignore_unused_variable_warning(b); + } + + template + void interop_rand_access_constraints( + Iterator1 const& i1, Iterator2 const& i2, + boost::random_access_traversal_tag, boost::random_access_traversal_tag) + { + bool b; + typename boost::detail::iterator_traits::difference_type n; + b = i1 < i2; + b = i1 <= i2; + b = i1 > i2; + b = i1 >= i2; + n = i1 - i2; + + b = i2 < i1; + b = i2 <= i1; + b = i2 > i1; + b = i2 >= i1; + n = i2 - i1; + boost::ignore_unused_variable_warning(b); + boost::ignore_unused_variable_warning(n); + } + + template + void interop_rand_access_constraints( + Iterator1 const&, Iterator2 const&, + boost::single_pass_traversal_tag, boost::single_pass_traversal_tag) + { } + + } // namespace detail + + BOOST_concept(InteroperableIterator,(Iterator)(ConstIterator)) + { + private: + typedef typename boost::detail::pure_traversal_tag< + typename boost::iterator_traversal< + Iterator + >::type + >::type traversal_category; + + typedef typename boost::detail::pure_traversal_tag< + typename boost::iterator_traversal< + ConstIterator + >::type + >::type const_traversal_category; + + public: + BOOST_CONCEPT_ASSERT((SinglePassIterator)); + BOOST_CONCEPT_ASSERT((SinglePassIterator)); + + BOOST_CONCEPT_USAGE(InteroperableIterator) + { + detail::interop_single_pass_constraints(i, ci); + detail::interop_rand_access_constraints(i, ci, traversal_category(), const_traversal_category()); + + ci = i; + } + + private: + Iterator i; + ConstIterator ci; + }; + +} // namespace boost_concepts + +#include + +#endif // BOOST_ITERATOR_CONCEPTS_HPP diff --git a/win32/include/boost/iterator/iterator_facade.hpp b/win32/include/boost/iterator/iterator_facade.hpp new file mode 100755 index 000000000..8344f3eda --- /dev/null +++ b/win32/include/boost/iterator/iterator_facade.hpp @@ -0,0 +1,879 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_ITERATOR_FACADE_23022003THW_HPP +#define BOOST_ITERATOR_FACADE_23022003THW_HPP + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include // this goes last + +namespace boost +{ + // This forward declaration is required for the friend declaration + // in iterator_core_access + template class iterator_facade; + + namespace detail + { + // A binary metafunction class that always returns bool. VC6 + // ICEs on mpl::always, probably because of the default + // parameters. + struct always_bool2 + { + template + struct apply + { + typedef bool type; + }; + }; + + // + // enable if for use in operator implementation. + // + template < + class Facade1 + , class Facade2 + , class Return + > + struct enable_if_interoperable +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + { + typedef typename mpl::if_< + mpl::or_< + is_convertible + , is_convertible + > + , Return + , int[3] + >::type type; + }; +#else + : ::boost::iterators::enable_if< + mpl::or_< + is_convertible + , is_convertible + > + , Return + > + {}; +#endif + + // + // Generates associated types for an iterator_facade with the + // given parameters. + // + template < + class ValueParam + , class CategoryOrTraversal + , class Reference + , class Difference + > + struct iterator_facade_types + { + typedef typename facade_iterator_category< + CategoryOrTraversal, ValueParam, Reference + >::type iterator_category; + + typedef typename remove_const::type value_type; + + typedef typename mpl::eval_if< + boost::detail::iterator_writability_disabled + , add_pointer + , add_pointer + >::type pointer; + +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \ + || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \ + || BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101)) \ + || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 310) + + // To interoperate with some broken library/compiler + // combinations, user-defined iterators must be derived from + // std::iterator. It is possible to implement a standard + // library for broken compilers without this limitation. +# define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1 + + typedef + iterator + base; +# endif + }; + + // iterators whose dereference operators reference the same value + // for all iterators into the same sequence (like many input + // iterators) need help with their postfix ++: the referenced + // value must be read and stored away before the increment occurs + // so that *a++ yields the originally referenced element and not + // the next one. + template + class postfix_increment_proxy + { + typedef typename iterator_value::type value_type; + public: + explicit postfix_increment_proxy(Iterator const& x) + : stored_value(*x) + {} + + // Returning a mutable reference allows nonsense like + // (*r++).mutate(), but it imposes fewer assumptions about the + // behavior of the value_type. In particular, recall taht + // (*r).mutate() is legal if operator* returns by value. + value_type& + operator*() const + { + return this->stored_value; + } + private: + mutable value_type stored_value; + }; + + // + // In general, we can't determine that such an iterator isn't + // writable -- we also need to store a copy of the old iterator so + // that it can be written into. + template + class writable_postfix_increment_proxy + { + typedef typename iterator_value::type value_type; + public: + explicit writable_postfix_increment_proxy(Iterator const& x) + : stored_value(*x) + , stored_iterator(x) + {} + + // Dereferencing must return a proxy so that both *r++ = o and + // value_type(*r++) can work. In this case, *r is the same as + // *r++, and the conversion operator below is used to ensure + // readability. + writable_postfix_increment_proxy const& + operator*() const + { + return *this; + } + + // Provides readability of *r++ + operator value_type&() const + { + return stored_value; + } + + // Provides writability of *r++ + template + T const& operator=(T const& x) const + { + *this->stored_iterator = x; + return x; + } + + // This overload just in case only non-const objects are writable + template + T& operator=(T& x) const + { + *this->stored_iterator = x; + return x; + } + + // Provides X(r++) + operator Iterator const&() const + { + return stored_iterator; + } + + private: + mutable value_type stored_value; + Iterator stored_iterator; + }; + +# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + template + struct is_non_proxy_reference_impl + { + static Reference r; + + template + static typename mpl::if_< + is_convertible< + R const volatile* + , Value const volatile* + > + , char[1] + , char[2] + >::type& helper(R const&); + + BOOST_STATIC_CONSTANT(bool, value = sizeof(helper(r)) == 1); + }; + + template + struct is_non_proxy_reference + : mpl::bool_< + is_non_proxy_reference_impl::value + > + {}; +# else + template + struct is_non_proxy_reference + : is_convertible< + typename remove_reference::type + const volatile* + , Value const volatile* + > + {}; +# endif + + // A metafunction to choose the result type of postfix ++ + // + // Because the C++98 input iterator requirements say that *r++ has + // type T (value_type), implementations of some standard + // algorithms like lexicographical_compare may use constructions + // like: + // + // *r++ < *s++ + // + // If *r++ returns a proxy (as required if r is writable but not + // multipass), this sort of expression will fail unless the proxy + // supports the operator<. Since there are any number of such + // operations, we're not going to try to support them. Therefore, + // even if r++ returns a proxy, *r++ will only return a proxy if + // *r also returns a proxy. + template + struct postfix_increment_result + : mpl::eval_if< + mpl::and_< + // A proxy is only needed for readable iterators + is_convertible + + // No multipass iterator can have values that disappear + // before positions can be re-visited + , mpl::not_< + is_convertible< + typename iterator_category_to_traversal::type + , forward_traversal_tag + > + > + > + , mpl::if_< + is_non_proxy_reference + , postfix_increment_proxy + , writable_postfix_increment_proxy + > + , mpl::identity + > + {}; + + // operator->() needs special support for input iterators to strictly meet the + // standard's requirements. If *i is not a reference type, we must still + // produce a lvalue to which a pointer can be formed. We do that by + // returning an instantiation of this special proxy class template. + template + struct operator_arrow_proxy + { + operator_arrow_proxy(T const* px) : m_value(*px) {} + T* operator->() const { return &m_value; } + // This function is needed for MWCW and BCC, which won't call operator-> + // again automatically per 13.3.1.2 para 8 + operator T*() const { return &m_value; } + mutable T m_value; + }; + + // A metafunction that gets the result type for operator->. Also + // has a static function make() which builds the result from a + // Reference + template + struct operator_arrow_result + { + // CWPro8.3 won't accept "operator_arrow_result::type", and we + // need that type below, so metafunction forwarding would be a + // losing proposition here. + typedef typename mpl::if_< + is_reference + , Pointer + , operator_arrow_proxy + >::type type; + + static type make(Reference x) + { + return implicit_cast(&x); + } + }; + +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + // Deal with ETI + template<> + struct operator_arrow_result + { + typedef int type; + }; +# endif + + // A proxy return type for operator[], needed to deal with + // iterators that may invalidate referents upon destruction. + // Consider the temporary iterator in *(a + n) + template + class operator_brackets_proxy + { + // Iterator is actually an iterator_facade, so we do not have to + // go through iterator_traits to access the traits. + typedef typename Iterator::reference reference; + typedef typename Iterator::value_type value_type; + + public: + operator_brackets_proxy(Iterator const& iter) + : m_iter(iter) + {} + + operator reference() const + { + return *m_iter; + } + + operator_brackets_proxy& operator=(value_type const& val) + { + *m_iter = val; + return *this; + } + + private: + Iterator m_iter; + }; + + // A metafunction that determines whether operator[] must return a + // proxy, or whether it can simply return a copy of the value_type. + template + struct use_operator_brackets_proxy + : mpl::not_< + mpl::and_< + // Really we want an is_copy_constructible trait here, + // but is_POD will have to suffice in the meantime. + boost::is_POD + , iterator_writability_disabled + > + > + {}; + + template + struct operator_brackets_result + { + typedef typename mpl::if_< + use_operator_brackets_proxy + , operator_brackets_proxy + , Value + >::type type; + }; + + template + operator_brackets_proxy make_operator_brackets_result(Iterator const& iter, mpl::true_) + { + return operator_brackets_proxy(iter); + } + + template + typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::false_) + { + return *iter; + } + + struct choose_difference_type + { + template + struct apply + : +# ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP + iterator_difference +# elif BOOST_WORKAROUND(BOOST_MSVC, < 1300) + mpl::if_< + is_convertible + , typename I1::difference_type + , typename I2::difference_type + > +# else + mpl::eval_if< + is_convertible + , iterator_difference + , iterator_difference + > +# endif + {}; + + }; + } // namespace detail + + + // Macros which describe the declarations of binary operators +# ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY +# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ + template < \ + class Derived1, class V1, class TC1, class Reference1, class Difference1 \ + , class Derived2, class V2, class TC2, class Reference2, class Difference2 \ + > \ + prefix typename mpl::apply2::type \ + operator op( \ + iterator_facade const& lhs \ + , iterator_facade const& rhs) +# else +# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ + template < \ + class Derived1, class V1, class TC1, class Reference1, class Difference1 \ + , class Derived2, class V2, class TC2, class Reference2, class Difference2 \ + > \ + prefix typename boost::detail::enable_if_interoperable< \ + Derived1, Derived2 \ + , typename mpl::apply2::type \ + >::type \ + operator op( \ + iterator_facade const& lhs \ + , iterator_facade const& rhs) +# endif + +# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \ + template \ + prefix Derived operator+ args + + // + // Helper class for granting access to the iterator core interface. + // + // The simple core interface is used by iterator_facade. The core + // interface of a user/library defined iterator type should not be made public + // so that it does not clutter the public interface. Instead iterator_core_access + // should be made friend so that iterator_facade can access the core + // interface through iterator_core_access. + // + class iterator_core_access + { +# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + // Tasteless as this may seem, making all members public allows member templates + // to work in the absence of member template friends. + public: +# else + + template friend class iterator_facade; + +# define BOOST_ITERATOR_FACADE_RELATION(op) \ + BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, boost::detail::always_bool2); + + BOOST_ITERATOR_FACADE_RELATION(==) + BOOST_ITERATOR_FACADE_RELATION(!=) + + BOOST_ITERATOR_FACADE_RELATION(<) + BOOST_ITERATOR_FACADE_RELATION(>) + BOOST_ITERATOR_FACADE_RELATION(<=) + BOOST_ITERATOR_FACADE_RELATION(>=) +# undef BOOST_ITERATOR_FACADE_RELATION + + BOOST_ITERATOR_FACADE_INTEROP_HEAD( + friend, -, boost::detail::choose_difference_type) + ; + + BOOST_ITERATOR_FACADE_PLUS_HEAD( + friend inline + , (iterator_facade const& + , typename Derived::difference_type) + ) + ; + + BOOST_ITERATOR_FACADE_PLUS_HEAD( + friend inline + , (typename Derived::difference_type + , iterator_facade const&) + ) + ; + +# endif + + template + static typename Facade::reference dereference(Facade const& f) + { + return f.dereference(); + } + + template + static void increment(Facade& f) + { + f.increment(); + } + + template + static void decrement(Facade& f) + { + f.decrement(); + } + + template + static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::true_) + { + return f1.equal(f2); + } + + template + static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::false_) + { + return f2.equal(f1); + } + + template + static void advance(Facade& f, typename Facade::difference_type n) + { + f.advance(n); + } + + template + static typename Facade1::difference_type distance_from( + Facade1 const& f1, Facade2 const& f2, mpl::true_) + { + return -f1.distance_to(f2); + } + + template + static typename Facade2::difference_type distance_from( + Facade1 const& f1, Facade2 const& f2, mpl::false_) + { + return f2.distance_to(f1); + } + + // + // Curiously Recurring Template interface. + // + template + static I& derived(iterator_facade& facade) + { + return *static_cast(&facade); + } + + template + static I const& derived(iterator_facade const& facade) + { + return *static_cast(&facade); + } + + private: + // objects of this class are useless + iterator_core_access(); //undefined + }; + + // + // iterator_facade - use as a public base class for defining new + // standard-conforming iterators. + // + template < + class Derived // The derived iterator type being constructed + , class Value + , class CategoryOrTraversal + , class Reference = Value& + , class Difference = std::ptrdiff_t + > + class iterator_facade +# ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE + : public boost::detail::iterator_facade_types< + Value, CategoryOrTraversal, Reference, Difference + >::base +# undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE +# endif + { + private: + // + // Curiously Recurring Template interface. + // + Derived& derived() + { + return *static_cast(this); + } + + Derived const& derived() const + { + return *static_cast(this); + } + + typedef boost::detail::iterator_facade_types< + Value, CategoryOrTraversal, Reference, Difference + > associated_types; + + protected: + // For use by derived classes + typedef iterator_facade iterator_facade_; + + public: + + typedef typename associated_types::value_type value_type; + typedef Reference reference; + typedef Difference difference_type; + typedef typename associated_types::pointer pointer; + typedef typename associated_types::iterator_category iterator_category; + + reference operator*() const + { + return iterator_core_access::dereference(this->derived()); + } + + typename boost::detail::operator_arrow_result< + value_type + , reference + , pointer + >::type + operator->() const + { + return boost::detail::operator_arrow_result< + value_type + , reference + , pointer + >::make(*this->derived()); + } + + typename boost::detail::operator_brackets_result::type + operator[](difference_type n) const + { + typedef boost::detail::use_operator_brackets_proxy use_proxy; + + return boost::detail::make_operator_brackets_result( + this->derived() + n + , use_proxy() + ); + } + + Derived& operator++() + { + iterator_core_access::increment(this->derived()); + return this->derived(); + } + +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + typename boost::detail::postfix_increment_result::type + operator++(int) + { + typename boost::detail::postfix_increment_result::type + tmp(this->derived()); + ++*this; + return tmp; + } +# endif + + Derived& operator--() + { + iterator_core_access::decrement(this->derived()); + return this->derived(); + } + + Derived operator--(int) + { + Derived tmp(this->derived()); + --*this; + return tmp; + } + + Derived& operator+=(difference_type n) + { + iterator_core_access::advance(this->derived(), n); + return this->derived(); + } + + Derived& operator-=(difference_type n) + { + iterator_core_access::advance(this->derived(), -n); + return this->derived(); + } + + Derived operator-(difference_type x) const + { + Derived result(this->derived()); + return result -= x; + } + +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + // There appears to be a bug which trashes the data of classes + // derived from iterator_facade when they are assigned unless we + // define this assignment operator. This bug is only revealed + // (so far) in STLPort debug mode, but it's clearly a codegen + // problem so we apply the workaround for all MSVC6. + iterator_facade& operator=(iterator_facade const&) + { + return *this; + } +# endif + }; + +# if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + template + inline typename boost::detail::postfix_increment_result::type + operator++( + iterator_facade& i + , int + ) + { + typename boost::detail::postfix_increment_result::type + tmp(*static_cast(&i)); + + ++i; + + return tmp; + } +# endif + + + // + // Comparison operator implementation. The library supplied operators + // enables the user to provide fully interoperable constant/mutable + // iterator types. I.e. the library provides all operators + // for all mutable/constant iterator combinations. + // + // Note though that this kind of interoperability for constant/mutable + // iterators is not required by the standard for container iterators. + // All the standard asks for is a conversion mutable -> constant. + // Most standard library implementations nowadays provide fully interoperable + // iterator implementations, but there are still heavily used implementations + // that do not provide them. (Actually it's even worse, they do not provide + // them for only a few iterators.) + // + // ?? Maybe a BOOST_ITERATOR_NO_FULL_INTEROPERABILITY macro should + // enable the user to turn off mixed type operators + // + // The library takes care to provide only the right operator overloads. + // I.e. + // + // bool operator==(Iterator, Iterator); + // bool operator==(ConstIterator, Iterator); + // bool operator==(Iterator, ConstIterator); + // bool operator==(ConstIterator, ConstIterator); + // + // ... + // + // In order to do so it uses c++ idioms that are not yet widely supported + // by current compiler releases. The library is designed to degrade gracefully + // in the face of compiler deficiencies. In general compiler + // deficiencies result in less strict error checking and more obscure + // error messages, functionality is not affected. + // + // For full operation compiler support for "Substitution Failure Is Not An Error" + // (aka. enable_if) and boost::is_convertible is required. + // + // The following problems occur if support is lacking. + // + // Pseudo code + // + // --------------- + // AdaptorA a1; + // AdaptorA a2; + // + // // This will result in a no such overload error in full operation + // // If enable_if or is_convertible is not supported + // // The instantiation will fail with an error hopefully indicating that + // // there is no operator== for Iterator1, Iterator2 + // // The same will happen if no enable_if is used to remove + // // false overloads from the templated conversion constructor + // // of AdaptorA. + // + // a1 == a2; + // ---------------- + // + // AdaptorA a; + // AdaptorB b; + // + // // This will result in a no such overload error in full operation + // // If enable_if is not supported the static assert used + // // in the operator implementation will fail. + // // This will accidently work if is_convertible is not supported. + // + // a == b; + // ---------------- + // + +# ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP +# define BOOST_ITERATOR_CONVERTIBLE(a,b) mpl::true_() +# else +# define BOOST_ITERATOR_CONVERTIBLE(a,b) is_convertible() +# endif + +# define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, return_prefix, base_op) \ + BOOST_ITERATOR_FACADE_INTEROP_HEAD(inline, op, result_type) \ + { \ + /* For those compilers that do not support enable_if */ \ + BOOST_STATIC_ASSERT(( \ + is_interoperable< Derived1, Derived2 >::value \ + )); \ + return_prefix iterator_core_access::base_op( \ + *static_cast(&lhs) \ + , *static_cast(&rhs) \ + , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \ + ); \ + } + +# define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \ + BOOST_ITERATOR_FACADE_INTEROP( \ + op \ + , boost::detail::always_bool2 \ + , return_prefix \ + , base_op \ + ) + + BOOST_ITERATOR_FACADE_RELATION(==, return, equal) + BOOST_ITERATOR_FACADE_RELATION(!=, return !, equal) + + BOOST_ITERATOR_FACADE_RELATION(<, return 0 >, distance_from) + BOOST_ITERATOR_FACADE_RELATION(>, return 0 <, distance_from) + BOOST_ITERATOR_FACADE_RELATION(<=, return 0 >=, distance_from) + BOOST_ITERATOR_FACADE_RELATION(>=, return 0 <=, distance_from) +# undef BOOST_ITERATOR_FACADE_RELATION + + // operator- requires an additional part in the static assertion + BOOST_ITERATOR_FACADE_INTEROP( + - + , boost::detail::choose_difference_type + , return + , distance_from + ) +# undef BOOST_ITERATOR_FACADE_INTEROP +# undef BOOST_ITERATOR_FACADE_INTEROP_HEAD + +# define BOOST_ITERATOR_FACADE_PLUS(args) \ + BOOST_ITERATOR_FACADE_PLUS_HEAD(inline, args) \ + { \ + Derived tmp(static_cast(i)); \ + return tmp += n; \ + } + +BOOST_ITERATOR_FACADE_PLUS(( + iterator_facade const& i + , typename Derived::difference_type n +)) + +BOOST_ITERATOR_FACADE_PLUS(( + typename Derived::difference_type n + , iterator_facade const& i +)) +# undef BOOST_ITERATOR_FACADE_PLUS +# undef BOOST_ITERATOR_FACADE_PLUS_HEAD + +} // namespace boost + +#include + +#endif // BOOST_ITERATOR_FACADE_23022003THW_HPP diff --git a/win32/include/boost/iterator/iterator_traits.hpp b/win32/include/boost/iterator/iterator_traits.hpp new file mode 100755 index 000000000..986b08f62 --- /dev/null +++ b/win32/include/boost/iterator/iterator_traits.hpp @@ -0,0 +1,92 @@ +// Copyright David Abrahams 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef ITERATOR_TRAITS_DWA200347_HPP +# define ITERATOR_TRAITS_DWA200347_HPP + +# include +# include + +namespace boost { + +// Unfortunately, g++ 2.95.x chokes when we define a class template +// iterator_category which has the same name as its +// std::iterator_category() function, probably due in part to the +// "std:: is visible globally" hack it uses. Use +// BOOST_ITERATOR_CATEGORY to write code that's portable to older +// GCCs. + +# if BOOST_WORKAROUND(__GNUC__, <= 2) +# define BOOST_ITERATOR_CATEGORY iterator_category_ +# else +# define BOOST_ITERATOR_CATEGORY iterator_category +# endif + + +template +struct iterator_value +{ + typedef typename boost::detail::iterator_traits::value_type type; +}; + +template +struct iterator_reference +{ + typedef typename boost::detail::iterator_traits::reference type; +}; + + +template +struct iterator_pointer +{ + typedef typename boost::detail::iterator_traits::pointer type; +}; + +template +struct iterator_difference +{ + typedef typename boost::detail::iterator_traits::difference_type type; +}; + +template +struct BOOST_ITERATOR_CATEGORY +{ + typedef typename boost::detail::iterator_traits::iterator_category type; +}; + +# if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +template <> +struct iterator_value +{ + typedef void type; +}; + +template <> +struct iterator_reference +{ + typedef void type; +}; + +template <> +struct iterator_pointer +{ + typedef void type; +}; + +template <> +struct iterator_difference +{ + typedef void type; +}; + +template <> +struct BOOST_ITERATOR_CATEGORY +{ + typedef void type; +}; +# endif + +} // namespace boost::iterator + +#endif // ITERATOR_TRAITS_DWA200347_HPP diff --git a/win32/include/boost/iterator/new_iterator_tests.hpp b/win32/include/boost/iterator/new_iterator_tests.hpp new file mode 100755 index 000000000..a6a95eb78 --- /dev/null +++ b/win32/include/boost/iterator/new_iterator_tests.hpp @@ -0,0 +1,264 @@ +#ifndef BOOST_NEW_ITERATOR_TESTS_HPP +# define BOOST_NEW_ITERATOR_TESTS_HPP + +// +// Copyright (c) David Abrahams 2001. +// Copyright (c) Jeremy Siek 2001-2003. +// Copyright (c) Thomas Witt 2002. +// +// Use, modification and distribution is subject to 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) +// + +// This is meant to be the beginnings of a comprehensive, generic +// test suite for STL concepts such as iterators and containers. +// +// Revision History: +// 28 Oct 2002 Started update for new iterator categories +// (Jeremy Siek) +// 28 Apr 2002 Fixed input iterator requirements. +// For a == b a++ == b++ is no longer required. +// See 24.1.1/3 for details. +// (Thomas Witt) +// 08 Feb 2001 Fixed bidirectional iterator test so that +// --i is no longer a precondition. +// (Jeremy Siek) +// 04 Feb 2001 Added lvalue test, corrected preconditions +// (David Abrahams) + +# include +# include +# include +# include // for detail::dummy_constructor +# include +# include +# include +# include + +# include +# include +# include + +namespace boost { + + +// Do separate tests for *i++ so we can treat, e.g., smart pointers, +// as readable and/or writable iterators. +template +void readable_iterator_traversal_test(Iterator i1, T v, mpl::true_) +{ + T v2(*i1++); + BOOST_TEST(v == v2); +} + +template +void readable_iterator_traversal_test(const Iterator i1, T v, mpl::false_) +{} + +template +void writable_iterator_traversal_test(Iterator i1, T v, mpl::true_) +{ + ++i1; // we just wrote into that position + *i1++ = v; + Iterator x(i1++); + (void)x; +} + +template +void writable_iterator_traversal_test(const Iterator i1, T v, mpl::false_) +{} + + +// Preconditions: *i == v +template +void readable_iterator_test(const Iterator i1, T v) +{ + Iterator i2(i1); // Copy Constructible + typedef typename detail::iterator_traits::reference ref_t; + ref_t r1 = *i1; + ref_t r2 = *i2; + T v1 = r1; + T v2 = r2; + BOOST_TEST(v1 == v); + BOOST_TEST(v2 == v); + +# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + readable_iterator_traversal_test(i1, v, detail::is_postfix_incrementable()); + + // I think we don't really need this as it checks the same things as + // the above code. + BOOST_STATIC_ASSERT(is_readable_iterator::value); +# endif +} + +template +void writable_iterator_test(Iterator i, T v, T v2) +{ + Iterator i2(i); // Copy Constructible + *i2 = v; + +# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + writable_iterator_traversal_test( + i, v2, mpl::and_< + detail::is_incrementable + , detail::is_postfix_incrementable + >()); +# endif +} + +template +void swappable_iterator_test(Iterator i, Iterator j) +{ + Iterator i2(i), j2(j); + typename detail::iterator_traits::value_type bi = *i, bj = *j; + iter_swap(i2, j2); + typename detail::iterator_traits::value_type ai = *i, aj = *j; + BOOST_TEST(bi == aj && bj == ai); +} + +template +void constant_lvalue_iterator_test(Iterator i, T v1) +{ + Iterator i2(i); + typedef typename detail::iterator_traits::value_type value_type; + typedef typename detail::iterator_traits::reference reference; + BOOST_STATIC_ASSERT((is_same::value)); + const T& v2 = *i2; + BOOST_TEST(v1 == v2); +# ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!is_non_const_lvalue_iterator::value); +# endif +} + +template +void non_const_lvalue_iterator_test(Iterator i, T v1, T v2) +{ + Iterator i2(i); + typedef typename detail::iterator_traits::value_type value_type; + typedef typename detail::iterator_traits::reference reference; + BOOST_STATIC_ASSERT((is_same::value)); + T& v3 = *i2; + BOOST_TEST(v1 == v3); + + // A non-const lvalue iterator is not neccessarily writable, but we + // are assuming the value_type is assignable here + *i = v2; + + T& v4 = *i2; + BOOST_TEST(v2 == v4); +# ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(is_non_const_lvalue_iterator::value); +# endif +} + +template +void forward_readable_iterator_test(Iterator i, Iterator j, T val1, T val2) +{ + Iterator i2; + Iterator i3(i); + i2 = i; + BOOST_TEST(i2 == i3); + BOOST_TEST(i != j); + BOOST_TEST(i2 != j); + readable_iterator_test(i, val1); + readable_iterator_test(i2, val1); + readable_iterator_test(i3, val1); + + BOOST_TEST(i == i2++); + BOOST_TEST(i != ++i3); + + readable_iterator_test(i2, val2); + readable_iterator_test(i3, val2); + + readable_iterator_test(i, val1); +} + +template +void forward_swappable_iterator_test(Iterator i, Iterator j, T val1, T val2) +{ + forward_readable_iterator_test(i, j, val1, val2); + Iterator i2 = i; + ++i2; + swappable_iterator_test(i, i2); +} + +// bidirectional +// Preconditions: *i == v1, *++i == v2 +template +void bidirectional_readable_iterator_test(Iterator i, T v1, T v2) +{ + Iterator j(i); + ++j; + forward_readable_iterator_test(i, j, v1, v2); + ++i; + + Iterator i1 = i, i2 = i; + + BOOST_TEST(i == i1--); + BOOST_TEST(i != --i2); + + readable_iterator_test(i, v2); + readable_iterator_test(i1, v1); + readable_iterator_test(i2, v1); + + --i; + BOOST_TEST(i == i1); + BOOST_TEST(i == i2); + ++i1; + ++i2; + + readable_iterator_test(i, v1); + readable_iterator_test(i1, v2); + readable_iterator_test(i2, v2); +} + +// random access +// Preconditions: [i,i+N) is a valid range +template +void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals) +{ + bidirectional_readable_iterator_test(i, vals[0], vals[1]); + const Iterator j = i; + int c; + + for (c = 0; c < N-1; ++c) + { + BOOST_TEST(i == j + c); + BOOST_TEST(*i == vals[c]); + typename detail::iterator_traits::value_type x = j[c]; + BOOST_TEST(*i == x); + BOOST_TEST(*i == *(j + c)); + BOOST_TEST(*i == *(c + j)); + ++i; + BOOST_TEST(i > j); + BOOST_TEST(i >= j); + BOOST_TEST(j <= i); + BOOST_TEST(j < i); + } + + Iterator k = j + N - 1; + for (c = 0; c < N-1; ++c) + { + BOOST_TEST(i == k - c); + BOOST_TEST(*i == vals[N - 1 - c]); + typename detail::iterator_traits::value_type x = j[N - 1 - c]; + BOOST_TEST(*i == x); + Iterator q = k - c; + BOOST_TEST(*i == *q); + BOOST_TEST(i > j); + BOOST_TEST(i >= j); + BOOST_TEST(j <= i); + BOOST_TEST(j < i); + --i; + } +} + +} // namespace boost + +# include + +#endif // BOOST_NEW_ITERATOR_TESTS_HPP diff --git a/win32/include/boost/iterator/permutation_iterator.hpp b/win32/include/boost/iterator/permutation_iterator.hpp new file mode 100755 index 000000000..05c740d34 --- /dev/null +++ b/win32/include/boost/iterator/permutation_iterator.hpp @@ -0,0 +1,72 @@ +// (C) Copyright Toon Knapen 2001. +// (C) Copyright David Abrahams 2003. +// (C) Copyright Roland Richter 2003. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PERMUTATION_ITERATOR_HPP +#define BOOST_PERMUTATION_ITERATOR_HPP + +#include + +#include + + +namespace boost +{ + +template< class ElementIterator + , class IndexIterator> +class permutation_iterator + : public iterator_adaptor< + permutation_iterator + , IndexIterator, typename detail::iterator_traits::value_type + , use_default, typename detail::iterator_traits::reference> +{ + typedef iterator_adaptor< + permutation_iterator + , IndexIterator, typename detail::iterator_traits::value_type + , use_default, typename detail::iterator_traits::reference> super_t; + + friend class iterator_core_access; + +public: + permutation_iterator() : m_elt_iter() {} + + explicit permutation_iterator(ElementIterator x, IndexIterator y) + : super_t(y), m_elt_iter(x) {} + + template + permutation_iterator( + permutation_iterator const& r + , typename enable_if_convertible::type* = 0 + , typename enable_if_convertible::type* = 0 + ) + : super_t(r.base()), m_elt_iter(r.m_elt_iter) + {} + +private: + typename super_t::reference dereference() const + { return *(m_elt_iter + *this->base()); } + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + template friend class permutation_iterator; +#else + public: +#endif + ElementIterator m_elt_iter; +}; + + +template +permutation_iterator +make_permutation_iterator( ElementIterator e, IndexIterator i ) +{ + return permutation_iterator( e, i ); +} + + +} // namespace boost + +#endif diff --git a/win32/include/boost/iterator/reverse_iterator.hpp b/win32/include/boost/iterator/reverse_iterator.hpp new file mode 100755 index 000000000..59bbbc06d --- /dev/null +++ b/win32/include/boost/iterator/reverse_iterator.hpp @@ -0,0 +1,69 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_REVERSE_ITERATOR_23022003THW_HPP +#define BOOST_REVERSE_ITERATOR_23022003THW_HPP + +#include +#include +#include + +namespace boost +{ + + // + // + // + template + class reverse_iterator + : public iterator_adaptor< reverse_iterator, Iterator > + { + typedef iterator_adaptor< reverse_iterator, Iterator > super_t; + + friend class iterator_core_access; + + public: + reverse_iterator() {} + + explicit reverse_iterator(Iterator x) + : super_t(x) {} + + template + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::type* = 0 + ) + : super_t(r.base()) + {} + + private: + typename super_t::reference dereference() const { return *boost::prior(this->base()); } + + void increment() { --this->base_reference(); } + void decrement() { ++this->base_reference(); } + + void advance(typename super_t::difference_type n) + { + this->base_reference() += -n; + } + + template + typename super_t::difference_type + distance_to(reverse_iterator const& y) const + { + return this->base_reference() - y.base(); + } + }; + + template + reverse_iterator make_reverse_iterator(BidirectionalIterator x) + { + return reverse_iterator(x); + } + +} // namespace boost + +#endif // BOOST_REVERSE_ITERATOR_23022003THW_HPP diff --git a/win32/include/boost/iterator/transform_iterator.hpp b/win32/include/boost/iterator/transform_iterator.hpp new file mode 100755 index 000000000..ce168cd23 --- /dev/null +++ b/win32/include/boost/iterator/transform_iterator.hpp @@ -0,0 +1,188 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_TRANSFORM_ITERATOR_23022003THW_HPP +#define BOOST_TRANSFORM_ITERATOR_23022003THW_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) +# include + +#endif +#include + + +namespace boost +{ + template + class transform_iterator; + + namespace detail + { + + template + struct function_object_result + { + typedef typename UnaryFunc::result_type type; + }; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct function_object_result + { + typedef Return type; + }; +#endif + + // Compute the iterator_adaptor instantiation to be used for transform_iterator + template + struct transform_iterator_base + { + private: + // By default, dereferencing the iterator yields the same as + // the function. Do we need to adjust the way + // function_object_result is computed for the standard + // proposal (e.g. using Doug's result_of)? + typedef typename ia_dflt_help< + Reference + , function_object_result + >::type reference; + + // To get the default for Value: remove any reference on the + // result type, but retain any constness to signal + // non-writability. Note that if we adopt Thomas' suggestion + // to key non-writability *only* on the Reference argument, + // we'd need to strip constness here as well. + typedef typename ia_dflt_help< + Value + , remove_reference + >::type cv_value_type; + + public: + typedef iterator_adaptor< + transform_iterator + , Iterator + , cv_value_type + , use_default // Leave the traversal category alone + , reference + > type; + }; + } + + template + class transform_iterator + : public boost::detail::transform_iterator_base::type + { + typedef typename + boost::detail::transform_iterator_base::type + super_t; + + friend class iterator_core_access; + + public: + transform_iterator() { } + + transform_iterator(Iterator const& x, UnaryFunc f) + : super_t(x), m_f(f) { } + + explicit transform_iterator(Iterator const& x) + : super_t(x) + { + // Pro8 is a little too aggressive about instantiating the + // body of this function. +#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + // don't provide this constructor if UnaryFunc is a + // function pointer type, since it will be 0. Too dangerous. + BOOST_STATIC_ASSERT(is_class::value); +#endif + } + + template< + class OtherUnaryFunction + , class OtherIterator + , class OtherReference + , class OtherValue> + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::type* = 0 +#if !BOOST_WORKAROUND(BOOST_MSVC, == 1310) + , typename enable_if_convertible::type* = 0 +#endif + ) + : super_t(t.base()), m_f(t.functor()) + {} + + UnaryFunc functor() const + { return m_f; } + + private: + typename super_t::reference dereference() const + { return m_f(*this->base()); } + + // Probably should be the initial base class so it can be + // optimized away via EBO if it is an empty class. + UnaryFunc m_f; + }; + + template + transform_iterator + make_transform_iterator(Iterator it, UnaryFunc fun) + { + return transform_iterator(it, fun); + } + + // Version which allows explicit specification of the UnaryFunc + // type. + // + // This generator is not provided if UnaryFunc is a function + // pointer type, because it's too dangerous: the default-constructed + // function pointer in the iterator be 0, leading to a runtime + // crash. + template +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + typename mpl::if_< +#else + typename iterators::enable_if< +#endif + is_class // We should probably find a cheaper test than is_class<> + , transform_iterator +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + , int[3] +#endif + >::type + make_transform_iterator(Iterator it) + { + return transform_iterator(it, UnaryFunc()); + } + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + template + transform_iterator< Return (*)(Argument), Iterator, Return> + make_transform_iterator(Iterator it, Return (*fun)(Argument)) + { + return transform_iterator(it, fun); + } +#endif + +} // namespace boost + +#include + +#endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP diff --git a/win32/include/boost/iterator/zip_iterator.hpp b/win32/include/boost/iterator/zip_iterator.hpp new file mode 100755 index 000000000..edc7e0957 --- /dev/null +++ b/win32/include/boost/iterator/zip_iterator.hpp @@ -0,0 +1,585 @@ +// Copyright David Abrahams and Thomas Becker 2000-2006. Distributed +// under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_ +# define BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_ + +#include +#include +#include +#include +#include // for enable_if_convertible +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + + // Zip iterator forward declaration for zip_iterator_base + template + class zip_iterator; + + // One important design goal of the zip_iterator is to isolate all + // functionality whose implementation relies on the current tuple + // implementation. This goal has been achieved as follows: Inside + // the namespace detail there is a namespace tuple_impl_specific. + // This namespace encapsulates all functionality that is specific + // to the current Boost tuple implementation. More precisely, the + // namespace tuple_impl_specific provides the following tuple + // algorithms and meta-algorithms for the current Boost tuple + // implementation: + // + // tuple_meta_transform + // tuple_meta_accumulate + // tuple_transform + // tuple_for_each + // + // If the tuple implementation changes, all that needs to be + // replaced is the implementation of these four (meta-)algorithms. + + namespace detail + { + + // Functors to be used with tuple algorithms + // + template + class advance_iterator + { + public: + advance_iterator(DiffType step) : m_step(step) {} + + template + void operator()(Iterator& it) const + { it += m_step; } + + private: + DiffType m_step; + }; + // + struct increment_iterator + { + template + void operator()(Iterator& it) + { ++it; } + }; + // + struct decrement_iterator + { + template + void operator()(Iterator& it) + { --it; } + }; + // + struct dereference_iterator + { + template + struct apply + { + typedef typename + iterator_traits::reference + type; + }; + + template + typename apply::type operator()(Iterator const& it) + { return *it; } + }; + + + // The namespace tuple_impl_specific provides two meta- + // algorithms and two algorithms for tuples. + // + namespace tuple_impl_specific + { + // Meta-transform algorithm for tuples + // + template + struct tuple_meta_transform; + + template + struct tuple_meta_transform_impl + { + typedef tuples::cons< + typename mpl::apply1< + typename mpl::lambda::type + , typename Tuple::head_type + >::type + , typename tuple_meta_transform< + typename Tuple::tail_type + , UnaryMetaFun + >::type + > type; + }; + + template + struct tuple_meta_transform + : mpl::eval_if< + boost::is_same + , mpl::identity + , tuple_meta_transform_impl + > + { + }; + + // Meta-accumulate algorithm for tuples. Note: The template + // parameter StartType corresponds to the initial value in + // ordinary accumulation. + // + template + struct tuple_meta_accumulate; + + template< + typename Tuple + , class BinaryMetaFun + , typename StartType + > + struct tuple_meta_accumulate_impl + { + typedef typename mpl::apply2< + typename mpl::lambda::type + , typename Tuple::head_type + , typename tuple_meta_accumulate< + typename Tuple::tail_type + , BinaryMetaFun + , StartType + >::type + >::type type; + }; + + template< + typename Tuple + , class BinaryMetaFun + , typename StartType + > + struct tuple_meta_accumulate + : mpl::eval_if< +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + mpl::or_< +#endif + boost::is_same +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + , boost::is_same + > +#endif + , mpl::identity + , tuple_meta_accumulate_impl< + Tuple + , BinaryMetaFun + , StartType + > + > + { + }; + +#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ + || ( \ + BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, != 0) && defined(_MSC_VER) \ + ) +// Not sure why intel's partial ordering fails in this case, but I'm +// assuming int's an MSVC bug-compatibility feature. + +# define BOOST_TUPLE_ALGO_DISPATCH +# define BOOST_TUPLE_ALGO(algo) algo##_impl +# define BOOST_TUPLE_ALGO_TERMINATOR , int +# define BOOST_TUPLE_ALGO_RECURSE , ... +#else +# define BOOST_TUPLE_ALGO(algo) algo +# define BOOST_TUPLE_ALGO_TERMINATOR +# define BOOST_TUPLE_ALGO_RECURSE +#endif + + // transform algorithm for tuples. The template parameter Fun + // must be a unary functor which is also a unary metafunction + // class that computes its return type based on its argument + // type. For example: + // + // struct to_ptr + // { + // template + // struct apply + // { + // typedef Arg* type; + // } + // + // template + // Arg* operator()(Arg x); + // }; + template + tuples::null_type BOOST_TUPLE_ALGO(tuple_transform) + (tuples::null_type const&, Fun BOOST_TUPLE_ALGO_TERMINATOR) + { return tuples::null_type(); } + + template + typename tuple_meta_transform< + Tuple + , Fun + >::type + + BOOST_TUPLE_ALGO(tuple_transform)( + const Tuple& t, + Fun f + BOOST_TUPLE_ALGO_RECURSE + ) + { + typedef typename tuple_meta_transform< + BOOST_DEDUCED_TYPENAME Tuple::tail_type + , Fun + >::type transformed_tail_type; + + return tuples::cons< + BOOST_DEDUCED_TYPENAME mpl::apply1< + Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type + >::type + , transformed_tail_type + >( + f(boost::tuples::get<0>(t)), tuple_transform(t.get_tail(), f) + ); + } + +#ifdef BOOST_TUPLE_ALGO_DISPATCH + template + typename tuple_meta_transform< + Tuple + , Fun + >::type + + tuple_transform( + const Tuple& t, + Fun f + ) + { + return tuple_transform_impl(t, f, 1); + } +#endif + + // for_each algorithm for tuples. + // + template + Fun BOOST_TUPLE_ALGO(tuple_for_each)( + tuples::null_type + , Fun f BOOST_TUPLE_ALGO_TERMINATOR + ) + { return f; } + + + template + Fun BOOST_TUPLE_ALGO(tuple_for_each)( + Tuple& t + , Fun f BOOST_TUPLE_ALGO_RECURSE) + { + f( t.get_head() ); + return tuple_for_each(t.get_tail(), f); + } + +#ifdef BOOST_TUPLE_ALGO_DISPATCH + template + Fun + tuple_for_each( + Tuple& t, + Fun f + ) + { + return tuple_for_each_impl(t, f, 1); + } +#endif + + // Equality of tuples. NOTE: "==" for tuples currently (7/2003) + // has problems under some compilers, so I just do my own. + // No point in bringing in a bunch of #ifdefs here. This is + // going to go away with the next tuple implementation anyway. + // + inline bool tuple_equal(tuples::null_type, tuples::null_type) + { return true; } + + template + bool tuple_equal( + Tuple1 const& t1, + Tuple2 const& t2 + ) + { + return t1.get_head() == t2.get_head() && + tuple_equal(t1.get_tail(), t2.get_tail()); + } + } + // + // end namespace tuple_impl_specific + + template + struct iterator_reference + { + typedef typename iterator_traits::reference type; + }; + +#ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT + // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work + // out well. Instantiating the nested apply template also + // requires instantiating iterator_traits on the + // placeholder. Instead we just specialize it as a metafunction + // class. + template<> + struct iterator_reference + { + template + struct apply : iterator_reference {}; + }; +#endif + + // Metafunction to obtain the type of the tuple whose element types + // are the reference types of an iterator tuple. + // + template + struct tuple_of_references + : tuple_impl_specific::tuple_meta_transform< + IteratorTuple, + iterator_reference + > + { + }; + + // Metafunction to obtain the minimal traversal tag in a tuple + // of iterators. + // + template + struct minimum_traversal_category_in_iterator_tuple + { + typedef typename tuple_impl_specific::tuple_meta_transform< + IteratorTuple + , iterator_traversal<> + >::type tuple_of_traversal_tags; + + typedef typename tuple_impl_specific::tuple_meta_accumulate< + tuple_of_traversal_tags + , minimum_category<> + , random_access_traversal_tag + >::type type; + }; + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) // ETI workaround + template <> + struct minimum_traversal_category_in_iterator_tuple + { + typedef int type; + }; +#endif + + // We need to call tuple_meta_accumulate with mpl::and_ as the + // accumulating functor. To this end, we need to wrap it into + // a struct that has exactly two arguments (that is, template + // parameters) and not five, like mpl::and_ does. + // + template + struct and_with_two_args + : mpl::and_ + { + }; + +# ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT + // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work + // out well. In this case I think it's an MPL bug + template<> + struct and_with_two_args + { + template + struct apply : mpl::and_ + {}; + }; +# endif + + /////////////////////////////////////////////////////////////////// + // + // Class zip_iterator_base + // + // Builds and exposes the iterator facade type from which the zip + // iterator will be derived. + // + template + struct zip_iterator_base + { + private: + // Reference type is the type of the tuple obtained from the + // iterators' reference types. + typedef typename + detail::tuple_of_references::type reference; + + // Value type is the same as reference type. + typedef reference value_type; + + // Difference type is the first iterator's difference type + typedef typename iterator_traits< + typename tuples::element<0, IteratorTuple>::type + >::difference_type difference_type; + + // Traversal catetgory is the minimum traversal category in the + // iterator tuple. + typedef typename + detail::minimum_traversal_category_in_iterator_tuple< + IteratorTuple + >::type traversal_category; + public: + + // The iterator facade type from which the zip iterator will + // be derived. + typedef iterator_facade< + zip_iterator, + value_type, + traversal_category, + reference, + difference_type + > type; + }; + + template <> + struct zip_iterator_base + { + typedef int type; + }; + } + + ///////////////////////////////////////////////////////////////////// + // + // zip_iterator class definition + // + template + class zip_iterator : + public detail::zip_iterator_base::type + { + + // Typedef super_t as our base class. + typedef typename + detail::zip_iterator_base::type super_t; + + // iterator_core_access is the iterator's best friend. + friend class iterator_core_access; + + public: + + // Construction + // ============ + + // Default constructor + zip_iterator() { } + + // Constructor from iterator tuple + zip_iterator(IteratorTuple iterator_tuple) + : m_iterator_tuple(iterator_tuple) + { } + + // Copy constructor + template + zip_iterator( + const zip_iterator& other, + typename enable_if_convertible< + OtherIteratorTuple, + IteratorTuple + >::type* = 0 + ) : m_iterator_tuple(other.get_iterator_tuple()) + {} + + // Get method for the iterator tuple. + const IteratorTuple& get_iterator_tuple() const + { return m_iterator_tuple; } + + private: + + // Implementation of Iterator Operations + // ===================================== + + // Dereferencing returns a tuple built from the dereferenced + // iterators in the iterator tuple. + typename super_t::reference dereference() const + { + return detail::tuple_impl_specific::tuple_transform( + get_iterator_tuple(), + detail::dereference_iterator() + ); + } + + // Two zip iterators are equal if all iterators in the iterator + // tuple are equal. NOTE: It should be possible to implement this + // as + // + // return get_iterator_tuple() == other.get_iterator_tuple(); + // + // but equality of tuples currently (7/2003) does not compile + // under several compilers. No point in bringing in a bunch + // of #ifdefs here. + // + template + bool equal(const zip_iterator& other) const + { + return detail::tuple_impl_specific::tuple_equal( + get_iterator_tuple(), + other.get_iterator_tuple() + ); + } + + // Advancing a zip iterator means to advance all iterators in the + // iterator tuple. + void advance(typename super_t::difference_type n) + { + detail::tuple_impl_specific::tuple_for_each( + m_iterator_tuple, + detail::advance_iterator(n) + ); + } + // Incrementing a zip iterator means to increment all iterators in + // the iterator tuple. + void increment() + { + detail::tuple_impl_specific::tuple_for_each( + m_iterator_tuple, + detail::increment_iterator() + ); + } + + // Decrementing a zip iterator means to decrement all iterators in + // the iterator tuple. + void decrement() + { + detail::tuple_impl_specific::tuple_for_each( + m_iterator_tuple, + detail::decrement_iterator() + ); + } + + // Distance is calculated using the first iterator in the tuple. + template + typename super_t::difference_type distance_to( + const zip_iterator& other + ) const + { + return boost::tuples::get<0>(other.get_iterator_tuple()) - + boost::tuples::get<0>(this->get_iterator_tuple()); + } + + // Data Members + // ============ + + // The iterator tuple. + IteratorTuple m_iterator_tuple; + + }; + + // Make function for zip iterator + // + template + zip_iterator + make_zip_iterator(IteratorTuple t) + { return zip_iterator(t); } + +} + +#endif diff --git a/win32/include/boost/iterator_adaptors.hpp b/win32/include/boost/iterator_adaptors.hpp new file mode 100755 index 000000000..51b0fe247 --- /dev/null +++ b/win32/include/boost/iterator_adaptors.hpp @@ -0,0 +1,13 @@ +// Copyright David Abrahams 2004. 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) + +// See www.boost.org/libs/iterator for documentation. + +#ifndef ITERATOR_ADAPTORS_DWA2004725_HPP +# define ITERATOR_ADAPTORS_DWA2004725_HPP + +#define BOOST_ITERATOR_ADAPTORS_VERSION 0x0200 +#include + +#endif // ITERATOR_ADAPTORS_DWA2004725_HPP diff --git a/win32/include/boost/lambda/algorithm.hpp b/win32/include/boost/lambda/algorithm.hpp new file mode 100755 index 000000000..42349c145 --- /dev/null +++ b/win32/include/boost/lambda/algorithm.hpp @@ -0,0 +1,1377 @@ +// -- algorithm.hpp -- Boost Lambda Library ----------------------------------- +// Copyright (C) 2002 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +// Copyright (C) 2002 Gary Powell (gwpowell@hotmail.com) +// +// 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) +// +// For more information, see http://www.boost.org + +#ifndef BOOST_LAMBDA_ALGORITHM_HPP +#define BOOST_LAMBDA_ALGORITHM_HPP + +#include "boost/lambda/core.hpp" + +#include +#include // for iterator_traits +#include // for std::pair + +namespace boost { + namespace lambda { + +namespace ll { + +// for_each --------------------------------- + +struct for_each { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<3, Args>::type + >::type type; + }; + + template + C + operator()(A a, A b, C c) const + { return ::std::for_each(a, b, c); } +}; + +// find --------------------------------- + +struct find { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b, const C& c) const + { return ::std::find(a, b, c); } +}; + + +// find_if --------------------------------- + +struct find_if { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b, C c) const + { return ::std::find_if(a, b, c); } +}; + +// find_end --------------------------------- + +struct find_end { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b, C c, C d) const + { return ::std::find_end(a, b, c, d); } + + template + A + operator()(A a, A b, C c, C d, E e) const + { return ::std::find_end(a, b, c, d, e); } + +}; + +// find_first_of --------------------------------- + +struct find_first_of { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b, C c, C d) const + { return ::std::find_first_of(a, b, c, d); } + + template + A + operator()(A a, A b, C c, C d, E e) const + { return ::std::find_first_of(a, b, c, d, e); } + +}; + +// adjacent_find --------------------------------- + +struct adjacent_find { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b) const + { return ::std::adjacent_find(a, b); } + + template + A + operator()(A a, A b, C c) const + { return ::std::adjacent_find(a, b, c); } + +}; + +// count --------------------------------- + +struct count { + + template + struct sig { + typedef typename ::std::iterator_traits< + typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type + >::difference_type type; + }; + + template + typename ::std::iterator_traits::difference_type + operator()(A a, A b, const C& c) const + { return ::std::count(a, b, c); } +}; + +// count_if --------------------------------- + +struct count_if { + + template + struct sig { + typedef typename ::std::iterator_traits< + typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type + >::difference_type type; + }; + + template + typename ::std::iterator_traits::difference_type + operator()(A a, A b, C c) const + { return ::std::count_if(a, b, c); } +}; + + +// mismatch --------------------------------- + +struct mismatch { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type element1_type; + + typedef typename boost::remove_const< + typename boost::tuples::element<3, Args>::type + >::type element2_type; + + typedef ::std::pair< element1_type, element2_type > type; + }; + + template + ::std::pair + operator()(A a, A b, C c) const + { return ::std::mismatch(a, b, c); } + + template + ::std::pair + operator()(A a, A b, C c, D d) const + { return ::std::mismatch(a, b, c, d); } + +}; + +// equal --------------------------------- + +struct equal { + + template + struct sig { + typedef bool type; + }; + + template + bool + operator()(A a, A b, C c) const + { return ::std::equal(a, b, c); } + + template + bool + operator()(A a, A b, C c, D d) const + { return ::std::equal(a, b, c, d); } + +}; + +// search -------------------------------- + +struct search { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b, C c, C d) const + { return std::search(a, b, c, d);} + + template + A + operator()(A a, A b, C c, C d, E e) const + { return std::search(a, b, c, d, e);} + +}; + +// copy --------------------------------- + +struct copy { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<3, Args>::type + >::type type; + }; + + template + C + operator()(A a, A b, C c) const + { return ::std::copy(a, b, c); } + +}; + +// copy_backward --------------------------------- + +struct copy_backward { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<3, Args>::type + >::type type; + }; + + template + C + operator()(A a, A b, C c) const + { return ::std::copy_backward(a, b, c); } + +}; + +// swap --------------------------------- + +struct swap { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b) const + { ::std::swap(a, b); } + +}; + +// swap_ranges --------------------------------- + +struct swap_ranges { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<3, Args>::type + >::type type; + }; + + template + C + operator()(A a, A b, C c) const + { return ::std::swap_ranges(a, b, c); } + +}; + +// iter_swap --------------------------------- + +struct iter_swap { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b) const + { ::std::iter_swap(a, b); } + +}; + + +// transform -------------------------------- + +struct transform { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element< + boost::tuples::length::value - 2, + Args + >::type + >::type type; + }; + + template + C + operator()(A a, A b, C c, D d) const + { return std::transform(a, b, c, d);} + + template + D + operator()(A a, A b, C c, D d, E e) const + { return std::transform(a, b, c, d, e);} + +}; + +// replace --------------------------------- + +struct replace { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b, const C& c, const C& d) const + { ::std::replace(a, b, c, d); } + +}; + +// replace_if --------------------------------- + +struct replace_if { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b, C c, const D& d) const + { ::std::replace_if(a, b, c, d); } + +}; + +// replace_copy --------------------------------- + +struct replace_copy { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<3, Args>::type + >::type type; + }; + + template + C + operator()(A a, A b, C c, const D& d, const D& e) const + { return ::std::replace_copy(a, b, c, d, e); } + +}; + +// replace_copy_if --------------------------------- + +struct replace_copy_if { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<3, Args>::type + >::type type; + }; + + template + C + operator()(A a, A b, C c, D d, const E& e) const + { return ::std::replace_copy_if(a, b, c, d, e); } + +}; + +// fill --------------------------------- + +struct fill { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b, const C& c) const + { ::std::fill(a, b, c); } + +}; + +// fill_n --------------------------------- + +struct fill_n { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, B b, const C& c) const + { ::std::fill_n(a, b, c); } + +}; + +// generate --------------------------------- + +struct generate { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b, C c) const + { ::std::generate(a, b, c); } + +}; + +// generate_n --------------------------------- + +struct generate_n { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, B b, C c) const + { ::std::generate_n(a, b, c); } + +}; + +// remove --------------------------------- + +struct remove { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b, const C& c) const + { return ::std::remove(a, b, c); } +}; + +// remove_if --------------------------------- + +struct remove_if { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b, C c) const + { return ::std::remove_if(a, b, c); } +}; + +// remove_copy --------------------------------- + +struct remove_copy { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<3, Args>::type + >::type type; + }; + + template + C + operator()(A a, A b, C c, const D& d) const + { return ::std::remove_copy(a, b, c, d); } +}; + +// remove_copy_if --------------------------------- + +struct remove_copy_if { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<3, Args>::type + >::type type; + }; + + template + C + operator()(A a, A b, C c, D d) const + { return ::std::remove_copy_if(a, b, c, d); } +}; + +// unique --------------------------------- + +struct unique { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b) const + { return ::std::unique(a, b); } + + template + A + operator()(A a, A b, C c) const + { return ::std::unique(a, b, c); } + +}; + +// unique_copy --------------------------------- + +struct unique_copy { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<3, Args>::type + >::type type; + }; + + template + C + operator()(A a, A b, C c) const + { return ::std::unique_copy(a, b, c); } + + template + C + operator()(A a, A b, C c, D d) const + { return ::std::unique_copy(a, b, c, d); } + +}; + +// reverse --------------------------------- + +struct reverse { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b) const + { ::std::reverse(a, b); } + +}; + +// reverse_copy --------------------------------- + +struct reverse_copy { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<3, Args>::type + >::type type; + }; + + template + C + operator()(A a, A b, C c) const + { return ::std::reverse_copy(a, b, c); } + +}; + +// rotate --------------------------------- + +struct rotate { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b, A c) const + { ::std::rotate(a, b, c); } + +}; + +// rotate_copy --------------------------------- + +struct rotate_copy { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<3, Args>::type + >::type type; + }; + + template + D + operator()(A a, A b, A c, D d) const + { return ::std::rotate_copy(a, b, c, d); } + +}; + +// random_shuffle --------------------------------- + +struct random_shuffle { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b) const + { ::std::random_shuffle(a, b); } + + template + void + operator()(A a, A b, const C& c) const + { ::std::random_shuffle(a, b, c); } + +}; + + +// partition --------------------------------- + +struct partition { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b, C c) const + { return ::std::partition(a, b, c); } + +}; + +// stable_partition --------------------------------- + +struct stable_partition { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b, C c) const + { return ::std::stable_partition(a, b, c); } + +}; + +// sort --------------------------------- + +struct sort { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b) const + { ::std::sort(a, b); } + + template + void + operator()(A a, A b, C c) const + { ::std::sort(a, b, c); } + +}; + +// stable_sort --------------------------------- + +struct stable_sort { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b) const + { ::std::stable_sort(a, b); } + + template + void + operator()(A a, A b, C c) const + { ::std::stable_sort(a, b, c); } + +}; + +// partial_sort --------------------------------- + +struct partial_sort { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b, A c) const + { ::std::partial_sort(a, b, c); } + + template + void + operator()(A a, A b, A c, D d) const + { ::std::partial_sort(a, b, c, d); } + +}; + +// partial_sort_copy --------------------------------- + +struct partial_sort_copy { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<3, Args>::type + >::type type; + }; + + template + C + operator()(A a, A b, C c, C d) const + { return ::std::partial_sort_copy(a, b, c, d); } + + template + C + operator()(A a, A b, C c, C d, E e) const + { return ::std::partial_sort_copy(a, b, c, d, e); } +}; + +// nth_element --------------------------------- + +struct nth_element { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b, A c) const + { ::std::nth_element(a, b, c); } + + template + void + operator()(A a, A b, A c, D d) const + { ::std::nth_element(a, b, c, d); } + +}; + +// lower_bound --------------------------------- + +struct lower_bound { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b, const C& c) const + { return ::std::lower_bound(a, b, c); } + + template + A + operator()(A a, A b, const C& c, D d) const + { return ::std::lower_bound(a, b, c, d); } + +}; + +// upper_bound --------------------------------- + +struct upper_bound { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b, const C& c) const + { return ::std::upper_bound(a, b, c); } + + template + A + operator()(A a, A b, const C& c, D d) const + { return ::std::upper_bound(a, b, c, d); } + +}; + +// equal_range --------------------------------- + +struct equal_range { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type element_type; + + typedef ::std::pair< element_type, element_type > type; + }; + + template + ::std::pair + operator()(A a, A b, const C& c) const + { return ::std::equal_range(a, b, c); } + + template + ::std::pair + operator()(A a, A b, const C& c, D d) const + { return ::std::equal_range(a, b, c, d); } + +}; + +// binary_search --------------------------------- + +struct binary_search { + + template + struct sig { + typedef bool type; + }; + + template + bool + operator()(A a, A b, const C& c) const + { return ::std::binary_search(a, b, c); } + + template + bool + operator()(A a, A b, const C& c, D d) const + { return ::std::binary_search(a, b, c, d); } + +}; + +// merge -------------------------------- + +struct merge { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<5, Args>::type + >::type type; + }; + + template + E + operator()(A a, A b, C c, C d, E e) const + { return std::merge(a, b, c, d, e);} + + template + E + operator()(A a, A b, C c, C d, E e, F f) const + { return std::merge(a, b, c, d, e, f);} + +}; + +// inplace_merge --------------------------------- + +struct inplace_merge { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b, A c) const + { ::std::inplace_merge(a, b, c); } + + template + void + operator()(A a, A b, A c, D d) const + { ::std::inplace_merge(a, b, c, d); } + +}; + +// includes --------------------------------- + +struct includes { + + template + struct sig { + typedef bool type; + }; + + template + bool + operator()(A a, A b, C c, C d) const + { return ::std::includes(a, b, c, d); } + + template + bool + operator()(A a, A b, C c, C d, E e) const + { return ::std::includes(a, b, c, d, e); } + +}; + +// set_union -------------------------------- + +struct set_union { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<5, Args>::type + >::type type; + }; + + template + E + operator()(A a, A b, C c, C d, E e) const + { return std::set_union(a, b, c, d, e);} + + template + E + operator()(A a, A b, C c, C d, E e, F f) const + { return std::set_union(a, b, c, d, e, f);} + +}; + +// set_intersection -------------------------------- + +struct set_intersection { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<5, Args>::type + >::type type; + }; + + template + E + operator()(A a, A b, C c, C d, E e) const + { return std::set_intersection(a, b, c, d, e);} + + template + E + operator()(A a, A b, C c, C d, E e, F f) const + { return std::set_intersection(a, b, c, d, e, f);} + +}; + +// set_difference -------------------------------- + +struct set_difference { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<5, Args>::type + >::type type; + }; + + template + E + operator()(A a, A b, C c, C d, E e) const + { return std::set_difference(a, b, c, d, e);} + + template + E + operator()(A a, A b, C c, C d, E e, F f) const + { return std::set_difference(a, b, c, d, e, f);} + +}; + + +// set_symmetric_difference -------------------------------- + +struct set_symmetric_difference { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<5, Args>::type + >::type type; + }; + + template + E + operator()(A a, A b, C c, C d, E e) const + { return std::set_symmetric_difference(a, b, c, d, e);} + + template + E + operator()(A a, A b, C c, C d, E e, F f) const + { return std::set_symmetric_difference(a, b, c, d, e, f);} + +}; + +// push_heap --------------------------------- + +struct push_heap { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b) const + { ::std::push_heap(a, b); } + + template + void + operator()(A a, A b, C c) const + { ::std::push_heap(a, b, c); } + +}; + +// pop_heap --------------------------------- + +struct pop_heap { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b) const + { ::std::pop_heap(a, b); } + + template + void + operator()(A a, A b, C c) const + { ::std::pop_heap(a, b, c); } + +}; + + +// make_heap --------------------------------- + +struct make_heap { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b) const + { ::std::make_heap(a, b); } + + template + void + operator()(A a, A b, C c) const + { ::std::make_heap(a, b, c); } + +}; + +// sort_heap --------------------------------- + +struct sort_heap { + + template + struct sig { + typedef void type; + }; + + template + void + operator()(A a, A b) const + { ::std::sort_heap(a, b); } + + template + void + operator()(A a, A b, C c) const + { ::std::sort_heap(a, b, c); } + +}; + +// min --------------------------------- + +struct min { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(const A& a, const A& b) const + { return (::std::min)(a, b); } + + template + A + operator()(const A& a, const A& b, C c) const + { return (::std::min)(a, b, c); } + +}; + +// max --------------------------------- + +struct max { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(const A& a, const A& b) const + { return (::std::max)(a, b); } + + template + A + operator()(const A& a, const A& b, C c) const + { return (::std::max)(a, b, c); } + +}; + +struct min_element { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b) const + { return ::std::min_element(a, b); } + + template + A + operator()(A a, A b, C c) const + { return ::std::min_element(a, b, c); } + +}; + +// max_element --------------------------------- + +struct max_element { + + template + struct sig { + typedef typename boost::remove_const< + typename boost::tuples::element<1, Args>::type + >::type type; + }; + + template + A + operator()(A a, A b) const + { return ::std::max_element(a, b); } + + template + A + operator()(A a, A b, C c) const + { return ::std::max_element(a, b, c); } + +}; + + +// lexicographical_compare --------------------------------- + +struct lexicographical_compare { + + template + struct sig { + typedef bool type; + }; + + template + bool + operator()(A a, A b, C c, C d) const + { return ::std::lexicographical_compare(a, b, c, d); } + + template + bool + operator()(A a, A b, C c, C d, E e) const + { return ::std::lexicographical_compare(a, b, c, d, e); } + +}; + +// next_permutation --------------------------------- + +struct next_permutation { + + template + struct sig { + typedef bool type; + }; + + template + bool + operator()(A a, A b) const + { return ::std::next_permutation(a, b); } + + template + bool + operator()(A a, A b, C c) const + { return ::std::next_permutation(a, b, c); } + +}; + +// prev_permutation --------------------------------- + +struct prev_permutation { + + template + struct sig { + typedef bool type; + }; + + template + bool + operator()(A a, A b) const + { return ::std::prev_permutation(a, b); } + + template + bool + operator()(A a, A b, C c) const + { return ::std::prev_permutation(a, b, c); } + +}; + + + + + +} // end of ll namespace + +// There is no good way to call an overloaded member function in a +// lambda expression. +// The macro below defines a function object class for calling a +// const_iterator returning member function of a container. + +#define CALL_MEMBER(X) \ +struct call_##X { \ +template \ + struct sig { \ + typedef typename boost::remove_const< \ + typename boost::tuples::element<1, Args>::type \ + >::type::const_iterator type; \ + }; \ + \ + template \ + typename T::const_iterator \ + operator()(const T& t) const \ + { \ + return t.X(); \ + } \ +}; + +// create call_begin and call_end classes +CALL_MEMBER(begin) +CALL_MEMBER(end) + +#undef CALL_MEMBER + +} // end of lambda namespace +} // end of boost namespace + + + +#endif diff --git a/win32/include/boost/lambda/bind.hpp b/win32/include/boost/lambda/bind.hpp new file mode 100755 index 000000000..0fd61464f --- /dev/null +++ b/win32/include/boost/lambda/bind.hpp @@ -0,0 +1,19 @@ +// -- bind.hpp -- Boost Lambda Library -------------------------------------- + +// Copyright (C) 1999-2001 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +// Gary Powell (gwpowell@hotmail.com) +// +// 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) +// +// For more information, see http://www.boost.org + +#ifndef BOOST_LAMBDA_BIND_HPP +#define BOOST_LAMBDA_BIND_HPP + +#include "boost/lambda/core.hpp" + +#include "boost/lambda/detail/bind_functions.hpp" + +#endif diff --git a/win32/include/boost/lambda/casts.hpp b/win32/include/boost/lambda/casts.hpp new file mode 100755 index 000000000..e9608faa9 --- /dev/null +++ b/win32/include/boost/lambda/casts.hpp @@ -0,0 +1,219 @@ +// - casts.hpp -- BLambda Library ------------- +// +// Copyright (C) 2000 Gary Powell (powellg@amazon.com) +// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +// +// 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) +// +// For more information, see http://www.boost.org + +// ----------------------------------------------- + +#if !defined(BOOST_LAMBDA_CASTS_HPP) +#define BOOST_LAMBDA_CASTS_HPP + +#include + +namespace boost { +namespace lambda { + +template class cast_action; + +template class static_cast_action; +template class dynamic_cast_action; +template class const_cast_action; +template class reinterpret_cast_action; + +class typeid_action; +class sizeof_action; + +// Cast actions + +template class cast_action > +{ +public: + template + static RET apply(Arg1 &a1) { + return static_cast(a1); + } +}; + +template class cast_action > { +public: + template + static RET apply(Arg1 &a1) { + return dynamic_cast(a1); + } +}; + +template class cast_action > { +public: + template + static RET apply(Arg1 &a1) { + return const_cast(a1); + } +}; + +template class cast_action > { +public: + template + static RET apply(Arg1 &a1) { + return reinterpret_cast(a1); + } +}; + + // typedid action +class typeid_action { +public: + template + static RET apply(Arg1 &a1) { + return typeid(a1); + } +}; + +// sizeof action +class sizeof_action +{ +public: + template + static RET apply(Arg1 &a1) { + return sizeof(a1); + } +}; + + +// return types of casting lambda_functors (all "T" type.) + +template